Skip to content

Make example scripts runnable and expand README - #8

Merged
lucascondeixa merged 1 commit into
masterfrom
fix/update_repo
Aug 13, 2026
Merged

Make example scripts runnable and expand README#8
lucascondeixa merged 1 commit into
masterfrom
fix/update_repo

Conversation

@lucascondeixa

Copy link
Copy Markdown
Collaborator

examples/run.jl:

  • Replace the hard-coded Windows working directory with cd(@DIR) and take the instance path from ARGS, defaulting to the 168-hour instance.
  • Fail early when the instance directory is missing or when the solve returns no solution, instead of erroring later during result extraction.
  • Keep Crossover enabled locally: without it the barrier runs into numerical trouble on these instances. It stays disabled in the cluster scripts.
  • Fix the Expressions and plot_objective_values calls to match their current signatures, and set GKSwstype before Plots loads so it takes effect.
  • Write to output_local so local runs do not clash with the cluster output.

examples/plot.jl: rewrite to re-plot from saved results without re-solving. It now reads the JSON written by run.jl (rebuilding the nested arrays back into their original dimensions), recomputes the expressions and drives perform_plotting.

src/plotting.jl: correct the expressions argument type in the plot_generation_dispatch and plot_generation_capacities dispatch wrappers.

README.md: document the model features and Specs fields, repository layout, instance data format, the result saving/loading options, the time series aggregation and data generation workflows, and the cluster scripts. The usage example was still showing the old API.

examples/run.jl:
- Replace the hard-coded Windows working directory with cd(@__DIR__) and take
  the instance path from ARGS, defaulting to the 168-hour instance.
- Fail early when the instance directory is missing or when the solve returns
  no solution, instead of erroring later during result extraction.
- Keep Crossover enabled locally: without it the barrier runs into numerical
  trouble on these instances. It stays disabled in the cluster scripts.
- Fix the Expressions and plot_objective_values calls to match their current
  signatures, and set GKSwstype before Plots loads so it takes effect.
- Write to output_local so local runs do not clash with the cluster output.

examples/plot.jl: rewrite to re-plot from saved results without re-solving.
It now reads the JSON written by run.jl (rebuilding the nested arrays back
into their original dimensions), recomputes the expressions and drives
perform_plotting.

src/plotting.jl: correct the expressions argument type in the
plot_generation_dispatch and plot_generation_capacities dispatch wrappers.

README.md: document the model features and Specs fields, repository layout,
instance data format, the result saving/loading options, the time series
aggregation and data generation workflows, and the cluster scripts. The usage
example was still showing the old API.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the example workflows and documentation to reflect the current API and to support a clearer “solve once, plot from saved results” workflow for EnergySystemModeling.jl.

Changes:

  • Updates examples/run.jl to be instance-argument driven, write to output_local, fail early on missing instances / missing solutions, and align plotting/expression calls with current signatures.
  • Rewrites examples/plot.jl to regenerate plots purely from saved JSON results without re-solving.
  • Expands README.md with updated usage examples, repository layout, instance format notes, and workflow documentation; and adjusts plotting dispatch wrappers in src/plotting.jl.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/plotting.jl Adjusts plotting wrapper dispatch signatures for expressions dictionaries.
examples/run.jl Makes the run script path/instance-argument driven, improves failure modes, and updates plotting calls.
examples/plot.jl Adds a “replot from saved JSON” workflow (reconstructing arrays and recomputing expressions).
README.md Major documentation expansion and updates usage examples to the newer API.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread examples/run.jl
Comment on lines 2 to +6
push!(LOAD_PATH, dirname(@__DIR__))
using EnergySystemModeling
cd("D:\\Eigene Dateien\\Documents\\GitHub\\EnergySystemModeling.jl\\examples")

ENV["GKSwstype"]="nul" # Prevent opening plots windows (must be set before Plots loads)
cd(@__DIR__)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GR reads GKSwstype lazily rather than at import time, so setting it after using
is fine as long as it happens before the first plotting call. The env inspection
lives in GR.init() (GR.jl src/GR.jl), and the source comment there notes that
init(true) is deferred until load_libs, i.e. until GR actually starts drawing.

Verified empirically: the script runs headless on our cluster/login nodes with this
ordering and writes the PDF/PNG output without ever opening a window.

Comment thread examples/run.jl
Comment on lines 66 to 70
@info "Extracting results"
variables = JuMPVar(model, VariablesDict)
objectives = JuMPObj(model, ObjectivesDict)
expressions = Expressions(parameters, variables)
expressions = Expressions(parameters, specs, variables)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both points don't apply here.

JuMPVar builds its dictionary from a generator whose values have mixed
dimensionality — p_gnt is 3D while p̄_gn and σ_nt are 2D, and all three are
created unconditionally. Dict's runtime type widening typejoins those to exactly
Array{Float64}, so the result is Dict{String, Array{Float64}}, which is the
signature Expressions expects (src/model.jl:117). Checked on Julia 1.10.3:

julia> typeof(Dict(i => f(i) for i in keys(d)))
Dict{String, Array{Float64}}

The first in JuMPObj (src/model.jl:98) is required rather than a bug.
retrieve_data(::AffExpr) is JuMP.value.(a), and JuMP makes AffExpr broadcast as
a RefValue, so that returns a 0-dimensional array which first unwraps to the
number. For the retrieve_data(::Number) method first is a no-op
(first(3.0) === 3.0).

This exact path already produces scalar objective values, e.g. the objectives.json
written by a local run: {"f1":2.3377567708928177e10, "f2":2.4376739928541374e9, ...}.

Comment thread README.md
Comment on lines +128 to +130
variables = JuMPVar(model, VariablesDict)
objectives = JuMPObj(model, ObjectivesDict)
expressions = Expressions(parameters, specs, variables)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the thread on examples/run.jlJuMPVar returns
Dict{String, Array{Float64}} (mixed variable dimensions widen to that), which
matches Expressions, and the first in JuMPObj unwraps the 0-dimensional array
that JuMP.value. returns for an AffExpr. No conversions are needed, so the README
snippet reflects what examples/run.jl actually runs.

Comment thread examples/plot.jl
Comment on lines 2 to +6
push!(LOAD_PATH, dirname(@__DIR__))
using EnergySystemModeling, Parameters, JSON

output = "output"

parameters = load_json(EnergySystemModeling.Params, joinpath(output, "parameters.json"))
variables = load_json(EnergySystemModeling.Variables, joinpath(output, "variables.json"))
objectives = load_json(EnergySystemModeling.Objectives, joinpath(output, "objectives.json"))
expressions = Expressions(parameters, variables)

using Plots
using StatsPlots
pyplot()

savefig(plot_objective_values(objectives),
joinpath(output, "objectives.svg"))

for n in parameters.N
savefig(plot_generation_dispatch(parameters, variables, expressions, n),
joinpath(output, "generation_dispatch_n$n.svg"))
savefig(plot_generation_capacities(parameters, variables, expressions, n),
joinpath(output, "generation_capacities_n$n.svg"))
savefig(plot_storage_level(parameters, variables, expressions, n),
joinpath(output, "storage_n$n.svg"))
savefig(plot_box(parameters, variables, expressions, n),
joinpath(output, "boxplot$n.svg"))

using EnergySystemModeling, JSON

ENV["GKSwstype"]="nul" # Prevent opening plots windows (must be set before Plots loads)
cd(@__DIR__)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the run.jl thread: GR reads GKSwstype in GR.init(), which is deferred
until the first plotting call, so setting it after using still takes effect. This
script runs headless as-is.

@lucascondeixa

Copy link
Copy Markdown
Collaborator Author

Thanks — I went through all four suggestions. They rest on two assumptions that don't
hold here: that GR reads GKSwstype at import time (it reads it lazily in GR.init(),
deferred to the first plotting call), and that JuMPVar returns Dict{String, Any}
(mixed variable dimensions widen to Dict{String, Array{Float64}}, which is what
Expressions takes; the first in JuMPObj unwraps the 0-dim array from
JuMP.value. on an AffExpr). Both paths are exercised by a full local run of
run.jl + plot.jl. No changes made.

@lucascondeixa
lucascondeixa merged commit 618fa5a into master Aug 13, 2026
4 checks passed
@lucascondeixa
lucascondeixa deleted the fix/update_repo branch August 13, 2026 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants