What ModelManager is
ModelManager.jl is the generic, simulator-agnostic core of a family of Julia packages for running large agent-based modeling (ABM) campaigns. It owns everything that does not depend on a particular simulator:
- the trial hierarchy (
Simulation,Monad,Sampling,Trial), - parameter variations and space-filling designs,
- the SQLite database schema, queries, and migration framework,
- the parallel runner (with SLURM/HPC support),
- global sensitivity analysis (MOAT, Sobol', RBD-FAST), and
- ABC-SMC calibration.
Everything that is simulator-specific — how a simulation is actually launched, what a "version" means, how input folders are compiled — is reached through a single extension point: the AbstractSimulator interface.
The ecosystem
┌─────────────────────────────────────────────┐
│ ModelManager.jl │
│ trial hierarchy · variations · database · │
│ runner · sensitivity · calibration │
└───────────────────────┬─────────────────────┘
│ AbstractSimulator interface
┌───────────────────┴───────────────────┐
▼ ▼
PhysiCellModelManager (your backend)
(PhysiCell) (MySimulator)A simulator package depends on ModelManager, defines MySimulator <: AbstractSimulator, implements the required interface methods, and registers its globals in __init__. The package's users then call the package's own entry points; ModelManager runs underneath, unaware of which simulator is plugged in.
This separation means a feature added here — say, a new sampling design or a calibration kernel — is immediately available to every backend without any simulator-specific code.
Who should read these docs?
- Backend authors building a new simulator package. Start with Building a Simulator Backend; the Core Concepts pages (beginning with The trial hierarchy) explain the machinery you are plugging into.
- Advanced users of a backend (e.g. PCMM) who want to understand the generic layer — how variations are stored, how the runner deduplicates work, what the database schema looks like. The concepts here are shared verbatim with the backend you use.
- Contributors to ModelManager itself.
Because ModelManager has no simulator of its own, the runnable examples in these docs assume a backend has been loaded and initialized (i.e. initializeModelManager has succeeded and a ModelManagerGlobals instance with a concrete simulator is registered). The API shown is identical regardless of which backend provides it.
A minute-long tour
Once a backend is initialized, the generic workflow looks like this:
# 1. Describe which input folders a run uses (see Project configuration).
inputs = InputFolders(; config="default", custom_code="default")
# 2. Describe how to vary parameters (see Variations).
dv = DiscreteVariation(:config, XMLPath(["overall", "max_time"]), [60.0, 120.0, 240.0])
# 3. Build and run a trial. createTrial picks the right hierarchy level for you.
output = run(inputs, dv; n_replicates=3)run builds the appropriate trial hierarchy object, writes the variations to the database, and dispatches each pending simulation to the runner. Re-running the same script is cheap: ModelManager matches existing simulations and only runs what is missing.
From there you can layer on space-filling designs, sensitivity analysis, or calibration — all built on the same three steps.