"""Define the System class, used to contain, modify, simulate and plot a model.
"""
importinspect
importnumpyasnp
importnetworkxasnx
...
...
@@ -15,16 +18,17 @@ class System:
"""
Base class for system dynamics.
A System stores two dictionnaries containing all
A System stores 3 dictionnaries containing all
nodes (constants, variables, and functions)
and equations (constan values, updating equations and initialisation equations)
and comments about nodes.
From this dictionnaries, it generates the updating pattern
and run the simulation.
"""
def__init__(self):
"""Initialise an empty System with nodes and equations dictionnaries"""
"""Initialise an empty System with nodes, equations and comments dictionnaries"""
self.nodes={
'cst':set(),
'var':set(),
...
...
@@ -36,67 +40,136 @@ class System:
'update':dict(),
'init':dict()
}
self.comments={}
# Modifiers
# ---------- Modifiers ----------
defadd_node(self,node,node_type):
"""Add a node to the System.
Parameters
----------
node : str
Name of the node.
node_type : str
Type (cst, var, fun) of the node.
"""
self.nodes[node_type].add(node)
defadd_all_nodes(self,all_nodes):
"""Add all nodes in the dictionnary `all_nodes`.
Parameters
----------
all_nodes : dict(str: set(str))
Dictionnary of all nodes to add. Like:
{'cst': {all constant names},
'var': {all variable names},
'fun': {all function names}}
"""
fornode_typeinall_nodes:
fornodeinall_nodes[node_type]:
self.add_node(node,node_type)
defadd_eq(self,node,eq_type,arguments):
"""Add an equation to the System.
Parameters
----------
node : str
Name of the node set by the equation.
eq_type : str
Type (cst, init, update) of the equation.
arguments : dict(str: set)
Arguments needed in the equation. Like:
{'cst': {constant names},
'var': {( variable name, index name)},
'fun': {dict_of_function_infomations}}
"""
# Check if some special functions (clip, step) are in arguments:
forfuninset(arguments['args']['fun']):
iffunnotininstance_fun_namesandfuninglobals():
delarguments['args']['fun'][fun]
self.eqs[eq_type][node]=arguments
defadd_all_eqs(self,all_eqs):
"""Add all equations.
Parameters
----------
all_nodes : dict(str: set(str))
Dictionnary of all equations to add. Like:
{'cst': {node name: equation},
'init': {node name: equation},
'update': {node name: equation}}
"""
foreq_typeinall_eqs:
fornodeinall_eqs[eq_type]:
self.add_eq(node,eq_type,all_eqs[eq_type][node])
defadd_comments(self,comments):
"""Add comments to the System.
Parameters
----------
comments : dict(str: str)
Each node name and its comment.
"""
fornode,commentincomments.items():
self.comments[node]=comment
defadd_units(self,units):
"""Unit of calculs. NOT USED.
"""
self.units=units
# Following functions are not used yet.
# def add_function(self, fun, name=None):
# """Add or reset a function to the system.
# The function should be any of init, update or set, and take the same arguments as defined in the system equations.
defadd_function(self,fun,name=None):
ifnotname:
name=fun.__name__
forsin('_','update','init','set'):
assertnotname.startswith(s),"Fun name shouldn't start with '{s}'"
setattr(self,fun.__name__,fun)
# Parameters
# ----------
# fun : function
# Function taking appropriate arguments and return a value. If name is None, the function name should be one of `init_var`, `upadte_var`, `set_cst` with `var` a variable name and `cst` a constant name.
# name : str
# Name of the function in case we want it different than fun.__name__.
# """
# if not name:
# name = fun.__name__
# for s in ('_', 'update', 'init', 'set'):
# assert not name.startswith(s), "Fun name shouldn't start with '{s}'"