From 9d2ea973f24eff195c48aeef2c194be1301275fd Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 14:17:24 +0200 Subject: [PATCH 01/14] Fresh clone of casadi_daebuilder.jinja from casadi_sx.jinja Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 292 +++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 test/templates/casadi_daebuilder.jinja diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja new file mode 100644 index 0000000..43bf4fe --- /dev/null +++ b/test/templates/casadi_daebuilder.jinja @@ -0,0 +1,292 @@ +{%- macro render_class(class) %} +class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(BaseModel): + """ + {{ class.description }} + """ + + def __init__(self): + super().__init__() + + # declare constants + {%- for const in class.c %} + {%- set comp = class.components[const] %} + {{ comp.name }} = {{ comp.start_value.data[0] }} + {%- endfor %} + + # declare parameters + {{ render_symbols(class, class.p) | indent(4) }} + {{ render_vector("self.p", class, class.p) | indent(12) }} + + # declare parameter start values + {{ render_vector_start_dict("self.p0", class, class.p) | indent(4) }} + + # declare discrete states + {{ render_symbols(class, class.z) | indent(4) }} + {{ render_vector("self.z", class, class.z) | indent(12) }} + + # declare discrete states start values + {{ render_vector_start_dict("self.z0", class, class.z) | indent(4) }} + + # declare inputs + {{ render_symbols(class, class.u) | indent(4) }} + {{ render_vector("self.u", class, class.u) | indent(12) }} + + # declare outputs + {{ render_zero_symbols(class, class.y) | indent(4) }} + {{ render_vector("self.y", class, class.y) | indent(12) }} + + # declare internal variables + {{ render_symbols(class, class.w) | indent(4) }} + + # declare continuous states + {{ render_symbols(class, class.x) | indent(4) }} + {{ render_vector("self.x", class, class.x) | indent(12) }} + + # declare continuous states start values + {{ render_vector_start_dict("self.x0", class, class.x) | indent(4) }} + + # algorithmic + {{ render_statement_list(class.algorithm) | indent(4) }} + + # algebraic + {{ render_statement_list(class.algebric) | indent(4) }} + + # ode + {{ render_ordermap_expression("self.ode", class.ode, class.x) | indent(8) }} + +{% if class.class_type == "Function" %} + # build function + self.F = ca.Function("{{ class.name }}", [self.u], [self.y], ['u'], ['y']) + + def __call__(self, *args): + return self.F(ca.vertcat(*args)) + +# callable function singleton +{{ class.name }} = __{{ class .name }}() + +{% endif %} +{%- endmacro %} + +{%- macro render_ndarray(array) -%} + {%- if array.dim | length == 1 -%} + {%- if array.dim == [1] -%} + {{ array.data[0] }} + {%- else -%} + {{ "{" }}{%- for i in range(array.dim[0]) -%} + {{ array.data[i]}}{% if not loop.last %},{% endif -%} + {%- endfor -%}{{ "}" }} + {%- endif -%} + {%- else -%} + {{ "{" }}{%- for i in range(array.dim[0]) -%} + {{ render_ndarray(array[i]) }}{% if not loop.last %},{% endif -%} + {%- endfor -%}{{ "}" }} + {%- endif -%} +{%- endmacro -%} + +{%- macro render_symbols(class, var_list) -%} + {%- for var in var_list -%} + {{ var }} = ca.SX.sym('{{ var }}' + {%- set comp = class.components[var] -%} + {%- if comp.array_subscripts | length > 0 -%}{{ ", " }} + {%- for sub in comp.array_subscripts -%} + {{ render_subscript(sub) -}}{% if not loop.last %},{% endif -%} + {%- endfor -%} + {%- endif -%}) + {% endfor -%} +{%- endmacro -%} + +{%- macro render_zero_symbols(class, var_list) -%} + {%- for var in var_list -%} + {%- set comp = class.components[var] -%} + {{- var }} = ca.SX.zeros( + {%- if comp.array_subscripts | length > 0 -%} + {%- for sub in comp.array_subscripts -%} + {{ render_subscript(sub) }}{% if not loop.last %},{% endif -%} + {%- endfor -%} + {%- endif -%}) + {% endfor -%} +{%- endmacro -%} + +{%- macro render_vector(target, class, var_list) -%} + {{ target }} = ca.vertcat( + {%- for var in var_list %}{{"\n"}} + {{- var }}{% if not loop.last %},{% endif %} + {%- endfor -%}) +{%- endmacro -%} + +{%- macro render_vector_start_dict(target, class, var_list) -%} + {{ target }} = { + {%- for var in var_list %} + {%- set comp = class.components[var]%} + '{{ var }}': {{ render_ndarray(comp.start_value) | indent(8) -}} + {% if not loop.last %},{% endif %} + {%- endfor %} + } +{%- endmacro -%} + +{%- macro render_ordermap_expression(target, map, var_list) -%} + {{ target }} = ca.vertcat( + {% for var in var_list -%} + {%- set expr = map[var] -%} + {{ render_expression(expr=expr) }}{% if not loop.last %},{% endif %} + {% endfor -%}) +{%- endmacro -%} + +{%- macro render_vector_expression(target, expr_list) -%} + {{ target }} = ca.vertcat( + {% for expr in expr_list -%} + {{ render_expression(expr=expr) }}{% if not loop.last %},{% endif %} + {% endfor -%}) +{%- endmacro -%} + +{%- macro render_binary(op, expr) -%} + {{ render_expression(expr=expr.lhs) }}{{ op }}{{ render_expression(expr=expr.rhs) -}} +{%- endmacro -%} + +{%- macro render_unary(op, expr) -%} + {{ op }}{{ render_expression(expr=expr.rhs) -}} +{%- endmacro -%} + +{%- macro render_subscript(sub) -%} + {%- for key, value in sub | items -%} + {%- if key == "Expression" -%} + {{ render_expression(expr=sub.Expression) | int }} + {%- elif key == "Colon" -%} + : + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_component_reference(comp) -%} + {%- if comp.local %}.{% endif -%} + {%- for part in comp.parts -%} + {{ part.name }} + {%- if part.array_subscripts | length > 0 %}[ + {%- for sub in part.array_subscripts -%} + {#- handles index from 1 to 0 from Modelica to python-#} + {{ render_subscript(sub) | int -1 }}{% if not loop.last -%}, {% endif %} + {%- endfor -%}] + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_expression(expr) -%} + {%- for key, value in expr | items -%} + {%- if key == "UnsignedReal" -%} + {{ value }} + {%- elif key == "UnsignedInteger" -%} + {{ value }} + {%- elif key == "Ref" -%} + {{ render_component_reference(comp=value.comp) }} + {%- elif key == "Add" -%} + {{ render_binary(op=" + ", expr=value) -}} + {%- elif key == "Sub" -%} + {{ render_binary(op=" - ", expr=value) -}} + {%- elif key == "Mul" -%} + {{ render_binary(op="*", expr=value) -}} + {%- elif key == "Div" -%} + {{ render_binary(op="/", expr=value) -}} + {%- elif key == "Exp" -%} + {{- render_binary(op="^", expr=value) -}} + {%- elif key == "Negative" -%} + {{ render_unary(op="-", expr=value) -}} + {%- elif key == "Parenthesis" -%} + ( {{- render_expression(expr=value.rhs) -}} ) + {%- elif key == "Not" %} + {{- render_unary(op="!", expr=value) -}} + {%- elif key == "Or" -%} + ca.logic_or( + {{- render_expression(expr=value.lhs) -}}, + {{- render_expression(expr=value.rhs) -}}) + {%- elif key == "And" -%} + ca.logic_and( + {{- render_expression(expr=value.lhs) -}}, + {{- render_expression(expr=value.rhs) -}}) + {%- elif key == "Equal" -%} + {{- render_expression(expr=value.lhs) -}} == + {{- render_expression(expr=value.rhs) -}} + {%- elif key == "ArrayArguments" -%} + ca.vertcat( + {%- for arg in value.args -%} + {{- "\n " }} {{ render_expression(expr=arg) }} {%- if not loop.last -%},{% endif %} + {%- endfor -%}) + {%- elif key == "FunctionCall" -%} + {{ value.comp.name }}( + {%- for arg in value.args -%} + {{ render_expression(expr=arg) }} {% if not loop.last -%}, {% endif %} + {%- endfor -%}) + {%- else -%} + {{ warn("unknown expression: " + key + value | pprint) }} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_statement_list(stmt_list) -%} + {%- for stmt in stmt_list -%} + {{ render_statement(stmt=stmt) }} + {% endfor -%} +{%- endmacro -%} + +{%- macro render_statement(stmt) -%} + {%- for key, value in stmt | items -%} + {%- if key == "Assignment" -%} + {{ render_component_reference(comp=value.comp) }} = {{ render_expression(expr=value.rhs) }} + {%- else -%} + {{ warn("unknown statement: " + key) }} + {%- endif %} + {%- endfor -%} +{%- endmacro -%} +# rumoca pkg version : {{ def.rumoca_version }} +# rumoca git version : {{ def.rumoca_git_hash }} +# template md5 : {{ def.template_md5 }} +# model md5 : {{ def.model_md5 }} + +import casadi as ca +import numpy as np + + +class BaseModel: + + def __init__(self): + pass + + def __repr__(self): + return repr(self.__dict__) + + def simulate(self, t=None, u=None): + if t is None: + t = np.arange(0, 1, 0.01) + if u is None: + u = 0 + + p0 = np.array([self.p0[k] for k in self.p0.keys()]) + z0 = np.array([self.z0[k] for k in self.z0.keys()]) + x0 = np.array([self.x0[k] for k in self.x0.keys()]) + + F = ca.integrator( + 'F', 'idas', + {'x': self.x, 'z': self.z, 'p': self.p, 'u': self.u, 'ode': self.ode, 'alg': self.alg}, + t[0], t) + + res = F(x0=x0, z0=z0, p=p0, u=u) + return { + 't': t, + 'x': res['xf'].T + } + + def linearize(self): + A = ca.jacobian(self.ode, self.x) + B = ca.jacobian(self.ode, self.u) + C = ca.jacobian(self.y, self.x) + D = ca.jacobian(self.y, self.u) + return (A, B, C, D) + + +def cat(axis, *args): + return ca.vertcat(*args) + + +{%- for key, val in def.classes | items %} + +{{ render_class(class=val) }} +{%- endfor %} From 6e7eaa1d0de7d94011d07f5a9f221291db657d59 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 14:42:35 +0200 Subject: [PATCH 02/14] Creating DaeBuilder symbols instead of SX symbols Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 66 +++++++------------------- 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 43bf4fe..f2527f1 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -5,30 +5,30 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas """ def __init__(self): - super().__init__() + super().__init__('{{ class.name }}') - # declare constants + # Constants {%- for const in class.c %} {%- set comp = class.components[const] %} {{ comp.name }} = {{ comp.start_value.data[0] }} {%- endfor %} - # declare parameters - {{ render_symbols(class, class.p) | indent(4) }} + # Parameters + {{ render_variables(class, class.p, "p") | indent(4) }} {{ render_vector("self.p", class, class.p) | indent(12) }} # declare parameter start values {{ render_vector_start_dict("self.p0", class, class.p) | indent(4) }} - # declare discrete states - {{ render_symbols(class, class.z) | indent(4) }} + # Discrete states + {{ render_variables(class, class.z, "x") | indent(4) }} {{ render_vector("self.z", class, class.z) | indent(12) }} # declare discrete states start values {{ render_vector_start_dict("self.z0", class, class.z) | indent(4) }} # declare inputs - {{ render_symbols(class, class.u) | indent(4) }} + {{ render_variables(class, class.u, "u") | indent(4) }} {{ render_vector("self.u", class, class.u) | indent(12) }} # declare outputs @@ -36,10 +36,10 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {{ render_vector("self.y", class, class.y) | indent(12) }} # declare internal variables - {{ render_symbols(class, class.w) | indent(4) }} + {{ render_variables(class, class.w, "w") | indent(4) }} # declare continuous states - {{ render_symbols(class, class.x) | indent(4) }} + {{ render_variables(class, class.x, "x") | indent(4) }} {{ render_vector("self.x", class, class.x) | indent(12) }} # declare continuous states start values @@ -83,15 +83,15 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- endif -%} {%- endmacro -%} -{%- macro render_symbols(class, var_list) -%} +{%- macro render_variables(class, var_list, ca_type) -%} {%- for var in var_list -%} - {{ var }} = ca.SX.sym('{{ var }}' + self.dae.add('{{ var }}', dict(type = '{{ca_type}}' {%- set comp = class.components[var] -%} - {%- if comp.array_subscripts | length > 0 -%}{{ ", " }} + {%- if comp.array_subscripts | length > 0 -%}{{ ", dimension = [" }} {%- for sub in comp.array_subscripts -%} {{ render_subscript(sub) -}}{% if not loop.last %},{% endif -%} {%- endfor -%} - {%- endif -%}) + {{ "]" }}{%- endif -%})) {% endfor -%} {%- endmacro -%} @@ -247,44 +247,12 @@ import numpy as np class BaseModel: - def __init__(self): - pass + def __init__(self, name): + # Underlying DaeBuilder instance + self.dae = ca.DaeBuilder(name) def __repr__(self): - return repr(self.__dict__) - - def simulate(self, t=None, u=None): - if t is None: - t = np.arange(0, 1, 0.01) - if u is None: - u = 0 - - p0 = np.array([self.p0[k] for k in self.p0.keys()]) - z0 = np.array([self.z0[k] for k in self.z0.keys()]) - x0 = np.array([self.x0[k] for k in self.x0.keys()]) - - F = ca.integrator( - 'F', 'idas', - {'x': self.x, 'z': self.z, 'p': self.p, 'u': self.u, 'ode': self.ode, 'alg': self.alg}, - t[0], t) - - res = F(x0=x0, z0=z0, p=p0, u=u) - return { - 't': t, - 'x': res['xf'].T - } - - def linearize(self): - A = ca.jacobian(self.ode, self.x) - B = ca.jacobian(self.ode, self.u) - C = ca.jacobian(self.y, self.x) - D = ca.jacobian(self.y, self.u) - return (A, B, C, D) - - -def cat(axis, *args): - return ca.vertcat(*args) - + return repr(self.dae) {%- for key, val in def.classes | items %} From d6a4670e5bb744ae0feb99e60c87415127466bec Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 14:55:06 +0200 Subject: [PATCH 03/14] [DaeBuilder] Setting parameter values with assign Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index f2527f1..01ed329 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -15,10 +15,9 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas # Parameters {{ render_variables(class, class.p, "p") | indent(4) }} - {{ render_vector("self.p", class, class.p) | indent(12) }} - # declare parameter start values - {{ render_vector_start_dict("self.p0", class, class.p) | indent(4) }} + # Parameter bindings + {{ render_bindings(class, class.p) | indent(4) }} # Discrete states {{ render_variables(class, class.z, "x") | indent(4) }} @@ -114,6 +113,13 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- endfor -%}) {%- endmacro -%} +{%- macro render_bindings(class, var_list) -%} + {%- for var in var_list -%} + {%- set comp = class.components[var] -%} + self.dae.assign('{{ var }}', {{ render_ndarray(comp.start_value) | indent(4) }}) + {% endfor -%} +{%- endmacro -%} + {%- macro render_vector_start_dict(target, class, var_list) -%} {{ target }} = { {%- for var in var_list %} From cca6056944f4fbd70e8c9f72f0f841c12b9bb665 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 14:57:17 +0200 Subject: [PATCH 04/14] [DaeBuilder] Setting constant values with assign Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 01ed329..531d40c 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -8,15 +8,15 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas super().__init__('{{ class.name }}') # Constants - {%- for const in class.c %} - {%- set comp = class.components[const] %} - {{ comp.name }} = {{ comp.start_value.data[0] }} - {%- endfor %} + {{ render_variables(class, class.c, "c") | indent(4) }} + + # Constant values + {{ render_bindings(class, class.c) | indent(4) }} # Parameters {{ render_variables(class, class.p, "p") | indent(4) }} - # Parameter bindings + # Parameter values {{ render_bindings(class, class.p) | indent(4) }} # Discrete states From c8d342ddb9a10a1e33151921e6268ebbe6f1f54c Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 14:59:30 +0200 Subject: [PATCH 05/14] [DaeBuilder] Setting start values Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 32 +++++++++++--------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 531d40c..3cfa928 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -21,28 +21,25 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas # Discrete states {{ render_variables(class, class.z, "x") | indent(4) }} - {{ render_vector("self.z", class, class.z) | indent(12) }} - # declare discrete states start values - {{ render_vector_start_dict("self.z0", class, class.z) | indent(4) }} + # Discrete states start values + {{ render_start(class, class.z) | indent(4) }} - # declare inputs + # Inputs {{ render_variables(class, class.u, "u") | indent(4) }} - {{ render_vector("self.u", class, class.u) | indent(12) }} - # declare outputs + # Outputs {{ render_zero_symbols(class, class.y) | indent(4) }} {{ render_vector("self.y", class, class.y) | indent(12) }} - # declare internal variables + # Internal variables {{ render_variables(class, class.w, "w") | indent(4) }} - # declare continuous states + # Differential states {{ render_variables(class, class.x, "x") | indent(4) }} - {{ render_vector("self.x", class, class.x) | indent(12) }} - # declare continuous states start values - {{ render_vector_start_dict("self.x0", class, class.x) | indent(4) }} + # Differential states start values + {{ render_start(class, class.x) | indent(4) }} # algorithmic {{ render_statement_list(class.algorithm) | indent(4) }} @@ -120,14 +117,11 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {% endfor -%} {%- endmacro -%} -{%- macro render_vector_start_dict(target, class, var_list) -%} - {{ target }} = { - {%- for var in var_list %} - {%- set comp = class.components[var]%} - '{{ var }}': {{ render_ndarray(comp.start_value) | indent(8) -}} - {% if not loop.last %},{% endif %} - {%- endfor %} - } +{%- macro render_start(class, var_list) -%} + {%- for var in var_list -%} + {%- set comp = class.components[var] -%} + self.dae.set_start('{{ var }}', {{ render_ndarray(comp.start_value) | indent(4) }}) + {% endfor -%} {%- endmacro -%} {%- macro render_ordermap_expression(target, map, var_list) -%} From c8a67339367f2c9965a40888bcdf27407555d669 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 15:04:51 +0200 Subject: [PATCH 06/14] [DaeBuilder] Output symbols Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 3cfa928..d0c6835 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -29,8 +29,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {{ render_variables(class, class.u, "u") | indent(4) }} # Outputs - {{ render_zero_symbols(class, class.y) | indent(4) }} - {{ render_vector("self.y", class, class.y) | indent(12) }} + {{ render_variables(class, class.y, "y") | indent(4) }} # Internal variables {{ render_variables(class, class.w, "w") | indent(4) }} From 6da4821dece84dd37ddab83f5ce9b00b46924ade Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 15:06:00 +0200 Subject: [PATCH 07/14] [DaeBuilder] Removed dead code Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index d0c6835..668578a 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -90,25 +90,6 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {% endfor -%} {%- endmacro -%} -{%- macro render_zero_symbols(class, var_list) -%} - {%- for var in var_list -%} - {%- set comp = class.components[var] -%} - {{- var }} = ca.SX.zeros( - {%- if comp.array_subscripts | length > 0 -%} - {%- for sub in comp.array_subscripts -%} - {{ render_subscript(sub) }}{% if not loop.last %},{% endif -%} - {%- endfor -%} - {%- endif -%}) - {% endfor -%} -{%- endmacro -%} - -{%- macro render_vector(target, class, var_list) -%} - {{ target }} = ca.vertcat( - {%- for var in var_list %}{{"\n"}} - {{- var }}{% if not loop.last %},{% endif %} - {%- endfor -%}) -{%- endmacro -%} - {%- macro render_bindings(class, var_list) -%} {%- for var in var_list -%} {%- set comp = class.components[var] -%} @@ -131,13 +112,6 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {% endfor -%}) {%- endmacro -%} -{%- macro render_vector_expression(target, expr_list) -%} - {{ target }} = ca.vertcat( - {% for expr in expr_list -%} - {{ render_expression(expr=expr) }}{% if not loop.last %},{% endif %} - {% endfor -%}) -{%- endmacro -%} - {%- macro render_binary(op, expr) -%} {{ render_expression(expr=expr.lhs) }}{{ op }}{{ render_expression(expr=expr.rhs) -}} {%- endmacro -%} From 6dc444df6968453a8ba84ae61f64ad22fc1372fc Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 15:16:19 +0200 Subject: [PATCH 08/14] [DaeBuilder] Passing differential equations Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 668578a..6825ddd 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -40,14 +40,14 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas # Differential states start values {{ render_start(class, class.x) | indent(4) }} - # algorithmic + # Algorithmic statements {{ render_statement_list(class.algorithm) | indent(4) }} - # algebraic + # Algebraic equations {{ render_statement_list(class.algebric) | indent(4) }} - # ode - {{ render_ordermap_expression("self.ode", class.ode, class.x) | indent(8) }} + # Differential equations + {{ render_ode(class.ode, class.x) | indent(4) }} {% if class.class_type == "Function" %} # build function @@ -93,7 +93,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- macro render_bindings(class, var_list) -%} {%- for var in var_list -%} {%- set comp = class.components[var] -%} - self.dae.assign('{{ var }}', {{ render_ndarray(comp.start_value) | indent(4) }}) + self.dae.bind('{{ var }}', {{ render_ndarray(comp.start_value) | indent(4) }}) {% endfor -%} {%- endmacro -%} @@ -104,12 +104,11 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {% endfor -%} {%- endmacro -%} -{%- macro render_ordermap_expression(target, map, var_list) -%} - {{ target }} = ca.vertcat( - {% for var in var_list -%} - {%- set expr = map[var] -%} - {{ render_expression(expr=expr) }}{% if not loop.last %},{% endif %} - {% endfor -%}) +{%- macro render_ode(map, var_list) -%} + {%- for var in var_list -%} + {%- set expr = map[var] -%} + self.dae.bind(self.dae.der('{{ var }}'), {{ render_expression(expr=expr) }}) + {% endfor -%} {%- endmacro -%} {%- macro render_binary(op, expr) -%} From 45ebe107e3b43ddcd2d06d84eea72d2db2f51d66 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 15:43:28 +0200 Subject: [PATCH 09/14] [DaeBuilder] Refactored assignments Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 6825ddd..bd03ce5 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -202,9 +202,9 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- macro render_statement(stmt) -%} {%- for key, value in stmt | items -%} {%- if key == "Assignment" -%} - {{ render_component_reference(comp=value.comp) }} = {{ render_expression(expr=value.rhs) }} + self.dae.bind('{{ render_component_reference(comp=value.comp) }}', {{ render_expression(expr=value.rhs) }}) {%- else -%} - {{ warn("unknown statement: " + key) }} + {{ warn("unknown statement: " + key) }} {%- endif %} {%- endfor -%} {%- endmacro -%} From 9139a3d6c59ae34343ed8f9cc964f127587a7b94 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 15:46:41 +0200 Subject: [PATCH 10/14] [DaeBuilder] Refactored referencing Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index bd03ce5..2ccd975 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -51,7 +51,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {% if class.class_type == "Function" %} # build function - self.F = ca.Function("{{ class.name }}", [self.u], [self.y], ['u'], ['y']) + #self.F = ca.Function("{{ class.name }}", [self.u], [self.y], ['u'], ['y']) def __call__(self, *args): return self.F(ca.vertcat(*args)) @@ -149,7 +149,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- elif key == "UnsignedInteger" -%} {{ value }} {%- elif key == "Ref" -%} - {{ render_component_reference(comp=value.comp) }} + self.dae('{{ render_component_reference(comp=value.comp) }}') {%- elif key == "Add" -%} {{ render_binary(op=" + ", expr=value) -}} {%- elif key == "Sub" -%} From 979772380eafa48402ceebbaa6cd266ec2a1e9e8 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 16:23:17 +0200 Subject: [PATCH 11/14] [DaeBuilder] Calling not implemented Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 2ccd975..069b21e 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -50,11 +50,8 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {{ render_ode(class.ode, class.x) | indent(4) }} {% if class.class_type == "Function" %} - # build function - #self.F = ca.Function("{{ class.name }}", [self.u], [self.y], ['u'], ['y']) - def __call__(self, *args): - return self.F(ca.vertcat(*args)) + raise NotImplementedError # callable function singleton {{ class.name }} = __{{ class .name }}() From 6d3a4edf7cd78a530e9fda7f68c1a13313cff137 Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 16:38:32 +0200 Subject: [PATCH 12/14] [DaeBuilder] No space after , in composite name Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 069b21e..4c02076 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -133,7 +133,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- if part.array_subscripts | length > 0 %}[ {%- for sub in part.array_subscripts -%} {#- handles index from 1 to 0 from Modelica to python-#} - {{ render_subscript(sub) | int -1 }}{% if not loop.last -%}, {% endif %} + {{ render_subscript(sub) | int -1 }}{% if not loop.last -%},{% endif %} {%- endfor -%}] {%- endif -%} {%- endfor -%} From ce5a37cefc4e2c8861be00221d5bbf1d0dd457ac Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 16:46:26 +0200 Subject: [PATCH 13/14] [DaeBuilder] Separate reference arguments in assignment and references Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 4c02076..14fbf96 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -129,11 +129,11 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- macro render_component_reference(comp) -%} {%- if comp.local %}.{% endif -%} {%- for part in comp.parts -%} - {{ part.name }} - {%- if part.array_subscripts | length > 0 %}[ + '{{ part.name }}' + {%- if part.array_subscripts | length > 0 %}, [ {%- for sub in part.array_subscripts -%} {#- handles index from 1 to 0 from Modelica to python-#} - {{ render_subscript(sub) | int -1 }}{% if not loop.last -%},{% endif %} + {{ render_subscript(sub) | int -1 }}{% if not loop.last -%}, {% endif %} {%- endfor -%}] {%- endif -%} {%- endfor -%} @@ -146,7 +146,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- elif key == "UnsignedInteger" -%} {{ value }} {%- elif key == "Ref" -%} - self.dae('{{ render_component_reference(comp=value.comp) }}') + self.dae({{ render_component_reference(comp=value.comp) }}) {%- elif key == "Add" -%} {{ render_binary(op=" + ", expr=value) -}} {%- elif key == "Sub" -%} @@ -199,7 +199,7 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- macro render_statement(stmt) -%} {%- for key, value in stmt | items -%} {%- if key == "Assignment" -%} - self.dae.bind('{{ render_component_reference(comp=value.comp) }}', {{ render_expression(expr=value.rhs) }}) + self.dae.bind({{ render_component_reference(comp=value.comp) }}, {{ render_expression(expr=value.rhs) }}) {%- else -%} {{ warn("unknown statement: " + key) }} {%- endif %} From 87f3eb7cc4b6422f9e7f0596b14d23c79ee677aa Mon Sep 17 00:00:00 2001 From: Joel Andersson Date: Wed, 15 Jan 2025 16:53:57 +0200 Subject: [PATCH 14/14] [DaeBuilder] Square brackets instead of curly braces for ndarrays Signed-off-by: Joel Andersson --- test/templates/casadi_daebuilder.jinja | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/templates/casadi_daebuilder.jinja b/test/templates/casadi_daebuilder.jinja index 14fbf96..e140894 100644 --- a/test/templates/casadi_daebuilder.jinja +++ b/test/templates/casadi_daebuilder.jinja @@ -64,14 +64,14 @@ class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(Bas {%- if array.dim == [1] -%} {{ array.data[0] }} {%- else -%} - {{ "{" }}{%- for i in range(array.dim[0]) -%} + {{ "[" }}{%- for i in range(array.dim[0]) -%} {{ array.data[i]}}{% if not loop.last %},{% endif -%} - {%- endfor -%}{{ "}" }} + {%- endfor -%}{{ "]" }} {%- endif -%} {%- else -%} - {{ "{" }}{%- for i in range(array.dim[0]) -%} + {{ "[" }}{%- for i in range(array.dim[0]) -%} {{ render_ndarray(array[i]) }}{% if not loop.last %},{% endif -%} - {%- endfor -%}{{ "}" }} + {%- endfor -%}{{ "]" }} {%- endif -%} {%- endmacro -%}