Skip to content

Commit

Permalink
Merge pull request #245 from NREL/existing-chiller-cop-api-setup
Browse files Browse the repository at this point in the history
Existing chiller cop api setup
  • Loading branch information
Bill-Becker authored Aug 8, 2023
2 parents f82349a + 8b22968 commit d105de3
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ Classify the change according to the following categories:
### Deprecated
### Removed

## Develop 2023-08-08
### Changed
- Updated `get_existing_chiller_cop` function to accept scalar values instead of vectors to allow for faster API transactions.
## v0.32.4
### Changed
- Consolidated PVWatts API calls to 1 call (previously 3 separate calls existed). API call occurs in `src/core/utils.jl/call_pvwatts_api()`. This function is called for PV in `src/core/production_factor.jl/get_production_factor(PV)` and for GHP in `src/core/scenario.jl`. If GHP and PV are evaluated together, the GHP PVWatts call for ambient temperature is also used to assign the pv.production_factor_series in Scenario.jl so that the PVWatts API does not get called again downstream in `get_production_factor(PV)`.
Expand Down
3 changes: 2 additions & 1 deletion src/REopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export
simulated_load,
get_absorption_chiller_defaults,
emissions_profiles,
easiur_data
easiur_data,
get_existing_chiller_default_cop

import HTTP
import JSON
Expand Down
22 changes: 11 additions & 11 deletions src/core/heating_cooling_loads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,23 +209,23 @@ end

"""
function get_existing_chiller_default_cop(; existing_chiller_max_thermal_factor_on_peak_load=nothing,
loads_kw=nothing,
loads_kw_thermal=nothing)
max_load_kw=nothing,
max_load_kw_thermal=nothing)
This function returns the default value for ExistingChiller.cop based on:
1. No information about load, returns average of lower and higher cop default values (`cop_unknown_thermal`)
2. If the cooling electric `loads_kw` is known, we first guess the thermal load profile using `cop_unknown_thermal`,
2. If the cooling electric `max_load_kw` is known, we first guess the thermal load profile using `cop_unknown_thermal`,
and then we use the default logic to determine the `existing_chiller_cop` based on the peak thermal load with a thermal factor multiplier.
3. If the cooling thermal `loads_kw_thermal` is known, same as 2. but we don't have to guess the cop to convert electric to thermal load first.
3. If the cooling thermal `max_load_kw_thermal` is known, same as 2. but we don't have to guess the cop to convert electric to thermal load first.
"""
function get_existing_chiller_default_cop(; existing_chiller_max_thermal_factor_on_peak_load=nothing, loads_kw=nothing, loads_kw_thermal=nothing)
function get_existing_chiller_default_cop(; existing_chiller_max_thermal_factor_on_peak_load=nothing, max_load_kw=nothing, max_load_kw_thermal=nothing)
cop_less_than_100_ton = 4.40
cop_more_than_100_ton = 4.69
cop_unknown_thermal = (cop_less_than_100_ton + cop_more_than_100_ton) / 2.0
max_cooling_load_ton = nothing
if !isnothing(loads_kw_thermal)
max_cooling_load_ton = maximum(loads_kw_thermal) / KWH_THERMAL_PER_TONHOUR
elseif !isnothing(loads_kw)
max_cooling_load_ton = maximum(loads_kw) / KWH_THERMAL_PER_TONHOUR * cop_unknown_thermal
if !isnothing(max_load_kw_thermal)
max_cooling_load_ton = max_load_kw_thermal / KWH_THERMAL_PER_TONHOUR
elseif !isnothing(max_load_kw)
max_cooling_load_ton = max_load_kw / KWH_THERMAL_PER_TONHOUR * cop_unknown_thermal
end
if isnothing(max_cooling_load_ton) || isnothing(existing_chiller_max_thermal_factor_on_peak_load)
return cop_unknown_thermal
Expand Down Expand Up @@ -366,7 +366,7 @@ struct CoolingLoad
elseif (!isempty(doe_reference_name) || !isempty(blended_doe_reference_names)) || isnothing(existing_chiller_cop)
# Generated loads_kw (electric) above based on the building's default fraction of electric profile
chiller_cop = get_existing_chiller_default_cop(;existing_chiller_max_thermal_factor_on_peak_load=existing_chiller_max_thermal_factor_on_peak_load,
loads_kw=loads_kw)
max_load_kw=maximum(loads_kw))
else
chiller_cop = existing_chiller_cop
end
Expand All @@ -376,7 +376,7 @@ struct CoolingLoad
# Now that cooling thermal loads_kw_thermal is known, update existing_chiller_cop if it was not input
if isnothing(existing_chiller_cop)
existing_chiller_cop = get_existing_chiller_default_cop(;existing_chiller_max_thermal_factor_on_peak_load=existing_chiller_max_thermal_factor_on_peak_load,
loads_kw_thermal=loads_kw_thermal)
max_load_kw_thermal=maximum(loads_kw_thermal))
end

if length(loads_kw_thermal) < 8760*time_steps_per_hour
Expand Down
8 changes: 4 additions & 4 deletions src/core/scenario.jl
Original file line number Diff line number Diff line change
Expand Up @@ -288,14 +288,14 @@ function Scenario(d::Dict; flex_hvac_from_json=false)
if haskey(d, "ExistingChiller")
if !haskey(d["ExistingChiller"], "cop")
d["ExistingChiller"]["cop"] = get_existing_chiller_default_cop(; existing_chiller_max_thermal_factor_on_peak_load=1.25,
loads_kw=nothing,
loads_kw_thermal=chiller_inputs[:loads_kw_thermal])
max_load_kw=nothing,
max_load_kw_thermal=maximum(chiller_inputs[:loads_kw_thermal]))
end
chiller_inputs = merge(chiller_inputs, dictkeys_tosymbols(d["ExistingChiller"]))
else
chiller_inputs[:cop] = get_existing_chiller_default_cop(; existing_chiller_max_thermal_factor_on_peak_load=1.25,
loads_kw=nothing,
loads_kw_thermal=chiller_inputs[:loads_kw_thermal])
max_load_kw=nothing,
max_load_kw_thermal=maximum(chiller_inputs[:loads_kw_thermal]))
end
existing_chiller = ExistingChiller(; chiller_inputs...)
end
Expand Down
2 changes: 1 addition & 1 deletion test/test_with_xpress.jl
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ end
# When the user specifies inputs["ExistingChiller"]["cop"], this changes the **electric** consumption of the chiller to meet that cooling thermal load
crb_cop = REopt.get_existing_chiller_default_cop(;
existing_chiller_max_thermal_factor_on_peak_load=s.existing_chiller.max_thermal_factor_on_peak_load,
loads_kw_thermal=s.cooling_load.loads_kw_thermal)
max_load_kw_thermal=maximum(s.cooling_load.loads_kw_thermal))
cooling_thermal_load_tonhour_total = 1427329.0 * crb_cop / REopt.KWH_THERMAL_PER_TONHOUR # From CRB models, in heating_cooling_loads.jl, BuiltInCoolingLoad data for location (SanFrancisco Hospital)
cooling_electric_load_total_mod_cop_kwh = cooling_thermal_load_tonhour_total / inputs.s.existing_chiller.cop * REopt.KWH_THERMAL_PER_TONHOUR

Expand Down

0 comments on commit d105de3

Please sign in to comment.