aerosandbox.common#

Module Contents#

Classes#

AeroSandboxObject

Helper class that provides a standard way to create an ABC using

ExplicitAnalysis

Helper class that provides a standard way to create an ABC using

ImplicitAnalysis

Helper class that provides a standard way to create an ABC using

Functions#

load(filename[, verbose])

Loads an AeroSandboxObject from a file.

class aerosandbox.common.AeroSandboxObject[source]#

Bases: abc.ABC

Helper class that provides a standard way to create an ABC using inheritance.

_asb_metadata: Dict[str, str][source]#
__eq__(other)[source]#

Checks if two AeroSandbox objects are value-equivalent. A more sensible default for classes that represent physical objects than checking for memory equivalence.

This is done by checking if the two objects are of the same type and have the same __dict__.

Parameters:

other – Another object.

Returns:

True if the objects are equal, False otherwise.

Return type:

bool

save(filename=None, verbose=True, automatically_add_extension=True)[source]#

Saves the object to a binary file, using the dill library.

Creates a .asb file, which is a binary file that can be loaded with aerosandbox.load(). This can be loaded

into memory in a different Python session or a different computer, and it will be exactly the same as when it was saved.

Parameters:
  • filename (Union[str, pathlib.Path]) – The filename to save this object to. Should be a .asb file.

  • verbose (bool) – If True, prints messages to console on successful save.

  • automatically_add_extension (bool) – If True, automatically adds the .asb extension to the filename if it doesn’t already have it. If False, does not add the extension.

Return type:

None

Returns: None (writes to file)

copy()[source]#

Returns a shallow copy of the object.

deepcopy()[source]#

Returns a deep copy of the object.

substitute_solution(sol, inplace=None)[source]#

Substitutes a solution from CasADi’s solver recursively as an in-place operation.

In-place operation. To make it not in-place, do y = copy.deepcopy(x) or similar first. :param sol: OptiSol object. :return:

Parameters:
  • sol (casadi.OptiSol) –

  • inplace (bool) –

aerosandbox.common.load(filename, verbose=True)[source]#

Loads an AeroSandboxObject from a file.

Upon load, will compare metadata from the file to the current Python version and AeroSandbox version. If there are any discrepancies, will raise a warning.

Parameters:
  • filename (Union[str, pathlib.Path]) – The filename to load from. Should be a .asb file.

  • verbose (bool) – If True, prints messages to console on successful load.

Return type:

AeroSandboxObject

Returns: An AeroSandboxObject.

class aerosandbox.common.ExplicitAnalysis[source]#

Bases: AeroSandboxObject

Helper class that provides a standard way to create an ABC using inheritance.

default_analysis_specific_options: Dict[type, Dict[str, Any]][source]#

This is part of AeroSandbox’s “analysis-specific options” feature, which lets you “tag” geometry objects with flags that change how different analyses act on them.

This variable, default_analysis_specific_options, allows you to specify default values for options that can be used for specific problems.

This should be a dictionary, where: * keys are the geometry-like types that you might be interested in defining parameters for. * values are dictionaries, where: * keys are strings that label a given option * values are anything. These are used as the default values, in the event that the associated geometry doesn’t override those.

An example of what this variable might look like, for a vortex-lattice method aerodynamic analysis:

>>> default_analysis_specific_options = {
>>>     Airplane: dict(
>>>         profile_drag_coefficient=0
>>>     ),
>>>     Wing    : dict(
>>>         wing_level_spanwise_spacing=True,
>>>         spanwise_resolution=12,
>>>         spanwise_spacing="cosine",
>>>         chordwise_resolution=12,
>>>         chordwise_spacing="cosine",
>>>         component=None,  # type: int
>>>         no_wake=False,
>>>         no_alpha_beta=False,
>>>         no_load=False,
>>>         drag_polar=dict(
>>>             CL1=0,
>>>             CD1=0,
>>>             CL2=0,
>>>             CD2=0,
>>>             CL3=0,
>>>             CD3=0,
>>>         ),
>>>     )
>>> }
get_options(geometry_object)[source]#

Retrieves the analysis-specific options that correspond to both:

  • An analysis type (which is this object, “self”), and

  • A specific geometry object, such as an Airplane or Wing.

Parameters:

geometry_object (AeroSandboxObject) –

An instance of an AeroSandbox geometry object, such as an Airplane, Wing, etc.

  • In order for this function to do something useful, you probably want this option to have

analysis_specific_options defined. See the asb.Airplane constructor for an example of this.

Return type:

Dict[str, Any]

Returns: A dictionary that combines:

  • This analysis’s default options for this geometry, if any exist.

  • The geometry’s declared analysis-specific-options for this analysis, if it exists. These geometry

options will override the defaults from the analysis.

This dictionary has the format:

  • keys are strings, listing specific options

  • values can be any type, and simply state the value of the analysis-specific option following the

logic above.

Note: if this analysis defines a set of default options for the geometry type in question (by using self.default_analysis_specific_options), all keys from the geometry object’s analysis_specific_options will be validated against those in the default options set. A warning will be raised if keys do not correspond to those in the defaults, as this (potentially) indicates a typo, which would otherwise be difficult to debug.

class aerosandbox.common.ImplicitAnalysis[source]#

Bases: AeroSandboxObject

Helper class that provides a standard way to create an ABC using inheritance.

property opti[source]#
property opti_provided[source]#
static initialize(init_method)[source]#

A decorator that should be applied to the __init__ method of ImplicitAnalysis or any subclass of it.

Usage example:

>>> class MyAnalysis(ImplicitAnalysis):
>>>
>>>     @ImplicitAnalysis.initialize
>>>     def __init__(self):
>>>         self.a = self.opti.variable(init_guess = 1)
>>>         self.b = self.opti.variable(init_guess = 2)
>>>
>>>         self.opti.subject_to(
>>>             self.a == self.b ** 2
>>>         ) # Add a nonlinear governing equation

Functionality:

The basic purpose of this wrapper is to ensure that every ImplicitAnalysis has an opti property that points to an optimization environment (asb.Opti type) that it can work in.

How do we obtain an asb.Opti environment to work in? Well, this decorator adds an optional opti parameter to the __init__ method that it is applied to.

1. If this opti parameter is not provided, then a new empty asb.Opti environment is created and stored as ImplicitAnalysis.opti.

2. If the opti parameter is provided, then we simply assign the given asb.Opti environment (which may already contain other variables/constraints/objective) to ImplicitAnalysis.opti.

In addition, a property called ImplicitAnalysis.opti_provided is stored, which records whether the user provided an Opti environment or if one was instead created for them.

If the user did not provide an Opti environment (Option 1 from our list above), we assume that the user basically just wants to perform a normal, single-disciplinary analysis. So, in this case, we proceed to solve the analysis as-is and do an in-place substitution of the solution.

If the user did provide an Opti environment (Option 2 from our list above), we assume that the user might potentially want to add other implicit analyses to the problem. So, in this case, we don’t solve the analysis, and the user must later solve the analysis by calling sol = opti.solve() or similar.