Coverage for backend/ahuora-compounds/ahuora_property_packages/component_metadata.py: 83%
27 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
1"""Read component metadata from the property packages used by IDAES."""
3from functools import lru_cache
5from pyomo.environ import ConcreteModel, units as pyunits, value
7from ahuora_property_packages.build_package import build_package
10@lru_cache(maxsize=128)
11def _molecular_weights_for_package(
12 package_name: str,
13 compounds: tuple[str, ...],
14) -> dict[str, float]:
15 """Build a package once and return its molecular weights in g/mol."""
16 model = ConcreteModel()
17 model.properties = build_package(package_name, list(compounds)) # type: ignore[arg-type]
18 parameter_block = model.properties
20 molecular_weights: dict[str, float] = {}
21 for component_name in parameter_block.component_list:
22 if hasattr(parameter_block, "mw_comp"):
23 molecular_weight = parameter_block.mw_comp[component_name]
24 else:
25 component = parameter_block.get_component(component_name)
26 molecular_weight = getattr(component, "mw", None)
28 if molecular_weight is None: 28 ↛ 29line 28 didn't jump to line 29 because the condition on line 28 was never true
29 continue
30 source_units = pyunits.get_units(molecular_weight)
31 if source_units is None: 31 ↛ 32line 31 didn't jump to line 32 because the condition on line 31 was never true
32 raise ValueError(
33 f"Molecular weight for component {component_name!r} in property "
34 f"package {package_name!r} has no units."
35 )
36 molecular_weights[str(component_name)] = pyunits.convert_value(
37 value(molecular_weight),
38 from_units=source_units,
39 to_units=pyunits.g / pyunits.mol,
40 )
42 return molecular_weights
45def get_component_molecular_weight(
46 package_name: str,
47 compounds: tuple[str, ...],
48 component_name: str,
49) -> float:
50 """Return canonical package component molecular weight in g/mol."""
51 molecular_weights = _molecular_weights_for_package(
52 package_name,
53 tuple(sorted(compounds)),
54 )
55 try:
56 return molecular_weights[component_name]
57 except KeyError as error:
58 raise ValueError(
59 f"Property package {package_name!r} does not expose a molecular "
60 f"weight for component {component_name!r}."
61 ) from error