Expand description
§The crates
Merlin is a workspace of small crates. The crates follow one rule: dependencies point from method to model, and from the run loop to the traits it drives, never the other way. A crate that solves does not know about files; the crate that writes files does not know about equations; the equations do not know about schemes. The compiler enforces it, because cargo refuses a cycle and a crate can name only what it depends on.
§The graph
An arrow points from a crate to a crate it depends on (the solid ones for what the crate
uses, the dashed ones for the Steppable contract: the two solvers implement it and the
driver drives it). merlin-cli also uses merlin-io and merlin-systems directly, and
merlin-docs, which has no code, links to all of them. merlin-materials depends on
merlin-core alone, for the bracketed root finds
(root_finder) that its interface solve and its numerical wave curves
share with the exact Riemann solver, and the arrow to it comes from merlin-systems, whose Euler
equations are closed by a fluid model.
| Crate | Depends on | What it holds |
|---|---|---|
merlin-core | rayon | Grids and fields with ghost cells in any dimension, the grid of blocks and its ghost exchange, boundary conditions, the executor that runs work over blocks on threads (the only module that names rayon), the stencil rules, the Runge-Kutta integrators, the multilinear interpolation to a probe point, the bracketed scalar root finds, the stepping core, and the Steppable trait that a run loop drives |
merlin-materials | core | The constitutive law of a fluid, FluidModel: the ideal, stiffened and Mie-Gruneisen gases; the response of each side of an interface (InterfaceResponse) and the solve of the interface problem between two, with the solver the caller names (solve_interface_problem, InterfaceSolver) |
merlin-systems | materials | The Equation trait and the systems: linear advection, Burgers’ equation, the Euler equations closed by any fluid model |
merlin-finite-volume | core, systems | Riemann solvers, flux schemes and limiters, the conservative operator, and the Solver |
merlin-levelset | core | Level-set transport: the Hamilton-Jacobi operator, velocity sources, reinitialisation, and the LevelSetSolver |
merlin-multimaterial | core, systems, finite-volume, levelset, materials | The solver of coupled fields (coupled materials): MultiMaterialSolver advances several materials with one Runge-Kutta loop over all their fields, each material a MaterialSlot that knows no fluid model (ConservativeSlot takes any equation and flux scheme); the owner map, the band of ghost cells and the fix-up of the level sets; with one material it is Solver to the last bit; a slot lends its material at an interface point (MaterialAtInterface) and the ghost fill takes all the materials at once, with the table of laws by pair of materials. Used by merlin-cli (the materials build) to run a problem file with several gases in contact |
merlin-io | core | Snapshots, checkpoints and their writers (CSV, and HDF5 with its XDMF description behind the hdf5 feature) |
merlin-driver | core, io | The run loop drive, the output schedule, progress hooks, and the construction of snapshots and checkpoints from any solver |
merlin-cli | all of the above (merlin-multimaterial in the materials build) | The merlin program: reads a TOML problem file, picks components by name, runs. Built in two families by cargo feature: materials (the fluids and the level set, on by default) and scalar (advection and Burgers); a build refuses a file whose system it does not hold |
merlin-docs | all of the above | This book, documentation only |
Two consequences of the graph: the numerics (merlin-finite-volume, merlin-levelset)
name no writer, so a solver can be built and tested without any file format, and the two
solvers do not depend on each other. cargo tree -e normal -p merlin-levelset shows
merlin-core alone.
§How a solver meets the run loop
A solver crate implements Steppable for its
own solver. The trait names what a run needs: the clock, a check of the end time and the
Courant number, one step towards a target time, the fields a snapshot holds, the field a
checkpoint saves, and a hook that rebuilds what is derived from the state after a
restart. The trait is in merlin-core because both solver crates must see it and neither
may depend on the other (a crate may implement a trait only if it defines the trait or the
type, so the trait sits in the crate they share).
merlin-driver is generic over that trait. drive shortens steps
to land on every requested output time and hands snapshots and checkpoints to the writer
and the sink the caller supplies; snapshot,
checkpoint and restore copy a
state out and back. A new solver needs no change in the driver.
Two details follow from what each solver outputs. The flux solver stores conserved
variables but writes primitive ones (density, velocity, pressure), so it builds an owned
copy of its state for each snapshot, and it reports the integrals of the conserved
variables separately, which is what a conservation check needs. The level-set solver
only lends phi and the velocity.
§Why the systems are apart from the schemes
The Equation trait says what a system is: its flux, its
wave speeds, its eigenvectors, its direction when swept. Everything that consumes a
system (a Riemann solver, a scheme, the operator) is in merlin-finite-volume and names
the system it needs. HLL and HLLC are written for any system that supplies its wave speeds
and star states (StarStates); the exact solver is written for
the Euler equations. All of them live with the numerics, not with the physics. Adding a system means adding a file to
merlin-systems; adding a scheme means a file to merlin-finite-volume; neither edits the
other.