Note for now much of the docs is LLM written. This was done to save time and focus on code development. The docs have been LOOSLEY reviewed. However, the code itself has been either fully written by hand or fully reviewed. Therefore, the docs should at the moment be seen as a loose resource rather than authoratiative (and this is on top of the general ability for docs to drift)
8.2 KiB
Equation MVP
Start with the consumer sandbox, then read the barotropic density balance and primal gravity. The sandbox assembles a manufactured equilibrium on a box; it is not a stellar solver.
Physics and execution
Physics lives in serif/equations/<name>.hpp. An equation declares its test term,
existing Operand dependencies, local residual, explicit partial derivatives,
admissibility, and a numerical-order hint. EOS calls occur here, never in assembly.
EquationPoint and PointLinearization are the author-facing input and output types.
The Equation concept checks this interface without selecting a backend.
EquationRegistry{...} is the model's list of equations and validates unique residual
rows. It does not own coefficients, prepared data, or solver layout. Scalar H1/L2
values and gradients, and vector H1 values/divergences/gradients are executable volume operations. Declaring
another operation does not make it executable.
Execution lives in serif/operators. EquationPlan interprets the description;
operators::backend::mfem::make_volume_equation_cache declares a graph whose ordinary
dependency cache owns the accepted linearization. prepare_volume supplies current
inputs; free residual and Jacobian functions consume the accepted data. Workspace
is reusable scratch, separate from frozen element data. All equations use
the same graph construction and application functions. The physics files do not
include MFEM or an operator backend.
See the operator architecture and extension guide for ownership, restrictions, and the numerical implementation. Start with the consumer sandbox to see how a model connects MFEM term bindings, named caches, and the MFEM Jacobian adapter.
Mathematics and state
The density balance is integral (A(rho) - A(rho_s) + Phi - Omega^2 Psi - U_s) q_rho dV on stellar
domains, with the EOS pressure potential A. It reads Omega and the surface level U_s from global
scalar coefficients in the numerical state; its constructor specifies the rotation axis and center.
The generic Jacobian applies d(w f) = w df + f dw, including the equation's explicit
position derivative. Scalar pullback basis functions stay fixed when displacement varies;
gradients and divergences also differentiate the mapped operand and test. Packed Jacobian
columns follow EquationPlan::Columns (unique terms), then displacement.
Default preparation uses PreparationMode::reuse_unchanged and refreshes only changed
dependencies. Explicit PreparationMode::rebuild forces the requested graph to refresh. Caller vectors may change or be destroyed after
preparation without changing that snapshot. A rejected preparation invalidates the previous
snapshot; residual and Jacobian calls then fail until a successful preparation.
try_prepare_volume returns numerical rejections with element/point context. Incorrect bindings
and sizes remain programming errors reported through SERiF's always-active checks.
Mesh, spaces, mapping object, term bindings, and compactification grid function must outlive
the cache and any accepted data still in use. Rebuild term bindings after mesh topology or space changes. For coordinate
edits, notify MFEM with NodesUpdated() and prepare again. In-place coordinate changes that bypass
MFEM's update notification cannot be detected. Calls sharing MFEM spaces/mapper are serial.
discretization::backend::mfem::TermBinding associates an existing term with an MFEM
space, using its registered support and domain schema. It owns only its supported-DOF indices. It does not define
another field catalog. When a general DOF implementation is migrated, consolidate this
binding with it rather than retaining two maps.
The existing quadrature policy can override each equation's quadrature estimate. The shared rule covers every operand form and includes an estimate for the displacement determinant's degree. Fractional/tabulated EOS and curved mappings still require quadrature convergence checks.
Gravity contributions
primal_gravity.hpp contains
PrimalPoissonBalance{four_pi_G}. The coefficient is supplied by the caller so dimensional
and normalized units use the same equation. Its volume residual is
integral_all grad(v) . grad(Phi) + four_pi_G integral_star v rho
A row can return contributions() as a tuple. Each contribution declares a
TestOperand, Support, Operands, and a point evaluator returning the coefficient
of its test. Contribution<Operand<Test, Operation>, Support> supplies the first two
aliases and the row term. This keeps the gradient on the test and the restricted source
visible in the physics file. The zero potential at infinity is imposed separately.
Values are selected with point.fields.get<Term>() when a term appears once, or
point.fields.get<Operand<Term, Operation>>() when sampling more than one operation.
The divergence of a vector is a scalar. For a vector result use
PointLinearization<Operands, discretization::forms::VectorValue>; a derivative with
respect to a scalar is a three-vector, and with respect to a vector is a 3x3 matrix
indexed [output_component][input_component]. Existing scalar equations retain their
original interface.
Use the scalar binding for gravity::potential and the restricted density binding. The row uses
the same make_volume_equation_cache and numerical application functions as every other
equation; no gravity-specific MFEM operator is required.
Scope and regression coverage
The backend handles scalar H1/L2 value, scalar H1 gradient and vector H1 value/divergence/gradient volume equations in three dimensions on conforming serial meshes. It rejects unsupported operations and spaces. Scalar boundary constraints, point constraints, global scalars, tensor contractions and complete serial transpose actions are implemented; see the operator guide. H(div), H(curl), surface integrals and MPI assembly remain deferred.
The closure numerical tests were in MeanField, not yet SERiF. The following contracts are
ported using SERiF naming/style and a small serial mesh with core, envelope and vacuum attributes.
They exercise the shared volume machinery through a test-only two-field closure,
rho - rho_EOS(h), declared in tests/include/serif/tests/equations/test_equations.hpp; it is
not a production equation:
| MeanField test contract | SERiF coverage |
|---|---|
| Representable constant closure; stellar mass matrix | closure_kernels.cpp |
| Thermodynamic and geometry centered differences | closure_kernels.cpp, closure_conditions.cpp |
| Mapped volume, vacuum exclusion, directional linearity | closure_kernels.cpp |
| Supported dimensions; reduced/full restriction | closure_prepared.cpp, state_validation.cpp |
| EOS and folded-geometry rejection, then recovery | closure_prepared.cpp |
| Residual, individual columns, combined and packed actions vs manual assembly | closure_prepared.cpp |
| Frozen ownership and fresh preparation after rho/h/geometry changes | closure_prepared.cpp |
| n=1, 1.5, 3 and deformation conditions; balanced combined differences | closure_conditions.cpp |
| Exact closure remains zero under deformation | closure_conditions.cpp |
| Context identity/revision invalidation | Shared exact snapshots and binding/mesh validation; explicit full refresh remains available |
manual_closure.cpp ports the direct quadrature algorithm and evaluates the analytic polytrope
independently of the new equation evaluator and cached basis contractions. It is a test reference,
not a second production operator. The shared serial tests additionally compare tensor and dense
contractions and complete transpose actions; MPI assembly remains outside this port.
Additional checks cover tetrahedra/hexahedra, both displacement orderings, analytic dilation volume
and derivative, stale bindings, quadrature overrides and a compatible non-polytropic EOS.
No new convergence experiments or resolution study are part of this change.
Build with meson compile -C build, run the full suite with meson test -C build --print-errorlogs,
or select the new cases with build/tests/serif_tests '[equations]'.