Source code for buildingmodel.models.climate

# -*- coding: utf-8 -*-

import numpy as np
import pvlib
from buildingmodel.logger import duration_logging


[docs] @duration_logging def sun_position(climate_data, latitude, longitude): """Calculate the height and azimuth of the sun for an array of time steps at a given latitude and longitude Based on astronomy computations provided by the `ephem package <https://rhodesmill.org/pyephem/>`_ Uses the ephem.Observer and ephem.Sun classes. Args: climate_data (Dataframe): a Dataframe with a DateTimeIndex for which the sun position is to be calculated latitude (float): longitude (float): Returns: Dataframe : DataFrame containing sun_height and sun_azimuth """ solar_position = pvlib.solarposition.get_solarposition( climate_data.index, latitude, longitude ) climate_data["sun_height"] = solar_position["elevation"] climate_data["sun_azimuth"] = solar_position["azimuth"]
[docs] @duration_logging def sky_temperature(climate_data): """Calculate the sky temperature using the air temperature, dew point temperature and sky cover Based on `EnergyPlus model <https://bigladdersoftware.com/epx/docs/8-3/engineering-reference/climate-calculations .html#energyplus-sky-temperature-calculation/>`_. Args: climate_data (Dataframe): a Dataframe containing dew point temperature, air temperature and opaque sky cover data latitude (float): longitude (float): Returns: Dataframe : DataFrame containing sky temperature """ sigma = 5.66797e-8 # Stefan-Boltzmann constant (in W/m2-K4) N = climate_data["opaque_sky_cover"] / 10.0 sky_emissivity = ( 0.787 + 0.764 * np.log((climate_data["dew_point_temperature"] + 273.15) / 273.15) ) * (1 + 0.0224 * N - 0.0035 * N**2 + 0.00028 * N**3) horizontal_infrared_radiation = ( sky_emissivity * sigma * (climate_data["air_temperature"] + 273.15) ** 4 ) sky_temperature = (horizontal_infrared_radiation / sigma) ** 0.25 - 273.15 climate_data["sky_temperature"] = sky_temperature
[docs] @duration_logging def ground_temperature(climate_data, ground_diffusivity=0.8e-6, depth=0.5): """Calculate the ground temperature using the air temperature Uses the `Kusuda model <https://bigladdersoftware.com/epx/docs/8-4/engineering-reference/undisturbed-ground -temperature-model-kusuda.html/>`_ Typical values of thermal diffusivity for various types of soils can be found in : Andújar Márquez, J. M., Martínez Bohórquez, M. Á., & Gómez Melgar, S. (2016). Ground thermal diffusivity calculation by direct soil temperature measurement. Application to very low enthalpy geothermal energy systems. Sensors, 16(3), 306. Args: climate_data (Dataframe): a Dataframe containing air temperature ground_diffusivity (float): the thermal diffusivity of the soil in m²/s depth (float): the depth at which the ground temperature is to be estimated in meters Returns: Dataframe : DataFrame containing ground temperature """ # Monthly rolling average of air temperature air_temperature_smoothed = ( climate_data["air_temperature"].rolling(int(24.0 * 30.5)).mean().bfill() ) ground_temperature_delta = ( max(air_temperature_smoothed) - min(air_temperature_smoothed) ) / 2.0 ground_average_temperature = np.mean(air_temperature_smoothed) time = (np.array(list(range(len(climate_data["air_temperature"])))) + 1.0) / 24.0 phase_shift = climate_data["air_temperature"].idxmin().dayofyear # Kusuda equation 1965 ground_temperature = ground_average_temperature - ground_temperature_delta * np.exp( -depth * np.sqrt(np.pi / (ground_diffusivity * 365.0 * 3600.0)) ) * np.cos( 2 * np.pi / 365.0 * ( time - phase_shift - depth / 2.0 * np.sqrt(365.0 / (np.pi * ground_diffusivity * 3600.0)) ) ) climate_data["ground_temperature"] = ground_temperature
[docs] def run_models(climate_data, metadata, parameters): """Runs all climate models Args: climate_data (DataFrame): a Dataframe containing EPW climate data loaded by :func:`buildingmodel.io.climate.load_data` Returns: Dataframe : DataFrame containing all necessary climate data """ sun_position(climate_data, metadata["latitude"], metadata["longitude"]) sky_temperature(climate_data) ground_temperature(climate_data) climate_data["air_temperature"] -= ( (metadata["building_altitude"] - metadata["altitude"]) / 100.0 * parameters.temperature_altitude_correction ) climate_data["extra_terrestrial"] = pvlib.irradiance.get_extra_radiation( climate_data.index ).values