Skip to content

Commit

Permalink
refactor to enable serilisation, consistent types, update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bertkdowns committed Oct 30, 2024
1 parent 6da86ae commit 36fff5b
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 220 deletions.
4 changes: 2 additions & 2 deletions Initial_gen/data/chemsep/chemsep1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27092,7 +27092,7 @@ edited to remove two compounds (duplicated in chemsep2):

<compound>
<LibraryIndex name="Index" value="501" />
<CompoundID name="Name" value="Benzene" />
<CompoundID name="Name" value="benzene" />
<StructureFormula name="Structure" value="-CHCHCHCHCHCH-" />
<Family name="Family" value="16" />
<CriticalTemperature name="Critical temperature" units="K" value="562.05" />
Expand Down Expand Up @@ -30481,7 +30481,7 @@ edited to remove two compounds (duplicated in chemsep2):

<compound>
<LibraryIndex name="Index" value="502" />
<CompoundID name="Name" value="Toluene" />
<CompoundID name="Name" value="toluene" />
<StructureFormula name="Structure" value="(C6H5)CH3" />
<Family name="Family" value="16" />
<CriticalTemperature name="Critical temperature" units="K" value="591.75" />
Expand Down
119 changes: 41 additions & 78 deletions compounds/Compound.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,36 @@
from typing import Dict
import os
import json
from pydantic import BaseModel


class Coefficients:
# Allows square bracket access
def __getitem__(self, name: str) -> any:
return self._attributes[name]

def __setitem__(self, name: str, value: any) -> None:
self._attributes[name] = value

def __init__(self, element: ET.Element):
self._attributes = {}
for child in element:
if child.get('value') is not None:
self[child.tag] = convert_string_to_float(child.get('value'))


class UnitValuePair:
def __init__(self, name, value, unit):
self.name = name
self.value = convert_string_to_float(value)
self.unit = unit
def convert_string_to_float(string: str) -> float:
try:
return float(string)
except:
return string

def to_dict(self) -> Dict[str, any]:
return {
'name': self.name,
'value': self.value,
'unit': self.unit
}
class UnitValuePair(BaseModel):
name: str | None
value: float | str | None
unit: str | None

def to_json(self) -> str:
return json.dumps(self.to_dict())

# Helper functions
def parse_element(elem: ET.Element):
try:
return UnitValuePair(elem.get('name'), elem.get('value'), elem.get('units'))
return UnitValuePair(name=elem.get('name'), value=convert_string_to_float(elem.get('value')), unit=elem.get('units'))
except:
return None

Coefficients = Dict[str, float]
def parse_coeff(element: ET.Element) -> Coefficients:
return Coefficients(element)
self = {}
for child in element:
value = child.get('value')
if value is not None:
self[child.tag] = convert_string_to_float(value)
return self

def convert_string_to_float(string: str) -> float:
try:
return float(string)
except:
return string

compound_template = {
'LibraryIndex': parse_element,
Expand Down Expand Up @@ -98,45 +80,26 @@ def convert_string_to_float(string: str) -> float:
'LiquidViscosityRPS': parse_coeff,
}

class Compound:

def __init__(self, name: str) -> None:
"""
Initializes the Compound object.
Args:
name (str): Name of compound.
"""

self._attributes = {}
self._parse_xml(name)

# Allows square bracket access
def __getitem__(self, name: str) -> any:
return self._attributes[name]

def __setitem__(self, name: str, value: any) -> None:
self._attributes[name] = value

def _parse_xml(self, name: str):
"""
Parses the XML string and populates the object's attributes.
Args:
xml_string (str): The XML data as a string.
"""

with open(os.path.dirname(__file__) + "/data_files/" + name + ".xml", 'r') as file:
file = ''.join(file.readlines())

root = ET.fromstring(file)

# Iterating over all attributes in the template
# and parsing the corresponding XML elements
for attr in compound_template:
if root.find(attr) is not None:
self[attr] = compound_template[attr](root.find(attr))
else:
self[attr] = None


Compound = Dict

def load_compound(name: str) -> Compound:
"""
Parses the XML string and populates the object's attributes.
Args:
xml_string (str): The XML data as a string.
"""
self = {}
with open(os.path.dirname(__file__) + "/data_files/" + name.lower() + ".xml", 'r') as file:
file = ''.join(file.readlines())

root = ET.fromstring(file)

# Iterating over all attributes in the template
# and parsing the corresponding XML elements
for attr in compound_template:
if root.find(attr) is not None:
self[attr] = compound_template[attr](root.find(attr))
else:
self[attr] = None
return self
10 changes: 6 additions & 4 deletions compounds/CompoundDB.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .Compound import Compound
from .Compound import load_compound
from typing import Dict
import os

# Loads all the compounds, and enables some basic queries for/on the compounds.
Expand All @@ -14,9 +15,10 @@
for file in os.listdir(os.path.dirname(__file__) + "/data_files"):
if file.endswith(".xml"):
compound_name = file[:-4]
all_compounds[compound_name] = Compound(compound_name)
compound = load_compound(compound_name)
all_compounds[compound_name] = compound

def get_compound(compound_name: str) -> Compound:
def get_compound(compound_name: str) -> Dict:
"""
Returns a Compound object for the given compound name.
Expand All @@ -26,7 +28,7 @@ def get_compound(compound_name: str) -> Compound:
Returns:
Compound: The Compound object.
"""
return all_compounds[compound_name]
return all_compounds[compound_name.lower()]

def get_compound_names() -> list:
"""
Expand Down
2 changes: 1 addition & 1 deletion compounds/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .Compound import Compound
from .Compound import load_compound
2 changes: 1 addition & 1 deletion compounds/data_files/benzene.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<compound>
<LibraryIndex name="Index" value="501" />
<CompoundID name="Name" value="Benzene" />
<CompoundID name="Name" value="benzene" />
<StructureFormula name="Structure" value="-CHCHCHCHCHCH-" />
<Family name="Family" value="16" />
<CriticalTemperature name="Critical temperature" units="K" value="562.05" />
Expand Down
2 changes: 1 addition & 1 deletion compounds/data_files/toluene.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<compound>
<LibraryIndex name="Index" value="502" />
<CompoundID name="Name" value="Toluene" />
<CompoundID name="Name" value="toluene" />
<StructureFormula name="Structure" value="(C6H5)CH3" />
<Family name="Family" value="16" />
<CriticalTemperature name="Critical temperature" units="K" value="591.75" />
Expand Down
4 changes: 2 additions & 2 deletions compounds/tests/create_benzene_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from ..Compound import Compound
from ..Compound import load_compound


def test_parsing():
comp = Compound("Benzene")
comp = load_compound("benzene")
assert comp["AbsEntropy"].value == 269300
assert comp["AbsEntropy"].unit == "J/kmol/K"
4 changes: 2 additions & 2 deletions compounds/tests/load_compounddb_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

def test_load_compounds():
from compounds import CompoundDB as db
assert "Benzene" in db.get_compound_names()
benzene = db.get_compound("Benzene")
assert "benzene" in db.get_compound_names()
benzene = db.get_compound("benzene")
assert benzene["AbsEntropy"].value == 269300
7 changes: 4 additions & 3 deletions property_packages/modular/builder/base_parser.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from typing import List, Dict
from compounds.Compound import Compound
from compounds.Compound import load_compound

class BuildBase:

def __init__(self) -> None:
pass

def serialise(compounds: List[Compound]) -> Dict:

@staticmethod
def serialise( compounds: List[Dict]) -> Dict:
"""
accepts
- List of compounds
Expand Down
15 changes: 12 additions & 3 deletions property_packages/modular/builder/common_parsers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
from .base_parser import BuildBase
from compounds.Compound import Compound
from compounds.Compound import load_compound,Compound
from pyomo.environ import units as pyunits
from idaes.models.properties.modular_properties.state_definitions import FTPx
from idaes.models.properties.modular_properties.phase_equil.bubble_dew import (LogBubbleDew)
Expand All @@ -19,7 +19,7 @@


class base_units_parser(BuildBase):

@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return {
'time': pyunits.s,
Expand All @@ -30,11 +30,12 @@ def serialise(compounds: List[Compound]) -> Dict[str, Any]:
}

class bubble_dew_method_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return LogBubbleDew

class components_parser(BuildBase):

@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:

def serialise_component(compound: Compound) -> Dict[str, Any]:
Expand Down Expand Up @@ -136,10 +137,12 @@ def serialise_component(compound: Compound) -> Dict[str, Any]:
return components_output

class phase_equilibrium_state_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return {("Vap", "Liq"): SmoothVLE} # TODO: Update to Smooth VLE_v2 https://github.com/IDAES/idaes-pse/blob/main/idaes/models/properties/modular_properties/phase_equil/smooth_VLE_2.py

class phases_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return {
"Liq": {
Expand All @@ -155,14 +158,17 @@ def serialise(compounds: List[Compound]) -> Dict[str, Any]:
}

class phases_in_equilibrium_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return [("Vap", "Liq")]

class pressure_ref_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return (101325, pyunits.Pa)

class state_bounds_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return {
"flow_mol": (0, 100, 1000, pyunits.mol / pyunits.s),
Expand All @@ -171,15 +177,18 @@ def serialise(compounds: List[Compound]) -> Dict[str, Any]:
}

class state_definition_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> str:
return FTPx

class temperature_ref_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
return (298.15, pyunits.K)


class pr_kappa_parser(BuildBase):
@staticmethod
def serialise(compounds: List[Compound]) -> Dict[str, Any]:
kappa_parameters = {}
for i, compound1 in enumerate(compounds):
Expand Down
Loading

0 comments on commit 36fff5b

Please sign in to comment.