What to build this week: a calibrated physics model of the commercial thermal-conductivity apparatus, connected live to the apparatus's data, estimating thermal conductivity k, interface (contact) resistance and heat-loss coefficient online, with a dashboard and a "virtual experiment" mode. That is a digital shadow with an honest predictive model. Closing the loop (the twin choosing the next set-point or stopping a run) is a day-5 stretch goal if the instrument accepts commands; otherwise it becomes the first task of week 2.
Why the timeline changed: version 1 assumed the team would build a hobby rig from scratch. The apparatus is real lab equipment, so the mechanical build disappears and the critical path becomes (a) getting data out of the instrument and (b) understanding its physics well enough to calibrate a model. Both fit in a week for six people, provided the instrument's data is reachable (see Section 4.2 on what to check on day 1).
What "truly replicates real life" means operationally: the model's predictions at sensors it was not fitted to fall inside the model's own stated uncertainty, on runs it has never seen, for the operating range you declare. Nothing more, nothing less. Industrial twins that work (Rolls-Royce engines, Aarhus incubator, Willcox's UAV) all share three traits: a fit-for-purpose model, few physically meaningful tunable parameters, and continual verification, validation and uncertainty quantification (VVUQ). Copy that discipline.
Three capabilities the twin must offer, and how each is implemented:
| Capability | Implementation | Section |
|---|---|---|
| Replicate (mirror the live experiment, with uncertainty) | 1D finite-difference heat model + Kalman filter for state + periodic least-squares refit of k, Rc, h; validation against held-out runs | 3, 5 |
| Run new experiments virtually ("what if we used sample X at 80 °C?") | Same model run forward from the current calibrated state with user-chosen inputs; material library; uncertainty bands from parameter posteriors | 5.5 |
| Optimise (which run next, which set-points, how long to wait) | Bayesian experimental design / Bayesian optimisation over the model; time-to-steady-state forecast; stop-early rule when k uncertainty falls below a target | 5.6 |
The honest caveat on one week: steady-state thermal runs take 30 minutes to 2 hours each. You can build and wire the whole twin in a week, but a proper validation (≥3 materials × ≥2 thicknesses) is roughly 15 hours of instrument time and will run in the background into week 2. Plan for that from day 1 by queuing instrument time.
| Members | Natural home | But everyone also |
|---|---|---|
| 2 computer-science engineers | Data pipeline, twin runtime, database, dashboard, repository hygiene | Runs at least one full experiment on the instrument |
| 1 energy engineer | Heat-transfer physics, loss analysis, instrument physics, model-form decisions | Writes code in the physics module and reviews pull requests |
| 3 chemical engineers | Experiment design and SOPs, calibration and validation, uncertainty budgets; later: reaction kinetics and reactor models | Each owns one Python module end to end this week |
Everyone is willing to work across the pipeline, so pair people across disciplines on each module (a CS engineer with a chemical engineer on the estimator, the energy engineer with a CS engineer on the model). The point of this first week is to make the whole team fluent in every layer before the reactor work, where the chemical engineers' knowledge becomes the critical path.
tmux or a simple queue.| This week (thermal-conductivity twin) | Weeks 2–4 | Later (reactor twin with catalysis database) |
|---|---|---|
| Instrument interface; 1D physics model; live estimation of k, Rc, h; dashboard; virtual-experiment mode; PostgreSQL store; first validation runs | Closed-loop control (if the instrument allows); Bayesian calibration on the workstation; experiment-design optimiser; 2D model check; lab-mode report generator; second instrument if available | Non-isothermal packed-bed reactor model reusing the heat model; kinetic parameters with priors from the catalysis database; hybrid physics + ML residual models; autonomous experiment loop |
Fourier's law: heat flux q″ = −k dT/dx, with k in W/(m·K). Treat temperature difference as voltage, heat rate Q (W) as current, and thermal resistance R = L/(kA) (K/W) as electrical resistance. At steady state the stack is a series circuit:
Q = ΔT_total / ( R_c,hot + L/(k·A) + R_c,cold )
If Q is known and the drop across the sample ΔTs is measured, then k = Q·L/(A·ΔTs). Most commercial instruments do exactly this, either measuring Q directly (heater power, with guards to stop losses) or comparatively, by placing reference bars of known kref in series with the sample so that the same Q flows through both: ks = kref(ΔTref/Lref)(Ls/ΔTs). With a reference bar above and below the sample, the mismatch between the two flux estimates is a live measure of heat loss — use it as a health signal.
ρc ∂T/∂t = ∂/∂x ( k ∂T/∂x ) − (hP/A)(T − T_ambient)
At steady state with one sample thickness, k and Rc are confounded: you only observe their series sum. Three ways to separate them: sensors on or inside the sample faces; testing 2–4 thicknesses and regressing total resistance against L (slope 1/(kA), intercept = contact term; this is the ASTM D5470 logic); or transient data. Likewise hloss and the true delivered power are confounded unless reference bars (or a guard) are present. Before writing the estimator, compute Beck-style scaled sensitivity coefficients θ ∂T/∂θ for each sensor the instrument exposes; if two parameters have proportional curves, they are not separately identifiable with that sensor set and you must change the experiment (power steps, multiple thicknesses) rather than the code.
| Method (standard) | Principle | Typical range | What it means for the twin |
|---|---|---|---|
| Guarded hot plate (ASTM C177, ISO 8302) | Absolute steady state; guard heater eliminates lateral loss | Insulators | Losses small; model the guard as a Dirichlet boundary |
| Heat flow meter (ASTM C518, ISO 8301) | Calibrated heat-flux transducer replaces power measurement | Insulation boards | Twin gets Q directly; estimate the transducer's calibration drift |
| Guarded comparative cut-bar (ASTM E1225) | Sample in series with reference bars, plus guard | 0.2–200 W/(m·K), 90–1300 K | Closest to a source/sample/sink stack; two flux estimates available |
| Meter-bar, thin materials (ASTM D5470) | Hot/cold meter bars; multi-thickness regression separates contact resistance | Thermal interface materials | Closest for thin samples; Rc becomes a first-class parameter |
| Transient plane source (ISO 22007-2) | Sensor is both heater and thermometer; fit the transient | Wide | Instrument already does an inverse fit; twin adds UQ and drift tracking |
| Laser flash (ASTM E1461) | Pulse one face; α ≈ 0.1388 L²/t½ | Diffusivity | Twin estimates α; k needs ρc from elsewhere |
ASTM E1225 defines a homogeneous specimen as one whose apparent conductivity does not vary with thickness or cross-section by more than ±5 %. That is a ready-made validation test. Your twin will be "E1225-inspired", not compliant; say so in reports.
| Approach | Use | Python |
|---|---|---|
| Analytical (series resistances; Fourier-series slab transient) | Day-1 test oracle for the solver | NumPy |
| Lumped RC network (3–10 nodes) | First twin model; runs in microseconds inside a filter | scipy.integrate.solve_ivp |
| 1D finite difference, method of lines: dT/dt = A(θ)T + B(θ)u | Main model this week (contact nodes, fin-loss term) | SciPy sparse; solve_ivp(method="BDF"); Crank–Nicolson via solve_banded |
| Explicit FTCS | Teaching only; stable only if αΔt/Δx² ≤ ½ | NumPy |
| Finite volume | Layered materials, flux-conservative | FiPy |
| 2D axisymmetric FEM | Week 2: quantify how much the 1D assumption costs; size insulation | scikit-fem (light); FEniCSx (Docker) |
| Reduced-order model (POD/DMD) | Only if FEM must run in real time | NumPy SVD, PyDMD |
| Surrogates (GP / NN / PINN) | Only after the physics model exists; GP surrogate speeds MCMC on the workstation | scikit-learn, GPyTorch, PyTorch, DeepXDE |
A commercial instrument gives you traceable geometry, a built-in heater controller, calibrated sensors and (usually) its own steady-state readout. It takes away freedom: you may not be able to add sensors where identifiability wants them, change the excitation profile, or command the heater from your code. The twin's job therefore shifts from "measure k" (the instrument already does that) to: estimate k earlier and with uncertainty, track drift of contact resistance and losses across runs, detect faults, simulate experiments that have not been run, and propose the next run.
| Question | Why it matters | Fallback if the answer is "no" |
|---|---|---|
| Does it stream data (RS-232/USB serial, Modbus, Ethernet, OPC UA) or only log to its own PC software? | Determines the ingest module: pyserial, pymodbus, opcua, or a file watcher on the vendor's CSV export | File watcher on exported CSV; worst case, periodic screenshot OCR is not acceptable — ask the vendor for a logging option |
| Which channels are exposed? (individual thermocouple/RTD readings, heater power, guard temperature, coolant temperature, or only the computed k) | Decides the observation model and identifiability | Add your own sensors on accessible surfaces (Section 4.3) |
| Can set-points be written remotely? | Needed for the virtual→physical loop (true twin) | Human-in-the-loop: the twin recommends, an operator applies; log the recommendation and the action |
| What are the internal geometry and materials (bar lengths, sensor positions, reference-bar k)? | Fixed model inputs; the manual or vendor drawings usually give them | Treat unknown geometry as parameters with tight priors; calibrate with a certified reference sample |
| What reference samples and calibration certificates come with it? | Your ground truth for validation | Buy or borrow references (Pyroceram 9606, stainless 304, PMMA, borosilicate) |
| Sampling rate and timestamp source? | Filter design; clock alignment | Timestamp on arrival at the ingest PC; keep sequence numbers |
| Safety interlocks and maximum temperatures? | Your software must never be the only protection | Never bypass; put software limits below hardware limits |
| Licence terms of the vendor software and data format? | Some vendors lock exports | Document the limitation; request an SDK |
If the instrument exposes too few channels for identifiability, add external sensors at accessible points (outer insulation surface, coolant inlet/outlet, ambient, and if the vendor allows, sample faces). Use NTC thermistors with an ADS1115, or PT100/PT1000 with MAX31865, on an ESP32 or Raspberry Pi, emitting JSON at 1 Hz. Inter-calibrate all added sensors against the instrument's own sensors by soaking them together at three temperatures; only relative offsets matter for ΔT. Print mounts in PETG/ASA/PC, not PLA, near warm surfaces. Keep added wiring away from the heater and outside the guard; otherwise you perturb the measurement you are twinning.
| Aspect | Lab mode (teaching) | Research mode |
|---|---|---|
| Who | Students following a worksheet | The team, and later other groups |
| Dashboard | Guided steps, live measured vs theoretical profile, "you are at 63 % of steady state", one-page auto-report with k ± U | Full parameter traces, residuals, posterior plots, raw data access, experiment-design suggestions |
| Estimation | Fixed, pre-calibrated Rc and h; estimates k only | Full θ estimation; drift tracking across runs |
| Control | None (or vendor software only) | Recommendations, closed loop where permitted |
| Data | Written to the same database, tagged mode=lab, course=... | Tagged mode=research, with run metadata and git commit |
Lab-mode runs are not throwaway: hundreds of student runs on reference samples are exactly the dataset you need to learn instrument drift, operator effects and sensor ageing, and to validate the model across time.
| Layer | This week's implementation |
|---|---|
| Physical asset | The commercial apparatus, plus any added sensors |
| Sensing / acquisition | Instrument stream or CSV export; optional ESP32 sensors; 1 Hz |
| Data pipeline | Ingest → pydantic validation → MQTT topic → PostgreSQL (+TimescaleDB) and Parquet archive |
| Virtual model | 1D finite difference; parameters θ = [k, Rc,hot, Rc,cold, hloss, ρc]; material library |
| Synchronisation | Kalman filter on temperature field at 1 Hz; windowed least-squares refit of θ every few minutes; UKF/Bayesian in week 2 |
| Analytics / services | Time-to-steady-state forecast; early k with uncertainty; residual-based fault flag; virtual experiments; next-run recommendation |
| Visualisation | Streamlit (lab and research pages) |
| Feedback (virtual→physical) | Recommendation shown to operator; direct set-point write if the instrument allows |
services/early_k.py, services/forecast.py, services/anomaly.py, services/virtual_experiment.py, services/next_run.py).scipy.optimize.least_squares (residuals Tmeas − Tmodel(θ); loss="soft_l1", bounds, x_scale). Covariance ≈ s²(JᵀJ)⁻¹ gives error bars from day one.emcee or PyMC with physical priors (e.g. PMMA k ∈ [0.15, 0.25]; log-normal Rc), ArviZ diagnostics; add a Kennedy–O'Hagan Gaussian-process discrepancy term if residuals show structure. This is the Kapteyn–Willcox view in miniature: each asset keeps a unique digital state on a shared model, updated by Bayesian inference.Expose a function simulate_run(material, thickness, T_hot, T_cold, duration, theta_samples) that integrates the model forward from either the current filtered state or a cold start, for each of N posterior samples of θ, and returns median and 5–95 % bands for every virtual sensor, time-to-steady-state and the expected ΔT across the sample. Two uses: (a) teaching — students predict before they measure; (b) research — screening whether a proposed sample/temperature combination will give a resolvable ΔT at all (Section 3 example: an aluminium disc 5 mm thick gives ΔT ≈ 0.02 K, which no instrument resolves well). Keep virtual runs in the same database with origin=simulated so they are never confused with measurements.
Assumes instrument data is reachable by day 2 and the team can commit roughly 25–30 hours each this week. Instrument time is the scarce resource: book it in blocks from day 1 and run reference samples continuously in the background.
| Day | Goal | Deliverables | Pairs (suggested) |
|---|---|---|---|
| 1 (Mon) | Scope and plumbing | Instrument checklist (4.2) completed; repo with CI; interfaces.py; PostgreSQL schema; analytical oracle; sensitivity study of exposed channels; instrument time booked | CS1 + ChemE1: repo, DB. CS2 + Energy: instrument interface spike. ChemE2 + ChemE3: manual, geometry, reference samples, SOP draft |
| 2 (Tue) | Data in, model running | Live or file-watch ingest writing to DB; replay tool; fd1d.py passing verification tests; first reference run recorded | CS2 + ChemE2: ingest. Energy + CS1: model. ChemE1 + ChemE3: first run, calibration log |
| 3 (Wed) | Estimation | Steady-state detector; least-squares fit on day-2 run with covariance; KF running on replay; residual plots | Energy + ChemE1: least squares. CS1 + ChemE3: KF. CS2 + ChemE2: dashboard skeleton, second run |
| 4 (Thu) | Digital shadow | End-to-end live: instrument → DB → KF → dashboard with 2σ bands; virtual-experiment page; lab-mode page | All, integration day; one person on documentation |
| 5 (Fri) | Decisions and review | Stop-early recommendation live; next-run suggester; if instrument allows, set-point write-back (twin); V&V summary from the runs so far; retrospective; week-2 plan | All; 30-minute demo to Prof. Khare |
| Weekend / background | Validation and Bayesian calibration | Remaining reference runs queued; MCMC on the workstation; posterior plots | Rota for instrument babysitting |
thermal-twin/ ├── pyproject.toml # pinned dependencies; package "thermotwin" ├── configs/ # instrument_<model>.yaml, materials.yaml, estimator.yaml, modes/lab.yaml, modes/research.yaml ├── firmware/esp32/ # only if extra sensors are added ├── hardware/ # fixtures, sensor mounts (STEP + source), photos ├── db/ # schema.sql, migrations/ (alembic), seeds/ ├── src/thermotwin/ │ ├── interfaces.py # Asset / Model / Estimator / Store / KnowledgeBase protocols │ ├── physics/ # analytical.py, lumped.py, fd1d.py, fem2d.py, materials.py │ ├── estimation/ # steady.py, least_squares.py, kalman.py, bayes.py, sensitivity.py │ ├── io/ # instrument_<model>.py, csv_watcher.py, serial_reader.py, mqtt_bridge.py, schema.py, storage_pg.py, replay.py │ ├── services/ # early_k.py, forecast.py, anomaly.py, virtual_experiment.py, next_run.py, report.py │ └── twin/ # state.py, runner.py, decisions.py, safety.py ├── dashboard/ # app.py, pages/lab.py, pages/research.py ├── notebooks/ # exploration only; never imported ├── data/ # raw/ (immutable), processed/; DVC or git-lfs ├── tests/ # unit, property (hypothesis), replay regression, @pytest.mark.instrument ├── docs/ # MkDocs: architecture, derivations, SOPs, data dictionary, assumptions log └── .github/workflows/ci.yml # ruff, mypy, pytest
interfaces.py is the investment that pays off in the reactor phase: FD1DConductionModel and a future PackedBedReactorModel both expose step(state, u, theta, dt), observe(state), params() and param_priors(), so every estimator, service and dashboard page is reused unchanged.
| Module | Libraries | What it does |
|---|---|---|
physics/analytical.py | NumPy | steady_profile(layers, T_hot, T_cold); slab_transient(x, t, alpha, L, T0, T1, n_terms); test oracle |
physics/fd1d.py | SciPy sparse, solve_ivp, solve_banded | Builds A(θ), B(θ) on a mesh with interface nodes; Dirichlet/Neumann/Robin classes; explicit, backward-Euler, Crank–Nicolson, BDF steppers |
physics/materials.py | YAML, pandas | Material library (k, ρ, c, temperature dependence, source and uncertainty) |
estimation/steady.py | pandas, statsmodels | Rolling-slope steady-state detector; comparative/absolute k; multi-thickness OLS for Rc |
estimation/least_squares.py | SciPy least_squares, NumPy | Windowed fit, Jacobian covariance, scaled sensitivity plots |
estimation/kalman.py | FilterPy (pin version) or a 60-line NumPy KF | Discretised F, B; Q, R from calibration noise; innovations; UKF later |
estimation/bayes.py | emcee or PyMC, ArviZ | Posterior over θ; runs on the workstation; writes posterior samples to DB |
estimation/sensitivity.py | SALib | Sobol/Morris indices; identifiability report |
io/instrument_*.py | pyserial / pymodbus / opcua / watchdog | Instrument-specific reader emitting a common Sample record |
io/schema.py | pydantic | Validates units, ranges, monotonic timestamps; rejects and logs bad packets |
io/mqtt_bridge.py | paho-mqtt, Mosquitto | Topics rig/<id>/telemetry and rig/<id>/cmd (the virtual→physical channel) |
io/storage_pg.py | SQLAlchemy 2, psycopg 3, TimescaleDB | Writes samples, runs, estimates, posteriors; Parquet export per run |
io/replay.py | pandas, asyncio | Re-streams stored runs at ×1–×100 for development and regression tests |
services/*.py | NumPy, model and estimator APIs | Early-k, forecast, anomaly, virtual experiment, next-run (D-optimal), report (Jinja2 → HTML/PDF) |
twin/runner.py | asyncio | Event loop: ingest → KF predict/update → periodic θ refit → services → decisions → persist |
twin/safety.py | — | Software limits below hardware limits; never the only protection |
dashboard/app.py | Streamlit, Plotly | Lab page and research page; buttons publish MQTT commands or recommendations |
instruments(id, model, serial_no, geometry_json, calibration_cert, installed_on)
runs(id, instrument_id, mode, operator, sample_id, thickness_m, clamp_force_n, started_at, ended_at,
config_hash, git_commit, origin) -- origin: measured | simulated | replay
samples(id, material, supplier, lot, nominal_k, notes)
telemetry(time, run_id, channel, value, unit) -- hypertable (TimescaleDB) or partitioned by run
estimates(time, run_id, estimator, param, mean, sd) -- k, R_c_hot, R_c_cold, h_loss, rho_c
posteriors(run_id, method, param, sample_idx, value) -- MCMC draws
events(time, run_id, kind, payload_json) -- steady_state, anomaly, recommendation, command
materials(name, k, rho, c, T_ref, k_dTdx, source) -- material library (also loaded into configs)
Keep telemetry long-format (one row per channel per timestamp) so new instruments add channels without schema changes. Never store derived quantities in the telemetry table; they go in estimates with the estimator version.
pre-commit with ruff and mypy; pinned dependencies; one shared environment on the workstation.| Pitfall | Symptom | Mitigation |
|---|---|---|
| Contact resistance dominates | k varies with thickness or re-clamping | Follow the vendor's grease/pressure SOP exactly; multi-thickness regression; explicit Rc parameter tracked across runs |
| Lateral losses | Upper and lower flux estimates disagree; curved bar profiles | Mean stack temperature near ambient; fin-loss term; guard set correctly; 2D check in week 2 |
| Sensor offsets | Non-zero ΔT with heater off | Zero-power check at the start of every run; inter-calibrate any added sensors |
| Thermocouple cold-junction error | Offsets that track room temperature | Log ambient; include an offset parameter per channel in research mode |
| Timestamp drift between instrument and PC | Filter diverges or lags | One time authority; sequence numbers; replay tests |
| Poor identifiability | Large, correlated parameter uncertainties | Sensitivity study before fitting; change the experiment, not the code |
| Over-trusting the vendor's k | Twin "validated" against the instrument's own output | Validate against certified reference materials, not the readout |
| Over-engineering | Kubernetes, cloud, no physics | Freeze the stack on day 1; the day-4 gate |
| Safety | Over-temperature; sample off-gassing | Hardware limits untouched; software limits lower; supervised runs; polymer samples below their service temperature |
twin.*) to the same server, or must the twin's data live elsewhere?Through a read-only KnowledgeBase adapter (io/catalysis_db.py) that converts records into ParameterPrior objects with value, uncertainty, units, provenance (table, record id, DOI) and validity range. The reactor model's param_priors() returns these; the same estimators that today update k from live data will then update kinetic parameters, with the database as prior and the experiment as evidence. Build the adapter against a tiny mock table this week (two rows is enough) so the interface exists before the real data arrives.
lumped.py).fd1d.py directly.| Tool | Decision | Reason |
|---|---|---|
| Plain Python (NumPy, SciPy, pandas, FilterPy, PyMC/emcee, SALib) | Adopt | Transparent, free, teaches the whole team every layer |
| Mosquitto (MQTT) | Adopt | Decouples ingest, twin and dashboard; trivial to add a second instrument |
| PostgreSQL + TimescaleDB | Adopt | Matches the provided database; SQL joins between twin data and catalysis data later |
| Streamlit | Adopt | Fastest route to lab and research pages; Grafana optional for time-series panels |
| Grafana on PostgreSQL | Optional | No-code monitoring panels for the lab bench |
| FMI/FMU (FMPy, pythonfmu), OpenModelica | Learn lightly; export the model as an FMU in week 2–3 | Co-simulation standard; useful when the reactor model meets other tools |
| scikit-fem / FEniCSx | Week 2 | 2D check of the 1D assumption |
| COMSOL / Ansys | Only if licensed, as an independent reference | Not a twin runtime |
| PyTorch, GPyTorch, BoTorch, DeepXDE | Workstation, from week 2 | Surrogates, Bayesian optimisation, PINN side-study |
| Eclipse Ditto, ThingsBoard, Node-RED | Skip for now | Orchestration is not the bottleneck; Aarhus found their simple twin fitted only 5 of 14 surveyed DT frameworks |
| Azure Digital Twins (DTDL), AWS IoT TwinMaker, NVIDIA Omniverse | Skip implementation; read DTDL for schema ideas | Cost, lock-in, GPU-heavy visuals |
| Asset Administration Shell (Eclipse BaSyx) | Optional later exercise | Describing the instrument as an AAS is good documentation practice |
Standards to cite: ASTM E1225, D5470, C177/ISO 8302, C518/ISO 8301, E1461, ISO 22007-2; GUM (JCGM 100:2008) for uncertainty; ISO 23247-1…4:2021; ISO/IEC 30173:2023; ISO/IEC 30141; FMI; AAS (IEC 63278); OPC UA; MQTT (OASIS). Check IEEE 2888 working-group status before citing it.
| Case | What they did | What worked | Documented difficulties | Apply here |
|---|---|---|---|---|
| NASA, Apollo and Glaessgen & Stargel (2012) | Physical ground twins in Apollo; 2012 paper defined the DT as a probabilistic, as-built simulation | Clear vision | "Ultra-high fidelity" exceeded available computing | Keep probabilistic and as-built; drop ultra-fidelity |
| Kapteyn, Pretorius & Willcox (2021), UAV | Dynamic Bayesian network over component-based reduced-order models; experimental calibration | Principled updating with end-to-end UQ | Needs ROM libraries and expertise | Posterior over θ + KF is the miniature version |
| Niederer et al. (2021) | Cardiac and aerospace exemplars | Clear challenge list | Twins are bespoke and hard to scale | Reuse-oriented interfaces |
| Aarhus incubator (2021–2025) | Insulated box with heat bed; RC models; message bus; KF anomaly detection; open source | A 4-parameter model captured heat-bed thermal inertia better than a 2-parameter one | Only 5/14 frameworks could host it; maintenance | Closest template: clone the repository, copy the RC + KF + messaging pattern |
| ETH Zurich machine-tool thermal twin (Lang et al., 2024) | Thermomechanical model + KF state observer | Few sensors plus estimation beat a 284-sensor interpolation; thermal-error RMSE roughly halved | Model reduction; long-term drift | Estimation beats adding sensors |
| Power-electronics thermal twins (Kuprat et al., 2024) | PSO identification + dual EKF online | Parameter drift reveals thermal-path ageing | Coexisting ageing mechanisms confound parameters | Track Rc across runs as an instrument-health signal |
| Inverse heat-transfer twins (ANN + Kalman smoother; EnKF in casting) | Surrogates inside filters | Near-real-time inversion | Surrogate training; sensor placement | Surrogates only when physics is too slow |
| GE Predix / Digital Wind Farm | IIoT platform with asset twins | Condition monitoring | Company-sourced value claims; platform was costly and some divisions struggled with it | Start from a decision, not a platform |
| Rolls-Royce engine health monitoring | Engine data to a ground twin that can refocus monitoring | Time-on-wing, predictive maintenance | Vendor-reported outcomes; heavy integration investment | Let the twin change what is measured next |
| Catalytic and process reactors (fixed-bed digital design; pilot SMR + WGS twin; plasma-reactor twin) | Calibrate a few meaningful PDE coefficients; "experiment digital twin" of lab kinetics scaled to plant | Reformer RMSE ~12 °C; H₂ yield within ~2 % | Scarce modelling skills; maintenance; vendor-heavy sources | Calibrate a few physical parameters, not large black-box models |
| Pharmaceutical continuous manufacturing | Mechanistic, hybrid and data-driven twins | Hybrid strategies | Real-time applications rare; integrated twins immature; regulation | A closed loop is an achievement; plan for it explicitly |
| Self-driving labs (Burger et al., 2020) | Mobile robot ran 688 experiments in 8 days via batched Bayesian optimisation | Closed-loop, model-guided experimentation | Robust automation; human oversight | Your next-run service is a micro self-driving lab |
| Buildings, batteries, additive manufacturing (thermal) | RC-network and equivalent-circuit twins with KF | Low-order RC + KF is the workhorse | Sparse sensors; drift; AM models too slow | The RC + KF core is industry-standard |
On industrial numbers: figures such as GE's "1.2 million digital twins" or Rolls-Royce's "400 unplanned maintenance events prevented annually" come from the companies or their vendors. Cite them as claims. The National Academies (2023) note that enthusiasm for digital twins currently outweighs evidence of their success.
Prioritised lessons: (1) start from the decision the twin informs; (2) few, physical, continuously updated parameters; (3) estimation beats adding sensors; (4) VVUQ and data quality are continual, not a phase; (5) design for reuse; (6) plan a real, small virtual→physical loop so the project does not stall at the shadow stage.
solve_ivp, least_squares, solve_banded); FiPy; scikit-fem; FEniCSx tutorial (jsdokken.com/dolfinx-tutorial).| Date | Who | Change |
|---|---|---|
| 2026-10-11 | Initial draft (v1) | 16-week plan for a self-built student rig; full physics, lessons and reading list. |
| 2026-10-11 | Revision (v2) | Rewritten for a six-person CS/Energy/ChemE team, a commercial instrument, a one-week build, PostgreSQL storage, a training workstation, lab and research modes, and explicit replicate / virtual-experiment / optimise capabilities. Converted to editable HTML. |