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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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".
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.
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
- 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.
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.
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:
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.