MID Benchmark Suite -- Environments
The environments in MIDBench serve as the interface between Python and the simulation & optimization (S&O) programs---be it a script running locally, or one running inside a Docker or Singularity container. Specifically, it should either perform simulation by taking the design variables and boundary conditions as input then yielding the performance metrics as requested, or perform optimization over the initial design variables by optimizing the performance metrics under the given boundary conditions. Since each S&O program is not necessarily written in Python, the design variables and boundary conditions need to be first transformed into a format readable to the program, and the resulting output of the program needs to be transformed back into Python variables.
In short, the MIDBench Environments are for generating the $(\bm{d}, \bm{b}, \bm{p})$---design, condition, performance---tuples for inverse design learning.
Basic Components
The MIDBench environments should complete their jobs with the following environment-specific Python classes---Env, Design, Condition, Performance---as components for easy management:
Env
class midbench.core.Env(specs: EnvSpec = None)
The parent class of the simulation/optimization environment, which serves as the interface between Python and the simulation/optimization program. In other words, it takes Python variables as inputs and outputs the results also in form of Python variables, while keeping the processing and running of the program under the hood.
-
Parameters:
- specs (
EnvSpec): The specifications for the initialization of the S&O program.
- specs (
-
Methods
As its role suggests,
Envshould have either a "simulate" method, or a "optimize" method. Both are for generating the $(\bm{d}, \bm{b}, \bm{p})$ tuples for inverse design learning, but with different motivations.-
simulate(designs: Design, conditions: Condition, performances: Performance, specs: SimSpec) → DataEntry:
Motivation: Design & Condition → Performance - Parameters - designs (
Design) - An $N\times D$ tensor-liked object defining the design space and storing the set of design variables $\bm{d}$. - conditions (Condition) - An $N\times B$ or $1\times B$ tensor-liked object storing the set of boundary conditions $\bm{b}$. If the first dimension is of size $1$, it will be propagated to all $N$ designs. - performances (Performance) - An $N\times P$ or $1\times P$ tensor-liked object storing the set of performances. It should be empty, with only the ID of the performances to be evaluated specified. If the first dimension is of size $1$, it will be propagated to all $N$ designs. - specs (SimSpec) - The specifications for running the simulation. Should be aDict-like object. - Returns - TheDataEntrydata logger storing the $(\bm{d}, \bm{b}, \bm{p})$ tuples, with theSimSpecinstance included for simulation replicability. - optimize(designs: Design, conditions: Condition, performances: Performance, specs: OptSpec) → DataEntry:Motivation: Performance & Condition → Design - Parameters - designs (
Design) - An $N\times D$ tensor-liked object defining the design space and storing the set of initial design variables $\bm{d}$. - conditions (Condition) - An $N\times B$ or $1\times B$ tensor-liked object storing the set of boundary conditions $\bm{b}$ under which the optimization is performed. If the first dimension is of size $1$, it will be propagated to all $N$ designs. - performances (Performance) - An $N\times P$ or $1\times P$ tensor-liked object storing the set of performances to be optimized. It should be empty, with only the ID of the performances to be evaluated specified. If the first dimension is of size $1$, it will be propagated to all $N$ designs. - specs (OptSpec): The specifications for running the optimization, including things like the number of iterations, tolerances, etc. Should be aDict-like object. - Returns - TheDataEntrydata entry storing the $(\bm{d}^\star, \bm{b}, \bm{p}^\star)$ tuples for either the optimization final result or the entire optimization history, with theOptSpecinstance included for optimization replicability.
-
-
Attributes:
- dbp (tuple): The tuple (Design, Condition, Performance) of classes dedicated to handling the data for this specific environment.
Design
class midbench.core.Design(data: array_like, specs: DesignSpec=None, dtype=None, **kwargs)
An ndarray subclass serving as the container and manager for the design variables $\bm{d}$ of a list of designs. We can develop environment-specific Designs by inheriting and overloading.
-
Arguments
- data (
array_like): The tensor of design variables or the directory of the design files. - specs (
DesignSpec): Adict-like object containing the specifications of the current design variable space. For instance, the specifications of the control point spaces of Bezier curve or B-spline. - dtype (
data-type, optional): dtype for ndarray. - kwargs: Optional keyword arguments used as key-value pairs to update the specifications in the
specsattribute. Cannot be any key other than the existing keys inspecs.
- data (
-
Methods
-
convert(specs: DesignSpec) → Design:
Convert the current design variables into a different design variable space.
- Parameters
- specs (
DesignSpec): The specification of the target design variable space.
- specs (
- Returns
- A new
Designin the target design space.
- A new
- Parameters
-
output(specs: MeshSpec) → Mesh:
Generate mesh file readable to the S&O program.
- Parameters
- specs (
MeshSpec): The specifications of the mesh.
- specs (
- Returns
- A mesh file (or its directory) that is readable to the environment.
- Parameters
-
-
Attributes
- specs (
DesignSpec): The specifications of the current design space. - Env (
Type): TheEnvclass that thisDesignclass is built for. - Spec(
Type): TheDesignSpecclass dedicated to thisDesignclass. A mandatory attribute in the definition ofDesignsubclass.
- specs (
Condition
class midbench.core.Condition(data: array_like, specs: ConditionSpec=None, dtype=None, **kwargs)
The container and manager for boundary conditions. This is the parent class of every other env-specific Condition.
-
Arguments
- data (
array_like): The values of the boundary conditions. - specs (
ConditionSpec): AnOrderedDict-like object containing the names and units of the values, and also specifying their order. Can be ignored if we only use the default metric system. - dtype (
data-type, optional): dtype for ndarray. - kwargs: Optional keyword arguments used as key-value pairs to update the specifications in the
specsattribute. Cannot be any key other than the existing keys inspecs.
- data (
-
Methods
-
output():
Transform it to the format that the S&O program can read.
- Returns
- The file or string that the S&O program can read.
-
convert(specs: ConditionSpec) → Condition:
- Parameters
- specs (
ConditionSpec): The metric system to be converted to.
- specs (
- Returns
- New
Conditioninstance with the given units.
- New
- Parameters
-
__repr__() → str:
- The string representation of the conditions for
print(), should be one showing both the values and the corresponding units.
-
-
Attributes
- specs (
ConditionSpec): The specifications of the current design space. - Env (
Type): TheEnvclass that thisConditionclass is built for. - Spec(
Type): TheConditionSpecclass dedicated to thisConditionclass. A mandatory attribute in the definition ofConditionsubclass. - names (
tuple): The names of the boundary conditions, which determines the order of the values. - units (
tuple): The units of the boundary conditions.
- specs (
Performance
class midbench.core.Performance(data: array_like, specs: PerformanceSpec=None, dtype=None, **kwargs)
The container and manager for performances. This is the parent class of every other env-specific Performance.
It may do two jobs:
- Storing the performance data produced by
simulate()andoptimize(). Empty values will be filled withNaN. -
Indicating the performances to be simulated or optimized (may need to add an additional attribute to
PerformanceSpec). -
Arguments
- data (
array_like): The values of the performances. - specs (
PerformanceSpec): The units of the values. Can be ignored if we only use the default metric system. - dtype (
data-type, optional): dtype for ndarray. - kwargs: Optional keyword arguments used as key-value pairs to update the specifications in the
specsattribute. Cannot be any key other than the existing keys inspecs.
- data (
-
Methods
-
output():
Transform it to the format that the S&O program can read.
- Returns
- The file or string that the S&O program can read.
-
convert(specs: PerformanceSpec) → Performance:
- Parameters
- specs (
PerformanceSpec): The units to be converted to.
- specs (
- Returns
- New
Performanceinstance with the given units.
- New
- Parameters
-
__repr__() → str:
The string representation of the performances for
print(), should be one showing both the values and the corresponding units.
-
-
Attributes
- specs (
PerformanceSpec): The specifications of the current design space. - Env (
Type): TheEnvclass that thisPerformanceclass is built for. - Spec(
Type): ThePerformanceSpecclass dedicated to thisPerformanceclass. A mandatory attribute in the definition ofPerformancesubclass. - names (
tuple): The names of the performances, which determines the order of the values. - units (
tuple): The units of the performances.
- specs (
Specifications
There might be a tremendous amount of specifications related to each environment components above. To efficiently manage them, enhance the tracability of simulations and optimizations, and improve the compatibility between different subclasses of the environment components, we use the instances of _Spec and _OrderedSpec to record, process and migrate all these specifications.
_Spec and _OrderedSpec are dict-like and OrderedDict-like objects, respectively. Their main difference to dictionaries---which is also the reason for the introduction of them---is that they have default keys and values, and their keys are immutable, which makes good sense for specifications. In addition, the specifications is also the defining characteristic of each subclass of the environment components, so it is a necessary attribute of each subclass and it is mandatory to specify it in the definition of each subclass.
_Spec
This class is for storing the specifications whose order does not matter. For instance, the DesignSpec of Design stores the specifications about the design variable space like the number of control points of the Bezier curve, and we do not care about their order.
Subclasses
DesignSpec, SimSpec, OptSpec, EnvSpec, MeshSpec...
_OrderedSpec
This is a subclass of _Spec for storing specifications whose order matters. For instance, for Condition and Performance, if we want to specify the unit of each dimension of these arrays, we had better also keep this info in a fixed order to remind us of the meaning of each dimension.
Subclasses
ConditionSpec, PerformanceSpec...
Compatibility
There are two ways to create a new _Spec instance, one is to specify explicity what the value of each key is, another is to take an existing _Spec instance as input and copy its values. The latter comes with a problem that two specifications might not have the same set of keys, so that a brainless copy between them is confusing for the fact that the keys of _Spec are fixed. However, this is to our benefit, as every Design, Condition and Performance subclass has a dedicated immutable _Spec which is part of its identity, and we can use this to determine which two subclasses are compatible.