OpenLSTO
This sub-module of TopOpt is a self-contained Julia translation of the level-set topology optimization method in OpenLSTO. It implements the 2D compliance-minimization workflow (with optional hole nucleation) and the 2D L-beam stress-minimization workflow, on its own mesh, fast marching, boundary discretization, and finite element solver.
Optimization drivers
TopOpt.OpenLSTO.compliance_minimization — Function
compliance_minimization(; nelx, nely, ...)Run the OpenLSTO level-set compliance-minimization loop on the cantilever problem (left edge fixed, downward point load at the midpoint of the right edge). Returns a LevelSetResult with the final level_set, boundary, study, sensitivities, and the per-iteration objectives and areas.
Keyword arguments:
nelx,nely: number of finite elements (and level-set cells) in x and y.E,nu,rho: material properties (Young's modulus, Poisson's ratio, density).holes: initial circular holes; defaults to the Swiss-cheese arrangement.move_limit,band_width,is_fixed_domain: level-set parameters.max_iterations,max_area,max_diff: stopping criteria.hole_nucleation: enable the hole-nucleation scheme (a port ofprojects/hole_creation);hole_cfl,hole_l_band, andnew_hole_area_limittune it.
Example (the OpenLSTO cantilever demo)
holes = [LevelSetHole(16, 14, 5), LevelSetHole(48, 14, 5), LevelSetHole(80, 14, 5), LevelSetHole(112, 14, 5), LevelSetHole(144, 14, 5), LevelSetHole(32, 27, 5), LevelSetHole(64, 27, 5), LevelSetHole(96, 27, 5), LevelSetHole(128, 27, 5), LevelSetHole(16, 40, 5), LevelSetHole(48, 40, 5), LevelSetHole(80, 40, 5), LevelSetHole(112, 40, 5), LevelSetHole(144, 40, 5), LevelSetHole(32, 53, 5), LevelSetHole(64, 53, 5), LevelSetHole(96, 53, 5), LevelSetHole(128, 53, 5), LevelSetHole(16, 66, 5), LevelSetHole(48, 66, 5), LevelSetHole(80, 66, 5), LevelSetHole(112, 66, 5), LevelSetHole(144, 66, 5)] result = compliance_minimization(; nelx=160, nely=80, holes)
TopOpt.OpenLSTO.stress_minimization — Function
stress_minimization(; nelx, nely, ...)Run the OpenLSTO level-set stress-minimization loop on the L-beam problem (top edge fixed, downward point load on the right edge at 2/5 height). The objective is the p-norm of the von Mises stress; the sensitivities use the adjoint method (compute_stress_sensitivities!). Returns a LevelSetResult whose objectives field holds the per-iteration p-norm stress.
Keyword arguments:
nelx,nely: number of finite elements (and level-set cells) in x and y.E,nu,rho: material properties.holes: initial circular holes; defaults to the five-hole L-beam seeding.move_limit,band_width: level-set parameters.max_iterations,max_area,max_diff,p_norm,reduced_move_limit: stopping and optimization parameters.
TopOpt.OpenLSTO.compliance_minimization_3d — Function
compliance_minimization_3d(; nelx, nely, nelz, ...)Run the OpenLSTO 3D level-set compliance-minimization loop on a cantilever (left face fixed, downward line load on the bottom edge of the right face). Returns a NamedTuple with the final level_set (LevelSet3D), the HexStudy, the boundary conditions, and the per-iteration compliances and volume-fraction areas.
Like the upstream projects/3d/comp_min.cpp, only the load region is pinned solid by default (pin_support=:none). To also keep material on the left-face supports — which the optimizer can otherwise erode onto void — pass pin_support=:soft (a large support sensitivity, analogous to the load pin) or pin_support=:hard (clamp the signed distance on the support face so the contour cannot recede past it).
TopOpt.OpenLSTO.LevelSetResult — Type
LevelSetResultThe result of compliance_minimization or stress_minimization. Holds the final level set, its discretized boundary, the finite element study and sensitivities, the per-iteration objective and area-fraction histories, and the problem's boundary conditions.
Fields:
level_set: the finalLevelSet(signed distance on the grid).boundary: the finalLevelSetBoundarydiscretization.study: theStationaryStudyholding the last FEA solve.sensitivities: theSensitivityAnalysisfrom the last iteration.boundary_conditions: theLevelSetBoundaryConditions(loads and supports) of the problem.objectives: per-iteration objective (compliance or p-norm stress) values.areas: per-iteration volume-fraction values.
TopOpt.OpenLSTO.LevelSetBoundaryConditions — Type
LevelSetBoundaryConditionsThe load and support (Dirichlet) specification of a level-set problem, carried by LevelSetResult so visualize can draw the load and support arrows without reconstructing them from the finite element vectors.
Fields:
loads:(node, load vector)pairs, one per applied load.supports:(component, node indices)pairs, one per constrained direction.
TopOpt.OpenLSTO.area_fractions — Function
area_fractions(result::LevelSetResult)Re-discretize the final level set and return the per-cell material area fraction, i.e. the density field of the optimized design. The vector has one entry per cell, ordered row-major (x fastest) to match the finite element mesh of result.study.
Level-set representation
TopOpt.OpenLSTO.LevelSetMesh — Type
LevelSetMesh(width, height)The level-set fixed grid: a width × height array of unit-square cells with one node per grid point, used to represent the signed-distance function. Node coordinates are (x, y) with x ∈ 0:width, y ∈ 0:height. LevelSetMesh is the level-set counterpart of the Ferrite grids used by the rest of TopOpt.jl.
TopOpt.OpenLSTO.LevelSet — Type
LevelSet(mesh; move_limit=0.5, band_width=6, is_fixed=false)
LevelSet(mesh, holes; move_limit=0.5, band_width=6, is_fixed=false)A signed-distance level set on a LevelSetMesh. Positive values are inside the structure, negative outside. The zero contour is advanced by a normal velocity extended from the boundary points, reinitialized by the fast marching method. holes seeds the initial configuration (default: the "Swiss cheese" arrangement of circular holes).
TopOpt.OpenLSTO.LevelSetHole — Type
LevelSetHole(x, y, r)A circular hole used to seed the initial level-set configuration: the region inside the circle (distance to the centre less than r) is material-free.
TopOpt.OpenLSTO.LevelSetBoundary — Type
LevelSetBoundary(level_set)The discretized boundary of a LevelSet. discretise! finds the boundary points where the zero contour crosses grid edges (marching squares) and compute_area_fractions! computes the material area fraction of every cell.
Fast marching and optimization
TopOpt.OpenLSTO.FastMarchingMethod — Type
FastMarchingMethod(mesh)Solves the Eikonal equation by the fast marching method to reinitialise a signed-distance function or to extend boundary velocities through the narrow band. A port of M2DO_LSM/src/fast_marching_method.cpp, adapted from Scikit-FMM. Use march! to run it.
TopOpt.OpenLSTO.Heap — Type
Heap(max_length)A binary min-heap used as the priority queue of the FastMarchingMethod. It stores (address, distance) pairs and is a faithful port of OpenLSTO's M2DO_LSM/src/heap.cpp, itself adapted from Scikit-FMM.
TopOpt.OpenLSTO.MersenneTwister — Type
MersenneTwister()A Mersenne-Twister random number generator. rng() draws a uniform value in [0, 1], integer draws a uniform integer, and normal draws a normal deviate. Seeded from the system entropy source unless set_seed! is called first.
TopOpt.OpenLSTO.integer — Function
integer(rng::MersenneTwister, min, max)Draw a uniform random integer in min:max (inclusive).
TopOpt.OpenLSTO.normal — Function
normal(rng::MersenneTwister)
normal(rng::MersenneTwister, mean, std_dev)Draw a normally distributed random number with zero mean and unit standard deviation (or the given mean and std_dev).
TopOpt.OpenLSTO.get_seed — Function
get_seed(rng::MersenneTwister)Return the generator seed.
TopOpt.OpenLSTO.set_seed! — Function
set_seed!(rng::MersenneTwister, seed)Reseed the generator.
TopOpt.OpenLSTO.LevelSetOptimizer — Type
LevelSetOptimizer(boundary_points, move_limit)Solves for the boundary-point velocities that advance the level set while satisfying the volume constraint. Uses a Newton-Raphson iteration on the Lagrange multiplier (a port of M2DO_LSM/src/optimise.cpp).
Finite element analysis
TopOpt.OpenLSTO.FEMesh — Type
FEMesh(nelx, nely)The structured nelx × nely finite element mesh (unit-square Q4 cells) used for the level-set compliance solve. Independent of the level-set LevelSetMesh but with matching cell ordering.
TopOpt.OpenLSTO.SolidMaterial — Type
SolidMaterial(E, ν, ρ; h=1.0)Plane-stress material with Young's modulus E, Poisson's ratio ν, density ρ, and thickness h. Stores the 4×4 constitutive matrix C and the 4×4 Voigt matrix V used for von Mises stress (σᵀ V σ = σ_vm² in the strain ordering of C).
TopOpt.OpenLSTO.SolidElement — Type
SolidElementA single 4-node (Q4) plane-stress finite element: its node indices, global dofs, material area fraction, and centroid.
TopOpt.OpenLSTO.StationaryStudy — Type
StationaryStudy(mesh, material, fixed_dofs)A linear static study K u = f for the level-set FEA: assembles the area-fraction-weighted stiffness matrix and solves it with a conjugate gradient method. Holds K, f, and the solution u.
TopOpt.OpenLSTO.SensitivityAnalysis — Type
SensitivityAnalysis(study)Computes the compliance or stress shape sensitivity at each Gauss point. The sensitivities are interpolated to the boundary points by weighted least squares (compute_boundary_sensitivity).
TopOpt.OpenLSTO.HexMaterial — Type
HexMaterial(E, ν, ρ)Isotropic 3D material with Young's modulus E, Poisson's ratio ν, and density ρ. Stores the 6x6 Voigt constitutive matrix C.
TopOpt.OpenLSTO.HexStudy — Type
HexStudy(nelx, nely, nz, material, fixed_dofs)A structured nelx x nely x nelz hex mesh with a K u = f stationary study, assembled with element area fractions and solved by conjugate gradient.
3D level-set method
TopOpt.OpenLSTO.LevelSet3D — Type
LevelSet3D(nx, ny, nz)A signed-distance level set on a 3D structured grid of nx x ny x nz cells. Positive values are inside the structure. The zero surface is discretized with marching cubes and advected by boundary velocities.
TopOpt.OpenLSTO.write_stl — Function
write_stl(level_set, filename; box_smooth=1)Write the discretized zero surface of a LevelSet3D as an ASCII STL file.
Internal helpers
TopOpt.OpenLSTO.discretise! — Function
discretise!(boundary, size_lambdas)Discretize the zero contour of the level set into boundary points and segments with marching squares.
TopOpt.OpenLSTO.compute_area_fractions! — Function
compute_area_fractions!(boundary)Compute the material area fraction of every cell from the discretized boundary and return the total area.
TopOpt.OpenLSTO.march! — Function
march!(fmm, signedDistance)
march!(fmm, signedDistance, velocity)Run the fast marching method to reinitialize signedDistance to a signed distance function, or (with velocity) to extend boundary velocities through the narrow band without changing the signed distance.
TopOpt.OpenLSTO.compute_compliance_sensitivities! — Function
compute_compliance_sensitivities!(sens)Compute the compliance shape sensitivity at each Gauss point: the strain-energy density times the area fraction. Sets sens.objective to the compliance.
TopOpt.OpenLSTO.compute_stress_sensitivities! — Function
compute_stress_sensitivities!(sens, p_norm)Compute the p-norm von Mises stress objective (Σ (ρ_e σ_vm)^p)^(1/p) and its adjoint-based sensitivity at each Gauss point. Sets sens.objective and sens.von_mises_max.
TopOpt.OpenLSTO.compute_boundary_sensitivity — Function
compute_boundary_sensitivity(sens, boundary_point; radius, indicator, p_norm)Interpolate Gauss-point sensitivities to a boundary point by weighted least squares. indicator == 0 returns the compliance sensitivity; indicator == 1 combines the two stress sensitivity components into the p-norm stress sensitivity.
Input and output
TopOpt.OpenLSTO.save_level_set_vtk — Function
save_level_set_vtk(level_set, datapoint; is_velocity=false, is_gradient=false, output_directory="")
save_level_set_vtk(level_set, filename; is_velocity=false, is_gradient=false)Write the signed distance function of a LevelSet as a ParaView VTK rectilinear grid, optionally including the nodal velocity and gradient fields.
TopOpt.OpenLSTO.save_level_set_txt — Function
save_level_set_txt(level_set, datapoint; output_directory="", is_xy=false)
save_level_set_txt(level_set, filename; is_xy=false)Write the signed distance, velocity, and gradient of a LevelSet as plain text, optionally prefixed by the nodal x/y coordinates.
TopOpt.OpenLSTO.save_boundary_points_txt — Function
save_boundary_points_txt(boundary, datapoint; output_directory="")
save_boundary_points_txt(boundary, filename)Write the boundary points of a LevelSetBoundary (x, y, length) as plain text.
TopOpt.OpenLSTO.save_boundary_segments_txt — Function
save_boundary_segments_txt(boundary, datapoint; output_directory="")
save_boundary_segments_txt(boundary, filename)Write the boundary segments of a LevelSetBoundary (each as two coordinate pairs separated by a blank line) as plain text.
TopOpt.OpenLSTO.save_area_fractions_vtk — Function
save_area_fractions_vtk(mesh, datapoint; output_directory="")
save_area_fractions_vtk(mesh, filename)Write the element area fractions of a LevelSetMesh as a ParaView VTK rectilinear grid (cell data).
TopOpt.OpenLSTO.save_area_fractions_txt — Function
save_area_fractions_txt(mesh, datapoint; output_directory="", is_xy=false)
save_area_fractions_txt(mesh, filename; is_xy=false)Write the element area fractions of a LevelSetMesh as plain text, optionally prefixed by the element centre coordinates.
TopOpt.OpenLSTO.boundary_vtk — Function
boundary_vtk(filename, boundary_points, sensitivities, neighbors)Write boundary points and their sensitivity fields as a ParaView VTK unstructured grid of line segments. boundary_points is a vector of coordinates, sensitivities a vector of per-field point values, and neighbors the (start, end) index pairs of the segments.
TopOpt.OpenLSTO.write_optimisation_history_txt — Function
write_optimisation_history_txt(objectives, constraints)Write the optimisation history (Output/optimisation_history.txt): the objective and constraint values, one row per iteration.