Source-pinned build for the OpenFOAM solver image behind the
EngiBench MTO2D problem.
This repository exists so EngiBench can consume a published image by digest, the
same way it consumes mdolab/public for Airfoil and
quay.io/dolfinadjoint/pyadjoint for the heat-conduction problems. EngiBench
itself carries no image build recipe.
Published as ghcr.io/ideallab/engibench-mto2d.
Nothing here is needed to run MTO2D. EngiBench pins the image digest in
MTO2D.container_id and pulls it automatically:
from engibench.problems.mto2d import MTO2D
problem = MTO2D()
design, _ = problem.random_design()
objectives = problem.simulate(design)The image exports a pristine writable case through mto2d-export-case;
EngiBench's model/runner.py uses that protocol automatically.
./build_source_image.sh engibench-mto2d:source-local
docker run --rm --platform linux/amd64 engibench-mto2d:source-local mto2d-source-smokeThe build takes no arguments and requires no private repository. It compiles
OpenMPI, PETSc, OpenFOAM 5, swak4Foam and the MTO2D solver from the revisions
and hashes in source-pins.env, and takes hours. A native AMD64 builder is much
faster than ARM emulation. MTO2D_BUILD_JOBS controls parallelism (default 8);
MTO2D_BUILDX_CACHE_FROM / MTO2D_BUILDX_CACHE_TO configure BuildKit caches.
The image is linux/amd64 only.
The case is vendored in case/ as reviewable OpenFOAM text. It is the
warm-ready-2d.zip case from IDEALLab/MTO-Scripts
(sha256 f90546a3f647aec6e6f0cac7a38ca580c32e0b9b15ed5b459e865551cdcf1fb0, at
warm_start/2D/templates/) with build output removed: no compiled EXEC, no
wmake output, no generated histories or decomposed time directories, no editor
backups. The build refuses to proceed if any of those reappear.
case/src_TF/MMA.h is the lab's stale copy and is overwritten during
installation by the hash-verified upstream header.
MMA comes from its public upstream,
topopt/TopOpt_in_PETSc by Niels
Aage, pinned to 9e433c64a100cddcd695b3823bc3027f38240c52 — the last revision
before upstream reformatted the file. mma-warm-restart.patch adds the
configurable asymptotes, the raa0 subproblem parameter and
resetAsymptotes() that the MTO2D solver needs for warm restarts.
Applying that patch to the pinned revision reproduces the source previously
taken from the private MTO-Scripts checkout byte for byte, and the build
asserts both SHA-256 hashes, so the compiled solver is unchanged.
Upstream is LGPL-2.1, carried in a repository-level lesser.txt that GitHub
does not auto-detect. mma-LICENSE.lesser.txt is that text; the build installs
it to /opt/mto2d/licenses/MMA-LGPL-2.1.txt inside the image.
Unresolved: the image label
org.opencontainers.image.licensesisGPL-3.0-or-laterwhile the image also contains LGPL-2.1 code. Confirm the SPDX expression is correct before publishing.
The Publish workflow (workflow_dispatch) runs the build and publish path
with GITHUB_TOKEN and packages: write, which is the supported way to create
the package under the organization. Publishing requires confirming
redistribution rights and passing the numerical parity gate.
Locally:
./publish_source_image.sh --image engibench-mto2d:source-local \
--confirm-redistribution-rights \
--reference-dataset IDEALLab/mto_2d_v0 --confirm-reference --pushAfter publishing, update DEFAULT_CONTAINER_IMAGE in
engibench/problems/mto2d/v0.py in EngiBench with the new digest.
verify_source_reference.py re-evaluates train row 2010 of
IDEALLab/mto_2d_v0 at conditions (-0.074, 63.1, 0.61) and q=0.01, and
requires the scalar histories and final gamma bytes to match
source-reference-golden.json exactly. It imports EngiBench, so install that
first (pip install engibench).
The recipe is GPL-3.0-or-later, matching EngiBench. It builds and redistributes third-party components under their own licences, including OpenFOAM (GPL-3.0) and MMA (LGPL-2.1, see above).