51
Canonical Grid model
Materials starter - Transformation fitting report
Explicitly request a nonlinear fitting report, reuse its coefficients, and inspect synthetic transformation residuals.
- Scale
- Small
- Source
- materials-transformation-fit-report.grid
- Length
- 113 lines
- Collection
- Advanced language
- Level
- Intermediate
- Runtime
- Portable
- Version
- 1.0.0
MODEL "Materials starter - Transformation fitting report"
DESCRIPTION "Explicitly request a nonlinear fitting report, reuse its coefficients, and inspect synthetic transformation residuals."
VERSION "1.0.0"
TAGS "materials", "starter", "kinetics", "regression", "residuals", "fit-report"
strict
input InitialTau_s = 80
VALIDATE BETWEEN 1 AND 1000 MESSAGE "Use a positive initial characteristic time from 1 to 1000 seconds."
input InitialExponent = 2
VALIDATE BETWEEN 0.1 AND 8 MESSAGE "Use a positive initial exponent from 0.1 to 8."
input PredictionTime_s = 150
VALIDATE BETWEEN 0 AND 10000 MESSAGE "Prediction time must be nonnegative; this example accepts up to 10000 seconds."
# Eight synthetic observations; not a material calibration or independent replication.
# Baseline checkpoint: tau about 100.037954 s, exponent about 2.490370,
# SSE about 5.713470247e-5; compare residuals as well as coefficients.
Times_s = [20, 40, 60, 80, 100, 120, 160, 200]
Fractions = [0.019729493624221495, 0.093241305536341912, 0.24735023991690364, 0.4338490391627452, 0.63512055882855767, 0.78949712943053385, 0.96176446053896381, 0.99550651072335383]
# Fit logarithms so the recovered tau and exponent stay positive. This changes
# parameter coordinates, not the unweighted squared-residual objective.
# All observations have appreciable transformed fractions; explicit grouping
# gives a negated positive power instead of a negative fractional-power base.
# This companion explicitly requests one report solve and reuses its coefficients.
# Report parameters are log_tau and log_exponent; its residuals are fitted minus observed.
output FittingReport = CURVE_FIT.REPORT(LAMBDA(time_s, log_tau, log_exponent, 1 - EXP(-((time_s / EXP(log_tau))^EXP(log_exponent)))), Times_s, Fractions, [LN(InitialTau_s), LN(InitialExponent)], 1e-12, 400)
LogFit = FittingReport.parameters
FittedTau_s = EXP(INDEX(LogFit, 1, 1))
FittedExponent = EXP(INDEX(LogFit, 1, 2))
PredictedFractions = MAP(Times_s, (time_s) => -EXPM1(-((time_s / FittedTau_s)^FittedExponent)))
Residuals = MAP(SEQUENCE(1, 8), (observation) => INDEX(Fractions, 1, observation) - INDEX(PredictedFractions, 1, observation))
ResidualSSE = SUMSQ(Residuals)
output CharacteristicTime_s = FittedTau_s
output AvramiExponent = FittedExponent
output SumSquaredResiduals = ResidualSSE
output RootMeanSquaredResidual = SQRT(ResidualSSE / 8)
output ResidualStandardError = SQRT(ResidualSSE / 6)
output Prediction = -EXPM1(-((PredictionTime_s / FittedTau_s)^FittedExponent))
output HalfTransformationTime_s = FittedTau_s * (LN(2)^(1 / FittedExponent))
output ResidualValues = Residuals
output Assumptions = "Unweighted least squares for X(t)=1-exp(-((t/tau)^n)); positive tau and n; synthetic data in seconds and fractions. Residuals are measured minus fitted. RMSE divides SSE by 8; residual standard error divides by 8-2. Neither is coefficient uncertainty or proof of a transformation mechanism."
output ScenarioGuide = "Save Baseline, then try InitialTau_s=120 and InitialExponent=3 as a Different initial guess scenario. Compare the fitted coefficients and SSE, not just a smooth curve. Restore Baseline or reset inputs. Predictions outside the observed 20-200 s window are extrapolation. Inspect FittingReport for the stopping reason and local rank. Its coefficients are log_tau and log_exponent; its residuals are fitted minus measured, opposite to the residual chart."
FitData = MAP(SEQUENCE(1, 8), (observation) => {
time_s: INDEX(Times_s, 1, observation),
measured: INDEX(Fractions, 1, observation),
fitted: INDEX(PredictedFractions, 1, observation),
residual: INDEX(Residuals, 1, observation)
})
A1 = "Fitted characteristic time (s)"
B1 = CharacteristicTime_s
A2 = "Fitted exponent"
B2 = AvramiExponent
A3 = "Sum of squared residuals"
B3 = SumSquaredResiduals
A4 = "RMSE (fraction; divisor 8)"
B4 = RootMeanSquaredResidual
A5 = "Residual standard error (fraction; divisor 6)"
B5 = ResidualStandardError
A6 = "Predicted fraction at selected time"
B6 = Prediction
A7 = "Half-transformation time (s)"
B7 = HalfTransformationTime_s
A9 = Assumptions
A10 = ScenarioGuide
A12 = "Fitting report: stopping reason and local rank"
B12 = FittingReport
Charts_1!type = "charts"
Charts_1!config = <toml>
version = 1
kind = "charts"
title = "Transformation fit"
[layout]
title = "Synthetic transformed fractions"
x_axis = "Time (s)"
y_axis = "Transformed fraction"
[[charts]]
type = "scatter"
bind = "FitData"
x = "time_s"
y = "measured"
label = "Synthetic observations"
[[charts]]
type = "line"
smooth = false
bind = "FitData"
x = "time_s"
y = "fitted"
label = "Fit at observation times"
</toml>
Charts_2!type = "charts"
Charts_2!config = <toml>
version = 1
kind = "charts"
title = "Transformation residuals"
[layout]
title = "Measured minus fitted fraction"
x_axis = "Time (s)"
y_axis = "Residual (fraction)"
[[charts]]
type = "scatter"
bind = "FitData"
x = "time_s"
y = "residual"
label = "Residual"
</toml>
END MODEL