← 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 with five different labels. Thus physicsbase solves them with one kernel.

The physicsbase team
July 2026 · 7 min read

In every numerical-methods course, the professor solves the heat equation. Then the professor notes that the same code solves diffusion, electrostatics, and porous flow. You only change the labels on the variables. This looks like a trick. It is not. It is the strongest idea in computational physics. We built physicsbase around it.

The one equation

Remove the labels. Then every one of these steady problems is the same statement. A quantity u diffuses through a medium. A source drives it. A flow can also carry it.

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

The meaning of the symbols selects the physics. That is the whole idea:

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

Add the \(\mathbf{v}\cdot\nabla u\) term. Then it becomes convection-diffusion. A flow field carries a scalar. This is the base of transport problems. Add a time derivative. Then it is the transient version. We solve it with a θ-method integrator.

What that buys an agent

There is one element library, one assembly path, and one set of boundary conditions (prescribed value, flux, and convection). Then you get every physics above. An agent does not learn five APIs. It learns one problem shape. It 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 is the same as everywhere else in physicsbase. The agent sends a JSON description of the field problem. It reads a JSON answer. Here is a real one. A bar generates heat inside itself. Both ends are held at 20 °C. 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 each node and the heat flux in each element. You assemble nothing. You derive nothing:

← 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 is \(20 + \dfrac{QL^2}{8k}\) to the digit. This is the exact textbook answer for a heated bar. Change k to a diffusivity. The same call returns a concentration field. Set k to 1. The returned gradient is a velocity field. Same wire, same shapes, different physics.

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

The honest edge

This one method is strong because it is linear scalar transport. It gives you potential (inviscid) flow, which is a real and useful model. It gives you scalar transport through a known velocity field. It does not give you full viscous fluid dynamics. The Navier-Stokes equations couple velocity and pressure nonlinearly and need their own method. We say this plainly in the docs. We do not present potential flow as CFD. One kernel covers a lot. It does not cover everything. We prefer to tell you where the limit 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 →