diff --git a/src/time_domain_reduction/time_domain_reduction.jl b/src/time_domain_reduction/time_domain_reduction.jl index a349f24525..ee3c3593c9 100644 --- a/src/time_domain_reduction/time_domain_reduction.jl +++ b/src/time_domain_reduction/time_domain_reduction.jl @@ -515,8 +515,18 @@ function get_demand_multipliers(ClusterOutputData, weighted_cluster_zone_sums[demandcol] += (W[m] / (TimestepsPerRepPeriod)) * cluster_zone_sums[m][demandcol] end - demand_mults[demandcol] = zone_sums[demandcol] / - weighted_cluster_zone_sums[demandcol] + if iszero(weighted_cluster_zone_sums[demandcol]) + if iszero(zone_sums[demandcol]) + @debug "Zero demand detected; using neutral demand multiplier." demandcol + demand_mults[demandcol] = 1.0 + else + @warn "Zero clustered demand with nonzero total; using zero multiplier." demandcol + demand_mults[demandcol] = 0.0 + end + else + demand_mults[demandcol] = zone_sums[demandcol] / + weighted_cluster_zone_sums[demandcol] + end if v println(demandcol, ": ", diff --git a/test/test_time_domain_reduction.jl b/test/test_time_domain_reduction.jl index 7a70df7425..eafebbc9f7 100644 --- a/test/test_time_domain_reduction.jl +++ b/test/test_time_domain_reduction.jl @@ -3,6 +3,7 @@ module TestTDR import GenX import Test import JLD2, Clustering +import DataFrames include(joinpath(@__DIR__, "utilities.jl")) @@ -62,4 +63,40 @@ for file in filter(endswith(".csv"), readdir(TDR_Results_true)) Test.@test cmp_csv(joinpath(TDR_Results_test, file), joinpath(TDR_Results_true, file)) end +Test.@testset "Demand multiplier edge cases" begin + input_data = DataFrames.DataFrame(Demand_MW_z1 = zeros(2)) + cluster_output = DataFrames.DataFrame(Symbol(1) => zeros(2)) + weights = [2.0] + timesteps = 2 + demand_mults = GenX.get_demand_multipliers(cluster_output, + input_data, + [1], + weights, + [:Demand_MW_z1], + timesteps, + [:Demand_MW_z1, :GrpWeight], + 1, + 1) + Test.@test demand_mults[:Demand_MW_z1] == 1.0 + + input_data = DataFrames.DataFrame(Demand_MW_z1 = [1.0, 2.0]) + cluster_output = DataFrames.DataFrame(Symbol(1) => [0.5, 0.5]) + weights = [2.0] + timesteps = 2 + demand_mults = GenX.get_demand_multipliers(cluster_output, + input_data, + [1], + weights, + [:Demand_MW_z1], + timesteps, + [:Demand_MW_z1, :GrpWeight], + 1, + 1) + # Mirror the demand multiplier formula to validate expected scaling. + expected_multiplier = sum(input_data.Demand_MW_z1) / + ((weights[1] / timesteps) * + sum(cluster_output[!, Symbol(1)])) + Test.@test demand_mults[:Demand_MW_z1] == expected_multiplier +end + end # module TestTDR