diff --git a/main.gms b/main.gms index 365b8bd76..55cc5c07c 100755 --- a/main.gms +++ b/main.gms @@ -216,6 +216,12 @@ $offdigit *** turn profiling off (0) or on (1-3, different levels of detail) option profile = 0; +file foo_msg; !! This creates a dummy output file with a well-defined output format: +foo_msg.nr = 1; !! namely F-format (decimal) (and not E-format = scientific notation) +*** The file can throughout the code be activated with `putclose foo_msg;` and used in the form `put_utility foo_msg "msg" / "xxxx"` to print out xxxx to full.lst +*** and be sure that the numeric format is F-format + + *' @title{extrapage: "00_configuration"} Configuration *' @code{extrapage: "00_configuration"} *-------------------------------------------------------------------------- @@ -1644,6 +1650,12 @@ $setglobal c_testOneRegi_region EUR !! def = EUR !! regexp = [A-Z]{3} *** cm_taxrc_RE "switch to define whether tax on (CO2 content of) energy imports is recycled to additional direct investments in renewables (wind, solar and storage)" $setglobal cm_taxrc_RE none !! def = none !! regexp = none|REdirect +*' cm_repeatNonOpt "should nonoptimal regions be solved again?" +*' +*' * (off): no, only infeasable regions are repeated, standard setting +*' * (yes): also non-optimal regions are solved again, up to cm_solver_try_max +$setglobal cm_repeatNonOpt off + *' @stop *------------------------------------------------------------------------------------- diff --git a/modules/80_optimization/nash/declarations.gms b/modules/80_optimization/nash/declarations.gms index 57f944a3a..869bb4cba 100644 --- a/modules/80_optimization/nash/declarations.gms +++ b/modules/80_optimization/nash/declarations.gms @@ -55,6 +55,7 @@ p80_handle(all_regi) "parallel mode handle parameter" p80_repy(all_regi,solveinfo80) "summary report from solver " p80_repy_iteration(all_regi,solveinfo80,iteration) "summary report from solver in iteration" p80_repyLastOptim(all_regi,solveinfo80) "p80_repy from last iteration" +p80_repy_thisSolitr(all_regi,solveinfo80) "p80_repy from the current solitr - only shows results for regions that were run in this solItr" p80_repy_nashitr_solitr(all_regi,solveinfo80,iteration,sol_itr) "summary report from solver in nash iteration and solver iteration" p80_messageFailedMarket(tall,all_enty) "nash display helper" p80_messageShow(convMessage80) "nash display helper" diff --git a/modules/80_optimization/nash/postsolve.gms b/modules/80_optimization/nash/postsolve.gms index 4e54e8927..2763e8920 100644 --- a/modules/80_optimization/nash/postsolve.gms +++ b/modules/80_optimization/nash/postsolve.gms @@ -274,31 +274,31 @@ loop(trade$(NOT tradeSe(trade)), ); ); -*** critertion "infes": and are all solutions optimal? +*** critertion "infes": is any region neither optimal nor intermediate non-optimal -> then it is infeasible loop(regi, - if((p80_repy(regi,'modelstat') ne 2) and (p80_repy(regi,'modelstat') ne 7), - s80_bool = 0; - p80_messageShow("infes") = YES; - ); + if( (p80_repy(regi,'modelstat') ne 2) and (p80_repy(regi,'modelstat') ne 7), !! 2 is optimal, 7 nonopt, + s80_bool = 0; + p80_messageShow("infes") = YES; + ); *** critertion "nonopt": The next lines are a workaround for the status 7 *** problem. If the objective value does not differ too much from the last known *** optimal solution, accept this solution as if it were optimal. - p80_convNashObjVal_iter(iteration,regi) = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval'); - if (1 le iteration.val, - !! no last iteration if this is the first; NA value in p80_repyLastOptim is - !! sticky, so test this separately - if ( p80_repy(regi,'modelstat') eq 7 - !! The 1E-4 are quite arbitrary. One should do more research on how - !! the solution differs over iteration when status 7 occurs. - AND p80_convNashObjVal_iter(iteration,regi) lt - 1e-4, - s80_bool = 0; - p80_messageShow("nonopt") = YES; - display "Not all regions were status 2 in the last iteration. The deviation of the objective function from the last optimal solution is too large to be accepted:"; - s80_dummy = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval'); - display s80_dummy; - ); - ); -); !!regi + p80_convNashObjVal_iter(iteration,regi) = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval'); + if (1 le iteration.val, + !! no last iteration if this is the first; NA value in p80_repyLastOptim is + !! sticky, so test this separately + if ( p80_repy(regi,'modelstat') eq 7 + !! The 1E-4 are quite arbitrary. One should do more research on how + !! the solution differs over iteration when status 7 occurs. + AND p80_convNashObjVal_iter(iteration,regi) lt - 1e-4, + s80_bool = 0; + p80_messageShow("nonopt") = YES; + display "Not all regions were status 2 in the last iteration. The deviation of the objective function from the last optimal solution is too large to be accepted:"; + s80_dummy = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval'); + display s80_dummy; + ); + ); +); !! loop over regi *** criterion only for checking, not applied anymore: are the anticipation terms sufficienctly small? p80_fadeoutPriceAnticip_iter(iteration) = sm_fadeoutPriceAnticip; @@ -406,6 +406,7 @@ display p80_repy; display "trade convergence indicators"; display p80_surplusMaxTolerance, p80_surplusMax2100; +display p80_defic_trade, p80_defic_sum,p80_defic_sum_rel; display "Reasons for non-convergence in this iteration (if not yet converged)"; diff --git a/modules/80_optimization/nash/solve.gms b/modules/80_optimization/nash/solve.gms index d67314902..4e5ef7036 100644 --- a/modules/80_optimization/nash/solve.gms +++ b/modules/80_optimization/nash/solve.gms @@ -15,13 +15,15 @@ hybrid.solvelink = 0; $endif.debug loop (all_regi, - !! only solve for regions that do not have a valid solution for this nash - !! iteration - if ( sol_itr.val gt 1 - AND ( p80_repy(all_regi,"modelstat") eq 2 - OR p80_repy(all_regi,"modelstat") eq 7), - - p80_repy(all_regi,solveinfo80) = 0; + !! only solve for regions that do not have a valid solution for this nash iteration + if ( sol_itr.val gt 1 + AND ( p80_repy(all_regi,"modelstat") eq 2 +$ifthen.repeatNonOpt "%cm_repeatNonOpt%" == "off" + OR p80_repy(all_regi,"modelstat") eq 7 +$endif.repeatNonOpt + ), + + p80_repy_thisSolitr(all_regi,solveinfo80) = 0; continue; ); @@ -49,11 +51,11 @@ loop (all_regi, solve hybrid using nlp maximizing vm_welfareGlob; $ifthene.debug (sameas("%cm_nash_mode%","serial"))OR(sameas("%cm_nash_mode%","debug")) - p80_repy(all_regi,"solvestat") = hybrid.solvestat; - p80_repy(all_regi,"modelstat") = hybrid.modelstat; - p80_repy(all_regi,"resusd") = hybrid.resusd; - p80_repy(all_regi,"objval") = hybrid.objval; - if (p80_repy(all_regi,"modelstat") eq 2, + p80_repy_thisSolitr(all_regi,"solvestat") = hybrid.solvestat; + p80_repy_thisSolitr(all_regi,"modelstat") = hybrid.modelstat; + p80_repy_thisSolitr(all_regi,"resusd") = hybrid.resusd; + p80_repy_thisSolitr(all_regi,"objval") = hybrid.objval; + if (p80_repy_thisSolitr(all_regi,"modelstat") eq 2, p80_repyLastOptim(all_regi,"objval") = p80_repy(all_regi,"objval"); ); $endif.debug @@ -65,13 +67,15 @@ $endif.debug $ifthen.parallel %cm_nash_mode% == "parallel" repeat loop (all_regi$handlecollect(p80_handle(all_regi)), - p80_repy(all_regi,"solvestat") = hybrid.solvestat; - p80_repy(all_regi,"modelstat") = hybrid.modelstat; - p80_repy(all_regi,"resusd") = hybrid.resusd; - p80_repy(all_regi,"objval") = hybrid.objval; + p80_repy_thisSolitr(all_regi,"solvestat") = hybrid.solvestat; + p80_repy_thisSolitr(all_regi,"modelstat") = hybrid.modelstat; + p80_repy_thisSolitr(all_regi,"resusd") = hybrid.resusd; + p80_repy_thisSolitr(all_regi,"objval") = hybrid.objval; + +* p80_repyLatestSolve(all_regi,solveinfo80) = p80_repy(all_regi,solveinfo80); - if (p80_repy(all_regi,"modelstat") eq 2, - p80_repyLastOptim(all_regi,"objval") = p80_repy(all_regi,"objval"); + if (p80_repy_thisSolitr(all_regi,"modelstat") eq 2, + p80_repyLastOptim(all_regi,"objval") = p80_repy_thisSolitr(all_regi,"objval"); ); display$handledelete(p80_handle(all_regi)) "trouble deleting handles" ; @@ -83,19 +87,39 @@ $endif.parallel regi(all_regi) = YES; + +display p80_repy_thisSolitr; +display p80_repy; + *** internal nash helper paramter: pm_SolNonInfes(regi) = 0; p80_SolNonOpt(regi) = 0; + +putclose foo_msg; +*** This putclose serves to make foo_msg the last "active" put file, and thus makes GAMS use the foo_msg formating (namely F-format, not scientific E-format) +*** Otherwise, the following put messages will try to write modelstat in scientif format, throwing errors because of insufficient space + loop (regi, + if( (p80_repy_thisSolitr(regi,"solvestat") > 0) , + put_utility foo_msg "msg" / "Solitr:" sol_itr.tl:2:0 " " regi.tl:4:0 " updated. Modstat new " p80_repy_thisSolitr(regi,"modelstat"):2:0 ", old " p80_repy(regi,"modelstat"):2:0 "; Resusd new" p80_repy_thisSolitr(regi,"resusd"):5:0 ", old" p80_repy(regi,"resusd"):5:0 "; Obj new" p80_repy_thisSolitr(regi,"objval"):7:3 ", old" p80_repy(regi,"objval"):7:3 ; + p80_repy(regi,solveinfo80) = p80_repy_thisSolitr(regi,solveinfo80); !! copy info from this Solitr into p80_repy + else + put_utility foo_msg "msg" / "Solitr:" sol_itr.tl:2:0 " " regi.tl:4:0 " not updated. Modstat new " p80_repy_thisSolitr(regi,"modelstat"):2:0 ", old " p80_repy(regi,"modelstat"):2:0 "; Resusd new" p80_repy_thisSolitr(regi,"resusd"):5:0 ", old" p80_repy(regi,"resusd"):5:0 "; Obj new" p80_repy_thisSolitr(regi,"objval"):7:3 ", old" p80_repy(regi,"objval"):7:3 ; + ); + if (p80_repy(regi,"modelstat") eq 2 OR p80_repy(regi,"modelstat") eq 7, pm_SolNonInfes(regi) = 1; ); if (p80_repy(regi,"modelstat") eq 7, p80_SolNonOpt(regi) = 1); ); -*** set o_modelstat to the highest value across all regions, ignoring status 7 +*** set o_modelstat to the highest value across all regions o_modelstat - = smax(regi, p80_repy(regi,"modelstat")$(p80_repy(regi,"modelstat") ne 7)); +$ifthen.repeatNonOpt "%cm_repeatNonOpt%" == "off" + = smax(regi, p80_repy(regi,"modelstat")$(p80_repy(regi,"modelstat") ne 7)); !! ignoring status 7 +$else.repeatNonOpt + = smax(regi, p80_repy(regi,"modelstat")); !! also taking into account status 7 +$endif.repeatNonOpt *** in cm_nash_mode=debug mode, enable solprint for next sol_itr when last *** iteration was non-optimal: @@ -105,16 +129,22 @@ if (o_modelstat ne 2, ); $endif.solprint -p80_repy_iteration(all_regi,solveinfo80,iteration)$( - p80_repy(all_regi,solveinfo80) ) +p80_repy_iteration(all_regi,solveinfo80,iteration)$( p80_repy_thisSolitr(all_regi,solveinfo80) ) !! add information if this region was solved in this iteration !! store sum of resusd for all sol_itrs = ( p80_repy_iteration(all_regi,solveinfo80,iteration) - + p80_repy(all_regi,solveinfo80) + + p80_repy_thisSolitr(all_regi,solveinfo80) )$( sameas(solveinfo80,"resusd") ) - + p80_repy(all_regi,solveinfo80)$( NOT sameas(solveinfo80,"resusd") ); + + p80_repy_thisSolitr(all_regi,solveinfo80)$( NOT sameas(solveinfo80,"resusd") ); + +p80_repy_nashitr_solitr(all_regi,solveinfo80,iteration,sol_itr)$( p80_repy_thisSolitr(all_regi,solveinfo80) ) !! add information if this region was solved in this iteration + = p80_repy_thisSolitr(all_regi,solveinfo80); + +put_utility "msg" / "Solve overview: The following are the results for iteration " iteration.tl:3:0 " , sol_itr " sol_itr.tl:3:0 ; +display o_modelstat; +display p80_repy; +display p80_repy_thisSolitr; +display p80_repy_iteration; +display p80_repy_nashitr_solitr; -p80_repy_nashitr_solitr(all_regi,solveinfo80,iteration,sol_itr)$( - p80_repy(all_regi,solveinfo80) ) - = p80_repy(all_regi,solveinfo80); *** EOF ./modules/80_optimization/nash/solve.gms