Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 0 additions & 18 deletions reeds/core/setup/b_inputs.gms
Original file line number Diff line number Diff line change
Expand Up @@ -4109,24 +4109,6 @@ fuel_price(i,r,t)$[sum{f$fuel2tech(f,i),1}$(not fuel_price(i,r,t))] =
fuel_price(i,r,t)$upgrade(i) = sum{ii$upgrade_to(i,ii), fuel_price(ii,r,t) } ;


*=====================================================
* -- Climate impacts on nondispatchable hydropower --
*=====================================================

$ifthen.climatehydro %GSw_ClimateHydro% == 1

* declared over allt to allow for external data files that extend beyond end_year
* Written by climateprep.py
table climate_hydro_annual(r,allt) "annual dispatchable hydropower availability"
$offlisting
$ondelim
$include inputs_case%ds%climate_hydadjann.csv
$offdelim
$onlisting
;
$endif.climatehydro


*=====================================================
* -- Climate impacts on nondispatchable hydropower --
*=====================================================
Expand Down
23 changes: 0 additions & 23 deletions reeds/core/solve/2_temporal_params.gms
Original file line number Diff line number Diff line change
Expand Up @@ -472,29 +472,6 @@ $onlisting
/ ;
$offempty

$ifthen.climatehydro %GSw_ClimateHydro% == 1

* Written by climateprep.py
table climate_hydro_seasonal(r,allszn,allt) "annual/seasonal nondispatchable hydropower availability"
$offlisting
$ondelim
$include inputs_case%ds%%temporal_inputs%%ds%climate_hydadjsea.csv
$offdelim
$onlisting
;

* adjust cf_hyd based on annual/seasonal climate multipliers
* non-dispatchable hydro gets new seasonal profiles as well as annually-varying CF
* dispatchable hydro keeps the original seasonal profiles; only annual CF changes. Reflects the assumption
* that reservoirs will be utilized in the same seasonal pattern even if seasonal inflows change.
cf_hyd(i,szn,r,t)$[hydro_nd(i)$(yeart(t)>=Sw_ClimateStartYear)] =
sum{allt$att(allt,t), cf_hyd(i,szn,r,t) * climate_hydro_seasonal(r,szn,allt) } ;

cf_hyd(i,szn,r,t)$[hydro_d(i)$(yeart(t)>=Sw_ClimateStartYear)] =
sum{allt$att(allt,t), cf_hyd(i,szn,r,t) * climate_hydro_annual(r,allt) } ;

$endif.climatehydro

*created by reeds/input_processing/writecapdat.py
parameter cap_hyd_szn_adj(i,allszn,r) "--fraction-- seasonal max capacity adjustment for dispatchable hydro"
/
Expand Down
24 changes: 11 additions & 13 deletions reeds/input_processing/climateprep.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,21 +181,19 @@ def readwrite(
## Drop extra data after the model end year
.loc[:,:endyear]
)

# Files indexed by month undergo additional processing in hourly_writetimeseries. Create
# intermediate filenames for these files and melt them back to long format
file_prefix = 'temp' if 'month' in dfout.index.names else 'climate'
keepindex = False if file_prefix == 'temp' else True
if file_prefix == 'temp':
dfout = pd.melt(
dfout.reset_index(), id_vars=index[infile], value_vars=dfout.columns,
var_name='t', value_name='Value'
)

# Melt to long format
dfout = pd.melt(
dfout.reset_index(), id_vars=index[infile], value_vars=dfout.columns,
var_name='t', value_name='Value'
)
# ClimateWater files indexed by month undergo additional processing in hourly_writetimeseries -
# Create intermediate filenames for these files
file_prefix = 'temp' if infile in ['UnappWaterMult','UnappWaterSeaAnnDistr'] else 'climate'
# Write it to output folder
dfout.round(decimals).to_csv(os.path.join(inputs_case, f'{file_prefix}_{infile}.csv'),
index=keepindex)

index=False)


return dfout


Expand Down
10 changes: 2 additions & 8 deletions reeds/input_processing/hourly_writetimeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ def format_climate_inputs(filename, inputs_case, szn_month_weights):
szn_month_weights
"""
climate_index = {
'temp_hydadjsea': ['r','season','t'],
'temp_UnappWaterMult': ['wst','r','season','t'],
'temp_UnappWaterSeaAnnDistr': ['wst','r','season','t']
}
Expand Down Expand Up @@ -1105,10 +1104,8 @@ def main(sw, reeds_path, inputs_case, periodtype='rep', make_plots=1, logging=Tr
.rename(columns={"season": "szn"})
)

### Import and format monthly climate_{hydadjsea/UnappWaterMult/UnappWaterSeaAnnDistr}.csv
### Import and format monthly climate_{UnappWaterMult/UnappWaterSeaAnnDistr}.csv
climate_files = {}
if int(sw.GSw_ClimateHydro):
climate_files['temp_hydadjsea'] = format_climate_inputs('temp_hydadjsea', inputs_case, szn_month_weights)
if int(sw.GSw_ClimateWater):
for file in ['temp_UnappWaterMult', 'temp_UnappWaterSeaAnnDistr']:
climate_files[file] = format_climate_inputs(file, inputs_case, szn_month_weights)
Expand Down Expand Up @@ -1532,10 +1529,7 @@ def main(sw, reeds_path, inputs_case, periodtype='rep', make_plots=1, logging=Tr
"peak_h": [pd.DataFrame(columns=["*r", "h", "t", "MW"]), True, False],
}

# Add climate inputs based on GSw_Climate* switch selection
if int(sw.GSw_ClimateHydro):
## Climate-adjusted annual/seasonal nondispatchable hydropower availability
write['climate_hydadjsea'] = [climate_files['temp_hydadjsea'], True, True]
# Add climate inputs to write dictionary based on GSw_ClimateWater
if int(sw.GSw_ClimateWater):
## Climate-adjusted time-varying annual/seasonal water supply
write['climate_UnappWaterMult'] = [climate_files['temp_UnappWaterMult'], True, True]
Expand Down
67 changes: 67 additions & 0 deletions reeds/input_processing/hydcf.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,60 @@ def assemble_hydcf(

return hydcf

def apply_hydro_climate_adjustments(
hydcf_unadjusted: pd.DataFrame,
inputs_case: str
) -> pd.DataFrame:
"""
Applies climate adjustment factors to hydropower capacity factors, if applicable

Args:
hydcf_unadjusted: Monthly regional CFs prior to climate adjustments
inputs_case: Path to the inputs case directory.
Returns:
pd.DataFrame
"""
# Exit function if climate adjustments to hydropower are turned OFF, otherwise continue
sw = reeds.io.get_switches(inputs_case)
if not int(sw.GSw_ClimateHydro):
return

# Get sets for dispatchable/non-dispatchable hydro from tech subset table
tech_subsets = pd.read_csv(
os.path.join(inputs_case, 'tech-subset-table.csv'),
index_col=0
)
hydro_d = set(tech_subsets.loc[tech_subsets['HYDRO_D']=='YES'].index)
hydro_nd = set(tech_subsets.loc[tech_subsets['HYDRO_ND']=='YES'].index)

# Separate data into dispatchable vs non-dispatchable hydropower
hydcf_d = hydcf_unadjusted[hydcf_unadjusted.index.isin(hydro_d, level='*i')].reset_index().copy()
hydcf_nd = hydcf_unadjusted[hydcf_unadjusted.index.isin(hydro_nd, level='*i')].reset_index().copy()
assert len(hydcf_d)+len(hydcf_nd) == len(hydcf_unadjusted), "At least 1 hydro tech is unaccounted for from hydcf.csv"

# Read hydropower CF climate adjustments and melt to long form
adj_factors_ann = pd.read_csv(
os.path.join(inputs_case, 'climate_hydadjann.csv'),
dtype={'r':str,'t':int}
).rename(columns={'Value':'Factor'})
adj_factors_sea = pd.read_csv(
os.path.join(inputs_case, 'climate_hydadjsea.csv'),
dtype={'r':str,'t':int,'month':str}
).rename(columns={'Value':'Factor'})

# Apply adjustment factors
hydcf_d = pd.merge(hydcf_d, adj_factors_ann, how='left', on=['r','t'])
hydcf_d['value_adj'] = hydcf_d['value'] * hydcf_d['Factor']
hydcf_d = hydcf_d.drop(columns=['value','Factor']).rename(columns={'value_adj':'value'})
hydcf_nd = pd.merge(hydcf_nd, adj_factors_sea, how='left', on=['r','month','t'])
hydcf_nd['value_adj'] = hydcf_nd['value'] * hydcf_nd['Factor']
hydcf_nd = hydcf_nd.drop(columns=['value','Factor']).rename(columns={'value_adj':'value'})

# Reassemble hydcf
hydcf = pd.concat([hydcf_d,hydcf_nd],axis=0)


return hydcf

#%% ===========================================================================
### --- MAIN FUNCTION ---
Expand Down Expand Up @@ -431,6 +485,11 @@ def main(reeds_path, inputs_case):
future_monthly_regional_cf,
inputs_case
)
hydcf = apply_hydro_climate_adjustments(
hydcf,
inputs_case
)

hydcf.to_csv(os.path.join(inputs_case, 'hydcf.csv'))


Expand All @@ -455,6 +514,12 @@ def main(reeds_path, inputs_case):
reeds_path = args.reeds_path
inputs_case = args.inputs_case

# #%% Settings for testing
# reeds_path = reeds.io.reeds_path
# inputs_case = os.path.join(
# reeds_path,'runs',
# 'InstantiateRepo_USA_defaults','inputs_case')

#%% Set up logger
log = reeds.log.makelog(
scriptname=__file__,
Expand All @@ -468,3 +533,5 @@ def main(reeds_path, inputs_case):
path=os.path.join(inputs_case,'..'))

print('Finished hydcf.py')

# %%
2 changes: 2 additions & 0 deletions reeds/input_processing/runfiles.csv
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ heat_rate_mult.csv,inputs/waterclimate/heat_rate_mult.csv,int(sw.GSw_WaterMain)
heat_rate_penalty_spin.csv,inputs/plant_characteristics/heat_rate_penalty_spin.csv,1,ignore,ignore,,,,,0,,,,,,
hintage_char.csv,inputs/sets/hintage_char.csv,1,ignore,ignore,,,,,,,,set,hintage_char,characteristics available in hintage_data,
hyd_add_upg_cap.csv,inputs/supply_curve/hyd_add_upg_cap.csv,int(sw.GSw_HydroCapEnerUpgradeType) == 2,sum,hydroexist,r,"i,rscbin,wide",,1,0,,,,,,
hydadjann.csv,inputs/climate/{climatescen}/hydadjann.csv,int(sw.GSw_ClimateHydro) != 0,mean,uniform,r,t,,0,0,,,,,,
hydadjsea.csv,inputs/climate/{climatescen}/hydadjsea.csv,int(sw.GSw_ClimateHydro) != 0,mean,uniform,r,"month,t",,0,0,,,,,,
hyd_fom.csv,inputs/hydro/hyd_fom.csv,1,mean,uniform,wide,i,,1,0,,,,,,
hydcap.csv,inputs/supply_curve/hydcap.csv,1,sum,geosize,wide,"tech,class",,1,0,,,,,,
hydcapadj.csv,inputs/hydro/SeaCapAdj_hy.csv,1,mean,uniform,r,"*i,month",,0,0,,,,,,
Expand Down
2 changes: 1 addition & 1 deletion runreeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,7 @@ def write_batch_script(
for s in [
'copy_files',
'mcs_sampler',
'climateprep',
'hydcf',
'h2_storage',
'calc_financial_inputs',
Expand All @@ -1310,7 +1311,6 @@ def write_batch_script(
'writesupplycurves',
'writedrshift',
'plantcostprep',
'climateprep',
'hourly_load',
'recf',
'forecast',
Expand Down
Loading