This repository combines the working TCPC phantom LBM setup with the older Carreau-Yasuda non-Newtonian LBM implementation. It is configured for the #04 PE simulace regimes v1, v2, v3, v4a, and v4b, each runnable as:
newtoniansx(saccharose/SX constants from the historical non-Newtonian code)gx(glycerol/GX constants from the historical non-Newtonian code)
Generated geometry.vtk, solver binaries, and simulation results are intentionally not tracked.
Python:
python3 -m pip install numpy scipy trimesh vtk pyyamlSolver machine:
- CUDA compiler (
nvcc) - MPI compiler wrapper (
mpicxx) - VTK C++ development headers/libraries
- TNL checkout compatible with the historical solver
The build uses TNL_DIR to find TNL. Example:
scripts/build_solver.sh TNL_DIR=/home/bures/geraldine/Eichler/2026/2026_02_29-nonNew/Glycerol-nonNew/tnl_submoduleIf VTK is not discoverable through pkg-config, pass VTK_CONFIG:
scripts/build_solver.sh \
TNL_DIR=/path/to/tnl_submodule \
VTK_CONFIG="-I/usr/include/vtk -lvtkCommonCore -lvtkIOLegacy -lvtkCommonDataModel -lvtkIOXML -lvtksys"Generate the runtime geometry from the tracked STL:
python3 scripts/generate_geometry.pyThis writes:
runtime/geometry.vtk: solver input, withwalllabelsruntime/test.vtk: pre-PE label checkruntime/TCPC25_03_tapered.stl: tapered/capped intermediate STL
The default geometry reproduces the historical PE setup: 25 mm outlet extensions and 4 mm outlet diameter.
The generated VTK file is used as the wall mask. To match the historical working TCPC solver, the simulation imposes open boundary planes itself: x-min is IVC, x-max is SVC, y-min is outlet label 5, and y-max is outlet label 6. Wall cells from the VTK geometry override those plane labels.
scripts/build_solver.sh TNL_DIR=/path/to/tnl_submoduleThe solver executable is:
solver/sim_tcpc/sim_tcpcThe build still needs TNL headers for the lattice arrays, but the unused
immersed-boundary TNL sparse-matrix branch is disabled by default. Re-enable it
only for IBM/Lagrange experiments with use_TNL_LAGRANGE=yes.
Print all configured commands:
python3 scripts/run_all_cases.py --dry-runRun one case:
python3 scripts/run_case.py --regime v1 --material sxFor pilot or production runs, override timing/output directly on the command line instead of editing YAML:
python3 scripts/run_case.py --regime v1 --material newtonian --final-time 1 --vtk-period 1
python3 scripts/run_all_cases.py --final-time 10 --vtk-period 1 --print-period 0.1The solver writes results under results_<case-id>/, for example results_v1_sx/.
The command generated for each case passes the prescribed IVC/SVC flow rates from configs/regimes.yaml directly in ml/s.
For production runs, use the Slurm orchestrator from a persistent screen or
tmux session. It writes one job.sbatch and manifest.json per case,
submits the jobs, polls Slurm until all jobs finish, then computes
flows.csv for each completed result directory and a combined
flow_summary.csv under runtime/slurm/run-*.
Dry-run the planned submissions:
python3 scripts/slurm_run_cases.py \
--dry-run \
--case-prefix prod_batch_ \
--case-suffix _t10 \
--final-time 10 \
--vtk-period 1 \
--print-period 0.1Submit all configured regimes/materials and wait for postprocessing:
python3 scripts/slurm_run_cases.py \
--case-prefix prod_batch_ \
--case-suffix _t10 \
--final-time 10 \
--vtk-period 1 \
--print-period 0.1 \
2>&1 | tee runtime/slurm_driver_$(date +%Y%m%d_%H%M%S).logDefaults request --partition=gp, one GPU, 8 CPU threads, 32 GB RAM, and
12 hours walltime per case. Override these with flags such as
--time 24:00:00, --mem 64G, --gres gpu:rtx5080:1, or
--partition PARTITION_NAME.
The generated jobs export OMPI_MCA_accelerator=cuda so Open MPI does not
abort on nodes where both ROCm and CUDA accelerator plugins are present.
Additional job environment variables can be supplied as --env NAME=VALUE.
If the screen session is interrupted but Slurm jobs keep running, resume polling and harvesting with:
python3 scripts/slurm_run_cases.py --resume runtime/slurm/run-YYYYMMDD-HHMMSSVTK output includes:
wallvelocitymean_velocitylbm_rhopressure_pagamma_dotnu_phys_m2_smu_phys_pa_sturbulence_intensityrms_velocitystrain_diag_1_sstrain_shear_1_swss_proxy_pa
wss_proxy_pa is an approximate voxel-gradient wall-shear proxy on fluid cells adjacent to wall cells. It is not an exact stress projected onto the original STL surface.
Compute inlet/outlet flows and LPA/RPA split from VTK files:
python3 postprocess/compute_flows.py 'results_v1_sx/vtk3D/data_*.vtk' --output results_v1_sx/flows.csvDefault label names are:
3:IVC4:SVC5:RPA6:LPA
Override if visual inspection of the generated geometry shows the pulmonary labels are swapped:
python3 postprocess/compute_flows.py 'results_v1_sx/vtk3D/data_*.vtk' \
--labels 3:IVC,4:SVC,5:LPA,6:RPA \
--output results_v1_sx/flows.csv- Newtonian TCPC geometry/flow setup:
2026_02_20-simulationSetup - Non-Newtonian Carreau-Yasuda LBM implementation:
2026_02_29-nonNew - Historical flow postprocessing reference:
2026_03_18-zpracFlows