windloadpy 0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|