Skip to content

Commit

Permalink
Fixes for Pyomo 6.7 (watertap-org#1224)
Browse files Browse the repository at this point in the history
  • Loading branch information
bknueven authored Dec 5, 2023
1 parent 997b5a3 commit f063c13
Show file tree
Hide file tree
Showing 25 changed files with 34 additions and 90 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
# primary requirements for unit and property models
# maintainers: switch to SPECIAL_DEPENDENCIES_FOR_RELEASE when cutting a release of watertap
*SPECIAL_DEPENDENCIES_FOR_PRERELEASE,
"pyomo>=6.6.1,<6.7", # (also needed for units in electrolyte database (edb))
"pyomo>=6.6.1", # (also needed for units in electrolyte database (edb))
"pyyaml", # watertap.core.wt_database
# the following requirements are for the electrolyte database (edb)
"pymongo>3", # database interface
Expand Down
24 changes: 10 additions & 14 deletions watertap/core/plugins/solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
# "https://github.com/watertap-org/watertap/"
#################################################################################

import logging

import pyomo.environ as pyo
from pyomo.core.base.block import _BlockData
from pyomo.core.kernel.block import IBlock
from pyomo.solvers.plugins.solvers.IPOPT import IPOPT
import pyomo.repn.plugins.nl_writer as _nl_writer

import idaes.core.util.scaling as iscale
from idaes.core.util.scaling import (
Expand All @@ -25,17 +26,15 @@
from idaes.logger import getLogger

_log = getLogger("watertap.core")
_SuffixData = _nl_writer._SuffixData

_pyomo_nl_writer_log = logging.getLogger("pyomo.repn.plugins.nl_writer")

class _WTSuffixData(_SuffixData):
def update(self, suffix):
self.datatype.add(suffix.datatype)
for obj, val in suffix.items():
self._store(obj, val)

def store(self, obj, val):
self._store(obj, val)
def _pyomo_nl_writer_logger_filter(record):
msg = record.getMessage()
if "scaling_factor" in msg and "model contains export suffix" in msg:
return False
return True


@pyo.SolverFactory.register(
Expand All @@ -58,10 +57,6 @@ def _presolve(self, *args, **kwds):
"IpoptWaterTAP.solve takes 1 positional argument: a Pyomo ConcreteModel or Block"
)

# hot patch _SuffixData to prevent an overload
# on error reporting about `scaling_factor`
_nl_writer._SuffixData = _WTSuffixData

# until proven otherwise
self._cleanup_needed = False

Expand Down Expand Up @@ -103,6 +98,7 @@ def _presolve(self, *args, **kwds):
self._model = args[0]
self._cache_scaling_factors()
self._cleanup_needed = True
_pyomo_nl_writer_log.addFilter(_pyomo_nl_writer_logger_filter)

# NOTE: This function sets the scaling factors on the
# constraints. Hence we cache the constraint scaling
Expand Down Expand Up @@ -154,11 +150,11 @@ def _presolve(self, *args, **kwds):
raise

def _cleanup(self):
_nl_writer._SuffixData = _SuffixData
if self._cleanup_needed:
self._reset_scaling_factors()
# remove our reference to the model
del self._model
_pyomo_nl_writer_log.removeFilter(_pyomo_nl_writer_logger_filter)

def _postsolve(self):
self._cleanup()
Expand Down
20 changes: 9 additions & 11 deletions watertap/core/plugins/tests/test_solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@

from pyomo.solvers.plugins.solvers.IPOPT import IPOPT
from pyomo.common.errors import ApplicationError
import pyomo.repn.plugins.nl_writer as _nl_writer
from idaes.core.util.scaling import (
set_scaling_factor,
constraints_with_scale_factor_generator,
)
from idaes.core.solvers import get_solver
from watertap.core.plugins.solvers import IpoptWaterTAP, _SuffixData
from watertap.core.plugins.solvers import IpoptWaterTAP, _pyomo_nl_writer_log


class TestIpoptWaterTAP:
Expand Down Expand Up @@ -112,7 +111,6 @@ def test_postsolve_unscaled_constraints_and_bounds_cleanup(self, m, s):
assert cons_with_sf == [(m.b.d, 1e6)]

assert not hasattr(s, "_model")
assert _nl_writer._SuffixData is _SuffixData

@pytest.mark.unit
def test_option_absorption(self, m, s):
Expand All @@ -121,7 +119,7 @@ def test_option_absorption(self, m, s):
pyo.assert_optimal_termination(results)
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []
del s.options["ignore_variable_scaling"]

@pytest.mark.unit
Expand All @@ -138,7 +136,7 @@ def test_presolve_passthrough(self, m, s):
s._presolve(m, tee=True)
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []
s.options["nlp_scaling_method"] = "user-scaling"

@pytest.mark.unit
Expand All @@ -148,7 +146,7 @@ def test_passthrough_positive(self, m, s):
del s.options["nlp_scaling_method"]
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []

@pytest.mark.unit
def test_passthrough_negative(self, m, s):
Expand All @@ -160,7 +158,7 @@ def test_passthrough_negative(self, m, s):
del s.options["ignore_variable_scaling"]
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []

@pytest.mark.unit
def test_presolve_incorrect_number_of_arguments(self, m, s):
Expand All @@ -181,7 +179,7 @@ def test_presolve_AMPL_evaluation_error(self, m, s):
s.solve(m)
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []
m.a.value = 1

@pytest.mark.unit
Expand All @@ -199,7 +197,7 @@ def test_presolve_AMPL_evaluation_error_cleans_up(self, m, s):
s.solve(m)
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []
m.a.value = 1

@pytest.mark.unit
Expand All @@ -217,7 +215,7 @@ def _bad_presolve(*args, **kwargs):
s.solve(m)
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []
IPOPT._presolve = IPOPT_presolve

@pytest.mark.unit
Expand All @@ -235,7 +233,7 @@ def _bad_constraint_autoscale_large_jac(*args, **kwargs):
s.solve(m)
self._test_bounds(m)
assert not hasattr(s, "_scaling_cache")
assert _nl_writer._SuffixData is _SuffixData
assert _pyomo_nl_writer_log.filters == []
iscale.constraint_autoscale_large_jac = constraint_autoscale_large_jac

@pytest.fixture(scope="class")
Expand Down
4 changes: 1 addition & 3 deletions watertap/examples/custom_model_demo/simple_prop_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ def build(self):
self.NaCl = Component()

# parameters
self.cp = Param(
mutable=False, initialize=4.2e3, units=pyunits.J / (pyunits.kg * pyunits.K)
)
self.cp = Param(initialize=4.2e3, units=pyunits.J / (pyunits.kg * pyunits.K))

dens_mass_param_dict = {"0": 995, "1": 756}
self.dens_mass_param = Param(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ def function(unit):

seq.run(m, function)

solver = get_solver(options={"bound_push": 1e-4})
solver = get_solver()
results = solver.solve(m, tee=False)
check_solve(results, logger=_log, fail_flag=True)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ def test_structure(self, model):
assert degrees_of_freedom(model) == 0
assert_optimal_termination(model.results)

@pytest.mark.requires_idaes_solver
@pytest.mark.integration
def test_results(self, model):
# Treated water
Expand Down Expand Up @@ -144,10 +143,10 @@ def test_results(self, model):
0.101, rel=1e-2
)
assert value(model.fs.Sludge.conc_mass_comp[0, "X_MeOH"]) == pytest.approx(
1.36e-9, rel=1e2
1.81e-7, rel=1e2
)
assert value(model.fs.Sludge.conc_mass_comp[0, "X_MeP"]) == pytest.approx(
1.2e-8, rel=1e2
1.44e-6, rel=1e2
)
assert value(model.fs.Sludge.conc_mass_comp[0, "X_PAO"]) == pytest.approx(
1.95e-6, rel=1e2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def test_ideal_naocl_mixer():
].value == pytest.approx(5.373448801531194e-07, rel=1e-3)


@pytest.mark.requires_idaes_solver
@pytest.mark.component
def test_ideal_naocl_chlorination():
model = run_ideal_naocl_chlorination_example()
Expand All @@ -65,10 +64,9 @@ def test_ideal_naocl_chlorination():
].value == pytest.approx(4.254858076511e-07, rel=1e-3)
assert model.fs.ideal_naocl_chlorination_unit.outlet.mole_frac_comp[
0, "H_+"
].value == pytest.approx(5.75022333462775e-11, rel=1e-3)
].value == pytest.approx(5.64e-11, rel=1e-1)


@pytest.mark.requires_idaes_solver
@pytest.mark.component
def test_ideal_naocl_chlorination_full_block():
model = run_chlorination_block_example(fix_free_chlorine=True)
Expand All @@ -87,10 +85,10 @@ def test_ideal_naocl_chlorination_full_block():
)
assert model.fs.ideal_naocl_chlorination_unit.outlet.mole_frac_comp[
0, "OCl_-"
].value == pytest.approx(4.5088044031726496e-07, rel=1e-3)
].value == pytest.approx(4.48e-07, rel=1e-2)
assert model.fs.ideal_naocl_chlorination_unit.outlet.mole_frac_comp[
0, "H_+"
].value == pytest.approx(5.4260427865375997e-11, rel=1e-3)
].value == pytest.approx(5.43e-11, rel=1e-1)


@pytest.mark.component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,18 @@ def build(self):

self.mw_comp = Param(
self.component_list,
mutable=False,
initialize=extract_data(mw_comp_data),
units=pyunits.kg / pyunits.mol,
doc="Molecular weight",
)

self.dens_mass = Param(
mutable=False,
initialize=1000,
units=pyunits.kg / pyunits.m**3,
doc="Density",
)

self.cp = Param(
mutable=False, initialize=4.2e3, units=pyunits.J / (pyunits.kg * pyunits.K)
)
self.cp = Param(initialize=4.2e3, units=pyunits.J / (pyunits.kg * pyunits.K))

# ---default scaling---
self.set_default_scaling("temperature", 1e-2)
Expand Down
5 changes: 1 addition & 4 deletions watertap/property_models/NDMA_prop_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,12 @@ def build(self):
self.Liq = LiquidPhase()

# heat capacity
self.cp = Param(
mutable=False, initialize=4.2e3, units=pyunits.J / (pyunits.kg * pyunits.K)
)
self.cp = Param(initialize=4.2e3, units=pyunits.J / (pyunits.kg * pyunits.K))

# molecular weight
mw_comp_data = {"H2O": 18.01528e-3, "NDMA": 74.0819e-3}
self.mw_comp = Param(
self.component_list,
mutable=False,
initialize=extract_data(mw_comp_data),
units=pyunits.kg / pyunits.mol,
doc="Molecular weight kg/mol",
Expand Down
1 change: 0 additions & 1 deletion watertap/property_models/NaCl_T_dep_prop_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ def build(self):
mw_comp_data = {"H2O": 18.01528e-3, "NaCl": 58.44e-3}
self.mw_comp = Param(
self.component_list,
mutable=False,
initialize=extract_data(mw_comp_data),
units=pyunits.kg / pyunits.mol,
doc="Molecular weight kg/mol",
Expand Down
1 change: 0 additions & 1 deletion watertap/property_models/NaCl_prop_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ def build(self):
mw_comp_data = {"H2O": 18.01528e-3, "NaCl": 58.44e-3}
self.mw_comp = Param(
self.component_list,
mutable=False,
initialize=extract_data(mw_comp_data),
units=pyunits.kg / pyunits.mol,
doc="Molecular weight kg/mol",
Expand Down
2 changes: 0 additions & 2 deletions watertap/property_models/activated_sludge/asm1_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,12 @@ def build(self):

# Heat capacity of water
self.cp_mass = pyo.Param(
mutable=False,
initialize=4182,
doc="Specific heat capacity of water",
units=pyo.units.J / pyo.units.kg / pyo.units.K,
)
# Density of water
self.dens_mass = pyo.Param(
mutable=False,
initialize=997,
doc="Density of water",
units=pyo.units.kg / pyo.units.m**3,
Expand Down
2 changes: 0 additions & 2 deletions watertap/property_models/activated_sludge/asm2d_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,12 @@ def build(self):

# Heat capacity of water
self.cp_mass = pyo.Param(
mutable=False,
initialize=4182,
doc="Specific heat capacity of water",
units=pyo.units.J / pyo.units.kg / pyo.units.K,
)
# Density of water
self.dens_mass = pyo.Param(
mutable=False,
initialize=997,
doc="Density of water",
units=pyo.units.kg / pyo.units.m**3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,12 @@ def build(self):

# Heat capacity of water
self.cp_mass = pyo.Param(
mutable=False,
initialize=4182,
doc="Specific heat capacity of water",
units=pyo.units.J / pyo.units.kg / pyo.units.K,
)
# Density of water
self.dens_mass = pyo.Param(
mutable=False,
initialize=997,
doc="Density of water",
units=pyo.units.kg / pyo.units.m**3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,12 @@ def build(self):

# Heat capacity of water
self.cp_mass = pyo.Param(
mutable=False,
initialize=4182,
doc="Specific heat capacity of water",
units=pyo.units.J / pyo.units.kg / pyo.units.K,
)
# Density of water
self.dens_mass = pyo.Param(
mutable=False,
initialize=997,
doc="Density of water",
units=pyo.units.kg / pyo.units.m**3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,12 @@ def build(self):

# Heat capacity of water
self.cp_mass = pyo.Param(
mutable=False,
initialize=1.996,
doc="Specific heat capacity of water",
units=pyo.units.J / pyo.units.kg / pyo.units.K,
)
# Density of water
self.dens_mass = pyo.Param(
mutable=False,
# initialize=0.927613356,
initialize=0.01,
doc="Density of water",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,12 @@ def build(self):

# Heat capacity of water
self.cp_mass = pyo.Param(
mutable=False,
initialize=4182,
doc="Specific heat capacity of water",
units=pyo.units.J / pyo.units.kg / pyo.units.K,
)
# Density of water
self.dens_mass = pyo.Param(
mutable=False,
initialize=997,
doc="Density of water",
units=pyo.units.kg / pyo.units.m**3,
Expand Down
Loading

0 comments on commit f063c13

Please sign in to comment.