Generating Parameter Sensitvities#
This tutorial will demonstrate how to generate geometric parameter sensitivities using HyperVehicle.
See also
This example follows on from the sharp wedge tutorial.
Workflow#
Nominal Geometry#
First, create the nominal geometry configuration. For this example, we will be using the sharp wedge geometry constructed previously.
Parametric Geometry Generator#
The next step is to refactor the geometry generation code into a
ParametricGenerator
object. This object inherits from the
Generator
object. This class has two methods:
the Generator.__init__()
method,
where all geometric parameters are passed as arguments, and the
create_instance()
method, which returns a
Vehicle
object ready to be generate()
’d.
The code below provides an example of this class. Note that the
named kwargs
are passed to super().__init__
to be unpacked
and overwrite the default parameters. See Generator
for more details.
from hypervehicle import Vehicle
from hypervehicle.components import Fuselage
from hypervehicle.generator import Generator
from hypervehicle.geometry import Vector3, Line, CoonsPatch
class ParametricWedge(Generator):
def __init__(self, **kwargs) -> None:
# Wedge parameters
self.wingspan = 1
self.chord = 1
self.thickness = 0.1
# Complete instantiation
super().__init__(**kwargs)
def create_instance(self) -> Vehicle:
# Create vehicle object
wedge = Vehicle()
wedge.configure(name="Wedge", verbosity=1)
# Define wedge cross-section points
# ^ +y
# |
# W _ - _ N ___
# _ - | - _ |
# +x <--- < -------------- > | thickness
# - _ | _ - |
# S - _ - E ___
#
# |-----------------|
# wingspan
NW = Vector3(x=0, y=0.5 * self.thickness)
NE = Vector3(
x=-0.5 * self.chord,
y=0,
)
SE = Vector3(x=0, y=-0.5 * self.thickness)
SW = Vector3(x=0.5 * self.chord, y=0)
# Define patches forming wedge
sections = []
for i in [-1, 1]:
z_loc = 0.5 * i * self.wingspan
axial_shift = Vector3(x=0, y=0, z=z_loc)
N = Line(p0=NW + axial_shift, p1=NE + axial_shift)
S = Line(p0=SW + axial_shift, p1=SE + axial_shift)
E = Line(p0=SE + axial_shift, p1=NE + axial_shift)
W = Line(p0=SW + axial_shift, p1=NW + axial_shift)
patch = CoonsPatch(north=N, south=S, east=E, west=W)
sections.append(patch)
fuselage = Fuselage(
cross_sections=sections,
sweep_axis="z",
stl_resolution=10,
)
wedge.add_component(fuselage)
# Generate STL
return wedge
Note that the nominal geometry could be generated using the generator object as well:
parametric_wedge_generator = ParametricWedge()
wedge = parametric_wedge_generator.create_instance()
wedge.generate()
This is a good check to ensure that the generator has been correctly implemented.
Run the Sensitivity Study#
With the steps above completed, you can run a sensitivity study
by creating an instance of SensitivityStudy
.
Then, define the design parameters which you would like to get
sensitivities to. In this example, we are extracting the geometric
sensitivities to each wedge parameter: the thickness, the chord
and the wingspan. We specify this with the parameters
dictionary,
passing along the nominal values to perturb about.
Finally, run the study by calling the dvdp()
method, passing in
the design parameters.
from hypervehicle.utilities import SensitivityStudy
# Construct sensitivity study
ss = SensitivityStudy(ParametricWedge)
# Define parameters to get sensitivities to
parameters = {'thickness': 0.1, 'chord': 1, 'wingspan': 1}
# Perform study
sensitivities = ss.dvdp(parameters)
# Save to CSV
ss.to_csv()
The output of dvdp
is a nested dictionary, containing
pandas DataFrame
s for each parameter and component of the
Vehicle object.
You can also save the results of the study using the to_csv
method. This will create a unique file for each component.
Visualisation of Sensitivities#
The .csv
files can be opened in ParaView. After opening the file,
select Table to Points (set x
, y
and z
columns before applying),
then Delaunay 3D filter.