feat: integrate AMESim media models and editor UI
This commit is contained in:
1 parent
3e4f466114
commit
e7177ab03e
181 files changed
+7042
-25270
No files matched your search
@@ -17,9 +17,10 @@ from app.simulation.core.catalog import (
|
||||
from app.simulation.core.metadata import (
|
||||
SI_UNIT_BY_QUANTITY,
|
||||
ParameterDefinition,
|
||||
ParameterOption,
|
||||
ResultVariableDefinition,
|
||||
)
|
||||
from app.simulation.core.medium import IdealGasMedium
|
||||
from app.simulation.core.medium import GasMedium, IdealGasMedium
|
||||
from app.simulation.core.ports import PortDefinition, PortVariableDefinition
|
||||
|
||||
|
||||
@@ -81,7 +82,7 @@ class ComponentModelSpec:
|
||||
ports.append(payload)
|
||||
ports.sort(key=lambda item: (int(item["order"]), str(item["name"])))
|
||||
|
||||
return {
|
||||
payload: dict[str, object] = {
|
||||
"type": self.model_type,
|
||||
"modelType": self.model_type,
|
||||
"modelVersion": self.model_version,
|
||||
@@ -94,11 +95,14 @@ class ComponentModelSpec:
|
||||
parameter.as_interface_dict() for parameter in self.parameters
|
||||
],
|
||||
}
|
||||
if self.display.role is not None:
|
||||
payload["role"] = self.display.role
|
||||
return payload
|
||||
|
||||
def create(
|
||||
self,
|
||||
name: str,
|
||||
medium: IdealGasMedium,
|
||||
medium: GasMedium,
|
||||
values: Mapping[str, float],
|
||||
) -> Component:
|
||||
unknown = sorted(set(values) - set(self.parameter_by_name))
|
||||
@@ -410,6 +414,14 @@ def _validate_parameter(
|
||||
raise ValueError(f"{field} declarations must use ParameterDefinition.")
|
||||
_validate_member_id(parameter.name, field=f"{field} name")
|
||||
_validate_label(parameter.label, field=f"{field} '{parameter.name}' label")
|
||||
if not isinstance(parameter.description, str):
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' description must be a string."
|
||||
)
|
||||
if parameter.description and not parameter.description.strip():
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' description must not be blank."
|
||||
)
|
||||
_validate_quantity_unit(
|
||||
parameter.quantity,
|
||||
parameter.unit,
|
||||
@@ -433,6 +445,74 @@ def _validate_parameter(
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' minimum_exclusive must be a boolean."
|
||||
)
|
||||
if parameter.editor not in {
|
||||
None,
|
||||
"amesimGasReference",
|
||||
"amesimGasPropertyModel",
|
||||
}:
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' uses unsupported editor "
|
||||
f"'{parameter.editor}'."
|
||||
)
|
||||
if not isinstance(parameter.options, tuple):
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' options must use a tuple."
|
||||
)
|
||||
if parameter.editor == "amesimGasPropertyModel" and not parameter.options:
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' property-model editor must declare options."
|
||||
)
|
||||
if parameter.options and parameter.editor != "amesimGasPropertyModel":
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' options require the "
|
||||
"'amesimGasPropertyModel' editor."
|
||||
)
|
||||
option_values: list[float] = []
|
||||
for option in parameter.options:
|
||||
if not isinstance(option, ParameterOption):
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' options must use ParameterOption."
|
||||
)
|
||||
if (
|
||||
isinstance(option.value, bool)
|
||||
or not isinstance(option.value, (int, float))
|
||||
or not isfinite(option.value)
|
||||
):
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' option values must be finite numbers."
|
||||
)
|
||||
_validate_label(
|
||||
option.label,
|
||||
field=(
|
||||
f"{field} '{parameter.name}' option "
|
||||
f"'{option.value:g}' label"
|
||||
),
|
||||
)
|
||||
numeric_option = float(option.value)
|
||||
if (
|
||||
parameter.editor == "amesimGasPropertyModel"
|
||||
and not numeric_option.is_integer()
|
||||
):
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' property-model option values "
|
||||
"must be integers."
|
||||
)
|
||||
option_message = parameter.validation_message(numeric_option)
|
||||
if option_message is not None:
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' option {numeric_option:g} "
|
||||
f"{option_message}."
|
||||
)
|
||||
option_values.append(numeric_option)
|
||||
duplicate_option_values = sorted(
|
||||
{value for value in option_values if option_values.count(value) > 1}
|
||||
)
|
||||
if duplicate_option_values:
|
||||
duplicates = ", ".join(f"{value:g}" for value in duplicate_option_values)
|
||||
raise ValueError(
|
||||
f"{field} '{parameter.name}' contains duplicate option values: "
|
||||
f"{duplicates}."
|
||||
)
|
||||
if (
|
||||
parameter.minimum is not None
|
||||
and parameter.maximum is not None
|
||||
@@ -532,6 +612,11 @@ def validate_component_model_class(
|
||||
field=f"Component '{model_type}' display symbol",
|
||||
)
|
||||
_validate_order(display.order, field=f"Component '{model_type}' display order")
|
||||
if display.role not in {None, "amesimGasMediumDefinition"}:
|
||||
raise ValueError(
|
||||
f"Component '{model_type}' DISPLAY uses unsupported role "
|
||||
f"'{display.role}'."
|
||||
)
|
||||
if not isinstance(display.ports, tuple):
|
||||
raise ValueError(f"Component '{model_type}' DISPLAY ports must be a tuple.")
|
||||
if display.library_id != library.id:
|
||||
|
||||
Reference in new issue
Block a user