diff --git a/atlite/convert.py b/atlite/convert.py index ce3dd75c..62cec674 100644 --- a/atlite/convert.py +++ b/atlite/convert.py @@ -401,6 +401,81 @@ def heat_demand(cutout, threshold=15.0, a=1.0, constant=0.0, hour_shift=0.0, **p ) +# cooling demand +def convert_cooling_demand(ds, threshold, a, constant, hour_shift): + # Temperature is in Kelvin; take daily average + T = ds["temperature"] + T = T.assign_coords( + time=(T.coords["time"] + np.timedelta64(dt.timedelta(hours=hour_shift))) + ) + + T = T.resample(time="1D").mean(dim="time") + threshold += 273.15 + cooling_demand = a * (T - threshold) + + cooling_demand = cooling_demand.clip(min=0.0) + + return (constant + cooling_demand).rename("cooling_demand") + + +def cooling_demand( + cutout, threshold=23.0, a=1.0, constant=0.0, hour_shift=0.0, **params +): + """ + Convert outside temperature into daily cooling demand using the degree-day + approximation. + + Since "daily average temperature" means different things in + different time zones and since xarray coordinates do not handle + time zones gracefully like pd.DateTimeIndex, you can provide an + hour_shift to redefine when the day starts. + + E.g. for Moscow in summer, hour_shift = 3, for New York in summer, + hour_shift = -4 + + This time shift applies across the entire spatial scope of ds for + all times. More fine-grained control will be built in a some + point, i.e. space- and time-dependent time zones. + + WARNING: Because the original data is provided every month, at the + month boundaries there is untidiness if you use a time shift. The + resulting xarray will have duplicates in the index for the parts + of the day in each month at the boundary. You will have to + re-average these based on the number of hours in each month for + the duplicated day. + + Parameters + ---------- + threshold : float + Outside temperature in degrees Celsius below which there is no + cooling demand. The default 23C is taken as a more liberal + estimation following European computational practices + (e.g. UK Met Office and European commission take as thresholds + 22C and 24C, respectively) + a : float + Linear factor relating cooling demand to outside temperature. + constant : float + Constant part of cooling demand that does not depend on outside + temperature (e.g. due to ventilation). + hour_shift : float + Time shift relative to UTC for taking daily average + + Note + ---- + You can also specify all of the general conversion arguments + documented in the `convert_and_aggregate` function. + + """ + return cutout.convert_and_aggregate( + convert_func=convert_cooling_demand, + threshold=threshold, + a=a, + constant=constant, + hour_shift=hour_shift, + **params, + ) + + # solar thermal collectors def convert_solar_thermal( ds, orientation, trigon_model, clearsky_model, c0, c1, t_store diff --git a/atlite/cutout.py b/atlite/cutout.py index db792b75..cd10c755 100644 --- a/atlite/cutout.py +++ b/atlite/cutout.py @@ -32,6 +32,7 @@ from atlite.convert import ( coefficient_of_performance, convert_and_aggregate, + cooling_demand, csp, dewpoint_temperature, heat_demand, @@ -644,6 +645,8 @@ def layout_from_capacity_list(self, data, col="Capacity"): convert_and_aggregate = convert_and_aggregate + cooling_demand = cooling_demand + heat_demand = heat_demand temperature = temperature diff --git a/doc/introduction.rst b/doc/introduction.rst index 5937c549..11047f67 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -19,7 +19,7 @@ relevant quantities, mainly you can create data for * **Solar (PV)** power generation: Using predefined or custom panel properties. * **Solar (thermal)** heat generation from solar collectors. * **Hydro (run-off)** power generation. -* **Heating demand** (based on degree-day approx.). +* **Heating and cooling demand** (based on degree-day approx.). How it works ======================== diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 42f43442..ea85f186 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -11,3 +11,5 @@ * The option ``capacity_factor_timeseries`` can be selected when creating capacity factors to obtain the capacity factor of the selected resource per grid cell. + + * The methods ``convert_cooling_demand`` and ``cooling_demand`` are implemented to evaluate cooling demand using the cooling degree-days approximation.