AI-генеративний дизайн продуктів
Генеративний дизайн застосовує AI для створення оптимальних форм виробів із заданими фізичними обмеженнями: максимальна міцність при мінімальній вазі, аеродинаміка, тепловідвід. Використовується в авіації, автопромі, медичних імплантатах, архітектурі.
Топологічна оптимізація з 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) метод.
Класичний алгоритм генеративного дизайну.
"""
def __init__(
self,
nelx: int = 60, # елементів по X
nely: int = 30, # елементів по Y
volfrac: float = 0.5, # цільова доля матеріалу (50%)
penal: float = 3.0, # ступінь штрафу
rmin: float = 1.5 # радіус фільтра
):
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=фіксовано
max_iterations: int = 100
) -> np.ndarray:
"""Повертає матрицю щільностей (0=пусто, 1=матеріал)"""
# Ініціалізація
x = np.full((self.nely, self.nelx), self.volfrac)
xold = x.copy()
for iteration in range(max_iterations):
# Аналіз методом скінченних елементів
U = self._finite_element_analysis(x, load_case, boundary_conditions)
# Аналіз чутливості
dc = self._sensitivity_analysis(x, U)
# Фільтрація чутливостей
dc = self._filter_sensitivity(x, dc)
# Оновлення через OC (Optimality Criteria)
x = self._oc_update(x, dc)
# Конвергенція
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"Збіжність на ітерації {iteration+1}")
break
return x
def _oc_update(self, x: np.ndarray, dc: np.ndarray) -> np.ndarray:
"""Оновлення за критеріями оптимальності"""
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
Нейросетевий генеративний дизайн
import torch
import torch.nn as nn
class DesignGeneratorVAE(nn.Module):
"""
Варіаційний автокодер для генерування нових дизайнів
за заданими фізичними вимогами.
"""
def __init__(self, latent_dim: int = 64, design_resolution: int = 64):
super().__init__()
self.latent_dim = latent_dim
res = design_resolution
# Енкодер: дизайн → латентний вектор
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)
# Умовний вектор: фізичні обмеження
self.condition_proj = nn.Linear(16, latent_dim)
# Декодер: латентний вектор + умова → дизайн
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: тензор фізичних обмежень (навантаження, граничні умови)
Повертає матрицю щільностей 64×64 для кожного зразка
"""
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 (через 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:
"""Конвертуємо матрицю щільностей в 3D mesh через marching cubes"""
from skimage.measure import marching_cubes
# 2D → 3D екструзія для демонстрації
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)
Застосування
| Область | Задача | Обмеження | Мета |
|---|---|---|---|
| Авіація | Кронштейн | Навантаження на зсув | -40% ваги |
| Медицина | Костний імплант | Біомеханічні навантаження | Пористість для остеоінтеграції |
| Авто | Амортизаційна скоба | Ударні навантаження | -30% матеріалу |
| Архітектура | Несучі колони | Вітрові + снігові навантаження | Мінімальний матеріал |
Терміни: SIMP топологічна оптимізація для 2D задач — 1–2 тижні. VAE-генератор з навчанням на датасеті оптимізованих форм — 4–6 тижнів.







