Python_Matplotlib极坐标系作全向反应谱图

Python_Matplotlib极坐标系作全向反应谱图

\[ a_\theta(t)=a_x(t)\cos\theta+a_y(t)\sin\theta \]

  1. 通过NS和EW向地震波生成360度全方向地震波
  2. 计算出该条地震动反应谱
  3. 在极坐标系上使用等高线工具绘制全向反应谱图
1
2
3
4
5
def graph(theta,r,value,name):#theta,r,value,命名(包含路径)
fig, axes = plt.subplots(subplot_kw=dict(projection='polar'),figsize=(10,10))
contourplot = axes.contourf(theta,r,value,cmap=plt.cm.jet)
plt.colorbar(contourplot, shrink=.6, pad=0.08)
plt.savefig(name)
  • 只需要计算0-180度反应谱去最大值,\(\theta+180\)取最小值即可,减少计算量
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
import os
import math
import numpy as np
import matplotlib.pyplot as plt
import scipy
import pandas as pd
from docx import Document
from docx.shared import Inches,Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.table import WD_ALIGN_VERTICAL
from docx import shared
import _thread
import time

class spectrum:
sw=np.array([]) #地震波a
v=np.array([]) #地震波速度
su=np.array([]) #地震波位移
tf=np.array([]) #调幅后地震波a

u=np.array([])
u0=np.array([])
u00=np.array([])

#真最大最小值用于区分方向时使用
saT=np.array([])
sa=np.array([]) #谱加速度
sa_truemax=np.array([])# 真最大值
sa_truemin=np.array([])# 真最小值

sv=np.array([]) #谱速度
sv_truemax=np.array([])# 真最大值
sv_truemin=np.array([])# 真最小值

sd=np.array([]) #谱位移
sd_truemax=np.array([])# 真最大值
sd_truemin=np.array([])# 真最小值

PGA=0
PGD=0
PGV=0
t=0
id=""
x=np.array([]) #时程


def __init__(self,direction,t):#路径
self.t=t
self.sw=np.array(direction)
#基线修正
mean=self.sw.mean() #记录的平均
self.sw=self.sw-mean
self.x=np.linspace(0,self.t*len(self.sw),len(self.sw))
return

def newmark_beta(self,T,ksi=0.05,gamma=0.5,beta=0.25):#步长,周期,地震波
if T==0:
T=0.00000001
n=len(self.sw)
m=1.0
c=2*m*ksi*(2*np.pi/T)
#分别为加速度,速度,位移
u00=np.zeros(n)
u0=np.zeros(n)
u=np.zeros(n)
k=(2*np.pi/T)**2*m
u00[0]=-self.sw[0]-c*u0[0]-k*u[0]
a1=m/(beta*(self.t**2))+gamma*c/(beta*self.t)
a2=m/(beta*self.t)+(gamma/beta-1)*c
a3=(1/(2*beta)-1)*m+self.t*(gamma/(2*beta)-1)*c
k_hat=k+a1 #k^/hat

for i in range(1,n):
p_hat=-self.sw[i]+a1*u[i-1]+a2*u0[i-1]+a3*u00[i-1]
u[i]=p_hat/k_hat
u0[i]=gamma/(beta*self.t)*(u[i]-u[i-1])+(1-gamma/beta)*u0[i-1]+self.t*(1-gamma/(2*beta))*u00[i-1]
u00[i]=1/(beta*(self.t**2))*(u[i]-u[i-1])-u0[i-1]/(beta*self.t)-(1/(2*beta)-1)*u00[i-1]
self.u=u
self.u0=u0
self.u00=u00+self.sw
return u,u0,u00+self.sw

def central_difference(self,T,ksi=0.05,gamma=0.5,beta=0.25):
m=1.0
n=len(self.sw)
u00=np.zeros(n)
u0=np.zeros(n)
u=np.zeros(n+1)
c=2*m*ksi*(2*np.pi/T)
k=(2*np.pi/T)**2*m
u00[0]=-self.sw[0]-c*u0[0]-k*u[0]
u_1=u[0]-self.t*u0[0]+self.t**2*u00[0]/2
k_hat=m/(self.t**2)+c/(2*self.t)
a=m/(self.t**2)-c/(2*self.t)
b=k-2*m/(self.t**2)
for i in range(n):
if i==1:
p_hat=-self.sw[i]-a*u_1-b*u[i]
else:
p_hat=-self.sw[i]-a*u[i-1]-b*u[i]
u[i+1]=p_hat/k_hat
u0[i]=(u[i+1]-u[i-1])/(2*self.t)
u00[i]=(u[i+1]-2*u[i]+u[i-1])/(self.t**2)
self.u=u[:n]
self.u0=u0
self.u00=u00+self.sw
return

def get_PGA(self):
self.PGA=max(abs(self.sw))
return max(abs(self.sw))

def get_PGV(self):
self.PGV=max(abs(self.v))
return max(abs(self.v))

def get_PGD(self):
self.PGD=max(abs(self.su))
return max(abs(self.su))

def get_sa(self,begin,end,step):
T=np.arange(begin,end,step)
sa=np.array([])
sv=np.array([])
su=np.array([])
sa_truemax=np.array([])
sa_truemin=np.array([])
sv_truemax=np.array([])
sv_truemin=np.array([])
su_truemax=np.array([])
su_truemin=np.array([])
for i in T:
u,v,a=self.newmark_beta(i)
sa=np.append(sa,max(abs(a)))
sa_truemax=np.append(sa_truemax,max(a))
sa_truemin=np.append(sa_truemin,min(a))

sv=np.append(sv,max(abs(v)))
sv_truemax=np.append(sv_truemax,max(v))
sv_truemin=np.append(sv_truemin,min(v))

su=np.append(su,max(abs(u)))
su_truemax=np.append(su_truemax,max(u))
su_truemin=np.append(su_truemin,min(u))
self.saT=T
self.sa=sa
self.sd=su
self.sv=sv
self.sa_truemax=sa_truemax
self.sa_truemin=sa_truemin
self.sv_truemax=sv_truemax
self.sv_truemin=sv_truemin
self.sd_truemax=su_truemax
self.sd_truemin=su_truemin
return

def get_v(self):#步长,地震波
v=[]
v.append(0)
for i in range(len(self.sw)-1):
v.append(v[i]+self.t*0.5*(self.sw[i]+self.sw[i+1]))
self.v=np.array(v)
return v

def get_u(self):
v=self.get_v()
u=[]
u.append(0)
for i in range(len(self.sw)-1):
u.append(u[i]+self.t*v[i]+(0.5**2)*(self.sw[i]+self.sw[i+1])*(self.t**2))
self.su=np.array(u)
return u

def tiaofu_sa(self,T,target):# 地震波步长 地震波 要调幅到的周期和值'
u,v,a=self.newmark_beta(T)
sa=max(abs(a))
self.tf=self.sw
self.sw=self.sw*(target/sa)
self.get_v()
self.get_u()
return target/sa

def return_a(self):
return self.sw

def return_d(self):
return self.su

def return_v(self):
return self.v

def return_sj(self):
return self.x

def return_id(self):
return self.id

def return_saT(self):
return self.saT

def return_sa(self):
return self.sa

def return_sd(self):
return self.sd

def return_sv(self):
return self.sv

def return_sa_truemax(self):
return self.sa_truemax

def return_sa_truemin(self):
return self.sa_truemin

def return_sv_truemax(self):
return self.sv_truemax

def return_sv_truemin(self):
return self.sv_truemin

def return_sd_truemax(self):
return self.sd_truemax

def return_sd_truemin(self):
return self.sd_truemin

def four(self,form=1):# 加速度or速度
if form==1:
tmp=self.sw
elif form==2:
tmp=self.v
else:
return
inpf=np.fft.fft(tmp) #默认的是对行向量fourier变换,所以此处要定义下轴
fs=1/self.t
f=fs*np.arange(0,int(len(tmp)/2))/len(tmp)
nf=len(f)
tmp1=np.fft.fft(tmp)
Four=abs(tmp1)
return f,Four


def input_gmotion(path):#返回EW,NW,UP方向地震动数组和时间间隔t
f=open(path,'r')
t=float(f.readline().split(',')[0])
data=f.readlines()
ew=[]
ns=[]
up=[]
for d in data:
ew.append(float(d.split(',')[0]))
ns.append(float(d.split(',')[1]))
up.append(float(d.split(',')[2]))
f.close()
return ew,ns,up,t

def any_angle(ew,ns,theta):#EW,NS地震动,方向角,作用:返回任何方向的地震动
return np.array(ew)*np.cos(theta)+np.array(ns)*np.sin(theta)

def graph(theta,r,value,name):#theta,r,value,命名(包含路径)
fig, axes = plt.subplots(subplot_kw=dict(projection='polar'),figsize=(10,10))
contourplot = axes.contourf(theta,r,value,cmap=plt.cm.jet)
plt.colorbar(contourplot, shrink=.6, pad=0.08)
plt.savefig(name)

def any_angle_spectrum(path):
ew,ns,up,t=input_gmotion(path)
space_theta = np.radians(np.linspace(0, 360, 361)) #转化为弧度
space_r = np.linspace(0, 2, 21)
r,theta = np.meshgrid(space_r,space_theta)
if(not os.path.exists(path.split('.')[-2]+'_a.jpg')):
value_a=np.zeros(len(space_theta)*len(space_r)).reshape(len(space_theta),len(space_r)) # 数值矩阵 加速度
value_v=np.zeros(len(space_theta)*len(space_r)).reshape(len(space_theta),len(space_r)) # 速度
value_u=np.zeros(len(space_theta)*len(space_r)).reshape(len(space_theta),len(space_r)) # 位移
for i in range(0,181):
new_a=any_angle(ew,ns,np.radians(i))
sp=spectrum(new_a,t)
sp.get_sa(0,2.1,0.1)
value_a[i]=sp.return_sa_truemax()
value_a[i+180]=abs(sp.return_sa_truemin())
value_v[i]=sp.return_sv_truemax()
value_v[i+180]=abs(sp.return_sv_truemin())
value_u[i]=sp.return_sd_truemax()
value_u[i+180]=abs(sp.return_sd_truemin())


graph(theta,r,value_a,path.split('.')[-2]+'_a.jpg')
graph(theta,r,value_v,path.split('.')[-2]+'_v.jpg')
graph(theta,r,value_u,path.split('.')[-2]+'_u.jpg')
np.savetxt(path.split('.')[-2]+'_a.txt',value_a)
np.savetxt(path.split('.')[-2]+'_v.txt',value_v)
np.savetxt(path.split('.')[-2]+'_u.txt',value_u)
print("处理{}".format(path))
else:
print("跳过{}".format(path))
return

path=r'E:\吾儿美岗\1'
doc=Document()
for root,dirs,files in os.walk(path):
for file in files:
if file.split('.')[-1]=="csv":
any_angle_spectrum(os.path.join(path,file))
#word添加标题
p=doc.add_paragraph(file.split('.')[0])
p.paragraph_format.alignment=WD_ALIGN_PARAGRAPH.CENTER
tab =doc.add_table(rows=3,cols=1)
#word添加表格,并向表格内插入图片
miaoshu=["加速度全向反应谱","速度全向反应谱","位移全向反应谱"]
t=['_a','_v','_u']
height=[6,6,6]

for i in range(3):
cell=tab.cell(i,0)
run=cell.paragraphs[0].add_run()
run.add_picture(os.path.join(root,file.split('.')[0])+t[i]+".jpg",height=shared.Cm(height[i]))
cell.paragraphs[0].alignment=WD_PARAGRAPH_ALIGNMENT.CENTER

cell.add_paragraph(miaoshu[i])
cell.paragraphs[1].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER #竖直居中
doc.add_page_break()
doc.save("nn.docx")

参考文献

  • 強震動の観測記録に基づく周期特性を考慮した2 方向地震動の方向性分析,土木学会論文集A1(構造・地震工学), Vol. 76, No. 4(地震工学論文集第39巻), I_205-I_213, 2020.