Simple EDB Example

STEPS

  1. Connect to the database

  2. Get ‘base’ for configuration

  3. Get components

  4. Get reactions

  5. Generate IDAES config

1. Connect to the database

By default, the class will attempt to connect to a MongoDB server running on port 27017 (default MongoDB port) on the local host. You can pass a connection string to choose any other valid MongoDB instance.

[1]:
from watertap.edb import ElectrolyteDB

print(f"connecting to {ElectrolyteDB.DEFAULT_URL}")
db = ElectrolyteDB()
connecting to mongodb://localhost:27017

Failure to connect example

If you try to connect to a database and it fails, there will be a logged error message and then the constructor will raise an error. If you really need to defer connection until later, add check_connection=False to the constructor arguments.

[ ]:
db2 = ElectrolyteDB("mongodb://some.other.host", check_connection=False)
print("Didn't check the connection, no exception")

Connecting to Cloud DB

Alternatively, instead of connecting to your local MongoDB instance, you can connect to the cloud-hosted database for WaterTAP. Note: It is generally recommended that you set check_connection=True so that an exception will be thrown if a connection was not available.

[ ]:
public_cloud_url = "mongodb+srv://edbnawi:edb-user@nawi-edb.utpac.mongodb.net"
db_name = "electrolytedb"

db_cloud = ElectrolyteDB(url=public_cloud_url, db=db_name, check_connection=False)

2. Get a ‘base’ for the configuration

For a ‘thermo’ type of IDAES configuration, we will grab the ‘default_thermo’ base.

[11]:
wb = db.get_base("default_thermo")
[12]:
wb.idaes_config
[12]:
{'base_units': {'time': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dc23d0>,
  'length': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dc2460>,
  'mass': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dac970>,
  'amount': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dc27f0>,
  'temperature': <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>},
 'phases': {'Liq': {'type': idaes.core.base.phases.AqueousPhase,
   'equation_of_state': idaes.models.properties.modular_properties.eos.ideal.Ideal}},
 'state_definition': idaes.models.properties.modular_properties.state_definitions.FTPx.FTPx,
 'state_bounds': {'flow_mol': (0, 50, 100),
  'temperature': (273.15, 300, 650),
  'pressure': (50000.0, 100000.0, 1000000.0)},
 'pressure_ref': 100000.0,
 'temperature_ref': 300}

3. Get components

You can get components explicitly or by giving a list of elements.

[13]:
element_list = ["H", "O"]

components = db.get_components(element_names=element_list)

Add components to base configuration

[14]:
for comp in components:
    print(f"adding component {comp.name}")
    wb.add(comp)
adding component H_+
adding component OH_-
adding component H2O

4. Get reactions

You generally want to get all the reactions associated with the same set of components. You can also fetch reactions explicitly by name by providing a reaction_names keyword argument. For fetching by component, the flag any_components controls its behavior. From the docstring:

any_components: If False, the default, only return reactions where
                one side of the reaction has all components provided.
                If true, return the (potentially larger) set of reactions where
                any of the components listed are present.
[15]:
reactions = db.get_reactions(component_names=wb.component_names)
reactions2 = db.get_reactions(component_names=wb.component_names, any_components=True)
for r in reactions2:
    print(r.name)
NH4_Ka
H2CO3_Ka2
Ca[OH]2_Kb1
Ca[OH]2_Kb2
CO2_to_H2CO3
H2CO3_Ka1
H3PO4_Ka2
H3PO4_Ka1
H3PO4_Ka3
HOCl_Ka
NCl3_K
NH2Cl_K
NHCl2_K
H2O_Kw

Add reactions to base configuration

[16]:
for r in reactions:
    print(f"adding {r.reaction_type} reaction: {r.name}")
    # set a reaction order that is different from the stoichiometry
    print(f"- stoichiometry = {r._data['stoichiometry']}")
    # mess with the 'type' of the reaction, if necessary
    r._data["type"] = "inherent"
    wb.add(r)
adding equilibrium reaction: H2O_Kw
- stoichiometry = {'Liq': {'H2O': -1, 'H_+': 1, 'OH_-': 1}}
- reaction order = {'Liq': {'H2O': 0, 'H_+': 1, 'OH_-': 1}}

5. Generate the IDAES config dict

This is done ‘magically’ by accessing the idaes_config property of the base configuration object.

[17]:
config = wb.idaes_config

display(config)
{'base_units': {'time': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dc23d0>,
  'length': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dc2460>,
  'mass': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dac970>,
  'amount': <pyomo.core.base.units_container._PyomoUnit at 0x259f8dc27f0>,
  'temperature': <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>},
 'phases': {'Liq': {'type': idaes.core.base.phases.AqueousPhase,
   'equation_of_state': idaes.models.properties.modular_properties.eos.ideal.Ideal}},
 'state_definition': idaes.models.properties.modular_properties.state_definitions.FTPx.FTPx,
 'state_bounds': {'flow_mol': (0, 50, 100),
  'temperature': (273.15, 300, 650),
  'pressure': (50000.0, 100000.0, 1000000.0)},
 'pressure_ref': 100000.0,
 'temperature_ref': 300,
 'components': {'H_+': {'valid_phase_types': <PhaseType.aqueousPhase: 4>,
   'dens_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'enth_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'cp_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'entr_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'parameter_data': {'mw': (1.00784,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c444c0>),
    'dens_mol_liq_comp_coeff': {'1': (5.459,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259fb1ef790>),
     '2': (0.30542,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>),
     '3': (647.13,
      <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>),
     '4': (0.081,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>)},
    'enth_mol_form_liq_comp_ref': (-230.0,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb1ef130>),
    'cp_mol_liq_comp_coeff': {'1': (276370.0,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c44dc0>),
     '2': (-2090.1,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c44040>),
     '3': (8.125,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c44d00>),
     '4': (-0.014116,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c44250>),
     '5': (9.3701e-06,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7adf0>)},
    'entr_mol_form_liq_comp_ref': (-10.75,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7af10>)},
   'type': idaes.core.base.components.Cation,
   'charge': 1},
  'OH_-': {'valid_phase_types': <PhaseType.aqueousPhase: 4>,
   'dens_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'enth_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'cp_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'entr_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'parameter_data': {'mw': (17.008,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb125040>),
    'dens_mol_liq_comp_coeff': {'1': (5.459,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259c8c188e0>),
     '2': (0.30542,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>),
     '3': (647.13,
      <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>),
     '4': (0.081,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>)},
    'enth_mol_form_liq_comp_ref': (-230.0,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb125a30>),
    'cp_mol_liq_comp_coeff': {'1': (276370.0,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb1256d0>),
     '2': (-2090.1,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb125340>),
     '3': (8.125,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c52cd0>),
     '4': (-0.014116,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fa0a7e20>),
     '5': (9.3701e-06,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c527f0>)},
    'entr_mol_form_liq_comp_ref': (-10.75,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb125370>)},
   'type': idaes.core.base.components.Anion,
   'charge': -1},
  'H2O': {'dens_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'enth_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'cp_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'entr_mol_liq_comp': idaes.models.properties.modular_properties.pure.Perrys.Perrys,
   'enth_mol_ig_comp': idaes.models.properties.modular_properties.pure.NIST.NIST,
   'pressure_sat_comp': idaes.models.properties.modular_properties.pure.NIST.NIST,
   'phase_equilibrium_form': {'Vap': idaes.models.properties.modular_properties.phase_equil.forms.fugacity,
    'Liq': idaes.models.properties.modular_properties.phase_equil.forms.fugacity},
   'parameter_data': {'mw': (18.0153,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fa087fd0>),
    'pressure_crit': (22064000.0,
     <pyomo.core.base.units_container._PyomoUnit at 0x259fb21dac0>),
    'temperature_crit': (647,
     <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>),
    'dens_mol_liq_comp_coeff': {'1': (5.459,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259f8c7a8b0>),
     '2': (0.30542,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>),
     '3': (647.13,
      <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>),
     '4': (0.081,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>)},
    'enth_mol_form_liq_comp_ref': (-285.83,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fa087ee0>),
    'enth_mol_form_vap_comp_ref': (0,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7ad00>),
    'cp_mol_liq_comp_coeff': {'1': (276370.0,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7a340>),
     '2': (-2090.1,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7ad30>),
     '3': (8.125,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7a490>),
     '4': (-0.014116,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7aa90>),
     '5': (9.3701e-06,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7aa00>)},
    'cp_mol_ig_comp_coeff': {'A': (30.092,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7a5e0>),
     'B': (6.832514,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259f8c7a2b0>),
     'C': (6.793435,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259f8c7a190>),
     'D': (-2.53448,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259f8c7aee0>),
     'E': (0.082139,
      <pyomo.core.expr.numeric_expr.NPV_ProductExpression at 0x259f8c7a3a0>),
     'F': (-250.881,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7a0a0>),
     'G': (223.3967,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7a160>),
     'H': (0,
      <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7ac70>)},
    'entr_mol_form_liq_comp_ref': (69.95,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c7a430>),
    'pressure_sat_comp_coeff': {'A': (4.6543,
      <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>),
     'B': (1435.264,
      <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>),
     'C': (-64.848,
      <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>)}},
   'type': idaes.core.base.components.Solvent}},
 'inherent_reactions': {'H2O_Kw': {'stoichiometry': {('Liq', 'H2O'): -1,
    ('Liq', 'H_+'): 1,
    ('Liq', 'OH_-'): 1},
   'heat_of_reaction': idaes.models.properties.modular_properties.reactions.dh_rxn.constant_dh_rxn,
   'equilibrium_constant': idaes.models.properties.modular_properties.reactions.equilibrium_constant.van_t_hoff,
   'equilibrium_form': idaes.models.properties.modular_properties.reactions.equilibrium_forms.log_power_law_equil,
   'concentration_form': <ConcentrationForm.moleFraction: 4>,
   'parameter_data': {'dh_rxn_ref': (55.83,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259fb125880>),
    'ds_rxn_ref': (-80.7,
     <pyomo.core.expr.numeric_expr.NPV_DivisionExpression at 0x259f8c529a0>),
    'k_eq_ref': (3.281873555975635e-18,
     <pyomo.core.base.units_container._PyomoUnit at 0x259fb1a7340>),
    'T_eq_ref': (298,
     <pyomo.core.base.units_container._PyomoUnit at 0x259f8c4ae80>),
     }}}}
[ ]: