"Shape optimization" is a common way to improve an existing design. At a high level, the workflow looks something like
That is, the mesh is the input to the analysis, and it is parameterized by its nodal coordinates
From there, the mesh is used as part of a simulation, usually involving a PDE of interest (elasticity, heat transfer, E&M, etc), to find the solution
But to make the design better, we don't actually need the value of the objective function, we want its derivative with respect the parameters we control (in this case, the nodes of the mesh). To do that, we proceed by reverse-mode differentiation, as indicated below.
This process starts by computing the gradient of our objective function w.r.t.
which is the quantity we were originally looking for. We can interpret
Depending on whether we're interested in maximizing or minimizing
Okay, okay-- shape optimization sounds great, but doesn't that lead to weird designs?
Yes.
This is less of an issue if you're planning to create the parts using a 3D printer, but it's a big problem if you intend to mass produce a part or realize the design through conventional machining. This is one of the main reasons that human-designed parts usually have shapes with simple features (e.g. flat surfaces, circular holes, symmetry planes, etc) -- those sorts of designs are way easier to manufacture and assemble.
So, what can we do to find more manufacturable designs?
One possible way to address this problem is to explicitly parameterize the design (or parts of it) in terms of quantities and dimensions that one would see in a standard dimensioned drawing (e.g. there is a hole of radius
We can express this explicitly-parameterized workflow in almost the same way as before, except now we have one more step at the beginning:
Now, the parameters are the input to the overall workflow, rather than the mesh. Those parameters are fed into a program which generates the mesh for the current design, and then the rest of the analysis continues as it did before.
This new mesh generation step also incurs another step right at the end of our reverse-mode differentiation process. Now we have one more vector-Jacobian product to evaluate:
What is
Differentiating through the mesh generation process directly would be nasty, but thankfully there's a simple alternative if the mesh is generated through a level-set function,
So
which is pretty easy to compute.
For example, here's a toy problem in 2D that parameterizes a "wrench" shape with 8 parameters. The red lines visualize the values of
The C++ code for the parameterized level set function used to generate these meshes is given below
xtemplate < std::size_t n >
double smooth_min(std::array< float, n > values, float r) {
double weighted_sum{};
for (auto x : values) {
weighted_sum += exp(-x / r);
}
return -r * log(weighted_sum);
}
float sdf_difference(float a, float b) {
return std::max(a, -b);
}
float level_set_function(vec2f x, std::array< float, 8 > p) {
auto [x1, r1, t1, x2, r2, t2, h, rho] = p;
Disk left_disk{{x1, 0.0f}, r1 + t1};
AABB handle{{x1, -0.5f * h}, {x2, 0.5f * h}};
Disk right_disk{{x2, 0.0f}, r2 + t2};
Disk left_hole{{x1, 0.0f}, r1};
AABB left_slot{{x1 - 1.5f * (r1 + t1), -r1}, {x1, r1}};
Disk right_hole{{x2, 0.0f}, r2};
float SDF1 = smooth_min(std::array{left_disk.SDF(x), handle.SDF(x), right_disk.SDF(x)}, rho);
float SDF2 = min(std::array{left_hole.SDF(x), left_slot.SDF(x), right_hole.SDF(x)});
return sdf_difference(SDF1, SDF2);
}
shape optimization is a useful tool for improving designs, but moving each node in the mesh independently can often lead to designs that are hard to build
parameterizing features explicitly can help to simplify the design and address the issue above
the explicit parameterization adds one more step to the shape optimization workflow, which also needs to be accounted for in the reverse-mode differentiation pass
for the case where meshes are generated from an implicit definition of the geometry, we have a simple approximation to the Jacobian of the mesh generation step, without having to actually differentiate through the mesh generation