Replace Python numerical kernels with native C execution
This commit is contained in:
1 parent
48da6be21c
commit
3b38f73fe0
227 files changed
+16801
-75499
No files matched your search
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
|
||||
from app.simulation.core.base import Component, DynamicComponent
|
||||
from app.simulation.core.equations import EquationResidual
|
||||
from app.simulation.core.equations import EquationDefinition
|
||||
from app.simulation.core.metadata import ResultVariableMetadata
|
||||
from app.simulation.core.ports import PortState
|
||||
|
||||
@@ -182,62 +182,25 @@ class SimulationNetwork:
|
||||
)
|
||||
return component.get_port(endpoint.port)
|
||||
|
||||
def connection_equation_residuals(self) -> tuple[EquationResidual, ...]:
|
||||
"""Evaluate connector equations that have a direct scalar residual.
|
||||
|
||||
Stream variables are resolved by the stream-mixing layer and therefore do
|
||||
not incorrectly appear here as an equality between outflow properties.
|
||||
"""
|
||||
|
||||
residuals: list[EquationResidual] = []
|
||||
def connection_equation_definitions(self) -> tuple[EquationDefinition, ...]:
|
||||
equations=[]
|
||||
for connection in self.connections:
|
||||
if connection.kind != "physical":
|
||||
continue
|
||||
|
||||
first_port = self._port_for(connection.endpoint_a)
|
||||
second_port = self._port_for(connection.endpoint_b)
|
||||
definition = first_port.definition
|
||||
if definition is None:
|
||||
raise ValueError(
|
||||
f"Connected port {connection.endpoint_a} has no interface definition."
|
||||
)
|
||||
|
||||
if connection.kind!='physical':continue
|
||||
definition=self._port_for(connection.endpoint_a).definition
|
||||
for variable in definition.variables:
|
||||
if variable.connection_rule == "equal":
|
||||
value = float(getattr(first_port, variable.name)) - float(
|
||||
getattr(second_port, variable.name)
|
||||
)
|
||||
elif variable.connection_rule == "sumToZero":
|
||||
value = float(getattr(first_port, variable.name)) + float(
|
||||
getattr(second_port, variable.name)
|
||||
)
|
||||
else:
|
||||
continue
|
||||
residuals.append(
|
||||
EquationResidual(
|
||||
id=f"{connection.id}:{variable.name}",
|
||||
owner="connection",
|
||||
owner_id=connection.id,
|
||||
relation=variable.connection_rule,
|
||||
variables=(
|
||||
f"{connection.endpoint_a}.{variable.name}",
|
||||
f"{connection.endpoint_b}.{variable.name}",
|
||||
),
|
||||
role=variable.role,
|
||||
value=value,
|
||||
)
|
||||
)
|
||||
return tuple(residuals)
|
||||
if variable.connection_rule not in ('equal','sumToZero'):continue
|
||||
equations.append(EquationDefinition(id=f'{connection.id}:{variable.name}',owner='connection',owner_id=connection.id,relation=variable.connection_rule,variables=(f'{connection.endpoint_a}.{variable.name}',f'{connection.endpoint_b}.{variable.name}'),role=variable.role))
|
||||
return tuple(equations)
|
||||
|
||||
def pressure_flow_equation_residuals(self) -> tuple[EquationResidual, ...]:
|
||||
def equation_definitions(self) -> tuple[EquationDefinition, ...]:
|
||||
"""Evaluate the complete algebraic pressure-flow equation subsystem."""
|
||||
|
||||
component_residuals = tuple(
|
||||
residual
|
||||
for component in self.components.values()
|
||||
for residual in component.pressure_flow_equation_residuals()
|
||||
for residual in component.equation_definitions()
|
||||
)
|
||||
return component_residuals + self.connection_equation_residuals()
|
||||
return component_residuals + self.connection_equation_definitions()
|
||||
|
||||
def pressure_flow_unknowns(self) -> tuple[str, ...]:
|
||||
return tuple(
|
||||
@@ -251,7 +214,7 @@ class SimulationNetwork:
|
||||
|
||||
def pressure_flow_structure_dict(self) -> dict[str, object]:
|
||||
unknowns = self.pressure_flow_unknowns()
|
||||
equations = self.pressure_flow_equation_residuals()
|
||||
equations = self.equation_definitions()
|
||||
return {
|
||||
"unknownCount": len(unknowns),
|
||||
"equationCount": len(equations),
|
||||
@@ -269,20 +232,7 @@ class SimulationNetwork:
|
||||
if isinstance(component, DynamicComponent)
|
||||
]
|
||||
|
||||
def initial_state_vector(self) -> list[float]:
|
||||
values: list[float] = []
|
||||
for component in self.dynamic_components():
|
||||
values.extend(component.get_state_vector())
|
||||
return values
|
||||
|
||||
def apply_state_vector(self, values: list[float]) -> None:
|
||||
cursor = 0
|
||||
for component in self.dynamic_components():
|
||||
next_cursor = cursor + component.state_size
|
||||
component.set_state_vector(values[cursor:next_cursor])
|
||||
cursor = next_cursor
|
||||
if cursor != len(values):
|
||||
raise ValueError("State vector length does not match dynamic components.")
|
||||
|
||||
def result_variable_metadata(self) -> tuple[ResultVariableMetadata, ...]:
|
||||
return tuple(
|
||||
|
||||
Reference in new issue
Block a user