-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintegrate-strang.F90
403 lines (311 loc) · 11.3 KB
/
integrate-strang.F90
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
module integrator
! Module for Capreole (3D)
! Author: Garrelt Mellema
! Date: 2006-03-27 (2003-08-14)
! Integrates the set of equations over one time step (dt).
! Version: Strang splitting
use precision, only: dp
use my_mpi
use sizes, only: neq,neuler,nrOfDim,mbc
use mesh, only: sx,ex,sy,ey,sz,ez,meshx,meshy,meshz
use grid, only: dx,dy,dz,vol,volx
use hydro, only: stnew,stold,NEW,OLD,state1,state2,state,pressr
use times, only: dt
use problem, only: apply_grav_force,domainboundaryconditions, &
problemboundary
use protection, only: presprot
!use oddeven, only: odd_even
use boundary, only: boundaries
use hydrosolver, only: solver,state1d,wp,dstate,constr_solver,destr_solver
use ionic, only: rad_evolve3d
implicit none
integer,parameter,private :: transverse=1
integer,parameter,private :: notransverse=0
contains
subroutine integrate(nstep,istop)
! This routine integrates the grid for one time step
integer,intent(in) :: nstep ! time step counter
integer,intent(out) :: istop ! control integer
! Local variables
integer :: istop1,istop2
integer :: inegative
integer :: ierror,num,mpierror
integer,dimension(nrOfDim) :: instep
! Set flags to zero
inegative=0
ierror=0
mpierror=0
istop1=0
istop2=0
istop=0
! reset this to store flag for oe-fix
!stold(:,:,:,neq)=0.0d0
!stnew(:,:,:,neq)=0.0d0
! Do gravitational step
call apply_grav_force(0.5*dt,OLD)
! exchange boundaries with neighbours
! This routine also calculates the new pressure
call boundaries(OLD,domainboundaryconditions,problemboundary)
! Take one time step Strang splitting
! Alternate the order between time steps
instep=ran123()
do num=1,nrofDim
istoptest: if (istop == 0) then
! Point generic volume array to volx
vol => volx
select case (instep(num))
case (1)
if (meshx > 1) then
call xintegr(ierror)
else
stnew=stold ! no evolution (to get the pointers right)
endif
case (2)
if (meshy > 1) then
call yintegr(ierror)
else
stnew=stold ! no evolution (to get the pointers right)
endif
case (3)
if (meshz > 1) then
call zintegr(ierror)
else
stnew=stold ! no evolution (to get the pointers right)
endif
end select
! check for hydro errors (ierror <> 0)
! (find the maximum of ierror and store this in istop1)
istop1=ierror
#ifdef MPI
call MPI_ALLREDUCE(ierror,istop1,1,MPI_INTEGER,MPI_MAX, &
MPI_COMM_NEW,mpierror)
#endif
! Point generic state array to stnew
state => stnew
! set the inflow condition
! the inflow routine has to be supplied
!call inflow(NEW)
! exchange boundaries with neighbours
! This routine also calculates the new pressure
call boundaries(NEW,domainboundaryconditions,problemboundary)
! Odd-even fix
!call odd_even(NEW,0)
! exchange boundaries with neighbours
! This routine also calculates the new pressure
!call boundaries(NEW,domainboundaryconditions,problemboundary)
! Protect against negative pressures
!pressr(20,20,20)=-0.01*pressr(20,20,20)
call presprot(inegative,instep(num),NEW)
istop2=inegative
#ifdef MPI
call MPI_ALLREDUCE(inegative,istop2,1,MPI_INTEGER,MPI_MAX, &
MPI_COMM_NEW,mpierror)
#endif
istop=istop1+istop2
! exchange boundaries with neighbours
! This routine also calculates the new pressure
call boundaries(NEW,domainboundaryconditions,problemboundary)
! Copy new state to old state
! This is now done by pointing stnew and stold
! alternatingly to state1 and state2, thus eliminating
! the need of a data copy.
! To establish where we are in this cycle we also need
! to know the number of time steps that have been taken
! (nstep).
! Note that the fact that we have an odd number of
! dimensions implies that after a full cycle, the
! newest state is actually found in stold.
if (mod(num+nstep,2) == 0) then
stold => state2
stnew => state1
else
stold => state1
stnew => state2
endif
endif istoptest
enddo
! Do gravitational step
call apply_grav_force(0.5*dt,OLD)
! exchange boundaries with neighbours
! This routine also calculates the new pressure
call boundaries(OLD,domainboundaryconditions,problemboundary)
if (istop == 0) then ! otherwise serious error occurred
! Point generic state array to stold (the newest at this point)
state => stold
! Apply radiative processes.
! rad_evolve changes state in place (so no changing from stold
! to stnew is involved).
call rad_evolve3D(dt)
! exchange boundaries with neighbours
! This routine also calculates the new pressure
call boundaries(OLD,domainboundaryconditions,problemboundary)
endif
end subroutine integrate
!=======================================================================
subroutine xintegr(itoterror)
! This routine integrates the grid in the x direction
integer,intent(out) :: itoterror
! Local variables
integer :: i,j,k,ieq,ij,ik,mesh,ioff,ierror
!real(kind=dp),dimension(2) :: edge
! Initialize error status to zero
itoterror=0
mesh=ex-sx+1 ! the size of the y row
ioff=sx-1 ! offset between grid and y rows
!$omp parallel default(shared) private(ij,ik,k,j,i,ieq,ierror)
call constr_solver(mesh)
!$omp do schedule (dynamic,1) REDUCTION(+: itoterror)
kloop: do k=sz,ez
jloop :do j=sy,ey ! integrate over all rows
ij=j ! to export the current j position
ik=k ! to export the current k position
! remap to 1D state variable running from 1-mbc to ex-sx+1+mbc
! Calculate volume weighted state and pressure
do i=1-mbc,mesh+mbc
state1d(i,1:neq)=stold(i+ioff,j,k,1:neq)
wp(i)=pressr(i+ioff,j,k)
enddo
! Call Roe solver
call solver(mesh,dt,dx,dy,dz,2,3,4,ij,ik,ierror)
! Report problems
if (ierror /= 0) then
write(30,*) "Roe solver error (x), j,k= ",j,k
call flush(30)
itoterror=itoterror+ierror
endif
! Update the stnew variable
do ieq=1,neq
do i=sx,ex
stnew(i,j,k,ieq)=stold(i,j,k,ieq)+dstate(i-ioff,ieq)
enddo
enddo
enddo jloop
enddo kloop
!$omp end do
! Destroy solver variables
call destr_solver()
!$omp end parallel
end subroutine xintegr
!========================================================================
subroutine yintegr(itoterror)
! This routine integrates the grid in the y direction
integer,intent(out) :: itoterror
integer :: i,j,k,ieq,ij,ik,mesh,joff,ierror
! Initialize status to zero
itoterror=0
! remap to 1D state variable running from 1-mbc to ey-sy+1+mbc
mesh=ey-sy+1 ! size of the y row
joff=sy-1 ! offset between grid and row
!$omp parallel default(shared) private(ij,ik,k,j,i,ieq,ierror)
call constr_solver(mesh)
!$omp do schedule (dynamic,1) REDUCTION(+: itoterror)
kloop: do k=sz,ez
iloop: do i=sx,ex ! integrate over all rows
ij=i ! to export the current i position
ik=k ! to export the current k position
! Calculate volume weighted state and pressure
do j=1-mbc,mesh+mbc
state1d(j,1:neq)=stold(i,j+joff,k,1:neq)
wp(j)=pressr(i,j+joff,k)
enddo
! Call the Roe solver
call solver(mesh,dt,dy,dz,dx,3,4,2,ij,ik,ierror)
! Report problems
if (ierror /= 0) then
write(30,*) "Roe solver error (y), i,k= ",i,k
call flush(30)
itoterror=itoterror+ierror
endif
! Update the stnew variable
do ieq=1,neq
do j=sy,ey
stnew(i,j,k,ieq)=stold(i,j,k,ieq)+dstate(j-joff,ieq)
enddo
enddo
enddo iloop
enddo kloop
!$omp end do
! Destroy solver variables
call destr_solver()
!$omp end parallel
end subroutine yintegr
!========================================================================
subroutine zintegr(itoterror)
! This routine integrates the grid in the z direction
integer,intent(out) :: itoterror
integer :: i,j,k,ieq,ij,ik,mesh,koff,ierror
! Initialize status to zero
itoterror=0
! remap to 1D state variable running from 1-mbc to ez-sz+1+mbc
mesh=ez-sz+1 ! size of the x row
koff=sz-1 ! offset between grid and row
!$omp parallel default(shared) private(ij,ik,k,j,i,ieq,ierror)
call constr_solver(mesh)
!$omp do schedule (dynamic,1) REDUCTION(+: itoterror)
jloop: do j=sy,ey
iloop: do i=sx,ex ! integrate over all rows
ij=i ! to export the current i position
ik=j ! to export the current j position
! Calculate volume weighted state and pressure
do k=1-mbc,mesh+mbc
state1d(k,1:neq)=stold(i,j,k+koff,1:neq)
wp(k)=pressr(i,j,k+koff)
enddo
! Call the Roe solver
call solver(mesh,dt,dz,dx,dy,4,2,3,ij,ik,ierror)
! Report problems
if (ierror /= 0) then
write(30,*) "Roe solver error (z), i,j= ",i,j
call flush(30)
itoterror=itoterror+ierror
endif
! Update the stnew variable
do ieq=1,neq
do k=sz,ez
stnew(i,j,k,ieq)=stold(i,j,k,ieq)+dstate(k-koff,ieq)
enddo
enddo
enddo iloop
enddo jloop
!$omp end do
! Destroy solver variables
call destr_solver()
!$omp end parallel
end subroutine zintegr
!========================================================================
function ran123 ()
! Find a random order of the numbers 1, 2, 3
integer,dimension(3) :: ran123
real :: ran_num,order
call random_number(ran_num)
order=6.0*ran_num
if (order.lt.2.0) then
ran123(1)=1
if (order.lt.1.0) then
ran123(2)=2
ran123(3)=3
else
ran123(2)=3
ran123(3)=2
endif
elseif (order.lt.4.0) then
ran123(1)=2
if (order.lt.3.0) then
ran123(2)=1
ran123(3)=3
else
ran123(2)=3
ran123(3)=1
endif
else
ran123(1)=3
if (order.lt.5.0) then
ran123(2)=1
ran123(3)=2
else
ran123(2)=2
ran123(3)=1
endif
endif
end function ran123
end module integrator