From cda171c64279d507afa4a267955964282ae3f38a Mon Sep 17 00:00:00 2001 From: "Rathod, Bhavesh" Date: Tue, 26 Sep 2023 19:16:13 -0400 Subject: [PATCH] update results fields and add hybrid ghp test --- src/constraints/ghp_constraints.jl | 2 -- src/core/reopt_inputs.jl | 4 +++- src/results/financial.jl | 8 ++++---- test/test_with_xpress.jl | 21 ++++++++++++++++++++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/constraints/ghp_constraints.jl b/src/constraints/ghp_constraints.jl index e81ab4dbb..8cb67bfda 100644 --- a/src/constraints/ghp_constraints.jl +++ b/src/constraints/ghp_constraints.jl @@ -24,11 +24,9 @@ function add_ghp_constraints(m, p; _n="") m[:AvoidedCapexByGHP] = @expression(m, sum(p.avoided_capex_by_ghp_present_value[g] * m[Symbol("binGHP"*_n)][g] for g in p.ghp_options) ) - @info "check1" m[:ResidualGHXCapCost] = @expression(m, sum(p.ghx_residual_value[g] * m[Symbol("binGHP"*_n)][g] for g in p.ghp_options) ) - @info "check2" end \ No newline at end of file diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index eb1d6d7f3..04c996515 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -1009,11 +1009,13 @@ function setup_ghp_inputs(s::AbstractScenario, time_steps, time_steps_without_gr ghp_om_cost_year_one[i] = option.om_cost_year_one avoided_capex_by_ghp_present_value[i] = option.avoided_capex_by_ghp_present_value ghx_useful_life_years[i] = option.ghx_useful_life_years + # ownership guided residual value determination + discount_rate = (1 - 1*s.financial.third_party_ownership)*s.financial.offtaker_discount_rate_fraction + s.financial.third_party_ownership*s.financial.owner_discount_rate_fraction ghx_residual_value[i] = option.ghx_only_capital_cost* ( (option.ghx_useful_life_years - s.financial.analysis_years)/option.ghx_useful_life_years )/( - (1+s.financial.offtaker_discount_rate_fraction)^s.financial.analysis_years + (1 + discount_rate)^s.financial.analysis_years ) heating_thermal_load = s.space_heating_load.loads_kw + s.dhw_load.loads_kw diff --git a/src/results/financial.jl b/src/results/financial.jl index be88051ad..7cd159a05 100644 --- a/src/results/financial.jl +++ b/src/results/financial.jl @@ -49,10 +49,10 @@ function add_financial_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ end r["lcc"] = value(m[Symbol("Costs"*_n)]) + 0.0001 * value(m[Symbol("MinChargeAdder"*_n)]) - value(m[Symbol("dvComfortLimitViolationCost"*_n)]) r["lifecycle_om_costs_before_tax"] = value(m[Symbol("TotalPerUnitSizeOMCosts"*_n)] + - m[Symbol("TotalPerUnitProdOMCosts"*_n)] + m[Symbol("TotalPerUnitHourOMCosts"*_n)]) + m[Symbol("TotalPerUnitProdOMCosts"*_n)] + m[Symbol("TotalPerUnitHourOMCosts"*_n)] + m[Symbol("GHPOMCosts"*_n)]) ## LCC breakdown: ## - r["lifecycle_generation_tech_capital_costs"] = value(m[Symbol("TotalTechCapCosts"*_n)]) # Tech capital costs (including replacements) + r["lifecycle_generation_tech_capital_costs"] = value(m[Symbol("TotalTechCapCosts"*_n)] + m[Symbol("GHPCapCosts"*_n)]) # Tech capital costs (including replacements) r["lifecycle_storage_capital_costs"] = value(m[Symbol("TotalStorageCapCosts"*_n)]) # Storage capital costs (including replacements) r["lifecycle_om_costs_after_tax"] = r["lifecycle_om_costs_before_tax"] * (1 - p.s.financial.owner_tax_rate_fraction) # Fixed & Variable O&M if !isempty(p.techs.fuel_burning) @@ -85,9 +85,9 @@ function add_financial_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ r["year_one_om_costs_before_tax"] = r["lifecycle_om_costs_before_tax"] / (p.pwf_om * p.third_party_factor) r["year_one_om_costs_after_tax"] = r["lifecycle_om_costs_after_tax"] / (p.pwf_om * p.third_party_factor) - r["lifecycle_capital_costs_plus_om_after_tax"] = value(m[Symbol("TotalTechCapCosts"*_n)] + m[Symbol("TotalStorageCapCosts"*_n)]) + + r["lifecycle_capital_costs_plus_om_after_tax"] = value(m[Symbol("TotalTechCapCosts"*_n)] + m[Symbol("TotalStorageCapCosts"*_n)] + m[Symbol("GHPCapCosts"*_n)]) + r["lifecycle_om_costs_after_tax"] - r["lifecycle_capital_costs"] = value(m[Symbol("TotalTechCapCosts"*_n)] + m[Symbol("TotalStorageCapCosts"*_n)]) + r["lifecycle_capital_costs"] = value(m[Symbol("TotalTechCapCosts"*_n)] + m[Symbol("TotalStorageCapCosts"*_n)] + m[Symbol("GHPCapCosts"*_n)]) r["initial_capital_costs"] = initial_capex(m, p; _n=_n) future_replacement_cost, present_replacement_cost = replacement_costs_future_and_present(m, p; _n=_n) r["initial_capital_costs_after_incentives"] = r["lifecycle_capital_costs"] / p.third_party_factor - present_replacement_cost diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index 06ee8d2af..0ad8ef6db 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -1172,7 +1172,8 @@ end 3. GHP serves only the SpaceHeatingLoad by default unless it is allowed to serve DHW 4. GHP serves all the Cooling load 5. Input of a custom COP map for GHP and check the GHP performance to make sure it's using it correctly - + 6. Hybrid GHP capability functions as expected + """ # Load base inputs input_data = JSON.parsefile("scenarios/ghp_inputs.json") @@ -1244,6 +1245,24 @@ end # Average COP which includes pump power should be lower than Heat Pump only COP specified by the map @test heating_cop_avg <= 4.0 @test cooling_cop_avg <= 8.0 + + # Load base inputs + input_data = JSON.parsefile("scenarios/ghp_inputs.json") + + d["GHP"]["ghpghx_inputs"][1]["hybrid_ghx_sizing_method"] = "Automatic" + d["GHP"]["avoided_capex_by_ghp_present_value"] = 1.0e6 + d["GHP"]["ghx_useful_life_years"] = 35 + + inputs = REoptInputs(input_data) + # analysis period 25 years, ghx life 35 years, discount rate 8.3% + calculated_ghx_residual_value = (inputs.s.ghp_option_list[1].ghx_only_capital_cost)*((35-25)/35)/((1+0.083)^25) + + m1 = Model(optimizer_with_attributes(Xpress.Optimizer, "MIPRELSTOP" => 0.001, "OUTPUTLOG" => 0)) + m2 = Model(optimizer_with_attributes(Xpress.Optimizer, "MIPRELSTOP" => 0.001, "OUTPUTLOG" => 0)) + results = run_reopt([m1,m2], inputs) + + @test results["GHP"]["ghx_residual_value_present_value"] ≈ calculated_ghx_residual_value atol=0.1 + @test inputs.s.ghp_option_list[1].is_ghx_hybrid = true end @testset "Emissions and Renewable Energy Percent" begin