MOOSE Simulation on Windows (Git Bash + Docker)
This skill governs the complete lifecycle of running MOOSE simulations on a Windows machine using Docker. Follow every section as a checklist.
1. Prerequisites Checklist
Before running ANY simulation, verify all prerequisites. Do not skip any step.
1.1 Docker Desktop Must Be Running
docker info > /dev/null 2>&1 && echo "DOCKER OK" || echo "FAIL: Start Docker Desktop"
If Docker is not running, inform the user: "Docker Desktop must be running. Please start it and confirm." Do NOT proceed until Docker responds.
1.2 MOOSE Image Must Be Available
MSYS_NO_PATHCONV=1 docker image inspect idaholab/moose:latest > /dev/null 2>&1 \
&& echo "IMAGE OK" || echo "PULLING IMAGE..." && MSYS_NO_PATHCONV=1 docker pull idaholab/moose:latest
The MOOSE executable is at /opt/moose/bin/combined-opt inside the container.
This is the combined application that includes ALL 25+ physics modules.
1.3 Input File Must Exist
Every simulation requires a .i file (HIT format). Before running:
- Verify the
.ifile exists in the case directory - Read the file to confirm it is syntactically valid HIT
- Check that it has at minimum:
[Mesh],[Variables],[Kernels](or an Action that creates them),[Executioner], and[Outputs]
2. Input File Authoring Standards
When creating a new MOOSE input file, follow these conventions learned from 21 successful quickstart cases.
2.1 File and Directory Naming
quickstart-runs/caseNN-descriptive-name/
caseNN_descriptive_name.i # input file (underscores in filename)
README.md # physics + usage documentation
caseNN_descriptive_name_out.e # Exodus output (auto-generated)
caseNN_descriptive_name_out.csv # CSV postprocessor output (auto-generated)
caseNN_*.png # visualization plots (generated by script)
- Directory name:
caseNN-kebab-case(hyphens) - Input file:
caseNN_snake_case.i(underscores) - Always include
exodus = trueandcsv = truein[Outputs]
2.2 Header Comment Block
Every .i file must start with a descriptive header:
# ============================================================
# Case NN: Title — Subtitle
# Brief description of the physics being solved.
#
# Governing equations (in readable math notation)
# Boundary conditions summary
# Domain dimensions and mesh size
# ============================================================
2.3 Inline Comments
Add comments explaining:
- Why each kernel/BC/material is needed (not just what it does)
- Physical meaning of parameter values (units, typical ranges)
- Relationships between coupled variables
- Solver/preconditioner choices and why they suit this problem
2.4 Required Output Blocks
Every simulation must produce both spatial and scalar outputs:
[Outputs]
exodus = true # spatial fields for visualization
csv = true # postprocessor time histories
[]
For transient problems, also include relevant [Postprocessors]:
- At least one domain-averaged quantity (conservation check)
- Extreme values (min/max of primary variable)
- Boundary fluxes or integrals where physically meaningful
2.5 Mesh Sizing for Quick Runs
Keep meshes small enough to converge in under 2 minutes on a laptop:
| Problem Type | Recommended Mesh |
|---|---|
| 2D steady state | 20x20 to 40x40 |
| 2D transient | 20x20 to 40x40 |
| 2D FV (Navier-Stokes) | 30x30 |
| Quasi-1D (thin strip) | 100x5 |
| Phase field | 40x40 |
2.6 Docker Portability Rules
These rules prevent failures inside the idaholab/moose:latest container:
| Rule | Reason |
|---|---|
Add disable_fpoptimizer = true and enable_jit = false to ALL DerivativeParsedMaterial blocks |
The container lacks mpicxx, so JIT compilation fails. The fpoptimizer can also cause issues. |
Use time_step_interval not interval in [Outputs] sub-blocks |
MOOSE renamed this parameter; interval triggers an unused-parameter error |
Use NEWTON or PJFNK solve types with lu or hypre/boomeramg preconditioner |
These are the most robust choices for small educational meshes |
Avoid type = FileMesh unless the mesh file is in the same directory |
Docker volume mounts map a single host directory |
3. Running Simulations in Docker
3.1 The Canonical Run Command
ALWAYS use this exact pattern. Never deviate.
MSYS_NO_PATHCONV=1 docker run --rm \
-v "C:/Users/simon/Downloads/moose-next/quickstart-runs:/work" \
-w /work/caseNN-directory-name \
--entrypoint /bin/bash \
idaholab/moose:latest \
-c '/opt/moose/bin/combined-opt -i INPUT_FILE.i 2>&1 | tail -40'
Every element is mandatory:
| Element | Purpose |
|---|---|
MSYS_NO_PATHCONV=1 |
Prevents MINGW from mangling Unix paths like /work, /opt/moose |
--rm |
Auto-removes the container after exit |
-v "C:/...:/work" |
Mounts the host directory into the container. Use forward slashes for the Windows path. |
-w /work/subdir |
Sets the working directory inside the container |
--entrypoint /bin/bash |
Overrides the default entrypoint to use bash |
-c '...' |
Single-quoted command string prevents host shell expansion |
2>&1 | tail -40 |
Captures stderr+stdout and shows only the last 40 lines (MOOSE is verbose) |
3.2 Verifying Success
A successful run ends with output containing:
Solve Converged!
...
Finished Executing [XX.XX s] [XXX MB]
Check for these failure indicators:
| Indicator | Meaning |
|---|---|
*** ERROR *** |
Fatal error — read the message for the cause |
MPI_ABORT |
Crash — usually a missing material property or invalid parameter |
Solve failed and timestep already at dtmin |
Solver divergence — reduce dt, switch preconditioner, or relax tolerances |
unused parameter |
A parameter name is wrong or was renamed in this MOOSE version |
not defined on block |
A material property is missing — add the required [Materials] block |
JIT compile failed |
Missing mpicxx — add disable_fpoptimizer = true and enable_jit = false |
3.3 Running Multiple Cases
MSYS_NO_PATHCONV=1 docker run --rm \
-v "C:/Users/simon/Downloads/moose-next/quickstart-runs:/work" \
--entrypoint /bin/bash \
idaholab/moose:latest \
-c '
for dir in case14-thermoelasticity case15-lid-driven-cavity; do
echo "=== $dir ==="
cd /work/$dir
ifile=$(ls *.i | head -1)
/opt/moose/bin/combined-opt -i $ifile 2>&1 | tail -5
echo "STATUS: $?"
echo
done
'
4. Output Artifacts and Validation
After a successful run, these files MUST exist in the case directory:
4.1 Required Artifacts
| Artifact | Source | Purpose |
|---|---|---|
caseNN_name_out.e |
exodus = true |
Exodus II file — spatial field data for all variables at all time steps. Read with netCDF4 in Python or ParaView. |
caseNN_name_out.csv |
csv = true |
CSV of postprocessor values vs. time. Each row is a time step. Columns are time plus each postprocessor name. |
4.2 Validation Checks
After every run, verify:
- File existence: Both
.eand.csvfiles exist and have non-zero size - CSV sanity: Read the CSV and check that:
timecolumn spans fromstart_timetoend_time- Conserved quantities (e.g., average concentration, total energy) remain constant or change monotonically as expected
- No
NaNorInfvalues
- Exodus sanity: Open with netCDF4 and verify:
time_wholehas the expected number of steps- Nodal or element variables have physically reasonable values (no overflow, no all-zeros)
4.3 Named Output Sub-Blocks
When the input file uses a named [Outputs] sub-block like:
[Outputs]
csv = true
[exodus]
type = Exodus
time_step_interval = 5
[]
[]
The exodus file will be named caseNN_name_exodus.e (NOT caseNN_name_out.e).
The CSV always gets the _out.csv suffix from the top-level csv = true.
5. Visualization Requirements
Every case needs Python-generated PNG plots. The visualization script is at
quickstart-runs/visualize_all.py.
5.1 Plot Function Requirements
Each case needs a plot_caseNN() function that produces at least one PNG.
For steady-state problems: 2D contour of the primary variable(s) For transient problems: Snapshots at multiple times + time-history from CSV For multi-physics: Side-by-side panels showing each coupled field
5.2 Reading Exodus Files
MOOSE outputs two types of variables:
| Type | Where to Find | How to Read | Typical Variables |
|---|---|---|---|
Nodal (name_nod_var) |
vals_nod_var{N} |
get_nod_var(ds, idx, timestep) with node coordinates coordx, coordy |
T, u, disp_x, disp_y, c, w, V, porepressure, temperature |
Element (name_elem_var) |
vals_elem_var{N}eb{block} |
get_elem_var(ds, idx, block, timestep) with element centroids |
vonmises_stress, stress_xx, stress_yy |
FV (Finite Volume) variables (Navier-Stokes, etc.) are ALL element variables with NO nodal variables. Use element centroids for plotting.
Multi-block meshes (e.g., bimetallic strip with two materials) have separate
element variable arrays per block: vals_elem_var1eb1, vals_elem_var1eb2, etc.
Concatenate them for full-domain plots.
5.3 Plot Naming Convention
caseNN_descriptive_name.png # primary multi-panel plot
caseNN_variable_name.png # single-variable plot
caseNN_time_history.png # CSV-based time series
6. README Documentation Requirements
Every case directory MUST contain a README.md explaining the simulation.
Follow this structure:
# Case NN: Title — Subtitle
## Overview
2-3 paragraphs explaining:
- What physics is being modeled and why it matters
- What MOOSE modules/objects are used (with object names)
- What new concepts this case introduces vs. previous cases
---
## The Physics
- Governing equation(s) in readable form
- Boundary conditions and their physical meaning
- Material properties and their values (with units)
- Domain geometry and mesh
## Input File Walkthrough
Block-by-block explanation of the `.i` file:
- [Mesh]: domain and discretization
- [Variables]: what is being solved for
- [Kernels] or [Modules/...]: weak form terms
- [BCs]: boundary conditions
- [Materials]: constitutive relations
- [Executioner]: solver strategy and time stepping
- [Postprocessors]: quantities of interest
- [Outputs]: what files are produced
## Running the Simulation
Docker command (copy-paste ready):
```bash
MSYS_NO_PATHCONV=1 docker run --rm \
-v "C:/Users/simon/Downloads/moose-next/quickstart-runs:/work" \
-w /work/caseNN-directory-name \
--entrypoint /bin/bash \
idaholab/moose:latest \
-c '/opt/moose/bin/combined-opt -i caseNN_name.i 2>&1 | tail -30'
Expected Results
- What the solver output should look like (converged in N steps)
- Physical interpretation of the results
- What the plots show and how to read them
Key Takeaways
Bullet list of what the learner should take away from this case.
---
## 7. Common Failure Patterns and Fixes
These are real failures encountered across 21 cases. Check for these FIRST
when debugging a failed run.
### 7.1 MINGW Path Mangling (Silent Failure)
**Symptom**: Docker starts but produces no output files, or output is empty.
**Cause**: Missing `MSYS_NO_PATHCONV=1`.
**Fix**: Always prefix Docker commands with `MSYS_NO_PATHCONV=1`.
### 7.2 JIT Compilation Failure
**Symptom**: `sh: mpicxx: command not found` / `JIT compile failed`
**Cause**: `DerivativeParsedMaterial` tries to JIT-compile expressions using
`mpicxx`, which is not on PATH in the Docker container.
**Fix**: Add to every `DerivativeParsedMaterial`:
disable_fpoptimizer = true enable_jit = false
### 7.3 Missing Material Properties (PorousFlow)
**Symptom**: `Material property 'PorousFlow_constant_biot_modulus_qp' not defined on block 0`
**Cause**: `PorousFlowBasicTHM` action does NOT auto-create these materials.
**Fix**: Add explicit material blocks:
[Materials] [biot_modulus] type = PorousFlowConstantBiotModulus biot_coefficient = 1.0 solid_bulk_compliance = 1e-10 fluid_bulk_modulus = 2e9 [] [thermal_expansion] type = PorousFlowConstantThermalExpansionCoefficient biot_coefficient = 1.0 drained_coefficient = 0.0 fluid_coefficient = 0.0 [] []
### 7.4 Renamed Parameters
**Symptom**: `unused parameter 'Outputs/exodus/interval'`
**Cause**: MOOSE renamed `interval` to `time_step_interval`.
**Fix**: Use `time_step_interval` in all `[Outputs]` sub-blocks.
### 7.5 FV Navier-Stokes Parameter Names
**Symptom**: Vector parameter size mismatch errors in NavierStokesFV.
**Cause**: `momentum_inlet_function` was renamed to `momentum_inlet_functors`.
**Fix**: Use `momentum_inlet_functors` (plural, with "functors").
### 7.6 Solver Divergence
**Symptom**: `Solve failed and timestep already at dtmin, cannot continue!`
**Cause**: Newton iterations not converging — usually dt too large, bad
preconditioner, or ill-conditioned system.
**Fix** (try in order):
1. Reduce initial `dt` (e.g., from 0.5 to 0.1)
2. Switch preconditioner to LU: `-pc_type lu -pc_factor_mat_solver_type mumps`
3. Increase `nl_max_its` (e.g., from 20 to 30)
4. Add `nl_abs_tol` (e.g., 1e-11) alongside `nl_rel_tol`
5. Reduce `growth_factor` in `IterationAdaptiveDT` (e.g., from 1.5 to 1.2)
### 7.7 Porosity Material Type
**Symptom**: Errors about missing porosity derivatives or qp materials.
**Cause**: `PorousFlowPorosityConst` may not provide all derivatives that
`PorousFlowBasicTHM` expects.
**Fix**: Use `PorousFlowPorosity` with `porosity_zero` instead:
[porosity] type = PorousFlowPorosity porosity_zero = 0.3 mechanical = false thermal = false fluid = false []
---
## 8. Physics Module Quick Reference
Modules used in quickstart cases 01-21 and their key objects:
| Module | Cases | Key Objects |
|--------|-------|-------------|
| Framework only | 01-13 | `Diffusion`, `ADDiffusion`, `BodyForce`, `TimeDerivative`, `MatDiffusion`, `ConservativeAdvection` |
| `heat_transfer` | 14, 17, 21 | `ADHeatConduction`, `ADHeatConductionTimeDerivative`, `ADJouleHeatingSource` |
| `solid_mechanics` | 14, 20, 21 | `Physics/SolidMechanics/QuasiStatic`, `Physics/SolidMechanics/Dynamic`, `ComputeIsotropicElasticityTensor`, `ComputeLinearElasticStress`, `ADComputeThermalExpansionEigenstrain` |
| `navier_stokes` | 15, 16 | `[Modules/NavierStokesFV]` action — `INSFVMomentumDiffusion`, `INSFVMomentumAdvection`, `INSFVMassAdvection`, `INSFVMomentumBoussinesq`, `INSFVEnergyAdvection` |
| `phase_field` | 18 | `SplitCHParsed`, `SplitCHWRes`, `CoupledTimeDerivative`, `DerivativeParsedMaterial` |
| `porous_flow` | 19 | `[PorousFlowBasicTHM]` action, `PorousFlowPorosity`, `PorousFlowPermeabilityConst`, `PorousFlowMatrixInternalEnergy`, `PorousFlowThermalConductivityIdeal`, `PorousFlowConstantBiotModulus`, `PorousFlowConstantThermalExpansionCoefficient` |
| `fluid_properties` | 19 | `SimpleFluidProperties` |
---
## 9. Complete Run Workflow Checklist
When asked to create and run a new MOOSE simulation, follow ALL steps:
- [ ] **1. Verify prerequisites** (Section 1): Docker running, image available
- [ ] **2. Create case directory** with correct naming: `caseNN-kebab-name/`
- [ ] **3. Write input file** (Section 2): header, comments, outputs, portability rules
- [ ] **4. Run in Docker** (Section 3): use canonical command, check for convergence
- [ ] **5. Validate outputs** (Section 4): `.e` and `.csv` exist, values are sane
- [ ] **6. If run fails**: diagnose using Section 7, fix, and re-run
- [ ] **7. Generate plots** (Section 5): add function to `visualize_all.py`, handle nodal vs element vars
- [ ] **8. Verify plots visually**: read the PNG files and confirm physics looks correct
- [ ] **9. Write README.md** (Section 6): physics, walkthrough, Docker command, results
- [ ] **10. Report results** to user: summarize what converged, what the plots show, physical interpretation