windloadpy 0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- windloadpy/__init__.py +3 -0
- windloadpy/mapping/__init__.py +1 -0
- windloadpy/mapping/location.py +32 -0
- windloadpy/solve/__init__.py +4 -0
- windloadpy/solve/gust_factor.py +255 -0
- windloadpy/solve/header.py +16 -0
- windloadpy/solve/natural_frequency.py +31 -0
- windloadpy/solve/signage.py +126 -0
- windloadpy/solve/velocity.py +122 -0
- {windloadpy-0.1.dist-info → windloadpy-0.1.1.dist-info}/METADATA +1 -1
- windloadpy-0.1.1.dist-info/RECORD +14 -0
- windloadpy-0.1.dist-info/RECORD +0 -6
- {windloadpy-0.1.dist-info → windloadpy-0.1.1.dist-info}/WHEEL +0 -0
- {windloadpy-0.1.dist-info → windloadpy-0.1.1.dist-info}/top_level.txt +0 -0
windloadpy/__init__.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
from .location import get_map
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import requests
|
2
|
+
from IPython.display import display
|
3
|
+
from PIL import Image
|
4
|
+
from io import BytesIO
|
5
|
+
|
6
|
+
def get_map(longitude, latitude, map_style="streets-v11", zoom=12, width=600, height=400):
|
7
|
+
"""
|
8
|
+
Fetches a static map image from Mapbox API.
|
9
|
+
|
10
|
+
Parameters:
|
11
|
+
longitude (float): Longitude of the location.
|
12
|
+
latitude (float): Latitude of the location.
|
13
|
+
map_style (str): Mapbox map style (default: "streets-v11").
|
14
|
+
zoom (int): Zoom level (default: 12).
|
15
|
+
width (int): Width of the image in pixels (default: 600).
|
16
|
+
height (int): Height of the image in pixels (default: 400).
|
17
|
+
"""
|
18
|
+
mapbox_access_token = "pk.eyJ1IjoiYWxiZXJ0cGFtb25hZyIsImEiOiJjbDJsa3d1M3kwb2VtM2Nwa2Vxajd1MDdsIn0.GQx5HParNf5Ba4AngkoBAw"
|
19
|
+
|
20
|
+
url = (f"https://api.mapbox.com/styles/v1/mapbox/{map_style}/static/"
|
21
|
+
f"{longitude},{latitude},{zoom}/{width}x{height}"
|
22
|
+
f"?access_token={mapbox_access_token}")
|
23
|
+
|
24
|
+
response = requests.get(url)
|
25
|
+
if response.status_code == 200:
|
26
|
+
image = Image.open(BytesIO(response.content))
|
27
|
+
display(image)
|
28
|
+
else:
|
29
|
+
print("Error fetching map image:", response.json())
|
30
|
+
|
31
|
+
# Example usage
|
32
|
+
# get_map(120.9842, 14.5995)
|
@@ -0,0 +1,4 @@
|
|
1
|
+
from .velocity import calculate_velocity_pressure
|
2
|
+
from .gust_factor import calculate_gust
|
3
|
+
from .natural_frequency import natural_frequency
|
4
|
+
from .signage import calculate_wall_sign_ratios, calculate_reduction_factor, interpolate_force_coefficient_for_ab , calculate_wind_force
|
@@ -0,0 +1,255 @@
|
|
1
|
+
import math
|
2
|
+
|
3
|
+
CONSTANTS = {
|
4
|
+
"B": {
|
5
|
+
"alpha": 7.0,
|
6
|
+
"zg": 356.76,
|
7
|
+
"a_prime": 1 / 7,
|
8
|
+
"b_prime": 0.84,
|
9
|
+
"a_bar": 1 / 4,
|
10
|
+
"b_bar": 0.45,
|
11
|
+
"c": 0.30,
|
12
|
+
"l": 97.54,
|
13
|
+
"e": 1 / 3,
|
14
|
+
"zmin": 9.14,
|
15
|
+
},
|
16
|
+
"C": {
|
17
|
+
"alpha": 9.5,
|
18
|
+
"zg": 274.32,
|
19
|
+
"a_prime": 1 / 9.5,
|
20
|
+
"b_prime": 1.00,
|
21
|
+
"a_bar": 1 / 6.5,
|
22
|
+
"b_bar": 0.65,
|
23
|
+
"c": 0.20,
|
24
|
+
"l": 152.40,
|
25
|
+
"e": 1 / 5,
|
26
|
+
"zmin": 4.57,
|
27
|
+
},
|
28
|
+
"D": {
|
29
|
+
"alpha": 11.5,
|
30
|
+
"zg": 213.36,
|
31
|
+
"a_prime": 1 / 11.5,
|
32
|
+
"b_prime": 1.07,
|
33
|
+
"a_bar": 1 / 9,
|
34
|
+
"b_bar": 0.80,
|
35
|
+
"c": 0.15,
|
36
|
+
"l": 198.12,
|
37
|
+
"e": 1 / 8,
|
38
|
+
"zmin": 2.13,
|
39
|
+
},
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
class calculate_gust:
|
44
|
+
"""
|
45
|
+
exposure : exposure type of wind [B,C,D]
|
46
|
+
wind_speed : wind speed in m/s
|
47
|
+
b_length : milimeters
|
48
|
+
l_length : milimeters
|
49
|
+
"""
|
50
|
+
def __init__(self,exposure,mean_height,wind_speed,b_length,l_length,nat_freq):
|
51
|
+
self.exposure = exposure
|
52
|
+
self.mean_height = mean_height
|
53
|
+
self.constants = CONSTANTS
|
54
|
+
self.V = wind_speed * 0.2777777778 #convert to m/s
|
55
|
+
self.B = b_length
|
56
|
+
self.L = l_length
|
57
|
+
self.n1 = nat_freq
|
58
|
+
self.type = type
|
59
|
+
|
60
|
+
def aerodynamicHeight(self):
|
61
|
+
zmin = self.constants[self.exposure]["zmin"]
|
62
|
+
z_bar = max(0.6 * self.mean_height, zmin)
|
63
|
+
units = ""
|
64
|
+
report = '''
|
65
|
+
\\text{ MAX}\\left( 0.6 \\times h, z_{min}\\right) <br>
|
66
|
+
|
67
|
+
'''
|
68
|
+
results = {
|
69
|
+
"value" : z_bar,
|
70
|
+
"units" : units,
|
71
|
+
"report" : report
|
72
|
+
}
|
73
|
+
return results
|
74
|
+
|
75
|
+
def turbulenceIntensity(self):
|
76
|
+
c = self.constants[self.exposure]["c"]
|
77
|
+
Iz_bar = c * math.pow(10/self.aerodynamicHeight()['value'],1/ 6)
|
78
|
+
results = {
|
79
|
+
"value" : Iz_bar,
|
80
|
+
# "units" : units,
|
81
|
+
# "report" : report
|
82
|
+
}
|
83
|
+
return results
|
84
|
+
|
85
|
+
def scaleOfTurbulence(self):
|
86
|
+
l_val = self.constants[self.exposure]["l"]
|
87
|
+
e = self.constants[self.exposure]["e"]
|
88
|
+
Lz_bar = l_val * math.pow(self.aerodynamicHeight()['value']/10,e)
|
89
|
+
# return Lz_bar
|
90
|
+
results = {
|
91
|
+
"value" : Lz_bar,
|
92
|
+
# "units" : units,
|
93
|
+
# "report" : report
|
94
|
+
}
|
95
|
+
return results
|
96
|
+
|
97
|
+
|
98
|
+
def meanWindSpeed(self):
|
99
|
+
a_bar = self.constants[self.exposure]["a_bar"]
|
100
|
+
b_bar = self.constants[self.exposure]["b_bar"]
|
101
|
+
Vz_bar = b_bar * math.pow(self.aerodynamicHeight()['value']/10,a_bar) * self.V
|
102
|
+
results = {
|
103
|
+
"value" : Vz_bar,
|
104
|
+
# "units" : units,
|
105
|
+
# "report" : report
|
106
|
+
}
|
107
|
+
return results
|
108
|
+
|
109
|
+
def gustResponsePeakResponse(self):
|
110
|
+
val = 2.0 * math.log(3600.0 * self.n1)
|
111
|
+
gR = math.sqrt(val) + 0.577 / math.sqrt(val)
|
112
|
+
results = {
|
113
|
+
"value" : gR,
|
114
|
+
# "units" : units,
|
115
|
+
# "report" : report
|
116
|
+
}
|
117
|
+
return results
|
118
|
+
|
119
|
+
def backgroundResponse(self):
|
120
|
+
|
121
|
+
background_response_init = 1.0 + 0.63 * math.pow( (self.B + self.mean_height)/self.scaleOfTurbulence()['value'],0.63)
|
122
|
+
background_response = math.sqrt(1.0/background_response_init)
|
123
|
+
results = {
|
124
|
+
"value" : background_response,
|
125
|
+
# "units" : units,
|
126
|
+
# "report" : report
|
127
|
+
}
|
128
|
+
return results
|
129
|
+
|
130
|
+
def reducedFrequency(self):
|
131
|
+
ni = (self.n1 * self.scaleOfTurbulence()['value']) / self.meanWindSpeed()['value']
|
132
|
+
results = {
|
133
|
+
"value" : ni,
|
134
|
+
# "units" : units,
|
135
|
+
# "report" : report
|
136
|
+
}
|
137
|
+
return results
|
138
|
+
|
139
|
+
def sizeFactorEffect(self):
|
140
|
+
dimensions = [
|
141
|
+
{"name": "h", "value": self.mean_height, "constant": 4.6},
|
142
|
+
{"name": "B", "value": self.B, "constant": 4.6},
|
143
|
+
{"name": "L", "value": self.L, "constant": 15.4},
|
144
|
+
]
|
145
|
+
R_values = {}
|
146
|
+
|
147
|
+
for dim in dimensions:
|
148
|
+
eta = dim["constant"] * self.n1 * (dim["value"] / self.meanWindSpeed()['value'])
|
149
|
+
term_exp = math.exp(-2.0 * eta)
|
150
|
+
Rsizefactor = (1.0 / eta) - ((1.0 / (2.0 * eta * eta)) * (1.0 - term_exp))
|
151
|
+
R_values[f"R{dim['name']}"] = Rsizefactor
|
152
|
+
|
153
|
+
results = {
|
154
|
+
"rh" : {
|
155
|
+
"value" : R_values['Rh'],
|
156
|
+
"units" : "",
|
157
|
+
"report" : ""
|
158
|
+
},
|
159
|
+
"rB" : {
|
160
|
+
"value" : R_values['RB'],
|
161
|
+
"units" : "",
|
162
|
+
"report" : ""
|
163
|
+
},
|
164
|
+
"rL" : {
|
165
|
+
"value" : R_values['RL'],
|
166
|
+
"units" : "",
|
167
|
+
"report" : ""
|
168
|
+
}
|
169
|
+
}
|
170
|
+
return results
|
171
|
+
|
172
|
+
def resonantResponseFactor(self,beta_input = 0.010):
|
173
|
+
'''
|
174
|
+
concrete structure = 0.015
|
175
|
+
steel = 0.010
|
176
|
+
'''
|
177
|
+
r_factor = self.sizeFactorEffect()
|
178
|
+
|
179
|
+
beta = beta_input
|
180
|
+
rn = (7.47 * self.reducedFrequency()["value"] ) / math.pow(1 + 10.3 * self.reducedFrequency()["value"], 5 / 3)
|
181
|
+
|
182
|
+
r_value = math.sqrt(
|
183
|
+
(1.0 / beta)
|
184
|
+
* rn
|
185
|
+
* r_factor["rh"]["value"]
|
186
|
+
* r_factor["rB"]["value"]
|
187
|
+
* (0.53 + 0.47 * r_factor["rL"]["value"])
|
188
|
+
)
|
189
|
+
|
190
|
+
results = {
|
191
|
+
"rn" : {
|
192
|
+
"value" : rn,
|
193
|
+
"units" : "",
|
194
|
+
"report" : ""
|
195
|
+
},
|
196
|
+
"r" : {
|
197
|
+
"value" : r_value,
|
198
|
+
"units" : "",
|
199
|
+
"report" : ""
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
return results
|
204
|
+
|
205
|
+
def gust_factor(self):
|
206
|
+
#CONSTANT
|
207
|
+
GQ = 3.4
|
208
|
+
GV = 3.4
|
209
|
+
COEFFICIENT = 0.925
|
210
|
+
|
211
|
+
#Factors
|
212
|
+
Q_factor = self.backgroundResponse()["value"]
|
213
|
+
gR = self.gustResponsePeakResponse()["value"]
|
214
|
+
R_factor = self.resonantResponseFactor()["r"]["value"]
|
215
|
+
Iz_bar = self.turbulenceIntensity()["value"]
|
216
|
+
|
217
|
+
if(self.n1 <= 1):
|
218
|
+
Gfa = (math.pow(GQ,2)*math.pow(Q_factor,2)) + (math.pow(gR,2) * math.pow(R_factor,2))
|
219
|
+
Gf = COEFFICIENT * ((1.0 + (1.7*Iz_bar*math.sqrt(Gfa)))/ (1.0 + (1.7*GV*Iz_bar)))
|
220
|
+
units = ""
|
221
|
+
results = {
|
222
|
+
"value" : Gf,
|
223
|
+
"units" : units,
|
224
|
+
# "report" : report
|
225
|
+
}
|
226
|
+
else:
|
227
|
+
numerator = 1.0 + 0.7 * GQ * self.turbulenceIntensity()['value'] * self.backgroundResponse()['value']
|
228
|
+
denominator = 1.0 + 0.7 * GV * self.turbulenceIntensity()['value']
|
229
|
+
gust_factor = COEFFICIENT * (numerator / denominator)
|
230
|
+
units = ""
|
231
|
+
results = {
|
232
|
+
"value" : gust_factor,
|
233
|
+
"units" : units,
|
234
|
+
# "report" : report
|
235
|
+
}
|
236
|
+
return results
|
237
|
+
|
238
|
+
# kzt =1
|
239
|
+
# kd = 0.85
|
240
|
+
# wind_speed = 240
|
241
|
+
# exposure = "D"
|
242
|
+
# mean_height = 24.50
|
243
|
+
# na_value = 0.90
|
244
|
+
# # type = "rigid"
|
245
|
+
|
246
|
+
# wind_velocity = calculate_gust(exposure,mean_height,wind_speed,100,100,na_value)
|
247
|
+
# # print(wind_velocity.aerodynamicHeight())
|
248
|
+
# # print(wind_velocity.turbulenceIntensity())
|
249
|
+
# # print(wind_velocity.scaleOfTurbulence())
|
250
|
+
# # print(wind_velocity.meanWindSpeed())
|
251
|
+
# # print(wind_velocity.gustResponsePeakResponse())
|
252
|
+
# # print(wind_velocity.backgroundResponse())
|
253
|
+
# # # print(wind_velocity.reducedFrequency())
|
254
|
+
# print(wind_velocity.sizeFactorEffect())
|
255
|
+
# print(wind_velocity.gust_factor())
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import math
|
2
|
+
|
3
|
+
def radtodegree():
|
4
|
+
results = 180 / math.pi
|
5
|
+
return results
|
6
|
+
|
7
|
+
def header():
|
8
|
+
results = """
|
9
|
+
<h1><center><strong>WIND CALCULATION REPORT</strong></center></h1>
|
10
|
+
<h2>Reference</h2>
|
11
|
+
<ul>
|
12
|
+
<li>Association of Structural Engineers of the Philippines 2015 Edition, National Structural Code of the Philippines Volume 1, Quezon City, Philippines.</li>
|
13
|
+
<li>American Society of Civil Engineering, ASCE 7-10, USA</li>
|
14
|
+
</ul>
|
15
|
+
"""
|
16
|
+
return results
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import math
|
2
|
+
|
3
|
+
def natural_frequency(material_type, mean_height):
|
4
|
+
report = ""
|
5
|
+
|
6
|
+
if material_type == "concrete":
|
7
|
+
report += "<h4>For Concrete buildings</h4>"
|
8
|
+
na = 14.93 / math.pow(mean_height,0.9)
|
9
|
+
report += f"<center> \\( n_{{ a }} = \\frac {{ 14.93 }}{{ \\text{{h}}^{{0.9}} }} \\) </center>"
|
10
|
+
report += f"<center> \\( n_{{a }} = \\frac {{ 14.93 }}{{ \\left( {mean_height:.2f} \\right)^{{0.9}} }} \\) </center>"
|
11
|
+
elif material_type == "steel":
|
12
|
+
report += "<h4>For structural steel moment-resisting-frame buildings</h4>"
|
13
|
+
na = 8.58 / math.pow(mean_height,0.8)
|
14
|
+
report += f"<center> \\( n_{{ a }} = \\frac {{ 8.58 }}{{ \\text{{h}}^{{0.8}} }} \\) </center>"
|
15
|
+
report += f"<center> \\( n_{{ a }} = \\frac {{ 8.58 }}{{ \\left( {mean_height:.2f} \\right)^{{0.8}} }} \\) </center>"
|
16
|
+
elif material_type == "others":
|
17
|
+
na = 22.86 / mean_height
|
18
|
+
report += f"<center> \\( n_{{ a }} = \\frac {{ 22.86 }}{{ \\text{{h}} }} \\) </center>"
|
19
|
+
report += f"<center> \\( n_{{ a }} = \\frac {{ 22.86 }}{{ {mean_height:.2f} }} \\) </center>"
|
20
|
+
|
21
|
+
behavior = "rigid" if na >= 1.0 else "flexible"
|
22
|
+
# report += f"<center>\\( n_{{a}} = {na:.3f} \\therefore \\text{{Structure is {remarks}}} \\)</center>"
|
23
|
+
|
24
|
+
return {
|
25
|
+
"report": report,
|
26
|
+
"value": na,
|
27
|
+
"unit" : "hz",
|
28
|
+
"behavior": behavior
|
29
|
+
}
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
def calculate_wall_sign_ratios(h, s, B):
|
2
|
+
"""
|
3
|
+
Calculates the ratios of the vertical dimension to wall height (s/h)
|
4
|
+
and the horizontal dimension to vertical dimension (B/s).
|
5
|
+
|
6
|
+
:param h: The height of the wall.
|
7
|
+
:param s: The vertical dimension.
|
8
|
+
:param B: The horizontal dimension.
|
9
|
+
:return: A dict with keys:
|
10
|
+
- "clearance": s/h (rounded to 5 decimals)
|
11
|
+
- "aspect": B/s (rounded to 5 decimals)
|
12
|
+
"""
|
13
|
+
s_over_h = s / h
|
14
|
+
b_over_s = B / s
|
15
|
+
|
16
|
+
return {
|
17
|
+
"clearance": round(s_over_h, 5),
|
18
|
+
"aspect": round(b_over_s, 5),
|
19
|
+
}
|
20
|
+
|
21
|
+
def calculate_reduction_factor(epsilon):
|
22
|
+
"""
|
23
|
+
Calculates the reduction factor δ = 1 - (1 - ε)^(1.5).
|
24
|
+
|
25
|
+
:param epsilon: A value between 0 and 1.
|
26
|
+
:return: The reduction factor (rounded to 5 decimals).
|
27
|
+
"""
|
28
|
+
if epsilon < 0 or epsilon > 1:
|
29
|
+
raise ValueError("Epsilon (ε) must be between 0 and 1.")
|
30
|
+
|
31
|
+
delta = 1 - (1 - epsilon) ** 1.5
|
32
|
+
return round(delta, 5)
|
33
|
+
|
34
|
+
def interpolate_force_coefficient_for_ab(aspect_ratio, clearance_ratio, delta):
|
35
|
+
"""
|
36
|
+
Performs a bilinear interpolation of force coefficients (C_f) based on:
|
37
|
+
- aspect_ratio: (B/s)
|
38
|
+
- clearance_ratio: (s/h)
|
39
|
+
- delta: The reduction factor.
|
40
|
+
|
41
|
+
Uses pre-defined tables of aspect_ratios, clearance_ratios, and force_coefficients.
|
42
|
+
|
43
|
+
:param aspect_ratio: B/s
|
44
|
+
:param clearance_ratio: s/h
|
45
|
+
:param delta: reduction factor δ
|
46
|
+
:return: A dict with keys:
|
47
|
+
- "cfa": δ * interpolated_value (Case A)
|
48
|
+
- "cfb": δ * interpolated_value (Case B)
|
49
|
+
"""
|
50
|
+
aspect_ratios = [0.05, 0.1, 0.2, 0.5, 1, 2, 4, 5, 10, 20, 30, 45]
|
51
|
+
clearance_ratios = [1, 0.9, 0.7, 0.5, 0.3, 0.2, 0.16]
|
52
|
+
force_coefficients = [
|
53
|
+
[1.80, 1.70, 1.65, 1.55, 1.45, 1.40, 1.35, 1.35, 1.30, 1.30, 1.30, 1.30], # clearance = 1
|
54
|
+
[1.85, 1.75, 1.70, 1.60, 1.55, 1.50, 1.45, 1.45, 1.40, 1.40, 1.40, 1.40], # clearance = 0.9
|
55
|
+
[1.90, 1.85, 1.75, 1.70, 1.65, 1.60, 1.55, 1.55, 1.55, 1.55, 1.55, 1.55], # clearance = 0.7
|
56
|
+
[1.95, 1.85, 1.80, 1.75, 1.75, 1.70, 1.70, 1.70, 1.70, 1.70, 1.70, 1.75], # clearance = 0.5
|
57
|
+
[1.95, 1.90, 1.85, 1.80, 1.80, 1.80, 1.80, 1.80, 1.80, 1.85, 1.85, 1.85], # clearance = 0.3
|
58
|
+
[1.95, 1.90, 1.85, 1.80, 1.80, 1.80, 1.80, 1.80, 1.85, 1.90, 1.90, 1.95], # clearance = 0.2
|
59
|
+
[1.95, 1.90, 1.85, 1.85, 1.80, 1.80, 1.85, 1.85, 1.85, 1.90, 1.90, 1.95], # clearance = 0.16
|
60
|
+
]
|
61
|
+
|
62
|
+
def find_indices(arr, value):
|
63
|
+
"""
|
64
|
+
Finds the pair of indices in 'arr' between which 'value' lies.
|
65
|
+
If value is outside the range, returns the last pair of indices.
|
66
|
+
"""
|
67
|
+
for i in range(len(arr) - 1):
|
68
|
+
if arr[i] <= value <= arr[i + 1]:
|
69
|
+
return i, i + 1
|
70
|
+
return len(arr) - 2, len(arr) - 1
|
71
|
+
|
72
|
+
# Find indices for aspect ratio
|
73
|
+
i1, i2 = find_indices(aspect_ratios, aspect_ratio)
|
74
|
+
x1, x2 = aspect_ratios[i1], aspect_ratios[i2]
|
75
|
+
|
76
|
+
# Find indices for clearance ratio
|
77
|
+
j1, j2 = find_indices(clearance_ratios, clearance_ratio)
|
78
|
+
y1, y2 = clearance_ratios[j1], clearance_ratios[j2]
|
79
|
+
|
80
|
+
# Corner values for bilinear interpolation
|
81
|
+
Q11 = force_coefficients[j1][i1]
|
82
|
+
Q12 = force_coefficients[j1][i2]
|
83
|
+
Q21 = force_coefficients[j2][i1]
|
84
|
+
Q22 = force_coefficients[j2][i2]
|
85
|
+
|
86
|
+
# Bilinear interpolation
|
87
|
+
denominator = (x2 - x1) * (y2 - y1)
|
88
|
+
# Prevent division by zero if input is outside table range in a degenerate way
|
89
|
+
if abs(denominator) < 1e-12:
|
90
|
+
interpolated_value = Q11 # fallback or handle it differently if needed
|
91
|
+
else:
|
92
|
+
interpolated_value = (
|
93
|
+
Q11 * (x2 - aspect_ratio) * (y2 - clearance_ratio)
|
94
|
+
+ Q21 * (aspect_ratio - x1) * (y2 - clearance_ratio)
|
95
|
+
+ Q12 * (x2 - aspect_ratio) * (clearance_ratio - y1)
|
96
|
+
+ Q22 * (aspect_ratio - x1) * (clearance_ratio - y1)
|
97
|
+
) / denominator
|
98
|
+
|
99
|
+
cfa = delta * interpolated_value
|
100
|
+
cfb = delta * interpolated_value
|
101
|
+
|
102
|
+
return {
|
103
|
+
"cfa": cfa,
|
104
|
+
"cfb": cfb,
|
105
|
+
}
|
106
|
+
|
107
|
+
def calculate_wind_force(qh, G, CfA, As):
|
108
|
+
"""
|
109
|
+
Calculates the design wind force on a pylon.
|
110
|
+
|
111
|
+
:param qh: The velocity pressure at height h.
|
112
|
+
:param G: The gust effect factor.
|
113
|
+
:param CfA: The force coefficient (Cf) as obtained from tables, etc.
|
114
|
+
:param As: The projected area of the structure.
|
115
|
+
:param load_case_type: Either "A" or "B" (or a similar descriptor).
|
116
|
+
:param B: Horizontal dimension (used if needed for eccentricity).
|
117
|
+
:return: The design wind force (float).
|
118
|
+
"""
|
119
|
+
# Design wind force
|
120
|
+
force = qh * G * CfA * As
|
121
|
+
|
122
|
+
# If needed for case "B", you could calculate eccentricity = 0.2 * B
|
123
|
+
# but it does not affect the force itself in this function unless
|
124
|
+
# you incorporate it in further calculations.
|
125
|
+
|
126
|
+
return force
|
@@ -0,0 +1,122 @@
|
|
1
|
+
import math
|
2
|
+
import numpy as np
|
3
|
+
import pandas as pd
|
4
|
+
import matplotlib.pyplot as plt
|
5
|
+
|
6
|
+
class calculate_velocity_pressure:
|
7
|
+
def __init__(self, kzt, kd, wind_speed, exposure, mean_height):
|
8
|
+
self.kzt = kzt
|
9
|
+
self.kd = kd
|
10
|
+
self.wind_speed = wind_speed * 0.2777777778 # Convert to m/s
|
11
|
+
self.exposure = exposure
|
12
|
+
self.mean_height = mean_height
|
13
|
+
self.constants = {
|
14
|
+
"B": {"zg": 365.76, "alpha": 7},
|
15
|
+
"C": {"zg": 274.32, "alpha": 9.5},
|
16
|
+
"D": {"zg": 213.36, "alpha": 11.5}
|
17
|
+
}
|
18
|
+
self.zg = self.constants[exposure]["zg"]
|
19
|
+
self.alpha = self.constants[exposure]["alpha"]
|
20
|
+
self.qzkz = 0.613 * self.kzt * self.kd * self.wind_speed ** 2
|
21
|
+
self.height_data = [4.5, 6, 7.5, 9, 12, 15, 18, 21, 24, 27, 30, 36, 42, 48, 54, 60, 75, 90, 105, 120, 135, 150]
|
22
|
+
self.height_index = self._filter_height_data()
|
23
|
+
|
24
|
+
def _filter_height_data(self):
|
25
|
+
height_index = [index for index in self.height_data if index < self.mean_height]
|
26
|
+
height_index.append(self.mean_height)
|
27
|
+
return height_index
|
28
|
+
def calculate_qzkzvalue(self):
|
29
|
+
qzkz = 0.613 * self.kzt * self.kd * math.pow(self.wind_speed,2)
|
30
|
+
return qzkz
|
31
|
+
|
32
|
+
def generate_qzkzdata(self):
|
33
|
+
|
34
|
+
height_index = []
|
35
|
+
kzi_arr = [] #store kzi value
|
36
|
+
qzi_arr = [] #store the qzi value
|
37
|
+
|
38
|
+
height_data = [0,4.5, 6, 7.5, 9, 12, 15, 18, 21, 24, 27, 30, 36, 42, 48, 54, 60, 75, 90, 105, 120, 135, 150]
|
39
|
+
for i in height_data:
|
40
|
+
if i < self.mean_height:
|
41
|
+
height_index.append(i)
|
42
|
+
|
43
|
+
height_index.append(self.mean_height)
|
44
|
+
|
45
|
+
for height in height_index:
|
46
|
+
alpha_power = 2 / self.alpha
|
47
|
+
Kz_part_one = height / self.zg
|
48
|
+
if height == 0:
|
49
|
+
Kz_part_one = 4.5 / self.zg
|
50
|
+
Kzi = 2.01 * math.pow(Kz_part_one,alpha_power)
|
51
|
+
else:
|
52
|
+
# Kz_part_one = 4.5 / self.zg
|
53
|
+
Kzi = 2.01 * math.pow(Kz_part_one,alpha_power)
|
54
|
+
qzi = Kzi * self.calculate_qzkzvalue()
|
55
|
+
kzi_arr.append(Kzi)
|
56
|
+
qzi_arr.append(qzi)
|
57
|
+
final_data = [height_index,kzi_arr,qzi_arr]
|
58
|
+
return final_data
|
59
|
+
|
60
|
+
def report(self):
|
61
|
+
'''
|
62
|
+
Generate the report using the wind velocity
|
63
|
+
'''
|
64
|
+
##For qzkz
|
65
|
+
report = ""
|
66
|
+
report += "<h2>Velocity Pressure</h2>"
|
67
|
+
report += "<center> \\( q_{z } = 0.613 \\times K_{ z } \\times K_{ zt } \\times K_{ d } \\times \\left( V \\right)^{2} \\) </center>"
|
68
|
+
report += f"<center> \\( q_{{z}} = 0.613 \\times K_{{z}} \\times {self.kzt:.2f} \\times {self.kd:.2f} \\times \\left( {self.wind_speed:.2f} \\frac{{m}}{{s}} \\right)^{2} \\) </center>"
|
69
|
+
report += f"<center> \\( q_{{z}} = {self.calculate_qzkzvalue():.2f} \\times K_{{ z }} \\text{{ }} \\frac{{N}}{{m^{2}}} \\text{{ or }} P_{{a}} \\) </center>"
|
70
|
+
|
71
|
+
return report
|
72
|
+
|
73
|
+
|
74
|
+
def plot(self):
|
75
|
+
"""
|
76
|
+
Generate three arrays (Height, Kzi, Qzi) from self.generate_qzkzdata(),
|
77
|
+
and create a Matplotlib Figure without using Seaborn.
|
78
|
+
"""
|
79
|
+
|
80
|
+
# Retrieve data
|
81
|
+
data = self.generate_qzkzdata()
|
82
|
+
ht_arr = data[0] # Array of Heights (Y-axis)
|
83
|
+
qzi_arr = data[2] # Array of Wind Velocity Pressures (X-axis)
|
84
|
+
|
85
|
+
# Create figure and axis with improved size
|
86
|
+
fig, ax = plt.subplots(figsize=(8, 6), dpi=150)
|
87
|
+
|
88
|
+
# Plot with improved styling
|
89
|
+
ax.plot(qzi_arr, ht_arr, color='black', linewidth=2.5, linestyle='-')
|
90
|
+
|
91
|
+
# Label axes and title with enhanced visibility
|
92
|
+
ax.set_xlabel('Wind Velocity Pressure (Pa)', fontsize=14, fontweight='bold')
|
93
|
+
ax.set_ylabel('Height (m)', fontsize=14, fontweight='bold')
|
94
|
+
ax.set_title('Wind Pressure vs. Height Profile', fontsize=16, fontweight='bold')
|
95
|
+
|
96
|
+
# Customize tick labels for readability
|
97
|
+
ax.tick_params(axis='both', labelsize=12)
|
98
|
+
|
99
|
+
# Set x-axis to start at 0
|
100
|
+
ax.set_xlim(left=0)
|
101
|
+
|
102
|
+
# Enable professional grid style
|
103
|
+
ax.grid(True, linestyle='--', alpha=0.6, linewidth=0.8)
|
104
|
+
|
105
|
+
# Improve layout
|
106
|
+
plt.tight_layout()
|
107
|
+
|
108
|
+
# Return figure for further use
|
109
|
+
return fig
|
110
|
+
# return fig
|
111
|
+
|
112
|
+
|
113
|
+
# kzt =1
|
114
|
+
# kd = 0.85
|
115
|
+
# wind_speed = 240
|
116
|
+
# exposure = "B"
|
117
|
+
# mean_height = 24
|
118
|
+
|
119
|
+
# wind_velocity = calculate_velocity_pressure(kzt,kd,wind_speed,exposure,mean_height)
|
120
|
+
# print(wind_velocity.calculate_qzkzvalue())
|
121
|
+
# print(wind_velocity.generate_qzkzdata())
|
122
|
+
# print(wind_velocity.plot())
|
@@ -0,0 +1,14 @@
|
|
1
|
+
windloadpy/__init__.py,sha256=az3mo4y1O_p1_rXkGR3pLWtlg6RWMnIDVuZiEbofHfg,233
|
2
|
+
windloadpy/module.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
windloadpy/mapping/__init__.py,sha256=JjIts3E5sOwHm1aXMM8x4MECeqLPkEHk5MRIhC4CUiw,30
|
4
|
+
windloadpy/mapping/location.py,sha256=_k0381-lebZ3WCbLGP-oakwovWgyfIL6PqAcVsmthTY,1244
|
5
|
+
windloadpy/solve/__init__.py,sha256=ueB_GBCeKNVAwQ5ce1JwKeSnkGwYGYD-Hf4Ps6itEk0,278
|
6
|
+
windloadpy/solve/gust_factor.py,sha256=-g0A0fZA_T3KqCn1F4S0e1sBWUfoqdTLsff9a4hZEd8,7770
|
7
|
+
windloadpy/solve/header.py,sha256=XIZNFdl8pS9HADHai4x24ERLkjIzIMjzJxLyAR0vjOY,537
|
8
|
+
windloadpy/solve/natural_frequency.py,sha256=7S68xupzzGp6p1JVVM68dgp-RyeOebHEFPqNiMX2bUo,1423
|
9
|
+
windloadpy/solve/signage.py,sha256=bo8dS_wZ783o0Ib_cVUt_8PvAef6Fs2u__LCrhn_740,4906
|
10
|
+
windloadpy/solve/velocity.py,sha256=SExGJx_Gf5ZGqaoI0iMM9goCaz925msdgfePidhH7IM,4646
|
11
|
+
windloadpy-0.1.1.dist-info/METADATA,sha256=QDthcl9o_GJwaqAUYHH24sLwNF0WKxnxvyFqMuWHu2U,482
|
12
|
+
windloadpy-0.1.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
13
|
+
windloadpy-0.1.1.dist-info/top_level.txt,sha256=iRqSvDB0DOBDBTbTimA1ySiXGte-86P0W_4UGZDLKjM,11
|
14
|
+
windloadpy-0.1.1.dist-info/RECORD,,
|
windloadpy-0.1.dist-info/RECORD
DELETED
@@ -1,6 +0,0 @@
|
|
1
|
-
windloadpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
windloadpy/module.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
windloadpy-0.1.dist-info/METADATA,sha256=8hV0gLC55TZXUKPuDn1BRawYm-ZDPRh4hedO_-NBl_4,480
|
4
|
-
windloadpy-0.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
5
|
-
windloadpy-0.1.dist-info/top_level.txt,sha256=iRqSvDB0DOBDBTbTimA1ySiXGte-86P0W_4UGZDLKjM,11
|
6
|
-
windloadpy-0.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|