{
  "hppc": {
    "format": "lemonergy/cross-tool-benchmark@1",
    "contractRevision": "1.1.0",
    "contractFrozenAtUtc": "2026-08-23T04:00:00.000Z",
    "id": "MW-HPPC-2RC-SOC40-25C",
    "title": "MathWorks HPPC 2-RC fit, BAK N18650CL-29 cell, 25 C, 0.4 SOC discharge",
    "source": {
      "vendor": "MathWorks",
      "product": "MATLAB / Simscape Battery",
      "example": "Estimate Battery Model Parameters from HPPC Data",
      "url": "https://www.mathworks.com/help/simscape-battery/ug/estimate-battery-model-parameters-from-hppc-data.html",
      "introduced": "R2025a",
      "evidenceTier": "published-numeric-table",
      "retrievedOn": "2026-08-23",
      "executionMode": "published-parameter-distillation-third-party-tool-not-run",
      "references": [
        {
          "role": "parameter solution and measured pulse observables",
          "url": "https://www.mathworks.com/help/simscape-battery/ug/estimate-battery-model-parameters-from-hppc-data.html"
        },
        {
          "role": "BAK HPPC dataset and cell-characterization context",
          "url": "https://www.mathworks.com/help/simscape-battery/ug/battery-cell-characterization-for-ev.html"
        }
      ]
    },
    "operatingPoint": {
      "cell": "BAK N18650CL-29",
      "capacityAh": 2.84,
      "temperatureC": 25,
      "soc": 0.4,
      "direction": "discharge",
      "sourceCurrentA": -6.1871,
      "lemonergyCurrentPositive": "discharge",
      "lemonergyCurrentA": 6.1871,
      "sourcePulseDurationS": 30
    },
    "sourceMethod": {
      "mathWorksFunction": "fitECM",
      "modelOrder": "2-RC",
      "segmentToFit": "loadAndRelaxation",
      "optimizer": "custom fminsearch workflow shown by the official example",
      "parameterSummaryId": 5,
      "socAssignment": {
        "automaticValueBeforeManualAssignment": 0.43431,
        "manuallyAssignedValue": 0.4,
        "mathWorksFunction": "setDischargeSOCs"
      },
      "uncertainty": "The public rounded table does not disclose covariance, confidence intervals, or sufficient raw residual data to infer parameter uncertainty."
    },
    "publishedSolution": {
      "ocvV": 3.7353,
      "r0Ohm": 0.040839,
      "r1Ohm": 0.0020343,
      "tau1S": 1.1318,
      "c1F": 556.35,
      "r2Ohm": 0.012923,
      "tau2S": 20.73,
      "c2F": 1604.2,
      "fitPc": 0.000029118
    },
    "sourceObservablesNotReplayed": {
      "minimumVoltageV": 3.4001,
      "measuredVoltageTrace": "not imported in CT-01",
      "fitPc": "recorded under its source label but not equated to Lemonergy RMSE"
    },
    "distillation": {
      "equation": "V=OCV-I*R0-v1-v2; vk[n]=exp(-dt/tauk)*vk[n-1]+I[n]*Rk*(1-exp(-dt/tauk))",
      "samplePeriodS": 0.1,
      "calibrationCurrentA": 6.1871,
      "holdoutCurrentA": 5,
      "sequence": [
        {
          "mode": "rest",
          "durationS": 10
        },
        {
          "mode": "pulse",
          "durationS": 30
        },
        {
          "mode": "rest",
          "durationS": 70
        },
        {
          "mode": "pulse",
          "durationS": 30
        },
        {
          "mode": "rest",
          "durationS": 70
        }
      ],
      "purpose": "Recover the published R0/R1/tau1 solution with Lemonergy while holding the published slow branch fixed, then score a separately generated current-amplitude holdout.",
      "slowBranchPolicy": "Not tuned in this first run: the public 30 s pulse is shorter than Lemonergy's conservative three-time-constant excitation gate for tau2=20.73 s.",
      "oracleClassification": "synthetic analytical oracle authored from the published parameter row; not a replay of the measured MathWorks HPPC trace",
      "transformations": [
        "Author a uniform 0.1 s grid; this is a benchmark choice, not asserted as the source acquisition sample period.",
        "Normalize the source negative-discharge sign to positive-discharge current.",
        "Prepend a 10 s rest with zero RC polarization.",
        "Use a 30 s constant-current pulse followed by a 70 s rest.",
        "Duplicate the pulse-and-rest pair to exercise repeatability and relaxation memory.",
        "Generate a separate 5 A scale-only synthetic holdout from the same linear 2-RC parameter set.",
        "Hold OCV and all published parameters constant over each authored trace.",
        "Use exact zero-order-hold RC state updates and record voltage at the end of each 0.1 s step.",
        "Represent the cell as a 1s1p Lemonergy pack, so cell and pack current/voltage are numerically identical after the recorded scope normalization."
      ],
      "stateOfChargeMovement": {
        "calibrationApproximateDelta": 0.036309272300469486,
        "holdoutApproximateDelta": 0.029342723004694836,
        "interpretation": "The source row is treated as a local parameter operating point even though the authored two-pulse traces move SOC. OCV and parameters remain frozen by design."
      }
    },
    "comparisonLimits": {
      "forwardOracleVoltageRmseMvPerCell": 0.000001,
      "forwardOracleVoltageMaxAbsMvPerCell": 0.000001,
      "validationVoltageRmseMvPerCell": 2,
      "validationVoltageMaxAbsMvPerCell": 5,
      "r0RelativeErrorPct": 5,
      "r1RelativeErrorPct": 10,
      "tau1RelativeErrorPct": 10
    },
    "gateDefinitions": [
      {
        "id": "forward-oracle-voltage-rmse",
        "metric": "direct forward-model voltage RMSE at the published parameter values",
        "unit": "mV-per-cell",
        "direction": "less-than-or-equal",
        "limit": 0.000001,
        "rationale": "Strict numerical equivalence gate for two implementations of the same noiseless analytical model; not a physical tolerance.",
        "origin": "Lemonergy benchmark contract",
        "frozenAtUtc": "2026-08-23T04:00:00.000Z",
        "contractRevision": "1.1.0"
      },
      {
        "id": "forward-oracle-voltage-max-absolute",
        "metric": "direct forward-model maximum absolute voltage error at the published parameter values",
        "unit": "mV-per-cell",
        "direction": "less-than-or-equal",
        "limit": 0.000001,
        "rationale": "Strict numerical equivalence gate for time alignment, sign, unit, and exact-ZOH recurrence.",
        "origin": "Lemonergy benchmark contract",
        "frozenAtUtc": "2026-08-23T04:00:00.000Z",
        "contractRevision": "1.1.0"
      },
      {
        "id": "derived-holdout-voltage-rmse",
        "metric": "post-fit derived-holdout voltage RMSE",
        "unit": "mV-per-cell",
        "direction": "less-than-or-equal",
        "limit": 2,
        "rationale": "Internal engineering recovery gate for the synthetic holdout; not a MathWorks tolerance or a physical-accuracy limit.",
        "origin": "Lemonergy benchmark contract",
        "frozenAtUtc": "2026-08-23T04:00:00.000Z",
        "contractRevision": "1.1.0"
      },
      {
        "id": "derived-holdout-voltage-max-absolute",
        "metric": "post-fit derived-holdout maximum absolute voltage error",
        "unit": "mV-per-cell",
        "direction": "less-than-or-equal",
        "limit": 5,
        "rationale": "Internal engineering recovery gate for the synthetic holdout; not a MathWorks tolerance or a physical-accuracy limit.",
        "origin": "Lemonergy benchmark contract",
        "frozenAtUtc": "2026-08-23T04:00:00.000Z",
        "contractRevision": "1.1.0"
      },
      {
        "id": "published-parameter-relative-errors",
        "metric": "relative error of fitted R0, R1, and tau1 against the rounded published row",
        "unit": "percent",
        "direction": "less-than-or-equal",
        "limit": {
          "r0": 5,
          "r1": 10,
          "tau1": 10
        },
        "rationale": "Internal optimizer-recovery gates allowing for bounded search from disclosed perturbed starts; not vendor tolerances.",
        "origin": "Lemonergy benchmark contract",
        "frozenAtUtc": "2026-08-23T04:00:00.000Z",
        "contractRevision": "1.1.0"
      }
    ],
    "lemonergyTuningPlan": {
      "algorithm": "bounded Nelder-Mead through governed staged tuning",
      "fitted": [
        "R0",
        "R1",
        "tau1"
      ],
      "fixed": [
        "OCV",
        "R2",
        "tau2"
      ],
      "initialization": {
        "r0": "published value multiplied by 1.20",
        "r1": "published value multiplied by 1.35",
        "tau1": "published value multiplied by 1.40",
        "classification": "source-derived deterministic perturbation; not blind initialization"
      },
      "stages": [
        "ohmic",
        "fast-rc",
        "joint-refinement"
      ],
      "maximumCandidateEvaluations": 180,
      "maximumTemporalIntegrationSteps": 3000000,
      "randomness": "none"
    },
    "implementationScaffoldingNotCompared": {
      "cellMassG": 47,
      "voltageWindowV": [
        2.5,
        4.2
      ],
      "dischargeTemperatureWindowC": [
        -20,
        60
      ],
      "chargeTemperatureWindowC": [
        0,
        45
      ],
      "purpose": "Required simulator schema and safety/thermal ledger scaffolding; these are not transcribed source claims and are not benchmark observables.",
      "electricalIsolation": "Flat OCV, zero R0 activation energy, unity SOC factor, zero hysteresis, unit coulombic efficiency and zero entropic coefficient prevent these scaffolding fields from changing the compared electrical response."
    },
    "limitations": [
      "This is a synthetic analytical-oracle distillation from MathWorks' published parameter row, not execution of MATLAB and not replay of the measured MathWorks HPPC waveform.",
      "The derived holdout amplitude is generated from the same published linear 2-RC parameter set; it is not a second measured experiment or statistically independent physical validation.",
      "The source reports a 3.4001 V measured minimum for this row; CT-01 records but does not compare that observable because it does not import the measured trace and authors a different two-pulse protocol.",
      "Passing establishes published-parameter forward-model and governed tuning consistency for one disclosed operating point. It does not establish broad MATLAB parity, GT-SUITE parity, or independent physical validation of the cell model.",
      "The source parameter values are rounded and published without confidence intervals; numerical differences below the source precision must not be presented as physical certainty."
    ]
  },
  "rlc": {
    "id": "matlab-rlc-laplace",
    "version": 1,
    "frozenAt": "2026-09-30T21:26:54.000Z",
    "title": "Driven RLC circuit: current and capacitor charge",
    "question": "Does the existing Lemonergy Rust/Wasm equation engine reproduce the disclosed RLC current and charge solution?",
    "source": {
      "vendor": "MathWorks",
      "product": "MATLAB Symbolic Math Toolbox",
      "title": "Solve Differential Equations of RLC Circuit Using Laplace Transform",
      "url": "https://www.mathworks.com/help/symbolic/solve-differential-equations-using-laplace-transform.html",
      "retrievedDate": "2026-09-30",
      "documentationRelease": "R2026b",
      "location": "Workflow: Solve RLC Circuit Using Laplace Transform; Declare Equations; Substitute Values",
      "extraction": "Manually transcribed physical parameters and published symbolic I1sol/Qsol expressions; no digitization.",
      "evidenceTier": "A: explicit complete analytical solution, evaluated at native solver output times",
      "licensing": "Source page is MathWorks copyrighted documentation. No source code, page, figure, or model is redistributed; only attributed mathematical facts and an independently authored graph/oracle are included.",
      "locallyRetainedSourceArtifact": null,
      "parameters": {
        "R1Ohm": 4,
        "R2Ohm": 2,
        "R3Ohm": 3,
        "inductanceH": 1.6,
        "capacitanceF": 0.25,
        "initialCurrentA": 2,
        "initialChargeC": 2,
        "inputAmplitudeV": 1
      },
      "equations": [
        "E(t) = sin(t) V; t is in seconds, angular frequency = 1 rad/s",
        "dQ/dt = (E - Q/C + R2*I1)/(R2+R3)",
        "dI1/dt = (R2/L)*dQ/dt - ((R1+R2)/L)*I1"
      ],
      "publishedSolution": {
        "currentA": "200*cos(t)/8161 + 405*sin(t)/8161 + 16122*exp(-81*t/40)/8161*(cosh(sqrt(1761)*t/40)-742529*sqrt(1761)*sinh(sqrt(1761)*t/40)/14195421)",
        "chargeC": "924*sin(t)/8161 - 1055*cos(t)/8161 + 17377*exp(-81*t/40)/8161*(cosh(sqrt(1761)*t/40)+1109425*sqrt(1761)*sinh(sqrt(1761)*t/40)/30600897)"
      }
    },
    "executionMode": "published-reference-distillation",
    "matlabExecuted": false,
    "systemBoundary": "Three resistors, one inductor, one capacitor and a prescribed sinusoidal voltage, with the source Kirchhoff current directions.",
    "solverSettings": {
      "method": "dormand-prince-45",
      "startS": 0,
      "endS": 25,
      "initialStepS": 0.001,
      "minStepS": 1e-10,
      "maxStepS": 0.05,
      "relativeTolerance": 1e-10,
      "absoluteTolerance": 1e-12,
      "maxSteps": 100000
    },
    "excitationImplementation": "Native integrators solve s′=c, c′=-s, s(0)=0, c(0)=1, and E=1*s. Input accuracy is a mandatory separate gate.",
    "comparison": "All accepted native output points over [0,25] s, including both endpoints. Evaluate the published closed form directly at each time; no resampling, exclusions, clipping, or fitted parameters.",
    "metrics": [
      {
        "name": "current",
        "unit": "A",
        "gate": 1e-7
      },
      {
        "name": "charge",
        "unit": "C",
        "gate": 1e-7
      },
      {
        "name": "input",
        "unit": "V",
        "gate": 1e-7
      }
    ],
    "metricFormula": "maxAbsError = max(abs(native-reference)); rmse = sqrt(mean((native-reference)^2)); meanBias = mean(native-reference). Each native point has equal weight. Mandatory maximum-error gates use <=; no relative-error gate near zero.",
    "gateRationale": "Internal implementation consistency threshold, selected before running, in absolute SI units. This is not a MathWorks accuracy specification or a physical uncertainty estimate.",
    "completenessGate": "Nonempty finite trace, strict increasing times, first time 0 s, last time 25 s, all native node values finite.",
    "normalization": "Every graph signal uses dimensionless numeric blocks. I1 numeric value maps 1:1 to amperes, Q to coulombs, E to volts; dI1/dt to A/s and dQ/dt to C/s. Time remains seconds. SI-valued gains implement the disclosed equations. This mapping is explicit because charge and current-rate quantity types are absent from the product catalog.",
    "parameters": "All eight physical/input values are fixed from the source. No calibration, parameter fitting, or independent physical holdout.",
    "negativeControl": {
      "parameter": "R1Ohm",
      "sourceValue": 4,
      "perturbedValue": 4.4,
      "expected": "Current and/or charge maximum-error gate fails against unchanged source oracle."
    },
    "failurePolicy": "Unavailable Wasm or invalid graph throws; infrastructure failures do not become numerical passes. Incomplete or non-finite traces fail their gate.",
    "independentPhysicalValidation": "not established",
    "limitations": [
      "MATLAB was not executed. The independent oracle directly evaluates the complete symbolic solution published in its documentation.",
      "The benchmark exercises generic equation blocks and the existing numerical solver, not a symbolic Laplace transform engine or a dedicated electrical-network compiler.",
      "The sinusoidal input adds two native oscillator states; its error is included and separately gated.",
      "Native adaptive points are used for pointwise scoring; RMSE is sample-weighted, not a uniform-time integral.",
      "The source plots [0,15] s and [2,25] s; this contract uses their union [0,25] s.",
      "No measured circuit data, uncertainty analysis, hardware validation, or MATLAB runtime comparison is included."
    ]
  },
  "thermal": {
    "id": "matlab-iron-rod-thermal",
    "version": 1,
    "frozenAt": "2026-10-01T15:24:13.000Z",
    "title": "Iron rod: conduction, convection and lumped thermal response",
    "source": {
      "vendor": "MathWorks",
      "product": "Simscape",
      "title": "Heat Conduction Through Iron Rod",
      "url": "https://www.mathworks.com/help/simscape/ug/heat-conduction-through-iron-rod.html",
      "retrievedDate": "2026-09-30",
      "recheckedDate": "2026-10-01",
      "documentationRelease": "R2026b",
      "location": "Examples 1–3 and Lumped Mass Rod Model governing differential equation",
      "extraction": "Manually transcribed physical parameters, three rounded scalar answers and the single-mass governing equation; no plot digitization.",
      "evidenceTiers": {
        "printedScalarAnswers": "A: three public numerical results, limited to their printed precision",
        "transientResponses": "Published-reference distillation from disclosed equations and inputs; the analytical waveforms are authored here, not numerical traces exported by MathWorks."
      },
      "licensing": "MathWorks copyrighted documentation is attributed. No vendor code, model, figure or source-page copy is redistributed; graphs and analytical evaluators are independently authored.",
      "locallyRetainedSourceArtifact": null,
      "parameters": {
        "diameterM": 0.025,
        "lengthM": 0.2,
        "densityKgPerM3": 7800,
        "specificHeatJPerKgK": 447,
        "conductivityWPerMK": 80.2,
        "convectionWPerM2K": 32.1,
        "baseTemperatureC": 100,
        "ambientTemperatureC": 20,
        "initialTemperatureC": 20,
        "uniformTemperatureC": 55,
        "conductionHeatW": 18,
        "insulatedHeatW": 18
      },
      "publishedAnswers": {
        "conductionTipC": 8.5554,
        "convectionHeatW": 17.6479,
        "insulatedSlopeKPerS": 0.0526
      },
      "equations": [
        "A=pi*D^2/4; Acyl=pi*D*L; C=rho*A*L*c",
        "Ttip=Tbase-Q*L/(k*A); Qconvection=h*Acyl*(Tuniform-Tair); dT/dt=Q/C",
        "C*dT/dt=(2*k*A/L)*(Tbase-T)+(h*Acyl+2*A*k*h/(L*h+2*k))*(Tair-T)"
      ]
    },
    "executionMode": "published-reference-distillation",
    "matlabExecuted": false,
    "systemBoundary": "Four separate problems: prescribed conduction; cylindrical convection only; perfectly insulated uniform mass; a single midpoint mass with base conduction and cylindrical/tip losses.",
    "solverSettings": {
      "method": "dormand-prince-45",
      "startS": 0,
      "initialStepS": 0.01,
      "minStepS": 1e-10,
      "maxStepS": 5,
      "relativeTolerance": 1e-11,
      "absoluteTolerance": 1e-12,
      "maxSteps": 100000
    },
    "horizons": {
      "conduction": 1,
      "convection": 1,
      "insulated": 100,
      "lumped": 2500
    },
    "horizonRationale": "Steady problems use an authored 0–1 s observation window; insulated mass uses an authored 0–100 s window. Lumped response uses 0–2500 s, covering the source plot horizon.",
    "metrics": [
      {
        "name": "conduction-tip",
        "unit": "°C",
        "reference": 8.5554,
        "gate": 0.00005
      },
      {
        "name": "cylindrical-convection",
        "unit": "W",
        "reference": 17.6479,
        "gate": 0.00005
      },
      {
        "name": "insulated-heating-slope",
        "unit": "K/s",
        "reference": 0.0526,
        "gate": 0.00005
      },
      {
        "name": "insulated-temperature-trace",
        "unit": "K",
        "gate": 1e-7
      },
      {
        "name": "lumped-temperature-trace",
        "unit": "K",
        "gate": 1e-7
      }
    ],
    "comparison": "Scalar conduction/convection use the final native point; insulated slope is endpoint temperature difference divided by elapsed time. Both temperature traces are scored at every accepted native output point, including endpoints, against analytical expressions, without resampling, fitting or exclusions.",
    "metricFormula": "Scalar maxAbsError=abs(actual-reference). Trace maxAbsError=max(abs(native-reference)); rmse=sqrt(mean(error^2)); meanBias=mean(error). Native samples have equal weight. All mandatory gates use <=.",
    "gateRationale": "Scalar gates are half the last printed decimal. Trace gates are internal numerical consistency limits in kelvin chosen before execution, not vendor accuracy claims or physical uncertainty.",
    "completenessGate": "Every subcase has at least two finite points, strictly increasing time, exactly its specified first and last time, and finite values for all native nodes.",
    "normalization": "Native typed temperature signals are kelvin; heat is W, rates are K/s, time is s. Celsius is used only for source comparisons and reported temperature traces; differences in kelvin and Celsius have equal magnitude.",
    "parameters": "All source physical inputs are fixed; no parameter fitting, calibration, measurement holdout, or independent physical validation.",
    "oracle": "Three source-printed scalar references plus independently derived linear and exponential solutions of the source balances. The combined lumped response is not the spatial fin solution.",
    "negativeControl": {
      "parameter": "insulatedHeatW",
      "sourceValue": 18,
      "perturbedValue": 19.8,
      "expected": "The unchanged published heating-slope gate and unchanged linear temperature oracle fail."
    },
    "failurePolicy": "Unavailable Wasm or invalid graphs throw. Incomplete or non-finite traces fail. Infrastructure failures never become passes.",
    "independentPhysicalValidation": "not established",
    "limitations": [
      "MATLAB/Simscape was not executed; this compares the product solver to disclosed mathematics and three rounded published answers.",
      "The transient analytical evaluators are independently authored from the source equations, not exported Simscape output traces.",
      "A single lumped mass has no spatial temperature field; spatial fin midpoint/heat-flow references and the segmented rod are outside this contract.",
      "The source does not specify the insulated simulation horizon; 100 seconds is an authored test choice.",
      "Sample-weighted RMSE on adaptive times is not a uniform-time integral.",
      "No measured rod data, uncertainty analysis, or cross-product performance comparison is included."
    ]
  }
}
