Source code for cea.technologies.controllers

# -*- coding: utf-8 -*-
"""
controllers
"""
from __future__ import division
import numpy as np

__author__ = "Jimeno A. Fonseca"
__copyright__ = "Copyright 2016, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Jimeno A. Fonseca", "Gabriel Happle", "Martin Mosteiro"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "cea@arch.ethz.ch"
__status__ = "Production"


# temperature controllers

[docs]def calc_simple_temp_control(tsd, prop_comfort, limit_inf_season, limit_sup_season, weekday): def get_hsetpoint(a, b, Thset, Thsetback, weekday): if (b < limit_inf_season or b >= limit_sup_season): if a == 0: if 5 <= weekday <= 6: # system is off on the weekend return np.nan # huge so the system will be off else: return Thsetback else: return Thset else: return np.nan # huge so the system will be off def get_csetpoint(a, b, Tcset, Tcsetback, weekday): if limit_inf_season <= b < limit_sup_season: if a == 0: if 5 <= weekday <= 6: # system is off on the weekend return np.nan # huge so the system will be off else: return Tcsetback else: return Tcset else: return np.nan # huge so the system will be off tsd['ve'] = tsd['people'] * prop_comfort['Ve_lps'] * 3.6 # in m3/h tsd['ta_hs_set'] = np.vectorize(get_hsetpoint)(tsd['people'], range(8760), prop_comfort['Ths_set_C'], prop_comfort['Ths_setb_C'], weekday) tsd['ta_cs_set'] = np.vectorize(get_csetpoint)(tsd['people'], range(8760), prop_comfort['Tcs_set_C'], prop_comfort['Tcs_setb_C'], weekday) return tsd
[docs]def temperature_control_tabs(bpr, tsd, hoy, gv, control): """ Controls for TABS operating temperature based on the operating parameters defined by Koschenz and Lehmann "Thermoaktive Bauteilsysteme (TABS)" (2000), that is: maximum surface temperature and maximum temperature difference between TABS surface and air. If either of these is exceeded, they are set to the maximum and all temperatures are recalculated. The formulas below are simply reformulations of the calculations in the R-C model. """ # TODO: add documentation of input # TODO: add credits # TODO: add source and numbers of equations in standard # get values from bpr Htr_ms = bpr.rc_model['Htr_ms'] Htr_w = bpr.rc_model['Htr_w'] Htr_em = bpr.rc_model['Htr_em'] Htr_is = bpr.rc_model['Htr_is'] Cm = bpr.rc_model['Cm'] # get values from tsd Hve = tsd['h_ve_adj'][hoy] I_ia = tsd['I_ia'][hoy] I_st = tsd['I_st'][hoy] I_m = tsd['I_m'][hoy] te_t = tsd['T_ext'][hoy] tm_t0 = tsd['Tm'][hoy-1] # assuming that tm_t0 means mass temperature at previous time step if control == 'max_ts': # if the calculated surface temperature exceeds the maximum, set ts = ts_max and calculate maximum power # and all other temperatures ts_max = gv.max_surface_temperature_tabs a = np.array([[(Hve + Htr_is), (-Htr_is), 0, (-0.5)], [(-Htr_is), (Htr_w + Htr_ms + Htr_is), (-Htr_ms), (-0.5)], [0, (-Htr_ms), ((Htr_ms + Htr_em) / 2 + Cm), (-0.5)], [0, 1, 0, 0]]) b = np.array([(Hve * te_t + I_ia), (Htr_w * te_t + I_st + Htr_ms / 2 * tm_t0), (Htr_em * te_t + (-(Htr_ms + Htr_em) / 2 + Cm) * tm_t0 + I_m), ts_max]) [ta, ts, tm_t, IH_max] = np.linalg.solve(a, b) if control == 'max_ts-ta': # if the calculated temperature difference between the surface and inside air exceeds the maximum, # set ts - ta = dt_max and calculate maximum power and other temperatures dt_max = gv.max_temperature_difference_tabs a = np.array([[(Hve + Htr_is), (-Htr_is), 0, (-0.5)], [(-Htr_is), (Htr_w + Htr_ms + Htr_is), (-Htr_ms), (-0.5)], [0, (-Htr_ms), ((Htr_ms + Htr_em) / 2 + Cm), (-0.5)], [-1, 1, 0, 0]]) b = np.array([(Hve * te_t + I_ia), (Htr_w * te_t + I_st + Htr_ms / 2 * tm_t0), (Htr_em * te_t + (-(Htr_ms + Htr_em) / 2 + Cm) * tm_t0 + I_m), dt_max]) [ta, ts, tm_t, IH_max] = np.linalg.solve(a, b) return ta, ts, tm_t, IH_max
# ventilation controllers
[docs]def calc_simple_ventilation_control(ve, people, Af, gv, hour_day, hour_year, n50): """ Modified version of calc_simple_ventilation_control from functions. Fixed infiltration according to schedule is only considered for mechanically ventilated buildings. ve : required ventilation rate according to schedule (?) people : occupancy schedules (pax?) Af : conditioned floor area (m2) gv : globalvars hour_day : hour of the day [0..23] hour_year : hour of the year [0..8760] n50 : building envelope leakiness from archetypes q_req : required ventilation rate schedule (m3/s) """ # TODO: check units # 'flat rate' infiltration considered for all buildings # estimation of infiltration air volume flow rate according to Eq. (3) in DIN 1946-6 n_inf = 0.5 * n50 * (gv.delta_p_dim/50) ** (2/3) # [air changes per hour] m3/h.m2 infiltration = gv.hf * Af * n_inf * 0.000277778 # m3/s if (21 < hour_day or hour_day < 7) and not gv.is_heating_season(hour_year): q_req = max(ve * 0.000277778, infiltration) * 1.3 # m3/s # free cooling during summer nights (1.3x required ventilation rate per pax plus infiltration) else: q_req = max(ve * 0.000277778, infiltration) # m3/s return q_req # m3/s
[docs]def calc_ventialtion_HVAC_buildings(area_envelope, HVAC_on, Tin, Tout, ws, method): """ infiltration according to energy plus, blast, or DOE2 tools """ def calc_F_schedule(HVAC_on): #according to (SSPC 90.1 Envelope Subcommittee if HVAC_on: F_schedule = 0.25 else: F_schedule = 1 return F_schedule def calc_Idesign(ws, area_envelope): I_75pa = 0.00914400602372 * area_envelope # known leakage rate(1.8cfm/sf2) at 75pa per area of building envelope in m/s n = 0.65 # air flow exponent Cs = 0.1617 # average surface presure coefficient rho = 1.18 #kg/m3 alpha_terrain = 0.22 # urban terrain constant I_design = (alpha_terrain+1)*I_75pa*(0.5*Cs*rho*(ws**2))**n # m3/s return I_design if method is "BLAST": A = 0.606 B = 0.03636 C = 0.1177 elif method is "EPLUS": A = 1 B = 0 C = 0 elif method is "DOE2": A = 1 B = 0 C = 0.224 else: A = 1 B = 0 C = 0.224 I_design = calc_Idesign(ws, area_envelope) F_schedule = calc_F_schedule(HVAC_on) ventilation = I_design + F_schedule *(A+B*abs(Tin-Tout)+C*ws) return ventilation