Source code for openaerostruct.geometry.ffd_component

""" Manipulate geometry mesh based on high-level design parameters. """

import numpy as np

import openmdao.api as om

try:
    from pygeo import DVGeometry
except ImportError:
    pass


[docs] class GeometryMesh(om.ExplicitComponent): """ OpenMDAO component that performs mesh manipulation functions. It reads in the initial mesh from the surface dictionary and outputs the altered mesh based on the geometric design variables. Depending on the design variables selected or the supplied geometry information, only some of the follow parameters will actually be given to this component. If parameters are not active (they do not deform the mesh), then they will not be given to this component. Parameters ---------- Returns ------- mesh[nx, ny, 3] : numpy array Modified mesh based on the initial mesh in the surface dictionary and the geometric design variables. """ def initialize(self): self.options.declare("surface", types=dict) self.options.declare("DVGeo", types=DVGeometry) def setup(self): self.surface = surface = self.options["surface"] self.mx, self.my = self.surface["mx"], self.surface["my"] self.DVGeo = self.options["DVGeo"] # Associate a 'reference axis' for large-scale manipulation self.DVGeo.addRefAxis("wing_axis", xFraction=0.25, alignIndex="i") # Now add local (shape) variables self.DVGeo.addLocalDV("shape", lower=-0.5, upper=0.5, axis="z") pts = surface["mesh"].reshape(-1, 3) self.DVGeo.addPointSet(pts, "surface") coords = self.DVGeo.getLocalIndex(0) self.inds = coords[:, 0, :] self.inds2 = coords[:, 1, :] self.add_input("shape", val=np.zeros((self.mx, self.my)), units="m") self.add_output("mesh", val=surface["mesh"], units="m") self.declare_partials("*", "*") def compute(self, inputs, outputs): surface = self.surface dvs = self.DVGeo.getValues() for i, row in enumerate(self.inds): for j, ind in enumerate(row): ind2 = self.inds2[i, j] dvs["shape"][ind] = inputs["shape"][i, j] dvs["shape"][ind2] = inputs["shape"][i, j] self.DVGeo.setDesignVars(dvs) coords = self.DVGeo.update("surface") mesh = coords.copy() mesh = mesh.reshape(surface["mesh"].shape) outputs["mesh"] = mesh def compute_partials(self, inputs, partials): self.DVGeo.computeTotalJacobian("surface") jac = self.DVGeo.JT["surface"].toarray().T my_jac = partials["mesh", "shape"] my_jac[:, :] = 0.0 for i, ind in enumerate(self.inds.flatten()): ind2 = self.inds2.flatten()[i] my_jac[:, i] += jac[:, ind] my_jac[:, i] += jac[:, ind2] partials["mesh", "shape"] = my_jac