DeepSDFStruct.optimization#
Structural Optimization Utilities#
This module provides tools for gradient-based optimization of SDF-based geometries, with a focus on structural design problems. It integrates with TorchFEM for finite element analysis and provides optimization algorithms suitable for constrained design problems.
Key Features#
- MMA Optimizer
Implementation of the Method of Moving Asymptotes (MMA), a gradient-based algorithm well-suited for structural optimization with nonlinear constraints. MMA is particularly effective for: - Topology optimization - Shape optimization with constraints - Problems with expensive objective evaluations - Highly nonlinear design spaces
- Finite Element Integration
Conversion between TorchFEM and PyVista mesh formats
Support for tetrahedral and hexahedral elements
Linear and quadratic element types
Integration with gradient computation
- Mesh Quality Utilities
Signed volume computation for tetrahedra
Mesh quality metrics
Degeneracy detection
The module is designed to work seamlessly with differentiable SDF representations, enabling gradient-based optimization of complex 3D structures.
Functions
|
Convert a TorchFEM Solid mesh to PyVista UnstructuredGrid. |
|
Compute signed volumes of tetrahedral elements. |
Classes
|
Method of Moving Asymptotes (MMA) optimizer for constrained problems. |
- class DeepSDFStruct.optimization.MMA(parameters, bounds, max_step=0.1)#
Bases:
objectMethod of Moving Asymptotes (MMA) optimizer for constrained problems.
MMA is a gradient-based optimization algorithm designed for nonlinear constrained problems. It constructs convex subproblems using moving asymptotes and is particularly effective for structural optimization.
The optimizer handles a single objective function and a single constraint, with box bounds on design variables. It automatically normalizes the objective by its initial value for better numerical behavior.
- Parameters:
parameters (torch.Tensor) – Initial design variables (will be optimized in-place).
bounds (array-like of shape (n, 2)) – Box constraints [[lower_1, upper_1], …, [lower_n, upper_n]] for each design variable.
max_step (float, default 0.1) – Maximum allowed change in design variables per iteration, as a fraction of the bound range.
- parameters#
Current design variables (updated in-place each iteration).
- Type:
torch.Tensor
- loop#
Current iteration number.
- Type:
int
- x#
Current design variables in numpy format.
- Type:
ndarray
- xold1, xold2
Design variables from previous two iterations (for MMA history).
- Type:
ndarray
- step(F, dF, G, dG)#
Perform one MMA optimization step given objective, constraint, and their gradients.
Notes
MMA was developed by Krister Svanberg and is widely used in topology optimization. It is particularly effective for problems where: - The objective and constraints are expensive to evaluate - Gradients are available (via automatic differentiation) - The design space is high-dimensional - Strong nonlinearity is present
The implementation uses the mmapy package for the core MMA algorithm.
Examples
>>> import torch >>> from DeepSDFStruct.optimization import MMA >>> >>> # Define design variables >>> params = torch.ones(10, requires_grad=True) >>> bounds = [[0.0, 2.0]] * 10 >>> >>> # Create optimizer >>> optimizer = MMA(params, bounds, max_step=0.1) >>> >>> # Optimization loop >>> for i in range(100): ... # Compute objective and constraint ... objective = (params ** 2).sum() ... constraint = params.sum() - 5.0 ... ... # Compute gradients ... dF = torch.autograd.grad(objective, params, create_graph=True)[0] ... dG = torch.autograd.grad(constraint, params, create_graph=True)[0] ... ... # MMA step ... optimizer.step(objective, dF, constraint, dG) ... ... if optimizer.ch < 1e-3: ... break
References
- step(F, dF, G, dG)#
Perform one MMA optimization step.
Updates design variables by solving a convex subproblem constructed from the objective, constraint, and their gradients.
- Parameters:
F (torch.Tensor or float) – Objective function value at current design.
dF (torch.Tensor) – Gradient of objective w.r.t. design variables, shape (n,).
G (torch.Tensor or float) – Constraint function value at current design (≤ 0 is feasible).
dG (torch.Tensor) – Gradient of constraint w.r.t. design variables, shape (n,).
Notes
The method automatically: - Normalizes the objective by its initial value - Enforces move limits based on max_step - Updates MMA history (xold1, xold2) - Computes and logs convergence metric (ch) - Updates self.parameters in-place
The convergence metric ch is the relative change in design variables.
- DeepSDFStruct.optimization.get_mesh_from_torchfem(Solid)#
Convert a TorchFEM Solid mesh to PyVista UnstructuredGrid.
This function enables visualization and export of TorchFEM finite element meshes using PyVista. It supports both tetrahedral and hexahedral elements with linear and quadratic shape functions.
- Parameters:
Solid (torchfem.Solid) – TorchFEM solid mesh object containing nodes, elements, and element type.
- Returns:
PyVista mesh representation suitable for visualization and I/O.
- Return type:
pyvista.UnstructuredGrid
- Raises:
NotImplementedError – If input is not a torchfem.Solid object.
Notes
Supported element types: - Tetra1: 4-node linear tetrahedron - Tetra2: 10-node quadratic tetrahedron - Hexa1: 8-node linear hexahedron - Hexa2: 20-node quadratic hexahedron
Examples
>>> from DeepSDFStruct.optimization import get_mesh_from_torchfem >>> import torchfem >>> >>> # Assume we have a TorchFEM solid mesh >>> # solid = torchfem.Solid(...) >>> >>> # Convert to PyVista for visualization >>> pv_mesh = get_mesh_from_torchfem(solid) >>> pv_mesh.plot()
- DeepSDFStruct.optimization.tet_signed_vol(vertices, tets)#
Compute signed volumes of tetrahedral elements.
Calculates the signed volume of each tetrahedron, which is positive for correctly oriented elements and negative for inverted elements. This is useful for detecting mesh degeneracies and enforcing mesh quality constraints.
- Parameters:
vertices (torch.Tensor) – Vertex coordinates of shape (N, 3).
tets (torch.Tensor) – Tetrahedral connectivity of shape (M, 4), where each row contains vertex indices [v0, v1, v2, v3].
- Returns:
Signed volumes of shape (M,), one per tetrahedron. Positive volumes indicate correctly oriented elements.
- Return type:
torch.Tensor
Notes
- The signed volume is computed as:
V = (1/6) * ((v1-v0) × (v2-v0)) · (v3-v0)
Examples
>>> import torch >>> from DeepSDFStruct.optimization import tet_signed_vol >>> >>> # Define a simple tetrahedron >>> vertices = torch.tensor([ ... [0.0, 0.0, 0.0], ... [1.0, 0.0, 0.0], ... [0.0, 1.0, 0.0], ... [0.0, 0.0, 1.0] ... ]) >>> tets = torch.tensor([[0, 1, 2, 3]]) >>> volumes = tet_signed_vol(vertices, tets) >>> print(f"Volume: {volumes[0]:.3f}") # Should be 1/6 ≈ 0.167