matto.design#
Design-variable parameterization as a chain of operators.
Every design variable is stored twice: a raw field that the optimizer controls and a physical field that enters the material model. The map between them is a composition of operators,
raw –T_1–> … –T_k–> phys,
and the sensitivity of anything with respect to raw is obtained by applying the adjoints in the opposite order,
dJ/draw = T_1^T … T_k^T dJ/dphys.
Each operator implements its forward map and its adjoint, and may carry a continuation schedule (the Heaviside sharpness, for instance). DesignVariable only walks the chain; nothing in it is specific to any operator.
- matto.design.volume_constraint(field, upper_bound, dx)[source]#
A volume constraint on a physical design field, as the dictionary build_constraints() returns: the field’s integral over the domain, normalized by the domain volume, no larger than upper_bound.
- class matto.design.Operator(input_field, output_field)[source]#
Bases:
ABCOne map in the parameterization chain, together with its adjoint.
An operator reads
self.inputand writesself.output. The two may be the same Function when the map acts in place.forward() must run before backward() within an iteration. Operators are free to cache the linearization at the current point during forward() and use it in backward().
Operators that can appear in an input file’s
operatorslist implement from_spec() and are listed in OPERATOR_TYPES.- classmethod from_spec(spec, input_field, output_field, context)[source]#
Build the operator from one entry of an input file’s operators list.
input_field is the field written by the previous operator (or the raw field). output_field is the variable’s phys field when this operator is last in the chain and None otherwise, in which case the operator allocates its own intermediate. context holds
name,index,comm,petsc_optionsandphysical_space.
- abstractmethod backward(gradients)[source]#
Apply the adjoint to a list of PETSc vectors living on the output side and return the corresponding list on the input side.
Entries may be None and are passed through untouched. The returned vectors may alias or overwrite the given ones, or be work vectors owned by the operator that stay valid only until its next backward() call. Callers that need to keep a result copy it.
- update(iteration)[source]#
Advance any continuation schedule at the start of an iteration.
Returns True when the operator changed, so the caller can avoid declaring convergence on a step where the map itself moved.
- property continuation_complete#
True once the continuation schedule, if any, has run out.
- class matto.design.Identity(input_field, output_field)[source]#
Bases:
OperatorCopy input to output. Used when a variable has no operators.
- backward(gradients)[source]#
Apply the adjoint to a list of PETSc vectors living on the output side and return the corresponding list on the input side.
Entries may be None and are passed through untouched. The returned vectors may alias or overwrite the given ones, or be work vectors owned by the operator that stay valid only until its next backward() call. Callers that need to keep a result copy it.
- class matto.design.HelmholtzKernel(comm, input_space, output_space, radius, petsc_options=None)[source]#
Bases:
objectThe matrices and solver of a Helmholtz filter for one space pair and radius.
Every design field filtered with the same spaces and radius on the same mesh can share one of these; the operators hold only their own bound fields. The work vectors are shared too, which is fine as the operators run one after another.
- class matto.design.HelmholtzFilter(kernel, input_field, output_field)[source]#
Bases:
OperatorPDE filter: -R^2 lap(phys) + phys = raw with natural boundary conditions.
The raw and filtered fields may live in different spaces. Written as a linear map phys = Kf^{-1} T raw, the adjoint is T^T Kf^{-1} since Kf is symmetric.
- classmethod from_spec(spec, input_field, output_field, context)[source]#
Build the operator from one entry of an input file’s operators list.
input_field is the field written by the previous operator (or the raw field). output_field is the variable’s phys field when this operator is last in the chain and None otherwise, in which case the operator allocates its own intermediate. context holds
name,index,comm,petsc_optionsandphysical_space.
- backward(gradients)[source]#
Apply the adjoint to a list of PETSc vectors living on the output side and return the corresponding list on the input side.
Entries may be None and are passed through untouched. The returned vectors may alias or overwrite the given ones, or be work vectors owned by the operator that stay valid only until its next backward() call. Callers that need to keep a result copy it.
- class matto.design.HeavisideProjection(input_field, output_field, beta, beta_max, update_interval, eta=0.5)[source]#
Bases:
OperatorSmoothed Heaviside projection about the threshold eta.
- phys = [tanh(beta eta) + tanh(beta (x - eta))]
/ [tanh(beta eta) + tanh(beta (1 - eta))],
with the sharpness beta doubled every
update_intervaliterations up tobeta_max. Acts pointwise, so input and output share a space and the adjoint is multiplication by dphys/dx at the current point.- classmethod from_spec(spec, input_field, output_field, context)[source]#
Build the operator from one entry of an input file’s operators list.
input_field is the field written by the previous operator (or the raw field). output_field is the variable’s phys field when this operator is last in the chain and None otherwise, in which case the operator allocates its own intermediate. context holds
name,index,comm,petsc_optionsandphysical_space.
- update(iteration)[source]#
Advance any continuation schedule at the start of an iteration.
Returns True when the operator changed, so the caller can avoid declaring convergence on a step where the map itself moved.
- property continuation_complete#
True once the continuation schedule, if any, has run out.
- backward(gradients)[source]#
Apply the adjoint to a list of PETSc vectors living on the output side and return the corresponding list on the input side.
Entries may be None and are passed through untouched. The returned vectors may alias or overwrite the given ones, or be work vectors owned by the operator that stay valid only until its next backward() call. Callers that need to keep a result copy it.
- matto.design.build_operator_chain(name, specs, raw, phys, comm, petsc_options, kernels=None)[source]#
Turn the
operatorslist of an input file into Operator objects.The chain is threaded from raw to phys: each operator reads the field the previous one wrote, and the last one writes phys. An operator that is not last allocates its own intermediate field, so raw is never overwritten.
kernels is a dict shared across the design variables of one problem so operators with the same matrices, such as a filter with the same spaces and radius, assemble them once.
- class matto.design.DesignVariable(name, settings, mesh, petsc_options=None, kernels=None)[source]#
Bases:
objectManage one optimization design variable.
- The class owns:
raw - the variable controlled by MMA phys - the variable after the operator chain
It walks the chain forward to update phys and backward to carry sensitivities from phys to raw.
- forward(iteration)[source]#
Map raw values to physical values.
Returns True when any operator advanced its continuation this iteration.