Computing Module
The computing module declares functions and classes to:
Hold numerical values for model quantities.
Declare Expressions to define the Blocks and ModelComponents Flux, InternalExpressions and SavedQuantities
Assemble the global System from those declaration.
Quantities
Define Quantities to represent discretized numeric values along with some convenience functions to handle them.
- class Quantity(value: Any)
Represent discretized values by holding their current and new numeric values.
Examples
>>> scalar = Quantity(0.5) >>> scalar.current == scalar.new # 0.5
>>> vector = Quantity([0.1, 0.2, 0.3]) >>> vector.current == vector.new # [0.1, 0.2, 0.3]
It can also be initialized with numpy arrays
>>> Quantity(np.ones(3)) # [1, 1, 1]
Matrixes are flattened when initializing a quantity: it can only be a scalar or vector.
>>> Quantity(np.ones((2, 2))) # [1, 1, 1, 1]
- property current: T
Get the current value (at step n) of the quantity
- Returns:
The current value
- Return type:
np.float64 | NDArray[np.float64]
- property new: T
Get the new value (at step n + 1) of the quantity
- Returns:
The new value
- Return type:
np.float64 | NDArray[np.float64]
- property size: int
Get the vector size of the quantity value (or 1 for scalars)
- Returns:
The vector size of the quantity
- Return type:
int
- update(new: Any) None
Set the new value (at step n + 1) of the quantity
- Parameters:
new (Any) – The new value
- Raises:
ValueError – Exception raised if the new value and the quantity value are not the same size
Example
>>> q = Quantity(0.5) >>> q.current # 0.5 >>> q.new # 0.5 >>> q.update(0.6) >>> q.current # 0.5 >>> q.new # 0.6
- initialize(value: Any) None
Set the current and new value of the quantity
- Parameters:
value (Any) – The value to set
Example
>>> q = Quantity(0.5) >>> q.update(0.6) >>> q.current # 0.5 >>> q.new # 0.6 >>> q.initialize(0.1) >>> q.current # 0.1 >>> q.new # 0.1
- property operation_value: T
Value used with base operators.
Direct operation are allowed and performed on the
currentvalue of the quantity.- Returns:
the current value
- Return type:
Any
Example
>>> q1 = Quantity(1.0) >>> q2 = Quantity(2.0) >>> q1.update(1.5) # Quantity sum is performed on current value: >>> q1 + q2 # 3.0 >>> q1.initialise(1.5) >>> q1 + q2 # 3.5
In place operators call
initialiseon the QuantityExample
>>> q1 = Quantity(1.0) >>> q1 += 0.5 >>> q1.current # 1.5 >>> q1.new # 1.5
- diff(q: Quantity[T]) T
Compute the difference between the new and the current value of the given Quantity
- Parameters:
q (Quantity) – The quantity
- Returns:
The difference betwen new and current for the quantity
- Return type:
np.float64 | NDArray[np.float64]
Examples
>>> q = Quantity(1.0) >>> diff(q) # 0.0 >>> q.update(1.1) >>> diff(q) # 0.1
- mid_alpha(q: Quantity[Any], scheme_time_shift: Any) Any
Compute the discretized value of the Quantity for a shifted time scheme.
\[x^{n+\alpha} = (\frac{1}{2} - \alpha) x^{n} + (\frac{1}{2} + \alpha) x^{n + 1}\]- Parameters:
q – The quantity
scheme_time_shift (float) – the time shift of the scheme.
- Raises:
ValueError – If scheme_time_shift is not a scalar, exception raised if scheme_time_shift and q are not the same size.
- Returns:
the discretized value of the quantity
- Return type:
np.float64 | NDArray[np.float64]
Example
>>> q = Quantity(1.0) >>> q.update(2.0) >>> mid_alpha(q, 0.25) # 1.75
- mid_point(q: Quantity[Any]) Any
Compute the discretized value of the Quantity for a mid point time scheme
\[x^{n + \frac{1}{2}} = \frac{1}{2} (x^{n} + x^{n + 1})\]- Parameters:
q (Quantity) – Quantity
- Returns:
Discretized value of the quantity
- Return type:
np.float64 | NDArray[np.float64]
Example
>>> q = Quantity(1.0) >>> q.update(2.0) >>> mid_point(q) # 1.5
Models
Declares the ModelComponents and the Block base classes along with objects to hold the Flux, Internal Expressions and Saved Quantities functions.
- SystemFunction
Type alias for functions composing the system
- class Expression(size: int, expr_func: SystemFunction, expr_gradients: Mapping[str, SystemFunction] = {})
Store function computing numerical values for terms in the models with the function result size.
Optionally, it can define a set of function to compute the partial derivatives for a set of variables.
Example
def f1(x1, x2): return 0.5 * x1 + 0.8 * x2 def df1_dx1(x1, x2): return 0.5 def df1_dx2(x1, x2): return 0.8 expression_f1 = Expression( 1, # size f1, # expression function { "x1": df1_dx1, "x2": df1_dx2, } # expressions partial derivatives )
- size: int
Size of the result of the function
- expr_func: SystemFunction
Function to compute the numerical value
- expr_gradients: dict[str, SystemFunction]
Collection of functions to compute the derivatives of the expression for variables
- class TermDefinition(term_id: str, size: int, index: int = 0)
Describe Terms defined in an
Expression.An
Expressionobject can define several Terms.Example
def vector_3d(x1, x2, x3): return [x1, x2, x3] expression_vector = Expression( 3, # size vector_3d # expression function ) x1_term = Term( "x1", # id 1, # term size 0 # starting index in vector expression ) x2_term = Term( "x2", # id 1, # term size 1 # starting index in vector expression ) x3_term = Term( "x3", # id 1, # term size 2 # starting index in vector expression )
- term_id: str
Term id
- size: int
Term size
- index: int = 0
Starting line of the term index in its expression
- class ExpressionDefinition(expression: Expression, terms: list[TermDefinition] = [])
Holds an
Expressionand theTermDefinitioncouple.Example
# Expression Definition for the example above: >>> definition = ExpressionDefinition( expression_vector, [ x1_term, x2_term, x3_term ] )
- expression: Expression
The expression
- terms: list[TermDefinition]
The expressed Terms
- property valid: bool
Check if the definition is complete, meaning a term is associated with each line of the expression and terms do not overlap.
- Returns:
True if the definition is valid, False otherwise
- Return type:
bool
# From example above >>> definition = ExpressionDefinition( expression_vector, [ x1_term, x2_term, x3_term ] ) >>> definition.valid # True >>> overlapping_definition = ExpressionDefinition( expression_vector, [ x1_term, x2_term, x3_term, x1_term # overlapping term on index 0 ] ) >>> overlapping_definition.valid # False >>> incomplete_definition = ExpressionDefinition( expression_vector, [ x1_term, # missing index 1 term x3_term ] ) >>> incomplete_definition.valid # False
- get_term(index: int) TermDefinition
Get term starting in expression at the given index
- Parameters:
index (int) – the first index of the term in the expression.
- Returns:
the term definition
- Return type:
# From example above >>> definition = ExpressionDefinition( expression_vector, [ x1_term, x2_term, x3_term ] ) >>> definition.get_term(0) # x1_term >>> definition.get_term(1) # x2_term >>> definition.get_term(2) # x3_term
- ExpressionsCollection
Type alias for a collection of expressions. Keys are the expression types as strings. Values are a tuple defining the actual expression and a list of Term Definitions it expresses.
- class ModelComponentMetaClass(*args: Any, **kwargs: Any)
Meta-class for
ModelComponent.Defines the model Internal Equations and Saved Quantities using
Expressionobjects.Internal Equations are expressing Internal Variables with a residual equation.
Saved Quantities are given with a direct relation
- property local_ids: list[str]
Get local parameters ids of the model.
Every member of the
ModelComponentannotated withQuantitytype has a local id.- Returns:
the local ids of the parameters
- Return type:
list[str]
Example
@dataclass class SimpleModel(metaclass=ModelComponentMetaClass): x1: Quantity x2: Quantity SimpleModel.local_ids # ["x1", "x2"]
- declares_internal_expression(variable_id: str, expr: Expression, size: int | None = None, index: int = 0) None
Declares a
Expressionobject for an Internal Equation of the model.- Parameters:
term_id (str) – the local id of the variable associated with the expression
expr (Expression) – the associated expression
size (int) – the term size
index (str) – the starting line index of the term in the expression.
Example
@dataclass class SimpleModel(metaclass=ModelComponentMetaClass): x1: Quantity a: Quantity b: Quantity def x1_residual(self): return self.a.current * self.x1.new - b.current def dx1_residual_dx1(self): return self.a x1_expression = Expression( 1, SimpleModel.x1_residual, { "x1": SimpleModel.dx1_residual_dx1 } ) SimpleModel.declare_internal_expression( "x1", # term id x1_expression, # term expression 1, # term size 0 # Term index in the expression )
- property internal_variables: list[TermDefinition]
Get the
TermDefinitionobject describing internal Variables- Returns:
the internal variables term definitions
- Return type:
list[TermDefinition]
- property internal_expressions: list[ExpressionDefinition]
Get the all
Expressionobject describing Internal Equations of the model component.- Returns:
the internal equation expressions
- Return type:
list[ExpressionDefinition]
- get_internal_variable_expression(term_id: str) tuple[Expression, int, int]
Get the
Expressionfor the given Internal Variable local name.- Parameters:
term_id (str) – the term id
- Returns:
the expression, its size and the starting index of the term in the expression.
- Return type:
tuple[Expression, int, int]
- has_internal_variable(variable_id: str) bool
Get if the given name match an Internal Variable of the model component
- Parameters:
variable_id (str) – the id to test
- Returns:
True if the id defines an Internal Variable, False otherwise
- Return type:
bool
- declares_saved_quantity_expression(term_id: str, expr: Expression, size: int | None = None, index: int = 0) None
Add a Saved Quantity
Expressionobject to the model definition.- Parameters:
term_id (str) – the local id of the term.
expr (Expression) – the associated expression
size (int) – the term size
index (str) – the starting line index of the term in the expression.
Example
@dataclass class SimpleModel(metaclass=ModelComponentMetaClass): x1: Quantity def x1_squared(self): return x1.current * x1.current x1_squared_expression = Expression( 1, SimpleModel.x1_squared ) SimpleModel.declares_saved_quantity_expression( "x1_squared", # term id x1_squared_expression, # term expression 1, # term size 0 # Term index in the expression )
- property saved_quantities: list[TermDefinition]
Get the saved quantities expressed by the model
- Returns:
the saved quantities local id and size.
- Return type:
list[tuple[str, int]]
- has_saved_quantity(saved_quantity_id: str) bool
Get if the given id is a saved quantity
- Parameters:
saved_quantity_id (str) – the id to test
- Returns:
True if the id defines a saved quantity, false otherwise
- Return type:
bool
- property saved_quantities_expressions: list[ExpressionDefinition]
Get the all saved quantities expressions
- Returns:
the saved quantities expressions
- Return type:
list[ExpressionDefinition]
- get_saved_quantity_expression(term_id: str) tuple[Expression, int, int]
Get the expression for the given saved quantity local id.
- Parameters:
term_id (str) – the term id
- Returns:
the expression, the starting index of the term in the expression and its size.
- Return type:
tuple[Expression, int, int]
- class ModelComponent
Holds parameters and define functions to compute Internal Equations and Saved Quantities.
- initialize() None
Override this method to define specific for model initialization.
- class BlockMetaClass(*args: Any, **kwargs: Any)
Meta-class for
Block.Extends
ModelComponentMetaClasstype adding FluxExpressionto the model definition.Every Flux is expressed toward the outside of the Block.
Every Local Nodes index of the Block defines one Flux.
Note
BlockMetaClasscan also define Internal Equations and Saved Quantities- declares_flux_expression(node_index: int, variable_id: str, expr: Expression) None
Add a flux expression defining a block external relation.
- Parameters:
node_index (int) – the local node index where the flux is shared
variable_id (str) – the local id of the variable associated to the node.
expr (Expression) – the associated expression
Example
@dataclass class SimpleBlock(metaclass=BlockMetaClass): q0.new: Quantity def flux_0(self): return q0.new def dflux_0_dq0(self): return 1.0 flux_0_expression = Expression( 1, SimpleBlock.flux_0, { "q0": SimpleBlock.dflux_0_dq0 } ) SimpleBlock.declares_flux_expression( 0, # Local Node index, "potential_0", # Associated DOF id flux_0_expression, # flux expression )
- property nodes: list[int]
Get all the local nodes indexes.
- Returns:
The list of indexes.
- Return type:
list[int]
- property fluxes_expressions: dict[int, ExpressionDefinition]
Get all the fluxes expressions in the block with the local node where they are shared.
- Returns:
the fluxes exressions ordered by node index.
- Return type:
dict[int, ExpressionDefinition]
- property external_variables_ids: list[str]
Get local id of variables defined by the flux connecting to a node in the block.
- Returns:
a list of all local external variables ids.
- Return type:
list[str]
- class Block
Extends
ModelComponentand declare functions to compute Flux.
Assembling
Allows to build systems that computes residual and gradient from collections of functions.
- class EqSystem(size: int)
Global Equation system
Allows to compute the numerical value of the residual and the gradient for a
Net.The system is built from a collection of System Parts. The parts are summed in a global system to compute the numerical value of the residual and the gradient.
- property system_size: int
Get the system size
- Returns:
the system size
- Return type:
int
- add_system_part(self, residual_index: int, residual_size: int, residual_func: SystemFunction, gradients_func: dict[int, SystemFunction], parameters: Any)
Add an equation system part to the global system.
- Parameters:
residual_index (int) – the line index where to sum the function in the global system
residual_size (int) – the size of the result of the residual_func
residual_func (SystemFunction) – the function to compute the residual part
gradients_func – the functions to compute the gradients parts associated with the index of the variable in the state vector
parameters (Any) – the parameters needed to compute the SystemFunctions (both residual and gradient) (should be the same type as the argument of the residual_func and the gradients_func input type)
- Raises:
ValueError – Raises a ValueError when either the size of the residual or the gradient part will exceed the global system size.
- compute_residual() NDArray[np.float64]
Compute the numerical value of the residual.
- Returns:
the residual
- Return type:
NDArray[np.float64]
- compute_gradient() NDArray[np.float64]
Compute the numerical value of the gradient.
- Returns:
the gradient
- Return type:
NDArray[np.float64]