diff --git a/idaes/core/initialization/initializer_base.py b/idaes/core/initialization/initializer_base.py index 27f4de040e..5ec8de7f75 100644 --- a/idaes/core/initialization/initializer_base.py +++ b/idaes/core/initialization/initializer_base.py @@ -551,7 +551,7 @@ class ModularInitializerBase(InitializerBase): CONFIG.declare( "solver", ConfigValue( - default=None, # TODO: Can we add a square problem solver as the default here? + default="ipopt_v2", # TODO: Can we add a square problem solver as the default here? # At the moment there is an issue with the scipy solvers not supporting the tee argument. description="Solver to use for initialization", ), @@ -563,6 +563,13 @@ class ModularInitializerBase(InitializerBase): description="Dict of options to pass to solver", ), ) + CONFIG.declare( + "writer_config", + ConfigDict( + implicit=True, + description="Dict of writer_config arguments to pass to solver", + ), + ) CONFIG.declare( "default_submodel_initializer", ConfigValue( @@ -820,6 +827,10 @@ def cleanup(self, model, plugin_initializer_args, sub_initializers): def _get_solver(self): if self._solver is None: - self._solver = get_solver(self.config.solver, self.config.solver_options) + self._solver = get_solver( + self.config.solver, + solver_options=self.config.solver_options, + writer_config=self.config.writer_config, + ) return self._solver diff --git a/idaes/core/initialization/tests/test_initializer_base.py b/idaes/core/initialization/tests/test_initializer_base.py index 94775ac525..2310c13d91 100644 --- a/idaes/core/initialization/tests/test_initializer_base.py +++ b/idaes/core/initialization/tests/test_initializer_base.py @@ -706,8 +706,9 @@ def test_base_attributed(self): assert initializer.config.default_submodel_initializer is None assert initializer._solver is None - assert initializer.config.solver is None + assert initializer.config.solver == "ipopt_v2" assert initializer.config.solver_options == {} + assert initializer.config.writer_config == {} @pytest.mark.unit def test_get_submodel_initializer_specific_model(self): diff --git a/idaes/models/unit_models/heat_exchanger_lc.py b/idaes/models/unit_models/heat_exchanger_lc.py index 53fd069c47..caac107fed 100644 --- a/idaes/models/unit_models/heat_exchanger_lc.py +++ b/idaes/models/unit_models/heat_exchanger_lc.py @@ -254,6 +254,9 @@ def build(self): self._add_wall_variables() self._add_wall_variable_constraints() + self.delta_temperature_in.setlb(1e-8) + self.delta_temperature_out.setlb(1e-8) + if self.config.dynamic_heat_balance: s1_metadata = self.hot_side.config.property_package.get_metadata() diff --git a/idaes/models_extra/temperature_swing_adsorption/initializer.py b/idaes/models_extra/temperature_swing_adsorption/initializer.py index 3c279defd0..f1f1326e3d 100644 --- a/idaes/models_extra/temperature_swing_adsorption/initializer.py +++ b/idaes/models_extra/temperature_swing_adsorption/initializer.py @@ -32,7 +32,6 @@ from idaes.core.util.exceptions import InitializationError from idaes.core.util.model_serializer import to_json, from_json from idaes.core.util.model_statistics import degrees_of_freedom -from idaes.core.solvers import get_solver from idaes.models_extra.temperature_swing_adsorption import SteamCalculationType @@ -107,10 +106,7 @@ def initialization_routine( ) # create solver - if self.config.solver is None: - self.opt = get_solver(self.config.solver, self.config.solver_options) - else: - self.opt = self.config.solver + solver = self._get_solver() # initialization of fixed bed TSA model unit init_log.info("Starting fixed bed TSA initialization") @@ -313,7 +309,7 @@ def initialization_routine( if degrees_of_freedom(blk) == 0: with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(blk, tee=slc.tee) + res = solver.solve(blk, tee=slc.tee) if check_optimal_termination(res): init_log.info( @@ -384,7 +380,7 @@ def initialization_routine( # re-solve compressor model with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(blk.compressor, tee=slc.tee) + res = solver.solve(blk.compressor, tee=slc.tee) if check_optimal_termination(res): init_log.info( @@ -461,7 +457,7 @@ def initialization_routine( ) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(blk.steam_heater, tee=slc.tee) + res = solver.solve(blk.steam_heater, tee=slc.tee) if check_optimal_termination(res): init_log.info_high( @@ -501,7 +497,7 @@ def initialization_routine( ) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(blk.steam_heater, tee=slc.tee) + res = solver.solve(blk.steam_heater, tee=slc.tee) if check_optimal_termination(res): init_log.info_high( @@ -570,7 +566,7 @@ def initialization_routine( if degrees_of_freedom(blk) == 0: with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(blk, tee=slc.tee) + res = solver.solve(blk, tee=slc.tee) if ( blk.config.compressor and blk.config.steam_calculation != SteamCalculationType.none @@ -682,8 +678,9 @@ def _step_initialize(self, cycle_step=None): ) # solve cycle step + solver = self._get_solver() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(cycle_step, tee=slc.tee) + res = solver.solve(cycle_step, tee=slc.tee) if check_optimal_termination(res): init_log.info( @@ -735,8 +732,9 @@ def _false_position_method(self, blk, cycle_step=None, t_guess=None): count = 1 # solve model + solver = self._get_solver() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(cycle_step, tee=slc.tee) + res = solver.solve(cycle_step, tee=slc.tee) if check_optimal_termination(res): init_log.info_high( @@ -778,7 +776,7 @@ def _false_position_method(self, blk, cycle_step=None, t_guess=None): # solve model with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(cycle_step, tee=slc.tee) + res = solver.solve(cycle_step, tee=slc.tee) if check_optimal_termination(res): init_log.info_high( @@ -843,7 +841,7 @@ def _false_position_method(self, blk, cycle_step=None, t_guess=None): # solve model with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: - res = self.opt.solve(cycle_step, tee=slc.tee) + res = solver.solve(cycle_step, tee=slc.tee) if check_optimal_termination(res): init_log.info_high( diff --git a/idaes/models_extra/temperature_swing_adsorption/tests/test_fixed_bed_tsa0d.py b/idaes/models_extra/temperature_swing_adsorption/tests/test_fixed_bed_tsa0d.py index 93ab2ed8cd..0ab6e37361 100644 --- a/idaes/models_extra/temperature_swing_adsorption/tests/test_fixed_bed_tsa0d.py +++ b/idaes/models_extra/temperature_swing_adsorption/tests/test_fixed_bed_tsa0d.py @@ -47,10 +47,7 @@ SteamCalculationType, TransformationScheme, ) -from idaes.models_extra.temperature_swing_adsorption.util import ( - plot_tsa_profiles, - tsa_summary, -) +from idaes.models_extra.temperature_swing_adsorption.util import tsa_summary import idaes.core.util.scaling as iscale # ----------------------------------------------------------------------------- @@ -182,10 +179,6 @@ def test_summary(self, model): assert "Cycle time [h]" in summary_df.index assert "Pressure drop [Pa]" in summary_df.index - @pytest.mark.unit - def test_plotting(self, model): - plot_tsa_profiles(model.fs.unit) - class TestTsaMgmof: # also testing calculate beds and simple steam calcs @@ -249,7 +242,7 @@ def test_units(self, model): @pytest.mark.skipif(solver is None, reason="Solver not available") @pytest.mark.component def test_initialize(self, model): - initializer = FixedBedTSA0DInitializer() + initializer = FixedBedTSA0DInitializer(constraint_tolerance=1e-4) initializer.initialize( model.fs.unit, heating_time_guess=2000, cooling_time_guess=900 )