1
1
# Metamodel for Energy Things (MetamEnTh)
2
2
3
- ![ Build Status] ( https://github.com/peteryefi /metamenth/actions/workflows/build.yml/badge.svg )
3
+ ![ Build Status] ( https://github.com/ptidejteam /metamenth/actions/workflows/build.yml/badge.svg )
4
4
![ Version] ( https://img.shields.io/badge/version-1.0.0-blue )
5
- [ ![ License] ( https://img.shields.io/github/license/peteryefi /metamenth )] ( https://github.com/username/repository /blob/main/LICENSE )
5
+ [ ![ License] ( https://img.shields.io/github/license/ptidejteam /metamenth )] ( https://github.com/ptidejteam/metamenth /blob/main/LICENSE )
6
6
![ PyPI version] ( https://img.shields.io/pypi/v/metamenth.svg )
7
- [ ![ Wiki] ( https://img.shields.io/badge/docs-wiki-blue.svg )] ( https://github.com/peteryefi /metamenth/wiki )
7
+ [ ![ Wiki] ( https://img.shields.io/badge/docs-wiki-blue.svg )] ( https://github.com/ptidejteam /metamenth/wiki )
8
8
9
9
** MetamEnTh** is an object-oriented framework for modeling the operational aspects of buildings, with a focus on mechanical, electrical, and plumbing (MEP) entities. It allows users to model and interact with physical structures, such as rooms, floors, HVAC systems, and appliances, providing a detailed simulation of building components and energy systems.
10
10
11
- Read the documentation here: [ MetamEnTh Documentation] ( https://github.com/peteryefi /metamenth/wiki )
11
+ Read the documentation here: [ MetamEnTh Documentation] ( https://github.com/ptidejteam /metamenth/wiki )
12
12
13
13
## Table of Contents
14
14
1 . [ Setting up MetamEnTh Locally] ( #setting-up-metamEnTh-locally )
@@ -25,7 +25,7 @@ Read the documentation here: [MetamEnTh Documentation](https://github.com/petery
25
25
### Cloning the repository:
26
26
27
27
``` sh
28
- git clone https://github.com/peteryefi /metamenth.git
28
+ git clone https://github.com/ptidejteam /metamenth.git
29
29
cd metamenth
30
30
```
31
31
@@ -86,15 +86,18 @@ internal_mass = MeasureFactory.create_measure(RecordingType.BINARY.value,
86
86
area = MeasureFactory.create_measure(RecordingType.BINARY .value,
87
87
Measure(MeasurementUnit.SQUARE_METERS , 45 ))
88
88
# create room
89
- room = Room(area, " Office 1 " , RoomType.OFFICE )
89
+ room = Room(area, " Room " , RoomType.OFFICE )
90
90
91
- mechanical_room = Room(area, " MR 01 " , RoomType.MECHANICAL )
91
+ mechanical_room = Room(area, " Mechanical Room " , RoomType.MECHANICAL )
92
92
93
93
# create a hall
94
- hall = OpenSpace(" Dinning Hall" , area, OpenSpaceType.HALL )
94
+ hall = OpenSpace(" Hall" , area, OpenSpaceType.HALL )
95
+
96
+ # create a corridor
97
+ corridor = OpenSpace(" Corridor" , area, OpenSpaceType.CORRIDOR )
95
98
96
99
# create floor with a room and a hall
97
- floor = Floor(area = area, number = 1 , floor_type = FloorType.REGULAR , rooms = [room, hall, mechanical_room])
100
+ floor = Floor(area = area, number = 1 , floor_type = FloorType.REGULAR , rooms = [room, hall, corridor, mechanical_room])
98
101
99
102
# create the building's address
100
103
address = Address(" Montreal" , " 6399 Rue Sherbrooke" , " QC" , " H1N 2Z3" , " Canada" )
@@ -103,7 +106,7 @@ address = Address("Montreal", "6399 Rue Sherbrooke", "QC", "H1N 2Z3", "Canada")
103
106
building = Building(2009 , height, floor_area, internal_mass, address,
104
107
BuildingType.COMMERCIAL , [floor])
105
108
```
106
- ### 2. Adding an Envelope with Roof
109
+ ### 2. Adding an envelope with roof
107
110
``` python
108
111
from metamenth.structure.layer import Layer
109
112
from metamenth.structure.material import Material
@@ -157,22 +160,27 @@ envelope.add_cover(roof_cover)
157
160
building.envelope = envelope # building was created 1 above
158
161
```
159
162
160
- ### 3. Create and associate Zones to the hall
163
+ ### 3. Create and associate zones to the hall, corridor, room and office
161
164
``` python
162
165
from metamenth.enumerations import ZoneType
163
166
from metamenth.enumerations import HVACType
164
167
from metamenth.virtual.zone import Zone
165
168
166
- hvac_cooling_zone = Zone(" HVAC_COOLING_ZONE" , ZoneType.HVAC , HVACType.INTERIOR )
167
- hvac_heating_zone = Zone(" HVAC_HEATING_ZONE" , ZoneType.HVAC , HVACType.PERIMETER )
168
- # make the cooling zone adjacent to the heating zone
169
- hvac_heating_zone.add_adjacent_zones([hvac_cooling_zone])
169
+ hvac_zone_1 = Zone(" HVAC Zone 1" , ZoneType.HVAC , HVACType.INTERIOR )
170
+ hvac_zone_2 = Zone(" HVAC Zone 2" , ZoneType.HVAC , HVACType.INTERIOR )
171
+ # set adjacent zones
172
+ hvac_zone_2.add_adjacent_zones([hvac_zone_1])
173
+
174
+ # assign the mechanical room to hvac zone 1
175
+ mechanical_room.add_zone(hvac_zone_1, building) # building and mechanical room were created in 1 above
170
176
171
- # assign the zone to the room
172
- hall.add_zone(hvac_heating_zone, building) # building and hall were created in 1 above
177
+ # assign the hall, corridor and room to hvac zone 2
178
+ room.add_zone(hvac_zone_2, building)
179
+ corridor.add_zone(hvac_zone_2, building)
180
+ hall.add_zone(hvac_zone_2, building)
173
181
174
182
```
175
- ### 4. Create and assign thermostats to the hall
183
+ ### 4. Create and assign thermostat to the hall
176
184
``` python
177
185
from metamenth.transducers.sensor import Sensor
178
186
from metamenth.subsystem.appliance import Appliance
@@ -207,8 +215,219 @@ thermostat.add_transducer(humidity_sensor)
207
215
208
216
# add thermostat to the hall
209
217
hall.add_appliance(thermostat) # hall was created in 1 above
218
+ ```
219
+ #### 5. Create and assign sensors to the corridor, room and mechanical room
220
+ ``` python
221
+ from metamenth.transducers.sensor import Sensor
222
+ from metamenth.subsystem.appliance import Appliance
223
+ from metamenth.enumerations import ApplianceType
224
+ from metamenth.enumerations import ApplianceCategory
225
+ from metamenth.enumerations import SensorMeasureType
226
+ from metamenth.enumerations import SensorMeasure
227
+ from metamenth.enumerations import SensorLogType
228
+ from metamenth.datatypes.measure import Measure
229
+ from metamenth.enumerations import MeasurementUnit
230
+ from metamenth.misc import MeasureFactory
210
231
232
+ # room sensors
233
+ room_temp_sensor = Sensor(" ROOM.TEMP.SENSOR" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
234
+ SensorMeasureType.THERMO_COUPLE_TYPE_A , 900 , sensor_log_type = SensorLogType.POLLING )
235
+ room_co2_sensor = Sensor(" ROOM.CO2.SENSOR" , SensorMeasure.CARBON_DIOXIDE , MeasurementUnit.PARTS_PER_MILLION ,
236
+ SensorMeasureType.THERMO_COUPLE_TYPE_A , 900 , sensor_log_type = SensorLogType.POLLING )
237
+ room.add_transducer(room_co2_sensor)
238
+ room.add_transducer(room_temp_sensor)
239
+
240
+ # mechanical room sensors
241
+ mec_room_temp_sensor = Sensor(" MEC.ROOM.TEMP.SENSOR" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
242
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.CHANGE_OF_VALUE )
243
+ mec_room_humidity_sensor = Sensor(" MEC.ROOM.HDT.SENSOR" , SensorMeasure.HUMIDITY , MeasurementUnit.RELATIVE_HUMIDITY ,
244
+ SensorMeasureType.THERMO_COUPLE_TYPE_A , 900 , sensor_log_type = SensorLogType.POLLING )
245
+ mechanical_room.add_transducer(mec_room_humidity_sensor)
246
+ mechanical_room.add_transducer(mec_room_temp_sensor)
247
+
248
+ # add smoke detector to mechanical room
249
+ temp_op_condition = MeasureFactory.create_measure(" Continuous" ,
250
+ Measure(MeasurementUnit.DEGREE_CELSIUS , 0 , 38 ))
251
+ humidity_op_condition = MeasureFactory.create_measure(" Continuous" ,
252
+ Measure(MeasurementUnit.RELATIVE_HUMIDITY , 0 , 95 ))
253
+ smoke_detector = Appliance(" SMK.DETECTOR" , [ApplianceCategory.HOME , ApplianceCategory.SMART ],
254
+ ApplianceType.SMOKE_DETECTOR ,
255
+ operating_conditions = [temp_op_condition, humidity_op_condition])
256
+ mechanical_room.add_appliance(smoke_detector)
257
+
258
+ # corridor sensors
259
+ corr_room_temp_sensor = Sensor(" CORR.ROOM.TEMP.SENSOR" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
260
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.CHANGE_OF_VALUE )
261
+ corridor.add_transducer(corr_room_temp_sensor)
211
262
```
263
+ #### 6. Create and add the fan coil unit, baseboard heater, chiller and boiler
264
+ ``` python
265
+ from metamenth.subsystem.hvac_components.fan_coil_unit import FanCoilUnit
266
+ from metamenth.subsystem.hvac_components.heat_exchanger import HeatExchanger
267
+ from metamenth.subsystem.hvac_components.chiller import Chiller
268
+ from metamenth.subsystem.hvac_components.boiler import Boiler
269
+ from metamenth.subsystem.hvac_components.fan import Fan
270
+ from metamenth.enumerations import ChillerType, BoilerCategory, FCUType, FCUPipeSystem, PowerState
271
+ from metamenth.enumerations import HeatingType, HeatExchangerType, HeatExchangerFlowType
272
+ from metamenth.subsystem.baseboard_heater import BaseboardHeater
273
+ from metamenth.subsystem.hvac_components.variable_frequency_drive import VariableFrequencyDrive
274
+
275
+ # create boiler and chiller and add them to mechanical room
276
+ boiler = Boiler(' MEC.BOILER' , BoilerCategory.NATURAL_GAS , PowerState.ON )
277
+ chiller = Chiller(' MEC.CHILLER' , ChillerType.WATER_COOLED , PowerState.ON )
278
+ mechanical_room.add_hvac_component(boiler)
279
+ mechanical_room.add_hvac_component(chiller)
280
+
281
+ # create baseboard heater add it to the corridor
282
+ baseboard_heater = BaseboardHeater(' CORR.BS.HEATER' , HeatingType.ELECTRIC , PowerState.OUT_OF_SERVICE )
283
+ corridor.add_hvac_component(baseboard_heater)
284
+
285
+ # create fan coil unit and add it to the hall
286
+ vfd = VariableFrequencyDrive(' VFD' )
287
+ fan = Fan(" FCU.FAN" , PowerState.ON , vfd)
288
+ heat_exchanger = HeatExchanger(" FCU.HT.EXG" , HeatExchangerType.FIN_TUBE , HeatExchangerFlowType.PARALLEL )
289
+ fcu = FanCoilUnit(' HALL.FCU' , heat_exchanger, fan, FCUType.STANDALONE , FCUPipeSystem.TWO_PIPE , False )
290
+ hall.add_hvac_component(fcu)
291
+ ```
292
+ #### 7. Create an HVAC system for the building
293
+ ``` python
294
+ from metamenth.subsystem.building_control_system import BuildingControlSystem
295
+ from metamenth.subsystem.hvac_system import HVACSystem
296
+ from metamenth.subsystem.hvac_components.duct import Duct
297
+ from metamenth.enumerations import DuctType, DuctSubType
298
+ from metamenth.subsystem.hvac_components.duct_connection import DuctConnection
299
+ from metamenth.enumerations import DuctConnectionEntityType, VentilationType
300
+ from metamenth.subsystem.ventilation_system import VentilationSystem
301
+
302
+ bcs = BuildingControlSystem(" EV Control System" )
303
+ hvac_system = HVACSystem()
304
+ bcs.hvac_system = hvac_system
305
+
306
+ # Create the fresh air duct for the ventilation system
307
+ supply_air_duct = Duct(" SUPP.VNT.01" , DuctType.AIR )
308
+ supply_air_duct.duct_sub_type = DuctSubType.FRESH_AIR
309
+
310
+ # create the return air duct for the ventilation system
311
+ return_air_duct = Duct(" RET.VNT.01" , DuctType.AIR )
312
+ return_air_duct.duct_sub_type = DuctSubType.RETURN_AIR
313
+
314
+ # create the recirculation air duct
315
+ recirculation_air_duct = Duct(" REC.VNT.01" , DuctType.AIR )
316
+ recirculation_air_duct.duct_sub_type = DuctSubType.RETURN_AIR
317
+
318
+ # connect the fresh air, return air and recirculation air ducts
319
+ duct2duct_conn = DuctConnection()
320
+ # add the return air duct as the source of the connection
321
+ duct2duct_conn.add_entity(DuctConnectionEntityType.SOURCE , return_air_duct)
322
+ # add the fresh air duct as the destination of the connection
323
+ duct2duct_conn.add_entity(DuctConnectionEntityType.DESTINATION , supply_air_duct)
324
+ # set the connection object as a property of the recirculation air duct
325
+ recirculation_air_duct.connections = duct2duct_conn
326
+
327
+ # set the recirculation air duct as the source for the supply air duct
328
+ supp_duct_conn = DuctConnection()
329
+ supp_duct_conn.add_entity(DuctConnectionEntityType.SOURCE , recirculation_air_duct)
330
+ supply_air_duct.connections = duct2duct_conn
331
+
332
+ # create the ventilation system with the supply air duct as the principal duct
333
+ ventilation_system = VentilationSystem(VentilationType.AIR_HANDLING_UNIT , supply_air_duct)
334
+
335
+ # set the ventilation system for the HVAC system
336
+ hvac_system.add_ventilation_system(ventilation_system)
337
+ ```
338
+ #### 8. Supply air duct components
339
+ ``` python
340
+ from metamenth.transducers.sensor import Sensor
341
+ from metamenth.enumerations import SensorMeasureType
342
+ from metamenth.enumerations import SensorMeasure
343
+ from metamenth.enumerations import SensorLogType
344
+ from metamenth.enumerations import MeasurementUnit
345
+ from metamenth.subsystem.hvac_components.damper import Damper
346
+ from metamenth.subsystem.hvac_components.filter import Filter
347
+ from metamenth.enumerations import DamperType, FilterType
348
+ from metamenth.subsystem.hvac_components.fan import Fan
349
+ from metamenth.subsystem.hvac_components.variable_frequency_drive import VariableFrequencyDrive
350
+ from metamenth.subsystem.hvac_components.duct import Duct
351
+ from metamenth.subsystem.hvac_components.duct_connection import DuctConnection
352
+ from metamenth.enumerations import DuctConnectionEntityType, HeatExchangerType, HeatExchangerFlowType, DuctType, DuctSubType
353
+ from metamenth.subsystem.hvac_components.heat_exchanger import HeatExchanger
354
+ from metamenth.subsystem.hvac_components.air_volume_box import AirVolumeBox
355
+ from metamenth.enumerations import AirVolumeType
356
+
357
+ # create the four temperature sensors and one pressure sensor for the supply air duct
358
+ supp_vnt_temp_sensor_1 = Sensor(" SUPP.VNT.TEMP.SENSOR.1" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
359
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.POLLING )
360
+ supp_vnt_temp_sensor_2 = Sensor(" SUPP.VNT.TEMP.SENSOR.2" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
361
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.POLLING )
362
+ supp_vnt_temp_sensor_3 = Sensor(" SUPP.VNT.TEMP.SENSOR.3" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
363
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.POLLING )
364
+ supp_vnt_temp_sensor_4 = Sensor(" SUPP.VNT.TEMP.SENSOR.4" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
365
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.POLLING )
366
+ supp_vnt_pressure_sensor = Sensor(" SUPP.VNT.PRS.SENSOR" , SensorMeasure.PRESSURE , MeasurementUnit.PASCAL ,
367
+ SensorMeasureType.THERMO_COUPLE_TYPE_B , 900 , sensor_log_type = SensorLogType.POLLING )
368
+ supply_air_duct.add_transducer(supp_vnt_temp_sensor_1) # supply_air_duct was created in Section 7
369
+ supply_air_duct.add_transducer(supp_vnt_temp_sensor_2)
370
+ supply_air_duct.add_transducer(supp_vnt_temp_sensor_3)
371
+ supply_air_duct.add_transducer(supp_vnt_temp_sensor_4)
372
+ supply_air_duct.add_transducer(supp_vnt_pressure_sensor)
373
+
374
+ # create and add the damper and filter to the supply air duct
375
+ damper = Damper(" SUPP.VNT.DP" , DamperType.BACK_DRAFT )
376
+ filter = Filter(" SUPP.VNT.FLT" , FilterType.ELECTROSTATIC )
377
+ supply_air_duct.add_filter(filter )
378
+ supply_air_duct.add_damper(damper)
379
+
380
+ # add fan to the supply air duct
381
+ vfd = VariableFrequencyDrive(' VFD' )
382
+ fan = Fan(" SUPP.VNT.FAN" , PowerState.ON , vfd)
383
+ supply_air_duct.add_fan(fan)
384
+
385
+ # add the two heat exchangers
386
+ heat_exchanger_1 = HeatExchanger(" SUPP.VNT.HT.EXG.1" , HeatExchangerType.FIN_TUBE , HeatExchangerFlowType.PARALLEL )
387
+ heat_exchanger_2 = HeatExchanger(" SUPP.VNT.HT.EXG.2" , HeatExchangerType.FIN_TUBE , HeatExchangerFlowType.PARALLEL )
388
+ supply_air_duct.add_heat_exchanger(heat_exchanger_1)
389
+ supply_air_duct.add_heat_exchanger(heat_exchanger_2)
390
+
391
+ # connect heat exchanger 1 to the boiler
392
+ heat_exchanger_boiler_pipe = Duct(" HXG.BLR.PIPE" , DuctType.WATER )
393
+ heat_exchanger_boiler_pipe.duct_sub_type = DuctSubType.HOT_AND_COLD_WATER
394
+
395
+ heat_exchanger_boiler_conn = DuctConnection()
396
+ heat_exchanger_boiler_conn.add_entity(DuctConnectionEntityType.SOURCE , heat_exchanger_1)
397
+ heat_exchanger_boiler_conn.add_entity(DuctConnectionEntityType.DESTINATION , boiler) # boiler was created in Section 6
398
+ heat_exchanger_boiler_conn.is_loop = True # source can become destination and vice versa
399
+ heat_exchanger_boiler_pipe.connections = heat_exchanger_boiler_conn
400
+ heat_exchanger_1.add_duct(heat_exchanger_boiler_pipe)
401
+
402
+ # connect heat exchanger 2 to the chiller
403
+ heat_exchanger_chiller_pipe = Duct(" HXG.CHL.PIP" , DuctType.WATER_WITH_ANTI_FREEZE )
404
+ heat_exchanger_chiller_conn = DuctConnection()
405
+ heat_exchanger_boiler_conn.add_entity(DuctConnectionEntityType.SOURCE , heat_exchanger_2)
406
+ heat_exchanger_boiler_conn.add_entity(DuctConnectionEntityType.DESTINATION , chiller) # chiller was created in Section 6
407
+ heat_exchanger_boiler_conn.is_loop = True # source can become destination and vice versa
408
+ heat_exchanger_chiller_pipe.connections = heat_exchanger_chiller_conn
409
+ heat_exchanger_2.add_duct(heat_exchanger_chiller_pipe)
410
+
411
+ # create the two VAV boxes for the supply air duct
412
+ vav_box_1 = AirVolumeBox(' SUPP.VNT.VAV.1' , AirVolumeType.VARIABLE_AIR_VOLUME )
413
+ vav_box_1.inlet_dampers = [Damper(' SUP.VNT.VAV.DMP.1' , DamperType.MANUAL_VOLUME )]
414
+ vav_box_1_temp_sensor = Sensor(" VAV.1.TEMP.SENSOR" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
415
+ SensorMeasureType.THERMO_COUPLE_TYPE_A , 900 , sensor_log_type = SensorLogType.POLLING )
416
+ vav_box_1.add_transducer(vav_box_1_temp_sensor)
417
+ supply_air_duct.add_connected_air_volume_box(vav_box_1)
212
418
419
+ vav_box_2 = AirVolumeBox(' SUPP.VNT.VAV.2' , AirVolumeType.VARIABLE_AIR_VOLUME )
420
+ vav_box_2.inlet_dampers = [Damper(' SUP.VNT.VAV.DMP.2' , DamperType.MANUAL_VOLUME )]
421
+ vav_box_2_temp_sensor = Sensor(" VAV.2.TEMP.SENSOR" , SensorMeasure.TEMPERATURE , MeasurementUnit.DEGREE_CELSIUS ,
422
+ SensorMeasureType.THERMO_COUPLE_TYPE_A , 900 , sensor_log_type = SensorLogType.POLLING )
423
+ vav_box_2.add_transducer(vav_box_2_temp_sensor)
424
+ supply_air_duct.add_connected_air_volume_box(vav_box_2)
425
+
426
+ # add the mechanical room to vav box 2 (the vav box suppliers air to that room)
427
+ vav_box_2.add_spaces([mechanical_room])
428
+
429
+ # add the corridor, hall and room to vav box 1
430
+ vav_box_1.add_spaces([room, corridor, hall])
431
+ ```
213
432
214
- NB: Refer to the [ test directory] ( https://github.com/peteryefi /metamenth/tree/main/tests ) for more insight on usage
433
+ NB: Refer to the [ test directory] ( https://github.com/ptidejteam /metamenth/tree/main/tests ) for more insight on usage
0 commit comments