def test_mixed_use_schedules(self): locator = ReferenceCaseOpenLocator() # calculate schedules list_uses = ['OFFICE', 'INDUSTRIAL'] occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} gv = GlobalVariables() date = pd.date_range(gv.date_start, periods=8760, freq='H') archetype_schedules, archetype_values = schedule_maker( date, locator, list_uses) calculated_schedules = calc_schedules(list_uses, archetype_schedules, occupancy, archetype_values) config = ConfigParser.SafeConfigParser() config.read(get_test_config_path()) reference_results = json.loads( config.get('test_mixed_use_schedules', 'reference_results')) for schedule in reference_results: self.assertAlmostEqual( calculated_schedules[schedule][REFERENCE_TIME], reference_results[schedule], places=4, msg="Schedule '%s' at time %s, %f != %f" % (schedule, str(REFERENCE_TIME), calculated_schedules[schedule][REFERENCE_TIME], reference_results[schedule]))
def test_mixed_use_schedules(self): config = cea.config.Configuration(cea.config.DEFAULT_CONFIG) stochastic_occupancy = config.demand.use_stochastic_occupancy gv = GlobalVariables() gv.config = config locator = ReferenceCaseOpenLocator() date = pd.date_range(gv.date_start, periods=8760, freq='H') building_properties = BuildingProperties(locator, gv, False, 'CH', False) bpr = building_properties['B01'] list_uses = ['OFFICE', 'INDUSTRIAL'] bpr.occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} # calculate schedules archetype_schedules, archetype_values = schedule_maker( 'CH', date, locator, list_uses) calculated_schedules = calc_schedules(list_uses, archetype_schedules, bpr, archetype_values, stochastic_occupancy) config = ConfigParser.SafeConfigParser() config.read(get_test_config_path()) reference_results = json.loads( config.get('test_mixed_use_schedules', 'reference_results')) for schedule in reference_results: self.assertAlmostEqual( calculated_schedules[schedule][REFERENCE_TIME], reference_results[schedule], places=4, msg="Schedule '%s' at time %s, %f != %f" % (schedule, str(REFERENCE_TIME), calculated_schedules[schedule][REFERENCE_TIME], reference_results[schedule]))
def create_test_data(): """Create test data to compare against - run this the first time you make changes that affect the results. Note, this will overwrite the previous test data.""" config = ConfigParser.SafeConfigParser() config.read(get_test_config_path()) if not config.has_section('test_mixed_use_archetype_values'): config.add_section('test_mixed_use_archetype_values') locator = ReferenceCaseOpenLocator() expected_results = calculate_test_mixed_use_archetype_values_results( locator) config.set('test_mixed_use_archetype_values', 'expected_results', expected_results.to_json()) # calculate schedules list_uses = ['OFFICE', 'INDUSTRIAL'] occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} gv = GlobalVariables() date = pd.date_range(gv.date_start, periods=8760, freq='H') archetype_schedules, archetype_values = schedule_maker( date, locator, list_uses) calculated_schedules = calc_schedules(list_uses, archetype_schedules, occupancy, archetype_values) if not config.has_section('test_mixed_use_schedules'): config.add_section('test_mixed_use_schedules') config.set( 'test_mixed_use_schedules', 'reference_results', json.dumps({ schedule: calculated_schedules[schedule][REFERENCE_TIME] for schedule in calculated_schedules.keys() })) with open(get_test_config_path(), 'w') as f: config.write(f)
def create_data(): """Create test data to compare against - run this the first time you make changes that affect the results. Note, this will overwrite the previous test data.""" test_config = ConfigParser.SafeConfigParser() test_config.read(get_test_config_path()) if not test_config.has_section('test_mixed_use_archetype_values'): test_config.add_section('test_mixed_use_archetype_values') locator = ReferenceCaseOpenLocator() expected_results = calculate_mixed_use_archetype_values_results(locator) test_config.set('test_mixed_use_archetype_values', 'expected_results', expected_results.to_json()) config = cea.config.Configuration(cea.config.DEFAULT_CONFIG) locator = ReferenceCaseOpenLocator() # calculate schedules building_properties = BuildingProperties(locator, False) bpr = building_properties['B01'] list_uses = ['OFFICE', 'INDUSTRIAL'] bpr.occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} # get year from weather file weather_path = locator.get_weather_file() weather_data = epwreader.epw_reader(weather_path)[['year']] year = weather_data['year'][0] date = pd.date_range(str(year) + '/01/01', periods=HOURS_IN_YEAR, freq='H') archetype_schedules, archetype_values = schedule_maker( 'CH', date, locator, list_uses) stochastic_occupancy = config.demand.use_stochastic_occupancy calculated_schedules = calc_schedules(list_uses, archetype_schedules, bpr, archetype_values, stochastic_occupancy) if not test_config.has_section('test_mixed_use_schedules'): test_config.add_section('test_mixed_use_schedules') test_config.set( 'test_mixed_use_schedules', 'reference_results', json.dumps({ schedule: calculated_schedules[schedule][REFERENCE_TIME] for schedule in calculated_schedules.keys() })) with open(get_test_config_path(), 'w') as f: test_config.write(f)
def create_test_data(): """Create test data to compare against - run this the first time you make changes that affect the results. Note, this will overwrite the previous test data.""" config = ConfigParser.SafeConfigParser() config.read(get_test_config_path()) if not config.has_section('test_mixed_use_archetype_values'): config.add_section('test_mixed_use_archetype_values') locator = ReferenceCaseOpenLocator() expected_results = calculate_test_mixed_use_archetype_values_results( locator) config.set('test_mixed_use_archetype_values', 'expected_results', expected_results.to_json()) config = cea.config.Configuration(cea.config.DEFAULT_CONFIG) gv = GlobalVariables() gv.config = config locator = ReferenceCaseOpenLocator() # calculate schedules building_properties = BuildingProperties(locator, gv, False, 'CH', False) bpr = building_properties['B01'] list_uses = ['OFFICE', 'INDUSTRIAL'] bpr.occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} gv = GlobalVariables() date = pd.date_range(gv.date_start, periods=8760, freq='H') archetype_schedules, archetype_values = schedule_maker( 'CH', date, locator, list_uses) stochastic_occupancy = config.demand.use_stochastic_occupancy calculated_schedules = calc_schedules(list_uses, archetype_schedules, bpr, archetype_values, stochastic_occupancy) if not config.has_section('test_mixed_use_schedules'): config.add_section('test_mixed_use_schedules') config.set( 'test_mixed_use_schedules', 'reference_results', json.dumps({ schedule: calculated_schedules[schedule][REFERENCE_TIME] for schedule in calculated_schedules.keys() })) with open(get_test_config_path(), 'w') as f: config.write(f)
def test_mixed_use_schedules(self): # get reference case to be tested archive = zipfile.ZipFile( os.path.join(os.path.dirname(cea.examples.__file__), 'reference-case-open.zip')) archive.extractall(tempfile.gettempdir()) reference_case = os.path.join(tempfile.gettempdir(), 'reference-case-open', 'baseline') locator = InputLocator(reference_case) # calculate schedules list_uses = ['OFFICE', 'INDUSTRIAL'] occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} gv = GlobalVariables() date = pd.date_range(gv.date_start, periods=8760, freq='H') archetype_schedules, archetype_values = schedule_maker( date, locator, list_uses) calculated_schedules = calc_schedules(list_uses, archetype_schedules, occupancy, archetype_values) reference_time = 3456 reference_results = { 'El': 0.1080392156862745, 'Qs': 0.0088163265306122462, 've': 0.01114606741573034, 'Epro': 0.17661721828842394, 'people': 0.0080000000000000019, 'Ed': 0.0, 'Vww': 0.0, 'Ea': 0.1340740740740741, 'Ere': 0.0, 'Vw': 0.0, 'X': 0.010264150943396229 } for schedule in reference_results: self.assertEqual(calculated_schedules[schedule][reference_time], reference_results[schedule], msg="Schedule '%s' at time %s, %f != %f" % (schedule, str(reference_time), calculated_schedules[schedule][reference_time], reference_results[schedule]))
def test_mixed_use_schedules(self): locator = ReferenceCaseOpenLocator() config = cea.config.Configuration(cea.config.DEFAULT_CONFIG) config.scenario = locator.scenario stochastic_occupancy = config.demand.use_stochastic_occupancy # get year from weather file weather_path = locator.get_weather_file() weather_data = epwreader.epw_reader(weather_path)[['year']] year = weather_data['year'][0] date = pd.date_range(str(year) + '/01/01', periods=HOURS_IN_YEAR, freq='H') building_properties = BuildingProperties(locator, False) bpr = building_properties['B01'] list_uses = ['OFFICE', 'INDUSTRIAL'] bpr.occupancy = {'OFFICE': 0.5, 'INDUSTRIAL': 0.5} # calculate schedules archetype_schedules, archetype_values = schedule_maker( date, locator, list_uses) calculated_schedules = calc_schedules(list_uses, archetype_schedules, bpr, archetype_values, stochastic_occupancy) config = ConfigParser.SafeConfigParser() config.read(get_test_config_path()) reference_results = json.loads( config.get('test_mixed_use_schedules', 'reference_results')) for schedule in reference_results: self.assertAlmostEqual( calculated_schedules[schedule][REFERENCE_TIME], reference_results[schedule], places=4, msg="Schedule '%s' at time %s, %f != %f" % (schedule, str(REFERENCE_TIME), calculated_schedules[schedule][REFERENCE_TIME], reference_results[schedule]))
def initialize_inputs(bpr, usage_schedules, weather_data, use_stochastic_occupancy): """ :param bpr: a collection of building properties for the building used for thermal loads calculation :type bpr: BuildingPropertiesRow :param usage_schedules: dict containing schedules and function names of buildings. :type usage_schedules: dict :param weather_data: data from the .epw weather file. Each row represents an hour of the year. The columns are: ``drybulb_C``, ``relhum_percent``, and ``windspd_ms`` :type weather_data: pandas.DataFrame :param use_stochastic_occupancy: Boolean specifying whether stochastic occupancy should be used. If False, deterministic schedules are used. :type use_stochastic_occupancy: Boolean :return schedules: :rtype schedules: :return tsd: time series data dict :rtype tsd: dict """ # TODO: documentation # this is used in the NN please do not erase or change!! tsd = initialize_timestep_data(bpr, weather_data) # get schedules list_uses = usage_schedules['list_uses'] archetype_schedules = usage_schedules['archetype_schedules'] archetype_values = usage_schedules['archetype_values'] schedules = occupancy_model.calc_schedules(list_uses, archetype_schedules, bpr, archetype_values, use_stochastic_occupancy) # calculate occupancy schedule and occupant-related parameters tsd['people'] = np.floor(schedules['people']) tsd['ve'] = schedules['ve'] * (bpr.comfort['Ve_lps'] * 3.6) # in m3/h tsd['Qs'] = schedules['Qs'] * bpr.internal_loads['Qs_Wp'] # in W # # latent heat gains tsd['w_int'] = sensible_loads.calc_Qgain_lat(schedules, bpr) return schedules, tsd
def calc_thermal_loads(building_name, bpr, weather_data, usage_schedules, date, gv, locator, use_dynamic_infiltration_calculation=False): """ Calculate thermal loads of a single building with mechanical or natural ventilation. Calculation procedure follows the methodology of ISO 13790 The structure of ``usage_schedules`` is: .. code-block:: python :emphasize-lines: 3,5 { 'list_uses': ['ADMIN', 'GYM', ...], 'schedules': [ ([...], [...], [...], [...]), (), (), () ] } * each element of the 'list_uses' entry represents a building occupancy type. * each element of the 'schedules' entry represents the schedules for a building occupancy type. * the schedules for a building occupancy type are a 4-tuple (occupancy, electricity, domestic hot water, probability of use), with each element of the 4-tuple being a list of hourly values (8760 values). Side effect include a number of files in two folders: * ``scenario/outputs/data/demand`` * ``${Name}.csv`` for each building * temporary folder (as returned by ``tempfile.gettempdir()``) * ``${Name}T.csv`` for each building daren-thomas: as far as I can tell, these are the only side-effects. :param building_name: name of building :type building_name: str :param bpr: a collection of building properties for the building used for thermal loads calculation :type bpr: BuildingPropertiesRow :param weather_data: data from the .epw weather file. Each row represents an hour of the year. The columns are: ``drybulb_C``, ``relhum_percent``, and ``windspd_ms`` :type weather_data: pandas.DataFrame :param usage_schedules: dict containing schedules and function names of buildings. :type usage_schedules: dict :param date: the dates (hours) of the year (8760) :type date: pandas.tseries.index.DatetimeIndex :param gv: global variables / context :type gv: GlobalVariables :returns: This function does not return anything :rtype: NoneType """ tsd = initialize_timestep_data(bpr, weather_data) # get schedules list_uses = usage_schedules['list_uses'] archetype_schedules = usage_schedules['archetype_schedules'] archetype_values = usage_schedules['archetype_values'] schedules = occupancy_model.calc_schedules(list_uses, archetype_schedules, bpr.occupancy, archetype_values) # calculate occupancy schedule and occupant-related parameters tsd['people'] = schedules['people'] * bpr.rc_model['Af'] tsd['ve'] = schedules['ve'] * (bpr.comfort['Ve_lps'] * 3.6) * bpr.rc_model['Af'] # in m3/h tsd['Qs'] = schedules['Qs'] * bpr.internal_loads['Qs_Wp'] * bpr.rc_model['Af'] # in W # get electrical loads (no auxiliary loads) tsd = electrical_loads.calc_Eint(tsd, bpr, schedules) # get refrigeration loads tsd['Qcref'], tsd['mcpref'], \ tsd['Tcref_re'], tsd['Tcref_sup'] = np.vectorize(refrigeration_loads.calc_Qcref)(tsd['Eref']) # get server loads tsd['Qcdataf'], tsd['mcpdataf'], \ tsd['Tcdataf_re'], tsd['Tcdataf_sup'] = np.vectorize(datacenter_loads.calc_Qcdataf)(tsd['Edataf']) # ground water temperature in C during heating season (winter) according to norm tsd['Twwf_re'][:] = bpr.building_systems['Tww_re_0'] # ground water temperature in C during non-heating season (summer) according to norm - FIXME: which norm? tsd['Twwf_re'][gv.seasonhours[0] + 1:gv.seasonhours[1] - 1] = 14 if bpr.rc_model['Af'] > 0: # building has conditioned area ventilation_air_flows_simple.calc_m_ve_required(bpr, tsd) ventilation_air_flows_simple.calc_m_ve_leakage_simple(bpr, tsd, gv) # get internal comfort properties tsd = controllers.calc_simple_temp_control(tsd, bpr.comfort, gv.seasonhours[0] + 1, gv.seasonhours[1], date.dayofweek) # # latent heat gains tsd['w_int'] = sensible_loads.calc_Qgain_lat(schedules, bpr.internal_loads['X_ghp'], bpr.rc_model['Af'], bpr.hvac['type_cs'], bpr.hvac['type_hs']) # end-use demand calculation for t in range(-720, 8760): hoy = helpers.seasonhour_2_hoy(t, gv) # heat flows in [W] # sensible heat gains tsd = sensible_loads.calc_Qgain_sen(hoy, tsd, bpr, gv) if use_dynamic_infiltration_calculation: # OVERWRITE STATIC INFILTRATION WITH DYNAMIC INFILTRATION RATE dict_props_nat_vent = ventilation_air_flows_detailed.get_properties_natural_ventilation(bpr, gv) qm_sum_in, qm_sum_out = ventilation_air_flows_detailed.calc_air_flows( tsd['theta_a'][hoy - 1] if not np.isnan(tsd['theta_a'][hoy - 1]) else tsd['T_ext'][hoy - 1], tsd['u_wind'][hoy], tsd['T_ext'][hoy], dict_props_nat_vent) # INFILTRATION IS FORCED NOT TO REACH ZERO IN ORDER TO AVOID THE RC MODEL TO FAIL tsd['m_ve_inf'][hoy] = max(qm_sum_in / 3600, 1 / 3600) # ventilation air flows [kg/s] ventilation_air_flows_simple.calc_air_mass_flow_mechanical_ventilation(bpr, tsd, hoy) ventilation_air_flows_simple.calc_air_mass_flow_window_ventilation(bpr, tsd, hoy) # ventilation air temperature ventilation_air_flows_simple.calc_theta_ve_mech(bpr, tsd, hoy, gv) # heating / cooling demand of building rc_model_crank_nicholson_procedure.calc_rc_model_demand_heating_cooling(bpr, tsd, hoy, gv) # END OF FOR LOOP # add emission losses to heating / cooling demand tsd['Qhs_sen_incl_em_ls'] = tsd['Qhs_sen_sys'] + tsd['Qhs_em_ls'] tsd['Qcs_sen_incl_em_ls'] = tsd['Qcs_sen_sys'] + tsd['Qcs_em_ls'] # Calc of Qhs_dis_ls/Qcs_dis_ls - losses due to distribution of heating/cooling coils Qhs_d_ls, Qcs_d_ls = np.vectorize(sensible_loads.calc_Qhs_Qcs_dis_ls)(tsd['theta_a'], tsd['T_ext'], tsd['Qhs_sen_incl_em_ls'], tsd['Qcs_sen_incl_em_ls'], bpr.building_systems['Ths_sup_0'], bpr.building_systems['Ths_re_0'], bpr.building_systems['Tcs_sup_0'], bpr.building_systems['Tcs_re_0'], np.nanmax(tsd['Qhs_sen_incl_em_ls']), np.nanmin(tsd['Qcs_sen_incl_em_ls']), gv.D, bpr.building_systems['Y'][0], bpr.hvac['type_hs'], bpr.hvac['type_cs'], gv.Bf, bpr.building_systems['Lv']) tsd['Qcsf_lat'] = tsd['Qcs_lat_sys'] tsd['Qhsf_lat'] = tsd['Qhs_lat_sys'] # Calc requirements of generation systems (both cooling and heating do not have a storage): tsd['Qhs'] = tsd['Qhs_sen_sys'] tsd['Qhsf'] = tsd['Qhs'] + tsd['Qhs_em_ls'] + Qhs_d_ls # no latent is considered because it is already added a # s electricity from the adiabatic system. tsd['Qcs'] = tsd['Qcs_sen_sys'] + tsd['Qcsf_lat'] tsd['Qcsf'] = tsd['Qcs'] + tsd['Qcs_em_ls'] + Qcs_d_ls # Calc nominal temperatures of systems Qhsf_0 = np.nanmax(tsd['Qhsf']) # in W Qcsf_0 = np.nanmin(tsd['Qcsf']) # in W in negative # Cal temperatures of all systems tsd['Tcsf_re'], tsd['Tcsf_sup'], tsd['Thsf_re'], \ tsd['Thsf_sup'], tsd['mcpcsf'], tsd['mcphsf'] = sensible_loads.calc_temperatures_emission_systems(tsd, bpr, Qcsf_0, Qhsf_0, gv) # Hot water loads -> TODO: is it not possible to have water loads without conditioned area (Af == 0)? Mww, tsd['Qww'], Qww_ls_st, tsd['Qwwf'], Qwwf_0, Tww_st, Vww, Vw, tsd['mcpwwf'] = hotwater_loads.calc_Qwwf( bpr.building_systems['Lcww_dis'], bpr.building_systems['Lsww_dis'], bpr.building_systems['Lvww_c'], bpr.building_systems['Lvww_dis'], tsd['T_ext'], tsd['theta_a'], tsd['Twwf_re'], bpr.building_systems['Tww_sup_0'], bpr.building_systems['Y'], gv, schedules, bpr) # calc auxiliary loads tsd['Eauxf'], tsd['Eauxf_hs'], tsd['Eauxf_cs'], \ tsd['Eauxf_ve'], tsd['Eauxf_ww'], tsd['Eauxf_fw'] = electrical_loads.calc_Eauxf(bpr.geometry['Blength'], bpr.geometry['Bwidth'], Mww, tsd['Qcsf'], Qcsf_0, tsd['Qhsf'], Qhsf_0, tsd['Qww'], tsd['Qwwf'], Qwwf_0, tsd['Tcsf_re'], tsd['Tcsf_sup'], tsd['Thsf_re'], tsd['Thsf_sup'], Vw, bpr.age['built'], bpr.building_systems[ 'fforma'], gv, bpr.geometry['floors_ag'], bpr.occupancy['PFloor'], bpr.hvac['type_cs'], bpr.hvac['type_hs'], tsd['Ehs_lat_aux'], tsd) elif bpr.rc_model['Af'] == 0: # if building does not have conditioned area tsd = update_timestep_data_no_conditioned_area(tsd) else: raise tsd['Qhprof'][:] = schedules['Qhpro'] * bpr.internal_loads['Qhpro_Wm2'] * bpr.rc_model['Af'] # in kWh # calculate other quantities tsd['Qcsf_lat'] = abs(tsd['Qcsf_lat']) tsd['Qcsf'] = abs(tsd['Qcsf']) tsd['Qcs'] = abs(tsd['Qcs']) tsd['people'] = np.floor(tsd['people']) tsd['QHf'] = tsd['Qhsf'] + tsd['Qwwf'] + tsd['Qhprof'] tsd['QCf'] = tsd['Qcsf'] + tsd['Qcdataf'] + tsd['Qcref'] tsd['Ef'] = tsd['Ealf'] + tsd['Edataf'] + tsd['Eprof'] + tsd['Ecaf'] + tsd['Eauxf'] + tsd['Eref'] tsd['QEf'] = tsd['QHf'] + tsd['QCf'] + tsd['Ef'] # write results to csv gv.demand_writer.results_to_csv(tsd, bpr, locator, date, building_name) # write report gv.report(tsd, locator.get_demand_results_folder(), building_name) return