← All posts
Engineering

One kernel, many physics.

Heat conduction, mass diffusion, potential flow, groundwater seepage, and pollutant transport look like five different problems. To a finite-element solver they are one equation wearing five different labels — so physicsbase solves them with a single kernel.

The physicsbase team
July 2026 · 7 min read

There's a moment in every numerical-methods course where the professor solves the heat equation, then quietly notes that the exact same code solves diffusion, and electrostatics, and porous flow, if you just relabel the variables. It feels like a trick. It isn't — it's the deepest bit of leverage in computational physics, and we built physicsbase around it.

The one equation

Strip the labels off and every one of these steady problems is the same statement: a quantity u diffuses through a medium, driven by a source and possibly carried along by a flow.

The field equation: \[ -\nabla\!\cdot\!(k\,\nabla u) \;+\; \mathbf{v}\cdot\nabla u \;=\; Q \]

Choosing what the symbols mean picks the physics. That's the whole idea:

Physicsu is…k is…
Heat conductiontemperaturethermal conductivity
Mass diffusionconcentrationdiffusivity
Potential flowvelocity potential1 (∇u is the velocity)
Seepage / Darcyhydraulic headpermeability
Electrostaticsvoltagepermittivity

Turn on the \(\mathbf{v}\cdot\nabla u\) term and it becomes convection-diffusion — a scalar being swept along by a flow field, the backbone of transport problems. Add a time derivative and it's the transient version, solved with a θ-method integrator.

What that buys an agent

One element library, one assembly path, one set of boundary conditions (prescribed value, flux, and convection), and every physics above comes for free. An agent doesn't learn five APIs — it learns one problem shape and changes the material label:

# heat: a bar with a hot end, cooling by convection at the other
from femengine import FieldModel, FieldMaterial, solve_field

m = FieldModel()
m.add_nodes([[x] for x in 0, ...])
m.add_material("steel", FieldMaterial(k=45))     # conductivity
m.set_value(0, 200)                            # fixed temperature
m.add_convection([-1], h=15, u_inf=20)          # Newton cooling
T = solve_field(m).values

# diffusion: identical call, k is now a diffusivity, u a concentration
m.add_material("gel", FieldMaterial(k=1e-9))

What crosses the wire

Over the API it's the same story as everywhere else in physicsbase: the agent sends a JSON description of the field problem and reads a JSON answer. Here's a real one — a bar generating heat internally, held at 20 °C at both ends. The agent sends the geometry, the conductivity, the heat source, and the fixed temperatures:

→ POST /field
"nodes": [[0],[0.25],[0.5],[0.75],[1.0]],
"materials": { "steel": { "k": 45 } },              // W/m·K
"elements": [ {"type":"field_line2","nodes":[0,1],"material":"steel"}, /* …3 more */ ],
"element_sources": [ {"element":0,"Q":50000}, /* … */ ],       // heat generation
"values": [ {"node":0,"value":20}, {"node":4,"value":20} ]        // held at 20°C

physicsbase returns the temperature at every node and the heat flux in every element — nothing to assemble, nothing to derive:

← physicsbase returns
"values":  [ 20.0, 124.17, 158.89, 124.17, 20.0 ],   // °C — a parabola
"fluxes":  [ [-18750.0], [-6250.0], /* … */ ],           // W/m² per element
"summary": { "n_nodes": 5, "analysis": "field_steady" }

That peak of 158.89 °C is not approximate — it's \(20 + \dfrac{QL^2}{8k}\) to the digit, the exact textbook answer for a heated bar. Relabel k as a diffusivity and the identical exchange returns a concentration field; set it to 1 and the returned gradient is a velocity field. Same wire, same shapes, different physics.

Under the hood the conductivity matrix is assembled exactly like a stiffness matrix, the capacitance matrix exactly like a mass matrix — the structural machinery and the field machinery are siblings, which is why both are validated against the same kind of closed-form checks: a linear temperature profile down a bar, the parabolic profile under uniform heating, the boundary-layer solution of convection-diffusion.

The honest edge

This unification is powerful precisely because it's linear scalar transport. It gives you potential (inviscid) flow, which is a real and useful model, and it gives you scalar transport through a known velocity field. What it does not give you is full viscous fluid dynamics — the Navier-Stokes equations couple velocity and pressure nonlinearly and need their own machinery. We say so plainly in the docs rather than dressing potential flow up as CFD. One kernel covers an enormous amount of ground; it doesn't cover everything, and we'd rather tell you where the edge is.

See it move. The homepage has a live heat-diffusion animation and streamline flow built on this kernel, and the docs have copy-paste examples for each physics. Read the multiphysics docs →