-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathloadfactors.py
160 lines (129 loc) · 5.35 KB
/
loadfactors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from typing import NamedTuple, Any
import json
import numpy as np
class Load(NamedTuple):
"""
A class to describe loads according to the Canadian National
Building Code (NBCC).
The loads themselves can be of any type as long as they play
well with either scalar arithmetic operators or numpy array
operators.
If array values are used, all arrays should be the same length.
"""
D: Any = 0.0
L: Any = 0.0
S: Any = 0.0
W: Any = 0.0
E: Any = 0.0
## Examples
L0 = Load() # An empty load
L1 = Load(D=2.3, L=2.4, S=0.9) # Not all fields need be entered
L2 = Load( # A load with array values
D=np.array([0.6, 1.1, 0.4]),
L=np.array([2.4, 3.6, 0.8]),
S=np.array([0.5, 1.2, 3.6]),
W=np.zeros(3),
E=np.zeros(3),
)
def open_load_combinations(filename='NBCC_vec.json') -> dict:
"""
Returns a dict representing the load combinations contained
in 'filename'.
"""
with open('NBCC_vec.json', 'r') as json_file:
nbcc_vec = json.load(json_file)
return nbcc_vec
def factored_max(load: Load, load_combinations: dict) -> Any:
"""
Returns a value representing the maximum factored load of 'load' calculated
from all of the load combinations in 'load_combinations'.
If 'load' contains scalar values, the maximum factored load is a scalar maximum.
If 'load' contains array values, the maximum factored load is the envelope of
maximum values across the input arrays in 'load'.
"""
fl = float('-inf') # acc
for load_combination, load_factors in load_combinations.items():
current_fl = factor_load(
np.array(load).T,
np.array(load_factors)
)
fl = np.maximum(current_fl, fl)
return fl
def factored_min(load: Load, load_combinations: dict) -> Any:
"""
Returns a value representing the minimum factored load of 'load' calculated
from all of the load combinations in 'load_combinations'.
If 'load' contains scalar values, the minimum factored load is a scalar minimum.
If 'load' contains array values, the minimum factored load is the envelope of
minimum values across the input arrays in 'load'.
"""
fl = float('inf') # acc
for load_combination, load_factors in load_combinations.items():
current_fl = factor_load(
np.array(load).T,
np.array(load_factors)
)
fl = np.minimum(current_fl, fl)
return fl
def factored_max_trace(load: Load, load_combinations: dict) -> Any:
"""
Returns a value representing the maximum factored load of 'load' calculated
from all of the load combinations in 'load_combinations'.
If 'load' contains scalar values, the maximum factored load is a scalar maximum.
If 'load' contains array values, the maximum factored load is the envelope of
maximum values across the input arrays in 'load'.
"""
factored_matrix = get_factored_matrix(load, load_combinations)
max_trace = np.argmax(factored_matrix, axis=0)
return max_trace
def factored_min_trace(load: Load, load_combinations: dict) -> Any:
"""
Returns a value representing the minimum factored load of 'load' calculated
from all of the load combinations in 'load_combinations'.
If 'load' contains scalar values, the minimum factored load is a scalar minimum.
If 'load' contains array values, the minimum factored load is the envelope of
minimum values across the input arrays in 'load'.
"""
factored_matrix = get_factored_matrix(load, load_combinations)
min_trace = np.argmin(factored_matrix, axis=0)
return min_trace
def get_factored_matrix(load: Load, load_combinations: dict) -> np.ndarray:
"""
Returns either a 1D or 2D array representing the loads in 'load' being
factored by 'load_combinations'. Each factored load combination is a
row in the resulting matrix.
If the values in 'load' are scalars, then a 1D matrix is returned
If the values in 'load' are 1D arrays, then a 2D matrix is returned
"""
acc = None
for idx, (load_combination, load_factors) in enumerate(
load_combinations.items()
):
current_fact = factor_load(
np.array(load).T, np.array(load_factors)
)
if idx == 0: acc = np.array([current_fact])
else: acc = np.concatenate([acc, [current_fact]])
return acc
def factor_load(load_vector: np.ndarray, factor_vector: np.ndarray) -> float:
"""
Returns the loads in 'load_vector' factored by 'factor_vector'.
Both arrays must be the same length.
"""
return load_vector @ factor_vector
def alias_to_service_loads(alias_loads: dict, alias_lookup: dict) -> Load:
"""
Returns a dictionary of service loads (i.e. loads conforming to the
code categories of DL, LL, SL, etc.) obtained from the given loads
in 'alias_loads' correlated against the load types in 'alias_lookup'.
If the load type in 'alias_loads' is not listed in 'alias_lookup', no
transformation takes place.
"""
service_loads = {}
for load_name, load_mag in alias_loads.items():
load_type = alias_lookup.get(load_name, load_name)
if load_type in service_loads:
service_loads[load_type] = service_loads[load_type] + load_mag
else:
service_loads.update({load_type: load_mag})
return Load(**service_loads)