cosapp.systems.system¶
Basic classes handling model resolution, system connections and conversion between level of modelings.
Classes
|
Enumeration of System conversion type. |
|
Enumeration of System algorithm to define component execution order. |
|
A class to describe generic properties and functions of a component that can be single or made of child System. |
- class cosapp.systems.system.ConversionType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
Enum
Enumeration of System conversion type.
- best_fidelity_to_cost = 'best_fidelity_to_cost_ratio'¶
- high_cost = 'highest_cost'¶
- high_fidelity = 'highest_fidelity'¶
- low_cost = 'lowest_cost'¶
- low_fidelity = 'lowest_fidelity'¶
- manual = 'manual'¶
- class cosapp.systems.system.ExecutionOrdering(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
Enum
Enumeration of System algorithm to define component execution order.
- MANUAL = 'manual'¶
- class cosapp.systems.system.System(name: str, **kwargs)[source]¶
Bases:
Module
,TimeObserver
A class to describe generic properties and functions of a component that can be single or made of child System.
- Parameters:
name (str) – Name of the System
- name¶
System name
- Type:
str
- inputs¶
Dictionary of BasePort containing the values needed to compute the System
- Type:
collections.OrderedDict
ofBasePort
- residues¶
Dictionary of residues generated by the System
- Type:
collections.OrderedDict
of :obj:float
- exec_order¶
Execution order in which sub-systems are computed.
- Type:
MappingView[str]
- properties¶
Dictionary of immutable parameters of the system.
- Type:
Dict[str, Any]
- design_methods¶
System pre-defined design methods
- Type:
Dict[Equations]
- name2variable¶
Variable name mapping to its value by reference
- Type:
Dict[str, VariableReference]
- _locked¶
if True, add_input, add_output, add_inward and add_outward are desactivated. This is the default behavior outside the setup function.
- Type:
bool
- _active¶
if False, the System will not execute its compute method
- Type:
bool
- _is_tree_clean¶
Reflects the status of the inputs and outputs. clean status means the group of ports was not updated since last computation of the System
- Type:
bool
- _compute_calls¶
Store if the System was computed at last call or not (due to inhibition of clean status)
- Type:
bool
Examples
To create your own System, you should inherit from this class and define your own setup and compute methods.
>>> import numpy as np >>> >>> class RealPort(Port): >>> >>> def setup(self): >>> self.add_variable('x',0.) >>> >>> class InvertedParabola(System): >>> >>> def setup(self): >>> self.add_input(RealPort, 'iterative') >>> self.add_input(RealPort, 'target_y') >>> self.add_output(RealPort, 'max_root') >>> self.add_inward({'a': 0.01, >>> 'b': 2., >>> 'c': 4.}) >>> self.add_outward('roots', None) >>> self.add_equation("a * iterative.x**2 + b * iterative.x + c == target_y.x", "y") >>> >>> def compute(self): >>> >>> discriminant = self.b**2 - 4. * self.a * self.c >>> if discriminant >= 0.: >>> self.roots = ((-self.b + np.sqrt(discriminant)) / (2. * self.a), >>> (-self.b - np.sqrt(discriminant)) / (2. * self.a)) >>> self.max_roots.x = max(self.roots) >>> else: >>> self.roots = None >>> self.max_roots.x = np.nan
- COMMON_PORTS: List[str] = ['INWARDS', 'OUTWARDS', 'MODEVARS_IN', 'MODEVARS_OUT']¶
- INWARDS: ClassVar[str] = 'inwards'¶
- MODEVARS_IN: ClassVar[str] = 'modevars_in'¶
- MODEVARS_OUT: ClassVar[str] = 'modevars_out'¶
- OUTWARDS: ClassVar[str] = 'outwards'¶
- property active_surrogate: bool¶
True if surrogate model is activated, False otherwise.
- Type:
bool
- add_child(child: AnySystem, execution_index: int | None = None, pulling: str | Collection[str] | Dict[str, str] | None = None, desc: str = '') AnySystem [source]¶
Add a child System to the current System.
When adding a child System, it is possible to specified its position in the execution order.
Child ports or individual inwards and outwards can also be pulled at the parent level by providing either the name of the port/inward/outward or a list of them or the name mapping of the child element (dictionary keys) to the parent element (dictionary values). If the argument is not a dictionary, the name in the parent system will be the same as in the child.
- Parameters:
[System] (- child) – System to add to the current System
[int (execution_index) – Index of the execution order list at which the System should be inserted; default latest.
optional] – Index of the execution order list at which the System should be inserted; default latest.
dict[str (- pulling [str or list[str] or) – Map of child ports to pulled ports at the parent system level; default None (no pulling)
str] – Map of child ports to pulled ports at the parent system level; default None (no pulling)
optional] – Map of child ports to pulled ports at the parent system level; default None (no pulling)
[str (- desc) – Sub-system description in the context of its parent.
optional] – Sub-system description in the context of its parent.
- Return type:
child
- add_design_method(name: str) MathematicalProblem [source]¶
Add a design method to the System
A design method is a set of free variables and equations that defines a way to design the System It is a easy way to pre-define a design of this System for users
The returned mathematical system is empty. It should be populated with the needed variables and equations (see Examples).
- Parameters:
name (str) – The name of the design method
- Returns:
The newly created mathematical problem.
- Return type:
Examples
>>> system1.add_design_method("method1") >>> .add_unknown([ >>> dict(name="x", max_rel_step=0.1), >>> "y" >>> ]) >>> .add_equation([ >>> "u == 0", >>> "v == 800" >>> ])
- add_equation(equation: str | Iterable[dict | str | Tuple[str, str]], name: str | None = None, reference: Number | ndarray | str = 1) MathematicalProblem [source]¶
Add off-design equation.
Equations may be added one by one, or provided by a list of dictionaries to add multiple equations at once. The dictionary keys are the arguments of this method.
- Parameters:
equation (-) – Equation or list of equations to add
name (-) – Name of the equation; default None => ‘lhs == rhs’
reference (-) – Reference value(s) used to normalize the equation; default is 1. If value is “norm”, actual reference value is estimated from order of magnitude.
- Returns:
The modified mathematical problem
- Return type:
- add_event(name: str, desc: str = '', trigger: str | Event | EventState | ZeroCrossing | None = None, final: bool = False) Event [source]¶
Add an event to system.
An event occurrence can either be determined by the system itself, or triggered by an event from another system.
This function cannot be called outside
setup()
.- Parameters:
[str] (- name) – Name of the event.
[str (- desc) – Event description; defaults to ‘’.
optional] – Event description; defaults to ‘’.
[Union[str (- trigger) – String, primary or derived event defining the event trigger; defaults to None.
Event – String, primary or derived event defining the event trigger; defaults to None.
EventState – String, primary or derived event defining the event trigger; defaults to None.
ZeroCrossing] – String, primary or derived event defining the event trigger; defaults to None.
optional] – String, primary or derived event defining the event trigger; defaults to None.
[bool (- final) – Defines whether or not event is final; defaults to False.
optional] – Defines whether or not event is final; defaults to False.
- Returns:
The newly created event.
- Return type:
event [Event]
Examples
>>> import numpy as np >>> >>> class PointMassDynamics(System): >>> # Free fall of a point mass, with friction >>> def setup(self): >>> self.add_inward('mass', 1.2, desc='Mass') >>> self.add_inward('cf', 0.1, desc='Friction coefficient') >>> self.add_inward('g', np.r_[0, 0, -9.81], unit='m/s**2', desc='External acceleration field') >>> >>> self.add_outward('a', np.zeros(3), unit='m/s**2', desc='Acceleration') >>> self.add_transient('v', der='a') >>> self.add_transient('x', der='v') >>> >>> def compute(self): >>> self.a = self.g - (self.cf / self.mass * np.linalg.norm(self.v)) * self.v >>> >>> class BouncingPointMass(System): >>> def setup(self): >>> self.add_child(PointMassDynamics('dyn'), pulling=['x', 'v', 'a', 'mass', 'cf', 'g']) >>> self.add_event('rebound', trigger="x[2] <= 0") >>> >>> def transition(self): >>> if self.rebound.present: >>> self.v[2] *= -1
- add_input(port_class: Type[AnyPort], name: str, variables: Dict[str, Any] | None = None, desc: str = '') AnyPort [source]¶
Add an input Port to the System.
This function cannot be called outside System.setup.
- Parameters:
[type[Port]] (- port_class) – Class of the Port to create
[str] (- name) – Port name
[str (- desc) – Port description
optional] – Port description
[dict[str (- variables) – Dictionary of initial values (default: None)
Any] – Dictionary of initial values (default: None)
optional] – Dictionary of initial values (default: None)
- Return type:
The created port
Examples
>>> class MyModule(System): >>> def setup(self): >>> self.add_input(MyPort, 'p_in1') >>> self.add_input(MyPort, 'p_in2', {'x': 1.5})
- add_inward(definition: str | Dict[str, Any], value: Any = 1, unit: str = '', dtype: Any | Tuple[Any, ...] | None = None, valid_range: Tuple[Any, Any] | None = None, invalid_comment: str = '', limits: Tuple[Any, Any] | None = None, out_of_limits_comment: str = '', desc: str = '', distribution: Distribution | None = None, scope: Scope = Scope.PRIVATE) None [source]¶
Add a inward variable to the System.
A inward variable is calculated by the System. But its value is not mandatory in any variables fluxes between this System and another one.
An unique inward variable can be defined by providing directly all arguments. And multiple inward variables can be defined by passing a dict of pair (str, Any) with an entry for each variable.
This function cannot be called outside
setup()
.- Parameters:
definition (str or Dict[str, Any]) – Name of the unique variable or a dictionary for multiple variables at once
value (Any, optional) – Value of the variable if definition is a str; default 1
unit (str, optional) – Variable unit; default empty string (i.e. dimensionless)
dtype (type or iterable of types, optional) – Variable type; default None (i.e. type of initial value)
valid_range (Tuple[Any, Any], optional) – Validity range of the variable; default None (i.e. all values are valid)
invalid_comment (str, optional) – Comment to show in case the value is not valid; default ‘’
limits (Tuple[Any, Any], optional) – Limits over which the use of the model is wrong; default valid_range
out_of_limits_comment (str, optional) – Comment to show in case the value is not valid; default ‘’
desc (str, optional) – Variable description; default ‘’
distribution (Distribution, optional) – Probability distribution of the variable; default None (no distribution)
scope (Scope {PRIVATE, PROTECTED, PUBLIC}, optional) – Variable visibility; default PRIVATE
Examples
To add one inward variable, arguments must be directly specified.
>>> system.add_inward('data', 2.)
To add multiple inward variables, a dictionary with one key per data should be provided.
>>> system.add_inward({ >>> 'data1': 42., >>> 'data2': False >>> })
- add_inward_modevar(name: str, value: Any = False, unit: str = '', dtype: Any | Tuple[Any, ...] | None = None, desc: str = '', scope: Scope = Scope.PRIVATE) None [source]¶
Add an inward mode variable to the System.
A mode variable is a piecewise constant variable in each continuous time phase. Like any input, inward mode variables should not be modified during system transitions.
This function cannot be called outside
setup()
.- Parameters:
name (str) – Name of the variable
value (Any, optional) – Value of the variable; default 1
unit (str, optional) – Variable unit; default empty string (i.e. dimensionless)
dtype (type) – Variable type; default None (i.e. type of initial value)
desc (str, optional) – Variable description; default ‘’
scope (Scope {PRIVATE, PROTECTED, PUBLIC}, optional) – Variable visibility; default PRIVATE
Examples
>>> class MultimodeSystem(System): >>> def setup(self): >>> self.add_inward_modevar('composite', True) >>> self.reconfig() >>> >>> def reconfig(self): >>> # Define one or two sub-systems, depending on mode >>> for name in list(self.children): >>> self.pop_child(name) >>> if self.composite: >>> a = self.add_child(Foo('a')) >>> b = self.add_child(Bar('b')) >>> self.connect(a, b, {'x', 'y'}) >>> else: >>> self.add_child(Bogus('c')) >>> >>> def transition(self): >>> self.reconfig()
- add_output(port_class: Type[AnyPort], name: str, variables: Dict[str, Any] | None = None, desc: str = '') AnyPort [source]¶
Add an output Port to the System.
This function cannot be called outside System.setup.
- Parameters:
[type[Port]] (- port_class) – Class of the Port to create
[str] (- name) – Port name
[str (- desc) – Port description
optional] – Port description
[dict[str (- variables) – Dictionary of initial values (default: None)
Any] – Dictionary of initial values (default: None)
optional] – Dictionary of initial values (default: None)
- Return type:
The created port
Examples
>>> class MyModule(System): >>> def setup(self): >>> self.add_output(MyPort, 'p_out1') >>> self.add_output(MyPort, 'p_out2', {'y': 1.5})
- add_outward(definition: str | Dict[str, Any], value: Any = 1, unit: str = '', dtype: Any | Tuple[Any, ...] | None = None, valid_range: Tuple[Any, Any] | None = None, invalid_comment: str = '', limits: Tuple[Any, Any] | None = None, out_of_limits_comment: str = '', desc: str = '', scope: Scope = Scope.PUBLIC) None [source]¶
Add a outward variable to the System.
A outward variable is calculated by the System. But its value is not mandatory in any variables fluxes between this System and another one.
An unique outward variable can be defined by providing directly all arguments. And multiple outward variables can be defined by passing a dict of pair (str, Any) with an entry for each variable.
This function cannot be called outside
setup()
.- Parameters:
definition (str or Dict[str, Any]) – Name of the unique variable or a dictionary for multiple variables at once
value (Any, optional) – Value of the variable if definition is a str; default 1
unit (str, optional) – Variable unit; default empty string (i.e. dimensionless)
dtype (type or iterable of types, optional) – Variable type; default None (i.e. type of initial value)
valid_range (Tuple[Any, Any], optional) – Validity range of the variable; default None (i.e. all values are valid)
invalid_comment (str, optional) – Comment to show in case the value is not valid; default ‘’
limits (Tuple[Any, Any], optional) – Limits over which the use of the model is wrong; default valid_range
out_of_limits_comment (str, optional) – Comment to show in case the value is not valid; default ‘’
desc (str, optional) – Variable description; default ‘’
scope (Scope {PRIVATE, PROTECTED, PUBLIC}, optional) – Variable visibility; default PUBLIC
Examples
To add an unique variable, arguments must be directly specified.
>>> system.add_outward('info', 2.)
To add multiple variables, a dictionary with one key per outward variable should be provided.
>>> system.add_inward({ >>> 'info1': 42., >>> 'info2': False >>> })
- add_outward_modevar(name: str, value: Any | None = None, unit: str = '', dtype: Any | Tuple[Any, ...] | None = None, desc: str = '', init: Any | None = None, scope: Scope = Scope.PRIVATE) None [source]¶
Add an outward mode variable to the System.
A mode variable is a piecewise constant variable in each continuous time phase. It may only be modified in the transition method of the System, and never inside method compute. Notwithstanding, its value may be used in compute. The modification of an output mode variable is often associated with the occurence of an event in the system.
This function cannot be called outside
setup()
.- Parameters:
name (str) – Name of the variable
value (Any, optional) – Value of the variable; default 1
unit (str, optional) – Variable unit; default empty string (i.e. dimensionless)
dtype (type) – Variable type; default None (i.e. type of initial value)
desc (str, optional) – Variable description; default ‘’
init (Any, optional) – Value imposed at the beginning of time simulations. If unspecified (default), the variable remains untouched.
scope (Scope {PRIVATE, PROTECTED, PUBLIC}, optional) – Variable visibility; default PRIVATE
Examples
>>> class ThresholdSystem(System): >>> def setup(self): >>> self.add_inward('threshold', 1.0) >>> self.add_inward('x', 0.0) >>> self.add_outward('y', 0.0) >>> self.add_event('activates', trigger='x >= threshold') >>> self.add_outward_modevar('activated', init='x > threshold') >>> >>> def compute(self): >>> self.y = self.x if self.activated else 0.0 >>> >>> def transition(self): >>> if self.activates.present: >>> self.activated = True
- add_rate(name: str, source: Any, initial_value: Number | ndarray | str = None, desc: str = None) None [source]¶
Add a variable monitoring the rate-of-change of a given quantity (referred to as source) as the system evolves. Rates are defined by their source, and are updated by the time driver computing the time evolution of the system.
This function cannot be called outside
setup()
.- Parameters:
name (str) – Name of the transient variable
source (Any) – Expression of the quantity of interest whose rate will be computed. The type and unit of the rate are deduced from source.
desc (str, optional) – Variable description; default None
initial_value (Number/array, or evaluable expression (str), optional.) – Initial value of the rate (otherwise unknown, as rates are only updated from the first time step on). If specified, it must be consistent with the type of source (scalar vs. array).
Examples
>>> system.add_inward('U', 0.1, desc='Input voltage') >>> system.add_rate('dUdt', source='U') # dUdt defined as dU/dt
- add_target(name: str | Iterable[dict | str | Tuple[str, str]], reference: Number | ndarray | str = 1, weak=False) MathematicalProblem [source]¶
Add deferred off-design equation on a targetted quantity.
Target equations may be added one by one, or provided by a list of dictionaries to add multiple equations at once. The dictionary keys are the arguments of this method.
- Parameters:
name (-) – Name of the equation; default None => ‘lhs == rhs’
reference (-) – Reference value(s) used to normalize the equation; default is 1. If value is “norm”, actual reference value is estimated from order of magnitude.
weak (-) – If True, the target is disregarded if the corresponding variable is connected; default is False.
- Returns:
The modified mathematical problem
- Return type:
- add_transient(name: str, der: str, desc: str = None, max_time_step: Number | str = inf, max_abs_step: Number | str = inf) None [source]¶
Declare a transient variable, defined implicitly by the expression of its time derivative, and add a time-dependent unknown to the mathematical problem. Transients can be used withinn the system, but their time evolution is computed outside the system, by a time driver.
If name already exists, it must refer to an inward. If name does not exist, a new inward name is created on the fly.
This function cannot be called outside
setup()
.- Parameters:
name (str) – Name of the transient variable
der (str) – Expression of the time derivative, used for integration during time driver execution. The type and unit of the transient variable are deduced from der.
desc (str, optional) – Variable description; default None
max_time_step (Number or evaluable expression (str), optional) – Maximum time step admissible for the integration of the variable (for stability, typically).
max_abs_step (Number or evaluable expression compatible with transient variable, optional) – Maximum variable step admissible over one time step (for stability, typically).
Examples
>>> system.add_inward('v', numpy.zeros(3), desc='Velocity') >>> system.add_inward('a', numpy.zeros(3), desc='Acceleration') >>> system.add_inward('area', 1.0) >>> system.add_outward('flowrate', desc='Volumetric flowrate') >>> system.add_transient('x', der='v') # x defined by dx/dt = v >>> system.add_transient('v', der = 'a', max_time_step = '0.1 / max(norm(a), 1e-9)', ) >>> system.add_transient('h', der = 'flowrate / area', max_abs_step = 0.1, )
- add_unknown(name: str | Iterable[dict | str], max_abs_step: Number = inf, max_rel_step: Number = inf, lower_bound: Number = -inf, upper_bound: Number = inf) MathematicalProblem [source]¶
Add unknown variables.
You can set variable one by one or provide a list of dictionary to set multiple variable at once. The dictionary key are the arguments of this method.
- Parameters:
name (-) – Name of the variable or list of variable to add
max_rel_step (-) – Maximal relative step by which the variable can be modified by the numerical solver; default numpy.inf
max_abs_step (-) – Maximal absolute step by which the variable can be modified by the numerical solver; default numpy.inf
lower_bound (-) – Lower bound on which the solver solution is saturated; default -numpy.inf
upper_bound (-) – Upper bound on which the solver solution is saturated; default numpy.inf
- Returns:
The modified mathematical problem
- Return type:
- append_name2variable(additional_mapping: Iterable[Tuple[str, VariableReference]]) None [source]¶
Append the Iterable of (str, VariableReference) Tuple to the lookup variables mapping.
The additional mapping is also transfer upward to the parent System.
- Parameters:
additional_mapping (Iterable[Tuple[str, VariableReference]]) – Additional list of (str, VariableReference) tuple to append
- assembled_problem() MathematicalProblem [source]¶
Returns the consolidated mathematical problem, assembled from entire system tree, and accounting for cyclic dependency loops.
- Returns:
The assembled mathematical problem.
- Return type:
- assembled_time_problem() TimeProblem [source]¶
Returns the consolidated transient problem, assembled from the entire system tree.
- Returns:
The assembled time problem.
- Return type:
- call_clean_run(skip_driver: bool = False) None [source]¶
Execute clean_run recursively on all modules.
- Parameters:
skip_drivers (bool) – Skip calling
cosapp.drivers.driver.Driver.clean_run()
- call_setup_run(skip_driver: bool = False) None [source]¶
Execute setup_run recursively on all modules.
- Parameters:
skip_drivers (bool) – Skip calling
cosapp.drivers.driver.Driver.setup_run()
- check(name: str | None = None) Dict[str, Validity] | Validity [source]¶
Get variable value validity for a given variable, port or system or all of them.
If name is not provided, returns a dictionary with the validity of all System variables; i.e. all variables in input and output ports including inwards and outwards of this system and all its children. Else only, the validity for the given variable will be returned.
- classmethod check_config_dict(params: dict) None [source]¶
Check if the provided dictionary respects the convention of a model file.
- Parameters:
params (dict) – Dictionary to be tested
- Raises:
jsonschema.exceptions.ValidationError – If the provided dictionary does not conform to the JSON schema.
- property child_connectors: Dict[str, List[Connector]]¶
Connectors between sub-systems, referenced by system names.
- Type:
Dict[str, List[Connector]]
- connect(object1: BasePort | System, object2: BasePort | System, mapping: str | List[str] | Dict[str, str] | None = None, cls: Type[BaseConnector] | None = None, **kwargs) None [source]¶
Connect two systems or two ports.
This method connects object1 to object2. If no mapping is provided, connection will be made between variables based on their names. If a name mapping is provided as a list, the name should be present in both objects. If the mapping is specified as a dictionary, keys are expected to belong to object1, and values to object2.
If both objects are systems, mapping is mandatory (full system connections are forbidden). In this case, each (key, value) pair of the mapping leads to a port-to-port connection.
Connections are oriented (i.e. the direction of value transfer is fixed). The decision tree is as following:
If one port is of type input and the other one of type output, the connection flows from the output to the input.
Else if one port (portA) belong to the parent System of the other port (portB), the connection flows from portA to portB if portA is an input. And it flows from portB to portA if portA is an output.
Else if both are inputs, the port is pulled on the parent and connected to the two children.
Connectors can only connect systems at the same level or a system with its parent. In all cases the connectors will be stored by the parent hosting the two connected systems.
- Parameters:
object1 (Union[BasePort, System]) – First end-point of connector.
object2 (Union[BasePort, System]) – Second end-point of connector.
mapping (str or List[str] or Dict[str, str], optional) – (List of) common name(s) or mapping name dictionary; default None (i.e. no mapping).
cls (Type[BaseConnector], optional) – Connector type. When specified, cls must be a specialization of BaseConnector. If cls is None (default), the actual connector type is either Connector, or a port-specific connector, if any. Port bound connectors are automatically selected when both ports are of same type, and when port class contains inner class Connector, derived from BaseConnector.
**kwargs – Additional keyword arguments forwarded to cls.
Examples
Here is an example, in which we assume a port p_in has inputs of a system s1 that come from some output port p_out of another system s2. In the last example, connect is called with two child systems, rather than ports. The container system being called top:
>>> class DemoPort(Port): >>> def setup(self): >>> self.add_variable('a', 1.0) >>> self.add_variable('b', 2.0) >>> self.add_variable('c', 3.0) >>> >>> class DummySystem(Port): >>> def setup(self): >>> self.add_inward('x', 1.0) >>> self.add_outward('y', 0.0) >>> self.add_input(DemoPort, 'p_in') >>> self.add_output(DemoPort, 'p_out') >>> >>> top = System('top') >>> top.add(DummySystem('s1')) >>> top.add(DummySystem('s2')) >>> >>> top.connect(top.s1.p_in, top.s2.p_out, 'a') >>> top.s1.p_in.a = 4 >>> top.run_once() >>> assert top.s1.p_in.a == top.s2.p_out.a >>> >>> top.connect(top.s1.p_in, top.s2.p_out, {'b': 'c'}) >>> top.run_once() >>> assert top.s1.p_in.b == top.s2.p_out.c >>> >>> top.connect(top.s1, top.s2, {'x': 'y', 'p_in.c': 'p_out.b'}) >>> top.run_once() >>> assert top.s1.x == top.s2.y >>> assert top.s1.p_in.c == top.s2.p_out.b
- connectors() Dict[str, Connector] [source]¶
Constructs a dictionary of all connectors within system, referenced by connector name.
- convert_to(*args, **kwargs) None [source]¶
Convert system into another System. Note: not implemented for class System.
- Raises:
TypeError – If the current System cannot be converted.
- design(method: str) MathematicalProblem [source]¶
Returns the chosen group of design equations.
- Parameters:
method (str) – Name of the group of equations to extract
- Returns:
Mathematical system to solve for the chosen method
- Return type:
- design_methods: Dict[str, MathematicalProblem]¶
- dump_surrogate(filename: str) None [source]¶
Dumps system surrogate model (if any) into a binary file.
- export_structure() Dict [source]¶
Export current system structure to a dictionary, which contains the definition of all ports, the structure of sub-system and the connections between ports.
- get_unsolved_problem() MathematicalProblem [source]¶
Returns the consolidated mathematical problem, assembled from entire system tree, and accounting for cyclic dependency loops.
Deprecated; use assembled_problem instead.
- Returns:
The assembled mathematical problem.
- Return type:
- property has_surrogate: bool¶
True if system has a surrogate model (even if inactive), False otherwise.
- Type:
bool
- incoming_connectors() Iterator[Connector] [source]¶
Iterator yielding all connectors targetting system.
- property input_mapping: Dict[str, VariableReference]¶
free input mapping
- Type:
Dict[str, VariableReference]
- is_clean(direction: PortType | None = None) bool [source]¶
Are the System ports with the given direction clean? If no direction is specified, checks if both directions are clean.
- Parameters:
direction (PortType, optional) – Direction of interest
- Returns:
Clean status
- Return type:
bool
- is_input_var(name: str) bool [source]¶
Returns True if name is the name of an input variable, False otherwise
- is_output_var(name: str) bool [source]¶
Returns True if name is the name of an output variable, False otherwise
- is_running() bool [source]¶
Is this System in execution?
- Returns:
In execution status
- Return type:
bool
- is_standalone() bool [source]¶
Is this System able to solve itself?
- Returns:
Ability to solve the system or not.
- Return type:
bool
- classmethod load(filepath: str | Path | StringIO, name: str | None = None) System [source]¶
Load configuration from file-like object.
- Parameters:
filepath (str or Path or file-like) – Filepath or file-like object (i.e. has a .read() method)
name (str, optional) – Name of the newly created system. If unspecified (default), uses the name contained in filepath.
- Returns:
The loaded system.
- Return type:
- classmethod load_from_dict(name: str, parameters: dict) System [source]¶
Instantiate a System from its name and its parameters.
The construction of the System is done recursively from the lower level. Therefore this function is also called recursively returning to the upper level, the lower System and its connections to the upper System via a dictionary. If no connections are to forwarded the second returned argument is None.
- Parameters:
name (str) – Identifier of the system
parameters (dict) – The dictionary containing the system definition
- Returns:
The generated system
- Return type:
- load_surrogate(filename: str, activate=True) None [source]¶
Loads a surrogate model from a binary file created by dump_surrogate.
- Parameters:
filename (-) – Destination file name.
activate (-) – Boolean determining whether or not surrogate model should be activated once loaded. Default is True.
- log_debug_message(handler: HandlerWithContextFilters, record: logging.LogRecord, format: LogFormat = LogFormat.RAW) bool [source]¶
Callback method on the system to log more detailed information.
This method will be called by the log handler when
log_context()
is active if the logging level is lower or equals to VERBOSE_LEVEL. It allows the object to send additional log message to help debugging a simulation.Note
logger.log method cannot be used here. Use handler.handle(record)
- Parameters:
handler (HandlerWithContextFilters) – Log handler on which additional message should be published.
record (logging.LogRecord) – Log record
format (LogFormat) – Format of the message
- Returns:
Should the provided record be logged?
- Return type:
bool
- make_surrogate(data_in: ~pandas.core.frame.DataFrame | ~typing.Dict[str, ~typing.List[float]], model=<class 'cosapp.utils.surrogate_models.kriging.FloatKrigingSurrogate'>, activate=True, data_out: ~pandas.core.frame.DataFrame | ~typing.Dict[str, ~typing.Any] | None = None, postsynch: str | ~typing.List[str] = '*', *args, **kwargs) SystemSurrogate [source]¶
Creates a surrogate model superseding the normal behaviour of compute(). The surrogate model is trained from datasets data_in and data_out, given as pandas.DataFrame objects, or dictionnaries interpretable as so.
If no output data are provided (default), they are computed as the response of system to design-of-experiment data_in.
- Parameters:
data_in (-) – Design of experiments for variables in dataframe columns or dict keys. Column/key names must match variable contextual names, as in ‘wing.geom.length’, e.g.
model (-) – Model class, implementing methods train(x, y) and predict(x), where x and y are 1D arrays. Default is cosapp.utils.surrogate_models.FloatKrigingSurrogate.
activate (-) – Boolean determining whether or not surrogate model should be activated once created. Default is True.
data_out (-) – Y-dataset used for surrogate model training. Default is None (dataset is computed).
postsynch (-) – List of output variable names to synchronize after each surrogate model execution. Default is ‘*’, meaning all outputs are post-synchronized.
*args (-) –
Additional parameters passed to model constructor.
**kwargs (Any) – Additional parameters passed to model constructor.
Returns
--------
SystemSurrogate – System surrogate attached to the system.
- name2variable: Dict[str, VariableReference]¶
- new_problem(name='problem') MathematicalProblem [source]¶
Create a new, empty MathematicalProblem in the context of system.
- Parameters:
name (str) – Name of the mathematical problem. Defaults to ‘problem’.
- Returns:
The newly created mathematical problem.
- Return type:
- pop_child(name: str) System [source]¶
Remove the subsystem called name.
- Parameters:
name (str) – Name of the subsystem to be removed
- Returns:
The removed subsystem
- Return type:
System
- Raises:
AttributeError –
- pop_name2variable(keys: Iterable[str]) None [source]¶
Remove the given keys from the name mapping dictionary.
The keys will be remove from the local mapping. Then the keys list will be sent upward to the parent System for deletion.
- Parameters:
keys (Iterable[str]) – Keys to remove
- property problem: MathematicalProblem¶
locally defined off-design mathematical problem, without considering sub-system tree.
Raises:¶
AttributeError unless system is being modified by a driver.
- type:
MathematicalProblem
- property properties: Dict[str, Any]¶
list of read-only properties and associated values
- Type:
Dict[str, Any]
- property rates¶
Returns a dictionary containing all time derivatives (rates) in current system tree
- run_once() None [source]¶
Run the system once.
Execute the model of this System and its children in the execution order.
Notes
The drivers are not executed when calling this method; only the physical model.
- save(fp, indent=2, sort_keys=True) None [source]¶
Serialize the System as a JSON formatted stream to fp.
- Parameters:
fp (str or Path or file-like) – A .write()-supporting file-like object or the filename
indent (int, optional) – Indentation in the file (default: 2)
sort_keys (bool, optional) – Sort the keys in alphabetic order (default: False)
- set_clean(direction: PortType) None [source]¶
Set to clean ports of a certain direction.
- Parameters:
direction (PortType) – Direction to set
- set_dirty(direction: PortType) None [source]¶
Set to dirty ports of a certain direction.
- Parameters:
direction (PortType) – Direction to set
- classmethod set_master(name: str, type_checking: bool = True) bool [source]¶
Set the master System
- Parameters:
name (str) – Name of the System calling this context manager
type_checking (bool, optional) – Whether to activate the type checking in the ports or not (default: True)
- Returns:
Is the callee the master System?
- Return type:
bool
- setup(**kwargs) None [source]¶
System port and/or child System are defined in this function.
This function allows to populate a customized System class. The helper functions for the user are:
add_input : add an input port
add_output : add an output port
add_inward : add a inward variable
add_outward : add a outward variable
add_child : add a child System
See also
Examples
Here is an example of System subclassing:
>>> class AdvancedDuct(System): >>> >>> def setup(self): >>> self.add_input(FlowPort, 'in') >>> self.add_output(FlowPort, 'out') >>> self.add_inward({'heat_source': 1.0, >>> 'pressure_loss': 0.01}) >>> self.add_outward('wall_temperature', 400.) >>> >>> self.add_child(AnotherSystem('system2'))
- static str_der(order: int) Callable[[str], str] [source]¶
Derivate name factory.
- Parameters:
order (int) – Derivative order
- Returns:
Function generating the derivate name from the variable name
- Return type:
Callable[[int, ], str]
- tags: ClassVar[FrozenSet[str]] = frozenset({})¶
- to_d3(show=True, size=435) IPython.display.IFrame [source]¶
Returns the hierarchical representation of this system in HTML format.
- Returns:
IFrame to the HTML formatted representation
- Return type:
IPython.display.IFrame
- to_html(filename: str, embeddable=False) None [source]¶
Save the System as HTML using vis.JS library.
- Parameters:
filename (str) – Filename to write to
embeddable (bool, optional) – Is the HTML to be embedded in an existing page? Default: False
- to_json(indent=2, sort_keys=True) str [source]¶
Return a string in JSON format representing the System.
- Parameters:
indent (int, optional) – Indentation of the JSON string (default: 2)
sort_keys (bool, optional) – Sort keys in alphabetic order (default: True)
- Returns:
String in JSON format
- Return type:
str
- property transients¶
Returns a dictionary containing all transient unknowns in current system tree
- transition() None [source]¶
Method describing system transition upon the occurrence of events (if any). Does not do anything by default, but should be implemented for systems with events.
Examples
>>> import numpy as np >>> >>> class PointMassDynamics(System): >>> # Free fall of a point mass, with friction >>> def setup(self): >>> self.add_inward('mass', 1.2, desc='Mass') >>> self.add_inward('cf', 0.1, desc='Friction coefficient') >>> self.add_inward('g', np.r_[0, 0, -9.81], desc='External acceleration field') >>> self.add_outward('a', np.zeros(3), desc='Acceleration') >>> self.add_transient('v', der='a') >>> self.add_transient('x', der='v') >>> >>> def compute(self): >>> v_norm = np.linalg.norm(self.v) >>> self.a = self.g - (self.cf / self.mass * v_norm) * self.v >>> >>> class BouncingPointMass(PointMassDynamics): >>> def setup(self): >>> super().setup() >>> self.add_event('rebound', trigger="x[2] <= 0") >>> >>> def transition(self): >>> if self.rebound.present: >>> self.v[2] *= -1
- update()[source]¶
Perform complex tasks due to data change.
Some parameters may be a file used to initialize a complex object. Updating that parameter may imply the modification of that complex object. This should be done in this method.
Examples
>>> class TableModel(System): >>> >>> def setup(self): >>> # Add a inwards to the file containing the table values >>> self.add_inward('table_file', '{myProject}/ressources/my_table.csv') >>> # Set a object able to interpolate the table >>> self.add_outward('table', Table(self.table_file)) >>> >>> def update(self): >>> # Update the table object as the source file may have been updated. >>> self.table = Table(self.table_file)
Notes
This method is called systematically after the
setup()
call. Otherwise the user is responsible to explicitly call it when needed.