Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ pre-commit
# coverage
pytest-cov

# TODO pin exact version for pylint and astroid
pylint<3
astroid
# pylint and astroid should be pinned to exact versions
pylint==3.3.9
astroid==3.3.11

# docs
sphinx==7.1.*
Expand Down
2 changes: 1 addition & 1 deletion watertap/core/util/chemistry.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def get_charge_group(charge: int) -> str:
group = "Neutrals"
elif charge > 0:
group = "Cations"
elif charge < 0:
else:
group = "Anions"
return group

Expand Down
5 changes: 5 additions & 0 deletions watertap/core/util/initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from idaes.core.util.model_statistics import degrees_of_freedom
import idaes.logger as idaeslog

from watertap.custom_exceptions import FrozenPipes

_log = idaeslog.getLogger(__name__)


Expand Down Expand Up @@ -102,6 +104,9 @@ def check_dof(blk, fail_flag=False, logger=_log, expected_dof=0):
f"Unexpected degrees of freedom: Degrees of freedom on {blk} = {degrees_of_freedom(blk)}. "
f"Expected {expected_dof}. Fix {degrees_of_freedom(blk) - expected_dof} variable(s)"
)
else:
raise FrozenPipes("Logic error in degrees of freedom check.")

if fail_flag:
logger.error(msg)
raise InitializationError(msg)
Expand Down
8 changes: 8 additions & 0 deletions watertap/costing/unit_models/gac.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
from idaes.core.util.exceptions import ConfigurationError
from idaes.core.util.misc import StrEnum
from idaes.core.util.math import smooth_min

from watertap.custom_exceptions import FrozenPipes

from ..util import (
register_costing_parameter_block,
make_capital_cost_var,
Expand Down Expand Up @@ -109,6 +112,11 @@ def _build_gac_cost_param_block(blk, contactor_type):
contactor_cost_coeff_data = {0: 75131.3, 1: 735.550, 2: -1.01827, 3: 0.000000}
other_cost_param_data = {0: 38846.9, 1: 0.490571}
energy_consumption_coeff_data = {0: 0.123782, 1: 0.132403, 2: -1.41512e-5}
else:
raise FrozenPipes(
f"{blk.unit_model.name} GAC costing unable to proceed. "
"Invalid contactor type provided."
)

# ---------------------------------------------------------------------
# design options
Expand Down
9 changes: 8 additions & 1 deletion watertap/costing/unit_models/ion_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#################################################################################

import pyomo.environ as pyo

from watertap.custom_exceptions import FrozenPipes
from ..util import (
register_costing_parameter_block,
make_capital_cost_var,
Expand Down Expand Up @@ -268,6 +270,10 @@ def cost_ion_exchange(blk):

elif ix_type == "anion":
resin_cost = ion_exchange_params.anion_exchange_resin_cost
else:
raise FrozenPipes(
f"Invalid ion exchange type {ix_type}. Valid types are 'cation' or 'anion'."
)

blk.capital_cost_vessel_constraint = pyo.Constraint(
expr=blk.capital_cost_vessel
Expand All @@ -282,7 +288,8 @@ def cost_ion_exchange(blk):
blk.capital_cost_resin_constraint = pyo.Constraint(
expr=blk.capital_cost_resin
== pyo.units.convert(
resin_cost * bed_vol_ft3, to_units=blk.costing_package.base_currency
resin_cost * bed_vol_ft3,
to_units=blk.costing_package.base_currency,
)
)
if blk.unit_model.config.regenerant == "single_use":
Expand Down
19 changes: 19 additions & 0 deletions watertap/custom_exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class FrozenPipes(Exception):
"""
Custom exception for WaterTAP developer errors.

Raised when there's an issue that indicates a problem with the model
implementation or configuration, rather than user input.

Parameters
----------
message : str
Error message describing the issue
"""

def __init__(self, message):
self.message = message
super().__init__(self.message)

def __str__(self):
return f"FrozenPipes: {self.message}"
1 change: 1 addition & 0 deletions watertap/flowsheets/dye_desalination/dye_desalination.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ def eq_flow_mass_comp_gac(blk, j):
else:
m.fs.concentrated_dye = Product(property_package=m.fs.prop_nf)

# pylint: disable=possibly-used-before-assignment
# pretreatment
if hasattr(m.fs, "pretreatment"):
prtrt.wwtp = SecondaryTreatmentWWTPZO(
Expand Down
4 changes: 2 additions & 2 deletions watertap/property_models/multicomp_aq_sol_prop_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2641,8 +2641,8 @@ def assert_electroneutrality(

# touch this var since it is required for this method
self.conc_mol_phase_comp

if solve:

if adjust_by_ion is not None:
ion_before_adjust = state_var["Liq", adjust_by_ion].value
solve = get_solver()
Expand Down Expand Up @@ -2693,7 +2693,7 @@ def assert_electroneutrality(
)
msg = (
f"{adjust_by_ion} adjusted: {state_var}['Liq',{adjust_by_ion}] was adjusted from "
f"{ion_before_adjust} and fixed "
f"{ion_before_adjust} and fixed " # pylint: disable=used-before-assignment
f"to {ion_adjusted}."
)
else:
Expand Down
5 changes: 5 additions & 0 deletions watertap/property_models/water_prop_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
)
import idaes.core.util.scaling as iscale
from watertap.core.util.scaling import transform_property_constraints
from watertap.custom_exceptions import FrozenPipes

# Set up logger
_log = idaeslog.getLogger(__name__)
Expand Down Expand Up @@ -1059,6 +1060,10 @@ def rule_therm_cond_phase(b, p):
) ** (
1 / 3
)
else:
raise FrozenPipes(
f"Index '{p}' is not valid for indexed component 'fs.stream[0].therm_cond_phase"
)
return (
b.therm_cond_phase[p]
== 10**log10_kw * 1e-3 * pyunits.W / pyunits.m / pyunits.K
Expand Down
1 change: 1 addition & 0 deletions watertap/tools/oli_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ def _get_result_link(req_json):
:return result_link: string indicating URL to access call results
"""

result_link = None
if "data" in req_json:
if "status" in req_json["data"]:
if req_json["data"]["status"] in ["IN QUEUE", "IN PROGRESS"]:
Expand Down
2 changes: 2 additions & 0 deletions watertap/tools/oli_api/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
cryptography, cryptography_available = attempt_import(
"cryptography", defer_import=False
)
# could also write a massive ftn to make sure it imports
if cryptography_available:
from cryptography.fernet import Fernet
requests, requests_available = attempt_import("requests", defer_import=False)
Expand Down Expand Up @@ -214,6 +215,7 @@ def _decrypt_credentials(self):
with open(self.config_file, "rb") as f:
encrypted_credentials = f.read()

# pylint: disable=possibly-used-before-assignment
cipher = Fernet(self.encryption_key)
decrypted_credentials = cipher.decrypt(encrypted_credentials).decode()
credentials = json.loads(decrypted_credentials)
Expand Down
3 changes: 3 additions & 0 deletions watertap/tools/oli_api/flash.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from copy import deepcopy
from itertools import product

from watertap.custom_exceptions import FrozenPipes
from watertap.tools.oli_api.util.watertap_to_oli_helper_functions import (
get_oli_name,
get_charge,
Expand Down Expand Up @@ -697,6 +698,8 @@ def _try_float(v):
]
missing_args = _check_args(args)
not_floats = _check_floats(args)
else:
raise FrozenPipes(f"Unsupported flow_type: {flow_type}")
if missing_args:
raise RuntimeError(
f"Missing argument(s) for {flash_method}: {missing_args}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
get_charge_group,
get_molar_mass,
)
from watertap.custom_exceptions import FrozenPipes

# TODO: consider replacing some functionality with molmass: https://pypi.org/project/molmass

Expand Down Expand Up @@ -78,10 +79,15 @@ def get_oli_name(watertap_name: str) -> str:
components = watertap_name.split("_")
if len(components) == 0:
raise IOError(f" Unable to parse solute '{watertap_name}'.")

if len(components) == 1:
molecule = components[0]
elif len(components) == 2:
molecule = components[0] + "ION"
else:
raise FrozenPipes(
f"molecule name could not be determined from the string '{watertap_name}'"
)
oli_name = molecule.replace("[", "").replace("]", "").upper()
return oli_name

Expand Down
1 change: 1 addition & 0 deletions watertap/unit_models/nanofiltration_DSPMDE_0D.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class ConcentrationPolarizationType(Enum):
calculated = auto()


# pylint: disable=possibly-used-before-assignment
@declare_process_block_class("NanofiltrationDSPMDE0D")
class NanofiltrationData(InitializationMixin, UnitModelBlockData):
"""
Expand Down
5 changes: 5 additions & 0 deletions watertap/unit_models/nanofiltration_ZO.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

from watertap.core import ControlVolume0DBlock, InitializationMixin
from watertap.costing.unit_models.nanofiltration import cost_nanofiltration
from watertap.custom_exceptions import FrozenPipes


_log = idaeslog.getLogger(__name__)
Expand Down Expand Up @@ -233,6 +234,10 @@ def build(self):
solute_set = self.config.property_package.ion_set
elif hasattr(self.config.property_package, "solute_set"):
solute_set = self.config.property_package.solute_set
else:
raise FrozenPipes(
"Property package must have either ion_set or solute_set attribute."
)

solvent_solute_set = self.config.property_package.solvent_set | solute_set

Expand Down
12 changes: 5 additions & 7 deletions watertap/unit_models/uv_aop.py
Original file line number Diff line number Diff line change
Expand Up @@ -862,35 +862,33 @@ def calculate_scaling_factors(self):
# these variables should have user input, if not there will be a warning
if iscale.get_scaling_factor(self.uv_intensity) is None:
sf = iscale.get_scaling_factor(self.uv_intensity, default=0.1, warning=True)
iscale.set_scaling_factor(self.uv_intensity, sf)

iscale.set_scaling_factor(self.uv_intensity, sf)
if iscale.get_scaling_factor(self.exposure_time) is None:
sf = iscale.get_scaling_factor(
self.exposure_time, default=1e-2, warning=True
)
iscale.set_scaling_factor(self.exposure_time, sf)

if iscale.get_scaling_factor(self.uv_dose) is None:
sf = iscale.get_scaling_factor(self.uv_dose, default=1e-3, warning=True)
iscale.set_scaling_factor(self.uv_dose, sf)
iscale.set_scaling_factor(self.uv_dose, sf)

if iscale.get_scaling_factor(self.inactivation_rate) is None:
sf = iscale.get_scaling_factor(
self.inactivation_rate, default=1e4, warning=True
)
iscale.set_scaling_factor(self.inactivation_rate, sf)
iscale.set_scaling_factor(self.inactivation_rate, sf)

if iscale.get_scaling_factor(self.rate_constant) is None:
sf = iscale.get_scaling_factor(
self.rate_constant, default=1e3, warning=True
)
iscale.set_scaling_factor(self.rate_constant, sf)
iscale.set_scaling_factor(self.rate_constant, sf)

if iscale.get_scaling_factor(self.electrical_efficiency_phase_comp) is None:
sf = iscale.get_scaling_factor(
self.electrical_efficiency_phase_comp, default=1e-5, warning=True
)
iscale.set_scaling_factor(self.electrical_efficiency_phase_comp, sf)
iscale.set_scaling_factor(self.electrical_efficiency_phase_comp, sf)

if hasattr(self, "photolysis_rate_constant"):
if iscale.get_scaling_factor(self.photolysis_rate_constant) is None:
Expand Down
5 changes: 5 additions & 0 deletions watertap/unit_models/zero_order/coag_and_floc_zo.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from idaes.core import declare_process_block_class

from watertap.core import build_pt, ZeroOrderBaseData
from watertap.custom_exceptions import FrozenPipes

# Some more information about this module
__author__ = "Adam Atia"
Expand Down Expand Up @@ -207,6 +208,10 @@ def rule_chem_flow(blk, t, j):
chemical_dosage = blk.alum_dose[t]
elif j == "polymer":
chemical_dosage = blk.polymer_dose[t]
else:
raise FrozenPipes(
f"Unexpected chemical {j} in coagulation/flocculation unit"
)
return blk.chemical_flow_mass[t, j] == pyunits.convert(
chemical_dosage * blk.properties[t].flow_vol,
to_units=pyunits.kg / pyunits.s,
Expand Down
Loading