Skip to content

Commit

Permalink
Add new tests for seven modules. Include GH workflow. (#563)
Browse files Browse the repository at this point in the history
This PR adds seven more tests to GenX: three-zone, multi-stage,
electrolyzer, VRE+storage, piecewise_fuel+CO2, TDR, and Method of Morris.
The tests are passed if the value of the objective function is
consistent over time (up to the tolerance of the solver).
The tests for the TDR validate the clustering by computing the rand
index and the mutual information and comparing the output files.
For the Method of Morris module, we are testing if the module is
correctly built and if the output is consistent over time.
  • Loading branch information
lbonaldo committed Nov 13, 2023
1 parent 60ca831 commit 2091f85
Show file tree
Hide file tree
Showing 125 changed files with 49,081 additions and 30 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: CI

on:
pull_request:
push:
branches: [main, develop]
tags: ['*']

jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name}}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- "1.6" # LTS (64-bit Linux)
- "1.7"
- "1.8"
- '1.9' # latest stable Julia release (Linux)
os:
- ubuntu-latest
arch:
- x64
include: # additional tests [Julia-nightly] (Linux)
- os: ubuntu-latest
version: 'nightly'
arch: x64
allow_failure: true
steps:
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
file: lcov.info
15 changes: 0 additions & 15 deletions .github/workflows/ci_test.yml

This file was deleted.

6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ gurobi.log
cplex.log
Highs.log

test/Logs

/docs/build/

# Microsoft office temporary files
Expand All @@ -42,3 +44,7 @@ Example_Systems/SmallNewEngland/ThreeZones_full/*

Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/*
test_get_retirement_period.jl

# Test files
test/TDR/TDR_Results_test
test/MethodofMorris/morris.csv
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add PR template (#516)
- Validation ensures that resource flags (THERM, HYDRO, LDS etc) are self-consistent (#513).
- Maintenance formulation for thermal-commit plants (#556).
- Add new tests for GenX: three-zone, multi-stage, electrolyzer, VRE+storage,
piecewise_fuel+CO2, TDR, and Method of Morris (#563).


### Fixed
- Set MUST_RUN=1 for RealSystemExample/small_hydro plants (#517).
Expand Down
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ YAML = "0.4.7"
julia = "1"

[extras]
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "Logging"]
test = ["Test", "JLD2", "Logging", "LoggingExtras"]
1 change: 1 addition & 0 deletions src/GenX.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export choose_output_dir
export run_ddp
export configure_multi_stage_inputs
export load_inputs_multi_stage
export compute_cumulative_min_retirements!
export write_multi_stage_outputs
export run_genx_case!
export run_timedomainreduction!
Expand Down
13 changes: 9 additions & 4 deletions src/additional_tools/method_of_morris.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const SEED = 1234


@doc raw"""
morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER)
Expand All @@ -14,6 +17,7 @@ struct MorrisResult{T1,T2}
variances::T1
elementary_effects::T2
end

function generate_design_matrix(p_range, p_steps, rng;len_design_mat,groups)
ps = [range(p_range[i][1], stop=p_range[i][2], length=p_steps[i]) for i in 1:length(p_range)]
indices = [rand(rng, 1:i) for i in p_steps]
Expand Down Expand Up @@ -74,8 +78,9 @@ function sample_matrices(p_range,p_steps, rng;num_trajectory,total_num_trajector
reduce(hcat,matrices)
end

function my_gsa(f, p_steps, num_trajectory, total_num_trajectory, p_range::AbstractVector,len_design_mat,groups)
function my_gsa(f, p_steps, num_trajectory, total_num_trajectory, p_range::AbstractVector, len_design_mat, groups, random)
rng = Random.default_rng()
if !random; Random.seed!(SEED); end
design_matrices_original = sample_matrices(p_range, p_steps, rng;num_trajectory,
total_num_trajectory,len_design_mat,groups)
println(design_matrices_original)
Expand Down Expand Up @@ -158,7 +163,7 @@ function my_gsa(f, p_steps, num_trajectory, total_num_trajectory, p_range::Abstr
end
MorrisResult(reduce(hcat, means),reduce(hcat, means_star),reduce(hcat, variances),effects)
end
function morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER)
function morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER; random=true)

# Reading the input parameters
Morris_range = load_dataframe(joinpath(path, "Method_of_morris_range.csv"))
Expand Down Expand Up @@ -197,7 +202,7 @@ function morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outp
end

# Perform the method of morris analysis
m = my_gsa(f1,p_steps,num_trajectory,total_num_trajectory,p_range,len_design_mat,groups)
m = my_gsa(f1,p_steps,num_trajectory,total_num_trajectory,p_range,len_design_mat,groups,random)
println(m.means)
println(DataFrame(m.means', :auto))
#save the mean effect of each uncertain variable on the objective fucntion
Expand All @@ -207,5 +212,5 @@ function morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outp
Morris_range[!,:variance] = DataFrame(m.variances', :auto)[!,:x1]

CSV.write(joinpath(outpath, "morris.csv"), Morris_range)

return Morris_range
end
21 changes: 13 additions & 8 deletions src/time_domain_reduction/time_domain_reduction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ using Distances
using CSV
using GenX


const SEED = 1234

@doc raw"""
rmse_score(y_true, y_pred)
Expand Down Expand Up @@ -202,7 +205,7 @@ function get_worst_period_idx(R)
end

@doc raw"""
cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters)
cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false, random=true)
Get representative periods using cluster centers from kmeans or kmedoids.
Expand All @@ -212,12 +215,13 @@ https://juliastats.org/Clustering.jl/dev/kmeans.html
K-Medoids:
https://juliastats.org/Clustering.jl/stable/kmedoids.html
"""
function cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false)
function cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false, random=true)
if ClusterMethod == "kmeans"
DistMatrix = pairwise(Euclidean(), Matrix(ClusteringInputDF), dims=2)
R = kmeans(Matrix(ClusteringInputDF), NClusters, init=:kmcen)

for i in 1:nIters
if !random; Random.seed!(SEED); end
R_i = kmeans(Matrix(ClusteringInputDF), NClusters)

if R_i.totalcost < R.totalcost
Expand All @@ -243,6 +247,7 @@ function cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false)
R = kmedoids(DistMatrix, NClusters, init=:kmcen)

for i in 1:nIters
if !random; Random.seed!(SEED); end
R_i = kmedoids(DistMatrix, NClusters)
if R_i.totalcost < R.totalcost
R = R_i
Expand All @@ -257,7 +262,7 @@ function cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false)
M = R.medoids # get the cluster centers - M for Medoids
else
println("INVALID ClusterMethod. Select kmeans or kmedoids. Running kmeans instead.")
return cluster("kmeans", ClusteringInputDF, NClusters, nIters)
return cluster("kmeans", ClusteringInputDF, NClusters, nIters, v, random)
end
return [R, A, W, M, DistMatrix]
end
Expand Down Expand Up @@ -485,7 +490,7 @@ end


@doc raw"""
cluster_inputs(inpath, settings_path, v=false, norm_plot=false, silh_plot=false, res_plots=false, indiv_plots=false, pair_plots=false)
cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false; random=true)
Use kmeans or kmedoids to cluster raw demand profiles and resource capacity factor profiles
into representative periods. Use Extreme Periods to capture noteworthy periods or
Expand Down Expand Up @@ -538,7 +543,7 @@ to separate Vre_and_stor_solar_variability.csv and Vre_and_stor_wind_variability
and wind profiles for co-located resources will be separated into different CSV files to be read by loading the inputs
after the clustering of the inputs has occurred.
"""
function cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false)
function cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false; random=true)
if v println(now()) end

##### Step 0: Load in settings and data
Expand Down Expand Up @@ -781,7 +786,7 @@ function cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false)
cluster_results = []

# Cluster once regardless of iteration decisions
push!(cluster_results, cluster(ClusterMethod, ClusteringInputDF, NClusters, nReps, v))
push!(cluster_results, cluster(ClusterMethod, ClusteringInputDF, NClusters, nReps, v, random))

# Iteratively add worst periods as extreme periods OR increment number of clusters k
# until threshold is met or maximum periods are added (If chosen in inputs)
Expand All @@ -790,15 +795,15 @@ function cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false)
if IterateMethod == "cluster"
if v println("Adding a new Cluster! ") end
NClusters += 1
push!(cluster_results, cluster(ClusterMethod, ClusteringInputDF, NClusters, nReps, v))
push!(cluster_results, cluster(ClusterMethod, ClusteringInputDF, NClusters, nReps, v, random))
elseif (IterateMethod == "extreme") & (UseExtremePeriods == 1)
if v println("Adding a new Extreme Period! ") end
worst_period_idx = get_worst_period_idx(last(cluster_results)[1])
removed_period = string(names(ClusteringInputDF)[worst_period_idx])
select!(ClusteringInputDF, Not(worst_period_idx))
push!(ExtremeWksList, parse(Int, removed_period))
if v println(worst_period_idx, " (", removed_period, ") ", ExtremeWksList) end
push!(cluster_results, cluster(ClusterMethod, ClusteringInputDF, NClusters, nReps, v))
push!(cluster_results, cluster(ClusterMethod, ClusteringInputDF, NClusters, nReps, v, random))
elseif IterateMethod == "extreme"
println("INVALID IterateMethod ", IterateMethod, " because UseExtremePeriods is off. Set to 1 if you wish to add extreme periods.")
break
Expand Down
121 changes: 121 additions & 0 deletions test/Electrolyzer/Demand_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1
50000,1,1,1,5,24,24.0,1,11122.0
,,,,,,3672.0,2,10655.0
,,,,,,5016.0,3,10441.0
,,,,,,24.0,4,10365.0
,,,,,,24.0,5,10639.0
,,,,,,,6,11577.0
,,,,,,,7,13349.0
,,,,,,,8,14550.0
,,,,,,,9,14922.0
,,,,,,,10,15165.0
,,,,,,,11,15328.0
,,,,,,,12,15380.0
,,,,,,,13,15275.0
,,,,,,,14,15154.0
,,,,,,,15,14953.0
,,,,,,,16,14885.0
,,,,,,,17,15340.0
,,,,,,,18,16003.0
,,,,,,,19,15767.0
,,,,,,,20,15236.0
,,,,,,,21,14663.0
,,,,,,,22,13889.0
,,,,,,,23,12855.0
,,,,,,,24,11809.0
,,,,,,,25,9702.0
,,,,,,,26,9229.0
,,,,,,,27,9004.0
,,,,,,,28,8951.0
,,,,,,,29,9188.0
,,,,,,,30,10087.0
,,,,,,,31,11929.0
,,,,,,,32,13166.0
,,,,,,,33,13504.0
,,,,,,,34,13632.0
,,,,,,,35,13724.0
,,,,,,,36,13742.0
,,,,,,,37,13665.0
,,,,,,,38,13641.0
,,,,,,,39,13501.0
,,,,,,,40,13366.0
,,,,,,,41,13376.0
,,,,,,,42,13524.0
,,,,,,,43,13736.0
,,,,,,,44,14401.0
,,,,,,,45,14006.0
,,,,,,,46,13006.0
,,,,,,,47,11658.0
,,,,,,,48,10416.0
,,,,,,,49,10219.0
,,,,,,,50,9671.0
,,,,,,,51,9383.0
,,,,,,,52,9269.0
,,,,,,,53,9483.0
,,,,,,,54,10103.0
,,,,,,,55,11573.0
,,,,,,,56,13059.0
,,,,,,,57,13905.0
,,,,,,,58,14430.0
,,,,,,,59,14873.0
,,,,,,,60,15179.0
,,,,,,,61,15323.0
,,,,,,,62,15515.0
,,,,,,,63,15537.0
,,,,,,,64,15481.0
,,,,,,,65,15485.0
,,,,,,,66,15440.0
,,,,,,,67,15208.0
,,,,,,,68,15028.0
,,,,,,,69,15221.0
,,,,,,,70,14913.0
,,,,,,,71,13573.0
,,,,,,,72,12159.0
,,,,,,,73,14935.0
,,,,,,,74,14062.0
,,,,,,,75,13498.0
,,,,,,,76,13146.0
,,,,,,,77,13178.0
,,,,,,,78,13712.0
,,,,,,,79,15192.0
,,,,,,,80,17114.0
,,,,,,,81,18656.0
,,,,,,,82,20020.0
,,,,,,,83,21201.0
,,,,,,,84,22009.0
,,,,,,,85,22567.0
,,,,,,,86,23070.0
,,,,,,,87,23388.0
,,,,,,,88,23629.0
,,,,,,,89,23770.0
,,,,,,,90,23575.0
,,,,,,,91,23034.0
,,,,,,,92,22325.0
,,,,,,,93,21921.0
,,,,,,,94,21122.0
,,,,,,,95,19311.0
,,,,,,,96,17514.0
,,,,,,,97,11232.0
,,,,,,,98,10825.0
,,,,,,,99,10632.0
,,,,,,,100,10622.0
,,,,,,,101,10948.0
,,,,,,,102,11984.0
,,,,,,,103,13879.0
,,,,,,,104,14890.0
,,,,,,,105,15134.0
,,,,,,,106,15241.0
,,,,,,,107,15360.0
,,,,,,,108,15407.0
,,,,,,,109,15385.0
,,,,,,,110,15372.0
,,,,,,,111,15285.0
,,,,,,,112,15482.0
,,,,,,,113,16544.0
,,,,,,,114,17247.0
,,,,,,,115,17114.0
,,,,,,,116,16657.0
,,,,,,,117,15936.0
,,,,,,,118,14783.0
,,,,,,,119,13342.0
,,,,,,,120,12052.0
2 changes: 2 additions & 0 deletions test/Electrolyzer/Energy_share_requirement.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
,Network_zones,ESR_1,ESR_2
NE,z1,0.259,0.348
Loading

0 comments on commit 2091f85

Please sign in to comment.