1010
1111import sys , os , shlex , re , inspect , textwrap , types , pickle , traceback , gc
1212import warnings
13+ import datetime
14+ import platform
15+
16+ from pyomo .solvers .plugins .solvers .direct_or_persistent_solver import (
17+ DirectOrPersistentSolver ,
18+ )
1319
1420import switch_model
1521from switch_model .utilities import (
2026 LogOutput ,
2127 warn ,
2228 query_yes_no ,
23- create_info_file ,
2429 get_module_list ,
2530 add_module_args ,
2631 _ScaledVariable ,
32+ add_git_info ,
2733)
2834from switch_model .upgrade import do_inputs_need_upgrade , upgrade_inputs
2935from switch_model .tools .graphing import graph
36+ from switch_model .utilities .results_info import save_info , add_info , ResultsInfoSection
3037
3138
3239def main (
@@ -116,6 +123,9 @@ def debug(type, value, tb):
116123 if not os .path .isdir (model .options .outputs_dir ):
117124 raise IOError ("Directory specified for prior solution does not exist." )
118125
126+ add_info ("Host name" , platform .node (), section = ResultsInfoSection .GENERAL )
127+ add_git_info ()
128+
119129 # get a list of modules to iterate through
120130 iterate_modules = get_iteration_list (model )
121131
@@ -217,6 +227,7 @@ def debug(type, value, tb):
217227 # (repeated if model is reloaded, to automatically run any new export code)
218228 if not instance .options .no_post_solve :
219229 if instance .options .verbose :
230+ timer .step_time ()
220231 print ("Executing post solve functions..." )
221232 instance .post_solve ()
222233 if instance .options .verbose :
@@ -226,8 +237,23 @@ def debug(type, value, tb):
226237 graph .main (args = ["--overwrite" ])
227238
228239 total_time = start_to_end_timer .step_time_as_str ()
229- create_info_file (
230- getattr (instance .options , "outputs_dir" , "outputs" ), run_time = total_time
240+ add_info ("Total run time" , total_time , section = ResultsInfoSection .GENERAL )
241+
242+ add_info (
243+ "End date" ,
244+ datetime .datetime .now ().strftime ("%Y-%m-%d" ),
245+ section = ResultsInfoSection .GENERAL ,
246+ )
247+ add_info (
248+ "End time" ,
249+ datetime .datetime .now ().strftime ("%H:%M:%S" ),
250+ section = ResultsInfoSection .GENERAL ,
251+ )
252+
253+ save_info (
254+ os .path .join (
255+ getattr (instance .options , "outputs_dir" , "outputs" ), "info.txt"
256+ )
231257 )
232258
233259 if instance .options .verbose :
@@ -921,6 +947,9 @@ def solve(model):
921947 keepfiles = model .options .keepfiles ,
922948 tee = model .options .tee ,
923949 symbolic_solver_labels = model .options .symbolic_solver_labels ,
950+ save_results = model .options .save_solution
951+ if isinstance (solver , DirectOrPersistentSolver )
952+ else None ,
924953 )
925954
926955 if model .options .warm_start is not None :
@@ -992,35 +1021,6 @@ def solve(model):
9921021 )
9931022 raise RuntimeError ("Infeasible model" )
9941023
995- # Raise an error if the solver failed to produce a solution
996- # Note that checking for results.solver.status in {SolverStatus.ok,
997- # SolverStatus.warning} is not enough because with a warning there will
998- # sometimes be a solution and sometimes not.
999- # Note: the results object originally contains values for model components
1000- # in results.solution.variable, etc., but pyomo.solvers.solve erases it via
1001- # result.solution.clear() after calling model.solutions.load_from() with it.
1002- # load_from() loads values into the model.solutions._entry, so we check there.
1003- # (See pyomo.PyomoModel.ModelSolutions.add_solution() for the code that
1004- # actually creates _entry).
1005- # Another option might be to check that model.solutions[-1].status (previously
1006- # result.solution.status, but also cleared) is in
1007- # pyomo.opt.SolutionStatus.['optimal', 'bestSoFar', 'feasible', 'globallyOptimal', 'locallyOptimal'],
1008- # but this seems pretty foolproof (if undocumented).
1009- if len (model .solutions [- 1 ]._entry ["variable" ]) == 0 :
1010- # no solution returned
1011- print ("Solver terminated without a solution." )
1012- print (" Solver Status: " , results .solver .status )
1013- print (" Solution Status: " , model .solutions [- 1 ].status )
1014- print (" Termination Condition: " , results .solver .termination_condition )
1015- if (
1016- model .options .solver == "glpk"
1017- and results .solver .termination_condition == TerminationCondition .other
1018- ):
1019- print (
1020- "Hint: glpk has been known to classify infeasible problems as 'other'."
1021- )
1022- raise RuntimeError ("Solver failed to find an optimal solution." )
1023-
10241024 # Report any warnings; these are written to stderr so users can find them in
10251025 # error logs (e.g. on HPC systems). These can occur, e.g., if solver reaches
10261026 # time limit or iteration limit but still returns a valid solution
0 commit comments