AI Generative Design of Products
Generative design applies AI to create optimal shapes of products with specified physical constraints: maximum strength with minimum weight, aerodynamics, heat dissipation. Used in aviation, automotive, medical implants, architecture.
Topology Optimization with SIMP
import numpy as np
from scipy.sparse import lil_matrix
from scipy.sparse.linalg import spsolve
class TopologyOptimizer:
"""
SIMP (Solid Isotropic Material with Penalization) method.
Classic generative design algorithm.
"""
def __init__(
self,
nelx: int = 60, # elements along X
nely: int = 30, # elements along Y
volfrac: float = 0.5, # target material fraction (50%)
penal: float = 3.0, # penalty exponent
rmin: float = 1.5 # filter radius
):
self.nelx = nelx
self.nely = nely
self.volfrac = volfrac
self.penal = penal
self.rmin = rmin
def optimize(
self,
load_case: dict, # {node: (fx, fy), ...}
boundary_conditions: dict, # {node: (ux, uy), ...} — 0=fixed
max_iterations: int = 100
) -> np.ndarray:
"""Returns density matrix (0=empty, 1=material)"""
# Initialization
x = np.full((self.nely, self.nelx), self.volfrac)
xold = x.copy()
for iteration in range(max_iterations):
# Finite element analysis
U = self._finite_element_analysis(x, load_case, boundary_conditions)
# Sensitivity analysis
dc = self._sensitivity_analysis(x, U)
# Sensitivity filtering
dc = self._filter_sensitivity(x, dc)
# Update via OC (Optimality Criteria)
x = self._oc_update(x, dc)
# Convergence
change = np.max(np.abs(x - xold))
xold = x.copy()
print(f"Iter {iteration+1:3d}, Volume: {x.mean():.4f}, Change: {change:.4f}")
if change < 0.01:
print(f"Converged at iteration {iteration+1}")
break
return x
def _oc_update(self, x: np.ndarray, dc: np.ndarray) -> np.ndarray:
"""Optimality Criteria update"""
l1, l2 = 0, 1e9
move = 0.2
while (l2 - l1) / (l1 + l2) > 1e-3:
lmid = 0.5 * (l1 + l2)
xnew = np.maximum(
1e-3,
np.maximum(
x - move,
np.minimum(
1.0,
np.minimum(x + move, x * np.sqrt(-dc / lmid))
)
)
)
if xnew.mean() - self.volfrac > 0:
l1 = lmid
else:
l2 = lmid
return xnew
Neural Network Generative Design
import torch
import torch.nn as nn
class DesignGeneratorVAE(nn.Module):
"""
Variational Autoencoder for generating new designs
based on specified physical requirements.
"""
def __init__(self, latent_dim: int = 64, design_resolution: int = 64):
super().__init__()
self.latent_dim = latent_dim
res = design_resolution
# Encoder: design → latent vector
self.encoder = nn.Sequential(
nn.Conv2d(1, 32, 4, stride=2, padding=1), # res/2
nn.ReLU(),
nn.Conv2d(32, 64, 4, stride=2, padding=1), # res/4
nn.ReLU(),
nn.Conv2d(64, 128, 4, stride=2, padding=1), # res/8
nn.ReLU(),
nn.Flatten()
)
encoder_out_size = 128 * (res // 8) ** 2
self.fc_mu = nn.Linear(encoder_out_size, latent_dim)
self.fc_logvar = nn.Linear(encoder_out_size, latent_dim)
# Conditional vector: physical constraints
self.condition_proj = nn.Linear(16, latent_dim)
# Decoder: latent vector + condition → design
self.decoder_input = nn.Linear(latent_dim * 2, 128 * (res // 8) ** 2)
self.decoder = nn.Sequential(
nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),
nn.ReLU(),
nn.ConvTranspose2d(64, 32, 4, stride=2, padding=1),
nn.ReLU(),
nn.ConvTranspose2d(32, 1, 4, stride=2, padding=1),
nn.Sigmoid()
)
self.res = res
def generate(self, conditions: torch.Tensor, n_samples: int = 1) -> torch.Tensor:
"""
conditions: tensor of physical constraints (loads, boundary conditions)
Returns density matrix 64×64 for each sample
"""
with torch.no_grad():
z = torch.randn(n_samples, self.latent_dim)
c = self.condition_proj(conditions.expand(n_samples, -1))
zc = torch.cat([z, c], dim=1)
h = self.decoder_input(zc)
h = h.view(n_samples, 128, self.res // 8, self.res // 8)
return self.decoder(h)
CAD Integration (via Python-OCC)
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeSolid
from OCC.Core.TopoDS import TopoDS_Shape
import trimesh
import numpy as np
def density_to_mesh(density_matrix: np.ndarray, threshold: float = 0.5) -> trimesh.Trimesh:
"""Convert density matrix to 3D mesh via marching cubes"""
from skimage.measure import marching_cubes
# 2D → 3D extrusion for demonstration
density_3d = np.stack([density_matrix] * 10, axis=-1)
verts, faces, normals, _ = marching_cubes(
density_3d,
level=threshold,
spacing=(1.0, 1.0, 1.0)
)
mesh = trimesh.Trimesh(vertices=verts, faces=faces, vertex_normals=normals)
mesh = trimesh.smoothing.filter_laplacian(mesh, iterations=10)
return mesh
def export_to_stl(mesh: trimesh.Trimesh, output_path: str) -> None:
mesh.export(output_path)
Applications
| Field | Task | Constraints | Goal |
|---|---|---|---|
| Aviation | Bracket | Shear loads | -40% weight |
| Medicine | Bone implant | Biomechanical loads | Porosity for osseointegration |
| Auto | Damping bracket | Impact loads | -30% material |
| Architecture | Load-bearing columns | Wind + snow loads | Minimal material |
Timeline: SIMP topology optimization for 2D problems — 1–2 weeks. VAE generator trained on optimized shapes dataset — 4–6 weeks.







