这篇博客主要介绍如何利用Fortran与Gunplot结合进行批量计算,主要针对模型研究时连续改变某个参数,批量的绘制想要结果图,这可以节省很多的时间,主要是在利用Fortran计算的时候,将相应参数绘图的gnuplot绘图代码写入相应文件,之后进行快速执行.
{:.info}

做模型研究的时候,通常会调节一个模型的很多参数来研究这些参数变化时某些量是如何演化的,这就涉及到批量计算绘图的问题,我是习惯用Fortran了,因为计算速度比较快,而且自己也比较熟悉了,结合gnuplot可以快速的将不同数据对应的结果进行作图.这里的有些内容可以参考做数值计算好用的软件及杂项整理这篇中的内容,废话不多说,直接上代码进行解释.

Fortran + Gnuplot 批量数据输出绘图

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
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
!   Anticommute mass term along y open gap
! tau*spin*orbit
! Rotation 45 degree calculate edge states
! kx--->(Kx + Ky) ky----->(Kx - Ky)
module pub
implicit none
integer yn,kn,ne,N,enn,hn
real eng ! energy
parameter(yn = 50,hn = 8,kn = 50, ne = 50,N = yn*hn)
real,parameter::pi = 3.1415926535
complex,parameter::im = (0.,1.0)
complex Ham(N,N)
!--------------------------------
real m0,mu,lamx,lamy,gamma,tx,ty,dx,dy,d0
complex g1(hn,hn) ,g4(hn,hn),g2(hn,hn),g3(hn,hn),g5(hn,hn)
complex am1(hn,hn),am2(hn,hn),am3(hn,hn),am4(hn,hn)
complex am5(hn,hn),am6(hn,hn),am7(hn,hn),am8(hn,hn),am(hn,hn)
real mm0,mmx,mmy
!---------------------------------
integer::lda = N
integer,parameter::lwmax = 2*N + N**2
real,allocatable::w(:)
complex,allocatable::work(:)
real,allocatable::rwork(:)
integer,allocatable::iwork(:)
integer lwork
integer lrwork
integer liwork
integer info
end module pub
!================= PROGRAM START ============================
program sol
use pub
!====空间申请==================
allocate(w(N))
allocate(work(lwmax))
allocate(rwork(1+5*N+2*N**2))
allocate(iwork(3+5*N))
!======parameter value setting =====
m0 = 1.5
! mu = 0.3
tx = 1.0
ty = 1.0
lamx = 1.0
lamy = 1.0
! dx = 0.5
! dy = -dx
mm0 = 0.2
! mmx = 0.5
! mmy = -mmx
call Pauli()
call main1()
! am = am1
! call cylinder(1)
! call plot(1)
stop
end program sol
!====================================================================================
subroutine main1()
use pub
am = am1
call cylinder(1)
call plot(1)

am = am2
call cylinder(2)
call plot(2)

am = am3
call cylinder(3)
call plot(3)

am = am4
call cylinder(4)
call plot(4)

am = am5
call cylinder(5)
call plot(5)

am = am6
call cylinder(6)
call plot(6)

am = am7
call cylinder(7)
call plot(7)

am = am8
call cylinder(8)
call plot(8)

end subroutine main1
!=============================================================================================
subroutine cylinder(m3)
! Calculate edge spectrum function
use pub
integer m1,m2,m3
real kx,ky
character*20::str1,str2,str3,str4,str5,str6
str1 = "oy45-sc-ym"
str2 = "ox45-sc-ym"
write(str3,"(I2.2)")m3
str4 = ".dat"
str5 = trim(str1)//trim(str3)//trim(str4)
str6 = trim(str2)//trim(str3)//trim(str4)
open(30,file=str5)
!-------------------------------------------------
! y-direction is open
do m1 = -kn,kn
kx = pi*m1/kn
call openy(kx)
write(30,999)kx/pi,(w(i),i = 1,N)
end do
close(30)
!--------------------------------------------------
! x-direction is open
open(31,file=str6)
do m1 = -kn,kn
ky = pi*m1/kn
call openx(ky)
write(31,999)ky/pi,(w(i),i=1,N)
end do
close(31)
999 format(802f11.5)
return
end subroutine cylinder
!======================== Pauli Matrix driect product============================
subroutine Pauli()
use pub
!---------Kinetic energy
g1(1,1) = 1
g1(2,2) = -1
g1(3,3) = 1
g1(4,4) = -1
g1(5,5) = -1
g1(6,6) = 1
g1(7,7) = -1
g1(8,8) = 1
!----------SOC-x
g2(1,2) = 1
g2(2,1) = 1
g2(3,4) = -1
g2(4,3) = -1
g2(5,6) = 1
g2(6,5) = 1
g2(7,8) = -1
g2(8,7) = -1
!---------SOC-y
g3(1,2) = -im
g3(2,1) = im
g3(3,4) = -im
g3(4,3) = im
g3(5,6) = im
g3(6,5) = -im
g3(7,8) = im
g3(8,7) = -im
!-------------------SC pairing
g4(1,7) = -1
g4(2,8) = -1
g4(3,5) = 1
g4(4,6) = 1
g4(5,3) = 1
g4(6,4) = 1
g4(7,1) = -1
g4(8,2) = -1
!------------------- Chemical potential
g5(1,1) = 1
g5(2,2) = 1
g5(3,3) = 1
g5(4,4) = 1
g5(5,5) = -1
g5(6,6) = -1
g5(7,7) = -1
g5(8,8) = -1
!-------------------Anti Mass-------------------------------
!i,y,i
am1(1,3) = -im
am1(2,4) = -im
am1(3,1) = im
am1(4,2) = im
am1(5,7) = -im
am1(6,8) = -im
am1(7,5) = im
am1(8,6) = im
!y,x,x
am2(1,8) = -im
am2(2,7) = -im
am2(3,6) = -im
am2(4,5) = -im
am2(5,4) = im
am2(6,3) = im
am2(7,2) = im
am2(8,1) = im
!i,x,i
am3(1,3) = 1
am3(2,4) = 1
am3(3,1) = 1
am3(4,2) = 1
am3(5,7) = 1
am3(6,8) = 1
am3(7,5) = 1
am3(8,6) = 1
!z,y,i
am4(1,3) = -im
am4(2,4) = -im
am4(3,1) = im
am4(4,2) = im
am4(5,7) = im
am4(6,8) = im
am4(7,5) = -im
am4(8,6) = -im
!x,y,x
am5(1,8) = -im
am5(2,7) = -im
am5(3,6) = im
am5(4,5) = im
am5(5,4) = -im
am5(6,3) = -im
am5(7,2) = im
am5(8,1) = im
!z,x,i
am6(1,3) = 1
am6(2,4) = 1
am6(3,1) = 1
am6(4,2) = 1
am6(5,7) = -1
am6(6,8) = -1
am6(7,5) = -1
am6(8,6) = -1
!x,x,x
am7(1,8) = 1
am7(2,7) = 1
am7(3,6) = 1
am7(4,5) = 1
am7(5,4) = 1
am7(6,3) = 1
am7(7,2) = 1
am7(8,1) = 1
!y,y,x
am8(1,8) = -1
am8(2,7) = -1
am8(3,6) = 1
am8(4,5) = 1
am8(5,4) = 1
am8(6,3) = 1
am8(7,2) = -1
am8(8,1) = -1
return
end subroutine Pauli
!==========================================================
subroutine openx(ky)
use pub
real ky
integer m,l,k
Ham = 0
!========== Positive energy ========
do k = 0,yn-1
if (k == 0) then ! Only right block in first line
do m = 1,hn
do l = 1,hn
Ham(m,l) = m0*g1(m,l)+ mm0*am(m,l)

Ham(m,l + hn) = (tx/2.0*cos(ky) - tx/(2*im)*sin(ky) + ty/2.0*cos(ky) + ty/(2*im)*sin(ky))*g1(m,l) +&
(lamx/(2*im)*cos(ky) + lamx/2.0*sin(ky))*g2(m,l) + (lamy/(2*im)*cos(ky) - lamy/2.0*sin(ky))*g3(m,l)&
+ (mmx/2.0*cos(ky) + mmx/(2*im)*sin(ky) - mmy/2.0*cos(ky) - mmy/(2*im)*sin(ky))*am(m,l)
end do
end do
elseif ( k==yn-1 ) then ! Only left block in last line
do m = 1,hn
do l = 1,hn
Ham(k*hn + m,k*hn + l) = m0*g1(m,l)+ mm0*am(m,l)

Ham(k*hn + m,k*hn + l - hn) = (tx/2.0*cos(ky) + tx/(2*im)*sin(ky) + ty/2.0*cos(ky) - ty/(2*im)*sin(ky))*g1(m,l) +&
(-lamx/(2*im)*cos(ky) + lamx/2.0*sin(ky))*g2(m,l) + (-lamy/(2*im)*cos(ky) - lamy/2.0*sin(ky))*g3(m,l)&
+ (mmx/2.0*cos(ky) - mmx/(2*im)*sin(ky) - mmy/2.0*cos(ky) + mmy/(2*im)*sin(ky))*am(m,l)
end do
end do
else
do m = 1,hn
do l = 1,hn ! k start from 1,matrix block from 2th row
Ham(k*hn + m,k*hn + l) = m0*g1(m,l)+ mm0*am(m,l)

Ham(k*hn + m,k*hn + l + hn) = (tx/2.0*cos(ky) - tx/(2*im)*sin(ky) + ty/2.0*cos(ky) + ty/(2*im)*sin(ky))*g1(m,l) +&
(lamx/(2*im)*cos(ky) + lamx/2.0*sin(ky))*g2(m,l) + (lamy/(2*im)*cos(ky) - lamy/2.0*sin(ky))*g3(m,l)&
+ (mmx/2.0*cos(ky) + mmx/(2*im)*sin(ky) - mmy/2.0*cos(ky) - mmy/(2*im)*sin(ky))*am(m,l)
Ham(k*hn + m,k*hn + l - hn) = (tx/2.0*cos(ky) + tx/(2*im)*sin(ky) + ty/2.0*cos(ky) - ty/(2*im)*sin(ky))*g1(m,l) +&
(-lamx/(2*im)*cos(ky) + lamx/2.0*sin(ky))*g2(m,l) + (-lamy/(2*im)*cos(ky) - lamy/2.0*sin(ky))*g3(m,l)&
+ (mmx/2.0*cos(ky) - mmx/(2*im)*sin(ky) - mmy/2.0*cos(ky) + mmy/(2*im)*sin(ky))*am(m,l)
end do
end do
end if
end do
!------------------------
call isHermitian()
call eigsol()
return
end subroutine openx
!==========================================================
subroutine openy(kx)
use pub
real kx
integer m,l,k
Ham = 0
!========== Positive energy ========
do k = 0,yn-1
if (k == 0) then ! Only right block in first line
do m = 1,hn
do l = 1,hn
Ham(m,l) = m0*g1(m,l) + mm0*am(m,l)

Ham(m,l + hn) = (tx/2.0*cos(kx) - tx/(2*im)*sin(kx) + ty/2.0*cos(kx) + ty/(2*im)*sin(kx))*g1(m,l)+&
(lamx/2.0*sin(kx) + lamx/(2*im)*cos(kx))*g2(m,l) + (lamy/2.0*sin(kx) - lamy/(2*im)*cos(kx))*g3(m,l)&
+ (mmx/2.0*cos(kx) + mmx/(2*im)*sin(kx) - mmy/2.0*cos(kx) - mmy/(2*im)*sin(kx))*am(m,l)
end do
end do
elseif ( k==yn-1 ) then ! Only left block in last line
do m = 1,hn
do l = 1,hn
Ham(k*hn + m,k*hn + l) = m0*g1(m,l)+ mm0*am(m,l)

Ham(k*hn + m,k*hn + l - hn) = (tx/2.0*cos(kx) + tx/(2*im)*sin(kx) + ty/2.0*cos(kx) - ty/(2*im)*sin(kx))*g1(m,l)+&
(lamx/2.0*sin(kx) - lamx/(2*im)*cos(kx))*g2(m,l) + (lamy/2.0*sin(kx) + lamy/(2*im)*cos(kx))*g3(m,l)&
+ (mmx/2.0*cos(kx) - mmx/(2*im)*sin(kx) - mmy/2.0*cos(kx) + mmy/(2*im)*sin(kx))*am(m,l)
end do
end do
else
do m = 1,hn
do l = 1,hn ! k start from 1,matrix block from 2th row
Ham(k*hn + m,k*hn + l) = m0*g1(m,l)+ mm0*am(m,l)

Ham(k*hn + m,k*hn + l + hn) = (tx/2.0*cos(kx) - tx/(2*im)*sin(kx) + ty/2.0*cos(kx) + ty/(2*im)*sin(kx))*g1(m,l)+&
(lamx/2.0*sin(kx) + lamx/(2*im)*cos(kx))*g2(m,l) + (lamy/2.0*sin(kx) - lamy/(2*im)*cos(kx))*g3(m,l)&
+ (mmx/2.0*cos(kx) + mmx/(2*im)*sin(kx) - mmy/2.0*cos(kx) - mmy/(2*im)*sin(kx))*am(m,l)
Ham(k*hn + m,k*hn + l - hn) = (tx/2.0*cos(kx) + tx/(2*im)*sin(kx) + ty/2.0*cos(kx) - ty/(2*im)*sin(kx))*g1(m,l)+&
(lamx/2.0*sin(kx) - lamx/(2*im)*cos(kx))*g2(m,l) + (lamy/2.0*sin(kx) + lamy/(2*im)*cos(kx))*g3(m,l)&
+ (mmx/2.0*cos(kx) - mmx/(2*im)*sin(kx) - mmy/2.0*cos(kx) + mmy/(2*im)*sin(kx))*am(m,l)
end do
end do
end if
end do
!---------------------------------
call isHermitian()
call eigsol()
return
end subroutine openy
!============================================================
subroutine isHermitian()
use pub
integer i,j
do i = 1,N
do j = 1,N
if (Ham(i,j) .ne. conjg(Ham(j,i)))then
open(160,file = 'hermitian.dat')
write(160,*)i,j
write(160,*)Ham(i,j)
write(160,*)Ham(j,i)
write(160,*)"===================="
write(*,*)"Hamiltonian is not hermitian"
stop
end if
end do
end do
close(160)
return
end subroutine isHermitian
!================= Hermitain Matrices solve ==============
subroutine eigsol(input)
use pub
integer m
character*20::str1,str2,str3,str4
str1 = "eigval_xmass"
str3 = ".dat"
write(str2,"(I4.4)")input
str4 = trim(str1)//trim(str2)//trim(str3)
lwork = -1
liwork = -1
lrwork = -1
call cheevd('V','U',N,Ham,lda,w,work,lwork,rwork,lrwork,iwork,liwork,info)
lwork = min(2*N+N**2, int( work( 1 ) ) )
lrwork = min(1+5*N+2*N**2, int( rwork( 1 ) ) )
liwork = min(3+5*N, iwork( 1 ) )
call cheevd('V','U',N,Ham,lda,w,work,lwork,rwork,lrwork,iwork,liwork,info)
if( info .GT. 0 ) then
open(110,file="mes.dat",status="unknown")
write(110,*)'The algorithm failed to compute eigenvalues.'
close(110)
end if
return
end subroutine eigsol
!==========================================================================
subroutine plot(m3)
use pub
character*20::str1,str2,str3,str4,str5,str6
integer m3
str1 = "diag-ym"
write(str2,"(I2.2)")m3
str3 = ".gnu"
str4 = trim(str1)//trim(str2)//trim(str3)
open(20,file=str4)
write(20,*)'set terminal png truecolor enhanced font ",50" size 3000, 1500'
write(20,*)"set output 'diag"//trim(str2)//"-cy-ym.png'"
write(20,*)"set size 1, 1"
write(20,*)"set multiplot layout 1, 2"
write(20,*)"unset key"
write(20,*)"set ytics 1.5 "
write(20,*)"set xtics 0.5"
write(20,*)"set xtics offset 0, 0.0"
write(20,*)'set xtics format "%4.1f" nomirror out '
write(20,*)'set ytics format "%4.1f"'
write(20,*)'set ylabel "E"'
write(20,*)"set ylabel offset 0.5, 0.0 "
write(20,*)"#set xlabel offset 0, -1.0 "
write(20,*)"set xrange [-1:1]"
write(20,*)"set yrange [-3:3]"
write(20,*)"set xlabel 'k_y' "
write(20,*)"plot for [i=2:400] 'ox45-sc-ym"//trim(str2)//".dat' u 1:i w l lw 5 lc 'blue'"
write(20,*)"set xlabel 'k_x' "
write(20,*)"plot for [i=2:400] 'oy45-sc-ym"//trim(str2)//".dat' u 1:i w l lw 5 lc 'blue'"
write(20,*)"unset multiplot"
close(20)
end subroutine plot

上面代码主要的内容是

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
  subroutine cylinder(m3)
! Calculate edge spectrum function
use pub
integer m1,m2,m3
real kx,ky
character*20::str1,str2,str3,str4,str5,str6
str1 = "oy45-sc-ym"
str2 = "ox45-sc-ym"
write(str3,"(I2.2)")m3
str4 = ".dat"
str5 = trim(str1)//trim(str3)//trim(str4)
str6 = trim(str2)//trim(str3)//trim(str4)
open(30,file=str5)
!-------------------------------------------------
! y-direction is open
do m1 = -kn,kn
kx = pi*m1/kn
call openy(kx)
write(30,999)kx/pi,(w(i),i = 1,N)
end do
close(30)
!--------------------------------------------------
! x-direction is open
open(31,file=str6)
do m1 = -kn,kn
ky = pi*m1/kn
call openx(ky)
write(31,999)ky/pi,(w(i),i=1,N)
end do
close(31)
999 format(802f11.5)
return
end subroutine cylinder

通过下面的代码可以组合出随着m3变化的字符串,将其作为文件名,这样就会对不同的输出,产生相对应的数据文件
1
2
3
4
5
6
str1 = "oy45-sc-ym"
str2 = "ox45-sc-ym"
write(str3,"(I2.2)")m3
str4 = ".dat"
str5 = trim(str1)//trim(str3)//trim(str4)
str6 = trim(str2)//trim(str3)//trim(str4)

而在绘图部分
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
subroutine plot(m3)
use pub
character*20::str1,str2,str3,str4,str5,str6
integer m3
str1 = "diag-ym"
write(str2,"(I2.2)")m3
str3 = ".gnu"
str4 = trim(str1)//trim(str2)//trim(str3)
open(20,file=str4)
write(20,*)'set terminal png truecolor enhanced font ",50" size 3000, 1500'
write(20,*)"set output 'diag"//trim(str2)//"-cy-ym.png'"
write(20,*)"set size 1, 1"
write(20,*)"set multiplot layout 1, 2"
write(20,*)"unset key"
write(20,*)"set ytics 1.5 "
write(20,*)"set xtics 0.5"
write(20,*)"set xtics offset 0, 0.0"
write(20,*)'set xtics format "%4.1f" nomirror out '
write(20,*)'set ytics format "%4.1f"'
write(20,*)'set ylabel "E"'
write(20,*)"set ylabel offset 0.5, 0.0 "
write(20,*)"#set xlabel offset 0, -1.0 "
write(20,*)"set xrange [-1:1]"
write(20,*)"set yrange [-3:3]"
write(20,*)"set xlabel 'k_y' "
write(20,*)"plot for [i=2:400] 'ox45-sc-ym"//trim(str2)//".dat' u 1:i w l lw 5 lc 'blue'"
write(20,*)"set xlabel 'k_x' "
write(20,*)"plot for [i=2:400] 'oy45-sc-ym"//trim(str2)//".dat' u 1:i w l lw 5 lc 'blue'"
write(20,*)"unset multiplot"
close(20)
end subroutine plot

同样利用相同的方法来产生相对应数据的gnuplot作图文件.

这里再提供一个编译执行fortran文件的shell脚本

1
2
3
4
5
6
7
8
9
10
#!/bin/sh  
#============ get the file name ===========
rm *.gnu *.png no* *.dat *.out 1>/dev/null 2>/dev/null &
Folder_A=$(pwd)
for file_a in ${Folder_A}/*.f90
do
temp_file=`basename $file_a .f90`
ifort -mkl -O3 -CB $file_a -o $temp_file.out
nohup ./$temp_file.out 1>/dev/null 2>/dev/null &
done

将这个脚本文件放在放置在和需要编译的fortran文件相同的文件夹中,这个脚本会自动搜寻当前文件夹中所有后缀名为.f90的文件,然后编译并执行,这里采用的ifort进行编译的,而且因为对角化用到了mkl库中的cheevd这个函数,所有编译选项有-mkl这个参数.
{:.success}

将上面的脚本命名为run1.sh然后执行

1
sh run1.sh

结果如下图所示

png

可以看到这里得到了数据结果filename.dat与其相应的一系列绘图脚本filename.gnu,下面批量执行所有的filename.gnu绘图脚本

1
2
3
4
5
6
7
#!/bin/sh  
#============ get the file name ===========
Folder_A=$(pwd)
for file_a in ${Folder_A}/*.gnu
do
gnuplot $file_a
done

同样的,这个脚本的作用是寻找该文件夹下面所有后缀为.gnu的文件,执行绘图程序gnuplot filename.gnu,结果如下

png

可以看到批量执行之后会有一系列的结果图.

除了上面对单个文件的操作,有时候如果是对单个文件夹中的多个文件操作,上面的操作同样是可性的,因为编译执行的脚本是对后缀名进行识别的,所以如果有多个fortran文件,那么它们都会被编译执行,而绘图的脚本也是同样的道理.
{:.warning}

文件夹递归操作

除了对单个文件夹中的多个文件进行编译执行操作,有时候在计算时,可能会有很多个文件夹,而每个文件夹中又有多个文件需要进行编译执行,这时候上面的脚本就不能发挥作用了,需要对文件夹进行递归操作,也就是说要找到当前文件夹下面包含的每个文件夹,进行该文件夹然后再执行上面的脚本,比如当前文件夹下面还有一些文件夹

png

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
#!/bin/bash 
# 递归搜寻文件夹下面所有的.f90或者.f后缀结尾的文件,并利用ifort编译该文件,然后执行
function getdir(){
for element in `ls $1`
do
dir_or_file=$1"/"$element
if [ -d $dir_or_file ]
then
getdir $dir_or_file
else # 下面的全是文件
if [ "${dir_or_file##*.}"x = "f90"x ]||[ "${dir_or_file##*.}"x = "f"x ];then # 筛选处特定后缀的文件
dir_name=`dirname $dir_or_file` # 读取目录
file_name=`basename $dir_or_file .f90` # 读取以f90结尾的文件名
out_file_name="$dir_name/$file_name" # 定义编号成功的文件名称
ifort -mkl $dir_or_file -o $out_file_name.out # 开始编译fortran文件,编译后文件名以out结尾
dir1=`dirname $out_file_name`
#echo $dir1
cd $dir1 # 切换到具体的文件夹
sh run1.sh & # 执行当前文件夹下面的run1.sh脚本
#./$file_name.out 1>mes 2>bad & # 执行该文件夹下面编译好的文件
# ./$out_file_name.out 1>mes 2>bad &
rm $out_file_name.out
fi
#temp_file=`basename $dir_or_file .f90` #将文件名后缀删除
#ifort -mkl $dir_or_file -o $temp_file.out # 编译后文件名以out结尾
#echo $dir_or_file # 这里的变量时完整的路径名
fi
done
}

#root_dir="/home/yxli/te"
root_dir=`pwd`
getdir $root_dir

代码的主要部分是

1
2
3
4
5
  $dir1  # 切换到具体的文件夹
sh run1.sh & # 执行当前文件夹下面的run1.sh脚本
#./$file_name.out 1>mes 2>bad & # 执行该文件夹下面编译好的文件
# ./$out_file_name.out 1>mes 2>bad &
rm $out_file_name.out

我在这里使用了sh run1.sh这个命令,这样的好处是会对cd切换到的每个文件夹中均编译执行所有.f90的文件(这是脚本run1.sh的功能),同样也可以使用
1
2
   #./$file_name.out 1>mes 2>bad &  # 执行该文件夹下面编译好的文件
# ./$out_file_name.out 1>mes 2>bad &

这个命令,我这里是将它进行了注释,它也是会编译并执行所有后缀为.f90的文件,而关于后缀名的选择,是在
1
if [ "${dir_or_file##*.}"x = "f90"x ]||[ "${dir_or_file##*.}"x = "f"x ];then	# 筛选处特定后缀的文件

这里进行筛选的,所以如果是想要编译执行其他类型程序的文件,可以对这个后缀名进行修改并调整对应的编译器即可.

这个脚本的主要思路就是,遍历当前文件夹下的所有文件夹,而每个文件夹中又有前面提及到的run1.sh这个脚本,在循环遍历所有的文件夹过程中,执行每个文件夹下面的run1.sh脚本,这样就相当于对所有的文件夹都启动的编译执行程序,由于这是一个递归的过程,就算当前文件夹下面包含的文件夹深度不止一层,这个脚本同样可以使用.
{:.success}

在将fortran程序递归的编译执行完成之后,每个文件夹中会产生了许多的.gnu文件可以用来绘图,与上面相同的思路,此时递归遍历每个文件夹并执行plot.sh这个绘图脚本

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
#!/bin/bash 
function getdir(){
for element in `ls $1`
do
dir_or_file=$1"/"$element
if [ -d $dir_or_file ]
then
getdir $dir_or_file
else # 下面的全是文件
if [ "${dir_or_file##*.}"x = "gnu"x ];then # 筛选处特定后缀的文件
dir_name=`dirname $dir_or_file` # 读取目录
file_name=`basename $dir_or_file .gnu` # 读取以.gnu结尾的文件名
out_file_name="$dir_name/$file_name" # 定义编号成功的文件名称
#ifort -mkl $dir_or_file -o $out_file_name.out # 编译后文件名以out结尾
dir1=`dirname $out_file_name`
#echo $dir1
cd $dir1 # 切换到具体的文件夹
gnuplot $dir_or_file &
fi
#temp_file=`basename $dir_or_file .f90` #将文件名后缀删除
#ifort -mkl $dir_or_file -o $temp_file.out # 编译后文件名以out结尾
#echo $dir_or_file # 这里的变量时完整的路径名
fi
done
}

# fold="/home/yxli/te"
fold=`pwd`
getdir $fold

最终就可以将所有文件夹下面的程序执行完毕,并进行绘图了.

其实这里还有一个小的缺陷,就是必须等到程序执行完毕之后才会去画图,这当然是必然的事情,程序不执行完毕,没有数据肯定不能绘图,但我们不知道程序何时会执行完毕,所以此时还是需要认为的等待程序执行结束后,才能运行批量绘图的这个脚本,我想可以进行升级,让服务器自动监测程序时候执行完毕,如果执行完毕就可以自动执行绘图的脚本,这样只需要服务器自行判断即可,我们需要的只是去做别的事情,然后再完成之后,去检查计算结果即可,节省时间,高效率才是搞科研的终极目标.
{:.warning}

上面提到的小缺陷我已经在监测程序运行的Shell脚本这篇博客中给出了解决方案.
{:.success}

小改动

这里稍微修改了一下程序编译后的名称,干脆用数字表示了,防止因为原来的文件名太长,导致可执行文件名也很长,不方便查看.

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
#!/bin/bash 
# 递归搜寻文件夹下面所有的.f90或者.f后缀结尾的文件,并利用ifort编译该文件,然后执行
cnt=0 # 定义一个变量,来统计文件夹下面对应程序的个数
function getdir(){
for element in `ls $1`
do
out="out"
dir_or_file=$1"/"$element
if [ -d $dir_or_file ]
then
getdir $dir_or_file
else # 下面的全是文件
rm *dat *gnu *png 1>/dev/null 2>/dev/null
if [ "${dir_or_file##*.}"x = "f90"x ]||[ "${dir_or_file##*.}"x = "f"x ];then # 筛选处特定后缀的文件
cnt=$[$cnt+1]
dir_name=`dirname $dir_or_file` # 读取目录
file_name=`basename $dir_or_file .f90` # 读取以f90结尾的文件名
#out_file_name="$dir_name/$file_name" # 定义编号成功的文件名称
out_file_name="$dir_name/$cnt" # 定义编号成功的文件名称
ifort -mkl $dir_or_file -o $out_file_name.$out # 开始编译fortran文件,编译后文件名以out结尾,以数字命名
dir1=`dirname $out_file_name`
#echo $out_file_name.$out
#echo $dir1
cd $dir1 # 切换到具体的文件夹,是为了在具体的文件夹中,运行编译好的可执行文件
#echo $cnt.$out
./$cnt.$out 1>/dev/null 2>/dev/null & # 执行该文件夹下面编译好的文件
#rm $out_file_name.$out
fi
#temp_file=`basename $dir_or_file .f90` #将文件名后缀删除
#ifort -mkl $dir_or_file -o $temp_file.out # 编译后文件名以out结尾
#echo $dir_or_file # 这里的变量时完整的路径名
fi
done
}

root_dir=`pwd`
getdir $root_dir

公众号

相关内容均会在公众号进行同步,若对该Blog感兴趣,欢迎关注微信公众号。
{:.info}

QR Code

Email

yxliphy@gmail.com