mabuseif commited on
Commit
93f9be7
·
verified ·
1 Parent(s): 1aba450

Update data/reference_data.py

Browse files
Files changed (1) hide show
  1. data/reference_data.py +263 -429
data/reference_data.py CHANGED
@@ -7,16 +7,51 @@ from typing import Dict, List, Any, Optional
7
  import pandas as pd
8
  import json
9
  import os
 
 
 
 
 
 
10
 
11
  # Define paths
12
  DATA_DIR = os.path.dirname(os.path.abspath(__file__))
 
13
 
14
 
15
  class ReferenceData:
16
  """Class for managing reference data for the HVAC calculator."""
17
-
18
  def __init__(self):
19
  """Initialize reference data structures."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  self.materials = self._load_materials()
21
  self.wall_types = self._load_wall_types()
22
  self.roof_types = self._load_roof_types()
@@ -24,590 +59,389 @@ class ReferenceData:
24
  self.window_types = self._load_window_types()
25
  self.door_types = self._load_door_types()
26
  self.internal_loads = self._load_internal_loads()
27
-
28
  def _load_materials(self) -> Dict[str, Dict[str, Any]]:
29
  """
30
- Load material properties from reference data.
31
-
32
  Returns:
33
  Dictionary of material properties
34
  """
35
- # This would typically load from a JSON or CSV file
36
- # For now, we'll define some common materials inline
37
  return {
38
  "brick": {
 
39
  "name": "Common Brick",
40
  "conductivity": 0.72, # W/(m·K)
41
  "density": 1920, # kg/m³
42
  "specific_heat": 840, # J/(kg·K)
43
- "typical_thickness": 0.1 # m
 
 
44
  },
45
  "concrete": {
 
46
  "name": "Concrete",
47
  "conductivity": 1.4, # W/(m·K)
48
  "density": 2300, # kg/m³
49
  "specific_heat": 880, # J/(kg·K)
50
- "typical_thickness": 0.2 # m
 
 
51
  },
52
  "mineral_wool": {
 
53
  "name": "Mineral Wool Insulation",
54
  "conductivity": 0.04, # W/(m·K)
55
  "density": 30, # kg/m³
56
  "specific_heat": 840, # J/(kg·K)
57
- "typical_thickness": 0.1 # m
58
- },
59
- "eps_insulation": {
60
- "name": "EPS Insulation",
61
- "conductivity": 0.035, # W/(m·K)
62
- "density": 25, # kg/m³
63
- "specific_heat": 1400, # J/(kg·K)
64
- "typical_thickness": 0.1 # m
65
  },
66
- "gypsum_board": {
67
- "name": "Gypsum Board",
68
- "conductivity": 0.25, # W/(m·K)
69
- "density": 900, # kg/m³
70
- "specific_heat": 1000, # J/(kg·K)
71
- "typical_thickness": 0.0125 # m
 
 
 
 
72
  },
73
- "wood": {
74
- "name": "Wood (Pine)",
75
- "conductivity": 0.14, # W/(m·K)
76
- "density": 500, # kg/m³
77
- "specific_heat": 1600, # J/(kg·K)
78
- "typical_thickness": 0.025 # m
 
 
 
79
  },
80
- "steel": {
81
- "name": "Steel",
82
- "conductivity": 50, # W/(m·K)
83
- "density": 7800, # kg/m³
84
- "specific_heat": 450, # J/(kg·K)
85
- "typical_thickness": 0.005 # m
86
- },
87
- "glass": {
88
- "name": "Glass",
89
- "conductivity": 1.0, # W/(m·K)
90
- "density": 2500, # kg/m³
91
- "specific_heat": 840, # J/(kg·K)
92
- "typical_thickness": 0.006 # m
93
- },
94
- "air_gap": {
95
- "name": "Air Gap",
96
- "conductivity": 0.024, # W/(m·K)
97
- "density": 1.2, # kg/m³
98
- "specific_heat": 1000, # J/(kg·K)
99
- "typical_thickness": 0.025 # m
100
- },
101
- "concrete_block": {
102
- "name": "Concrete Block",
103
- "conductivity": 0.51, # W/(m·K)
104
- "density": 1400, # kg/m³
105
- "specific_heat": 1000, # J/(kg·K)
106
- "typical_thickness": 0.2 # m
107
- },
108
- "asphalt_shingle": {
109
- "name": "Asphalt Shingle",
110
  "conductivity": 0.7, # W/(m·K)
111
- "density": 1100, # kg/m³
112
- "specific_heat": 1260, # J/(kg·K)
113
- "typical_thickness": 0.006 # m
114
- },
115
- "carpet": {
116
- "name": "Carpet",
117
- "conductivity": 0.06, # W/(m·K)
118
- "density": 200, # kg/m³
119
- "specific_heat": 1300, # J/(kg·K)
120
- "typical_thickness": 0.01 # m
121
- },
122
- "vinyl_flooring": {
123
- "name": "Vinyl Flooring",
124
- "conductivity": 0.17, # W/(m·K)
125
- "density": 1200, # kg/m³
126
- "specific_heat": 1460, # J/(kg·K)
127
- "typical_thickness": 0.003 # m
128
  }
 
129
  }
130
-
131
  def _load_wall_types(self) -> Dict[str, Dict[str, Any]]:
132
  """
133
- Load predefined wall types from reference data.
134
-
135
  Returns:
136
  Dictionary of wall types with properties
137
  """
138
  return {
139
  "brick_veneer_wood_frame": {
140
- "name": "Brick veneer with wood frame",
 
141
  "description": "Brick veneer with wood frame, insulation, and gypsum board",
142
  "u_value": 0.35, # W/(m²·K)
143
- "wall_group": "B", # ASHRAE wall group
144
  "layers": [
145
  {"material": "brick", "thickness": 0.1},
146
  {"material": "air_gap", "thickness": 0.025},
147
  {"material": "wood", "thickness": 0.038},
148
  {"material": "mineral_wool", "thickness": 0.089},
149
  {"material": "gypsum_board", "thickness": 0.0125}
150
- ]
 
 
151
  },
152
- "concrete_block_insulated": {
153
- "name": "Concrete block with interior insulation",
154
- "description": "Concrete block wall with interior insulation and gypsum board",
155
- "u_value": 0.48, # W/(m²·K)
156
- "wall_group": "C", # ASHRAE wall group
 
157
  "layers": [
158
- {"material": "concrete_block", "thickness": 0.2},
 
159
  {"material": "eps_insulation", "thickness": 0.05},
160
  {"material": "gypsum_board", "thickness": 0.0125}
161
- ]
162
- },
163
- "precast_concrete_panel": {
164
- "name": "Precast concrete panel",
165
- "description": "Precast concrete panel with insulation and gypsum board",
166
- "u_value": 0.45, # W/(m²·K)
167
- "wall_group": "D", # ASHRAE wall group
168
- "layers": [
169
- {"material": "concrete", "thickness": 0.1},
170
- {"material": "eps_insulation", "thickness": 0.075},
171
- {"material": "gypsum_board", "thickness": 0.0125}
172
- ]
173
- },
174
- "metal_panel_insulated": {
175
- "name": "Metal panel with insulation",
176
- "description": "Metal panel wall with insulation and interior finish",
177
- "u_value": 0.4, # W/(m²·K)
178
- "wall_group": "E", # ASHRAE wall group
179
- "layers": [
180
- {"material": "steel", "thickness": 0.001},
181
- {"material": "mineral_wool", "thickness": 0.1},
182
- {"material": "gypsum_board", "thickness": 0.0125}
183
- ]
184
  },
185
- "wood_frame_wall": {
186
- "name": "Wood frame wall",
187
- "description": "Wood frame wall with insulation and gypsum board",
188
- "u_value": 0.3, # W/(m²·K)
189
- "wall_group": "A", # ASHRAE wall group
 
 
190
  "layers": [
191
- {"material": "wood", "thickness": 0.019},
192
- {"material": "air_gap", "thickness": 0.025},
193
- {"material": "wood", "thickness": 0.038},
194
- {"material": "mineral_wool", "thickness": 0.14},
195
  {"material": "gypsum_board", "thickness": 0.0125}
196
- ]
 
 
197
  }
198
  }
199
-
200
  def _load_roof_types(self) -> Dict[str, Dict[str, Any]]:
201
  """
202
- Load predefined roof types from reference data.
203
-
204
  Returns:
205
  Dictionary of roof types with properties
206
  """
207
  return {
208
  "flat_roof_concrete": {
209
- "name": "Flat concrete roof with insulation",
 
210
  "description": "Flat concrete roof with insulation and ceiling",
211
  "u_value": 0.25, # W/(m²·K)
212
- "roof_group": "B", # ASHRAE roof group
213
  "layers": [
214
  {"material": "concrete", "thickness": 0.15},
215
  {"material": "eps_insulation", "thickness": 0.15},
216
  {"material": "gypsum_board", "thickness": 0.0125}
217
- ]
 
 
218
  },
219
- "pitched_roof_wood": {
220
- "name": "Pitched wood roof with insulation",
221
- "description": "Pitched wood roof with insulation and ceiling",
222
- "u_value": 0.2, # W/(m²·K)
223
- "roof_group": "A", # ASHRAE roof group
224
- "layers": [
225
- {"material": "asphalt_shingle", "thickness": 0.006},
226
- {"material": "wood", "thickness": 0.019},
227
- {"material": "air_gap", "thickness": 0.025},
228
- {"material": "mineral_wool", "thickness": 0.2},
229
- {"material": "gypsum_board", "thickness": 0.0125}
230
- ]
231
- },
232
- "metal_deck_roof": {
233
- "name": "Metal deck roof with insulation",
234
- "description": "Metal deck roof with insulation and ceiling",
235
- "u_value": 0.3, # W/(m²·K)
236
- "roof_group": "C", # ASHRAE roof group
237
  "layers": [
238
- {"material": "steel", "thickness": 0.001},
239
  {"material": "eps_insulation", "thickness": 0.1},
240
- {"material": "air_gap", "thickness": 0.1},
241
  {"material": "gypsum_board", "thickness": 0.0125}
242
- ]
 
 
243
  }
244
  }
245
-
246
  def _load_floor_types(self) -> Dict[str, Dict[str, Any]]:
247
  """
248
- Load predefined floor types from reference data.
249
-
250
  Returns:
251
  Dictionary of floor types with properties
252
  """
253
  return {
254
  "concrete_slab_on_grade": {
255
- "name": "Concrete slab on grade",
 
256
  "description": "Concrete slab on grade with insulation",
257
  "u_value": 0.3, # W/(m²·K)
258
  "is_ground_contact": True,
259
  "layers": [
260
  {"material": "concrete", "thickness": 0.1},
261
  {"material": "eps_insulation", "thickness": 0.05}
262
- ]
263
- },
264
- "suspended_concrete_floor": {
265
- "name": "Suspended concrete floor",
266
- "description": "Suspended concrete floor with insulation",
267
- "u_value": 0.25, # W/(m²·K)
268
- "is_ground_contact": False,
269
- "layers": [
270
- {"material": "concrete", "thickness": 0.15},
271
- {"material": "eps_insulation", "thickness": 0.1},
272
- {"material": "gypsum_board", "thickness": 0.0125}
273
- ]
274
  },
275
- "wood_joist_floor": {
276
- "name": "Wood joist floor",
277
- "description": "Wood joist floor with insulation",
278
- "u_value": 0.22, # W/(m²·K)
279
- "is_ground_contact": False,
280
- "layers": [
281
- {"material": "wood", "thickness": 0.025},
282
- {"material": "air_gap", "thickness": 0.15},
283
- {"material": "mineral_wool", "thickness": 0.15},
284
- {"material": "gypsum_board", "thickness": 0.0125}
285
- ]
286
- },
287
- "carpet_on_concrete": {
288
- "name": "Carpet on concrete",
289
- "description": "Carpet on concrete slab with insulation",
290
- "u_value": 0.28, # W/(m²·K)
291
  "is_ground_contact": True,
292
  "layers": [
293
- {"material": "carpet", "thickness": 0.01},
294
  {"material": "concrete", "thickness": 0.1},
295
- {"material": "eps_insulation", "thickness": 0.05}
296
- ]
 
297
  }
298
  }
299
-
300
  def _load_window_types(self) -> Dict[str, Dict[str, Any]]:
301
  """
302
- Load predefined window types from reference data.
303
-
304
  Returns:
305
  Dictionary of window types with properties
306
  """
307
  return {
308
- "single_glazed": {
309
- "name": "Single glazed window",
310
- "description": "Single glazed window with aluminum frame",
311
- "u_value": 5.8, # W/(m²·K)
312
- "shgc": 0.86, # Solar Heat Gain Coefficient
313
- "vt": 0.9, # Visible Transmittance
314
- "glazing_layers": 1,
315
- "gas_fill": "Air",
316
- "frame_type": "Aluminum",
317
- "low_e_coating": False
318
- },
319
- "double_glazed_air": {
320
- "name": "Double glazed window with air",
321
- "description": "Double glazed window with air gap and aluminum frame",
322
- "u_value": 2.8, # W/(m²·K)
323
- "shgc": 0.76, # Solar Heat Gain Coefficient
324
- "vt": 0.81, # Visible Transmittance
325
- "glazing_layers": 2,
326
- "gas_fill": "Air",
327
- "frame_type": "Aluminum",
328
- "low_e_coating": False
329
- },
330
  "double_glazed_argon_low_e": {
331
- "name": "Double glazed window with argon and low-e coating",
 
332
  "description": "Double glazed window with argon fill, low-e coating, and vinyl frame",
333
  "u_value": 1.4, # W/(m²·K)
334
- "shgc": 0.4, # Solar Heat Gain Coefficient
335
- "vt": 0.7, # Visible Transmittance
336
  "glazing_layers": 2,
337
  "gas_fill": "Argon",
338
  "frame_type": "Vinyl",
339
- "low_e_coating": True
 
340
  },
341
- "triple_glazed_argon_low_e": {
342
- "name": "Triple glazed window with argon and low-e coating",
343
- "description": "Triple glazed window with argon fill, low-e coating, and vinyl frame",
344
- "u_value": 0.8, # W/(m²·K)
345
- "shgc": 0.3, # Solar Heat Gain Coefficient
346
- "vt": 0.6, # Visible Transmittance
347
- "glazing_layers": 3,
 
348
  "gas_fill": "Argon",
349
- "frame_type": "Vinyl",
350
- "low_e_coating": True
 
351
  }
352
  }
353
-
354
  def _load_door_types(self) -> Dict[str, Dict[str, Any]]:
355
  """
356
- Load predefined door types from reference data.
357
-
358
  Returns:
359
  Dictionary of door types with properties
360
  """
361
  return {
362
- "solid_wood_door": {
363
- "name": "Solid wood door",
364
- "description": "Solid wood door with no glazing",
365
- "u_value": 2.2, # W/(m²·K)
366
- "glazing_percentage": 0,
367
- "door_type": "Solid"
368
- },
369
  "insulated_steel_door": {
370
- "name": "Insulated steel door",
 
371
  "description": "Insulated steel door with no glazing",
372
  "u_value": 1.2, # W/(m²·K)
373
  "glazing_percentage": 0,
374
- "door_type": "Solid"
 
375
  },
376
- "partially_glazed_door": {
377
- "name": "Partially glazed door",
378
- "description": "Wood door with 25% glazing",
379
- "u_value": 2.8, # W/(m²·K)
380
- "glazing_percentage": 25,
 
381
  "door_type": "Partially glazed",
382
- "shgc": 0.76, # Solar Heat Gain Coefficient for the glazed portion
383
- "vt": 0.81 # Visible Transmittance for the glazed portion
384
- },
385
- "glass_door": {
386
- "name": "Glass door",
387
- "description": "Full glass door with aluminum frame",
388
- "u_value": 3.8, # W/(m²·K)
389
- "glazing_percentage": 90,
390
- "door_type": "Glass",
391
- "shgc": 0.76, # Solar Heat Gain Coefficient
392
- "vt": 0.81 # Visible Transmittance
393
  }
394
  }
395
-
396
  def _load_internal_loads(self) -> Dict[str, Dict[str, Any]]:
397
  """
398
- Load internal load data from reference data.
399
-
400
  Returns:
401
  Dictionary of internal load types with properties
402
  """
403
  return {
404
  "occupancy": {
405
- "seated_very_light_work": {
406
- "name": "Seated, very light work",
407
- "sensible_heat": 70, # W per person
408
- "latent_heat": 45 # W per person
409
- },
410
- "office_work_standing": {
411
- "name": "Office work, standing",
412
  "sensible_heat": 75, # W per person
413
- "latent_heat": 55 # W per person
 
414
  },
415
- "light_physical_work": {
416
- "name": "Light physical work",
 
417
  "sensible_heat": 80, # W per person
418
- "latent_heat": 140 # W per person
419
- },
420
- "medium_physical_work": {
421
- "name": "Medium physical work",
422
- "sensible_heat": 90, # W per person
423
- "latent_heat": 185 # W per person
424
- },
425
- "heavy_physical_work": {
426
- "name": "Heavy physical work",
427
- "sensible_heat": 170, # W per person
428
- "latent_heat": 255 # W per person
429
  }
430
  },
431
  "lighting": {
432
- "led": {
433
- "name": "LED",
434
- "power_density_range": [5, 10], # W/m²
435
- "heat_to_space": 0.9 # Fraction of power that becomes heat
436
- },
437
- "fluorescent": {
438
- "name": "Fluorescent",
439
- "power_density_range": [10, 15], # W/m²
440
- "heat_to_space": 0.95 # Fraction of power that becomes heat
441
- },
442
- "incandescent": {
443
- "name": "Incandescent",
444
- "power_density_range": [15, 25], # W/m²
445
- "heat_to_space": 0.98 # Fraction of power that becomes heat
446
- },
447
- "halogen": {
448
- "name": "Halogen",
449
- "power_density_range": [12, 20], # W/m²
450
- "heat_to_space": 0.97 # Fraction of power that becomes heat
451
  }
452
  },
453
  "equipment": {
454
- "office_equipment": {
455
- "name": "Office Equipment",
456
- "power_density_range": [10, 20], # W/m²
457
- "sensible_fraction": 0.9,
458
- "latent_fraction": 0.1
459
- },
460
- "kitchen_equipment": {
461
- "name": "Kitchen Equipment",
462
- "power_density_range": [30, 200], # W/m²
463
- "sensible_fraction": 0.6,
464
- "latent_fraction": 0.4
465
- },
466
- "manufacturing_equipment": {
467
- "name": "Manufacturing Equipment",
468
- "power_density_range": [20, 100], # W/m²
469
- "sensible_fraction": 0.8,
470
- "latent_fraction": 0.2
471
  }
472
  }
473
  }
474
-
475
- def get_material(self, material_id: str) -> Optional[Dict[str, Any]]:
476
  """
477
- Get material properties by ID.
478
-
479
  Args:
480
- material_id: Material identifier
481
-
482
- Returns:
483
- Dictionary of material properties or None if not found
484
- """
485
- return self.materials.get(material_id)
486
-
487
- def get_wall_type(self, wall_type_id: str) -> Optional[Dict[str, Any]]:
 
 
 
 
 
 
 
 
 
 
488
  """
489
- Get wall type properties by ID.
490
-
491
  Args:
492
- wall_type_id: Wall type identifier
493
-
494
- Returns:
495
- Dictionary of wall type properties or None if not found
496
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
497
  return self.wall_types.get(wall_type_id)
498
-
499
  def get_roof_type(self, roof_type_id: str) -> Optional[Dict[str, Any]]:
500
- """
501
- Get roof type properties by ID.
502
-
503
- Args:
504
- roof_type_id: Roof type identifier
505
-
506
- Returns:
507
- Dictionary of roof type properties or None if not found
508
- """
509
  return self.roof_types.get(roof_type_id)
510
-
511
  def get_floor_type(self, floor_type_id: str) -> Optional[Dict[str, Any]]:
512
- """
513
- Get floor type properties by ID.
514
-
515
- Args:
516
- floor_type_id: Floor type identifier
517
-
518
- Returns:
519
- Dictionary of floor type properties or None if not found
520
- """
521
  return self.floor_types.get(floor_type_id)
522
-
523
  def get_window_type(self, window_type_id: str) -> Optional[Dict[str, Any]]:
524
- """
525
- Get window type properties by ID.
526
-
527
- Args:
528
- window_type_id: Window type identifier
529
-
530
- Returns:
531
- Dictionary of window type properties or None if not found
532
- """
533
  return self.window_types.get(window_type_id)
534
-
535
  def get_door_type(self, door_type_id: str) -> Optional[Dict[str, Any]]:
536
- """
537
- Get door type properties by ID.
538
-
539
- Args:
540
- door_type_id: Door type identifier
541
-
542
- Returns:
543
- Dictionary of door type properties or None if not found
544
- """
545
  return self.door_types.get(door_type_id)
546
-
547
  def get_internal_load(self, load_type: str, load_id: str) -> Optional[Dict[str, Any]]:
548
- """
549
- Get internal load properties by type and ID.
550
-
551
- Args:
552
- load_type: Type of internal load (occupancy, lighting, equipment)
553
- load_id: Internal load identifier
554
-
555
- Returns:
556
- Dictionary of internal load properties or None if not found
557
- """
558
- if load_type in self.internal_loads:
559
- return self.internal_loads[load_type].get(load_id)
560
- return None
561
-
562
- def export_to_json(self, file_path: str) -> None:
563
- """
564
- Export all reference data to a JSON file.
565
-
566
- Args:
567
- file_path: Path to the output JSON file
568
- """
569
- data = {
570
- "materials": self.materials,
571
- "wall_types": self.wall_types,
572
- "roof_types": self.roof_types,
573
- "floor_types": self.floor_types,
574
- "window_types": self.window_types,
575
- "door_types": self.door_types,
576
- "internal_loads": self.internal_loads
577
- }
578
-
579
- with open(file_path, 'w') as f:
580
- json.dump(data, f, indent=4)
581
-
582
- @classmethod
583
- def from_json(cls, file_path: str) -> 'ReferenceData':
584
- """
585
- Create a ReferenceData instance from a JSON file.
586
-
587
- Args:
588
- file_path: Path to the input JSON file
589
-
590
- Returns:
591
- A new ReferenceData instance
592
- """
593
- with open(file_path, 'r') as f:
594
- data = json.load(f)
595
-
596
- ref_data = cls()
597
- ref_data.materials = data.get("materials", ref_data.materials)
598
- ref_data.wall_types = data.get("wall_types", ref_data.wall_types)
599
- ref_data.roof_types = data.get("roof_types", ref_data.roof_types)
600
- ref_data.floor_types = data.get("floor_types", ref_data.floor_types)
601
- ref_data.window_types = data.get("window_types", ref_data.window_types)
602
- ref_data.door_types = data.get("door_types", ref_data.door_types)
603
- ref_data.internal_loads = data.get("internal_loads", ref_data.internal_loads)
604
-
605
- return ref_data
606
 
607
 
608
- # Create a singleton instance
609
- reference_data = ReferenceData()
 
 
 
 
610
 
611
- # Export reference data to JSON if needed
612
  if __name__ == "__main__":
613
- reference_data.export_to_json(os.path.join(DATA_DIR, "reference_data.json"))
 
 
 
 
7
  import pandas as pd
8
  import json
9
  import os
10
+ import logging
11
+ from uuid import uuid4
12
+
13
+ # Configure logging
14
+ logging.basicConfig(level=logging.INFO)
15
+ logger = logging.getLogger(__name__)
16
 
17
  # Define paths
18
  DATA_DIR = os.path.dirname(os.path.abspath(__file__))
19
+ DEFAULT_DATA_FILE = os.path.join(DATA_DIR, "reference_data.json")
20
 
21
 
22
  class ReferenceData:
23
  """Class for managing reference data for the HVAC calculator."""
24
+
25
  def __init__(self):
26
  """Initialize reference data structures."""
27
+ self.materials = {}
28
+ self.wall_types = {}
29
+ self.roof_types = {}
30
+ self.floor_types = {}
31
+ self.window_types = {}
32
+ self.door_types = {}
33
+ self.internal_loads = {}
34
+
35
+ try:
36
+ self._load_all_data()
37
+ except Exception as e:
38
+ logger.error(f"Error initializing reference data: {str(e)}")
39
+ raise
40
+
41
+ def _load_all_data(self) -> None:
42
+ """Load all reference data, attempting to load from JSON first."""
43
+ try:
44
+ if os.path.exists(DEFAULT_DATA_FILE):
45
+ self._load_from_json(DEFAULT_DATA_FILE)
46
+ else:
47
+ self._load_default_data()
48
+ self.export_to_json(DEFAULT_DATA_FILE)
49
+ except Exception as e:
50
+ logger.error(f"Error loading reference data: {str(e)}")
51
+ self._load_default_data() # Fallback to default data
52
+
53
+ def _load_default_data(self) -> None:
54
+ """Load default reference data."""
55
  self.materials = self._load_materials()
56
  self.wall_types = self._load_wall_types()
57
  self.roof_types = self._load_roof_types()
 
59
  self.window_types = self._load_window_types()
60
  self.door_types = self._load_door_types()
61
  self.internal_loads = self._load_internal_loads()
62
+
63
  def _load_materials(self) -> Dict[str, Dict[str, Any]]:
64
  """
65
+ Load material properties.
 
66
  Returns:
67
  Dictionary of material properties
68
  """
 
 
69
  return {
70
  "brick": {
71
+ "id": str(uuid4()),
72
  "name": "Common Brick",
73
  "conductivity": 0.72, # W/(m·K)
74
  "density": 1920, # kg/m³
75
  "specific_heat": 840, # J/(kg·K)
76
+ "typical_thickness": 0.1, # m
77
+ "emissivity": 0.9,
78
+ "solar_absorptance": 0.7
79
  },
80
  "concrete": {
81
+ "id": str(uuid4()),
82
  "name": "Concrete",
83
  "conductivity": 1.4, # W/(m·K)
84
  "density": 2300, # kg/m³
85
  "specific_heat": 880, # J/(kg·K)
86
+ "typical_thickness": 0.2, # m
87
+ "emissivity": 0.92,
88
+ "solar_absorptance": 0.65
89
  },
90
  "mineral_wool": {
91
+ "id": str(uuid4()),
92
  "name": "Mineral Wool Insulation",
93
  "conductivity": 0.04, # W/(m·K)
94
  "density": 30, # kg/m³
95
  "specific_heat": 840, # J/(kg·K)
96
+ "typical_thickness": 0.1, # m
97
+ "emissivity": 0.9,
98
+ "solar_absorptance": 0.6
 
 
 
 
 
99
  },
100
+ # Additional materials
101
+ "polyurethane_foam": {
102
+ "id": str(uuid4()),
103
+ "name": "Polyurethane Foam",
104
+ "conductivity": 0.025, # W/(m·K)
105
+ "density": 40, # kg/m³
106
+ "specific_heat": 1500, # J/(kg·K)
107
+ "typical_thickness": 0.05, # m
108
+ "emissivity": 0.9,
109
+ "solar_absorptance": 0.6
110
  },
111
+ "fiberglass_insulation": {
112
+ "id": str(uuid4()),
113
+ "name": "Fiberglass Insulation",
114
+ "conductivity": 0.045, # W/(m·K)
115
+ "density": 12, # kg/
116
+ "specific_heat": 850, # J/(kg·K)
117
+ "typical_thickness": 0.15, # m
118
+ "emissivity": 0.9,
119
+ "solar_absorptance": 0.6
120
  },
121
+ "stucco": {
122
+ "id": str(uuid4()),
123
+ "name": "Stucco",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  "conductivity": 0.7, # W/(m·K)
125
+ "density": 1850, # kg/m³
126
+ "specific_heat": 900, # J/(kg·K)
127
+ "typical_thickness": 0.025, # m
128
+ "emissivity": 0.92,
129
+ "solar_absorptance": 0.5
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
131
+ # Add more materials as needed
132
  }
133
+
134
  def _load_wall_types(self) -> Dict[str, Dict[str, Any]]:
135
  """
136
+ Load predefined wall types.
 
137
  Returns:
138
  Dictionary of wall types with properties
139
  """
140
  return {
141
  "brick_veneer_wood_frame": {
142
+ "id": str(uuid4()),
143
+ "name": "Brick Veneer with Wood Frame",
144
  "description": "Brick veneer with wood frame, insulation, and gypsum board",
145
  "u_value": 0.35, # W/(m²·K)
146
+ "wall_group": "B",
147
  "layers": [
148
  {"material": "brick", "thickness": 0.1},
149
  {"material": "air_gap", "thickness": 0.025},
150
  {"material": "wood", "thickness": 0.038},
151
  {"material": "mineral_wool", "thickness": 0.089},
152
  {"material": "gypsum_board", "thickness": 0.0125}
153
+ ],
154
+ "thermal_mass": 180, # kg/m²
155
+ "color": "Medium"
156
  },
157
+ "insulated_concrete_form": {
158
+ "id": str(uuid4()),
159
+ "name": "Insulated Concrete Form",
160
+ "description": "ICF with EPS insulation and concrete core",
161
+ "u_value": 0.25, # W/(m²·K)
162
+ "wall_group": "C",
163
  "layers": [
164
+ {"material": "eps_insulation", "thickness": 0.05},
165
+ {"material": "concrete", "thickness": 0.15},
166
  {"material": "eps_insulation", "thickness": 0.05},
167
  {"material": "gypsum_board", "thickness": 0.0125}
168
+ ],
169
+ "thermal_mass": 220, # kg/m²
170
+ "color": "Light"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  },
172
+ # Additional wall types
173
+ "sip_panel": {
174
+ "id": str(uuid4()),
175
+ "name": "Structural Insulated Panel",
176
+ "description": "SIP with OSB and EPS core",
177
+ "u_value": 0.28, # W/(m²·K)
178
+ "wall_group": "A",
179
  "layers": [
180
+ {"material": "wood", "thickness": 0.012},
181
+ {"material": "eps_insulation", "thickness": 0.15},
182
+ {"material": "wood", "thickness": 0.012},
 
183
  {"material": "gypsum_board", "thickness": 0.0125}
184
+ ],
185
+ "thermal_mass": 80, # kg/m²
186
+ "color": "Light"
187
  }
188
  }
189
+
190
  def _load_roof_types(self) -> Dict[str, Dict[str, Any]]:
191
  """
192
+ Load predefined roof types.
 
193
  Returns:
194
  Dictionary of roof types with properties
195
  """
196
  return {
197
  "flat_roof_concrete": {
198
+ "id": str(uuid4()),
199
+ "name": "Flat Concrete Roof with Insulation",
200
  "description": "Flat concrete roof with insulation and ceiling",
201
  "u_value": 0.25, # W/(m²·K)
202
+ "roof_group": "B",
203
  "layers": [
204
  {"material": "concrete", "thickness": 0.15},
205
  {"material": "eps_insulation", "thickness": 0.15},
206
  {"material": "gypsum_board", "thickness": 0.0125}
207
+ ],
208
+ "solar_absorptance": 0.7,
209
+ "emissivity": 0.9
210
  },
211
+ "green_roof": {
212
+ "id": str(uuid4()),
213
+ "name": "Green Roof",
214
+ "description": "Vegetated roof with insulation and drainage",
215
+ "u_value": 0.22, # W/(m²·K)
216
+ "roof_group": "A",
 
 
 
 
 
 
 
 
 
 
 
 
217
  "layers": [
218
+ {"material": "soil", "thickness": 0.1},
219
  {"material": "eps_insulation", "thickness": 0.1},
220
+ {"material": "concrete", "thickness": 0.1},
221
  {"material": "gypsum_board", "thickness": 0.0125}
222
+ ],
223
+ "solar_absorptance": 0.5,
224
+ "emissivity": 0.95
225
  }
226
  }
227
+
228
  def _load_floor_types(self) -> Dict[str, Dict[str, Any]]:
229
  """
230
+ Load predefined floor types.
 
231
  Returns:
232
  Dictionary of floor types with properties
233
  """
234
  return {
235
  "concrete_slab_on_grade": {
236
+ "id": str(uuid4()),
237
+ "name": "Concrete Slab on Grade",
238
  "description": "Concrete slab on grade with insulation",
239
  "u_value": 0.3, # W/(m²·K)
240
  "is_ground_contact": True,
241
  "layers": [
242
  {"material": "concrete", "thickness": 0.1},
243
  {"material": "eps_insulation", "thickness": 0.05}
244
+ ],
245
+ "thermal_mass": 230 # kg/m²
 
 
 
 
 
 
 
 
 
 
246
  },
247
+ "radiant_floor": {
248
+ "id": str(uuid4()),
249
+ "name": "Radiant Floor",
250
+ "description": "Concrete floor with radiant heating and insulation",
251
+ "u_value": 0.27, # W/(m²·K)
 
 
 
 
 
 
 
 
 
 
 
252
  "is_ground_contact": True,
253
  "layers": [
254
+ {"material": "tile", "thickness": 0.015},
255
  {"material": "concrete", "thickness": 0.1},
256
+ {"material": "eps_insulation", "thickness": 0.075}
257
+ ],
258
+ "thermal_mass": 240 # kg/m²
259
  }
260
  }
261
+
262
  def _load_window_types(self) -> Dict[str, Dict[str, Any]]:
263
  """
264
+ Load predefined window types.
 
265
  Returns:
266
  Dictionary of window types with properties
267
  """
268
  return {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  "double_glazed_argon_low_e": {
270
+ "id": str(uuid4()),
271
+ "name": "Double Glazed with Argon and Low-E",
272
  "description": "Double glazed window with argon fill, low-e coating, and vinyl frame",
273
  "u_value": 1.4, # W/(m²·K)
274
+ "shgc": 0.4,
275
+ "vt": 0.7,
276
  "glazing_layers": 2,
277
  "gas_fill": "Argon",
278
  "frame_type": "Vinyl",
279
+ "low_e_coating": True,
280
+ "frame_factor": 0.15
281
  },
282
+ "electrochromic_window": {
283
+ "id": str(uuid4()),
284
+ "name": "Electrochromic Window",
285
+ "description": "Smart window with dynamic tinting",
286
+ "u_value": 1.2, # W/(m²·K)
287
+ "shgc": 0.35,
288
+ "vt": 0.65,
289
+ "glazing_layers": 2,
290
  "gas_fill": "Argon",
291
+ "frame_type": "Fiberglass",
292
+ "low_e_coating": True,
293
+ "frame_factor": 0.12
294
  }
295
  }
296
+
297
  def _load_door_types(self) -> Dict[str, Dict[str, Any]]:
298
  """
299
+ Load predefined door types.
 
300
  Returns:
301
  Dictionary of door types with properties
302
  """
303
  return {
 
 
 
 
 
 
 
304
  "insulated_steel_door": {
305
+ "id": str(uuid4()),
306
+ "name": "Insulated Steel Door",
307
  "description": "Insulated steel door with no glazing",
308
  "u_value": 1.2, # W/(m²·K)
309
  "glazing_percentage": 0,
310
+ "door_type": "Solid",
311
+ "thermal_mass": 50 # kg/m²
312
  },
313
+ "insulated_fiberglass_door": {
314
+ "id": str(uuid4()),
315
+ "name": "Insulated Fiberglass Door",
316
+ "description": "Insulated fiberglass door with small glazing",
317
+ "u_value": 1.5, # W/(m²·K)
318
+ "glazing_percentage": 10,
319
  "door_type": "Partially glazed",
320
+ "shgc": 0.7,
321
+ "vt": 0.8,
322
+ "thermal_mass": 40 # kg/m²
 
 
 
 
 
 
 
 
323
  }
324
  }
325
+
326
  def _load_internal_loads(self) -> Dict[str, Dict[str, Any]]:
327
  """
328
+ Load internal load data.
 
329
  Returns:
330
  Dictionary of internal load types with properties
331
  """
332
  return {
333
  "occupancy": {
334
+ "office_typing": {
335
+ "id": str(uuid4()),
336
+ "name": "Office Typing",
 
 
 
 
337
  "sensible_heat": 75, # W per person
338
+ "latent_heat": 55, # W per person
339
+ "metabolic_rate": 1.2 # met
340
  },
341
+ "retail_sales": {
342
+ "id": str(uuid4()),
343
+ "name": "Retail Sales",
344
  "sensible_heat": 80, # W per person
345
+ "latent_heat": 70, # W per person
346
+ "metabolic_rate": 1.4 # met
 
 
 
 
 
 
 
 
 
347
  }
348
  },
349
  "lighting": {
350
+ "led_high_efficiency": {
351
+ "id": str(uuid4()),
352
+ "name": "High Efficiency LED",
353
+ "power_density_range": [4, 8], # W/m²
354
+ "heat_to_space": 0.85,
355
+ "efficacy": 120 # lm/W
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  }
357
  },
358
  "equipment": {
359
+ "computer_workstation": {
360
+ "id": str(uuid4()),
361
+ "name": "Computer Workstation",
362
+ "power_density_range": [15, 25], # W/m²
363
+ "sensible_fraction": 0.95,
364
+ "latent_fraction": 0.05
 
 
 
 
 
 
 
 
 
 
 
365
  }
366
  }
367
  }
368
+
369
+ def _load_from_json(self, file_path: str) -> None:
370
  """
371
+ Load reference data from JSON file.
 
372
  Args:
373
+ file_path: Path to JSON file
374
+ """
375
+ try:
376
+ with open(file_path, 'r') as f:
377
+ data = json.load(f)
378
+ self.materials = data.get("materials", self.materials)
379
+ self.wall_types = data.get("wall_types", self.wall_types)
380
+ self.roof_types = data.get("roof_types", self.roof_types)
381
+ self.floor_types = data.get("floor_types", self.floor_types)
382
+ self.window_types = data.get("window_types", self.window_types)
383
+ self.door_types = data.get("door_types", self.door_types)
384
+ self.internal_loads = data.get("internal_loads", self.internal_loads)
385
+ logger.info(f"Successfully loaded reference data from {file_path}")
386
+ except Exception as e:
387
+ logger.error(f"Error loading JSON data from {file_path}: {str(e)}")
388
+ raise
389
+
390
+ def export_to_json(self, file_path: str) -> None:
391
  """
392
+ Export all reference data to a JSON file.
 
393
  Args:
394
+ file_path: Path to the output JSON file
 
 
 
395
  """
396
+ try:
397
+ data = {
398
+ "materials": self.materials,
399
+ "wall_types": self.wall_types,
400
+ "roof_types": self.roof_types,
401
+ "floor_types": self.floor_types,
402
+ "window_types": self.window_types,
403
+ "door_types": self.door_types,
404
+ "internal_loads": self.internal_loads
405
+ }
406
+ with open(file_path, 'w') as f:
407
+ json.dump(data, f, indent=4)
408
+ logger.info(f"Successfully exported reference data to {file_path}")
409
+ except Exception as e:
410
+ logger.error(f"Error exporting to JSON: {str(e)}")
411
+ raise
412
+
413
+ # Getter methods with validation
414
+ def get_material(self, material_id: str) -> Optional[Dict[str, Any]]:
415
+ return self.materials.get(material_id)
416
+
417
+ def get_wall_type(self, wall_type_id: str) -> Optional[Dict[str, Any]]:
418
  return self.wall_types.get(wall_type_id)
419
+
420
  def get_roof_type(self, roof_type_id: str) -> Optional[Dict[str, Any]]:
 
 
 
 
 
 
 
 
 
421
  return self.roof_types.get(roof_type_id)
422
+
423
  def get_floor_type(self, floor_type_id: str) -> Optional[Dict[str, Any]]:
 
 
 
 
 
 
 
 
 
424
  return self.floor_types.get(floor_type_id)
425
+
426
  def get_window_type(self, window_type_id: str) -> Optional[Dict[str, Any]]:
 
 
 
 
 
 
 
 
 
427
  return self.window_types.get(window_type_id)
428
+
429
  def get_door_type(self, door_type_id: str) -> Optional[Dict[str, Any]]:
 
 
 
 
 
 
 
 
 
430
  return self.door_types.get(door_type_id)
431
+
432
  def get_internal_load(self, load_type: str, load_id: str) -> Optional[Dict[str, Any]]:
433
+ return self.internal_loads.get(load_type, {}).get(load_id)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
 
435
 
436
+ # Singleton instance
437
+ try:
438
+ reference_data = ReferenceData()
439
+ except Exception as e:
440
+ logger.error(f"Failed to create ReferenceData instance: {str(e)}")
441
+ raise
442
 
 
443
  if __name__ == "__main__":
444
+ try:
445
+ reference_data.export_to_json(DEFAULT_DATA_FILE)
446
+ except Exception as e:
447
+ logger.error(f"Error exporting default data: {str(e)}")