Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ Classify the change according to the following categories:
### Deprecated
### Removed

## v0.58.2
### Added
- **Generator** **om_cost_per_hr_per_kw_rated**: Generator non-fuel variable operations and maintenance costs in \$/hr/kw_rated (default of 0.0)

### Changed
- Refactored some results expressions so that `value.` isn't called within them.

### Fixed
- Fixed an error creating results for flows from hot TES to the steam turbine.
- Fixed an bug preventing `include_cooling_in_chp_size` from being included in CHP inputs.

## v0.58.1
### Fixed
- Calculation of offgrid_microgrid_lcoe_dollars_per_kwh for sub-hourly runs.
Expand All @@ -38,14 +49,12 @@ Classify the change according to the following categories:

### Changed
- Updated heating dispatch results by separating heat flows to absorption chiller from heating load served (formerly, these were aggregated).
- **HotThermalStorage** and **HighTempThermalStorage** output **storage_to_turbine_series_mmbtu_per_hour** to **storage_to_steamturbine_series_mmbtu_per_hour**

### Fixed
- Fixed a bug in which the CHP system requires a **DomesticHotWater** load.
- Fixed a bug in which the storage to steam turbine flow was included in the thermal heating load served.

### Changed
- **HotThermalStorage** and **HighTempThermalStorage** output **storage_to_turbine_series_mmbtu_per_hour** to **storage_to_steamturbine_series_mmbtu_per_hour**

## v0.57.0
### Fixed
- Include boiler emissions in emissions calculations
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "REopt"
uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6"
authors = ["Nick Laws", "Hallie Dunham <hallie.dunham@nlr.gov>", "Bill Becker <william.becker@nlr.gov>", "Bhavesh Rathod <bhavesh.rathod@nlr.gov>", "Alex Zolan <alexander.zolan@nlr.gov>", "Amanda Farthing <amanda.farthing@nlr.gov>", "Xiangkun Li <xiangkun.li@nlr.gov>", "An Pham <an.pham@nlr.gov>", "Byron Pullutasig <byron.pullatasig@nlr.gov>"]
version = "0.58.1"
version = "0.58.2"

[deps]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Expand Down
38 changes: 37 additions & 1 deletion src/constraints/generator_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ function add_binGenIsOnInTS_constraints(m,p)
end
end


function add_gen_can_run_constraints(m,p)
if p.s.generator.only_runs_during_grid_outage
for ts in p.time_steps_with_grid, t in p.techs.gen
Expand All @@ -58,6 +57,38 @@ function add_gen_rated_prod_constraint(m, p)
)
end

"""
add_generator_hourly_om_charges(m, p)

- add decision variable "dvOMByHourBySizeGen" for the hourly Generator operations and maintenance costs
- add the cost to TotalPerUnitHourOMCosts
"""
function add_generator_hourly_om_charges(m, p)
dv = "dvOMByHourBySizeGen"
m[Symbol(dv)] = @variable(m, [p.techs.gen, p.time_steps], base_name=dv, lower_bound=0)

#Constraint Generator-hourly-om-a: om per hour, per time step >= per_unit_size_cost * size for when on, >= zero when off
@constraint(m, GeneratorHourlyOMBySizeA[t in p.techs.gen, ts in p.time_steps],
p.s.generator.om_cost_per_hr_per_kw_rated * m[Symbol("dvSize")][t] -
(p.s.generator.existing_kw + p.s.generator.max_kw) * p.s.generator.om_cost_per_hr_per_kw_rated * (1-m[Symbol("binGenIsOnInTS")][t,ts])
<= m[Symbol("dvOMByHourBySizeGen")][t, ts]
)
#Constraint Generator-hourly-om-b: om per hour, per time step <= per_unit_size_cost * size for each hour
@constraint(m, GeneratorHourlyOMBySizeB[t in p.techs.gen, ts in p.time_steps],
p.s.generator.om_cost_per_hr_per_kw_rated * m[Symbol("dvSize")][t]
>= m[Symbol("dvOMByHourBySizeGen")][t, ts]
)
#Constraint Generator-hourly-om-c: om per hour, per time step <= zero when off, <= per_unit_size_cost*max_size
@constraint(m, GeneratorHourlyOMBySizeC[t in p.techs.gen, ts in p.time_steps],
(p.s.generator.existing_kw + p.s.generator.max_kw) * p.s.generator.om_cost_per_hr_per_kw_rated * m[Symbol("binGenIsOnInTS")][t,ts]
>= m[Symbol("dvOMByHourBySizeGen")][t, ts]
)

m[:TotalHourlyGenOMCosts] = @expression(m, p.third_party_factor * p.pwf_om *
sum(m[Symbol(dv)][t, ts] * p.hours_per_time_step for t in p.techs.gen, ts in p.time_steps))
nothing
end


"""
add_gen_constraints(m, p)
Expand All @@ -70,6 +101,11 @@ function add_gen_constraints(m, p)
add_gen_can_run_constraints(m,p)
add_gen_rated_prod_constraint(m,p)

m[:TotalHourlyGenOMCosts] = 0
if p.s.generator.om_cost_per_hr_per_kw_rated > 1.0E-7
add_generator_hourly_om_charges(m, p)
end

m[:TotalGenPerUnitProdOMCosts] = @expression(m, p.third_party_factor * p.pwf_om *
sum(p.s.generator.om_cost_per_kwh * p.hours_per_time_step *
m[:dvRatedProduction][t, ts] for t in p.techs.gen, ts in p.time_steps)
Expand Down
1 change: 0 additions & 1 deletion src/core/chp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ conflict_res_min_allowable_fraction_of_max = 0.25
serve_absorption_chiller_only::Bool = false # If CHP produced heat either serves absorption chiller or sends it to waste; only applies to the months specified in months_serving_absorption_chiller_only if true
months_serving_absorption_chiller_only::AbstractVector{Int64} = Int64[] # months in which CHP only sevres the absorption chiller, with 1=January and 12=December; only applied when serve_absorption_chiller_only = true
follow_electrical_load::Bool = false # If CHP follows the electrical load by running at capacity or meeting the load only.
include_cooling_in_chp_size::Bool = false # If true, includes cooling load (via absorption chiller) in the heuristic CHP sizing calculation along with heating loads. Defaults to true when AbsorptionChiller is present with CHP. Requires CoolingLoad to be specified.

macrs_option_years::Int = 5 # Notes: this value cannot be 0 if aiming to apply 100% bonus depreciation; default may change if Site.sector is not "commercial/industrial"
macrs_bonus_fraction::Float64 = 1.0 #Note: default may change if Site.sector is not "commercial/industrial"
Expand Down
4 changes: 4 additions & 0 deletions src/core/generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
installed_cost_per_kw::Real = off_grid_flag ? 880 : only_runs_during_grid_outage ? 650.0 : 800.0,
om_cost_per_kw::Real = off_grid_flag ? 10.0 : 20.0,
om_cost_per_kwh::Real = 0.0,
om_cost_per_hr_per_kw_rated::Float64 = 0.0, # Generator non-fuel variable operations and maintenance costs in \$/hr/kw_rated
fuel_cost_per_gallon::Real = 2.25,
electric_efficiency_full_load::Real = 0.322,
electric_efficiency_half_load::Real = electric_efficiency_full_load,
Expand Down Expand Up @@ -57,6 +58,7 @@ struct Generator <: AbstractGenerator
installed_cost_per_kw
om_cost_per_kw
om_cost_per_kwh
om_cost_per_hr_per_kw_rated
fuel_cost_per_gallon
electric_efficiency_full_load
electric_efficiency_half_load
Expand Down Expand Up @@ -104,6 +106,7 @@ struct Generator <: AbstractGenerator
installed_cost_per_kw::Real = off_grid_flag ? 880 : only_runs_during_grid_outage ? 650.0 : 800.0,
om_cost_per_kw::Real= off_grid_flag ? 10.0 : 20.0,
om_cost_per_kwh::Real = 0.0,
om_cost_per_hr_per_kw_rated::Float64 = 0.0, # Generator non-fuel variable operations and maintenance costs in \$/hr/kw_rated
fuel_cost_per_gallon::Real = 2.25,
electric_efficiency_full_load::Real = 0.322,
electric_efficiency_half_load::Real = electric_efficiency_full_load,
Expand Down Expand Up @@ -152,6 +155,7 @@ struct Generator <: AbstractGenerator
installed_cost_per_kw,
om_cost_per_kw,
om_cost_per_kwh,
om_cost_per_hr_per_kw_rated,
fuel_cost_per_gallon,
electric_efficiency_full_load,
electric_efficiency_half_load,
Expand Down
1 change: 1 addition & 0 deletions src/core/reopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ function build_reopt!(m::JuMP.AbstractModel, p::REoptInputs)
add_gen_constraints(m, p)
m[:TotalPerUnitProdOMCosts] += m[:TotalGenPerUnitProdOMCosts]
m[:TotalFuelCosts] += m[:TotalGenFuelCosts]
m[:TotalPerUnitHourOMCosts] += m[:TotalHourlyGenOMCosts]
end

if !isempty(p.techs.chp)
Expand Down
8 changes: 6 additions & 2 deletions src/core/scenario.jl
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,11 @@ function Scenario(d::Dict; flex_hvac_from_json=false)
avg_cooling_load_kw = nothing
absorption_chiller_cop = nothing
# User can override by explicitly setting include_cooling_in_chp_size = false
include_cooling_in_size = get(d["CHP"], "include_cooling_in_chp_size", haskey(d, "AbsorptionChiller"))
if "include_cooling_in_chp_size" in keys(d["CHP"])
include_cooling_in_size = pop!(d["CHP"], "include_cooling_in_chp_size")
else
include_cooling_in_size = haskey(d, "AbsorptionChiller")
end

if max_cooling_demand_kw > 0 && include_cooling_in_size
# Use already-processed cooling_load object
Expand All @@ -498,7 +502,7 @@ function Scenario(d::Dict; flex_hvac_from_json=false)
sector = site.sector,
federal_procurement_type = site.federal_procurement_type)
else # Only if modeling CHP without heating_load and existing_boiler (for prime generator, electric-only)
chp = CHP(d["CHP"],
chp = CHP(d["CHP"];
electric_load_series_kw = electric_load.loads_kw,
avg_cooling_load_kw = avg_cooling_load_kw,
absorption_chiller_cop = absorption_chiller_cop,
Expand Down
4 changes: 3 additions & 1 deletion src/mpc/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ function build_mpc!(m::JuMP.AbstractModel, p::MPCInputs)

m[:TotalFuelCosts] = 0.0
m[:TotalPerUnitProdOMCosts] = 0.0
m[:TotalPerUnitHourOMCosts] = 0.0

if !isempty(p.techs.gen)
add_gen_constraints(m, p)
Expand All @@ -164,6 +165,7 @@ function build_mpc!(m::JuMP.AbstractModel, p::MPCInputs)
sum(m[:dvFuelUsage][t,ts] * p.s.generator.fuel_cost_per_gallon for t in p.techs.gen, ts in p.time_steps)
)
m[:TotalFuelCosts] += m[:TotalGenFuelCosts]
m[:TotalPerUnitHourOMCosts] += m[:TotalHourlyGenOMCosts]
end

add_elec_utility_expressions(m, p)
Expand Down Expand Up @@ -203,7 +205,7 @@ function build_mpc!(m::JuMP.AbstractModel, p::MPCInputs)
@expression(m, Costs,

# Variable O&M
m[:TotalPerUnitProdOMCosts] +
m[:TotalPerUnitProdOMCosts] + m[:TotalPerUnitHourOMCosts] +

# Total Generator Fuel Costs
m[:TotalFuelCosts] +
Expand Down
4 changes: 4 additions & 0 deletions src/mpc/structs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ function MPCGenerator(;
only_runs_during_grid_outage::Bool = true,
sells_energy_back_to_grid::Bool = false,
om_cost_per_kwh::Real=0.0,
om_cost_per_hr_per_kw_rated::Real=0.0,
)
```
"""
Expand All @@ -276,6 +277,7 @@ struct MPCGenerator <: AbstractGenerator
only_runs_during_grid_outage
sells_energy_back_to_grid
om_cost_per_kwh
om_cost_per_hr_per_kw_rated

function MPCGenerator(;
size_kw::Real,
Expand All @@ -288,6 +290,7 @@ struct MPCGenerator <: AbstractGenerator
only_runs_during_grid_outage::Bool = true,
sells_energy_back_to_grid::Bool = false,
om_cost_per_kwh::Real=0.0,
om_cost_per_hr_per_kw_rated::Real=0.0,
)

max_kw = size_kw
Expand All @@ -304,6 +307,7 @@ struct MPCGenerator <: AbstractGenerator
only_runs_during_grid_outage,
sells_energy_back_to_grid,
om_cost_per_kwh,
om_cost_per_hr_per_kw_rated
)
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/results/boiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ function add_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="
r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(NewBoilerToSteamTurbine), digits=3)

if "AbsorptionChiller" in p.techs.cooling
@expression(m, NewBoilertoAbsorptionChillerKW[ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["Boiler",q,ts] for q in p.heating_loads)))
@expression(m, NewBoilertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["Boiler",q,ts])))
@expression(m, NewBoilertoAbsorptionChillerKW[ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["Boiler",q,ts] for q in p.heating_loads))
@expression(m, NewBoilertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["Boiler",q,ts]))
else
@expression(m, NewBoilertoAbsorptionChillerKW[ts in p.time_steps], 0.0)
@expression(m, NewBoilertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], 0.0)
Expand Down
4 changes: 2 additions & 2 deletions src/results/chp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="")
end
r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(CHPToSteamTurbineKW) / KWH_PER_MMBTU, digits=5)
if "AbsorptionChiller" in p.techs.cooling
@expression(m, CHPtoAbsorptionChillerKW[ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller][t,q,ts] for t in p.techs.chp, q in p.heating_loads)))
@expression(m, CHPtoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller][t,q,ts] for t in p.techs.chp)))
@expression(m, CHPtoAbsorptionChillerKW[ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller][t,q,ts] for t in p.techs.chp, q in p.heating_loads))
@expression(m, CHPtoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller][t,q,ts] for t in p.techs.chp))
else
@expression(m, CHPtoAbsorptionChillerKW[ts in p.time_steps], 0.0)
@expression(m, CHPtoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], 0.0)
Expand Down
4 changes: 2 additions & 2 deletions src/results/cst.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ function add_concentrating_solar_results(m::JuMP.AbstractModel, p::REoptInputs,
r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(CSTToSteamTurbine) / KWH_PER_MMBTU, digits=3)

if "AbsorptionChiller" in p.techs.cooling
@expression(m, CSTtoAbsorptionChillerKW[ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["CST",q,ts] for q in p.heating_loads)))
@expression(m, CSTtoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["CST",q,ts])))
@expression(m, CSTtoAbsorptionChillerKW[ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["CST",q,ts] for q in p.heating_loads))
@expression(m, CSTtoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["CST",q,ts]))
else
@expression(m, CSTtoAbsorptionChillerKW[ts in p.time_steps], 0.0)
@expression(m, CSTtoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], 0.0)
Expand Down
4 changes: 2 additions & 2 deletions src/results/electric_heater.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ function add_electric_heater_results(m::JuMP.AbstractModel, p::REoptInputs, d::D
r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(ElectricHeaterToSteamTurbine) / KWH_PER_MMBTU, digits=3)

if "AbsorptionChiller" in p.techs.cooling
@expression(m, ElectricHeatertoAbsorptionChillerKW[ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["ElectricHeater",q,ts] for q in p.heating_loads)))
@expression(m, ElectricHeatertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["ElectricHeater",q,ts])))
@expression(m, ElectricHeatertoAbsorptionChillerKW[ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["ElectricHeater",q,ts] for q in p.heating_loads))
@expression(m, ElectricHeatertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["ElectricHeater",q,ts]))
else
@expression(m, ElectricHeatertoAbsorptionChillerKW[ts in p.time_steps], 0.0)
@expression(m, ElectricHeatertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], 0.0)
Expand Down
4 changes: 2 additions & 2 deletions src/results/existing_boiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ function add_existing_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::D
r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(BoilerToSteamTurbineKW) ./ KWH_PER_MMBTU, digits=5)

if "AbsorptionChiller" in p.techs.cooling
@expression(m, BoilertoAbsorptionChillerKW[ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["ExistingBoiler",q,ts] for q in p.heating_loads)))
@expression(m, BoilertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(value.(m[:dvHeatToAbsorptionChiller]["ExistingBoiler",q,ts])))
@expression(m, BoilertoAbsorptionChillerKW[ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["ExistingBoiler",q,ts] for q in p.heating_loads))
@expression(m, BoilertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], sum(m[:dvHeatToAbsorptionChiller]["ExistingBoiler",q,ts]))
else
@expression(m, BoilertoAbsorptionChillerKW[ts in p.time_steps], 0.0)
@expression(m, BoilertoAbsorptionChillerByQualityKW[q in p.heating_loads, ts in p.time_steps], 0.0)
Expand Down
12 changes: 4 additions & 8 deletions src/results/generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
- `size_kw` Optimal generator capacity
- `lifecycle_fixed_om_cost_after_tax` Lifecycle fixed operations and maintenance cost in present value, after tax
- `year_one_fixed_om_cost_before_tax` fixed operations and maintenance cost over the first year, before considering tax benefits
- `lifecycle_variable_om_cost_after_tax` Lifecycle variable operations and maintenance cost in present value, after tax
- `year_one_variable_om_cost_before_tax` variable operations and maintenance cost over the first year, before considering tax benefits
- `lifecycle_variable_om_cost_after_tax` Lifecycle variable operations and maintenance cost in present value, after tax. Includes om_cost_per_kwh and om_cost_per_hr_per_kw_rated
- `year_one_variable_om_cost_before_tax` variable operations and maintenance cost over the first year, before considering tax benefits. Includes om_cost_per_kwh and om_cost_per_hr_per_kw_rated
- `lifecycle_fuel_cost_after_tax` Lifecycle fuel cost in present value, after tax
- `year_one_fuel_cost_before_tax` Fuel cost over the first year, before considering tax benefits. Does not include fuel use during outages if using multiple outage modeling.
- `year_one_fuel_cost_after_tax` Fuel cost over the first year, after considering tax benefits. Does not include fuel use during outages if using multiple outage modeling.
Expand All @@ -28,17 +28,13 @@ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _

GenPerUnitSizeOMCosts = @expression(m, p.third_party_factor * p.pwf_om * sum(m[:dvSize][t] * p.om_cost_per_kw[t] for t in p.techs.gen))

GenPerUnitProdOMCosts = @expression(m, p.third_party_factor * p.pwf_om * p.hours_per_time_step *
sum(m[:dvRatedProduction][t, ts] * p.production_factor[t, ts] * p.s.generator.om_cost_per_kwh
for t in p.techs.gen, ts in p.time_steps)
)
r["size_kw"] = round(value(sum(m[:dvSize][t] for t in p.techs.gen)), digits=2)
r["lifecycle_fixed_om_cost_after_tax"] = round(value(GenPerUnitSizeOMCosts) * (1 - p.s.financial.owner_tax_rate_fraction), digits=0)
r["lifecycle_variable_om_cost_after_tax"] = round(value(m[:TotalPerUnitProdOMCosts]) * (1 - p.s.financial.owner_tax_rate_fraction), digits=0)
r["lifecycle_variable_om_cost_after_tax"] = round((value(m[:TotalGenPerUnitProdOMCosts]) + value(m[:TotalHourlyGenOMCosts])) * (1 - p.s.financial.owner_tax_rate_fraction), digits=0)
r["lifecycle_fuel_cost_after_tax"] = round(value(m[:TotalGenFuelCosts]) * (1 - p.s.financial.offtaker_tax_rate_fraction), digits=2)
r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalGenFuelCosts]) / p.pwf_fuel["Generator"], digits=2)
r["year_one_fuel_cost_after_tax"] = r["year_one_fuel_cost_before_tax"] * (1 - p.s.financial.offtaker_tax_rate_fraction)
r["year_one_variable_om_cost_before_tax"] = round(value(GenPerUnitProdOMCosts) / (p.pwf_om * p.third_party_factor), digits=0)
r["year_one_variable_om_cost_before_tax"] = round(value(m[:TotalGenPerUnitProdOMCosts] + m[:TotalHourlyGenOMCosts]) / (p.pwf_om * p.third_party_factor), digits=0)
r["year_one_fixed_om_cost_before_tax"] = round(value(GenPerUnitSizeOMCosts) / (p.pwf_om * p.third_party_factor), digits=0)

if !isempty(p.s.storage.types.elec)
Expand Down
Loading
Loading