Docs / Thermal, core-loss & FNO

Thermal, core-loss & FNO new live

The live cufemlab API includes six analysis types in this thermal / core-loss / FNO lane: two GPU thermal-conduction solvers (steady and transient), an eddy-to-thermal coupling, a Bertotti core-loss estimator, a coupled core-loss / thermal chain, and a field-to-field neural surrogate. Each is documented below with its model, parameters, outputs, downloadable artifacts, validation tier, limitations, and a copy-paste SDK example. Every type takes parametric inputs with defaults, so you can run it with an empty input_params and refine from there.

Validation status for all six new types. Every type on this page returns a result.v1 payload whose validation_card.status is "not_validated" (claim_allowed_public=false). This means the five physics types are validated internally against the method's own analytic or energy identity, with no external validation passport attached yet. The field-to-field neural operator is instead an experimental in-distribution surrogate that self-scores against the real solver each run. They are not externally cross-checked against an independent oracle the way cogging_torque_movingband (FEMM / GetDP) and cufem3d_field_validation (analytic sphere) are. Treat their numbers as internally consistent engineering results, not third-party evidence.
How to read the tiers. cufemlab labels every result by evidence tier. On this page you will see two tiers: internally validated for the five physics types (verified against an analytic solution or an energy-balance identity, external passport not yet attached), and experimental surrogate for the neural operator (an in-distribution, self-validating demo). Read the honest-claims summary on the Validation & claims page for the full policy.

The API in one minute

All types are submitted the same way. Authenticate with a Bearer access token or an X-API-Key key, then POST /api/v1/jobs with {analysis_type, input_params, project_id}. Poll GET /api/v1/jobs/{id} until the job is done, then read GET /api/v1/jobs/{id}/result. The result is a result.v1 object (schema version, verdict, result summary, artifact list, validation card, provenance). Common errors: 422 invalid domain parameters, 402 INSUFFICIENT_CREDITS, and 429 CONCURRENCY_LIMIT_EXCEEDED (a maximum of 2 concurrent jobs per user).

thermal_conduction_steady3 credits · GPU · internally validated
thermal_conduction_transient4 credits · GPU · internally validated
eddy_thermal_coupled5 credits · GPU · internally validated
core_loss_estimate2 credits · CPU · internally validated
coreloss_thermal_coupled5 credits · GPU · internally validated
field_to_field_neural_operator4 credits · GPU · experimental surrogate

Note on eddy-current physics: standalone eddy-current solvers exist inside the engine, but on the customer API eddy physics reaches you only through eddy_thermal_coupled.


1. thermal_conduction_steady internally validated

What it solves. Steady-state heat conduction on a tetrahedral mesh: it finds the temperature field T that satisfies -div(k grad T) = Q, where k is the thermal conductivity (a scalar or a full conductivity tensor) and Q is a volumetric heat source. Boundary conditions can be fixed temperature (Dirichlet), fixed flux (Neumann), or convective (Robin). The discretisation uses linear P1 tetrahedra.

Inputs all have defaults
thermal_conductivity_kW/(m·K) - scalar or 3×3 tensor components
volumetric_source_QW/m3
dirichlet_bcK - fixed boundary temperature
neumann_bcW/m2 - prescribed boundary flux
robin_bch in W/(m2·K), T_inf in K
Outputs
T_min_K / T_max_K / T_mean_Ktemperature statistics, K
mean_flux_W_m2mean heat flux magnitude
energy_balance_relativeresidual of the global energy identity
n_nodes / n_tetsmesh size
Artifacts

temperature_field.json, energy_balance.json, result.json

Validation tier. Validated internally against the method of manufactured solutions (observed L2 convergence order ~1.93) and a global energy-balance identity (relative residual 3.7e-14 against a 1e-6 tolerance); external validation passport not yet attached.

Limitations. Linear, isotropic-or-tensor conduction only; no temperature-dependent k, no radiation, no phase change, no conjugate fluid flow. Convection enters only through the Robin coefficient you supply. Results are internally validated, not externally cross-checked.

Steady thermal conductionPython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])   # default base https://app.cufemlab.secrotec.nl
project = client.create_project(name="thermal-steady-demo")

job = client.analyze(
    project_id=project.id,
    analysis_type="thermal_conduction_steady",
    input_params={
        "thermal_conductivity_k": 45.0,     # W/(m.K)
        "volumetric_source_Q": 2.0e5,       # W/m3
        "robin_bc": {"h": 25.0, "T_inf": 313.15},
    },
    gpu=True,
)

job.wait(poll_interval=10)
result = job.result()
print(result.verdict, result.value)        # verdict + result_summary.value
print(result.metrics)                        # T_min/max/mean_K, energy_balance_relative, ...

2. thermal_conduction_transient internally validated

What it solves. The time-dependent heat equation rho c dT/dt - div(k grad T) = Q on the same P1 tetrahedral discretisation, integrated in time with the theta-method. Set theta = 0.5 for Crank-Nicolson (second-order in time), theta = 1.0 for backward Euler. You choose the end time and step size; the solver marches the field and reports its evolution plus the final state.

Inputs all have defaults
t_end_ss - simulation end time
time_step_ss - fixed time step
theta- 0.5 Crank-Nicolson, 1.0 backward Euler
thermal_conductivity_kW/(m·K)
volumetric_source_QW/m3
dirichlet_bc / neumann_bc / robin_bcas in the steady type
Outputs
T evolutiontemperature statistics per stored time step, K
final temperature fieldfield at t_end_s
T_min/max/mean_Kfinal-state statistics
n_nodes / n_tetsmesh size
Artifacts

temperature_field.json (final + time series), energy_balance.json, result.json

Validation tier. Validated internally against the theta-method reference behaviour, with the Crank-Nicolson second-order time-convergence confirmed on a manufactured solution; external validation passport not yet attached.

Limitations. Constant material properties, fixed time step, linear conduction only; no adaptive stepping, no temperature-dependent k or c, no radiation or phase change. Very small steps at large end times increase credit-metered compute. Internally validated, not externally cross-checked.

Transient thermal conductionPython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])
project = client.create_project(name="thermal-transient-demo")

job = client.analyze(
    project_id=project.id,
    analysis_type="thermal_conduction_transient",
    input_params={
        "t_end_s": 60.0,
        "time_step_s": 0.5,
        "theta": 0.5,                       # Crank-Nicolson
        "volumetric_source_Q": 1.0e5,
    },
    gpu=True,
)

job.wait(poll_interval=10)
result = job.result()
print(result.verdict, result.value)
print(result.metrics)                        # final T stats + time evolution summary

3. eddy_thermal_coupled internally validated

What it solves. A one-way multiphysics chain: it computes the eddy-current (skin-effect) Joule loss density in a conductor under a harmonic excitation, then feeds that loss as the volumetric heat source into the thermal-conduction solver to produce the resulting temperature field. This is the only path through which eddy-current physics is exposed on the customer API.

Inputs all have defaults
frequency_HzHz - excitation frequency
electrical_conductivity_sigmaS/m
excitation_amplitudeA or A/m (field drive)
thermal_conductivity_kW/(m·K)
robin_bch in W/(m2·K), T_inf in K (cooling)
Outputs
loss_density fieldJoule loss W/m3 from eddy currents
coupled temperature fieldT resulting from the loss, K
T_min/max/mean_Ktemperature statistics
energy_balance_relativechain energy consistency
Artifacts

loss_density.json, temperature_field.json, energy_balance.json, result.json

Validation tier. Validated internally against the analytic skin-effect decay (observed spatial order 1.998) and the loss-to-thermal energy chain (energy-balance identity); external validation passport not yet attached.

Limitations. One-way coupling only (loss drives temperature; temperature does not feed back to conductivity); linear, harmonic single-frequency excitation; no motion, no saturation, no temperature-dependent material properties. Internally validated, not externally cross-checked.

Eddy-to-thermal couplingPython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])
project = client.create_project(name="eddy-thermal-demo")

job = client.analyze(
    project_id=project.id,
    analysis_type="eddy_thermal_coupled",
    input_params={
        "frequency_Hz": 400.0,
        "electrical_conductivity_sigma": 1.0e7,
        "robin_bc": {"h": 40.0, "T_inf": 300.0},
    },
    gpu=True,
)

job.wait(poll_interval=10)
result = job.result()
print(result.verdict, result.value)
print(result.metrics)                        # loss density summary + coupled T stats

4. core_loss_estimate internally validated

What it solves. A Bertotti three-term core-loss separation: total specific loss is split into hysteresis, classical (eddy), and excess components as a function of peak flux density and electrical frequency. The classical coefficient uses the closed form k_c = pi^2 · sigma · d^2 / (6 · rho) for a lamination of thickness d. This is a CPU analysis and returns quickly.

Inputs all have defaults
grade- steel grade, default M19
peak_flux_density_TT - B_peak
frequency_HzHz - electrical frequency
lamination_thickness_d_mm
Outputs
hysteresis_lossW/kg
classical_lossW/kg
excess_lossW/kg
total_specific_lossW/kg
Artifacts

core_loss_breakdown.json, result.json

Validation tier. Validated internally against the Bertotti three-term separation with cited coefficients, with the classical closed-form coefficient k_c agreeing to 0.05% against an open reference; external validation passport not yet attached.

Limitations. Sinusoidal-flux Bertotti model with tabulated coefficients per grade; no minor-loop / PWM harmonic loss, no rotational loss, no DC bias, no manufacturing build-factor. Datasheet MAPE was not part of internal validation. It is an internally validated loss model, not an externally cross-checked measurement.

Bertotti core-loss estimatePython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])
project = client.create_project(name="core-loss-demo")

job = client.analyze(
    project_id=project.id,
    analysis_type="core_loss_estimate",
    input_params={
        "grade": "M19",
        "peak_flux_density_T": 1.5,
        "frequency_Hz": 400.0,
        "lamination_thickness_d_m": 0.35e-3,
    },
    gpu=False,                               # CPU analysis
)

job.wait(poll_interval=10)
result = job.result()
print(result.verdict, result.value)
print(result.metrics)                        # hysteresis / classical / excess / total W/kg

5. coreloss_thermal_coupled internally validated

What it solves. A one-way chain from core loss to temperature: the Bertotti loss density is applied as a distributed heat source in a cooled block, and the thermal solver returns the resulting steady temperature field. It answers "given this core-loss density and this cooling, how hot does the iron get".

Inputs all have defaults
grade- steel grade, default M19
peak_flux_density_TT
frequency_HzHz
thermal_conductivity_kW/(m·K)
robin_bch in W/(m2·K), T_inf in K (cooling)
Outputs
core_loss_densityW/m3 applied as source
coupled temperature fieldT of the cooled block, K
T_min/max/mean_Ktemperature statistics
energy_balance_relativechain energy consistency
Artifacts

core_loss_breakdown.json, temperature_field.json, energy_balance.json, result.json

Validation tier. Validated internally against the core-loss-density to thermal-response energy chain (energy-balance identity on the cooled block); external validation passport not yet attached.

Limitations. One-way coupling (loss drives temperature, no thermal feedback to loss); constant properties, single operating point, simple cooled-block geometry; not a full machine thermal model. Internally validated, not externally cross-checked.

Coupled core-loss / thermalPython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])
project = client.create_project(name="coreloss-thermal-demo")

job = client.analyze(
    project_id=project.id,
    analysis_type="coreloss_thermal_coupled",
    input_params={
        "grade": "M19",
        "peak_flux_density_T": 1.4,
        "frequency_Hz": 200.0,
        "robin_bc": {"h": 50.0, "T_inf": 313.15},
    },
    gpu=True,
)

job.wait(poll_interval=10)
result = job.result()
print(result.verdict, result.value)
print(result.metrics)                        # core-loss density + coupled T stats

6. field_to_field_neural_operator experimental surrogate

Read this before using the neural operator. This is an in-distribution surrogate / self-validating demo, not a validated physics solver. It is a Fourier Neural Operator (FNO2d, 4 spectral layers) trained to map a conductivity field to a temperature field on one narrow training distribution.
  • Held-out accuracy is relative-L2 0.68% on the training distribution only. Out-of-distribution inputs degrade to about 5.8%. It beats a linear baseline (9.8%) and a POD-DeepONet (11.8%) on that same distribution.
  • It is a narrow surrogate, not a broadly applicable neural operator, and is not a substitute for the finite-element solvers above.
  • Input today is an integer conductivity_seed that draws a field from the training distribution. Custom conductivity-field or CAD-geometry input is a planned follow-on, not shipped.
  • Each run self-scores against the real solver on the same field, so you always get an honest per-run error number. Trust that number, not the headline.

What it solves. Given a conductivity field drawn from its training distribution, the FNO predicts the corresponding steady temperature field in a single forward pass, approximating what the thermal solver would produce. On every run it also solves the same field with the real solver and reports the measured relative-L2 error, so the prediction is self-validating.

Inputs all have defaults
conductivity_seedinteger - draws an in-distribution conductivity field
Outputs
predicted temperature fieldFNO forward-pass prediction
self_validation_rel_l2measured error vs the real solver, this run
held_out_rel_l2_reported0.0068 (training-distribution reference)
ood_warningflag for out-of-distribution use
Artifacts

model_card.json, fno_prediction.json

Validation tier. Experimental surrogate: an in-distribution, self-validating demo. Held-out relative-L2 is 0.68% on the training distribution; out-of-distribution use degrades (about 5.8%). It is not a broadly applicable neural operator, and arbitrary custom-field or CAD input is a planned follow-on, not shipped.

Limitations. Fixed resolution and geometry from training; input restricted to the seeded in-distribution conductivity family; no uncertainty guarantees away from that family; the ood_warning flag and the per-run self_validation_rel_l2 are there precisely because you must not trust the surrogate blindly. Do not treat its output as a validated or production-grade result.

Field-to-field neural surrogatePython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])
project = client.create_project(name="fno-demo")

job = client.analyze(
    project_id=project.id,
    analysis_type="field_to_field_neural_operator",
    input_params={
        "conductivity_seed": 7,             # draws an in-distribution field
    },
    gpu=True,
)

job.wait(poll_interval=10)
result = job.result()
print(result.verdict, result.value)
print(result.metrics)                        # self_validation_rel_l2, held_out_rel_l2_reported, ood_warning

result.v1 & artifacts

Every job on this page returns the same versioned envelope from GET /api/v1/jobs/{id}/result:

schema_version"result.v1"
verdictthe run's outcome; also exposed as result.verdict in the SDK
result_summary.valuethe headline scalar; result.value in the SDK
result_files[] / artifacts[]each with a download url /api/v1/jobs/{id}/artifacts/{artifact_id}
validation_cardstatus = "not_validated" for all six new types (claim_allowed_public=false)
provenancerun metadata for reproducibility

The validation_card is the field that carries the honest-claims tier. For all six types on this page it reads not_validated, with no external passport attached yet. The five physics types are internally validated against the method's own identity. The neural operator is instead an experimental in-distribution surrogate. Download artifacts by following each entry's url at /api/v1/jobs/{id}/artifacts/{artifact_id}. In the in-app Jupyter environment a scoped key is injected for you, so Client.from_env() works with zero paste and the examples above run unchanged.

Where to go next. See Validation & claims for the full six-tier policy, Hard limitations for what these solvers do not model, and cufem engine API for the job lifecycle and error codes.