Added modelica model emission
This commit is contained in:
6
src/bedit_core/modelica/__init__.py
Normal file
6
src/bedit_core/modelica/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from .compose import CompositionResult, compose_modelica_model
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"CompositionResult",
|
||||||
|
"compose_modelica_model"
|
||||||
|
]
|
||||||
260
src/bedit_core/modelica/compose.py
Normal file
260
src/bedit_core/modelica/compose.py
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import re
|
||||||
|
from bedit_core.models import (
|
||||||
|
Component,
|
||||||
|
BondPort,
|
||||||
|
GraphImplementation,
|
||||||
|
ValueType,
|
||||||
|
SignalDirection,
|
||||||
|
Port,
|
||||||
|
SignalPort,
|
||||||
|
PortID,
|
||||||
|
Parameter,
|
||||||
|
ParameterID,
|
||||||
|
EquationImplementation,
|
||||||
|
BondConnection,
|
||||||
|
SignalConnection,
|
||||||
|
ComponentID
|
||||||
|
)
|
||||||
|
|
||||||
|
_BEVALUE_PATTERN = re.compile(r"\$([A-Za-z0-9_-]+)\$")
|
||||||
|
|
||||||
|
class CompositionError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CompositionResult:
|
||||||
|
modelica: str = ""
|
||||||
|
model_name: str = ""
|
||||||
|
|
||||||
|
def compose_modelica_model(root: Component) -> CompositionResult:
|
||||||
|
composer = Composer(root)
|
||||||
|
return composer.compose()
|
||||||
|
|
||||||
|
class Composer():
|
||||||
|
def __init__(self, root: Component)-> None:
|
||||||
|
self.model : str = ""
|
||||||
|
self.root : Component = root
|
||||||
|
self.indent: int = 0
|
||||||
|
self.lines: list[str] = []
|
||||||
|
|
||||||
|
def compose(self) -> CompositionResult:
|
||||||
|
self.indent = 0
|
||||||
|
self.lines = []
|
||||||
|
|
||||||
|
self.emit_model(self.root)
|
||||||
|
|
||||||
|
# Expand macros
|
||||||
|
macros = self.derive_macros(self.root, {})
|
||||||
|
for i in range(len(self.lines)):
|
||||||
|
self.lines[i] = self.expand_bevalues(self.lines[i], macros)
|
||||||
|
|
||||||
|
self.model = '\n'.join(self.lines)
|
||||||
|
return CompositionResult(self.model, self.model_name_for(self.root))
|
||||||
|
|
||||||
|
def emit_model(self, component: Component) -> None:
|
||||||
|
indentation = '\t'*self.indent
|
||||||
|
body_indentation = '\t'*(self.indent+1)
|
||||||
|
model_name = self.model_name_for(component)
|
||||||
|
macros: dict[str, str] = {}
|
||||||
|
|
||||||
|
self.lines.append(f"{indentation}model {model_name}")
|
||||||
|
|
||||||
|
# Add BondPort definition
|
||||||
|
if self.indent == 0:
|
||||||
|
self.lines.extend([
|
||||||
|
f"{body_indentation}connector BondPort",
|
||||||
|
f"{body_indentation}\tReal e;",
|
||||||
|
f"{body_indentation}\tflow Real f;",
|
||||||
|
f"{body_indentation}end BondPort;",
|
||||||
|
])
|
||||||
|
|
||||||
|
# Emit subcomponents
|
||||||
|
if isinstance(component.implementation, GraphImplementation):
|
||||||
|
for c_id, c in component.implementation.graph.components.items():
|
||||||
|
self.indent += 1
|
||||||
|
self.emit_model(c)
|
||||||
|
self.indent -= 1
|
||||||
|
|
||||||
|
# Child models have already expanded their own name-based macros.
|
||||||
|
lines_start = len(self.lines)
|
||||||
|
|
||||||
|
# Interface
|
||||||
|
for port_id, port in component.interface.ports.items():
|
||||||
|
self.lines.append(f"{body_indentation}{self.port_declaration(port)};")
|
||||||
|
if port.multiplicity:
|
||||||
|
macros[f"{port.name}_N"] = f"${port_id}_N$"
|
||||||
|
macros[f"{port.name}_S"] = f"${port_id}_S$"
|
||||||
|
|
||||||
|
# Paramters
|
||||||
|
for param_id, param in component.parameters.items():
|
||||||
|
self.lines.append(f"{body_indentation}{self.param_declaration(param)};")
|
||||||
|
|
||||||
|
# declaration block if equation mode
|
||||||
|
if isinstance(component.implementation, EquationImplementation):
|
||||||
|
for line in component.implementation.declarations:
|
||||||
|
self.lines.append(f"{body_indentation}{line}")
|
||||||
|
|
||||||
|
# Component instantiations in graph mode
|
||||||
|
if isinstance(component.implementation, GraphImplementation):
|
||||||
|
for c_id, c in component.implementation.graph.components.items():
|
||||||
|
self.lines.append(f"{body_indentation}{self.model_name_for(c)} {c.name};")
|
||||||
|
|
||||||
|
# Initial equations if equation mode
|
||||||
|
if isinstance(component.implementation, EquationImplementation):
|
||||||
|
if len(component.implementation.initial_equations):
|
||||||
|
self.lines.append(f"{indentation}initial equation")
|
||||||
|
for line in component.implementation.initial_equations:
|
||||||
|
self.lines.append(f"{body_indentation}{line}")
|
||||||
|
|
||||||
|
self.lines.append(f"{indentation}equation")
|
||||||
|
|
||||||
|
# equations block if equation mode
|
||||||
|
if isinstance(component.implementation, EquationImplementation):
|
||||||
|
for line in component.implementation.equations:
|
||||||
|
self.lines.append(f"{body_indentation}{line}")
|
||||||
|
|
||||||
|
# Connections if graph mode
|
||||||
|
elif isinstance(component.implementation, GraphImplementation):
|
||||||
|
port_indices: dict[PortID, int] = {}
|
||||||
|
for c_id, c in component.implementation.graph.connections.items():
|
||||||
|
source = component.implementation.graph.components[self.get_component_from_port(component, c.source)]
|
||||||
|
target = component.implementation.graph.components[self.get_component_from_port(component, c.target)]
|
||||||
|
source_port_name = self.port_reference(source.interface.ports[c.source], c.source, port_indices)
|
||||||
|
target_port_name = self.port_reference(target.interface.ports[c.target], c.target, port_indices)
|
||||||
|
if isinstance(c, BondConnection):
|
||||||
|
self.lines.append(f"{body_indentation}connect({source.name}.{source_port_name}, {target.name}.{target_port_name});")
|
||||||
|
elif isinstance(c, SignalConnection):
|
||||||
|
self.lines.append(f"{body_indentation}{target.name}.{target_port_name} = {source.name}.{source_port_name};")
|
||||||
|
else:
|
||||||
|
raise CompositionError(f"Unknown connection type {type(c).__name__}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise CompositionError(f"Unknown implementation type {type(component).__name__}")
|
||||||
|
|
||||||
|
# Fill in macros
|
||||||
|
for i in range(lines_start, len(self.lines)):
|
||||||
|
try:
|
||||||
|
self.lines[i] = self.expand_bevalues(self.lines[i], macros)
|
||||||
|
except CompositionError:
|
||||||
|
# Accept unresolved macros
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.lines.append(f"{indentation}end {model_name};")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def model_name_for(component: Component) -> str:
|
||||||
|
# TODO make sure model name is safe
|
||||||
|
return f"m_{component.name}"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def modelica_type_from_ValueType(type: ValueType) -> str:
|
||||||
|
if type == ValueType.REAL:
|
||||||
|
return "Real"
|
||||||
|
elif type == ValueType.INT:
|
||||||
|
return "Integer"
|
||||||
|
elif type == ValueType.BOOL:
|
||||||
|
return "Boolean"
|
||||||
|
raise CompositionError(f"Unknown value type {type}")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def port_declaration(cls, port: Port) -> str:
|
||||||
|
direction = "output" if port.direction == SignalDirection.OUTPUT else "input"
|
||||||
|
name = port.name
|
||||||
|
dimensions = cls.port_dimensions(port)
|
||||||
|
if isinstance(port, BondPort):
|
||||||
|
return f"BondPort {name}{dimensions}"
|
||||||
|
elif isinstance(port, SignalPort):
|
||||||
|
port_type = cls.modelica_type_from_ValueType(port.value_type)
|
||||||
|
#TODO units
|
||||||
|
return f"{direction} {port_type} {name}{dimensions}"
|
||||||
|
raise CompositionError(f"Unknown port type {type(port).__name__}")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fixed_dimensions(cls, p: Port | Parameter) -> str:
|
||||||
|
dimensions = p.matrix_size
|
||||||
|
rows = max(1, p.matrix_size[0])
|
||||||
|
columns = max(1, p.matrix_size[1])
|
||||||
|
if rows == columns == 1:
|
||||||
|
return ""
|
||||||
|
if columns == 1:
|
||||||
|
return f"[{rows}]"
|
||||||
|
return f"[{rows},{columns}]"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def port_dimensions(cls, port: Port) -> str:
|
||||||
|
fixed = cls.fixed_dimensions(port)
|
||||||
|
if not port.multiplicity:
|
||||||
|
return fixed
|
||||||
|
entries = [f"${port.name}_N$"]
|
||||||
|
if fixed:
|
||||||
|
entries.extend(fixed[1:-1].split(","))
|
||||||
|
return f"[{','.join(entries)}]"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def expand_bevalues(text, values: dict[str, str]) -> str:
|
||||||
|
"""Replace BEdit ``$name$`` macros and reject unresolved composer values."""
|
||||||
|
def replace(match: re.Match[str]) -> str:
|
||||||
|
name = match.group(1)
|
||||||
|
if name not in values:
|
||||||
|
raise CompositionError(f"Unknown BEdit value ${name}$")
|
||||||
|
return values[name]
|
||||||
|
return _BEVALUE_PATTERN.sub(replace, text)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def param_declaration(cls, param: Parameter) -> str:
|
||||||
|
dimensions = cls.fixed_dimensions(param)
|
||||||
|
type = cls.modelica_type_from_ValueType(param.value_type)
|
||||||
|
# TODO units
|
||||||
|
return f"parameter {type} {param.name}{dimensions} = {param.value}"
|
||||||
|
|
||||||
|
def get_component_from_port(self, component: Component, port_id: PortID) -> ComponentID:
|
||||||
|
if isinstance(component.implementation, GraphImplementation):
|
||||||
|
for c_id, c in component.implementation.graph.components.items():
|
||||||
|
for p_id, p in c.interface.ports.items():
|
||||||
|
if p_id == port_id:
|
||||||
|
return c_id
|
||||||
|
|
||||||
|
raise CompositionError(f"Could not find component of port {port_id}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def port_reference(port: Port, port_id: PortID, indices: dict[PortID, int],) -> str:
|
||||||
|
"""Return a port name with its one-based multiplicity index."""
|
||||||
|
if not port.multiplicity:
|
||||||
|
return port.name
|
||||||
|
index = indices.get(port_id, 0) + 1
|
||||||
|
indices[port_id] = index
|
||||||
|
return f"{port.name}[{index}]"
|
||||||
|
|
||||||
|
def derive_macros(self, component: Component, macros: dict[str, str]) -> dict[str, str]:
|
||||||
|
for port_id, port in component.interface.ports.items():
|
||||||
|
if port.multiplicity:
|
||||||
|
macros.setdefault(f"{port_id}_N", "0")
|
||||||
|
macros.setdefault(f"{port_id}_S", "{}")
|
||||||
|
|
||||||
|
if isinstance(component.implementation, GraphImplementation):
|
||||||
|
for c_id, c in component.implementation.graph.connections.items():
|
||||||
|
source = component.implementation.graph.components[self.get_component_from_port(component, c.source)]
|
||||||
|
target = component.implementation.graph.components[self.get_component_from_port(component, c.target)]
|
||||||
|
if source.interface.ports[c.source].multiplicity:
|
||||||
|
self.record_multiplicity(macros, c.source, -1)
|
||||||
|
if target.interface.ports[c.target].multiplicity:
|
||||||
|
self.record_multiplicity(macros, c.target, 1)
|
||||||
|
|
||||||
|
for c_id, c in component.implementation.graph.components.items():
|
||||||
|
macros = self.derive_macros(c, macros)
|
||||||
|
|
||||||
|
return macros
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def record_multiplicity(macros: dict[str, str], port_id: PortID, sign: int) -> None:
|
||||||
|
"""Record a connection count and orientation for a multiplicity port."""
|
||||||
|
count_key = f"{port_id}_N"
|
||||||
|
signs_key = f"{port_id}_S"
|
||||||
|
macros[count_key] = str(int(macros.get(count_key, "0")) + 1)
|
||||||
|
signs = macros.get(signs_key, "{}")
|
||||||
|
entries = [] if signs == "{}" else signs[1:-1].split(", ")
|
||||||
|
entries.append(str(float(sign)))
|
||||||
|
macros[signs_key] = "{" + ", ".join(entries) + "}"
|
||||||
|
|
||||||
@@ -49,6 +49,11 @@ class PortCausality(Enum):
|
|||||||
SINGLE_EFFORT_IN = "single_effort_in"
|
SINGLE_EFFORT_IN = "single_effort_in"
|
||||||
SINGLE_FLOW_IN = "single_flow_in"
|
SINGLE_FLOW_IN = "single_flow_in"
|
||||||
|
|
||||||
|
class ValueType(Enum):
|
||||||
|
REAL = "real"
|
||||||
|
BOOL = "bool"
|
||||||
|
INT = "int"
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Document:
|
class Document:
|
||||||
format_version: int
|
format_version: int
|
||||||
@@ -78,7 +83,7 @@ class Port:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SignalPort(Port):
|
class SignalPort(Port):
|
||||||
value_type: str = "Real"
|
value_type: ValueType = ValueType.REAL
|
||||||
quantity: str | None = None
|
quantity: str | None = None
|
||||||
unit: str | None = None
|
unit: str | None = None
|
||||||
|
|
||||||
@@ -91,7 +96,8 @@ class BondPort(Port):
|
|||||||
class Parameter:
|
class Parameter:
|
||||||
name: str
|
name: str
|
||||||
value: Any = 1.0
|
value: Any = 1.0
|
||||||
value_type: str = "Real"
|
value_type: ValueType = ValueType.REAL
|
||||||
|
matrix_size: Annotated[list[int], 2] = field(default_factory=lambda: [1, 1])
|
||||||
quantity: str | None = None
|
quantity: str | None = None
|
||||||
unit: str | None = None
|
unit: str | None = None
|
||||||
description: str | None = None
|
description: str | None = None
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from bedit_core.models import (
|
|||||||
SignalConnection,
|
SignalConnection,
|
||||||
SignalDirection,
|
SignalDirection,
|
||||||
SignalPort,
|
SignalPort,
|
||||||
|
ValueType
|
||||||
)
|
)
|
||||||
|
|
||||||
class SerializationError(ValueError):
|
class SerializationError(ValueError):
|
||||||
@@ -118,7 +119,7 @@ def _port_to_data(port: Port) -> dict[str, Any]:
|
|||||||
return {
|
return {
|
||||||
"port_type": "signal",
|
"port_type": "signal",
|
||||||
**common,
|
**common,
|
||||||
"value_type": port.value_type,
|
"value_type": _data_to_valuetype(port.value_type),
|
||||||
"quantity": port.quantity,
|
"quantity": port.quantity,
|
||||||
"unit": port.unit,
|
"unit": port.unit,
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,6 @@ def _port_to_data(port: Port) -> dict[str, Any]:
|
|||||||
}
|
}
|
||||||
raise TypeError(f"unsupported port class: {type(port).__name__}")
|
raise TypeError(f"unsupported port class: {type(port).__name__}")
|
||||||
|
|
||||||
|
|
||||||
def _port_from_data(value: Any, where: str) -> Port:
|
def _port_from_data(value: Any, where: str) -> Port:
|
||||||
"""Construct the port subclass selected by ``port_type``."""
|
"""Construct the port subclass selected by ``port_type``."""
|
||||||
obj = _mapping(value, where)
|
obj = _mapping(value, where)
|
||||||
@@ -146,7 +146,7 @@ def _port_from_data(value: Any, where: str) -> Port:
|
|||||||
if port_type == "signal":
|
if port_type == "signal":
|
||||||
return SignalPort(
|
return SignalPort(
|
||||||
**common,
|
**common,
|
||||||
value_type=_string(obj.get("value_type", "Real"), f"{where}.value_type"),
|
value_type=_valuetype_to_data(_string(obj.get("value_type", "Real"), f"{where}.value_type")),
|
||||||
quantity=_optional_string(obj.get("quantity"), f"{where}.quantity"),
|
quantity=_optional_string(obj.get("quantity"), f"{where}.quantity"),
|
||||||
unit=_optional_string(obj.get("unit"), f"{where}.unit"),
|
unit=_optional_string(obj.get("unit"), f"{where}.unit"),
|
||||||
)
|
)
|
||||||
@@ -162,13 +162,32 @@ def _port_from_data(value: Any, where: str) -> Port:
|
|||||||
)
|
)
|
||||||
raise SerializationError(f"{where}.port_type: unsupported value {port_type!r}")
|
raise SerializationError(f"{where}.port_type: unsupported value {port_type!r}")
|
||||||
|
|
||||||
|
def _data_to_valuetype(type: ValueType) -> str:
|
||||||
|
if type == ValueType.REAL:
|
||||||
|
return "real"
|
||||||
|
elif type == ValueType.INT:
|
||||||
|
return "int"
|
||||||
|
elif type == ValueType.BOOL:
|
||||||
|
return "bool"
|
||||||
|
raise SerializationError(f"Unknown value type {type}")
|
||||||
|
|
||||||
|
def _valuetype_to_data(type: str) -> ValueType:
|
||||||
|
type = type.lower()
|
||||||
|
if type == "real":
|
||||||
|
return ValueType.REAL
|
||||||
|
elif type == "int":
|
||||||
|
return ValueType.INT
|
||||||
|
elif type == "bool":
|
||||||
|
return ValueType.BOOL
|
||||||
|
raise SerializationError(f"Unknown value type {type}")
|
||||||
|
|
||||||
def _parameter_to_data(parameter: Parameter) -> dict[str, Any]:
|
def _parameter_to_data(parameter: Parameter) -> dict[str, Any]:
|
||||||
"""Convert a parameter to raw values."""
|
"""Convert a parameter to raw values."""
|
||||||
return {
|
return {
|
||||||
"name": parameter.name,
|
"name": parameter.name,
|
||||||
"value": _plain_value(parameter.value),
|
"value": _plain_value(parameter.value),
|
||||||
"value_type": parameter.value_type,
|
"value_type": _data_to_valuetype(parameter.value_type),
|
||||||
|
"matrix_size": list(parameter.matrix_size),
|
||||||
"quantity": parameter.quantity,
|
"quantity": parameter.quantity,
|
||||||
"unit": parameter.unit,
|
"unit": parameter.unit,
|
||||||
"description": parameter.description,
|
"description": parameter.description,
|
||||||
@@ -181,7 +200,8 @@ def _parameter_from_data(value: Any, where: str) -> Parameter:
|
|||||||
return Parameter(
|
return Parameter(
|
||||||
name=_string(_required(obj, "name", where), f"{where}.name"),
|
name=_string(_required(obj, "name", where), f"{where}.name"),
|
||||||
value=obj.get("value", 1.0),
|
value=obj.get("value", 1.0),
|
||||||
value_type=_string(obj.get("value_type", "Real"), f"{where}.value_type"),
|
value_type=_valuetype_to_data(_string(obj.get("value_type", "Real"), f"{where}.value_type")),
|
||||||
|
matrix_size=_matrix_size(obj.get("matrix_size", [1, 1]), f"{where}.matrix_size"),
|
||||||
quantity=_optional_string(obj.get("quantity"), f"{where}.quantity"),
|
quantity=_optional_string(obj.get("quantity"), f"{where}.quantity"),
|
||||||
unit=_optional_string(obj.get("unit"), f"{where}.unit"),
|
unit=_optional_string(obj.get("unit"), f"{where}.unit"),
|
||||||
description=_optional_string(obj.get("description"), f"{where}.description"),
|
description=_optional_string(obj.get("description"), f"{where}.description"),
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import sys
|
import sys
|
||||||
from bedit_core.serialization import load, save
|
from bedit_core.serialization import load, save
|
||||||
from bedit_core.bondgraph import causality_inference
|
from bedit_core.bondgraph import causality_inference
|
||||||
|
from bedit_core.modelica import compose_modelica_model
|
||||||
|
|
||||||
def main(path: str):
|
def main(path: str):
|
||||||
doc = load(path)
|
doc = load(path)
|
||||||
for id, root in doc.root.items():
|
for id, root in doc.root.items():
|
||||||
doc.root[id] = causality_inference(doc.root[id])
|
doc.root[id] = causality_inference(doc.root[id])
|
||||||
|
composition = compose_modelica_model(doc.root[id])
|
||||||
|
print(composition.modelica)
|
||||||
save(doc, path)
|
save(doc, path)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"name": "Current Document",
|
"name": "Current Document",
|
||||||
"root": {
|
"root": {
|
||||||
"50e6ef97-f686-4400-bc01-e5a352e8cc22": {
|
"50e6ef97-f686-4400-bc01-e5a352e8cc22": {
|
||||||
"name": "New Graph Block 1",
|
"name": "test",
|
||||||
"interface": {
|
"interface": {
|
||||||
"ports": {}
|
"ports": {}
|
||||||
},
|
},
|
||||||
@@ -51,7 +51,11 @@
|
|||||||
"parameter-d056bc27": {
|
"parameter-d056bc27": {
|
||||||
"name": "c",
|
"name": "c",
|
||||||
"value": "1",
|
"value": "1",
|
||||||
"value_type": "Real",
|
"value_type": "real",
|
||||||
|
"matrix_size": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
"quantity": null,
|
"quantity": null,
|
||||||
"unit": null,
|
"unit": null,
|
||||||
"description": null
|
"description": null
|
||||||
@@ -128,7 +132,11 @@
|
|||||||
"parameter-d056bc27": {
|
"parameter-d056bc27": {
|
||||||
"name": "r",
|
"name": "r",
|
||||||
"value": "1",
|
"value": "1",
|
||||||
"value_type": "Real",
|
"value_type": "real",
|
||||||
|
"matrix_size": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
"quantity": null,
|
"quantity": null,
|
||||||
"unit": null,
|
"unit": null,
|
||||||
"description": null
|
"description": null
|
||||||
@@ -166,7 +174,11 @@
|
|||||||
"parameter-d056bc27": {
|
"parameter-d056bc27": {
|
||||||
"name": "e",
|
"name": "e",
|
||||||
"value": "1",
|
"value": "1",
|
||||||
"value_type": "Real",
|
"value_type": "real",
|
||||||
|
"matrix_size": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
"quantity": null,
|
"quantity": null,
|
||||||
"unit": null,
|
"unit": null,
|
||||||
"description": null
|
"description": null
|
||||||
@@ -242,7 +254,11 @@
|
|||||||
"parameter-d056bc27": {
|
"parameter-d056bc27": {
|
||||||
"name": "r",
|
"name": "r",
|
||||||
"value": "10",
|
"value": "10",
|
||||||
"value_type": "Real",
|
"value_type": "real",
|
||||||
|
"matrix_size": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
"quantity": null,
|
"quantity": null,
|
||||||
"unit": null,
|
"unit": null,
|
||||||
"description": null
|
"description": null
|
||||||
@@ -294,7 +310,11 @@
|
|||||||
"parameter-d056bc27": {
|
"parameter-d056bc27": {
|
||||||
"name": "i",
|
"name": "i",
|
||||||
"value": "1",
|
"value": "1",
|
||||||
"value_type": "Real",
|
"value_type": "real",
|
||||||
|
"matrix_size": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
"quantity": null,
|
"quantity": null,
|
||||||
"unit": null,
|
"unit": null,
|
||||||
"description": null
|
"description": null
|
||||||
|
|||||||
Reference in New Issue
Block a user