Skip to content
SHD Sim
Menu
Documentation menu

Draft. This manual is new and still growing. If something here does not match what you see in the software, the software is right — tell us and we will fix the page.

Case directory layout

What the application writes to disk, and where.

The claim this product makes is that it writes an ordinary input deck for the solver that will run it — one you can open in a text editor, run from a shell with the bundled binaries, hand to a colleague who has never seen this application, or diff against a case somebody else built by hand. This page is here so you can check that rather than take it on trust.

The short version: everything under a study directory belongs to the backend that solves it. Everything SHD Sim adds sits outside it, in the case directory around it.

Which backend depends on the analysis type, and most of this page is about the fluid one:

Analysis family The study directory holds
Every fluid family — flow, heat, multiphase, reacting, atmospheric, marine, and the OpenFOAM specialist solvers A standard OpenFOAM case: 0/, constant/, system/
Structural, and Thermal on the code_aster backend A code_aster deck: case.comm and case.export
Electromagnetics, Acoustics, and Thermal on the Elmer backend An Elmer deck: case.sif, ELMERSOLVER_STARTINFO and a mesh/ directory
Explicit dynamics An OpenRadioss deck: case_0000.rad and case_0001.rad
Shape optimisation SU2 configurations — direct.cfg, adjoint.cfg, and ffd.cfg / dot.cfg / deform.cfg as the run needs them — beside mesh.su2
Coupled (preCICE) Both participants' own directories, unchanged — an OpenFOAM case with a system/preciceDict on the fluid side, a code_aster deck on the solid side — plus precice-config.xml in run/ beside them

There is no system/controlDict in a structural, thermal, electromagnetic, acoustic, explicit-dynamics or shape study, and looking for one is the wrong question. Analysis types and solvers says which family an analysis type belongs to. The sections below, up to Standard OpenFOAM, or ours, describe the fluid case.


The library

Cases live in a workspace directory. The default is Documents/SHD Sim/My Cases, it is remembered between sessions, and --workspace=<dir> overrides it for one run.

My Cases/
└── Streamlined hull drag study (example)/   <- one directory per case
    ├── case.json                    SHD Sim
    ├── thumbnail.png                SHD Sim
    ├── geometry/                    SHD Sim
    │   └── hull.step                 the imported file, copied in
    └── run/                         SHD Sim
        └── case/                    <- the study directory: an OpenFOAM case
                                        here, a code_aster or Elmer deck for
                                        the families listed above

A case is a directory with a case.json in it — that is the test used on import, and an archive with no case.json anywhere is rejected.

The solver's directories live inside the case, not under AppData. A case has to be the whole case or it cannot be shared, archived or backed up.

Where a study lands

Case has Directory
One study run/case/
More than one study run/<study name>/, one per study

Two studies of the same body have different meshes and different solutions, so each gets its own directory rather than meshing over the other's polyMesh.

Study names are sanitised for the filesystem: \ / : * ? " < > | become _, whitespace runs become _, leading dots are stripped, and an empty result becomes case.

--dump-case=<dir> writes to <dir>/golden/ instead. With no case open at all — the dump and catalogue paths — the fallback root is runs/ under the application's local data directory.


The OpenFOAM case

A fluid study only. From here down, nothing is SHD Sim's own invention.

run/case/
├── 0/                     one file per field
├── constant/
│   ├── polyMesh/          written by the mesher
│   ├── triSurface/        the geometry as ASCII STL
│   └── …                  physical properties
├── system/
│   ├── controlDict
│   ├── fvSchemes
│   ├── fvSolution
│   └── …                  utility dictionaries
├── <time>/                written by the solver
├── postProcessing/        written by function objects
├── processor*/            written by decomposePar
├── log.<application>      one per utility and solver step
└── <case name>.foam       an empty ParaView marker, on request

Always written

File
system/controlDict Run control, libs, and every function object
system/fvSchemes Discretisation
system/fvSolution Linear solvers and the SIMPLE/PIMPLE/PISO block
system/decomposeParDict Parallel decomposition
system/blockMeshDict The background block
system/snappyHexMeshDict Body-fitted meshing
system/surfaceFeatureExtractDict Feature edges — one entry per geometry part
system/meshQualityDict #includeEtc the shipped defaults, then override maxNonOrtho and minTetQuality
0/<field> One per field in the derived field set

constant/turbulenceProperties is written except for the Euler-Euler, electrostatic, magnetic, MHD, solid-stress, conduction and shallow-water families.

constant/transportProperties or constant/thermophysicalProperties — never both. They are alternatives: a solver that builds a thermophysical model reads the latter and ignores the former, so shipping both leaves one silently unused. Neither is written for the Euler-Euler, electrostatic, solid-stress or shallow-water families.

Written when the physics asks for it

Family Adds
Marine & Waves constant/waveProperties
Euler-Euler constant/phaseProperties, and per phase constant/thermophysicalProperties.<phase> and constant/turbulenceProperties.<phase>
Lagrangian constant/kinematicCloudProperties
Compressible multiphase constant/thermophysicalProperties.<phase> per phase
Rotating frame (SRF) constant/SRFProperties
Solid stress constant/mechanicalProperties, constant/thermalProperties
Electrostatics, magnetostatics, MHD constant/physicalProperties
Shallow water constant/gravitationalProperties
Spray constant/sprayCloudProperties, constant/combustionProperties, constant/chemistryProperties, constant/reactions, constant/thermo
Premixed combustion constant/combustionProperties
Combustion / Reacting constant/combustionProperties, constant/chemistryProperties, constant/reactions, constant/thermo, constant/radiationProperties

Written when a setting asks for it

Setting Adds
Gravity on, or a solver that requires it constant/g
A rotating zone constant/MRFProperties
Any cell zone to cut system/topoSetDict
A moving mesh constant/dynamicMeshDict
A 6-DoF body 0/pointDisplacement
An initialisation region, or a VoF fill level system/setFieldsDict
Any fvOptions item, or Coriolis constant/fvOptions
Mesh operation mirrorMesh system/mirrorMeshDict
Mesh operation extrudeMesh system/extrudeMeshDict
Mesh operation createPatch system/createPatchDict
Mesh operation refineMesh with a cell set system/refineMeshDict

Mesh operations that can be driven entirely from the command line — renumberMesh, subsetMesh and the rest — get no dictionary.

Multi-region (conjugate heat transfer)

A conjugate case has a different shape entirely: almost nothing at the top level, because nothing is solved there.

run/case/
├── 0/<region>/<field>
├── constant/
│   ├── regionProperties
│   ├── g
│   └── <region>/thermophysicalProperties
│   └── <region>/turbulenceProperties     fluid regions only
└── system/
    ├── controlDict  fvSchemes  fvSolution  decomposeParDict
    ├── blockMeshDict  snappyHexMeshDict
    ├── surfaceFeatureExtractDict  meshQualityDict
    └── <region>/fvSchemes
    └── <region>/fvSolution

constant/regionProperties is what tells the solver — and the application, when it reads the case back — that this is a multi-region case.


Field files

One file per field in 0/. Which fields exist is derived from the analysis type and the turbulence model, not chosen; see Turbulence and viscosity models and Analysis types and solvers.

Each file carries dimensions, internalField and a boundaryField with one entry per patch. Dimensions are derived from the field name and are never asked for. The patch entries are the fan-out described in Boundary condition types.


What the mesher and the solver add

Nothing below is written by the application. It is what the bundled OpenFOAM utilities produce, in the places they normally produce them.

Path Written by
constant/triSurface/body.stl, or one .stl per geometry part Written by the application before meshing, from the imported geometry
constant/triSurface/*.eMesh surfaceFeatureExtract
constant/polyMesh/ blockMesh, then snappyHexMesh
constant/<region>/polyMesh/ splitMeshRegions
<time>/ directories The solver
postProcessing/<function>/<time>/<file>.dat The function objects in controlDict
processor*/ decomposePar, run with -force so an earlier decomposition is replaced. reconstructPar reads them back afterwards
system/data The solver, as a cache of the last run's residuals
log.<application> The application, capturing each step's merged output

log.checkMesh, log.blockMesh, log.snappyHexMesh, log.simpleFoam and so on. This is the convention OpenFOAM users expect, and it is the only record left once the log dock is cleared or the application is closed. It is also what the application reads back to recover the mesh quality figures for a case it did not mesh in this session.

system/data is deleted before every fresh run. A diverged run writes nan into it and the next attempt then dies before its first iteration with Wrong token type — expected scalar value, found on line 2: word 'nan', which says nothing about the divergence that actually happened. The per-rank copies under processor*/system/data are deleted too, because decomposePar does not overwrite what is already in a processor directory.

The mesh consolidation step

snappyHexMesh -overwrite writes its layer-added points into 0/polyMesh/ and leaves the pre-layer positions in constant/. A time directory shadows constant/ entirely, so the solver would read one and the utilities the other.

Immediately after snapping, the application moves 0/polyMesh/* into constant/polyMesh/ — and 0/<region>/polyMesh/* into constant/<region>/polyMesh/ — and says so in the log. Everything downstream then reads the mesh the mesher actually produced.

This is a fix-up, not a format change. What ends up in constant/polyMesh is an ordinary polyMesh.


Regeneration, and what survives it

The case is regenerated in full on every write. Nothing is patched in place.

Directory On rewrite
0/ Written, and pruned — any field file no longer part of the case is deleted
constant/ Written over. Nothing is deleted
system/ Written over. Nothing is deleted

0/ is pruned because OpenFOAM reads every field in the start time directory. A field left behind by an earlier configuration is still read: switching a case to a laminar solver left 0/k, 0/omega and 0/nut on disk, and renumberMesh then failed on 0/k because its boundaryField named patches the current mesh no longer had.

constant/ and system/ are not pruned, deliberately. They can legitimately hold a dictionary the application does not generate — a chemistry mechanism, an optimisationDict — and deleting those would throw away work. A dictionary you add by hand to constant/ or system/ survives; a field you add to 0/ does not.

Fields are not written at all on the pass that imports a mesh. Until the converter has run, nobody knows what the patches are called.

Paths are sanitised before anything is written: absolute paths, drive letters, UNC prefixes, .. traversal and the characters < > : " | ? * are all refused, and the refused paths are reported rather than silently dropped.


Standard OpenFOAM, or ours

The distinction this page exists to make.

The backend's own — everything inside run/<study>/. For a fluid study that means standard OpenFOAM, below. For the other families it means a code_aster, Elmer, OpenRadioss or SU2 deck, in that tool's own format and named as that tool expects: code_aster's run-aster.bat given case.export is what runs a structural or code_aster thermal study, and ElmerSolver reading ELMERSOLVER_STARTINFO is what runs an Elmer one.

Standard OpenFOAM — a fluid study's run/<study>/. The dictionary names, the directory structure, the FoamFile header, the keyword-and-semicolon syntax, the dimension sets, log.<application>, postProcessing/, processor*/, system/data, the time directories. A case copied out of run/ and run from a shell with the bundled binaries behaves exactly as it does here.

SHD Sim's own — everything outside it.

case.json The case model: analysis type, every setting, every study, the post-processing pipeline. This is what the application reads; it does not reconstruct a case by parsing the dictionaries back
thumbnail.png 320 px render of the viewport, captured on save, so the library is scannable
geometry/ The imported geometry file, copied into the case so the case is portable
run/ The container for study directories. Not a concept any of the backends have
exports/ CSV, images and animation frames, stamped with the time they were written

Two things inside the case are ours in content but standard in form:

  • The banner comment at the top of every generated dictionary reads Generated by SHD Sim and Do not edit by hand. It is a comment. The FoamFile block below it is standard.
  • The .foam marker file, written on request for ParaView, is named after the case rather than case.foam. It is empty either way — ParaView reads the directory it sits in.

Nothing in the case directory is encrypted, compressed, binary-only or keyed to an installation. writeFormat defaults to binary for the time directories, which is an OpenFOAM setting and can be changed to ascii; every dictionary the application writes is ASCII regardless.


Checking the claim

Open the case directory from the log dock, or find it at

Documents/SHD Sim/My Cases/<case>/run/<study>/

On a fluid study, read system/controlDict and then run the solver named in its application entry against that directory using the bundled binaries. On a structural or code_aster thermal study, read case.comm and hand case.export to the bundled run-aster.bat. On an Elmer study, read case.sif and run ElmerSolver in that directory. If any of them behaves differently from the way it behaved inside the application, that is a defect worth reporting.