The pdemodel Abstraction¶
pdemodel is the frontend abstraction that connects user-defined physics to
Exasim's numerical infrastructure. It contains symbolic callback functions for
the PDE, boundary terms, initial conditions, auxiliary variables, visualization
fields, and quantities of interest.
For the mathematical meaning of ModelC, ModelD, ModelW, u, q, w,
v, EOS, and artificial viscosity, see
Physics Models.
The frontend evaluates these callbacks symbolically during preprocessing and code generation. The generated C++ kernels are then called by the backend solver on CPU or GPU.
Architectural Role¶
flowchart LR
PDE["pde: sizes, parameters, solver options"] --> MODEL["pdemodel callbacks"]
MESH["mesh: geometry and boundary tags"] --> PRE["preprocessing"]
MODEL --> PRE
MODEL --> GEN["symbolic code generation"]
PRE --> BIN["backend input files"]
GEN --> K["generated kernels"]
BIN --> SOLVER["C++ solver"]
K --> SOLVER
SOLVER --> POST["solution, QoI, visualization"]
The pdemodel file does not own the mesh or solver state. It defines local
mathematical expressions evaluated at quadrature points, face points, or
initialization points.
Language Forms¶
In MATLAB, the model file returns a structure of function handles. In Python and Julia, the frontend imports or looks up functions by name.
Callback Arguments¶
Most callbacks use this argument pattern:
Boundary callbacks also receive trace and normal data:
| Argument | Meaning |
|---|---|
u |
Primary unknowns. |
q |
Gradient/LDG auxiliary unknowns. |
w |
wdg auxiliary variables, often used for additional model state. |
v |
odg auxiliary variables. MATLAB examples often name this argument v; Python examples use v; some documentation calls it odg. |
x |
Physical coordinates. |
t |
Physical time. |
param / named variables such as mu |
Entries from pde.physicsparam. |
uinf / named variables such as eta |
Entries from pde.externalparam / freestream data. |
uhat |
HDG trace state on faces. |
n |
Unit normal on a face. |
tau |
Stabilization parameter vector. |
Python and Julia examples often expose physicsparam and externalparam as
positional symbols such as mu, eta; code generation maps those symbols back to
the backend param and uinf arrays.
Core Components¶
| Component | Purpose | Used by |
|---|---|---|
initu |
Initial primary state and ncu inference. |
Preprocessing, initial solution construction. |
initv / initodg |
Initial odg auxiliary variables and nco inference. |
Preprocessing, backend initialization. |
initw |
Initial wdg auxiliary variables and ncw inference. |
Preprocessing, backend initialization. |
flux |
Physical flux for conservation laws or diffusive systems. | Residual/Jacobian assembly, postprocessing callbacks. |
source |
Volume source term. | Residual/Jacobian assembly. |
tdfunc / mass |
Time-derivative/mass contribution when required. | Time-dependent solves. |
ubou |
Boundary state prescription. | Boundary residuals and generated boundary kernels. |
fbou |
Boundary flux for LDG-like paths. | Boundary residuals and generated boundary kernels. |
fbouhdg |
HDG boundary flux. | HDG trace equations. |
fhat, uhat, stab |
Numerical flux, trace, and stabilization customization. | Advanced HDG/interface paths. |
sourcew |
Source/update equation for wdg. |
Models with auxiliary w variables. |
visscalars, visvectors, vistensors |
Derived fields for visualization. | Preprocessing output-count inference and VTK/postprocessing. |
qoivolume, qoiboundary |
Volume and boundary quantities of interest. | QoI postprocessing. |
Mathematical Meaning¶
For a conservation law, flux represents the physical flux tensor
\(F(u, q, w, v, x, t; \mu)\). source represents the volume source
\(S(u, q, w, v, x, t; \mu)\). Boundary callbacks define numerical boundary
states or fluxes depending on the discretization.
For an LDG diffusion model, a common pattern is:
For HDG, the trace state uhat appears in boundary and numerical flux terms:
Data Flow Through pdemodel¶
flowchart TD
PP["pde.physicsparam"] --> SYM["symbolic variables"]
UI["pde.modelfile"] --> MODEL["pdemodel"]
MODEL --> INIT["initu/initv/initw infer dimensions"]
MODEL --> OUT["vis/QoI callbacks infer output counts"]
MODEL --> GEN["flux/source/boundary callbacks generate kernels"]
INIT --> APP["app.bin sizes and flags"]
OUT --> APP
GEN --> CPP["Kokkos/C++ model kernels"]
APP --> RUN["backend solver"]
CPP --> RUN
RUN --> POST["dataout, VTK, QoI"]
Creating A New Model¶
The steps below create a scalar Poisson-like LDG model.
1. Choose dimensions and parameters¶
[pde, mesh] = initializeexasim();
pde.model = "ModelD";
pde.modelfile = "pdemodel";
pde.physicsparam = [1.0]; % diffusion coefficient
pde.tau = [1.0];
pde.porder = 2;
pde.saveParaview = 1;
For ModelD in 2D with one scalar unknown, preprocessing infers
ncu = 1, ncq = 2, and nc = 3.
2. Implement initu¶
initu must return the primary unknown vector. Preprocessing uses its length to
set ncu.
3. Implement volume terms¶
function f = flux(u, q, w, v, x, t, mu, eta)
f = mu*q;
end
function s = source(u, q, w, v, x, t, mu, eta)
x1 = x(1);
x2 = x(2);
s = (2*pi*pi)*sin(pi*x1)*sin(pi*x2);
end
4. Implement boundary terms¶
function fb = fbou(u, q, w, v, x, t, mu, eta, uhat, n, tau)
f = flux(u, q, w, v, x, t, mu, eta);
fb = f(1)*n(1) + f(2)*n(2) + tau*(u(1)-0.0);
end
function ub = ubou(u, q, w, v, x, t, mu, eta, uhat, n, tau)
ub = sym(0.0);
end
5. Add visualization or QoI callbacks¶
Set pde.saveParaview = 1 and define matching visualization callbacks when
backend VTK files are desired.
6. Run the simulation¶
The same callback structure applies in Python and Julia, with language-specific
syntax shown in the existing examples/Poisson/poisson2d/pdemodel.* files.
Parameterized Models And Sweeps¶
Use pde.physicsparam for numerical values that should change at runtime
without changing generated symbolic expressions. Use pde.physicsparamsweep
for multiple cases:
pde["physicsparam"] = [1.0]
pde["physicsparamsweep"] = [[0.5], [1.0], [2.0]]
pde["physicsparamwarmstart"] = 1
Best practice: keep the length and meaning of physicsparam fixed across a
sweep. Changing the number of parameters or the model equations requires
regeneration.
Advanced Topics¶
Multi-physics and coupled systems¶
Represent coupled systems by increasing ncu, adding auxiliary variables
through initw or initv, and writing flux/source/boundary callbacks that
return all components consistently. Ensure the ordering of variables is
documented in the model file.
Time-dependent models¶
Set pde.tdep = 1 or provide positive pde.dt entries. Use tdfunc or mass
callbacks when the model requires custom time-derivative behavior.
Auxiliary variables and material models¶
Use w/wdg and v/odg for auxiliary fields needed by closures, material
models, artificial viscosity, or multi-temperature/multi-species systems. Keep
auxiliary dimensions consistent with initw and initv.
Maintainability practices¶
- Keep model callbacks local and side-effect free.
- Use
physicsparamfor runtime parameters and avoid hard-coded constants that should be swept. - Keep variable ordering comments near
initu,flux, and boundary callbacks. - Validate boundary IDs against
mesh.boundarycondition. - Start with a single-rank CPU case before scaling to MPI/GPU.
Common Mistakes¶
| Mistake | Consequence |
|---|---|
| Returning the wrong number of flux components | Residual assembly or generated code dimensions become inconsistent. |
Omitting initu |
Preprocessing cannot infer ncu. |
Changing physicsparam length between sweep cases |
Standalone and frontend sweep validation should fail. |
Using boundary IDs not present in mesh.boundarycondition |
Boundary callbacks are not applied as intended. |
Defining visualization callbacks but leaving saveParaview = 0 |
No backend VTK files are written during solve mode. |