Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 229 additions & 0 deletions test/templates/casadi_daebuilder.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
{%- macro render_class(class) %}
class {% if class.class_type == "Function" -%}__{% endif -%}{{ class.name }}(BaseModel):
"""
{{ class.description }}
"""

def __init__(self):
super().__init__('{{ class.name }}')

# Constants
{{ 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 values
{{ render_bindings(class, class.p) | indent(4) }}

# Discrete states
{{ render_variables(class, class.z, "x") | indent(4) }}

# Discrete states start values
{{ render_start(class, class.z) | indent(4) }}

# Inputs
{{ render_variables(class, class.u, "u") | indent(4) }}

# Outputs
{{ render_variables(class, class.y, "y") | indent(4) }}

# Internal variables
{{ render_variables(class, class.w, "w") | indent(4) }}

# Differential states
{{ render_variables(class, class.x, "x") | indent(4) }}

# Differential states start values
{{ render_start(class, class.x) | indent(4) }}

# Algorithmic statements
{{ render_statement_list(class.algorithm) | indent(4) }}

# Algebraic equations
{{ render_statement_list(class.algebric) | indent(4) }}

# Differential equations
{{ render_ode(class.ode, class.x) | indent(4) }}

{% if class.class_type == "Function" %}
def __call__(self, *args):
raise NotImplementedError

# 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_variables(class, var_list, ca_type) -%}
{%- for var in var_list -%}
self.dae.add('{{ var }}', dict(type = '{{ca_type}}'
{%- set comp = class.components[var] -%}
{%- if comp.array_subscripts | length > 0 -%}{{ ", dimension = [" }}
{%- for sub in comp.array_subscripts -%}
{{ render_subscript(sub) -}}{% if not loop.last %},{% endif -%}
{%- endfor -%}
{{ "]" }}{%- endif -%}))
{% endfor -%}
{%- endmacro -%}

{%- macro render_bindings(class, var_list) -%}
{%- for var in var_list -%}
{%- set comp = class.components[var] -%}
self.dae.bind('{{ var }}', {{ render_ndarray(comp.start_value) | indent(4) }})
{% endfor -%}
{%- endmacro -%}

{%- 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_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) -%}
{{ 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" -%}
self.dae({{ 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" -%}
self.dae.bind({{ 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, name):
# Underlying DaeBuilder instance
self.dae = ca.DaeBuilder(name)

def __repr__(self):
return repr(self.dae)

{%- for key, val in def.classes | items %}

{{ render_class(class=val) }}
{%- endfor %}
Loading