not-sure / data /ashrae_tables.py
mabuseif's picture
Upload 25 files
6cc22a6 verified
"""
ASHRAE tables module for HVAC Load Calculator.
This module provides access to ASHRAE tables for cooling and heating load calculations.
"""
from typing import Dict, List, Any, Optional, Tuple
import math
import numpy as np
import pandas as pd
import os
from datetime import datetime
class ASHRAETables:
"""Class for accessing ASHRAE tables for cooling and heating load calculations."""
def __init__(self):
"""Initialize ASHRAE tables."""
# Table 3: Percentage of the Daily Range
self.daily_range_percentage = {
1: 87, 2: 92, 3: 96, 4: 99, 5: 100, 6: 98,
7: 93, 8: 84, 9: 71, 10: 56, 11: 39, 12: 23,
13: 11, 14: 3, 15: 0, 16: 3, 17: 10, 18: 21,
19: 34, 20: 47, 21: 58, 22: 68, 23: 76, 24: 82
}
# Table 5: Cooling Load Temperature Differences (CLTD) for Flat Roofs (SI Units)
# Format: {roof_group: {hour: cltd}}
self.cltd_flat_roofs = {
# Group 1: Steel sheet with 25.4mm (or 50.8mm) insulation
1: {
1: 0, 2: -1, 3: -2, 4: -3, 5: -3, 6: -2, 7: 1, 8: 5, 9: 11, 10: 19, 11: 27, 12: 34,
13: 40, 14: 43, 15: 44, 16: 43, 17: 39, 18: 33, 19: 25, 20: 17, 21: 10, 22: 7, 23: 3, 24: 1
},
# Group 2: 25.4mm wood with 25.4mm insulation
2: {
1: 3, 2: 0, 3: -1, 4: -2, 5: -2, 6: -1, 7: 2, 8: 8, 9: 15, 10: 22, 11: 29, 12: 35,
13: 39, 14: 41, 15: 41, 16: 39, 17: 35, 18: 29, 19: 21, 20: 15, 21: 11, 22: 8, 23: 5, 24: 3
},
# Group 3: 101.6mm light weight concrete
3: {
1: 6, 2: 3, 3: 1, 4: 0, 5: -1, 6: -2, 7: 0, 8: 5, 9: 11, 10: 18, 11: 25, 12: 31,
13: 36, 14: 39, 15: 40, 16: 39, 17: 37, 18: 32, 19: 25, 20: 19, 21: 14, 22: 10, 23: 7, 24: 6
},
# Group 4: 50.8mm heavy weight concrete with 25.4mm insulation (or 50.8mm insulation)
4: {
1: 7, 2: 5, 3: 3, 4: 2, 5: 0, 6: -1, 7: 0, 8: 2, 9: 6, 10: 11, 11: 17, 12: 23,
13: 28, 14: 33, 15: 36, 16: 37, 17: 37, 18: 34, 19: 30, 20: 25, 21: 20, 22: 15, 23: 10, 24: 7
},
# Group 5: 25.4mm wood with 50.8mm insulation
5: {
1: 2, 2: 0, 3: -2, 4: -3, 5: -4, 6: -4, 7: -2, 8: 3, 9: 9, 10: 15, 11: 22, 12: 27,
13: 32, 14: 36, 15: 38, 16: 38, 17: 35, 18: 32, 19: 27, 20: 20, 21: 14, 22: 10, 23: 6, 24: 3
},
# Group 6: 152.4mm Light Weight Concrete
6: {
1: 12, 2: 10, 3: 7, 4: 5, 5: 3, 6: 2, 7: 0, 8: 2, 9: 4, 10: 8, 11: 13, 12: 18,
13: 24, 14: 29, 15: 33, 16: 36, 17: 38, 18: 38, 19: 35, 20: 32, 21: 28, 22: 24, 23: 19, 24: 16
},
# Group 7: 63.5mm wood with 25.4mm insulation
7: {
1: 10, 2: 13, 3: 11, 4: 9, 5: 7, 6: 5, 7: 3, 8: 4, 9: 5, 10: 8, 11: 11, 12: 15,
13: 19, 14: 22, 15: 27, 16: 29, 17: 31, 18: 31, 19: 30, 20: 27, 21: 25, 22: 22, 23: 19, 24: 13
},
# Group 8: 203.2mm light weight concrete
8: {
1: 20, 2: 17, 3: 14, 4: 12, 5: 10, 6: 8, 7: 6, 8: 5, 9: 5, 10: 7, 11: 11, 12: 14,
13: 18, 14: 22, 15: 26, 16: 30, 17: 33, 18: 34, 19: 34, 20: 33, 21: 30, 22: 27, 23: 25, 24: 22
},
# Group 9: 101.6mm heavy weight concrete with 25.4mm insulation (or 50.8mm insulation)
9: {
1: 14, 2: 12, 3: 10, 4: 8, 5: 7, 6: 5, 7: 4, 8: 4, 9: 6, 10: 8, 11: 11, 12: 15,
13: 18, 14: 22, 15: 25, 16: 28, 17: 29, 18: 30, 19: 29, 20: 27, 21: 24, 22: 21, 23: 19, 24: 16
},
# Group 10: 152.4mm heavy weight concrete
10: {
1: 18, 2: 15, 3: 13, 4: 11, 5: 9, 6: 7, 7: 5, 8: 5, 9: 5, 10: 7, 11: 10, 12: 13,
13: 17, 14: 21, 15: 24, 16: 27, 17: 29, 18: 30, 19: 29, 20: 28, 21: 26, 22: 24, 23: 21, 24: 19
},
# Group 11: Roof terrace system
11: {
1: 19, 2: 17, 3: 15, 4: 14, 5: 12, 6: 11, 7: 9, 8: 8, 9: 8, 10: 8, 11: 10, 12: 12,
13: 15, 14: 18, 15: 20, 16: 22, 17: 24, 18: 25, 19: 26, 20: 25, 21: 24, 22: 22, 23: 20, 24: 19
},
# Group 12: 101.6mm heavy weight concrete with 25.4mm insulation (or 50.8mm insulation)
12: {
1: 18, 2: 16, 3: 14, 4: 12, 5: 11, 6: 10, 7: 9, 8: 8, 9: 9, 10: 10, 11: 12, 12: 15,
13: 17, 14: 20, 15: 22, 16: 24, 17: 25, 18: 25, 19: 25, 20: 25, 21: 23, 22: 20, 23: 19, 24: 18
},
# Group 13: 152.4mm wood with 25.4mm insulation (or 50.8mm insulation)
13: {
1: 21, 2: 20, 3: 18, 4: 17, 5: 16, 6: 14, 7: 13, 8: 11, 9: 10, 10: 9, 11: 9, 12: 10,
13: 12, 14: 14, 15: 16, 16: 19, 17: 21, 18: 22, 19: 23, 20: 24, 21: 24, 22: 23, 23: 22, 24: 21
}
}
# Table 6: Cooling Load Temperature Differences (CLTD) for Walls (SI Units)
# Format: {wall_group: {orientation: {hour: cltd}}}
self.cltd_walls = {
# Group A: 100mm concrete wall
"A": {
"N": {
1: 0, 2: -1, 3: -1, 4: -2, 5: -2, 6: -2, 7: 0, 8: 2, 9: 4, 10: 6, 11: 7, 12: 8,
13: 9, 14: 10, 15: 10, 16: 10, 17: 9, 18: 7, 19: 5, 20: 3, 21: 2, 22: 1, 23: 1, 24: 0
},
"NE": {
1: -1, 2: -1, 3: -2, 4: -2, 5: -2, 6: 0, 7: 5, 8: 10, 9: 13, 10: 14, 11: 14, 12: 13,
13: 12, 14: 11, 15: 10, 16: 9, 17: 7, 18: 5, 19: 3, 20: 1, 21: 0, 22: 0, 23: -1, 24: -1
},
"E": {
1: 0, 2: -1, 3: -1, 4: -2, 5: -2, 6: 0, 7: 4, 8: 9, 9: 14, 10: 17, 11: 19, 12: 19,
13: 18, 14: 16, 15: 14, 16: 11, 17: 8, 18: 6, 19: 3, 20: 2, 21: 1, 22: 1, 23: 0, 24: 0
},
"SE": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: 0, 7: 3, 8: 7, 9: 11, 10: 15, 11: 17, 12: 18,
13: 18, 14: 17, 15: 15, 16: 12, 17: 9, 18: 6, 19: 4, 20: 3, 21: 2, 22: 2, 23: 1, 24: 1
},
"S": {
1: 2, 2: 2, 3: 1, 4: 0, 5: 0, 6: 0, 7: 0, 8: 1, 9: 3, 10: 7, 11: 10, 12: 14,
13: 16, 14: 17, 15: 17, 16: 16, 17: 13, 18: 10, 19: 7, 20: 5, 21: 4, 22: 3, 23: 3, 24: 2
},
"SW": {
1: 3, 2: 2, 3: 2, 4: 1, 5: 0, 6: 0, 7: 0, 8: 0, 9: 1, 10: 3, 11: 5, 12: 8,
13: 11, 14: 14, 15: 16, 16: 17, 17: 17, 18: 15, 19: 12, 20: 9, 21: 7, 22: 5, 23: 4, 24: 3
},
"W": {
1: 2, 2: 2, 3: 1, 4: 1, 5: 0, 6: 0, 7: 0, 8: 0, 9: 1, 10: 2, 11: 3, 12: 5,
13: 7, 14: 10, 15: 13, 16: 15, 17: 16, 18: 16, 19: 14, 20: 11, 21: 8, 22: 6, 23: 4, 24: 3
},
"NW": {
1: 1, 2: 0, 3: 0, 4: 0, 5: -1, 6: -1, 7: 0, 8: 0, 9: 1, 10: 3, 11: 4, 12: 5,
13: 6, 14: 7, 15: 9, 16: 11, 17: 12, 18: 12, 19: 10, 20: 7, 21: 5, 22: 3, 23: 2, 24: 1
},
"Horizontal": {
1: 0, 2: -1, 3: -1, 4: -2, 5: -2, 6: -1, 7: 1, 8: 3, 9: 6, 10: 9, 11: 12, 12: 14,
13: 16, 14: 17, 15: 17, 16: 16, 17: 14, 18: 11, 19: 8, 20: 5, 21: 3, 22: 2, 23: 1, 24: 0
}
},
# Group B: 200mm concrete wall with 50mm insulation outside
"B": {
"N": {
1: 3, 2: 2, 3: 1, 4: 0, 5: 0, 6: -1, 7: -1, 8: 0, 9: 1, 10: 2, 11: 3, 12: 4,
13: 5, 14: 6, 15: 6, 16: 7, 17: 7, 18: 6, 19: 6, 20: 5, 21: 5, 22: 4, 23: 4, 24: 3
},
"NE": {
1: 2, 2: 1, 3: 0, 4: 0, 5: -1, 6: 0, 7: 2, 8: 5, 9: 7, 10: 8, 11: 9, 12: 9,
13: 9, 14: 9, 15: 8, 16: 8, 17: 7, 18: 6, 19: 5, 20: 4, 21: 4, 22: 3, 23: 3, 24: 2
},
"E": {
1: 3, 2: 2, 3: 1, 4: 0, 5: 0, 6: 0, 7: 2, 8: 5, 9: 8, 10: 10, 11: 12, 12: 12,
13: 12, 14: 12, 15: 11, 16: 10, 17: 9, 18: 7, 19: 6, 20: 5, 21: 5, 22: 4, 23: 4, 24: 3
},
"SE": {
1: 4, 2: 3, 3: 2, 4: 1, 5: 1, 6: 1, 7: 2, 8: 4, 9: 7, 10: 9, 11: 11, 12: 12,
13: 13, 14: 13, 15: 12, 16: 11, 17: 10, 18: 8, 19: 7, 20: 6, 21: 6, 22: 5, 23: 5, 24: 4
},
"S": {
1: 5, 2: 4, 3: 4, 4: 3, 5: 2, 6: 2, 7: 2, 8: 2, 9: 3, 10: 5, 11: 7, 12: 9,
13: 11, 14: 12, 15: 13, 16: 13, 17: 12, 18: 11, 19: 9, 20: 8, 21: 7, 22: 7, 23: 6, 24: 5
},
"SW": {
1: 6, 2: 5, 3: 5, 4: 4, 5: 3, 6: 3, 7: 2, 8: 2, 9: 3, 10: 3, 11: 5, 12: 6,
13: 8, 14: 10, 15: 12, 16: 13, 17: 13, 18: 13, 19: 12, 20: 10, 21: 9, 22: 8, 23: 7, 24: 6
},
"W": {
1: 5, 2: 5, 3: 4, 4: 3, 5: 3, 6: 2, 7: 2, 8: 2, 9: 2, 10: 3, 11: 3, 12: 4,
13: 6, 14: 7, 15: 9, 16: 11, 17: 12, 18: 13, 19: 12, 20: 11, 21: 9, 22: 8, 23: 7, 24: 6
},
"NW": {
1: 4, 2: 3, 3: 3, 4: 2, 5: 2, 6: 1, 7: 1, 8: 1, 9: 1, 10: 2, 11: 3, 12: 3,
13: 4, 14: 5, 15: 6, 16: 8, 17: 9, 18: 10, 19: 9, 20: 8, 21: 7, 22: 6, 23: 5, 24: 4
},
"Horizontal": {
1: 3, 2: 2, 3: 1, 4: 0, 5: 0, 6: 0, 7: 1, 8: 2, 9: 4, 10: 6, 11: 8, 12: 10,
13: 11, 14: 12, 15: 13, 16: 13, 17: 12, 18: 10, 19: 8, 20: 7, 21: 6, 22: 5, 23: 4, 24: 3
}
},
# Group C: 300mm concrete wall
"C": {
"N": {
1: 4, 2: 3, 3: 3, 4: 2, 5: 2, 6: 1, 7: 1, 8: 1, 9: 1, 10: 2, 11: 2, 12: 3,
13: 3, 14: 4, 15: 4, 16: 5, 17: 5, 18: 5, 19: 5, 20: 5, 21: 5, 22: 5, 23: 4, 24: 4
},
"NE": {
1: 3, 2: 3, 3: 2, 4: 2, 5: 1, 6: 1, 7: 2, 8: 3, 9: 5, 10: 6, 11: 6, 12: 7,
13: 7, 14: 7, 15: 7, 16: 6, 17: 6, 18: 6, 19: 5, 20: 5, 21: 4, 22: 4, 23: 4, 24: 3
},
"E": {
1: 4, 2: 3, 3: 3, 4: 2, 5: 2, 6: 1, 7: 2, 8: 3, 9: 5, 10: 7, 11: 8, 12: 9,
13: 10, 14: 10, 15: 9, 16: 9, 17: 8, 18: 7, 19: 7, 20: 6, 21: 6, 22: 5, 23: 5, 24: 4
},
"SE": {
1: 5, 2: 4, 3: 4, 4: 3, 5: 3, 6: 2, 7: 2, 8: 3, 9: 5, 10: 7, 11: 8, 12: 10,
13: 10, 14: 11, 15: 11, 16: 10, 17: 9, 18: 9, 19: 8, 20: 7, 21: 7, 22: 6, 23: 6, 24: 5
},
"S": {
1: 6, 2: 6, 3: 5, 4: 5, 5: 4, 6: 3, 7: 3, 8: 3, 9: 3, 10: 4, 11: 6, 12: 7,
13: 9, 14: 10, 15: 11, 16: 11, 17: 11, 18: 10, 19: 10, 20: 9, 21: 8, 22: 8, 23: 7, 24: 7
},
"SW": {
1: 7, 2: 7, 3: 6, 4: 6, 5: 5, 6: 4, 7: 4, 8: 3, 9: 3, 10: 3, 11: 4, 12: 5,
13: 6, 14: 8, 15: 9, 16: 10, 17: 11, 18: 11, 19: 11, 20: 10, 21: 10, 22: 9, 23: 8, 24: 8
},
"W": {
1: 7, 2: 6, 3: 6, 4: 5, 5: 5, 6: 4, 7: 3, 8: 3, 9: 3, 10: 3, 11: 3, 12: 4,
13: 4, 14: 6, 15: 7, 16: 8, 17: 10, 18: 10, 19: 11, 20: 10, 21: 9, 22: 9, 23: 8, 24: 7
},
"NW": {
1: 5, 2: 5, 3: 4, 4: 4, 5: 3, 6: 3, 7: 2, 8: 2, 9: 2, 10: 2, 11: 2, 12: 3,
13: 3, 14: 4, 15: 5, 16: 6, 17: 7, 18: 8, 19: 8, 20: 8, 21: 7, 22: 7, 23: 6, 24: 6
},
"Horizontal": {
1: 5, 2: 4, 3: 3, 4: 3, 5: 2, 6: 2, 7: 2, 8: 2, 9: 3, 10: 5, 11: 6, 12: 8,
13: 9, 14: 10, 15: 10, 16: 11, 17: 10, 18: 10, 19: 9, 20: 8, 21: 7, 22: 6, 23: 6, 24: 5
}
},
# Group D: 200mm concrete wall with 50mm insulation inside
"D": {
"N": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: -1, 7: 0, 8: 1, 9: 3, 10: 4, 11: 5, 12: 6,
13: 7, 14: 7, 15: 7, 16: 7, 17: 6, 18: 5, 19: 4, 20: 3, 21: 2, 22: 2, 23: 1, 24: 1
},
"NE": {
1: 0, 2: 0, 3: -1, 4: -1, 5: -1, 6: 0, 7: 3, 8: 7, 9: 10, 10: 11, 11: 11, 12: 11,
13: 10, 14: 9, 15: 8, 16: 7, 17: 5, 18: 4, 19: 3, 20: 2, 21: 1, 22: 1, 23: 0, 24: 0
},
"E": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: 0, 7: 3, 8: 7, 9: 11, 10: 14, 11: 15, 12: 15,
13: 14, 14: 13, 15: 11, 16: 9, 17: 7, 18: 5, 19: 3, 20: 2, 21: 2, 22: 1, 23: 1, 24: 1
},
"SE": {
1: 2, 2: 1, 3: 1, 4: 0, 5: 0, 6: 0, 7: 2, 8: 5, 9: 9, 10: 12, 11: 14, 12: 15,
13: 15, 14: 14, 15: 12, 16: 10, 17: 8, 18: 6, 19: 4, 20: 3, 21: 3, 22: 2, 23: 2, 24: 2
},
"S": {
1: 3, 2: 3, 3: 2, 4: 1, 5: 1, 6: 0, 7: 0, 8: 1, 9: 3, 10: 6, 11: 9, 12: 12,
13: 14, 14: 15, 15: 15, 16: 13, 17: 11, 18: 9, 19: 7, 20: 5, 21: 4, 22: 4, 23: 3, 24: 3
},
"SW": {
1: 4, 2: 3, 3: 3, 4: 2, 5: 1, 6: 1, 7: 0, 8: 0, 9: 1, 10: 2, 11: 4, 12: 7,
13: 10, 14: 13, 15: 15, 16: 16, 17: 15, 18: 13, 19: 11, 20: 8, 21: 7, 22: 6, 23: 5, 24: 4
},
"W": {
1: 3, 2: 3, 3: 2, 4: 2, 5: 1, 6: 0, 7: 0, 8: 0, 9: 0, 10: 1, 11: 2, 12: 4,
13: 6, 14: 9, 15: 12, 16: 14, 17: 15, 18: 14, 19: 12, 20: 10, 21: 8, 22: 6, 23: 5, 24: 4
},
"NW": {
1: 2, 2: 1, 3: 1, 4: 0, 5: 0, 6: -1, 7: 0, 8: 0, 9: 1, 10: 2, 11: 3, 12: 4,
13: 5, 14: 6, 15: 8, 16: 10, 17: 11, 18: 10, 19: 9, 20: 7, 21: 5, 22: 4, 23: 3, 24: 2
},
"Horizontal": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: 0, 7: 1, 8: 3, 9: 6, 10: 9, 11: 11, 12: 13,
13: 14, 14: 15, 15: 14, 16: 13, 17: 11, 18: 9, 19: 7, 20: 5, 21: 3, 22: 2, 23: 2, 24: 1
}
},
# Group E: 100mm concrete wall with 50mm insulation outside
"E": {
"N": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: -1, 7: 0, 8: 1, 9: 2, 10: 3, 11: 4, 12: 5,
13: 5, 14: 6, 15: 6, 16: 6, 17: 5, 18: 4, 19: 3, 20: 3, 21: 2, 22: 2, 23: 1, 24: 1
},
"NE": {
1: 0, 2: 0, 3: -1, 4: -1, 5: -1, 6: 0, 7: 3, 8: 6, 9: 8, 10: 9, 11: 9, 12: 9,
13: 8, 14: 8, 15: 7, 16: 6, 17: 5, 18: 4, 19: 3, 20: 2, 21: 1, 22: 1, 23: 1, 24: 0
},
"E": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: 0, 7: 2, 8: 6, 9: 9, 10: 11, 11: 12, 12: 12,
13: 12, 14: 11, 15: 9, 16: 8, 17: 6, 18: 5, 19: 3, 20: 2, 21: 2, 22: 1, 23: 1, 24: 1
},
"SE": {
1: 2, 2: 1, 3: 1, 4: 0, 5: 0, 6: 0, 7: 2, 8: 4, 9: 7, 10: 10, 11: 11, 12: 12,
13: 12, 14: 12, 15: 10, 16: 9, 17: 7, 18: 5, 19: 4, 20: 3, 21: 3, 22: 2, 23: 2, 24: 2
},
"S": {
1: 3, 2: 2, 3: 2, 4: 1, 5: 1, 6: 0, 7: 0, 8: 1, 9: 3, 10: 5, 11: 8, 12: 10,
13: 11, 14: 12, 15: 12, 16: 11, 17: 9, 18: 8, 19: 6, 20: 5, 21: 4, 22: 4, 23: 3, 24: 3
},
"SW": {
1: 3, 2: 3, 3: 2, 4: 2, 5: 1, 6: 1, 7: 0, 8: 0, 9: 1, 10: 2, 11: 4, 12: 6,
13: 8, 14: 10, 15: 12, 16: 12, 17: 12, 18: 11, 19: 9, 20: 7, 21: 6, 22: 5, 23: 4, 24: 4
},
"W": {
1: 3, 2: 2, 3: 2, 4: 1, 5: 1, 6: 0, 7: 0, 8: 0, 9: 0, 10: 1, 11: 2, 12: 3,
13: 5, 14: 7, 15: 9, 16: 11, 17: 12, 18: 11, 19: 10, 20: 8, 21: 6, 22: 5, 23: 4, 24: 3
},
"NW": {
1: 2, 2: 1, 3: 1, 4: 0, 5: 0, 6: -1, 7: 0, 8: 0, 9: 1, 10: 1, 11: 2, 12: 3,
13: 4, 14: 5, 15: 6, 16: 8, 17: 8, 18: 8, 19: 7, 20: 6, 21: 4, 22: 3, 23: 3, 24: 2
},
"Horizontal": {
1: 1, 2: 0, 3: 0, 4: -1, 5: -1, 6: 0, 7: 1, 8: 2, 9: 5, 10: 7, 11: 9, 12: 10,
13: 11, 14: 12, 15: 11, 16: 10, 17: 9, 18: 7, 19: 6, 20: 4, 21: 3, 22: 2, 23: 2, 24: 1
}
},
# Group F: 100mm concrete wall with 50mm insulation inside
"F": {
"N": {
1: 0, 2: 0, 3: -1, 4: -1, 5: -1, 6: -1, 7: 0, 8: 1, 9: 3, 10: 4, 11: 5, 12: 6,
13: 6, 14: 6, 15: 6, 16: 6, 17: 5, 18: 4, 19: 3, 20: 2, 21: 1, 22: 1, 23: 1, 24: 0
},
"NE": {
1: 0, 2: -1, 3: -1, 4: -1, 5: -1, 6: 0, 7: 3, 8: 7, 9: 9, 10: 10, 11: 10, 12: 9,
13: 9, 14: 8, 15: 7, 16: 5, 17: 4, 18: 3, 19: 2, 20: 1, 21: 1, 22: 0, 23: 0, 24: 0
},
"E": {
1: 0, 2: 0, 3: -1, 4: -1, 5: -1, 6: 0, 7: 3, 8: 7, 9: 10, 10: 13, 11: 14, 12: 14,
13: 13, 14: 11, 15: 9, 16: 7, 17: 5, 18: 4, 19: 2, 20: 1, 21: 1, 22: 1, 23: 0, 24: 0
},
"SE": {
1: 1, 2: 1, 3: 0, 4: 0, 5: -1, 6: 0, 7: 2, 8: 5, 9: 8, 10: 11, 11: 13, 12: 14,
13: 14, 14: 13, 15: 11, 16: 9, 17: 6, 18: 4, 19: 3, 20: 2, 21: 2, 22: 1, 23: 1, 24: 1
},
"S": {
1: 2, 2: 2, 3: 1, 4: 1, 5: 0, 6: 0, 7: 0, 8: 1, 9: 3, 10: 6, 11: 9, 12: 11,
13: 13, 14: 14, 15: 13, 16: 12, 17: 10, 18: 7, 19: 5, 20: 4, 21: 3, 22: 3, 23: 2, 24: 2
},
"SW": {
1: 3, 2: 2, 3: 2, 4: 1, 5: 1, 6: 0, 7: 0, 8: 0, 9: 1, 10: 2, 11: 4, 12: 7,
13: 9, 14: 12, 15: 13, 16: 14, 17: 13, 18: 12, 19: 9, 20: 7, 21: 5, 22: 4, 23: 4, 24: 3
},
"W": {
1: 2, 2: 2, 3: 1, 4: 1, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 1, 11: 2, 12: 3,
13: 5, 14: 8, 15: 10, 16: 12, 17: 13, 18: 13, 19: 11, 20: 8, 21: 6, 22: 5, 23: 4, 24: 3
},
"NW": {
1: 1, 2: 1, 3: 0, 4: 0, 5: 0, 6: -1, 7: 0, 8: 0, 9: 1, 10: 1, 11: 2, 12: 3,
13: 4, 14: 6, 15: 7, 16: 9, 17: 9, 18: 9, 19: 8, 20: 6, 21: 4, 22: 3, 23: 2, 24: 2
},
"Horizontal": {
1: 0, 2: 0, 3: -1, 4: -1, 5: -1, 6: 0, 7: 1, 8: 3, 9: 5, 10: 8, 11: 10, 12: 12,
13: 13, 14: 13, 15: 13, 16: 11, 17: 9, 18: 7, 19: 5, 20: 3, 21: 2, 22: 1, 23: 1, 24: 0
}
},
# Group G: 300mm brick wall
"G": {
"N": {
1: 3, 2: 2, 3: 2, 4: 1, 5: 1, 6: 0, 7: 0, 8: 1, 9: 1, 10: 2, 11: 2, 12: 3,
13: 3, 14: 4, 15: 4, 16: 4, 17: 4, 18: 4, 19: 4, 20: 4, 21: 4, 22: 4, 23: 3, 24: 3
},
"NE": {
1: 2, 2: 2, 3: 1, 4: 1, 5: 0, 6: 1, 7: 2, 8: 3, 9: 4, 10: 5, 11: 6, 12: 6,
13: 6, 14: 6, 15: 6, 16: 5, 17: 5, 18: 5, 19: 4, 20: 4, 21: 3, 22: 3, 23: 3, 24: 2
},
"E": {
1: 3, 2: 2, 3: 2, 4: 1, 5: 1, 6: 1, 7: 2, 8: 3, 9: 5, 10: 6, 11: 7, 12: 8,
13: 8, 14: 8, 15: 8, 16: 7, 17: 7, 18: 6, 19: 5, 20: 5, 21: 4, 22: 4, 23: 3, 24: 3
},
"SE": {
1: 4, 2: 3, 3: 3, 4: 2, 5: 2, 6: 1, 7: 2, 8: 3, 9: 4, 10: 6, 11: 7, 12: 8,
13: 9, 14: 9, 15: 9, 16: 8, 17: 8, 18: 7, 19: 6, 20: 6, 21: 5, 22: 5, 23: 4, 24: 4
},
"S": {
1: 5, 2: 5, 3: 4, 4: 4, 5: 3, 6: 3, 7: 2, 8: 2, 9: 3, 10: 4, 11: 5, 12: 6,
13: 7, 14: 8, 15: 9, 16: 9, 17: 9, 18: 9, 19: 8, 20: 7, 21: 7, 22: 6, 23: 6, 24: 5
},
"SW": {
1: 6, 2: 6, 3: 5, 4: 5, 5: 4, 6: 3, 7: 3, 8: 3, 9: 3, 10: 3, 11: 4, 12: 5,
13: 6, 14: 7, 15: 8, 16: 9, 17: 9, 18: 9, 19: 9, 20: 9, 21: 8, 22: 7, 23: 7, 24: 6
},
"W": {
1: 6, 2: 5, 3: 5, 4: 4, 5: 4, 6: 3, 7: 3, 8: 2, 9: 2, 10: 2, 11: 3, 12: 3,
13: 4, 14: 5, 15: 6, 16: 7, 17: 8, 18: 9, 19: 9, 20: 8, 21: 8, 22: 7, 23: 7, 24: 6
},
"NW": {
1: 4, 2: 4, 3: 3, 4: 3, 5: 3, 6: 2, 7: 2, 8: 1, 9: 1, 10: 2, 11: 2, 12: 2,
13: 3, 14: 3, 15: 4, 16: 5, 17: 6, 18: 7, 19: 7, 20: 6, 21: 6, 22: 5, 23: 5, 24: 5
},
"Horizontal": {
1: 4, 2: 3, 3: 3, 4: 2, 5: 2, 6: 1, 7: 1, 8: 2, 9: 3, 10: 4, 11: 5, 12: 6,
13: 7, 14: 8, 15: 9, 16: 9, 17: 9, 18: 8, 19: 7, 20: 6, 21: 6, 22: 5, 23: 5, 24: 4
}
}
}
# Table 10: Cooling Load Temperature Differences (CLTD) for Conduction Through Glass (SI Units)
# Format: {hour: cltd}
self.cltd_glass = {
1: 1, 2: 0, 3: -1, 4: -2, 5: -2, 6: -2, 7: -2, 8: 0, 9: 2, 10: 4, 11: 7, 12: 9,
13: 11, 14: 13, 15: 14, 16: 14, 17: 13, 18: 12, 19: 10, 20: 7, 21: 5, 22: 3, 23: 2, 24: 1
}
# Table 13: Cooling Load Factor (CLF) with No Interior Shading
# Format: {orientation: {hour: clf}}
self.clf_glass_no_shade = {
"N": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.01, 7: 0.04, 8: 0.09, 9: 0.14, 10: 0.17, 11: 0.19, 12: 0.19,
13: 0.17, 14: 0.14, 15: 0.11, 16: 0.06, 17: 0.02, 18: 0.00, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"NE": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.08, 7: 0.18, 8: 0.23, 9: 0.22, 10: 0.16, 11: 0.11, 12: 0.08,
13: 0.06, 14: 0.05, 15: 0.04, 16: 0.02, 17: 0.01, 18: 0.00, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"E": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.09, 7: 0.26, 8: 0.36, 9: 0.36, 10: 0.27, 11: 0.17, 12: 0.12,
13: 0.09, 14: 0.07, 15: 0.05, 16: 0.03, 17: 0.02, 18: 0.00, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"SE": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.08, 7: 0.22, 8: 0.33, 9: 0.37, 10: 0.35, 11: 0.27, 12: 0.19,
13: 0.13, 14: 0.09, 15: 0.06, 16: 0.04, 17: 0.02, 18: 0.00, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"S": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.03, 7: 0.07, 8: 0.10, 9: 0.16, 10: 0.23, 11: 0.30, 12: 0.36,
13: 0.35, 14: 0.29, 15: 0.19, 16: 0.10, 17: 0.04, 18: 0.00, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"SW": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.03, 7: 0.07, 8: 0.10, 9: 0.13, 10: 0.15, 11: 0.19, 12: 0.24,
13: 0.33, 14: 0.40, 15: 0.41, 16: 0.34, 17: 0.19, 18: 0.06, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"W": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.03, 7: 0.07, 8: 0.10, 9: 0.13, 10: 0.15, 11: 0.17, 12: 0.19,
13: 0.21, 14: 0.24, 15: 0.34, 16: 0.43, 17: 0.43, 18: 0.30, 19: 0.08, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"NW": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.03, 7: 0.07, 8: 0.10, 9: 0.13, 10: 0.15, 11: 0.17, 12: 0.19,
13: 0.17, 14: 0.16, 15: 0.16, 16: 0.23, 17: 0.30, 18: 0.24, 19: 0.09, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"Horizontal": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.08, 7: 0.18, 8: 0.30, 9: 0.41, 10: 0.51, 11: 0.59, 12: 0.66,
13: 0.66, 14: 0.64, 15: 0.55, 16: 0.44, 17: 0.30, 18: 0.15, 19: 0.06, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
}
}
# Table 19: Cooling Load Factor (CLF) for People
# Format: {hours_in_space: {hour: clf}}
self.clf_people = {
"8h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.84, 10: 0.93, 11: 0.98, 12: 1.00,
13: 1.00, 14: 1.00, 15: 1.00, 16: 1.00, 17: 0.94, 18: 0.00, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"10h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.83, 10: 0.91, 11: 0.96, 12: 0.99,
13: 1.00, 14: 1.00, 15: 1.00, 16: 1.00, 17: 0.99, 18: 0.94, 19: 0.00, 20: 0.00, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"12h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.83, 10: 0.90, 11: 0.95, 12: 0.98,
13: 0.99, 14: 1.00, 15: 1.00, 16: 1.00, 17: 1.00, 18: 0.99, 19: 0.97, 20: 0.91, 21: 0.00, 22: 0.00, 23: 0.00, 24: 0.00
},
"14h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.82, 10: 0.89, 11: 0.94, 12: 0.97,
13: 0.99, 14: 1.00, 15: 1.00, 16: 1.00, 17: 1.00, 18: 1.00, 19: 0.99, 20: 0.97, 21: 0.94, 22: 0.87, 23: 0.00, 24: 0.00
},
"16h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.81, 10: 0.88, 11: 0.93, 12: 0.96,
13: 0.98, 14: 0.99, 15: 1.00, 16: 1.00, 17: 1.00, 18: 1.00, 19: 1.00, 20: 0.99, 21: 0.97, 22: 0.94, 23: 0.89, 24: 0.00
},
"18h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.81, 10: 0.87, 11: 0.92, 12: 0.95,
13: 0.97, 14: 0.99, 15: 0.99, 16: 1.00, 17: 1.00, 18: 1.00, 19: 1.00, 20: 1.00, 21: 0.99, 22: 0.97, 23: 0.94, 24: 0.89
},
"24h": {
1: 0.46, 2: 0.30, 3: 0.19, 4: 0.12, 5: 0.08, 6: 0.06, 7: 0.08, 8: 0.17, 9: 0.57, 10: 0.69, 11: 0.80, 12: 0.86,
13: 0.91, 14: 0.94, 15: 0.96, 16: 0.99, 17: 1.00, 18: 0.98, 19: 0.93, 20: 0.86, 21: 0.80, 22: 0.74, 23: 0.67, 24: 0.59
}
}
# Table 17: Cooling Load Factor (CLF) for Lights
# Format: {hours_operation: {hour: clf}}
self.clf_lights = {
"8h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.72, 10: 0.85, 11: 0.91, 12: 0.94,
13: 0.96, 14: 0.97, 15: 0.97, 16: 0.97, 17: 0.44, 18: 0.18, 19: 0.11, 20: 0.08, 21: 0.06, 22: 0.04, 23: 0.03, 24: 0.02
},
"10h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.72, 10: 0.84, 11: 0.90, 12: 0.93,
13: 0.95, 14: 0.96, 15: 0.97, 16: 0.97, 17: 0.97, 18: 0.97, 19: 0.34, 20: 0.16, 21: 0.10, 22: 0.07, 23: 0.05, 24: 0.04
},
"12h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.71, 10: 0.83, 11: 0.89, 12: 0.92,
13: 0.94, 14: 0.95, 15: 0.96, 16: 0.97, 17: 0.97, 18: 0.97, 19: 0.97, 20: 0.97, 21: 0.28, 22: 0.14, 23: 0.09, 24: 0.06
},
"14h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.70, 10: 0.82, 11: 0.88, 12: 0.91,
13: 0.93, 14: 0.95, 15: 0.96, 16: 0.96, 17: 0.97, 18: 0.97, 19: 0.97, 20: 0.97, 21: 0.97, 22: 0.97, 23: 0.23, 24: 0.12
},
"16h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.69, 10: 0.81, 11: 0.87, 12: 0.90,
13: 0.93, 14: 0.94, 15: 0.95, 16: 0.96, 17: 0.96, 18: 0.97, 19: 0.97, 20: 0.97, 21: 0.97, 22: 0.97, 23: 0.97, 24: 0.97
},
"18h": {
1: 0.19, 2: 0.11, 3: 0.08, 4: 0.06, 5: 0.04, 6: 0.03, 7: 0.02, 8: 0.02, 9: 0.69, 10: 0.80, 11: 0.86, 12: 0.89,
13: 0.92, 14: 0.93, 15: 0.95, 16: 0.95, 17: 0.96, 18: 0.96, 19: 0.97, 20: 0.97, 21: 0.97, 22: 0.97, 23: 0.97, 24: 0.97
},
"24h": {
1: 0.65, 2: 0.57, 3: 0.50, 4: 0.44, 5: 0.39, 6: 0.35, 7: 0.32, 8: 0.30, 9: 0.75, 10: 0.83, 11: 0.88, 12: 0.91,
13: 0.93, 14: 0.94, 15: 0.95, 16: 0.96, 17: 0.96, 18: 0.96, 19: 0.97, 20: 0.97, 21: 0.97, 22: 0.96, 23: 0.95, 24: 0.94
}
}
# Table 22: Cooling Load Factor (CLF) for Equipment
# Format: {hours_operation: {hour: clf}}
self.clf_equipment = {
"8h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.80, 10: 0.90, 11: 0.95, 12: 0.98,
13: 0.99, 14: 1.00, 15: 1.00, 16: 1.00, 17: 0.52, 18: 0.21, 19: 0.13, 20: 0.09, 21: 0.06, 22: 0.05, 23: 0.03, 24: 0.02
},
"10h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.79, 10: 0.89, 11: 0.94, 12: 0.97,
13: 0.98, 14: 0.99, 15: 1.00, 16: 1.00, 17: 1.00, 18: 1.00, 19: 0.40, 20: 0.19, 21: 0.12, 22: 0.08, 23: 0.06, 24: 0.04
},
"12h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.78, 10: 0.88, 11: 0.93, 12: 0.96,
13: 0.98, 14: 0.99, 15: 0.99, 16: 1.00, 17: 1.00, 18: 1.00, 19: 1.00, 20: 1.00, 21: 0.32, 22: 0.16, 23: 0.10, 24: 0.07
},
"14h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.77, 10: 0.87, 11: 0.92, 12: 0.95,
13: 0.97, 14: 0.98, 15: 0.99, 16: 0.99, 17: 1.00, 18: 1.00, 19: 1.00, 20: 1.00, 21: 1.00, 22: 1.00, 23: 0.26, 24: 0.14
},
"16h": {
1: 0.00, 2: 0.00, 3: 0.00, 4: 0.00, 5: 0.00, 6: 0.00, 7: 0.00, 8: 0.00, 9: 0.76, 10: 0.86, 11: 0.91, 12: 0.94,
13: 0.96, 14: 0.98, 15: 0.99, 16: 0.99, 17: 0.99, 18: 1.00, 19: 1.00, 20: 1.00, 21: 1.00, 22: 1.00, 23: 1.00, 24: 1.00
},
"18h": {
1: 0.22, 2: 0.13, 3: 0.09, 4: 0.06, 5: 0.05, 6: 0.03, 7: 0.02, 8: 0.02, 9: 0.75, 10: 0.85, 11: 0.90, 12: 0.94,
13: 0.96, 14: 0.97, 15: 0.98, 16: 0.99, 17: 0.99, 18: 1.00, 19: 1.00, 20: 1.00, 21: 1.00, 22: 1.00, 23: 1.00, 24: 1.00
},
"24h": {
1: 0.71, 2: 0.62, 3: 0.54, 4: 0.47, 5: 0.41, 6: 0.36, 7: 0.32, 8: 0.30, 9: 0.81, 10: 0.89, 11: 0.93, 12: 0.96,
13: 0.97, 14: 0.98, 15: 0.99, 16: 0.99, 17: 1.00, 18: 1.00, 19: 1.00, 20: 1.00, 21: 1.00, 22: 1.00, 23: 0.99, 24: 0.97
}
}
def get_daily_range_percentage(self, hour: int) -> float:
"""
Get percentage of daily range for a specific hour.
Args:
hour: Hour of the day (1-24)
Returns:
Percentage of daily range (0-100)
"""
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
return self.daily_range_percentage.get(hour, 0)
def get_cltd_flat_roof(self, roof_group: int, hour: int) -> float:
"""
Get Cooling Load Temperature Difference (CLTD) for flat roof.
Args:
roof_group: Roof construction group (1-13)
hour: Hour of the day (1-24)
Returns:
CLTD value in °C
"""
if roof_group < 1 or roof_group > 13:
raise ValueError(f"Roof group must be between 1 and 13, got {roof_group}")
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
return self.cltd_flat_roofs.get(roof_group, {}).get(hour, 0)
def get_cltd_wall(self, wall_group: str, orientation: str, hour: int) -> float:
"""
Get Cooling Load Temperature Difference (CLTD) for wall.
Args:
wall_group: Wall construction group (A-G)
orientation: Wall orientation (N, NE, E, SE, S, SW, W, NW, Horizontal)
hour: Hour of the day (1-24)
Returns:
CLTD value in °C
"""
if wall_group not in ["A", "B", "C", "D", "E", "F", "G"]:
raise ValueError(f"Wall group must be one of A, B, C, D, E, F, G, got {wall_group}")
if orientation not in ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "Horizontal"]:
raise ValueError(f"Orientation must be one of N, NE, E, SE, S, SW, W, NW, Horizontal, got {orientation}")
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
return self.cltd_walls.get(wall_group, {}).get(orientation, {}).get(hour, 0)
def get_cltd_glass(self, hour: int) -> float:
"""
Get Cooling Load Temperature Difference (CLTD) for glass conduction.
Args:
hour: Hour of the day (1-24)
Returns:
CLTD value in °C
"""
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
return self.cltd_glass.get(hour, 0)
def get_clf_glass_no_shade(self, orientation: str, hour: int) -> float:
"""
Get Cooling Load Factor (CLF) for glass with no interior shading.
Args:
orientation: Glass orientation (N, NE, E, SE, S, SW, W, NW, Horizontal)
hour: Hour of the day (1-24)
Returns:
CLF value (0-1)
"""
if orientation not in ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "Horizontal"]:
raise ValueError(f"Orientation must be one of N, NE, E, SE, S, SW, W, NW, Horizontal, got {orientation}")
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
return self.clf_glass_no_shade.get(orientation, {}).get(hour, 0)
def get_clf_people(self, hour: int, hours_occupancy: str) -> float:
"""
Get Cooling Load Factor (CLF) for people.
Args:
hour: Hour of the day (1-24)
hours_occupancy: Hours of occupancy (8h, 10h, 12h, 14h, 16h, 18h, 24h)
Returns:
CLF value (0-1)
"""
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
if hours_occupancy not in ["8h", "10h", "12h", "14h", "16h", "18h", "24h"]:
raise ValueError(f"Hours of occupancy must be one of 8h, 10h, 12h, 14h, 16h, 18h, 24h, got {hours_occupancy}")
return self.clf_people.get(hours_occupancy, {}).get(hour, 0)
def get_clf_lights(self, hour: int, hours_operation: str) -> float:
"""
Get Cooling Load Factor (CLF) for lights.
Args:
hour: Hour of the day (1-24)
hours_operation: Hours of operation (8h, 10h, 12h, 14h, 16h, 18h, 24h)
Returns:
CLF value (0-1)
"""
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
if hours_operation not in ["8h", "10h", "12h", "14h", "16h", "18h", "24h"]:
raise ValueError(f"Hours of operation must be one of 8h, 10h, 12h, 14h, 16h, 18h, 24h, got {hours_operation}")
return self.clf_lights.get(hours_operation, {}).get(hour, 0)
def get_clf_equipment(self, hour: int, hours_operation: str) -> float:
"""
Get Cooling Load Factor (CLF) for equipment.
Args:
hour: Hour of the day (1-24)
hours_operation: Hours of operation (8h, 10h, 12h, 14h, 16h, 18h, 24h)
Returns:
CLF value (0-1)
"""
if hour < 1 or hour > 24:
raise ValueError(f"Hour must be between 1 and 24, got {hour}")
if hours_operation not in ["8h", "10h", "12h", "14h", "16h", "18h", "24h"]:
raise ValueError(f"Hours of operation must be one of 8h, 10h, 12h, 14h, 16h, 18h, 24h, got {hours_operation}")
return self.clf_equipment.get(hours_operation, {}).get(hour, 0)
def calculate_corrected_cltd_wall(self, wall_group: str, orientation: str, hour: int, color: str,
month: str, latitude: str, indoor_temp: float, outdoor_temp: float) -> float:
"""
Calculate corrected CLTD for wall.
Args:
wall_group: Wall construction group (A-G)
orientation: Wall orientation (N, NE, E, SE, S, SW, W, NW, Horizontal)
hour: Hour of the day (1-24)
color: Surface color (Dark, Medium, Light)
month: Month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec)
latitude: Latitude (24N, 32N, 40N, 48N, 56N)
indoor_temp: Indoor temperature in °C
outdoor_temp: Outdoor temperature in °C
Returns:
Corrected CLTD value in °C
"""
# Get base CLTD
base_cltd = self.get_cltd_wall(wall_group, orientation, hour)
# Apply color correction
if color == "Dark":
color_factor = 1.0
elif color == "Medium":
color_factor = 0.83
elif color == "Light":
color_factor = 0.65
else:
raise ValueError(f"Color must be one of Dark, Medium, Light, got {color}")
# Apply latitude and month correction
# This is a simplified approach; in a real implementation, you would use more detailed correction factors
month_latitude_correction = 0
if latitude == "24N":
if month in ["Dec", "Jan", "Feb"]:
month_latitude_correction = -3
elif month in ["Mar", "Apr", "May", "Sep", "Oct", "Nov"]:
month_latitude_correction = -1
elif latitude == "48N":
if month in ["Dec", "Jan", "Feb"]:
month_latitude_correction = -5
elif month in ["Mar", "Apr", "May", "Sep", "Oct", "Nov"]:
month_latitude_correction = -2
elif latitude == "56N":
if month in ["Dec", "Jan", "Feb"]:
month_latitude_correction = -6
elif month in ["Mar", "Apr", "May", "Sep", "Oct", "Nov"]:
month_latitude_correction = -3
# Apply indoor temperature correction
indoor_temp_correction = 24 - indoor_temp
# Apply outdoor temperature correction
outdoor_temp_correction = (outdoor_temp - 29.4) / 2
# Calculate corrected CLTD
corrected_cltd = base_cltd * color_factor + month_latitude_correction + indoor_temp_correction + outdoor_temp_correction
return max(0, corrected_cltd)
def calculate_corrected_cltd_roof(self, roof_group: int, hour: int, color: str,
month: str, latitude: str, indoor_temp: float, outdoor_temp: float) -> float:
"""
Calculate corrected CLTD for roof.
Args:
roof_group: Roof construction group (1-13)
hour: Hour of the day (1-24)
color: Surface color (Dark, Medium, Light)
month: Month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec)
latitude: Latitude (24N, 32N, 40N, 48N, 56N)
indoor_temp: Indoor temperature in °C
outdoor_temp: Outdoor temperature in °C
Returns:
Corrected CLTD value in °C
"""
# Get base CLTD
base_cltd = self.get_cltd_flat_roof(roof_group, hour)
# Apply color correction
if color == "Dark":
color_factor = 1.0
elif color == "Medium":
color_factor = 0.83
elif color == "Light":
color_factor = 0.65
else:
raise ValueError(f"Color must be one of Dark, Medium, Light, got {color}")
# Apply latitude and month correction
# This is a simplified approach; in a real implementation, you would use more detailed correction factors
month_latitude_correction = 0
if latitude == "24N":
if month in ["Dec", "Jan", "Feb"]:
month_latitude_correction = -3
elif month in ["Mar", "Apr", "May", "Sep", "Oct", "Nov"]:
month_latitude_correction = -1
elif latitude == "48N":
if month in ["Dec", "Jan", "Feb"]:
month_latitude_correction = -5
elif month in ["Mar", "Apr", "May", "Sep", "Oct", "Nov"]:
month_latitude_correction = -2
elif latitude == "56N":
if month in ["Dec", "Jan", "Feb"]:
month_latitude_correction = -6
elif month in ["Mar", "Apr", "May", "Sep", "Oct", "Nov"]:
month_latitude_correction = -3
# Apply indoor temperature correction
indoor_temp_correction = 24 - indoor_temp
# Apply outdoor temperature correction
outdoor_temp_correction = (outdoor_temp - 29.4) / 2
# Calculate corrected CLTD
corrected_cltd = base_cltd * color_factor + month_latitude_correction + indoor_temp_correction + outdoor_temp_correction
return max(0, corrected_cltd)
def get_scl(self, orientation: str, hour: int, latitude_month: str) -> float:
"""
Get Solar Cooling Load (SCL) for glass.
Args:
orientation: Glass orientation (N, NE, E, SE, S, SW, W, NW, Horizontal)
hour: Hour of the day (1-24)
latitude_month: Latitude and month key (e.g., "40N_JUL")
Returns:
SCL value in W/m²
"""
# This is a simplified approach; in a real implementation, you would use more detailed SCL tables
# For now, we'll use a simplified calculation based on CLF and typical solar radiation values
# Get CLF for glass with no interior shading
clf = self.get_clf_glass_no_shade(orientation, hour)
# Define typical maximum solar radiation values for different orientations and latitudes
# These are simplified values; in a real implementation, you would use more detailed data
max_solar_radiation = {
"N": 200,
"NE": 600,
"E": 750,
"SE": 700,
"S": 650,
"SW": 700,
"W": 750,
"NW": 600,
"Horizontal": 950
}
# Apply latitude and month adjustment
latitude = latitude_month.split("_")[0]
month = latitude_month.split("_")[1]
latitude_month_factor = 1.0
if latitude == "24N":
if month in ["DEC", "JAN", "FEB"]:
latitude_month_factor = 0.85
elif month in ["MAR", "APR", "MAY", "SEP", "OCT", "NOV"]:
latitude_month_factor = 0.95
elif latitude == "48N":
if month in ["DEC", "JAN", "FEB"]:
latitude_month_factor = 0.65
elif month in ["MAR", "APR", "MAY", "SEP", "OCT", "NOV"]:
latitude_month_factor = 0.85
elif latitude == "56N":
if month in ["DEC", "JAN", "FEB"]:
latitude_month_factor = 0.55
elif month in ["MAR", "APR", "MAY", "SEP", "OCT", "NOV"]:
latitude_month_factor = 0.75
# Calculate SCL
scl = max_solar_radiation.get(orientation, 0) * clf * latitude_month_factor
return scl
# Create a singleton instance
ashrae_tables = ASHRAETables()