I’m trying to use dolfin-adjoint to, for now, design a force inverter compliant mechanism as a stepping stone to get to more complex topology optimizations. I’ve gotten it working with specifying a fixed region, an input load, and an output objective region to maximize the displacement of the objective region, basically this:
Now I’m trying to vary the fixed locations from just being on the corners to being anywhere within the mesh, so I’m trying to add the x and y coordinates of the fixed locations as controls, but I’m getting an error (I believe) since dolfin-adjoint isn’t establishing a link between the scalar controls and the model as a whole.
My basic setup is that the forward_linear which computes the displacements of the mesh (which works when there is no x or y control) gets passed the density distribution (the part that is optimizing correctly), the fixed x, the fixed y, and the boundary conditions. It then uses those fixed x and fixed y to call another method which remarks the domains to update the fixed regions.
I’ve looked at this thread and it seems like I’m supposed to define a derivative based on the controls, but I’m not exactly sure how to do that in the force inverter problem.
I made a simpler optimization which has a similar structure to and the same error as the force inverter optimization I’m trying to get working. It’s basically just a mesh where the forward_linear is given a scalar radius and it returns the number of nodes that are within that radius of (0,0). The optimization is to get the best radius for selecting 100 nodes. Obviously I could define a derivative for this simpler example, but I don’t know how to do that for the compliant mechanism optimization.
This is the error I’m getting:
File "compliant_example.py", line 35, in <module> solver = IPOPTSolver(MinimizationProblem(Jhat, bounds = (0.0,1.0))) ... AttributeError: 'NoneType' object has no attribute 'value_size'
For this code:
import numpy as np from dolfin import * from dolfin_adjoint import * class GetCircularRegion(SubDomain): def __init__(self, radius): super().__init__() self.radius = float(radius) def inside(self, x, on_boundary): return between(x ** 2.0 + x ** 2.0, (0.0,radius ** 2.0)) mesh = RectangleMesh(Point(-5.0,-5.0),Point(5.0,5.0), 40, 40, 'crossed') dx = Measure('dx', domain=mesh) def markRegion(radius): region = GetCircularRegion(radius) domains = MeshFunction("size_t", mesh, 2) region.mark(domains, 1) return domains # Count number of nodes within the radius def forward_linear(radius): domains = markRegion(radius) data = domains.array() return float(np.count_nonzero(data)) # Find optimal radius to select 100 nodes if __name__ == "__main__": # Initial Guess radius = Constant(3.0) u = forward_linear(radius) # Minimize integral of (# selected nodes - 100) => minimize (# selected nodes - 100) J = assemble(np.abs(u - 100.0) * dx) Jhat = ReducedFunctional(J, Control(radius)) solver = IPOPTSolver(MinimizationProblem(Jhat, bounds=(0.0,10.0))) r_opt = solver.solve() print(r_opt)
The NoneType error is coming from how Control(radius).value() is None, but I don’t know how to get it to not be that. How should I approach this problem?