完成求解器雅可比矩阵首轮优化,增加更新目录,整理了文档文件夹,增加了服务启动脚本

This commit is contained in:
lujingze committed 2026-08-17 07:33:31 +00:00
1 parent 6bb0591d32
commit 16a7eb2d6c
48 files changed
+8172 -217

No files matched your search

@@ -1,6 +1,8 @@
from __future__ import annotations
from collections.abc import Mapping
from collections.abc import Mapping, Sequence
from dataclasses import dataclass
from math import isfinite
from app.simulation.components.amesim.gases import (
AMESIM_GAS_INDEX_PARAMETER,
@@ -14,11 +16,24 @@ from app.simulation.core.metadata import (
ResultVariableDefinition,
THERMODYNAMIC_VOLUME_RESULT_VARIABLES,
)
from app.simulation.core.medium import GasMedium, ThermodynamicProperties
from app.simulation.core.medium import (
GasMedium,
ThermodynamicProperties,
ThermodynamicPropertiesLinearization,
)
from app.simulation.core.ports import PortDefinition
from app.simulation.core.state import VolumeState
@dataclass(frozen=True)
class Pnch012DerivativeLinearization:
derivative: tuple[float, float]
tangents: tuple[tuple[float, ...], tuple[float, ...]]
properties: ThermodynamicPropertiesLinearization
valid: bool = True
reason: str | None = None
class AmesimPnch023(ThermodynamicVolumeComponent):
"""AMESim PNCH023 simple pneumatic chamber with heat exchange.
@@ -518,6 +533,132 @@ class AmesimPnch012(ThermodynamicVolumeComponent):
energy_derivative -= props.p * self.total_volume_rate()
return VolumeState(m=mass_derivative, U=energy_derivative).as_vector()
def linearize_state_derivative(
self,
connected_h: Mapping[str, float],
*,
state_mass_tangent: Sequence[float],
state_energy_tangent: Sequence[float],
external_volume_tangent: Sequence[float],
external_volume_rate_tangent: Sequence[float],
port_mass_flow_tangents: Mapping[str, Sequence[float]],
connected_h_tangents: Mapping[str, Sequence[float]],
property_linearization: ThermodynamicPropertiesLinearization | None = None,
flow_boundary_tolerance: float = 1.0e-12,
) -> Pnch012DerivativeLinearization:
"""Linearize the chamber balance while keeping stream modes fixed."""
port_names = ("port_1", "port_2", "port_3", "port_4")
vectors = {
"state_mass": tuple(float(value) for value in state_mass_tangent),
"state_energy": tuple(float(value) for value in state_energy_tangent),
"volume": tuple(float(value) for value in external_volume_tangent),
"volume_rate": tuple(
float(value) for value in external_volume_rate_tangent
),
}
for port_name in port_names:
vectors[f"flow:{port_name}"] = tuple(
float(value) for value in port_mass_flow_tangents[port_name]
)
vectors[f"enthalpy:{port_name}"] = tuple(
float(value) for value in connected_h_tangents[port_name]
)
widths = {len(values) for values in vectors.values()}
if len(widths) != 1:
raise ValueError("PNCH012 tangent vectors must have equal lengths.")
width = len(vectors["state_mass"])
invalid_reason: str | None = None
if not all(isfinite(value) for values in vectors.values() for value in values):
invalid_reason = "non_finite_tangent_input"
raw_volume = (
self.cvol0
+ sum(self.external_volumes.values())
+ self.connected_external_volume()
)
minimum_volume = self.cvol0 / 100.0
volume_scale = max(abs(raw_volume), abs(minimum_volume), 1.0e-18)
on_volume_boundary = (
abs(raw_volume - minimum_volume) <= 1.0e-12 * volume_scale
)
supplied_volume_tangent = vectors["volume"]
if raw_volume < minimum_volume or on_volume_boundary:
used_volume_tangent = (0.0,) * width
used_volume_rate_tangent = (0.0,) * width
if on_volume_boundary and any(
value != 0.0
for value in (
*supplied_volume_tangent,
*vectors["volume_rate"],
)
):
invalid_reason = invalid_reason or "volume_floor_boundary"
else:
used_volume_tangent = supplied_volume_tangent
used_volume_rate_tangent = vectors["volume_rate"]
properties = property_linearization or self.medium.linearize_properties_from_mU(
self.state.m,
self.state.U,
self.total_volume(),
vectors["state_mass"],
vectors["state_energy"],
used_volume_tangent,
)
if properties.tangents.width != width:
raise ValueError(
"PNCH012 property tangent width must match balance tangents."
)
props = properties.properties
if not properties.valid:
invalid_reason = invalid_reason or properties.reason
mass_derivative = sum(
self.get_port(port_name).m_flow for port_name in port_names
)
volume_rate = self.total_volume_rate()
energy_derivative = self.thermal_energy_flow_w(props.T) - props.p * volume_rate
mass_tangent = [0.0] * width
energy_tangent = [
-self.kth * self.sth * properties.tangents.T[index]
- volume_rate * properties.tangents.p[index]
- props.p * used_volume_rate_tangent[index]
for index in range(width)
]
for port_name in port_names:
port = self.get_port(port_name)
flow_tangent = vectors[f"flow:{port_name}"]
if (
abs(port.m_flow) <= flow_boundary_tolerance
and any(value != 0.0 for value in flow_tangent)
):
invalid_reason = invalid_reason or (
f"flow_direction_boundary:{port_name}"
)
if port.m_flow > 0.0:
inlet_h = connected_h[port_name]
inlet_h_tangent = vectors[f"enthalpy:{port_name}"]
else:
inlet_h = props.h
inlet_h_tangent = properties.tangents.h
energy_derivative += port.m_flow * inlet_h
for index in range(width):
mass_tangent[index] += flow_tangent[index]
energy_tangent[index] += (
inlet_h * flow_tangent[index]
+ port.m_flow * inlet_h_tangent[index]
)
return Pnch012DerivativeLinearization(
derivative=(mass_derivative, energy_derivative),
tangents=(tuple(mass_tangent), tuple(energy_tangent)),
properties=properties,
valid=invalid_reason is None,
reason=invalid_reason,
)
def pressure_flow_equation_values(self) -> tuple[float, ...]:
pressure = self.medium.properties_from_mU(
self.state.m,