Research · research/simulation-tools.md · Markdown

FOSS simulation and optimisation survey for cad-agent (J501 / AGX Orin enclosure)

Survey date: 2026-10-26. Licences were checked against each repo's LICENSE/COPYING file (GitHub API or GitLab API) unless marked otherwise. "Last commit" means the newest commit on the default branch at survey time. Docker tags come from the Docker Hub API on the same day.

Licence rule used throughout:

Existing exposure to flag: cad-agent already does import gmsh. Gmsh is GPL-2.0-or-later. Its exception covers combination with Netgen, METIS, OpenCASCADE and ParaView, but not with arbitrary MIT code (gmsh.info/LICENSE.txt, PyPI gmsh 4.15.2, "GPLv2+"). This is the same situation as foamlib below. Document gmsh as an optional dependency, or call it via its CLI.


1. 3D topology optimisation from Python

Candidate Licence (verified) Maintenance Install Fit
pyMOTO MIT (repo) v2.0.1, 2026-05-07; last commit 2026-06-02 (releases) pip install pymoto[fast] or conda install -c aatmdelissen pymoto (README) Best fit. Voxel VoxelDomain in 2D and 3D; density filter; robust (eroded/dilated) formulation for minimum length scale; OverhangFilter (Langelaar AM filter, example); OC, MMA and GCMMA; multigrid-preconditioned CG for 3D; stress constraints; thermal and thermo-mechanical modules (ex_showcase_thermal.py, ex_thermo_mech.py); WriteToVTI to dump the density field every iteration (io.py). Modules carry their own sensitivities, so non-design regions are just a mask or mapping on the design vector.
PyTopo3D MIT (repo) v0.3.0, 2026-06-16 (PyPI) pip install pytopo3d ([gpu] extra uses CuPy) Simple 3D SIMP on voxels, with "obstacle" (non-design) regions from JSON and optional GPU. The README mentions no overhang or robust filter. A good, small fallback or reference.
dl4to Apache-2.0 (repo) Last commit 2024-11-19; not on PyPI pip install git+https://github.com/dl4to/dl4to PyTorch voxel SIMP plus deep-learning research tooling. Stale.
FEniTop GPL-3.0 (repo) Last commit 2024-11-01; pinned to dolfinx 0.7.3 Manual on a FEniCSx env Works on unstructured tets with a PDE filter, OC/MMA and MPI. Stale and pinned to an old dolfinx. GPL, so it can only run as a separate process.
dolfinx (roll our own) LGPL-3.0 (repo) v0.11.0, 2026-06; active Docker dolfinx/dolfinx:v0.11.0 (hub) or conda-forge The right base if we later need tets and MPI scale. LGPL is fine to import.
jax-fem GPL-3.0 per the LICENSE file (repo). The PyPI classifier wrongly says BSD (PyPI). v0.0.12, 2026-06; active pip Differentiable FE on GPU (JAX), with topopt examples. GPL, so it can only run as a separate process.
TopOpt_in_PETSc Unclear. GitHub detects no licence; main.cc says "The authors reserves all rights" but the repo also ships lesser.txt (LGPL text) (repo) Last commit 2026-10-17 Build against PETSc + MPI Scales to very large structured grids in C++. Avoid until the licence is clarified.
beso (CalculiX) LGPL-3.0 (repo) Last commit 2025-04-03 Python scripts + CalculiX ≥2.17 + FreeCAD BESO on tets via CalculiX .inp files. Works, but it's file-driven and needs FreeCAD.
scikit-fem topopt example BSD-3 (repo) Active (12.0.2, 2026-06) Already installed None found: docs/examples ex01–ex56 contain no topology-optimisation example. We would have to write SIMP + MMA ourselves on top of our existing P2-tet FEA.
OpenFOAM adjoint (ESI) GPL-3 v2606 Docker (see §3) adjointOptimisationFoam has topologyOptimisation tutorials for fluid topology (tree). This could later shape vents and ducts; it's not for structure.
SU2 LGPL-2.1 v8.5.0 — Has a fea_topology test case (TestCases). Niche.

Recommendation: use pyMOTO (MIT, importable) as the structural and thermal topology engine on a voxel domain built from our CadQuery solids:

2. Parametric shape/size optimisation drivers (expensive, multi-objective)

Candidate Licence Latest Notes
Optuna MIT (repo) v5.0.0, 2026-09-07 (release notes) v5 made GPSampler stable, with qLogEHVI / qLogCEHVI: batch multi-objective Bayesian optimisation with constraints. TPE is now the default multi-objective sampler. A new core trial.set_constraint() API was added. Storage is RDB or Journal, so runs are resumable and parallel, and it includes Pareto plots.
pymoo Apache-2.0 (repo) 0.6.2, 2026-06-28 NSGA-II/III, MOEA/D, constraint handling, decision making. Better suited to cheap surrogates than to expensive CFD.
Ax / BoTorch MIT (Ax, BoTorch) Ax 1.3.1 (2026-06-09), BoTorch 0.18.1 (2026-06-08) The most capable Bayesian optimisation (qNEHVI, multi-fidelity), but heavier (PyTorch).
OpenMDAO Apache-2.0 (LICENSE.txt) 3.45.1, 2026-09-10 Gradient-based MDO framework. Worth it only once we have adjoint gradients, e.g. pyMOTO or DAFoam.
scipy.optimize BSD-3 (repo) — Single-objective local optimisers (SLSQP, COBYQA, differential_evolution). Fine for 1–3 parameter refinements.

Recommendation: use Optuna 5 + GPSampler as the outer driver over CadQuery parameters (wall thickness, rib count and height, vent area and position, infill). Run it with three objectives and a temperature constraint:

3. CFD + conjugate heat transfer

OpenFOAM: ESI/OpenCFD vs Foundation

ESI / OpenCFD (openfoam.com) Foundation (openfoam.org)
Licence GPL-3 (v2606 news) GPL-3 (COPYING)
Current v2606 (June 2026); source moved to gitlab.com/openfoam/core/openfoam v14, 14 Jul 2026 (download, OpenFOAM-14)
Steady CHT solver chtMultiRegionSimpleFoam (tutorial dir tutorials/heatTransfer/chtMultiRegionSimpleFoam) foamMultiRun with fluid + solid modules (e.g. circuitBoardCooling Allrun); single-region buoyant flow is foamRun -solver fluid
Closest tutorial cpuCabinet (tree): snappyHexMesh multi-region. Regions are domain0 (air), v_CPU (solid with 100 W scalarSemiImplicitSource on h) and v_fins (heatsink). The fan is an MRF zone (MRFProperties, ω = 209.44 rad/s). This is almost exactly our problem. circuitBoardCooling (baffles), heatExchanger (porous region + inter-region heat transfer), heatedDuct, hotWire (snappy) (tree)
Fan models fan cyclic-baffle jump BC with modes velocity / uniformVelocity / volumeFlowRate / nonDimensional (fanFvPatchField.H); fanPressure; swirlFanVelocity; fanMomentumSource fvOption: Δp(Q) fan curve applied in a cellZone (header); MRF; actuationDiskSource; explicitPorositySource fanPressureJump and fanPressure BCs (src); fvModels actuationDisk, radialActuationDisk, porosityForce, interRegionHeatTransfer, heatSource (src/fvModels); MRF (mixerVessel2DMRF)
Docker opencfd/openfoam-run:2606 (runtime only, 2026-06-23). opencfd/openfoam-default:2512 / latest has tutorials and source; no 2606 tag yet (run, default). Starter script: openfoam-docker. No official images after v11: the newest on Docker Hub is openfoam/openfoam11-paraview510, last updated 2024-06 (hub). v14 is shipped as Ubuntu apt packages (needs sudo) or source.

Other solvers

Candidate Licence (verified) Status CHT / fan fit
Elmer FEM GPL-2.0+; ElmerSolver library and some modules LGPL-2.1, most solver modules GPL (LICENSE.md, licence policy) release-26.2 (2026-04-28); active. Docker build repo ElmerCSC/elmerfem-docker Strong for conduction, thermal and multiphysics on gmsh tets. Fan-driven turbulent air needs more effort than OpenFOAM. A good solid-side thermal and thermo-mechanical solver.
SU2 LGPL-2.1 (LICENSE.md) v8.5.0 (2026-04-27) Has coupled_cht and solid_heat_conduction test cases (TestCases). Aero-oriented, with no snappy-style STL meshing. Not recommended here.
Code_Saturne GPL-2.0 (repo) v9.2.0; docker simvia/code_saturne:9.2.0 (2026-07-13) (hub) Industrial-grade finite-volume solver with CHT. Smaller ecosystem for STL → mesh. Second choice.
XLB (Autodesk) Apache-2.0 (LICENSE) v0.3.1 (2026-01-12); pip install "xlb[warp]" GPU LBM (Warp/JAX), differentiable. The README mentions no thermal/CHT, so it's isothermal airflow only.
lettuce MIT (repo) 0.3.0 (2026-10-06); pip install lettucecfd (the PyPI name lettuce is an unrelated package) PyTorch GPU LBM; no thermal in the README. Research grade.
OpenLB GPL-2.0 (LICENSE) 1.9r0 (2025-12-18) (download) C++ GPU LBM with thermal examples (examples/thermal: Rayleigh–Bénard, porous plate) and a "Conjugate Heat Transfer" showcase listed on the site (not inspected). Works only as a separate process.
Palabos AGPL-3.0 (COPYING) Active (2026-07) Works only as a separate process. No advantage over OpenFOAM for our case.
FluidX3D Non-commercial licence — Rejected per the brief.
DAFoam GPL-3 (LICENSE.md) v5.1.1; docker dafoam/opt-packages:v5.1.1 Discrete adjoint of OpenFOAM + OpenMDAO. A future option for gradient-based vent shape optimisation.
CfdOF (FreeCAD) LGPL-3 (repo) Active A GUI case generator for snappy and cfMesh, porous regions, buoyant flow. The README shows no multi-region CHT. A useful reference for writing snappy dictionaries.

Python case-generation helpers

None of the good options is permissive. Recommendation:

ESI OpenFOAM v2606 in Docker (opencfd/openfoam-run:2606; use openfoam-default:2512 for tutorials), chtMultiRegionSimpleFoam, starting from cpuCabinet. Rationale:

Pipeline:

  1. CadQuery exports one STL per region: fluid = enclosure interior minus solids; solids = TTP/module block with a volumetric heat source, heatsink fins + base, and heatpipes as high-k solids; optionally the PLA walls as a solid region so wall temperature is resolved.
  2. blockMesh → surfaceFeatureExtract → snappyHexMesh → splitMeshRegions -cellZones → decomposePar -allRegions → mpirun -np 24 chtMultiRegionSimpleFoam -parallel. This is the cpuCabinet Allrun / Allrun.pre sequence.
  3. Model heatpipes as anisotropic or effective high-conductivity solids. This is my engineering assumption and needs calibration; no source verified.
  4. Run time for 2–5 M cells on 24 cores is unmeasured; plan on hours, not minutes.

Fast low-fidelity path for optimisation loops

4. Post-processing, visualisation, animation

Recommendation:

5. Slicer CLIs for real grams and print time

All three slicers are AGPL-3.0, so we call them as subprocesses only (BambuStudio, OrcaSlicer, PrusaSlicer). Latest: Bambu Studio GitHub release v02.08.02.61; the installed snap is 02.08.04.57 (beta channel). OrcaSlicer v2.4.2. PrusaSlicer 2.9.6.

Bambu Studio (tested here, headless, works)

The working invocation:

bambu-studio --slice 0 --arrange 1 --orient 0 \
  --load-settings "machine.json;process.json" \
  --load-filaments "filament.json" \
  --outputdir OUT --export-3mf out.3mf  model.stl   # or a .3mf project

OrcaSlicer

It's the same CLI lineage: orca-slicer --slice 0 --load-settings "machine.json;process.json" --load-filaments f.json --outputdir OUT --export-3mf out.3mf model.stl. Flags use hyphens, --slice 0 means all plates, and the machine file comes before the process file (Orca wiki CLI, actions; third-party reference printago). Install via the AppImage or flatpak (no sudo). Not tested here.

PrusaSlicer

From the source option table (PrintConfig.cpp):

Recommendation: use the installed Bambu Studio snap as the ground truth for filament grams and print time, with flattened P1S profiles cached in the repo. Use OrcaSlicer as a cross-check.

6. Thermal reference data

Jetson AGX Orin module. Sources: datasheet DS-10662-001 v1.8, Sep 2025, mirror and Jetson Linux r36.4 power/thermal page.

Seeed J501 cooler. The reference cooler in the repo README is Seeed p-5970. The page publishes no numeric specs and it 403s to scripts. Seeed hosts a vendor datasheet under the J501 wiki (WS-RDN-601, 100×87×34 mm); the repo has a saved copy:

Printed-material limits (Bambu TDS; third-party-hosted copies; values read with pdftotext):

Material Tg (DSC) HDT 0.45 MPa HDT 1.8 MPa Source
PLA Basic (TDS V2.0) 60 °C 57 °C 54 °C TDS
PETG Basic (V2.0) 68 °C 69 °C 65 °C TDS
PETG HF (V1.0) 66 °C 69 °C 62 °C TDS

With the TTP allowed up to 80 °C and the fan exhausting warm air, PLA within a few cm of the heatsink, the exhaust path or the cooler clamp is marginal. Use PETG (or better) for parts that carry the cooler, and treat ~50 °C PLA / ~60 °C PETG sustained wall temperature under load as design limits. Those limits are my margin choice, not a datasheet value. Creep under clamp load is a separate, unmodelled risk.

Existing projects combining CAD + TO + CFD for 3D printing

There is no single mature FOSS project that does CadQuery → topology optimisation → CHT CFD → slicer. The closest building blocks:

Reuse the ESI cpuCabinet case, pyMOTO examples and Optuna as templates, rather than adopting a framework.

Could not verify