diff --git a/building_energy_standards_data/applications/create_openstudio_standards_json.py b/building_energy_standards_data/applications/create_openstudio_standards_json.py index b2f9144..72db8c5 100644 --- a/building_energy_standards_data/applications/create_openstudio_standards_json.py +++ b/building_energy_standards_data/applications/create_openstudio_standards_json.py @@ -381,6 +381,9 @@ def create_openstudio_standards_data_json_ashrae_90_1( "constructions": "support_constructions", "curves": "support_performance_curves", "space_type_schedules": "support_schedules", + "occupant_types": "support_occupant_types", + "occupant_energy_behavior": "support_occupant_energy_behavior", + "occupant_physical_characteristics": "support_occupant_physical_characteristics", } # Generate and "export" the data to the correct location within the OpenStudio Standards repository diff --git a/building_energy_standards_data/database_files/support_occupant_energy_behavior.json b/building_energy_standards_data/database_files/support_occupant_energy_behavior.json new file mode 100644 index 0000000..628c0ba --- /dev/null +++ b/building_energy_standards_data/database_files/support_occupant_energy_behavior.json @@ -0,0 +1,29 @@ +[ + { + "energy_behavior_name": "office_wasteful", + "cooling_setpoint": 21.9, + "cooling_setpoint_units": "Celsius", + "heating_setpoint": 24.9, + "heating_setpoint_units": "Celsius", + "minimum_dimming_level": 0, + "annotation": "Based on previous literature, see the reference table in Occupant Types Dataset section in Structure.md" + }, + { + "energy_behavior_name": "office_normal", + "cooling_setpoint": 23.7, + "cooling_setpoint_units": "Celsius", + "heating_setpoint": 22.7, + "heating_setpoint_units": "Celsius", + "minimum_dimming_level": 0.2, + "annotation": "Based on previous literature, see the reference table in Occupant Types Dataset section in Structure.md" + }, + { + "energy_behavior_name": "office_austerity", + "cooling_setpoint": 25.4, + "cooling_setpoint_units": "Celsius", + "heating_setpoint": 20.5, + "heating_setpoint_units": "Celsius", + "minimum_dimming_level": 0.5, + "annotation": "Based on previous literature, see the reference table in Occupant Types Dataset section in Structure.md" + } +] \ No newline at end of file diff --git a/building_energy_standards_data/database_files/support_occupant_physical_characteristics.json b/building_energy_standards_data/database_files/support_occupant_physical_characteristics.json new file mode 100644 index 0000000..d752a1f --- /dev/null +++ b/building_energy_standards_data/database_files/support_occupant_physical_characteristics.json @@ -0,0 +1,12 @@ +[ + { + "physical_characteristic_name": "office_worker_physical_characteristics", + "schedule_activity_level": "default_activity_schedule", + "schedule_clothing_insulation": "default_clothing_insulation_schedule", + "schedule_air_velocity": "default_air_velocity_schedule", + "work_efficiency": 0, + "co2_generation": 0.0084, + "co2_generation_units": "cfm/met/person", + "annotation": null + } +] \ No newline at end of file diff --git a/building_energy_standards_data/database_files/support_occupant_types.json b/building_energy_standards_data/database_files/support_occupant_types.json new file mode 100644 index 0000000..9a9cb53 --- /dev/null +++ b/building_energy_standards_data/database_files/support_occupant_types.json @@ -0,0 +1,74 @@ +[ + { + "name": "office_occupant", + "energy_behavior": "office_wasteful", + "occupant_schedule": "office_occupant_early_bird", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_wasteful", + "occupant_schedule": "office_occupant_regular_worker", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_wasteful", + "occupant_schedule": "office_occupant_late_owl", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_wasteful", + "occupant_schedule": "office_occupant_night_shift", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_normal", + "occupant_schedule": "office_occupant_early_bird", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_normal", + "occupant_schedule": "office_occupant_regular_worker", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_normal", + "occupant_schedule": "office_occupant_late_owl", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_normal", + "occupant_schedule": "office_occupant_night_shift", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_austerity", + "occupant_schedule": "office_occupant_early_bird", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_austerity", + "occupant_schedule": "office_occupant_regular_worker", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_austerity", + "occupant_schedule": "office_occupant_late_owl", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + }, + { + "name": "office_occupant", + "energy_behavior": "office_austerity", + "occupant_schedule": "office_occupant_night_shift", + "occupant_physical_characteristics": "office_worker_physical_characteristics" + } +] \ No newline at end of file diff --git a/building_energy_standards_data/database_files/support_schedules.json b/building_energy_standards_data/database_files/support_schedules.json index 381e500..e35a94d 100644 --- a/building_energy_standards_data/database_files/support_schedules.json +++ b/building_energy_standards_data/database_files/support_schedules.json @@ -27538,5 +27538,345 @@ "hr_23": 0, "hr_24": 0, "annotation": null + }, + { + "name": "office_occupant_early_bird", + "category": "Occupancy", + "units": null, + "day_types": "Default|Wkdy", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 0, + "hr_2": 0, + "hr_3": 0.01, + "hr_4": 0.01, + "hr_5": 0.07, + "hr_6": 0.16, + "hr_7": 0.36, + "hr_8": 0.63, + "hr_9": 0.84, + "hr_10": 0.94, + "hr_11": 0.95, + "hr_12": 0.9, + "hr_13": 0.75, + "hr_14": 0.62, + "hr_15": 0.44, + "hr_16": 0.12, + "hr_17": 0, + "hr_18": 0, + "hr_19": 0, + "hr_20": 0, + "hr_21": 0, + "hr_22": 0, + "hr_23": 0, + "hr_24": 0, + "annotation": "From ATUS" + }, + { + "name": "office_occupant_regular_worker", + "category": "Occupancy", + "units": null, + "day_types": "Default|SmrDsn|Wkdy|Sun|Sat|WntrDsn|Hol", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 0, + "hr_2": 0, + "hr_3": 0, + "hr_4": 0, + "hr_5": 0, + "hr_6": 0.01, + "hr_7": 0.07, + "hr_8": 0.3, + "hr_9": 0.73, + "hr_10": 0.91, + "hr_11": 0.96, + "hr_12": 0.95, + "hr_13": 0.87, + "hr_14": 0.93, + "hr_15": 0.97, + "hr_16": 0.96, + "hr_17": 0.72, + "hr_18": 0.25, + "hr_19": 0.09, + "hr_20": 0.03, + "hr_21": 0.02, + "hr_22": 0.01, + "hr_23": 0, + "hr_24": 0, + "annotation": "From ATUS" + }, + { + "name": "office_occupant_late_owl", + "category": "Occupancy", + "units": null, + "day_types": "Default|Wkdy", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 0.1, + "hr_2": 0.05, + "hr_3": 0.03, + "hr_4": 0.01, + "hr_5": 0, + "hr_6": 0, + "hr_7": 0, + "hr_8": 0, + "hr_9": 0, + "hr_10": 0.02, + "hr_11": 0.04, + "hr_12": 0.11, + "hr_13": 0.25, + "hr_14": 0.4, + "hr_15": 0.57, + "hr_16": 0.72, + "hr_17": 0.83, + "hr_18": 0.85, + "hr_19": 0.81, + "hr_20": 0.73, + "hr_21": 0.62, + "hr_22": 0.47, + "hr_23": 0.31, + "hr_24": 0.18, + "annotation": "From ATUS" + }, + { + "name": "office_occupant_night_shift", + "category": "Occupancy", + "units": null, + "day_types": "Default|Wkdy", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 0.86, + "hr_2": 0.8, + "hr_3": 0.75, + "hr_4": 0.72, + "hr_5": 0.65, + "hr_6": 0.62, + "hr_7": 0.52, + "hr_8": 0.24, + "hr_9": 0.22, + "hr_10": 0.22, + "hr_11": 0.22, + "hr_12": 0.2, + "hr_13": 0.18, + "hr_14": 0.19, + "hr_15": 0.19, + "hr_16": 0.21, + "hr_17": 0.22, + "hr_18": 0.26, + "hr_19": 0.34, + "hr_20": 0.39, + "hr_21": 0.46, + "hr_22": 0.58, + "hr_23": 0.84, + "hr_24": 0.88, + "annotation": "From ATUS" + }, + { + "name": "office_occupant_weekend", + "category": "Occupancy", + "units": null, + "day_types": "WntrDsn|Hol|Sun|Sat", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 0.01, + "hr_2": 0.01, + "hr_3": 0.01, + "hr_4": 0.01, + "hr_5": 0.01, + "hr_6": 0.02, + "hr_7": 0.04, + "hr_8": 0.09, + "hr_9": 0.17, + "hr_10": 0.2, + "hr_11": 0.21, + "hr_12": 0.21, + "hr_13": 0.2, + "hr_14": 0.2, + "hr_15": 0.2, + "hr_16": 0.18, + "hr_17": 0.14, + "hr_18": 0.07, + "hr_19": 0.04, + "hr_20": 0.03, + "hr_21": 0.03, + "hr_22": 0.02, + "hr_23": 0.02, + "hr_24": 0.02, + "annotation": "From ATUS" + }, + { + "name": "default_air_velocity_schedule", + "category": "Air Velocity", + "units": "m/s", + "day_types": "Default|SmrDsn|Wkdy|Sun|Sat|WntrDsn|Hol", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 0.2, + "hr_2": 0.2, + "hr_3": 0.2, + "hr_4": 0.2, + "hr_5": 0.2, + "hr_6": 0.2, + "hr_7": 0.2, + "hr_8": 0.2, + "hr_9": 0.2, + "hr_10": 0.2, + "hr_11": 0.2, + "hr_12": 0.2, + "hr_13": 0.2, + "hr_14": 0.2, + "hr_15": 0.2, + "hr_16": 0.2, + "hr_17": 0.2, + "hr_18": 0.2, + "hr_19": 0.2, + "hr_20": 0.2, + "hr_21": 0.2, + "hr_22": 0.2, + "hr_23": 0.2, + "hr_24": 0.2, + "annotation": "Follow current 90.1 prototypes schedule" + }, + { + "name": "default_clothing_insulation_schedule", + "category": "Clothing Insulation", + "units": "clo", + "day_types": "Default|Wkdy|Sat|Sun", + "start_date": "1/1/2023", + "end_date": "4/30/2023", + "type": "Hourly", + "hr_1": 1, + "hr_2": 1, + "hr_3": 1, + "hr_4": 1, + "hr_5": 1, + "hr_6": 1, + "hr_7": 1, + "hr_8": 1, + "hr_9": 1, + "hr_10": 1, + "hr_11": 1, + "hr_12": 1, + "hr_13": 1, + "hr_14": 1, + "hr_15": 1, + "hr_16": 1, + "hr_17": 1, + "hr_18": 1, + "hr_19": 1, + "hr_20": 1, + "hr_21": 1, + "hr_22": 1, + "hr_23": 1, + "hr_24": 1, + "annotation": "Follow current 90.1 prototypes schedule" + }, + { + "name": "default_clothing_insulation_schedule", + "category": "Clothing Insulation", + "units": "clo", + "day_types": "SmrDsn|Wkdy|Sun|Sat", + "start_date": "5/1/2023", + "end_date": "9/30/2023", + "type": "Hourly", + "hr_1": 0.5, + "hr_2": 0.5, + "hr_3": 0.5, + "hr_4": 0.5, + "hr_5": 0.5, + "hr_6": 0.5, + "hr_7": 0.5, + "hr_8": 0.5, + "hr_9": 0.5, + "hr_10": 0.5, + "hr_11": 0.5, + "hr_12": 0.5, + "hr_13": 0.5, + "hr_14": 0.5, + "hr_15": 0.5, + "hr_16": 0.5, + "hr_17": 0.5, + "hr_18": 0.5, + "hr_19": 0.5, + "hr_20": 0.5, + "hr_21": 0.5, + "hr_22": 0.5, + "hr_23": 0.5, + "hr_24": 0.5, + "annotation": "Follow current 90.1 prototypes schedule" + }, + { + "name": "default_clothing_insulation_schedule", + "category": "Clothing Insulation", + "units": "clo", + "day_types": "WntrDsn|Wkdy|Sat|Sun|Hol", + "start_date": "10/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 1, + "hr_2": 1, + "hr_3": 1, + "hr_4": 1, + "hr_5": 1, + "hr_6": 1, + "hr_7": 1, + "hr_8": 1, + "hr_9": 1, + "hr_10": 1, + "hr_11": 1, + "hr_12": 1, + "hr_13": 1, + "hr_14": 1, + "hr_15": 1, + "hr_16": 1, + "hr_17": 1, + "hr_18": 1, + "hr_19": 1, + "hr_20": 1, + "hr_21": 1, + "hr_22": 1, + "hr_23": 1, + "hr_24": 1, + "annotation": "Follow current 90.1 prototypes schedule" + }, + { + "name": "default_activity_schedule", + "category": "Activity", + "units": "Watts/person", + "day_types": "Default|SmrDsn|Wkdy|Sat|Sun|WntrDsn|Hol", + "start_date": "1/1/2023", + "end_date": "12/31/2023", + "type": "Hourly", + "hr_1": 120, + "hr_2": 120, + "hr_3": 120, + "hr_4": 120, + "hr_5": 120, + "hr_6": 120, + "hr_7": 120, + "hr_8": 120, + "hr_9": 120, + "hr_10": 120, + "hr_11": 120, + "hr_12": 120, + "hr_13": 120, + "hr_14": 120, + "hr_15": 120, + "hr_16": 120, + "hr_17": 120, + "hr_18": 120, + "hr_19": 120, + "hr_20": 120, + "hr_21": 120, + "hr_22": 120, + "hr_23": 120, + "hr_24": 120, + "annotation": "Follow current 90.1 prototypes schedule" } ] \ No newline at end of file diff --git a/building_energy_standards_data/database_tables/__init__.py b/building_energy_standards_data/database_tables/__init__.py index c51fd88..95ae964 100644 --- a/building_energy_standards_data/database_tables/__init__.py +++ b/building_energy_standards_data/database_tables/__init__.py @@ -87,6 +87,8 @@ "exterior_lighting_90_1", "exterior_lighting_90_1_prm", "exterior_lighting_IECC", + "support_occupant_energy_behavior", + "support_occupant_physical_characteristics", # tables with foreign keys "level_2_lighting_space_types", "level_2_ventilation_space_types", @@ -95,6 +97,7 @@ "envelope_requirements_90_1", "envelope_requirements_90_1_prm", "envelope_requirements_IECC", + "support_occupant_types", ] diff --git a/building_energy_standards_data/database_tables/support_occupant_energy_behavior.py b/building_energy_standards_data/database_tables/support_occupant_energy_behavior.py new file mode 100644 index 0000000..a88b118 --- /dev/null +++ b/building_energy_standards_data/database_tables/support_occupant_energy_behavior.py @@ -0,0 +1,112 @@ +from building_energy_standards_data.database_engine.database import DBOperation +from building_energy_standards_data.database_engine.database_util import ( + is_float, + getattr_either, +) + +TABLE_NAME = "support_occupant_energy_behavior" + +RECORD_HELP = """ +Must provide a dict that contains the following key-value pairs: +energy_behavior_name TEXT NOT NULL UNIQUE , +cooling_setpoint NUMERIC, +cooling_setpoint_units TEXT NOT NULL, +heating_setpoint NUMERIC, +heating_setpoint_units TEXT NOT NULL, +minimum_dimming_level NUMERIC, +annotation TEXT +""" + +CREATE_ENERGY_BEHAVIOR_TABLE = """ +CREATE TABLE IF NOT EXISTS support_occupant_energy_behavior ( + energy_behavior_name TEXT UNIQUE NOT NULL PRIMARY KEY, + cooling_setpoint NUMERIC, + cooling_setpoint_units TEXT NOT NULL, + heating_setpoint NUMERIC, + heating_setpoint_units TEXT NOT NULL, + minimum_dimming_level NUMERIC, + annotation TEXT +); +""" + +INSERT_ENERGY_BEHAVIOR = """ + INSERT INTO support_occupant_energy_behavior + (energy_behavior_name, + cooling_setpoint, + cooling_setpoint_units, + heating_setpoint, + heating_setpoint_units, + minimum_dimming_level,annotation) + VALUES (?, ?, ?, ?, ?, ?,?); +""" + +RECORD_TEMPLATE = { + "energy_behavior_name": "", + "cooling_setpoint": 0.0, + "cooling_setpoint_units": "", + "heating_setpoint": 0.0, + "heating_setpoint_units": "", + "minimum_dimming_level": 0.0, + "annotation": "", +} + + +class SupportEnergyBehaviorTable(DBOperation): + def __init__(self): + super(SupportEnergyBehaviorTable, self).__init__( + table_name="support_occupant_energy_behavior", + record_template=RECORD_TEMPLATE, + initial_data_directory=f"building_energy_standards_data/database_files/{TABLE_NAME}", + create_table_query=CREATE_ENERGY_BEHAVIOR_TABLE, + insert_record_query=INSERT_ENERGY_BEHAVIOR, + ) + + def get_record_info(self): + """ + A function to return the record info of the table + :return: + """ + return RECORD_HELP + + def validate_record_datatype(self, record): + str_expected = [ + "energy_behavior_name", + "cooling_setpoint_units", + "heating_setpoint_units", + ] + + for f in str_expected: + if record.get(f): + assert isinstance( + record[f], str + ), f"{f} requires to be a string, instead got {record[f]}" + + float_expected = [ + "cooling_setpoint", + "heating_setpoint", + "minimum_dimming_level", + ] + + for f in float_expected: + if record.get(f): + assert is_float( + record.get(f) + ), f"{f} requires to be numeric data type, instead got {record[f]}" + return True + + def _preprocess_record(self, record): + """ + + :param record: dict + :return: + """ + + return ( + getattr_either("energy_behavior_name", record), + getattr_either("cooling_setpoint", record), + getattr_either("cooling_setpoint_units", record), + getattr_either("heating_setpoint", record), + getattr_either("heating_setpoint_units", record), + getattr_either("minimum_dimming_level", record), + getattr_either("annotation", record), + ) diff --git a/building_energy_standards_data/database_tables/support_occupant_physical_characteristics.py b/building_energy_standards_data/database_tables/support_occupant_physical_characteristics.py new file mode 100644 index 0000000..d842dcb --- /dev/null +++ b/building_energy_standards_data/database_tables/support_occupant_physical_characteristics.py @@ -0,0 +1,115 @@ +from building_energy_standards_data.database_engine.database import DBOperation +from building_energy_standards_data.database_engine.database_util import ( + is_float, + getattr_either, +) + +TABLE_NAME = "support_occupant_physical_characteristics" + +RECORD_HELP = """ +Must provide a dict that contains following key value pairs: +physical_characteristic_name TEXT UNIQUE NOT NULL PRIMARY KEY, +schedule_activity_level TEXT NOT NULL, +schedule_clothing_insulation TEXT NOT NULL, +schedule_air_velocity TEXT NOT NULL, +work_efficiency NUMERIC, +co2_generation NUMERIC, +co2_generation_units TEXT, +annotation TEXT, +""" + +CREATE_PHYSICAL_CHAR_TABLE = """ +CREATE TABLE IF NOT EXISTS support_occupant_physical_characteristics ( + physical_characteristic_name TEXT UNIQUE NOT NULL PRIMARY KEY , + schedule_activity_level TEXT NOT NULL, + schedule_clothing_insulation TEXT NOT NULL, + schedule_air_velocity TEXT NOT NULL, + work_efficiency NUMERIC, + co2_generation NUMERIC, + co2_generation_units TEXT, + annotation TEXT +); +""" + +INSERT_PHYSICAL_CHAR = """ + INSERT INTO support_occupant_physical_characteristics + (physical_characteristic_name, + schedule_activity_level, + schedule_clothing_insulation, + schedule_air_velocity, + work_efficiency, + co2_generation, + co2_generation_units,annotation) + VALUES (?, ?, ?, ?, ?, ?, ?,?); +""" + +RECORD_TEMPLATE = { + "physical_characteristic_name": "", + "schedule_activity_level": "", + "schedule_clothing_insulation": "", + "schedule_air_velocity": "", + "work_efficiency": 0.0, + "co2_generation": 0.0, + "co2_generation_units": "", + "annotation": "", +} + + +class SupportPhysicalCharacteristicsTable(DBOperation): + def __init__(self): + super(SupportPhysicalCharacteristicsTable, self).__init__( + table_name=f"{TABLE_NAME}", + record_template=RECORD_TEMPLATE, + initial_data_directory=f"building_energy_standards_data/database_files/{TABLE_NAME}", + create_table_query=CREATE_PHYSICAL_CHAR_TABLE, + insert_record_query=INSERT_PHYSICAL_CHAR, + ) + + def get_record_info(self): + """ + A function to return the record info of the table + :return: + """ + return RECORD_HELP + + def validate_record_datatype(self, record): + str_expected = [ + "physical_characteristic_name", + "schedule_activity_level", + "schedule_clothing_insulation", + "schedule_air_velocity", + "co2_generation_units", + ] + + for f in str_expected: + if record.get(f): + assert isinstance( + record[f], str + ), f"{f} requires to be a string, instead got {record[f]}" + + float_expected = ["work_efficiency", "co2_generation"] + + for f in float_expected: + if record.get(f): + assert is_float( + record.get(f) + ), f"{f} requires to be numeric data type, instead got {record[f]}" + return True + + def _preprocess_record(self, record): + """ + + :param record: dict + :return: + """ + + return ( + getattr_either("physical_characteristic_name", record), + getattr_either("schedule_activity_level", record), + getattr_either("schedule_clothing_insulation", record), + getattr_either("schedule_air_velocity", record), + getattr_either("work_efficiency", record), + getattr_either("co2_generation", record), + getattr_either("co2_generation_units", record), + getattr_either("annotation", record), + ) diff --git a/building_energy_standards_data/database_tables/support_occupant_types.py b/building_energy_standards_data/database_tables/support_occupant_types.py new file mode 100644 index 0000000..27d7829 --- /dev/null +++ b/building_energy_standards_data/database_tables/support_occupant_types.py @@ -0,0 +1,81 @@ +from building_energy_standards_data.database_engine.database import DBOperation +from building_energy_standards_data.database_engine.database_util import ( + is_float, + getattr_either, +) + +TABLE_NAME = "support_occupant_types" + +RECORD_HELP = """ +Must provide a dict that contains following key value pairs: +name TEXT NOT NULL, +energy_behavior TEXT, +occupant_schedule TEXT, +occupant_physical_characteristics TEXT +""" + +CREATE_OCCUPANT_TYPE_TABLE = """ +CREATE TABLE IF NOT EXISTS support_occupant_types ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + energy_behavior TEXT NOT NULL, + occupant_schedule TEXT NOT NULL, + occupant_physical_characteristics TEXT NOT NULL, + FOREIGN KEY(energy_behavior) REFERENCES support_occupant_energy_behavior(energy_behavior_name), + FOREIGN KEY(occupant_physical_characteristics) REFERENCES support_occupant_physical_characteristics(physical_characteristic_name) +); +""" + + +INSERT_OCCUPANT_TYPE = """ + INSERT INTO support_occupant_types + (name, energy_behavior, + occupant_schedule, + occupant_physical_characteristics) + VALUES (?, ?, ?, ?); +""" + + +RECORD_TEMPLATE = { + "name": "", + "enrgy_behavior": "", + "occupant_schedule": "", + "occupant_physical_characteristics": "", +} + + +class SupportOccupantTypeTable(DBOperation): + def __init__(self): + super(SupportOccupantTypeTable, self).__init__( + table_name=TABLE_NAME, + record_template=RECORD_TEMPLATE, + initial_data_directory=f"building_energy_standards_data/database_files/{TABLE_NAME}", + create_table_query=CREATE_OCCUPANT_TYPE_TABLE, + insert_record_query=INSERT_OCCUPANT_TYPE, + ) + + def get_record_info(self): + return RECORD_HELP + + def validate_record_datatype(self, record): + str_expected = [ + "name" "energy_behavior", + "occupant_schedule", + "occupant_physical_characteristics", + ] + + for f in str_expected: + if record.get(f): + assert isinstance( + record[f], str + ), f"{f} requires to be a string, instead got {record[f]}" + + return True + + def _preprocess_record(self, record): + return ( + getattr_either("name", record), + getattr_either("energy_behavior", record), + getattr_either("occupant_schedule", record), + getattr_either("occupant_physical_characteristics", record), + ) diff --git a/docs/ATUS_schedule.drawio.png b/docs/ATUS_schedule.drawio.png new file mode 100644 index 0000000..6f0f6fb Binary files /dev/null and b/docs/ATUS_schedule.drawio.png differ diff --git a/docs/Design_OT_sql.drawio.png b/docs/Design_OT_sql.drawio.png new file mode 100644 index 0000000..bc5d7ac Binary files /dev/null and b/docs/Design_OT_sql.drawio.png differ diff --git a/docs/Structure.md b/docs/Structure.md index c9a7705..1007aad 100644 --- a/docs/Structure.md +++ b/docs/Structure.md @@ -26,4 +26,45 @@ The equipment assumptions are based on a plug-load values derived from a project ![Equipment Power Density Determination Using Plug-Load Data](plug_loads_methodology.png "Equipment Power Density Determination Using Plug-Load Data") #### Schedules -The schedules used in the database were determined based on the PNNL led *Development of Building-Space-Specific Loads for Performance Rating Methods* project. The schedules were derived from the [SBEM-NCN database](https://www.ncm-pcdb.org.uk/sap/page.jsp?id=7), modifications were applied to make them perceived as more realistic such as reducing the occupancy fraction during the day (as space is very rarely fully occupied), or leave a very small fraction of the lights on at night. \ No newline at end of file +The schedules used in the database were determined based on the PNNL led *Development of Building-Space-Specific Loads for Performance Rating Methods* project. The schedules were derived from the [SBEM-NCN database](https://www.ncm-pcdb.org.uk/sap/page.jsp?id=7), modifications were applied to make them perceived as more realistic such as reducing the occupancy fraction during the day (as space is very rarely fully occupied), or leave a very small fraction of the lights on at night. + +### Occupant Types Dataset +Different groups of occupants may exhibit varying behaviors influenced by factors such as the type of space, cultural background, and social context. The occupant types database is designed to caputure diverse behavioral patterns and create a representative dataset that enables users to improve the building energy modeling and advance research on dynamic occupant behavior. + +#### Occupant Types Data Structure +This database is insipried by a previous work led by Lawrence Berkeley National Laboratory (LBNL) [(Sun and Hong 2017)](https://www.sciencedirect.com/science/article/abs/pii/S0378778817302013), which established a framework categorizing occupant types into three primary categories: +- energy behavior (including actions related to thermostat and lighting), +- physical characteristics of occupants (including clothing insulation, work efficiency, CO2 generation, and air velocity), +- 24-hour occupant schedule. + +The structure of the occupant type database is illustrated in the following figure: +![Occupant schedule clustering](Design_OT_sql.drawio.png "Occupant schedule clustering") + +#### Energy behavior +The energy behavior is further divided into three categories: +- wasteful occupants prefer colder settings during cooling seasons and higher settings during heating seasons and never dim the lights in their space +- austerity occupants have the opposite preferences on thermostat settings and always dim the lights when daylight is sufficient +- and normal occupants behave in a typical manner. + +#### Physical Charateristics +For physical characteristics, the options that can be modified by the user include clothing insulation, work efficiency, CO2 generation rate, and air velocity. + +#### Occupancy Schedule +Occupancy density over 24 hours on weekdays and weekends is based on the analysis of the multiple years of the [American Time Use Survey](https://www.bls.gov/tus/). The clustering algorithm determined four optimal clusters: early birds, late owls, regular 8-hour workers, and night shift workers,the clustering result can be seen in following figure. Default values for each cluster are based on their respective ratios. + +![Occupant schedule clustering](ATUS_schedule.drawio.png "Occupant schedule clustering") + + +The specific details of each subcategory of design occupant types are summarized in the following table. It is worth noting that this database currently focuses on office buildings. + + +
Space Type | Occupant type subcategory | Reference | Notes |
Office | Occupant schedule | American Time Use Survey | Early birds, late owls, regular 8-hour workers, and night shift workers, and weekend schedule; Clustering algorithm used on office worker. |
Thermostat behavior | Learning occupants’ indoor comfort temperature through a Bayesian inference approach for office buildings in United States | A data-driven approach to learn thermal comfort preference in office buildings through ASHRAE Thermal Comfort Database. | |
Lighting behavior | Lighting preference profiles of users in an open office environment | Lighting preference profiles based on objective measurements and subjective data obtained in two field studies. | |
Clothing insulation | ASHRAE Handbook Fundamentals | Table 7 in Chapter 9 provides a reference for estimating the clothing insulation levels of occupants. | |
CO2 generation rate | ANSI/ASHRAE Standard 62.1-2017 | A default metabolic rate of 1 met is assumed. |