perf: retain exact flow caches and compiled targets
This commit is contained in:
1 parent
f09dfcf542
commit
22b35b2945
7 files changed
+138
-21
No files matched your search
@@ -327,6 +327,14 @@ class PressureFlowSolver:
|
||||
selected: self._filter_explicit_flow_plan(selected)
|
||||
for selected in (frozenset(("f", "m_flow")), frozenset(("f",)))
|
||||
}
|
||||
self._explicit_flow_unknowns_by_variables = {
|
||||
selected: tuple(
|
||||
unknown
|
||||
for unknown in self.unknowns
|
||||
if unknown.variable in selected
|
||||
)
|
||||
for selected in self._explicit_flow_plans_by_variables
|
||||
}
|
||||
self._equation_scale_plans = self._build_equation_scale_plans(
|
||||
self._equation_templates
|
||||
)
|
||||
@@ -1519,6 +1527,25 @@ class PressureFlowSolver:
|
||||
|
||||
return read_component_equation
|
||||
|
||||
def _connection_flow_target_reader(
|
||||
self,
|
||||
equation,
|
||||
unknown: AlgebraicUnknown,
|
||||
) -> Callable[[], float]:
|
||||
if equation.relation != "sumToZero" or len(equation.variables) != 2:
|
||||
raise ValueError(
|
||||
f"Connection flow equation {equation.id} must sum two variables."
|
||||
)
|
||||
first = self._unknowns_by_id[equation.variables[0]]
|
||||
second = self._unknowns_by_id[equation.variables[1]]
|
||||
if unknown is first:
|
||||
return lambda: 0.0 - (0.0 + second.read())
|
||||
if unknown is second:
|
||||
return lambda: 0.0 - (first.read() + 0.0)
|
||||
raise ValueError(
|
||||
f"Connection flow equation {equation.id} does not contain {unknown.id}."
|
||||
)
|
||||
|
||||
def _pressure_flow_equation_values(self) -> tuple[float, ...]:
|
||||
"""Evaluate live equation values through the compiled topology."""
|
||||
|
||||
@@ -1562,7 +1589,7 @@ class PressureFlowSolver:
|
||||
return ExplicitFlowAssignment(
|
||||
equation_id=equation.id,
|
||||
unknown=unknown,
|
||||
evaluate=self._equation_value_reader(equation),
|
||||
evaluate=self._connection_flow_target_reader(equation, unknown),
|
||||
)
|
||||
|
||||
evaluation = self._component_equation_plans_by_id[equation.owner_id]
|
||||
@@ -1747,6 +1774,7 @@ class PressureFlowSolver:
|
||||
def _evaluate_explicit_flow_stage(
|
||||
stage: ExplicitFlowStage,
|
||||
) -> tuple[float, ...]:
|
||||
"""Evaluate simultaneous targets while this stage's unknowns are zero."""
|
||||
assignments = stage.assignments
|
||||
values: list[float | None] = [None] * len(assignments)
|
||||
for assignment_index, evaluate in stage.direct_evaluations:
|
||||
@@ -1764,7 +1792,9 @@ class PressureFlowSolver:
|
||||
"Compiled algebraic equation disappeared at runtime: "
|
||||
f"{equation_id}."
|
||||
)
|
||||
values[assignment_index] = float(equation_values[equation_index])
|
||||
values[assignment_index] = 0.0 - float(
|
||||
equation_values[equation_index]
|
||||
)
|
||||
if any(value is None for value in values):
|
||||
raise RuntimeError("Explicit flow evaluation plan returned no value.")
|
||||
return tuple(float(value) for value in values)
|
||||
@@ -1776,9 +1806,15 @@ class PressureFlowSolver:
|
||||
"""Execute staged flow/force assignments without repeated equations."""
|
||||
|
||||
selected = frozenset(variables)
|
||||
for unknown in self.unknowns:
|
||||
if unknown.variable in selected:
|
||||
unknown.write(0.0)
|
||||
reset_unknowns = self._explicit_flow_unknowns_by_variables.get(selected)
|
||||
if reset_unknowns is None:
|
||||
reset_unknowns = tuple(
|
||||
unknown
|
||||
for unknown in self.unknowns
|
||||
if unknown.variable in selected
|
||||
)
|
||||
for unknown in reset_unknowns:
|
||||
unknown.write(0.0)
|
||||
|
||||
seeded_ids: set[str] = set()
|
||||
plan = self._explicit_flow_plans_by_variables.get(selected)
|
||||
@@ -1787,14 +1823,7 @@ class PressureFlowSolver:
|
||||
for stage in plan:
|
||||
assignments = stage.assignments
|
||||
values = self._evaluate_explicit_flow_stage(stage)
|
||||
targets = tuple(
|
||||
(
|
||||
assignment,
|
||||
assignment.unknown.read() - value,
|
||||
)
|
||||
for assignment, value in zip(assignments, values)
|
||||
)
|
||||
for assignment, target_value in targets:
|
||||
for assignment, target_value in zip(assignments, values):
|
||||
if not isfinite(target_value):
|
||||
continue
|
||||
assignment.unknown.write(target_value)
|
||||
|
||||
Reference in new issue
Block a user