Skip to content

About

Shape optimization with neural implicit geometry representation.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

DeepShapeOpt

DOI

Shape optimization with neural implicit geometry and adjoint CFD sensitivities. A design is a DeepSDF latent lattice (or a free-form deformation) inside a design box; every iteration the body-fitted hex mesh is generated directly from the signed distance field, OpenFOAM's continuous adjoint or DAFoam's discrete adjoint returns the wall sensitivities, and the method of moving asymptotes (MMA) takes a step under CFD and geometric constraints.

Installation and machine setup: INSTALL.md.

One driver, one config

uv run deepshapeopt optimize --config experiments/drag_cube/config_latent_cube.json

The config sections mirror the building blocks of a run:

Section Block Options
run name, device, iterations, debug, heavy-data and scratch directories
geometry input mesh, length unit, design domain, flow type internal / external
parametrization design variables deepsdf (latent lattice, optional PCA reduction), ffd; locked control points
mesh the sdf_hex mesher: octree castellation and differentiable snap onto the SDF caps, patches, refinement
solver forward solver and adjoint openfoam (continuous, ESI), dafoam (discrete)
objective CFD metric plus penalties drag, uniformity, uniformity_directional, losses; proximity, lattice smoothness
constraints MMA rows with budgets CFD metric, volume, centroid, FFD fold-over guard, undercut, minimum steg length, no thinning in a painted region
optimizer MMA settings move limit, bounds, GCMMA inner loop, feasibility restoration, step control, convergence stop
diagnostics run mode and exports optimize, noise_probe, jacobian_probe; VTK / STL series

The no_thinning constraint protects a region in which the start design may only gain solid. The region is a 2-D mask extruded along one axis, painted on a projection of the start design:

uv run deepshapeopt paint-mask --config <config>.json --out data/masks/<name>.json

A new --out starts from an empty mask and an existing one is loaded for editing; the start design comes from the run's rec_parameters.pt (or --params-file), and --axis, --device and --port set the extrusion axis, the device and the server port. The painter serves on http://127.0.0.1:8001. Under Mirror, the two in-plane axes can be mirrored at planes through the lattice-box centre (the planes of parametrization.deepsdf.symmetry; the axes listed there are checked at start). The brush and eraser then act on every mirror image, the active planes are drawn as dashed lines with a ghost cursor on each image, Symmetrize mask adds the mirror image of the current mask, and the panel counts the pixels without a mirror partner. The symmetry is stored in the painted pixels, so the mask file and the constraint are unchanged. Paint on solid only (key S, on by default) lets the brush set only pixels that are solid in the start design. That means solid in at least one section along the axis, or at least the min. solid share of the sections; within the extrusion range once both ends are set. Clip mask to solid removes painted pixels that fail that test, and the panel counts pixels on fluid (drawn hatched); for no_thinning such pixels do nothing.

Older configs (two blocks reconstruction / optimization) convert with uv run deepshapeopt migrate-config --write <config>.

Exporting the full geometry

The result of a run exports as one watertight STL of the full geometry: the input geometry (geometry.mesh_path, or mesh.sdf_hex.geometry_stl) with the optimized design in the design domain. A half model (a domain face with patch_types symmetry / symmetryPlane) is mirrored, so the STL is always the full body:

uv run deepshapeopt export-stl --config <config>.json [--params <file>.pt] [--part full|design] \
    [--out <file>.stl] [--resolution 256] [--blend <width>] [--device cpu]
option default meaning
--params <run.name>/optimization/parameters.pt parameter file; any saved design works, e.g. reconstruction/rec_parameters.pt for the reconstructed start design
--part full full: the closed full geometry; design: only the surface inside the design domain (the half the mesh keeps, not mirrored), cut exactly at the design-domain faces: the counterpart of the run's current_shape.stl, meshed like the full geometry
--out optimized_<part>.stl next to the parameter file STL to write, in the geometry unit (no unit_to_metre scaling)
--resolution 256 marching-cubes cells along the longest design-domain side (DeepSDF, spline SDF)
--blend 4 % of the longest design-domain side width of the transition into the input geometry at the design-domain faces it passes through; 0 switches it off
--device run.device device for the design SDF evaluation

parameters.pt is written after the last optimizer step, i.e. one step past the last design the solver evaluated. Results in the old v1 layout (<run.name>/*/optimization/updated_parameters.pt) are found as well.

How the geometry is assembled:

  • DeepSDF and spline SDF. The design SDF is sampled on a uniform grid two cells beyond the design domain and meshed with marching cubes; an exact boolean (manifold3d) cuts the piece at the design domain and joins it with the input STL outside, which stays untouched. Towards every design-domain face that the input passes through, the design SDF is blended into the exact signed distance of the input (smoothstep over --blend), so the piece meets the input without a step: the reconstruction error at the locked faces is absorbed within the band instead of leaving a seam. The log reports that step per face and warns when the design departs from the input by more than a quarter of the band there (a face that is not locked); the blend then reshapes the design near that face. The mesh inside the design domain is finer and smoother than the triangulation of the input STL, so the change of tessellation at the faces stays visible in shading.
  • FFD. The input STL is deformed directly (the vertices inside the design domain and their mirror images), so the result keeps its triangulation and needs no remeshing or blending.
  • Symmetry. If the input extends across the symmetry plane, only the design is mirrored and replaces the input on the other side as well; if the input ends at the plane, the assembled body is mirrored and stitched at the plane.

The log closes with the number of triangles and bodies, the volume and the bounds, and warns if the result is not a single closed body.

Repository layout

deepshapeopt/
  driver.py, problem.py, cli.py     the optimization loop, its assembly from a config, the command line
  config/                           schema v2, loader, run paths, v1 migration
  geometry/                         domain frame, lattice reconstruction, reconstruction analysis, projected masks
  parametrization/                  DeepSDF lattice, PCA basis, FFD, locked control points, design space
  hexmesh/                          sdf_hex: octree, snap, polyMesh writer, caps and outlet sub-patches
  mesher.py                         MeshResult and the mesher wrapper the loop uses
  solvers/                          metric registry; openfoam/ (runtime, sensitivities, export); dafoam/ (runner, in-container script)
  terms/                            objective, penalties and constraint rows (CFD, volume, centroid, FFD jacobian, undercut, steg length, no thinning)
  optimizer/                        MMA wrapper (DeepSDFStruct.optimization.MMA), step control, convergence stop
  diagnostics/                      history CSV, plots, exports, probes, path consistency, noise estimate, latent metric
  latent_gui/                       web editor for the latent codes of a saved design
  mask_painter/                     brush editor for the protected region of the no_thinning constraint
openfoam/                           OpenFOAM user libraries (directional uniformity objective, powerLaw-Arrhenius material model)
external/dafoam_patches/            DAFoam patch (fvMatrix preconditioner) and its build notes
experiments/                        drag_cube/ (external flow), channel/ (internal flow), reconstruction/ (rim, shiba, propeller, channel)
tests/                              pytest (CPU only) and tests/smoke/ end-to-end configs
scripts/                            optimize.py, reconstruct.py, latent_gui.py (thin wrappers around the CLI), publish_dafoam_build.sh
slurm/                              generic SLURM template, config as argument

Experiments

  • experiments/drag_cube/: drag of a cube-like body (DeepSDF lattice with and without PCA, FFD, OpenFOAM and DAFoam), the case template foam_case/ and dafoam_case/.
  • experiments/channel/: internal flow through a branching channel, outlet velocity uniformity under a pressure-loss constraint (DeepSDF lattice and FFD).
  • experiments/reconstruction/: DeepSDF reconstructions of public geometries (rim, shiba, ship propeller from Thingiverse, and the channel).

Each run writes <experiment>/<run.name>/{reconstruction,optimization}/ with current_shape.stl, parameters.pt, optimization_history.csv, plots and run.log; with run.debug the VTK / STL series go to run.heavy_data_dir. Iteration numbering starts at 0.

Paper

The results of the companion paper (citation to follow) were produced with the archived snapshots DeepShapeOpt 10.5281/zenodo.20210465 and DeepSDFStruct 10.5281/zenodo.20210456 (concept DOIs 10.5281/zenodo.20210464 and 10.5281/zenodo.20205817). Those snapshots contain the snappyHexMesh path used for the paper runs, which this version replaced by the SDF hex mesher. Training data for the decoder: 10.48436/12y18-j6236 (only needed to retrain).

Citation

Cite the archived release (DeepShapeOpt v0.1.0, https://doi.org/10.5281/zenodo.20210464); a machine-readable citation is in CITATION.cff.

Reconstruction geometries: My little shiba by layerone (thing:1308678), Parametric Ship Propeller by Fysik_klubben (thing:6906448), RC Rim by Attila_d (thing:1328760), all Thingiverse.

License

See LICENSE.

About

Shape optimization with neural implicit geometry representation.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages