Fixed some bugs
This commit is contained in:
@@ -1,21 +0,0 @@
|
|||||||
model m_Test
|
|
||||||
model m_Constant0
|
|
||||||
output Real y(quantity="Length", unit="m");
|
|
||||||
parameter Real v = 2;
|
|
||||||
equation
|
|
||||||
y = v;
|
|
||||||
end m_Constant0;
|
|
||||||
model m_Gain0
|
|
||||||
input Real u;
|
|
||||||
output Real y;
|
|
||||||
parameter Real k(quantity="Current", unit="A") = 2.5;
|
|
||||||
equation
|
|
||||||
y = k*u;
|
|
||||||
end m_Gain0;
|
|
||||||
m_Constant0 Constant0;
|
|
||||||
m_Gain0 Gain0;
|
|
||||||
equation
|
|
||||||
Gain0.u = Constant0.y;
|
|
||||||
annotation(
|
|
||||||
experiment(StartTime = 0, StopTime = 1, Tolerance = 1e-06, Interval = 0.002));
|
|
||||||
end m_Test;
|
|
||||||
@@ -25,8 +25,6 @@ def infer_causality(component: dict[str, Any], toplevel: bool = True) -> dict[st
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if toplevel:
|
if toplevel:
|
||||||
log.info("Causality inference")
|
|
||||||
|
|
||||||
# Reset causalities
|
# Reset causalities
|
||||||
reset_causality(component)
|
reset_causality(component)
|
||||||
|
|
||||||
@@ -61,20 +59,40 @@ def infer_causality(component: dict[str, Any], toplevel: bool = True) -> dict[st
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Soft choices
|
# Soft choices may need several passes when a junction has multiple
|
||||||
for block in graph.get("blocks", []):
|
# unresolved bonds. Stop as soon as a pass makes no further progress.
|
||||||
for port in block.get('interface', {}).get('ports', []):
|
while True:
|
||||||
if port.get('type', '') != 'power':
|
unresolved_before = sum(
|
||||||
continue
|
con.get('type') == 'power' and con.get('causality', 'none') == 'none'
|
||||||
if is_port_fully_assigned(block, port, graph):
|
for con in graph.get('connections', [])
|
||||||
continue
|
)
|
||||||
if port.get('causality', 'indifferent') == 'likes effort out':
|
for block in graph.get("blocks", []):
|
||||||
propagate_from_port(block, port, 'effort out', graph, id_list)
|
for port in block.get('interface', {}).get('ports', []):
|
||||||
elif port.get('causality', 'indifferent') == 'likes flow out':
|
if port.get('type', '') != 'power':
|
||||||
propagate_from_port(block, port, 'flow out', graph, id_list)
|
continue
|
||||||
elif port.get('causality', 'indifferent') in ['indifferent', 'single flow in', 'single effort in']:
|
if is_port_fully_assigned(block, port, graph):
|
||||||
# Force an arbitrary assignment on the first unassigned bond connected to this port
|
continue
|
||||||
propagate_from_port(block, port, 'effort out', graph, id_list)
|
if port.get('causality', 'indifferent') == 'likes effort out':
|
||||||
|
propagate_from_port(block, port, 'effort out', graph, id_list)
|
||||||
|
elif port.get('causality', 'indifferent') == 'likes flow out':
|
||||||
|
propagate_from_port(block, port, 'flow out', graph, id_list)
|
||||||
|
elif port.get('causality', 'indifferent') == 'single effort in':
|
||||||
|
evaluate_junction_constraints(block, port, graph, id_list)
|
||||||
|
if not is_port_fully_assigned(block, port, graph):
|
||||||
|
propagate_from_port(block, port, 'flow out', graph, id_list)
|
||||||
|
elif port.get('causality', 'indifferent') == 'single flow in':
|
||||||
|
evaluate_junction_constraints(block, port, graph, id_list)
|
||||||
|
if not is_port_fully_assigned(block, port, graph):
|
||||||
|
propagate_from_port(block, port, 'effort out', graph, id_list)
|
||||||
|
elif port.get('causality', 'indifferent') == 'indifferent':
|
||||||
|
# Force an arbitrary assignment on the first unassigned bond connected to this port
|
||||||
|
propagate_from_port(block, port, 'effort out', graph, id_list)
|
||||||
|
unresolved_after = sum(
|
||||||
|
con.get('type') == 'power' and con.get('causality', 'none') == 'none'
|
||||||
|
for con in graph.get('connections', [])
|
||||||
|
)
|
||||||
|
if unresolved_after == 0 or unresolved_after >= unresolved_before:
|
||||||
|
break
|
||||||
|
|
||||||
# Last check
|
# Last check
|
||||||
for con in graph.get('connections', []):
|
for con in graph.get('connections', []):
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ def emit_model(
|
|||||||
id_list: dict[str, Any],
|
id_list: dict[str, Any],
|
||||||
indent: int = 0,
|
indent: int = 0,
|
||||||
connection_counts: dict[str, int] | None = None,
|
connection_counts: dict[str, int] | None = None,
|
||||||
|
connection_signs: dict[str, list[float]] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Emit a component and its nested definitions as Modelica source."""
|
"""Emit a component and its nested definitions as Modelica source."""
|
||||||
|
|
||||||
@@ -92,16 +93,31 @@ def emit_model(
|
|||||||
implementation_kind = implementation.get("kind")
|
implementation_kind = implementation.get("kind")
|
||||||
nested_graph = implementation.get("graph", {})
|
nested_graph = implementation.get("graph", {})
|
||||||
port_counts = connection_counts or _interface_connection_counts(graph)
|
port_counts = connection_counts or _interface_connection_counts(graph)
|
||||||
macros = _port_count_macros(graph, port_counts)
|
port_signs = connection_signs or _interface_connection_signs(graph)
|
||||||
|
macros = _port_connection_macros(graph, port_counts, port_signs)
|
||||||
|
|
||||||
|
if indent == 0 and _contains_power_port(graph):
|
||||||
|
lines.extend(
|
||||||
|
(
|
||||||
|
f"{body_indent}connector BondPort \"Bond graph power port\"",
|
||||||
|
f"{body_indent}\tReal e \"Effort variable\";",
|
||||||
|
f"{body_indent}\tflow Real f \"Flow variable\";",
|
||||||
|
f"{body_indent}end BondPort;",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if implementation_kind == "graph":
|
if implementation_kind == "graph":
|
||||||
for block in nested_graph.get("blocks", []):
|
for block in nested_graph.get("blocks", []):
|
||||||
|
block_counts, block_signs = _block_connection_data(
|
||||||
|
nested_graph, block["id"]
|
||||||
|
)
|
||||||
lines.extend(
|
lines.extend(
|
||||||
emit_model(
|
emit_model(
|
||||||
block,
|
block,
|
||||||
{},
|
{},
|
||||||
indent + 1,
|
indent + 1,
|
||||||
_block_connection_counts(nested_graph, block["id"]),
|
block_counts,
|
||||||
|
block_signs,
|
||||||
)
|
)
|
||||||
.rstrip()
|
.rstrip()
|
||||||
.splitlines()
|
.splitlines()
|
||||||
@@ -157,8 +173,10 @@ def emit_model(
|
|||||||
target = _endpoint_expression(
|
target = _endpoint_expression(
|
||||||
connection["target"], graph, blocks, junctions, endpoint_indices
|
connection["target"], graph, blocks, junctions, endpoint_indices
|
||||||
)
|
)
|
||||||
# Connector types may require different equations in future.
|
if connection.get("type") == "power":
|
||||||
lines.append(f"{body_indent}{target} = {source};")
|
lines.append(f"{body_indent}connect({source}, {target});")
|
||||||
|
else:
|
||||||
|
lines.append(f"{body_indent}{target} = {source};")
|
||||||
else:
|
else:
|
||||||
initial_equations = str(
|
initial_equations = str(
|
||||||
implementation.get("source", {}).get("initialEquations", "")
|
implementation.get("source", {}).get("initialEquations", "")
|
||||||
@@ -213,10 +231,14 @@ def cleanup_graph(graph: dict[str, Any]) -> dict[str, Any]:
|
|||||||
def _port_declaration(
|
def _port_declaration(
|
||||||
port: dict[str, Any], direction: str, indent: int, macros: dict[str, str]
|
port: dict[str, Any], direction: str, indent: int, macros: dict[str, str]
|
||||||
) -> str:
|
) -> str:
|
||||||
port_type = modelica_type(port.get("valueType", "real"))
|
|
||||||
indentation = "\t" * indent
|
indentation = "\t" * indent
|
||||||
port_name = identifier(port["name"])
|
port_name = identifier(port["name"])
|
||||||
dimensions = _port_dimensions(port, port_name)
|
dimensions = _port_dimensions(port, port_name)
|
||||||
|
if port.get("type") == "power":
|
||||||
|
return expand_bevalues(
|
||||||
|
f"{indentation}BondPort {port_name}{dimensions};", macros
|
||||||
|
)
|
||||||
|
port_type = modelica_type(port.get("valueType", "real"))
|
||||||
attributes = _quantity_unit_attributes(port)
|
attributes = _quantity_unit_attributes(port)
|
||||||
declaration = (
|
declaration = (
|
||||||
f"{indentation}{direction} {port_type} {port_name}{dimensions}{attributes};"
|
f"{indentation}{direction} {port_type} {port_name}{dimensions}{attributes};"
|
||||||
@@ -299,16 +321,21 @@ def _index_array_endpoint(
|
|||||||
return f"{expression}[{endpoint_indices[key]}]"
|
return f"{expression}[{endpoint_indices[key]}]"
|
||||||
|
|
||||||
|
|
||||||
def _block_connection_counts(
|
def _block_connection_data(
|
||||||
graph: dict[str, Any], block_id: str
|
graph: dict[str, Any], block_id: str
|
||||||
) -> dict[str, int]:
|
) -> tuple[dict[str, int], dict[str, list[float]]]:
|
||||||
counts: dict[str, int] = {}
|
counts: dict[str, int] = {}
|
||||||
|
signs: dict[str, list[float]] = {}
|
||||||
for connection in graph.get("connections", []):
|
for connection in graph.get("connections", []):
|
||||||
for endpoint in (connection.get("source", {}), connection.get("target", {})):
|
for endpoint, sign in (
|
||||||
|
(connection.get("source", {}), -1.0),
|
||||||
|
(connection.get("target", {}), 1.0),
|
||||||
|
):
|
||||||
if endpoint.get("block") == block_id and endpoint.get("port"):
|
if endpoint.get("block") == block_id and endpoint.get("port"):
|
||||||
port_id = endpoint["port"]
|
port_id = endpoint["port"]
|
||||||
counts[port_id] = counts.get(port_id, 0) + 1
|
counts[port_id] = counts.get(port_id, 0) + 1
|
||||||
return counts
|
signs.setdefault(port_id, []).append(sign)
|
||||||
|
return counts, signs
|
||||||
|
|
||||||
|
|
||||||
def _interface_connection_counts(component: dict[str, Any]) -> dict[str, int]:
|
def _interface_connection_counts(component: dict[str, Any]) -> dict[str, int]:
|
||||||
@@ -324,19 +351,56 @@ def _interface_connection_counts(component: dict[str, Any]) -> dict[str, int]:
|
|||||||
return counts
|
return counts
|
||||||
|
|
||||||
|
|
||||||
def _port_count_macros(
|
def _interface_connection_signs(component: dict[str, Any]) -> dict[str, list[float]]:
|
||||||
component: dict[str, Any], connection_counts: dict[str, int]
|
implementation = component.get("implementation", {})
|
||||||
|
if implementation.get("kind") != "graph":
|
||||||
|
return {}
|
||||||
|
signs: dict[str, list[float]] = {}
|
||||||
|
for connection in implementation.get("graph", {}).get("connections", []):
|
||||||
|
for endpoint, sign in (
|
||||||
|
(connection.get("source", {}), -1.0),
|
||||||
|
(connection.get("target", {}), 1.0),
|
||||||
|
):
|
||||||
|
port_id = endpoint.get("interface")
|
||||||
|
if port_id:
|
||||||
|
signs.setdefault(port_id, []).append(sign)
|
||||||
|
return signs
|
||||||
|
|
||||||
|
|
||||||
|
def _port_connection_macros(
|
||||||
|
component: dict[str, Any],
|
||||||
|
connection_counts: dict[str, int],
|
||||||
|
connection_signs: dict[str, list[float]],
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
macros: dict[str, str] = {}
|
macros: dict[str, str] = {}
|
||||||
interface = component.get("interface", {})
|
interface = component.get("interface", {})
|
||||||
for port in interface.get("ports", []):
|
for port in interface.get("ports", []):
|
||||||
if port.get("multipleConnections", False):
|
if port.get("multipleConnections", False):
|
||||||
macros[f"{identifier(port['name'])}_N"] = str(
|
macro_name = identifier(port["name"])
|
||||||
connection_counts.get(port["id"], 0)
|
port_id = port["id"]
|
||||||
)
|
macros[f"{macro_name}_N"] = str(connection_counts.get(port_id, 0))
|
||||||
|
signs = connection_signs.get(port_id, [])
|
||||||
|
macros[f"{macro_name}_S"] = "{" + ", ".join(
|
||||||
|
f"{sign:.1f}" for sign in signs
|
||||||
|
) + "}"
|
||||||
return macros
|
return macros
|
||||||
|
|
||||||
|
|
||||||
|
def _contains_power_port(component: dict[str, Any]) -> bool:
|
||||||
|
if any(
|
||||||
|
port.get("type") == "power"
|
||||||
|
for port in component.get("interface", {}).get("ports", [])
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
implementation = component.get("implementation", {})
|
||||||
|
if implementation.get("kind") != "graph":
|
||||||
|
return False
|
||||||
|
return any(
|
||||||
|
_contains_power_port(block)
|
||||||
|
for block in implementation.get("graph", {}).get("blocks", [])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def expand_bevalues(text: str, values: dict[str, str]) -> str:
|
def expand_bevalues(text: str, values: dict[str, str]) -> str:
|
||||||
"""Replace BEdit ``$name$`` macros and reject unresolved composer values."""
|
"""Replace BEdit ``$name$`` macros and reject unresolved composer values."""
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
@@ -54,6 +56,7 @@ class ModelBuildResult:
|
|||||||
|
|
||||||
check_summary: str
|
check_summary: str
|
||||||
build_result: Any
|
build_result: Any
|
||||||
|
diagnostics: str = ""
|
||||||
|
|
||||||
|
|
||||||
class OpenModelicaInterface:
|
class OpenModelicaInterface:
|
||||||
@@ -100,21 +103,42 @@ class OpenModelicaInterface:
|
|||||||
"""Load and build one composed model as an ordered worker operation."""
|
"""Load and build one composed model as an ordered worker operation."""
|
||||||
|
|
||||||
def operation(omc, _temp_dir: Path):
|
def operation(omc, _temp_dir: Path):
|
||||||
unit_checking = omc.sendExpression(
|
capture = _LogCapture()
|
||||||
'setCommandLineOptions("--unitChecking")'
|
ompython_logger = logging.getLogger("OMPython")
|
||||||
)
|
previous_propagate = ompython_logger.propagate
|
||||||
if unit_checking is not True:
|
ompython_logger.addHandler(capture)
|
||||||
raise RuntimeError("OpenModelica could not enable unit checking")
|
ompython_logger.propagate = False
|
||||||
loaded = omc.sendExpression(f"loadString({json.dumps(model)})")
|
try:
|
||||||
if loaded is not True:
|
unit_checking = omc.sendExpression(
|
||||||
raise RuntimeError("OpenModelica could not load the composed model")
|
'setCommandLineOptions("--unitChecking")'
|
||||||
check_summary = omc.sendExpression(f"checkModel({model_name})")
|
|
||||||
if not isinstance(check_summary, str) or not check_summary.strip():
|
|
||||||
raise RuntimeError(
|
|
||||||
"OpenModelica did not return a model-check summary"
|
|
||||||
)
|
)
|
||||||
build_result = omc.sendExpression(f"buildModel({model_name})")
|
if unit_checking is not True:
|
||||||
return ModelBuildResult(check_summary, build_result)
|
raise RuntimeError("OpenModelica could not enable unit checking")
|
||||||
|
loaded = omc.sendExpression(f"loadString({json.dumps(model)})")
|
||||||
|
if loaded is not True:
|
||||||
|
raise RuntimeError("OpenModelica could not load the composed model")
|
||||||
|
diagnostics = [_read_omc_diagnostics(omc)]
|
||||||
|
check_summary = omc.sendExpression(f"checkModel({model_name})")
|
||||||
|
diagnostics.append(_read_omc_diagnostics(omc))
|
||||||
|
if not isinstance(check_summary, str) or not check_summary.strip():
|
||||||
|
raise RuntimeError(
|
||||||
|
"OpenModelica did not return a model-check summary"
|
||||||
|
)
|
||||||
|
raw_build_result = omc.sendExpression(
|
||||||
|
f"buildModel({model_name})", parsed=False
|
||||||
|
)
|
||||||
|
build_result = _parse_modelica_string_array(raw_build_result)
|
||||||
|
diagnostics.append(_read_omc_diagnostics(omc))
|
||||||
|
diagnostics.extend(capture.messages)
|
||||||
|
diagnostic_text = "\n".join(
|
||||||
|
item.strip()
|
||||||
|
for item in diagnostics
|
||||||
|
if isinstance(item, str) and item.strip()
|
||||||
|
)
|
||||||
|
return ModelBuildResult(check_summary, build_result, diagnostic_text)
|
||||||
|
finally:
|
||||||
|
ompython_logger.removeHandler(capture)
|
||||||
|
ompython_logger.propagate = previous_propagate
|
||||||
|
|
||||||
self._submit("build model", operation, callback, error_callback)
|
self._submit("build model", operation, callback, error_callback)
|
||||||
|
|
||||||
@@ -266,6 +290,51 @@ class OpenModelicaInterface:
|
|||||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _read_omc_diagnostics(omc) -> str:
|
||||||
|
"""Read OMC diagnostics without sending multiline text through OMPython's parser."""
|
||||||
|
|
||||||
|
raw = omc.sendExpression("getErrorString()", parsed=False)
|
||||||
|
if isinstance(raw, bytes):
|
||||||
|
raw = raw.decode("utf-8", errors="replace")
|
||||||
|
if not isinstance(raw, str):
|
||||||
|
return ""
|
||||||
|
text = raw.strip()
|
||||||
|
if not text:
|
||||||
|
return ""
|
||||||
|
try:
|
||||||
|
decoded = json.loads(text)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return text
|
||||||
|
return decoded if isinstance(decoded, str) else text
|
||||||
|
|
||||||
|
|
||||||
|
class _LogCapture(logging.Handler):
|
||||||
|
"""Collect dependency log messages for forwarding through BEdit's logger."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(level=logging.WARNING)
|
||||||
|
self.messages: list[str] = []
|
||||||
|
|
||||||
|
def emit(self, record: logging.LogRecord) -> None:
|
||||||
|
self.messages.append(record.getMessage())
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_modelica_string_array(raw: Any) -> tuple[str, ...]:
|
||||||
|
"""Parse the string array returned by ``buildModel`` in raw mode."""
|
||||||
|
|
||||||
|
if isinstance(raw, bytes):
|
||||||
|
raw = raw.decode("utf-8", errors="replace")
|
||||||
|
if not isinstance(raw, str):
|
||||||
|
raise RuntimeError(f"OpenModelica returned an invalid build result: {raw!r}")
|
||||||
|
values = tuple(
|
||||||
|
json.loads(token)
|
||||||
|
for token in re.findall(r'"(?:\\.|[^"\\])*"', raw)
|
||||||
|
)
|
||||||
|
if not values:
|
||||||
|
raise RuntimeError(f"OpenModelica returned an invalid build result: {raw!r}")
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _deliver_callback(callback: Callable[[Any], None], value: Any) -> None:
|
def _deliver_callback(callback: Callable[[Any], None], value: Any) -> None:
|
||||||
try:
|
try:
|
||||||
callback(value)
|
callback(value)
|
||||||
|
|||||||
@@ -45,11 +45,10 @@ class Simulation:
|
|||||||
graph: dict[str, Any],
|
graph: dict[str, Any],
|
||||||
callback: Callable[[str], None] | None = None,
|
callback: Callable[[str], None] | None = None,
|
||||||
error_callback: ErrorCallback | None = None,
|
error_callback: ErrorCallback | None = None,
|
||||||
|
message_callback: Callable[[SimulationMessage], None] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Compose and retain the active graph's Modelica representation."""
|
"""Compose and retain the active graph's Modelica representation."""
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
self.model_path = None
|
self.model_path = None
|
||||||
self.compose_source(graph)
|
self.compose_source(graph)
|
||||||
|
|
||||||
@@ -64,6 +63,24 @@ class Simulation:
|
|||||||
log.error("%s", failure)
|
log.error("%s", failure)
|
||||||
return
|
return
|
||||||
log.info("%s", result.check_summary.strip())
|
log.info("%s", result.check_summary.strip())
|
||||||
|
if message_callback is not None:
|
||||||
|
message_callback(
|
||||||
|
SimulationMessage(
|
||||||
|
stream="build",
|
||||||
|
type="info",
|
||||||
|
text=result.check_summary.strip(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if result.diagnostics:
|
||||||
|
log.warning("OpenModelica build diagnostics:\n%s", result.diagnostics)
|
||||||
|
if message_callback is not None:
|
||||||
|
message_callback(
|
||||||
|
SimulationMessage(
|
||||||
|
stream="build",
|
||||||
|
type="warning",
|
||||||
|
text=result.diagnostics,
|
||||||
|
)
|
||||||
|
)
|
||||||
log.info("Compiling OK: %s", result.build_result)
|
log.info("Compiling OK: %s", result.build_result)
|
||||||
try:
|
try:
|
||||||
self.model_path = str(result.build_result[0])
|
self.model_path = str(result.build_result[0])
|
||||||
@@ -77,6 +94,14 @@ class Simulation:
|
|||||||
else:
|
else:
|
||||||
log.error("%s", failure)
|
log.error("%s", failure)
|
||||||
return
|
return
|
||||||
|
if message_callback is not None:
|
||||||
|
message_callback(
|
||||||
|
SimulationMessage(
|
||||||
|
stream="build",
|
||||||
|
type="info",
|
||||||
|
text=f"Compiling OK: {result.build_result}",
|
||||||
|
)
|
||||||
|
)
|
||||||
if callback is not None:
|
if callback is not None:
|
||||||
callback(self.model_path)
|
callback(self.model_path)
|
||||||
|
|
||||||
@@ -134,7 +159,7 @@ class Simulation:
|
|||||||
error_callback,
|
error_callback,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.compose(graph, run_model, error_callback)
|
self.compose(graph, run_model, error_callback, message_callback)
|
||||||
|
|
||||||
def get_progress(self) -> SimulationProgress | None:
|
def get_progress(self) -> SimulationProgress | None:
|
||||||
"""Return the most recently received simulation status."""
|
"""Return the most recently received simulation status."""
|
||||||
|
|||||||
Binary file not shown.
@@ -177,13 +177,13 @@
|
|||||||
"source": {
|
"source": {
|
||||||
"equations": "der(state) = p.f;\np.e = state/c;",
|
"equations": "der(state) = p.f;\np.e = state/c;",
|
||||||
"declarations": "",
|
"declarations": "",
|
||||||
"initialEquations": ""
|
"initialEquations": "state = 0;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "bfa506d8-ee41-4bab-ae19-a97fd67bfcf6",
|
"id": "bfa506d8-ee41-4bab-ae19-a97fd67bfcf6",
|
||||||
"name": "1",
|
"name": "j1",
|
||||||
"position": {
|
"position": {
|
||||||
"x": -96.0,
|
"x": -96.0,
|
||||||
"y": -160.0
|
"y": -160.0
|
||||||
@@ -256,8 +256,8 @@
|
|||||||
"implementation": {
|
"implementation": {
|
||||||
"kind": "text",
|
"kind": "text",
|
||||||
"source": {
|
"source": {
|
||||||
"equations": "flow = p[1].f;\nsum(p[i].e for i in 1:$p_N$) = 0;\nfor i in 2:$p_N$ loop\n p[i].f = p[i-1].f;\nend for;",
|
"equations": "f = s[1] * p[1].f;\nsum(s[i] * p[i].e for i in 1:$p_N$) = 0;\nfor i in 2:$p_N$ loop\n s[i] * p[i].f = s[i-1] * p[i-1].f;\nend for;",
|
||||||
"declarations": "Real flow;",
|
"declarations": "parameter Real s[$p_N$] = $p_S$;\nReal f;",
|
||||||
"initialEquations": ""
|
"initialEquations": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,7 +399,7 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"id": "parameter-d056bc27",
|
"id": "parameter-d056bc27",
|
||||||
"name": "effort",
|
"name": "e",
|
||||||
"type": "real",
|
"type": "real",
|
||||||
"value": "1",
|
"value": "1",
|
||||||
"quantity": "",
|
"quantity": "",
|
||||||
@@ -446,15 +446,15 @@
|
|||||||
"implementation": {
|
"implementation": {
|
||||||
"kind": "text",
|
"kind": "text",
|
||||||
"source": {
|
"source": {
|
||||||
"equations": "p.e = effort;\nflow = p.f;",
|
"equations": "p.e = e;\nf = p.f;",
|
||||||
"declarations": "Real flow;",
|
"declarations": "Real f;",
|
||||||
"initialEquations": ""
|
"initialEquations": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "140ae14b-9dbb-4756-aa25-29101ef2a99e",
|
"id": "140ae14b-9dbb-4756-aa25-29101ef2a99e",
|
||||||
"name": "0",
|
"name": "j0",
|
||||||
"position": {
|
"position": {
|
||||||
"x": -96.0,
|
"x": -96.0,
|
||||||
"y": -32.0
|
"y": -32.0
|
||||||
@@ -527,130 +527,8 @@
|
|||||||
"implementation": {
|
"implementation": {
|
||||||
"kind": "text",
|
"kind": "text",
|
||||||
"source": {
|
"source": {
|
||||||
"equations": "effort = p[1].e;\nsum(p[i].f for i in 1:$p_N$) = 0;\nfor i in 2:$p_N$ loop\n p[i].e = p[i-1].e;\nend for;",
|
"equations": "e = p[1].e;\nsum(p[i].f for i in 1:$p_N$) = 0;\nfor i in 2:$p_N$ loop\n p[i].e = p[i-1].e;\nend for;",
|
||||||
"declarations": "Real effort;",
|
"declarations": "Real e;",
|
||||||
"initialEquations": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "6a6fbadd-28ec-4d10-b854-876752a6b287",
|
|
||||||
"name": "C0",
|
|
||||||
"position": {
|
|
||||||
"x": -96.0,
|
|
||||||
"y": 96.0
|
|
||||||
},
|
|
||||||
"rotation": 0.0,
|
|
||||||
"interface": {
|
|
||||||
"ports": [
|
|
||||||
{
|
|
||||||
"id": "port-2e1d884f",
|
|
||||||
"name": "p",
|
|
||||||
"position": {
|
|
||||||
"x": 0.0,
|
|
||||||
"y": 0.0
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"iconPosition": {
|
|
||||||
"x": 64.0,
|
|
||||||
"y": 64.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "power",
|
|
||||||
"multipleConnections": false,
|
|
||||||
"valueType": "real",
|
|
||||||
"quantity": "",
|
|
||||||
"unit": "",
|
|
||||||
"dimensions": {
|
|
||||||
"rows": 1,
|
|
||||||
"columns": 1
|
|
||||||
},
|
|
||||||
"description": "",
|
|
||||||
"orientation": "input",
|
|
||||||
"domain": "power",
|
|
||||||
"causality": "preferred effort out"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "port-ca7716d5",
|
|
||||||
"name": "state",
|
|
||||||
"position": {
|
|
||||||
"x": 0.0,
|
|
||||||
"y": 0.0
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"iconPosition": {
|
|
||||||
"x": 88.0,
|
|
||||||
"y": 40.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "signal",
|
|
||||||
"multipleConnections": false,
|
|
||||||
"valueType": "real",
|
|
||||||
"quantity": "",
|
|
||||||
"unit": "",
|
|
||||||
"dimensions": {
|
|
||||||
"rows": 1,
|
|
||||||
"columns": 1
|
|
||||||
},
|
|
||||||
"description": "",
|
|
||||||
"orientation": "output",
|
|
||||||
"domain": "power",
|
|
||||||
"causality": "indifferent"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"id": "parameter-d056bc27",
|
|
||||||
"name": "c",
|
|
||||||
"type": "real",
|
|
||||||
"value": "1",
|
|
||||||
"quantity": "",
|
|
||||||
"unit": "",
|
|
||||||
"dimensions": {
|
|
||||||
"rows": 1,
|
|
||||||
"columns": 1
|
|
||||||
},
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"icon": {
|
|
||||||
"shape": "rectangle",
|
|
||||||
"fill": "#f4f4f4",
|
|
||||||
"border": "#303030",
|
|
||||||
"text": "Text",
|
|
||||||
"size": {
|
|
||||||
"width": 128.0,
|
|
||||||
"height": 128.0
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"x": 40.0,
|
|
||||||
"y": 40.0,
|
|
||||||
"width": 48.0,
|
|
||||||
"height": 48.0,
|
|
||||||
"text": "C",
|
|
||||||
"color": "#303030",
|
|
||||||
"fontSize": 32.0,
|
|
||||||
"lineStyle": "solid",
|
|
||||||
"lineWidth": 1.5,
|
|
||||||
"stroke": "#303030",
|
|
||||||
"fill": "#ffffff"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"showName": false
|
|
||||||
},
|
|
||||||
"library": {
|
|
||||||
"showSubtree": true
|
|
||||||
},
|
|
||||||
"implementation": {
|
|
||||||
"kind": "text",
|
|
||||||
"source": {
|
|
||||||
"equations": "der(state) = p.f;\np.e = state/c;",
|
|
||||||
"declarations": "",
|
|
||||||
"initialEquations": ""
|
"initialEquations": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -699,7 +577,7 @@
|
|||||||
"id": "parameter-d056bc27",
|
"id": "parameter-d056bc27",
|
||||||
"name": "r",
|
"name": "r",
|
||||||
"type": "real",
|
"type": "real",
|
||||||
"value": "1",
|
"value": "10",
|
||||||
"quantity": "",
|
"quantity": "",
|
||||||
"unit": "",
|
"unit": "",
|
||||||
"dimensions": {
|
"dimensions": {
|
||||||
@@ -868,7 +746,7 @@
|
|||||||
"source": {
|
"source": {
|
||||||
"equations": "der(state) = p.e;\np.f = state/i;",
|
"equations": "der(state) = p.e;\np.f = state/i;",
|
||||||
"declarations": "",
|
"declarations": "",
|
||||||
"initialEquations": ""
|
"initialEquations": "state = 0;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -906,23 +784,6 @@
|
|||||||
"waypoints": []
|
"waypoints": []
|
||||||
},
|
},
|
||||||
"type": "power",
|
"type": "power",
|
||||||
"causality": "target"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ae95fbfc-c771-47f2-8f9e-1c823daaf6b8",
|
|
||||||
"source": {
|
|
||||||
"block": "140ae14b-9dbb-4756-aa25-29101ef2a99e",
|
|
||||||
"port": "port-3e53bf80"
|
|
||||||
},
|
|
||||||
"target": {
|
|
||||||
"block": "6a6fbadd-28ec-4d10-b854-876752a6b287",
|
|
||||||
"port": "port-2e1d884f"
|
|
||||||
},
|
|
||||||
"name": "",
|
|
||||||
"properties": {
|
|
||||||
"waypoints": []
|
|
||||||
},
|
|
||||||
"type": "power",
|
|
||||||
"causality": "source"
|
"causality": "source"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -977,7 +838,7 @@
|
|||||||
"causality": "target"
|
"causality": "target"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "d6940de3-5b4c-42be-a247-639b3803d85e",
|
"id": "e67f412c-39ae-404d-a513-d4a0c389ef40",
|
||||||
"source": {
|
"source": {
|
||||||
"block": "bfa506d8-ee41-4bab-ae19-a97fd67bfcf6",
|
"block": "bfa506d8-ee41-4bab-ae19-a97fd67bfcf6",
|
||||||
"port": "port-3e53bf80"
|
"port": "port-3e53bf80"
|
||||||
@@ -996,7 +857,13 @@
|
|||||||
],
|
],
|
||||||
"annotations": [],
|
"annotations": [],
|
||||||
"junctions": [],
|
"junctions": [],
|
||||||
"simulation": {}
|
"simulation": {
|
||||||
|
"startTime": 0.0,
|
||||||
|
"stopTime": 10.0,
|
||||||
|
"intervalMode": "numberOfIntervals",
|
||||||
|
"numberOfIntervals": 500,
|
||||||
|
"intervalTime": 0.002
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user