Launching of simulation application
This commit is contained in:
95
src/bedit_gui/services/simulation_loader.py
Normal file
95
src/bedit_gui/services/simulation_loader.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
from bedit_core.models import Component, ComponentID, Document, GraphImplementation
|
||||
from bedit_gui.models import Simulation, SimulationMethod
|
||||
from bedit_gui.services import document_files
|
||||
from bedit_gui.simulation_models import CompiledModel, SimulationRoot
|
||||
from bedit_simulation import compile_component_sync
|
||||
|
||||
|
||||
def component_choices(document: Document) -> list[tuple[ComponentID, Component, str]]:
|
||||
choices: list[tuple[ComponentID, Component, str]] = []
|
||||
|
||||
def collect(items: dict[ComponentID, Component], path: tuple[str, ...] = ()) -> None:
|
||||
for component_id, component in items.items():
|
||||
component_path = (*path, component.name)
|
||||
choices.append((component_id, component, ".".join(component_path)))
|
||||
if isinstance(component.implementation, GraphImplementation):
|
||||
collect(component.implementation.graph.components, component_path)
|
||||
|
||||
collect(document.root)
|
||||
return choices
|
||||
|
||||
|
||||
def load_and_compile_bedit(path: str | Path, *, component_selector: str | None = None, simulation_selector: str | None = None, working_directory: str | Path | None = None, omc_command: str = "omc") -> tuple[SimulationRoot, CompiledModel]:
|
||||
"""Open a BEdit document, resolve one launch target, and compile it."""
|
||||
if bool(component_selector) == bool(simulation_selector):
|
||||
raise ValueError("specify exactly one component or simulation settings block")
|
||||
source_path = Path(path).resolve()
|
||||
document = document_files.load(source_path)
|
||||
choices = component_choices(document)
|
||||
settings_name: str | None = None
|
||||
|
||||
if component_selector is not None:
|
||||
component_id, component, component_path = _find_component(choices, component_selector)
|
||||
settings = _default_settings(component_id)
|
||||
else:
|
||||
database = document.metadata.get("simulation_database") if document.metadata is not None else None
|
||||
if database is None or not hasattr(database, "simulations"):
|
||||
raise ValueError("the BEdit document does not contain simulation settings")
|
||||
matches = [(simulation_id, simulation) for simulation_id, simulation in database.simulations.items() if simulation.name == simulation_selector or str(simulation_id) == simulation_selector]
|
||||
if len(matches) != 1:
|
||||
raise ValueError(f"simulation settings {simulation_selector!r} were not found or are ambiguous")
|
||||
_simulation_id, settings = matches[0]
|
||||
component_id, component, component_path = _find_component(choices, str(settings.component))
|
||||
settings_name = settings.name
|
||||
|
||||
build_directory = Path(working_directory) if working_directory is not None else Path(tempfile.mkdtemp(prefix="bedit-compiled-"))
|
||||
root = SimulationRoot(
|
||||
format_version=1,
|
||||
source_document=str(source_path),
|
||||
source_document_id=str(document.id),
|
||||
component=component_id,
|
||||
component_path=component_path,
|
||||
settings_name=settings_name,
|
||||
settings=settings,
|
||||
)
|
||||
return root, _compile(component, build_directory, omc_command)
|
||||
|
||||
|
||||
def compile_simulation_root(root: SimulationRoot, *, working_directory: str | Path | None = None, omc_command: str = "omc") -> CompiledModel:
|
||||
if root.source_document is None:
|
||||
raise ValueError("the simulation does not reference a BEdit source document and cannot be recompiled")
|
||||
document = document_files.load(root.source_document)
|
||||
_component_id, component, _component_path = _find_component(component_choices(document), str(root.component))
|
||||
build_directory = Path(working_directory) if working_directory is not None else Path(tempfile.mkdtemp(prefix="bedit-compiled-"))
|
||||
return _compile(component, build_directory, omc_command)
|
||||
|
||||
|
||||
def _find_component(choices: list[tuple[ComponentID, Component, str]], selector: str) -> tuple[ComponentID, Component, str]:
|
||||
matches = [choice for choice in choices if str(choice[0]) == selector or choice[2] == selector]
|
||||
if len(matches) != 1:
|
||||
raise ValueError(f"component {selector!r} was not found or is ambiguous")
|
||||
return matches[0]
|
||||
|
||||
|
||||
def _default_settings(component_id: ComponentID) -> Simulation:
|
||||
return Simulation(
|
||||
component=component_id,
|
||||
name="Default",
|
||||
start_time=0.0,
|
||||
duration=1.0,
|
||||
use_timed_steps=False,
|
||||
number_of_steps=500,
|
||||
step_size=0.002,
|
||||
method=SimulationMethod.DASSL,
|
||||
dassl_tolerance=1e-6,
|
||||
)
|
||||
|
||||
|
||||
def _compile(component: Component, working_directory: Path, omc_command: str) -> CompiledModel:
|
||||
build = compile_component_sync(component, working_directory, omc_command=omc_command)
|
||||
return CompiledModel(build.model_name, str(build.executable.resolve()), str(build.executable.parent.resolve()))
|
||||
Reference in New Issue
Block a user