merge/model-development-into-main #2
No files matched your search
@@ -0,0 +1,16 @@
|
||||
# test_mql
|
||||
|
||||
Model name used in this repository: `test_mql`.
|
||||
|
||||
Source AMESim archive: `AmesimModels/test_mql.ame`.
|
||||
|
||||
Python port files added for this model:
|
||||
|
||||
- `PythonModels/systems/test_mql.py`
|
||||
- `PythonModels/scripts/run_test_mql.py`
|
||||
|
||||
Current status: structural port scaffold. It records the AMESim component
|
||||
inventory, global parameters, submodel counts, connection topology, and the
|
||||
AMESim modelinfo state counts. Existing PythonModels code is not modified.
|
||||
Detailed physical equations should be filled in incrementally per AMESim
|
||||
submodel family.
|
||||
@@ -0,0 +1,74 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from PythonModels.systems.test_mql import TestMqlRunConfig, TestMqlSystem
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlPathConfig:
|
||||
output_dir: Path | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlExecutionConfig:
|
||||
write_summary: bool = True
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TestMqlScriptConfig:
|
||||
run: TestMqlRunConfig = field(default_factory=TestMqlRunConfig)
|
||||
paths: TestMqlPathConfig = field(default_factory=TestMqlPathConfig)
|
||||
execution: TestMqlExecutionConfig = field(default_factory=TestMqlExecutionConfig)
|
||||
|
||||
|
||||
def _default_output_dir() -> Path:
|
||||
pythonmodels_root = Path(__file__).resolve().parents[1]
|
||||
timestamp = datetime.now(UTC).strftime("test_mql_%Y%m%d_%H%M%S_%f")
|
||||
return pythonmodels_root / "runs" / timestamp
|
||||
|
||||
|
||||
def format_test_mql_summary(system: TestMqlSystem) -> str:
|
||||
snapshot = system.snapshot()
|
||||
lines = [
|
||||
"Model: test_mql",
|
||||
f"Source archive: {system.archive_path}",
|
||||
f"Components: {snapshot.component_count}",
|
||||
f"Connections: {snapshot.connection_count}",
|
||||
f"Continuous states in AMESim modelinfo: {snapshot.continuous_state_count}",
|
||||
f"Discrete states in AMESim modelinfo: {snapshot.discrete_state_count}",
|
||||
"Global parameters:",
|
||||
]
|
||||
for name, value in sorted(snapshot.global_parameters.items()):
|
||||
lines.append(f" - {name}: {value}")
|
||||
lines.append("Component submodels:")
|
||||
for name, count in sorted(snapshot.submodel_counts.items()):
|
||||
lines.append(f" - {name}: {count}")
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def run_test_mql(config: TestMqlScriptConfig | None = None):
|
||||
config = config or TestMqlScriptConfig()
|
||||
system = TestMqlSystem()
|
||||
result = system.simulate(config.run)
|
||||
output_dir = config.paths.output_dir or _default_output_dir()
|
||||
if config.execution.write_summary:
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
(output_dir / "test_mql_model_summary.txt").write_text(
|
||||
format_test_mql_summary(system),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return system, result, output_dir
|
||||
|
||||
|
||||
def main() -> None:
|
||||
system, result, output_dir = run_test_mql()
|
||||
print(format_test_mql_summary(system), end="")
|
||||
print(f"Samples: {len(result.t)}")
|
||||
print(f"Output directory: {output_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large.
Load diff
Whitespace-only changes.
@@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from PythonModels.systems.test_mql import GLOBAL_PARAMETERS, SUBMODEL_COUNTS, TestMqlSystem
|
||||
|
||||
|
||||
class TestMqlStructuralTest(unittest.TestCase):
|
||||
def test_snapshot_matches_amesim_archive_metadata(self) -> None:
|
||||
snapshot = TestMqlSystem().snapshot()
|
||||
|
||||
self.assertEqual(snapshot.model_name, "test_mql")
|
||||
self.assertEqual(snapshot.component_count, 117)
|
||||
self.assertEqual(snapshot.connection_count, 84)
|
||||
self.assertEqual(snapshot.continuous_state_count, 132)
|
||||
self.assertEqual(snapshot.discrete_state_count, 24)
|
||||
self.assertEqual(snapshot.global_parameters["P0"], "153")
|
||||
self.assertEqual(snapshot.global_parameters["cf"], "0.45")
|
||||
|
||||
def test_network_preserves_component_and_connection_counts(self) -> None:
|
||||
system = TestMqlSystem()
|
||||
|
||||
self.assertEqual(len(system.network.components), 117)
|
||||
self.assertEqual(len(system.network.connections), 84)
|
||||
self.assertIn("pn_brp2_8", system.network.components)
|
||||
self.assertIn("pn_gas_data", system.network.components)
|
||||
|
||||
def test_submodel_counts_keep_key_amesim_families(self) -> None:
|
||||
self.assertEqual(SUBMODEL_COUNTS["PNRP17"], 8)
|
||||
self.assertEqual(SUBMODEL_COUNTS["PNCH012"], 8)
|
||||
self.assertEqual(SUBMODEL_COUNTS["PNOR001"], 8)
|
||||
self.assertEqual(SUBMODEL_COUNTS["PNVO001"], 8)
|
||||
self.assertEqual(SUBMODEL_COUNTS["PNGD00"], 1)
|
||||
self.assertEqual(GLOBAL_PARAMETERS["V"], "15")
|
||||
|
||||
def test_structural_simulation_shape(self) -> None:
|
||||
result = TestMqlSystem().simulate()
|
||||
|
||||
self.assertEqual(len(result.t), 101)
|
||||
self.assertEqual(len(result.y), 132)
|
||||
self.assertEqual(result.series["component_count"][0], 117.0)
|
||||
self.assertEqual(result.series["connection_count"][0], 84.0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user