Source code for topopt.mechanisms.boundary_conditions

"""Boundary conditions for mechanism synthesis (forces and fixed nodes)."""

# Import standard library
import functools

# Import modules
import numpy

# Import TopOpt modules
from ..boundary_conditions import BoundaryConditions
from ..utils import xy_to_id


[docs]class MechanismSynthesisBoundaryConditions(BoundaryConditions): """Boundary conditions for compliant mechanism synthesis.""" @property def output_displacement_mask(self): """:obj:`numpy.ndarray`:Mask of the output displacement.""" pass
[docs]class DisplacementInverterBoundaryConditions( MechanismSynthesisBoundaryConditions): """Boundary conditions for a displacment inverter compliant mechanism.""" @property def fixed_nodes(self): """:obj:`numpy.ndarray`:Fixed bottom and top left corner nodes.""" # topx_to_id = numpy.vectorize( # lambda x: xy_to_id(x, 0, self.nelx, self.nely)) # topx = 2 * topx_to_id(numpy.arange(self.nelx + 1)) + 1 id1 = 2 * xy_to_id(0, 0, self.nelx, self.nely) id2 = 2 * xy_to_id(0, self.nely, self.nelx, self.nely) # fixed = numpy.union1d(topx, numpy.array([id2, id2 + 1])) fixed = numpy.array([id1, id1 + 1, id2, id2 + 1]) return fixed @property def forces(self): """:obj:`numpy.ndarray`:Middle left input force.""" f = numpy.zeros((self.ndof, 2)) # f[2 * xy_to_id(0, 0, self.nelx, self.nely), 0] = 1 f[2 * xy_to_id(0, self.nely // 2, self.nelx, self.nely), 0] = 1 # f[2 * xy_to_id(self.nelx, 0, self.nelx, self.nely), 1] = -1 f[2 * xy_to_id( self.nelx, self.nely // 2, self.nelx, self.nely), 1] = -1 return f @property def output_displacement_mask(self): """:obj:`numpy.ndarray`:Middle right output displacement mask.""" l = numpy.zeros(self.ndof, dtype=bool) # noqa l[2 * xy_to_id(self.nelx, self.nely // 2, self.nelx, self.nely), 0] = True return l
[docs]class GripperBoundaryConditions(MechanismSynthesisBoundaryConditions): """Boundary conditions for a gripping mechanism.""" @property def fixed_nodes(self): """:obj:`numpy.ndarray`:Fixed bottom and top left corner nodes.""" y = numpy.arange((self.nely + 1) // 20) lefty_to_id = numpy.vectorize( lambda y: xy_to_id(0, y, self.nelx, self.nely)) ids1 = 2 * lefty_to_id(y) x = numpy.arange((self.nelx + 1) // 20) botx_to_id = numpy.vectorize( lambda x: xy_to_id(x, self.nely, self.nelx, self.nely)) ids2 = 2 * botx_to_id(x) fixed = functools.reduce( numpy.union1d, [ids1, ids1 + 1, ids2, ids2 + 1]) return fixed @property def forces(self): """:obj:`numpy.ndarray`:Middle left input force.""" f = numpy.zeros((self.ndof, 2)) # f[2 * xy_to_id(0, 0, self.nelx, self.nely), 0] = 1 f[2 * xy_to_id(0, self.nely // 2, self.nelx, self.nely), 0] = 1 # f[2 * xy_to_id(self.nelx, 0, self.nelx, self.nely), 1] = -1 f[2 * xy_to_id( self.nelx, 4 * self.nely // 10, self.nelx, self.nely) + 1, 1] = -1 f[2 * xy_to_id( self.nelx, 6 * self.nely // 10, self.nelx, self.nely) + 1, 1] = 1 return f
[docs]class CrossSensitivityExampleBoundaryConditions( MechanismSynthesisBoundaryConditions): """Boundary conditions from Figure 2.19 of *Topology Optimization*.""" @property def fixed_nodes(self): """:obj:`numpy.ndarray`:Fixed bottom and top left corner nodes.""" y = numpy.arange((self.nely + 1) // 10) lefty_to_id = numpy.vectorize( lambda y: xy_to_id(0, y, self.nelx, self.nely)) ids1 = 2 * lefty_to_id(y) x = numpy.arange((self.nelx + 1) // 10) botx_to_id = numpy.vectorize( lambda x: xy_to_id(x, self.nely, self.nelx, self.nely)) ids2 = 2 * botx_to_id(x) fixed = functools.reduce( numpy.union1d, [ids1, ids1 + 1, ids2, ids2 + 1]) return fixed @property def forces(self): """:obj:`numpy.ndarray`:Middle left input force.""" f = numpy.zeros((self.ndof, 2)) # f[2 * xy_to_id(0, 0, self.nelx, self.nely), 0] = 1 f[2 * xy_to_id(0, self.nely // 2, self.nelx, self.nely), 0] = 1 # f[2 * xy_to_id(self.nelx, 0, self.nelx, self.nely), 1] = -1 f[2 * xy_to_id(self.nelx, 0, self.nelx, self.nely), 1] = -1 return f @property def active_elements(self): """:obj:`numpy.ndarray`:Active elements to be set to full density.""" return numpy.array([ xy_to_id(0, 0, self.nelx - 1, self.nely - 1), xy_to_id(0, 1, self.nelx - 1, self.nely - 1), xy_to_id(1, 1, self.nelx - 1, self.nely - 1), xy_to_id(1, 0, self.nelx - 1, self.nely - 1), xy_to_id(0, self.nely // 2, self.nelx - 1, self.nely - 1), xy_to_id(1, self.nely // 2, self.nelx - 1, self.nely - 1), xy_to_id(0, self.nely // 2 + 1, self.nelx - 1, self.nely - 1), xy_to_id(1, self.nely // 2 + 1, self.nelx - 1, self.nely - 1), xy_to_id(self.nely - 1, 0, self.nelx - 1, self.nely - 1)]) @property def output_displacement_mask(self): """:obj:`numpy.ndarray`:Middle right output displacement mask.""" l = numpy.zeros(self.ndof, dtype=bool) # noqa l[2 * xy_to_id(self.nelx, 0, self.nelx, self.nely), 0] = True return l