andes.core.block.Block#
- class andes.core.block.Block(name: str | None = None, tex_name: str | None = None, info: str | None = None, namespace: str = 'local')[source]#
Base class for control blocks.
Blocks are meant to be instantiated as Model attributes to provide pre-defined equation sets. Subclasses must overload the __init__ method to take custom inputs. Subclasses of Block must overload the define method to provide initialization and equation strings. Exported variables, services and blocks must be constructed into a dictionary
self.varsat the end of the constructor.Blocks can be nested. A block can have blocks but itself as attributes and therefore reuse equations. When a block has sub-blocks, the outer block must be constructed with a``name``.
Nested block works in the following way: the parent block modifies the sub-block's
nameattribute by prepending the parent block's name at the construction phase. The parent block then exports the sub-block as a whole. When the parent Model class picks up the block, it will recursively import the variables in the block and the sub-blocks correctly. See the example section for details.- Parameters:
- namestr, optional
Block name
- tex_namestr, optional
Block LaTeX name
- infostr, optional
Block description.
- namespacestr, local or parent
Namespace of the exported elements. If 'local', the block name will be prepended by the parent. If 'parent', the original element name will be used when exporting.
Warning
It is a good practice to avoid more than one level of nesting, to avoid multi-underscore variable names.
Examples
Example for two-level nested blocks. Suppose we have the following hierarchy
SomeModel instance M contains an instance of LeadLag block named A, which contains a Lag instance named B. Both A and B exports two variables
xandy.In the code for SomeModel, the following code is used to instantiate LeadLag
class SomeModel: def __init__(...) ... self.A = LeadLag(name='A', u=self.foo1, T1=self.foo2, T2=self.foo3)
To use Lag in the LeadLag code, the following lines are found in the constructor of LeadLag
class LeadLag: def __init__(name, ...) ... self.B = Lag(u=self.y, K=self.K, T=self.T) # register `self.B` with the name `A` self.vars = {..., 'B': self.B}
When instantiating any block instance, its
__setattr__function assigns names to exported variables and blocks. For the LeadLag instance with the nameA, its member attributeBis assigned the nameA_Bby convention. That is,A_Bwill be set to B.name.When A is picked up by
SomeModel.__setattr__, B is captured from A's exports with the nameA_B. Recursively, B's variables are exported, Recall that B.name is nowA_B, following the naming rule (parent block's name + variable name), B's internal variables becomeA_B_xandA_B_y.Again, the LeadLag instance name (
A.namein this example) must be given when instantiating in SomeModel's constructor to ensure correct name propagation. If there is more than one level of nesting, other than the terminal-level block, all names of the parent blocks must be provided at instantiation.In such a way, B's
define()needs no modification since the naming rule is the same. For example, B's internal y is always{self.name}_y, although the nested B has gotten a new nameA_B.- __init__(name: str | None = None, tex_name: str | None = None, info: str | None = None, namespace: str = 'local')[source]#
Methods
define()Function for setting the initialization and equation strings for internal variables.
enforce_tex_name(fields)Enforce tex_name is not None
export()Method for exporting instances defined in this class in a dictionary.
f_numeric(**kwargs)Function call to update differential equation values.
g_numeric(**kwargs)Function call to update algebraic equation values.
j_numeric(**kwargs)Per-iteration numerical Jacobian update.
j_reset()Helper function to clear the lists holding the numerical Jacobians.
j_setup()One-time Jacobian sparsity pattern and constant value setup.
Attributes
class_nameReturn the class name.