From f10e745a6a8a40c7070096a52bfd043c6fae2c00 Mon Sep 17 00:00:00 2001 From: Tomas Date: Thu, 20 Nov 2025 14:06:00 -0800 Subject: [PATCH 1/3] making solver-log-dir option work with EF on generic cylinders. fixing small bug in GurobiDirect that makes the logs not always be saved properly --- mpisppy/generic_cylinders.py | 17 +++++++++++++++-- mpisppy/spopt.py | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mpisppy/generic_cylinders.py b/mpisppy/generic_cylinders.py index fa1dc0f2d..6724f6960 100644 --- a/mpisppy/generic_cylinders.py +++ b/mpisppy/generic_cylinders.py @@ -24,6 +24,7 @@ from mpisppy.extensions.extension import MultiExtension, Extension import mpisppy.utils.solver_spec as solver_spec +from pyomo.solvers.plugins.solvers.gurobi_direct import GurobiDirect from mpisppy import global_toc from mpisppy import MPI @@ -568,11 +569,23 @@ def _do_EF(module, cfg, scenario_creator, scenario_creator_kwargs, scenario_deno # We probably could just assign the dictionary in one line... for option_key,option_value in solver_options.items(): solver.options[option_key] = option_value + + solver_log_dir = cfg.get("solver_log_dir","") + solve_kw_args = dict() + if solver_log_dir and len(solver_log_dir)>0: + os.makedirs(solver_log_dir, exist_ok=True) + solve_kw_args['keepfiles'] = True + log_fn = f"EFsolverlog.log" + solve_kw_args['logfile'] = os.path.join(solver_log_dir, log_fn) + if isinstance(solver, GurobiDirect): + solver.options['LogToConsole'] = cfg.tee_EF + solver.options['OutputFlag'] = True + if 'persistent' in solver_name: solver.set_instance(ef, symbolic_solver_labels=True) - results = solver.solve(tee=cfg.tee_EF) + results = solver.solve(tee=cfg.tee_EF, **solve_kw_args) else: - results = solver.solve(ef, tee=cfg.tee_EF, symbolic_solver_labels=True,) + results = solver.solve(ef, tee=cfg.tee_EF, symbolic_solver_labels=True, **solve_kw_args) if not pyo.check_optimal_termination(results): print("Warning: non-optimal solver termination") diff --git a/mpisppy/spopt.py b/mpisppy/spopt.py index 71df08488..ce92c9e0d 100644 --- a/mpisppy/spopt.py +++ b/mpisppy/spopt.py @@ -214,7 +214,9 @@ def _vb(msg): # Workaround for Pyomo/pyomo#3589: Setting 'keepfiles' to True is required # for proper functionality when using the GurobiDirect / GurobiPersistent solver. if isinstance(s._solver_plugin, GurobiDirect): + s._solver_plugin.options["LogToConsole"] = tee s._solver_plugin.options["LogFile"] = os.path.join(dir_name, file_name) + s._solver_plugin.options["OutputFlag"] = 1 else: solve_keyword_args["logfile"] = os.path.join(dir_name, file_name) self._subproblem_solve_index[k] += 1 From 528da7a3dee4ba6efb2d87c95828eae5e649f6aa Mon Sep 17 00:00:00 2001 From: Tomas Date: Thu, 20 Nov 2025 15:45:16 -0800 Subject: [PATCH 2/3] no changes needed to spopt, only in generic_cylinders --- mpisppy/generic_cylinders.py | 4 ---- mpisppy/spopt.py | 2 -- 2 files changed, 6 deletions(-) diff --git a/mpisppy/generic_cylinders.py b/mpisppy/generic_cylinders.py index 6724f6960..f4d7d64eb 100644 --- a/mpisppy/generic_cylinders.py +++ b/mpisppy/generic_cylinders.py @@ -24,7 +24,6 @@ from mpisppy.extensions.extension import MultiExtension, Extension import mpisppy.utils.solver_spec as solver_spec -from pyomo.solvers.plugins.solvers.gurobi_direct import GurobiDirect from mpisppy import global_toc from mpisppy import MPI @@ -577,9 +576,6 @@ def _do_EF(module, cfg, scenario_creator, scenario_creator_kwargs, scenario_deno solve_kw_args['keepfiles'] = True log_fn = f"EFsolverlog.log" solve_kw_args['logfile'] = os.path.join(solver_log_dir, log_fn) - if isinstance(solver, GurobiDirect): - solver.options['LogToConsole'] = cfg.tee_EF - solver.options['OutputFlag'] = True if 'persistent' in solver_name: solver.set_instance(ef, symbolic_solver_labels=True) diff --git a/mpisppy/spopt.py b/mpisppy/spopt.py index ce92c9e0d..71df08488 100644 --- a/mpisppy/spopt.py +++ b/mpisppy/spopt.py @@ -214,9 +214,7 @@ def _vb(msg): # Workaround for Pyomo/pyomo#3589: Setting 'keepfiles' to True is required # for proper functionality when using the GurobiDirect / GurobiPersistent solver. if isinstance(s._solver_plugin, GurobiDirect): - s._solver_plugin.options["LogToConsole"] = tee s._solver_plugin.options["LogFile"] = os.path.join(dir_name, file_name) - s._solver_plugin.options["OutputFlag"] = 1 else: solve_keyword_args["logfile"] = os.path.join(dir_name, file_name) self._subproblem_solve_index[k] += 1 From e73b886f8a5729f6135553add45fb70ffefc9a63 Mon Sep 17 00:00:00 2001 From: Tomas Date: Thu, 20 Nov 2025 15:51:03 -0800 Subject: [PATCH 3/3] fixing ruff linting error --- mpisppy/generic_cylinders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpisppy/generic_cylinders.py b/mpisppy/generic_cylinders.py index f4d7d64eb..e3ccdd7d0 100644 --- a/mpisppy/generic_cylinders.py +++ b/mpisppy/generic_cylinders.py @@ -574,7 +574,7 @@ def _do_EF(module, cfg, scenario_creator, scenario_creator_kwargs, scenario_deno if solver_log_dir and len(solver_log_dir)>0: os.makedirs(solver_log_dir, exist_ok=True) solve_kw_args['keepfiles'] = True - log_fn = f"EFsolverlog.log" + log_fn = "EFsolverlog.log" solve_kw_args['logfile'] = os.path.join(solver_log_dir, log_fn) if 'persistent' in solver_name: