MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_advance.t
Go to the documentation of this file.
1!> Module containing all the time stepping schemes
3
4 implicit none
5 private
6
7 !> Whether to conserve fluxes at the current sub-step
8 logical :: fix_conserve_at_step = .true.
9
10 !> Per-rank compute-only accumulator for lb_diagnose (sums the iigrid
11 !> block-loop wall time across all substages within one full advance call,
12 !> excluding ghostcell exchanges and flux conservation collectives).
13 double precision :: lb_compute_accum = 0.0d0
14
15 public :: advance
16 public :: process
17 public :: process_advanced
18
19contains
20
21 !> Advance all the grids over one time step, including all sources
22 subroutine advance(iit)
24 use mod_particles, only: handle_particles
25 use mod_eos
29
30 integer, intent(in) :: iit
31
32 integer :: iigrid, igrid, idimsplit
33
34 ! ---- per-rank load-balance diagnostic (gated by lb_diagnose) ----
35 double precision :: t_advance_start, t_advance_local
36 double precision :: t_dummy(1)
37 double precision, allocatable, save :: t_all_ranks(:)
38 double precision, allocatable, save :: c_all_ranks(:)
39 double precision, allocatable, save :: tc_all_ranks(:)
40 double precision, allocatable, save :: cool_all_ranks(:)
41 double precision, allocatable, save :: rt_all_ranks(:)
42 double precision :: cmax, cmean, ratioc
43 double precision :: tcmax, tcmean, ratiotc
44 double precision :: coolmax, coolmean, ratiocool
45 double precision :: rtmax, rtmean, ratiort
46 integer, save :: lb_log_unit = -1
47 logical, save :: lb_first_call = .true.
48 integer :: ipe
49 double precision :: tmax, tmean, ratio
50 character(len=256) :: lb_log_name
51 ! ----------------------------------------------------------------
52
53 if (lb_diagnose) then
54 if (lb_first_call .and. mype==0) then
55 allocate(t_all_ranks(npe))
56 allocate(c_all_ranks(npe))
57 allocate(tc_all_ranks(npe))
58 allocate(cool_all_ranks(npe))
59 allocate(rt_all_ranks(npe))
60 write(lb_log_name,'(a,a)') trim(base_filename), 'rank_timing.log'
61 open(newunit=lb_log_unit, file=trim(lb_log_name), status='replace', action='write')
62 write(lb_log_unit,'(a)',advance='no') '# it time '
63 do ipe=0,npe-1
64 write(lb_log_unit,'(a,i0,a)',advance='no') 't_rank',ipe,' '
65 end do
66 do ipe=0,npe-1
67 write(lb_log_unit,'(a,i0,a)',advance='no') 'c_rank',ipe,' '
68 end do
69 do ipe=0,npe-1
70 write(lb_log_unit,'(a,i0,a)',advance='no') 't_tc_rank',ipe,' '
71 end do
72 do ipe=0,npe-1
73 write(lb_log_unit,'(a,i0,a)',advance='no') 't_cool_rank',ipe,' '
74 end do
75 do ipe=0,npe-1
76 write(lb_log_unit,'(a,i0,a)',advance='no') 't_rt_rank',ipe,' '
77 end do
78 write(lb_log_unit,'(a)',advance='no') 'tmax tmean R cmax cmean Rc '
79 write(lb_log_unit,'(a)',advance='no') 'tcmax tcmean Rtc coolmax coolmean Rcool '
80 write(lb_log_unit,'(a)') 'rtmax rtmean Rrt'
81 flush(lb_log_unit)
82 lb_first_call = .false.
83 else if (lb_first_call) then
84 lb_first_call = .false.
85 end if
86 t_advance_start = mpi_wtime()
87 lb_compute_accum = 0.0d0
88 lb_tc_accum = 0.0d0
89 lb_cool_accum = 0.0d0
90 end if
91
92 ! Per-block cost reset for the cost-weighted load balancer.
93 ! Cleared every step before the iigrid loops fill it.
94 ! Seed with the sweep cost measured by rt_sc_solve() earlier this step, then
95 ! clear that accumulator for the next solve. The hydro timers below add on
96 ! top, so the partitioner sees transfer and hydro cost for the same step.
97 if (lb_automatic) then
99 block_cost_rt = 0.0d0
100 end if
101
102 ! split source addition
103 call add_split_source(prior=.true.) !> calculates temperature based on conservative state
104
105 if(dimsplit) then
106 if((iit/2)*2==iit .or. typedimsplit=='xy') then
107 ! do the sweeps in order of increasing idim,
108 do idimsplit=1,ndim
109 call advect(idimsplit,idimsplit)
110 end do
111 else
112 ! If the parity of "iit" is odd and typedimsplit=xyyx,
113 ! do sweeps backwards
114 do idimsplit=ndim,1,-1
115 call advect(idimsplit,idimsplit)
116 end do
117 end if
118 else
119 ! Add fluxes from all directions at once
120 call advect(1,ndim)
121 end if
122
123 ! split source addition
124 call add_split_source(prior=.false.) !> calculates temperature based on conservative state
125
126 if(use_particles) call handle_particles
127
128 !$OMP PARALLEL DO PRIVATE(igrid)
129 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
130 call eos%update_eos(ixg^ll,ixg^ll,ps(igrid)%w,ps(igrid)%x)
131 end do
132 !$OMP END PARALLEL DO
133
134 ! Cost-weighted load balancer: per-block measurements in block_cost
135 ! (per-rank, per-igrid) are folded into the global Morton-indexed
136 ! costlist via EWMA blend inside get_Morton_range_costed when
137 ! load_balance is next invoked. No end-of-advance work needed here.
138
139 if (lb_diagnose) then
140 t_advance_local = mpi_wtime() - t_advance_start
141 if (mype==0) then
142 call mpi_gather(t_advance_local,1,mpi_double_precision, &
143 t_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
144 call mpi_gather(lb_compute_accum,1,mpi_double_precision, &
145 c_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
146 call mpi_gather(lb_tc_accum,1,mpi_double_precision, &
147 tc_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
148 call mpi_gather(lb_cool_accum,1,mpi_double_precision, &
149 cool_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
150 call mpi_gather(lb_rt_accum,1,mpi_double_precision, &
151 rt_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
152 tmax = maxval(t_all_ranks)
153 tmean = sum(t_all_ranks)/dble(npe)
154 cmax = maxval(c_all_ranks)
155 cmean = sum(c_all_ranks)/dble(npe)
156 tcmax = maxval(tc_all_ranks)
157 tcmean = sum(tc_all_ranks)/dble(npe)
158 coolmax = maxval(cool_all_ranks)
159 coolmean = sum(cool_all_ranks)/dble(npe)
160 rtmax = maxval(rt_all_ranks)
161 rtmean = sum(rt_all_ranks)/dble(npe)
162 if (tmean > 0.0d0) then
163 ratio = tmax/tmean
164 else
165 ratio = 1.0d0
166 end if
167 if (cmean > 0.0d0) then
168 ratioc = cmax/cmean
169 else
170 ratioc = 1.0d0
171 end if
172 if (tcmean > 0.0d0) then
173 ratiotc = tcmax/tcmean
174 else
175 ratiotc = 1.0d0
176 end if
177 if (coolmean > 0.0d0) then
178 ratiocool = coolmax/coolmean
179 else
180 ratiocool = 1.0d0
181 end if
182 if (rtmean > 0.0d0) then
183 ratiort = rtmax/rtmean
184 else
185 ratiort = 1.0d0
186 end if
187 write(lb_log_unit,'(i10,1x,es16.8,1x)',advance='no') it, global_time
188 do ipe=1,npe
189 write(lb_log_unit,'(es14.6,1x)',advance='no') t_all_ranks(ipe)
190 end do
191 do ipe=1,npe
192 write(lb_log_unit,'(es14.6,1x)',advance='no') c_all_ranks(ipe)
193 end do
194 do ipe=1,npe
195 write(lb_log_unit,'(es14.6,1x)',advance='no') tc_all_ranks(ipe)
196 end do
197 do ipe=1,npe
198 write(lb_log_unit,'(es14.6,1x)',advance='no') cool_all_ranks(ipe)
199 end do
200 do ipe=1,npe
201 write(lb_log_unit,'(es14.6,1x)',advance='no') rt_all_ranks(ipe)
202 end do
203 write(lb_log_unit,'(15(es14.6,1x))') &
204 tmax, tmean, ratio, cmax, cmean, ratioc, &
205 tcmax, tcmean, ratiotc, coolmax, coolmean, ratiocool, &
206 rtmax, rtmean, ratiort
207 flush(lb_log_unit)
208 else
209 call mpi_gather(t_advance_local,1,mpi_double_precision, &
210 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
211 call mpi_gather(lb_compute_accum,1,mpi_double_precision, &
212 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
213 call mpi_gather(lb_tc_accum,1,mpi_double_precision, &
214 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
215 call mpi_gather(lb_cool_accum,1,mpi_double_precision, &
216 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
217 call mpi_gather(lb_rt_accum,1,mpi_double_precision, &
218 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
219 end if
220 ! The sweep accumulates before advance is entered, so it is cleared here,
221 ! after the gather, rather than in the reset block at the top.
222 lb_rt_accum = 0.0d0
223 end if
224
225 end subroutine advance
226
227 !> Advance all grids over one time step, but without taking dimensional
228 !> splitting or split source terms into account
229 subroutine advect(idim^LIM)
233 use mod_comm_lib, only: mpistop
234
235 integer, intent(in) :: idim^lim
236 integer :: iigrid, igrid
237
238 call init_comm_fix_conserve(idim^lim,nwflux)
239 fix_conserve_at_step = time_advance .and. levmax>levmin
240
241 ! copy w instead of wold because of potential use of dimsplit or sourcesplit
242 !$OMP PARALLEL DO PRIVATE(igrid)
243 do iigrid=1,igridstail; igrid=igrids(iigrid);
244 ps1(igrid)%w=ps(igrid)%w
245 if(stagger_grid) ps1(igrid)%ws=ps(igrid)%ws
246 end do
247 !$OMP END PARALLEL DO
248
249 istep = 0
250
251 select case (t_stepper)
252 case (onestep)
253 select case (t_integrator)
254 case (forward_euler)
255 call advect1(flux_method,one,idim^lim,global_time,ps1,global_time,ps)
256
257 case (imex_euler)
258 call advect1(flux_method,one,idim^lim,global_time,ps,global_time,ps1)
259 call global_implicit_update(one,dt,global_time+dt,ps,ps1)
260
261 case (imex_sp)
262 call global_implicit_update(one,dt,global_time,ps,ps1)
263 !$OMP PARALLEL DO PRIVATE(igrid)
264 do iigrid=1,igridstail; igrid=igrids(iigrid);
265 ps1(igrid)%w=ps(igrid)%w
266 if(stagger_grid) ps1(igrid)%ws=ps(igrid)%ws
267 end do
268 !$OMP END PARALLEL DO
269 call advect1(flux_method,one,idim^lim,global_time,ps1,global_time,ps)
270
271 case default
272 call mpistop("unkown onestep time_integrator in advect")
273 end select
274
275 case (twostep)
276 select case (t_integrator)
278 ! PC or explicit midpoint
279 ! predictor step
280 fix_conserve_at_step = .false.
281 call advect1(typepred1,half,idim^lim,global_time,ps,global_time,ps1)
282 ! corrector step
283 fix_conserve_at_step = time_advance .and. levmax>levmin
284 call advect1(flux_method,one,idim^lim,global_time+half*dt,ps1,global_time,ps)
285
286 case (rk2_alf)
287 ! RK2 with alfa parameter, where rk_a21=alfa
288 call advect1(flux_method,rk_a21, idim^lim,global_time,ps,global_time,ps1)
289 !$OMP PARALLEL DO PRIVATE(igrid)
290 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
291 ps(igrid)%w = ps(igrid)%w+rk_b1*(ps1(igrid)%w-ps(igrid)%w)/rk_a21
292 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws+(one-rk_b2)*(ps1(igrid)%ws-ps(igrid)%ws)/rk_a21
293 end do
294 !$OMP END PARALLEL DO
295 call advect1(flux_method,rk_b2,idim^lim,global_time+rk_a21*dt,ps1,global_time+rk_b1*dt,ps)
296
297 case (ssprk2)
298 ! ssprk2 or Heun's method
299 call advect1(flux_method,one, idim^lim,global_time,ps,global_time,ps1)
300 !$OMP PARALLEL DO PRIVATE(igrid)
301 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
302 ps(igrid)%w = half*ps(igrid)%w+half*ps1(igrid)%w
303 if(stagger_grid) ps(igrid)%ws = half*ps(igrid)%ws+half*ps1(igrid)%ws
304 end do
305 !$OMP END PARALLEL DO
306 call advect1(flux_method,half,idim^lim,global_time+dt,ps1,global_time+half*dt,ps)
307
308 case (imex_midpoint)
309 call advect1(flux_method,half, idim^lim,global_time,ps,global_time,ps1)
310 call global_implicit_update(half,dt,global_time+half*dt,ps2,ps1)
311 !$OMP PARALLEL DO PRIVATE(igrid)
312 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
313 ps(igrid)%w = ps(igrid)%w+2.0d0*(ps2(igrid)%w-ps1(igrid)%w)
314 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws+2.0d0*(ps2(igrid)%ws-ps1(igrid)%ws)
315 end do
316 !$OMP END PARALLEL DO
317 call advect1(flux_method,one, idim^lim,global_time+half*dt,ps2,global_time,ps)
318
319 case (imex_trapezoidal)
320 call advect1(flux_method,one, idim^lim,global_time,ps,global_time,ps1)
321 !$OMP PARALLEL DO PRIVATE(igrid)
322 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
323 ps2(igrid)%w = half*(ps(igrid)%w+ps1(igrid)%w)
324 if(stagger_grid) ps2(igrid)%ws = half*(ps(igrid)%ws+ps1(igrid)%ws)
325 end do
326 !$OMP END PARALLEL DO
327 call evaluate_implicit(global_time,ps)
328 !$OMP PARALLEL DO PRIVATE(igrid)
329 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
330 ps1(igrid)%w = ps1(igrid)%w+half*dt*ps(igrid)%w
331 if(stagger_grid) ps1(igrid)%ws = ps1(igrid)%ws+half*dt*ps(igrid)%ws
332 end do
333 !$OMP END PARALLEL DO
334 !$OMP PARALLEL DO PRIVATE(igrid)
335 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
336 ps(igrid)%w = ps2(igrid)%w+half*dt*ps(igrid)%w
337 if(stagger_grid) ps(igrid)%ws = ps2(igrid)%ws+half*dt*ps(igrid)%ws
338 end do
339 !$OMP END PARALLEL DO
340 call getbc(global_time+dt,dt,ps1,iwstart,nwgc)
341 call global_implicit_update(half,dt,global_time+dt,ps2,ps1)
342 !$OMP PARALLEL DO PRIVATE(igrid)
343 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
344 ps(igrid)%w = ps(igrid)%w+ps2(igrid)%w-ps1(igrid)%w
345 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws+ps2(igrid)%ws-ps1(igrid)%ws
346 end do
347 !$OMP END PARALLEL DO
348 call advect1(flux_method,half, idim^lim,global_time+dt,ps2,global_time+half*dt,ps)
349
350 case (imex_222)
351 ! One-parameter family of schemes (parameter is imex222_lambda) from
352 ! Pareschi&Russo 2005, which is L-stable (for default lambda) and
353 ! asymptotically SSP.
354 ! See doi.org/10.1007/s10915-004-4636-4 (table II)
355 ! See doi.org/10.1016/j.apnum.2016.10.018 for interesting values of lambda
356
357 ! Preallocate ps2 as y^n for the implicit update
358 !$OMP PARALLEL DO PRIVATE(igrid)
359 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
360 ps2(igrid)%w = ps(igrid)%w
361 if(stagger_grid) ps2(igrid)%ws = ps(igrid)%ws
362 end do
363 !$OMP END PARALLEL DO
364 ! Solve xi1 = y^n + lambda.dt.F_im(xi1)
365 call global_implicit_update(imex222_lambda, dt, global_time, ps2, ps)
366
367 ! Set ps1 = y^n + dt.F_ex(xi1)
368 call advect1(flux_method, one, idim^lim, global_time, ps2, global_time, ps1)
369 ! Set ps2 = dt.F_im(xi1) (is at t^n)
370 ! Set ps = y^n + dt/2 . F(xi1) (is at t^n+dt/2)
371 ! Set ps1 = y^n + dt.F_ex(xi1) + (1-2.lambda).dt.F_im(xi1) and enforce BC (at t^n+dt)
372 !$OMP PARALLEL DO PRIVATE(igrid)
373 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
374 ps2(igrid)%w = (ps2(igrid)%w - ps(igrid)%w) / imex222_lambda
375 if(stagger_grid) ps2(igrid)%ws = (ps2(igrid)%ws - ps(igrid)%ws) / imex222_lambda
376 end do
377 !$OMP END PARALLEL DO
378 !$OMP PARALLEL DO PRIVATE(igrid)
379 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
380 ps(igrid)%w = half*(ps(igrid)%w + ps1(igrid)%w + ps2(igrid)%w)
381 if(stagger_grid) ps(igrid)%ws = half*(ps(igrid)%ws + ps1(igrid)%ws + ps2(igrid)%ws)
382 end do
383 !$OMP END PARALLEL DO
384 !$OMP PARALLEL DO PRIVATE(igrid)
385 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
386 ps1(igrid)%w = ps1(igrid)%w + (1.0d0 - 2.0d0*imex222_lambda)*ps2(igrid)%w
387 if(stagger_grid) ps1(igrid)%ws = ps1(igrid)%ws + (1.0d0 - 2.0d0*imex222_lambda)*ps2(igrid)%ws
388 end do
389 !$OMP END PARALLEL DO
390 call getbc(global_time+dt,dt,ps1,iwstart,nwgc)
391
392 ! Preallocate ps2 as xi1 for the implicit update (is at t^n)
393 !$OMP PARALLEL DO PRIVATE(igrid)
394 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
395 ps2(igrid)%w = 2.0d0*ps2(igrid)%w - ps1(igrid)%w - imex222_lambda*ps2(igrid)%w
396 if(stagger_grid) ps2(igrid)%ws = 2.0d0*ps2(igrid)%ws - ps1(igrid)%ws - imex222_lambda*ps2(igrid)%ws
397 end do
398 !$OMP END PARALLEL DO
399 ! Solve xi2 = (ps1) + lambda.dt.F_im(xi2)
400 call global_implicit_update(imex222_lambda, dt, global_time, ps2, ps1)
401
402 ! Add dt/2.F_im(xi2) to ps
403 !$OMP PARALLEL DO PRIVATE(igrid)
404 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
405 ps(igrid)%w = ps(igrid)%w + (ps2(igrid)%w - ps1(igrid)%w) / (2.0d0 * imex222_lambda)
406 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + (ps2(igrid)%ws - ps1(igrid)%ws) / (2.0d0 * imex222_lambda)
407 end do
408 !$OMP END PARALLEL DO
409 ! Set ps = y^n + dt/2.(F(xi1)+F(xi2)) = y^(n+1)
410 call advect1(flux_method, half, idim^lim, global_time+dt, ps2, global_time+half*dt, ps)
411
412 case default
413 call mpistop("unkown twostep time_integrator in advect")
414 end select
415
416 case (threestep)
417 select case (t_integrator)
418 case (ssprk3)
419 ! this is SSPRK(3,3) Gottlieb-Shu 1998 or SSP(3,2) depending on ssprk_order (3 vs 2)
420 call advect1(flux_method,rk_beta11, idim^lim,global_time,ps,global_time,ps1)
421 !$OMP PARALLEL DO PRIVATE(igrid)
422 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
423 ps2(igrid)%w=rk_alfa21*ps(igrid)%w+rk_alfa22*ps1(igrid)%w
424 if(stagger_grid) ps2(igrid)%ws=rk_alfa21*ps(igrid)%ws+rk_alfa22*ps1(igrid)%ws
425 end do
426 !$OMP END PARALLEL DO
427 call advect1(flux_method,rk_beta22, idim^lim,global_time+rk_c2*dt,ps1,global_time+rk_alfa22*rk_c2*dt,ps2)
428 !$OMP PARALLEL DO PRIVATE(igrid)
429 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
430 ps(igrid)%w=rk_alfa31*ps(igrid)%w+rk_alfa33*ps2(igrid)%w
431 if(stagger_grid) ps(igrid)%ws=rk_alfa31*ps(igrid)%ws+rk_alfa33*ps2(igrid)%ws
432 end do
433 !$OMP END PARALLEL DO
434 call advect1(flux_method,rk_beta33, idim^lim,global_time+rk_c3*dt,ps2,global_time+(1.0d0-rk_beta33)*dt,ps)
435
436 case (rk3_bt)
437 ! this is a general threestep RK according to its Butcher Table
438 call advect1(flux_method,rk3_a21, idim^lim,global_time,ps,global_time,ps1)
439 !$OMP PARALLEL DO PRIVATE(igrid)
440 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
441 ps3(igrid)%w=(ps1(igrid)%w-ps(igrid)%w)/rk3_a21
442 if(stagger_grid) ps3(igrid)%ws=(ps1(igrid)%ws-ps(igrid)%ws)/rk3_a21
443 end do
444 !$OMP END PARALLEL DO
445 !$OMP PARALLEL DO PRIVATE(igrid)
446 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
447 ps2(igrid)%w=ps(igrid)%w+rk3_a31*ps3(igrid)%w
448 if(stagger_grid) ps2(igrid)%ws=ps(igrid)%ws+rk3_a31*ps3(igrid)%ws
449 end do
450 !$OMP END PARALLEL DO
451 call advect1(flux_method,rk3_a32, idim^lim,global_time+rk3_c2*dt,ps1,global_time+rk3_a31*dt,ps2)
452 !$OMP PARALLEL DO PRIVATE(igrid)
453 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
454 ps(igrid)%w=ps(igrid)%w+rk3_b1*ps3(igrid)%w &
455 +rk3_b2*(ps2(igrid)%w-(ps(igrid)%w+rk3_a31*ps3(igrid)%w))/rk3_a32
456 if(stagger_grid)then
457 ps(igrid)%ws=ps(igrid)%ws+rk3_b1*ps3(igrid)%ws &
458 +rk3_b2*(ps2(igrid)%ws-(ps(igrid)%ws+rk3_a31*ps3(igrid)%ws))/rk3_a32
459 endif
460 end do
461 !$OMP END PARALLEL DO
462 call advect1(flux_method,rk3_b3, idim^lim,global_time+rk3_c3*dt,ps2,global_time+(1.0d0-rk3_b3)*dt,ps)
463
464 case (imex_ars3)
465 ! this is IMEX scheme ARS3
466 call advect1(flux_method,ars_gamma, idim^lim,global_time,ps,global_time,ps1)
467 !$OMP PARALLEL DO PRIVATE(igrid)
468 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
469 ps4(igrid)%w=(ps1(igrid)%w-ps(igrid)%w)/ars_gamma
470 if(stagger_grid) ps4(igrid)%ws=(ps1(igrid)%ws-ps(igrid)%ws)/ars_gamma
471 end do
472 !$OMP END PARALLEL DO
473 call global_implicit_update(ars_gamma,dt,global_time+ars_gamma*dt,ps2,ps1)
474 !$OMP PARALLEL DO PRIVATE(igrid)
475 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
476 ps1(igrid)%w=(ps2(igrid)%w-ps1(igrid)%w)/ars_gamma
477 if(stagger_grid) ps1(igrid)%ws=(ps2(igrid)%ws-ps1(igrid)%ws)/ars_gamma
478 end do
479 !$OMP END PARALLEL DO
480 !$OMP PARALLEL DO PRIVATE(igrid)
481 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
482 ps3(igrid)%w=ps(igrid)%w+(ars_gamma-1.0d0)*ps4(igrid)%w+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%w
483 if(stagger_grid) then
484 ps3(igrid)%ws=ps(igrid)%ws+(ars_gamma-1.0d0)*ps4(igrid)%ws+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%ws
485 endif
486 end do
487 !$OMP END PARALLEL DO
488 call advect1(flux_method,2.0d0*(1.0d0-ars_gamma), idim^lim,global_time+ars_gamma*dt,ps2,global_time+(ars_gamma-1.0d0)*dt,ps3)
489 !$OMP PARALLEL DO PRIVATE(igrid)
490 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
491 ps2(igrid)%w=ps1(igrid)%w+(ps3(igrid)%w-(ps(igrid)%w+ &
492 (ars_gamma-1.0d0)*ps4(igrid)%w+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%w))/(2.0d0*(1.0d0-ars_gamma))
493 if(stagger_grid) then
494 ps2(igrid)%ws=ps1(igrid)%ws+(ps3(igrid)%ws-(ps(igrid)%ws+ &
495 (ars_gamma-1.0d0)*ps4(igrid)%ws+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%ws))/(2.0d0*(1.0d0-ars_gamma))
496 endif
497 end do
498 !$OMP END PARALLEL DO
499 call global_implicit_update(ars_gamma,dt,global_time+(1.0d0-ars_gamma)*dt,ps4,ps3)
500 !$OMP PARALLEL DO PRIVATE(igrid)
501 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
502 ps(igrid)%w=ps(igrid)%w+half*ps2(igrid)%w &
503 +half*(ps4(igrid)%w-ps3(igrid)%w)/ars_gamma
504 if(stagger_grid) then
505 ps(igrid)%ws=ps(igrid)%ws+half*ps2(igrid)%ws &
506 +half*(ps4(igrid)%ws-ps3(igrid)%ws)/ars_gamma
507 endif
508 end do
509 !$OMP END PARALLEL DO
510 call advect1(flux_method,half, idim^lim,global_time+(1.0d0-ars_gamma)*dt,ps4,global_time+half*dt,ps)
511
512 case (imex_232)
513 ! this is IMEX_ARK(2,3,2) or IMEX_SSP(2,3,2)
514 call advect1(flux_method,imex_a21, idim^lim,global_time,ps,global_time,ps1)
515 !$OMP PARALLEL DO PRIVATE(igrid)
516 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
517 ps4(igrid)%w=(ps1(igrid)%w-ps(igrid)%w)/imex_a21
518 ps3(igrid)%w=ps(igrid)%w
519 if(stagger_grid) then
520 ps4(igrid)%ws=(ps1(igrid)%ws-ps(igrid)%ws)/imex_a21
521 ps3(igrid)%ws=ps(igrid)%ws
522 endif
523 end do
524 !$OMP END PARALLEL DO
525 call evaluate_implicit(global_time,ps3)
526 !$OMP PARALLEL DO PRIVATE(igrid)
527 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
528 ps1(igrid)%w=ps1(igrid)%w+imex_ha21*dt*ps3(igrid)%w
529 if(stagger_grid) ps1(igrid)%ws=ps1(igrid)%ws+imex_ha21*dt*ps3(igrid)%ws
530 end do
531 !$OMP END PARALLEL DO
532 call getbc(global_time+imex_a21*dt,dt,ps1,iwstart,nwgc)
533 call global_implicit_update(imex_ha22,dt,global_time+imex_c2*dt,ps2,ps1)
534 !$OMP PARALLEL DO PRIVATE(igrid)
535 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
536 ps(igrid)%w=ps(igrid)%w+imex_a31*ps4(igrid)%w &
537 +imex_b1*dt*ps3(igrid)%w+imex_b2*(ps2(igrid)%w-ps1(igrid)%w)/imex_ha22
538 if(stagger_grid) then
539 ps(igrid)%ws=ps(igrid)%ws+imex_a31*ps4(igrid)%ws &
540 +imex_b1*dt*ps3(igrid)%ws+imex_b2*(ps2(igrid)%ws-ps1(igrid)%ws)/imex_ha22
541 endif
542 end do
543 !$OMP END PARALLEL DO
544 !$OMP PARALLEL DO PRIVATE(igrid)
545 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
546 ps3(igrid)%w=ps1(igrid)%w-imex_a21*ps4(igrid)%w &
547 -imex_ha21*dt*ps3(igrid)%w+imex_b1*dt*ps3(igrid)%w
548 if(stagger_grid) then
549 ps3(igrid)%ws=ps1(igrid)%ws-imex_a21*ps4(igrid)%ws &
550 -imex_ha21*dt*ps3(igrid)%ws+imex_b1*dt*ps3(igrid)%ws
551 endif
552 end do
553 !$OMP END PARALLEL DO
554 call advect1(flux_method,imex_a32, idim^lim,global_time+imex_c2*dt,ps2,global_time+imex_a31*dt,ps)
555 !$OMP PARALLEL DO PRIVATE(igrid)
556 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
557 ps2(igrid)%w=(ps(igrid)%w-ps3(igrid)%w-imex_a31*ps4(igrid)%w)/imex_a32 &
558 +(1.0d0-imex_b2/imex_a32)*(ps2(igrid)%w-ps1(igrid)%w)/imex_ha22
559 if(stagger_grid) then
560 ps2(igrid)%ws=(ps(igrid)%ws-ps3(igrid)%ws-imex_a31*ps4(igrid)%ws)/imex_a32 &
561 +(1.0d0-imex_b2/imex_a32)*(ps2(igrid)%ws-ps1(igrid)%ws)/imex_ha22
562 endif
563 end do
564 !$OMP END PARALLEL DO
565 !$OMP PARALLEL DO PRIVATE(igrid)
566 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
567 ps1(igrid)%w=ps3(igrid)%w+imex_b1*ps4(igrid)%w+imex_b2*ps2(igrid)%w
568 if(stagger_grid) then
569 ps1(igrid)%ws=ps3(igrid)%ws+imex_b1*ps4(igrid)%ws+imex_b2*ps2(igrid)%ws
570 endif
571 end do
572 !$OMP END PARALLEL DO
573 call global_implicit_update(imex_b3,dt,global_time+imex_c3*dt,ps2,ps)
574 !$OMP PARALLEL DO PRIVATE(igrid)
575 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
576 ps(igrid)%w=ps1(igrid)%w+ps2(igrid)%w-ps(igrid)%w
577 if(stagger_grid) then
578 ps(igrid)%ws=ps1(igrid)%ws+ps2(igrid)%ws-ps(igrid)%ws
579 endif
580 end do
581 !$OMP END PARALLEL DO
582 call advect1(flux_method,imex_b3, idim^lim,global_time+imex_c3*dt,ps2,global_time+(1.0d0-imex_b3)*dt,ps)
583
584 case (imex_cb3a)
585 ! Third order IMEX scheme with low-storage implementation (4 registers).
586 ! From Cavaglieri&Bewley 2015, see doi.org/10.1016/j.jcp.2015.01.031
587 ! (scheme called "IMEXRKCB3a" there). Uses 3 explicit and 2 implicit stages.
588 ! Parameters are in imex_bj, imex_cj (same for implicit/explicit),
589 ! imex_aij (implicit tableau) and imex_haij (explicit tableau).
590 call advect1(flux_method, imex_ha21, idim^lim, global_time, ps, global_time, ps1)
591 call global_implicit_update(imex_a22, dt, global_time+imex_c2*dt, ps2, ps1)
592 !$OMP PARALLEL DO PRIVATE(igrid)
593 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
594 ps3(igrid)%w = ps(igrid)%w + imex_a32/imex_a22 * (ps2(igrid)%w - ps1(igrid)%w)
595 ps(igrid)%w = ps(igrid)%w + imex_b2 /imex_a22 * (ps2(igrid)%w - ps1(igrid)%w)
596 ps1(igrid)%w = ps3(igrid)%w
597 if(stagger_grid) ps3(igrid)%ws = ps(igrid)%ws + imex_a32/imex_a22 * (ps2(igrid)%ws - ps1(igrid)%ws)
598 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + imex_b2 /imex_a22 * (ps2(igrid)%ws - ps1(igrid)%ws)
599 if(stagger_grid) ps1(igrid)%ws = ps3(igrid)%ws
600 end do
601 !$OMP END PARALLEL DO
602 call advect1(flux_method, imex_ha32, idim^lim, global_time+imex_c2*dt, ps2, global_time, ps3)
603 !$OMP PARALLEL DO PRIVATE(igrid)
604 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
605 ps(igrid)%w = ps(igrid)%w + imex_b2 /imex_ha32 * (ps3(igrid)%w - ps1(igrid)%w)
606 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + imex_b2 /imex_ha32 * (ps3(igrid)%ws - ps1(igrid)%ws)
607 end do
608 call global_implicit_update(imex_a33, dt, global_time+imex_c3*dt, ps1, ps3)
609 !$OMP PARALLEL DO PRIVATE(igrid)
610 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
611 ps(igrid)%w = ps(igrid)%w + imex_b3 /imex_a33 * (ps1(igrid)%w - ps3(igrid)%w)
612 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + imex_b3 /imex_a33 * (ps1(igrid)%ws - ps3(igrid)%ws)
613 end do
614 !$OMP END PARALLEL DO
615 call advect1(flux_method, imex_b3, idim^lim, global_time+imex_c3*dt, ps1, global_time+imex_b2*dt, ps)
616
617 case default
618 call mpistop("unkown threestep time_integrator in advect")
619 end select
620
621 case (fourstep)
622 select case (t_integrator)
623 case (ssprk4)
624 ! SSPRK(4,3) or SSP(4,2) depending on ssprk_order (3 vs 2)
625 ! ssprk43: Strong stability preserving 4 stage RK 3rd order by Ruuth and Spiteri
626 ! Ruuth & Spiteri J. S C, 17 (2002) p. 211 - 220
627 ! supposed to be stable up to CFL=2.
628 ! ssp42: stable up to CFL=3
629 call advect1(flux_method,rk_beta11, idim^lim,global_time,ps,global_time,ps1)
630 !$OMP PARALLEL DO PRIVATE(igrid)
631 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
632 ps2(igrid)%w=rk_alfa21*ps(igrid)%w+rk_alfa22*ps1(igrid)%w
633 if(stagger_grid) ps2(igrid)%ws=rk_alfa21*ps(igrid)%ws+rk_alfa22*ps1(igrid)%ws
634 end do
635 !$OMP END PARALLEL DO
636 call advect1(flux_method,rk_beta22, idim^lim,global_time+rk_c2*dt,ps1,global_time+rk_alfa22*rk_c2*dt,ps2)
637 !$OMP PARALLEL DO PRIVATE(igrid)
638 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
639 ps1(igrid)%w=rk_alfa31*ps(igrid)%w+rk_alfa33*ps2(igrid)%w
640 if(stagger_grid) ps1(igrid)%ws=rk_alfa31*ps(igrid)%ws+rk_alfa33*ps2(igrid)%ws
641 end do
642 !$OMP END PARALLEL DO
643 call advect1(flux_method,rk_beta33, idim^lim,global_time+rk_c3*dt,ps2,global_time+rk_alfa33*rk_c3*dt,ps1)
644 !$OMP PARALLEL DO PRIVATE(igrid)
645 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
646 ps(igrid)%w=rk_alfa41*ps(igrid)%w+rk_alfa44*ps1(igrid)%w
647 if(stagger_grid) ps(igrid)%ws=rk_alfa41*ps(igrid)%ws+rk_alfa44*ps1(igrid)%ws
648 end do
649 !$OMP END PARALLEL DO
650 call advect1(flux_method,rk_beta44, idim^lim,global_time+rk_c4*dt,ps1,global_time+(1.0d0-rk_beta44)*dt,ps)
651
652 case (rk4)
653 ! the standard RK(4,4) method
654 !$OMP PARALLEL DO PRIVATE(igrid)
655 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
656 ps2(igrid)%w=ps(igrid)%w
657 ps3(igrid)%w=ps(igrid)%w
658 if(stagger_grid) then
659 ps2(igrid)%ws=ps(igrid)%ws
660 ps3(igrid)%ws=ps(igrid)%ws
661 endif
662 end do
663 !$OMP END PARALLEL DO
664 call advect1(flux_method,half, idim^lim,global_time,ps,global_time,ps1)
665 call advect1(flux_method,half, idim^lim,global_time+half*dt,ps1,global_time,ps2)
666 call advect1(flux_method,1.0d0, idim^lim,global_time+half*dt,ps2,global_time,ps3)
667 !$OMP PARALLEL DO PRIVATE(igrid)
668 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
669 ps(igrid)%w=(1.0d0/3.0d0)*(-ps(igrid)%w+ps1(igrid)%w+2.0d0*ps2(igrid)%w+ps3(igrid)%w)
670 if(stagger_grid) ps(igrid)%ws=(1.0d0/3.0d0) &
671 *(-ps(igrid)%ws+ps1(igrid)%ws+2.0d0*ps2(igrid)%ws+ps3(igrid)%ws)
672 end do
673 !$OMP END PARALLEL DO
674 call advect1(flux_method,1.0d0/6.0d0, idim^lim,global_time+dt,ps3,global_time+dt*5.0d0/6.0d0,ps)
675
676 case default
677 call mpistop("unkown fourstep time_integrator in advect")
678 end select
679
680 case (fivestep)
681 select case (t_integrator)
682 case (ssprk5)
683 ! SSPRK(5,4) by Ruuth and Spiteri
684 !bcexch = .false.
685 call advect1(flux_method,rk_beta11, idim^lim,global_time,ps,global_time,ps1)
686 !$OMP PARALLEL DO PRIVATE(igrid)
687 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
688 ps2(igrid)%w=rk_alfa21*ps(igrid)%w+rk_alfa22*ps1(igrid)%w
689 if(stagger_grid) ps2(igrid)%ws=rk_alfa21*ps(igrid)%ws+rk_alfa22*ps1(igrid)%ws
690 end do
691 !$OMP END PARALLEL DO
692 call advect1(flux_method,rk_beta22, idim^lim,global_time+rk_c2*dt,ps1,global_time+rk_alfa22*rk_c2*dt,ps2)
693 !$OMP PARALLEL DO PRIVATE(igrid)
694 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
695 ps1(igrid)%w=rk_alfa31*ps(igrid)%w+rk_alfa33*ps2(igrid)%w
696 if(stagger_grid) ps1(igrid)%ws=rk_alfa31*ps(igrid)%ws+rk_alfa33*ps2(igrid)%ws
697 end do
698 !$OMP END PARALLEL DO
699 call advect1(flux_method,rk_beta33, idim^lim,global_time+rk_c3*dt,ps2,global_time+rk_alfa33*rk_c3*dt,ps1)
700 !$OMP PARALLEL DO PRIVATE(igrid)
701 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
702 ps3(igrid)%w=rk_alfa53*ps2(igrid)%w+rk_alfa54*ps1(igrid)%w
703 if(stagger_grid) ps3(igrid)%ws=rk_alfa53*ps2(igrid)%ws+rk_alfa54*ps1(igrid)%ws
704 end do
705 !$OMP END PARALLEL DO
706 !$OMP PARALLEL DO PRIVATE(igrid)
707 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
708 ps2(igrid)%w=rk_alfa41*ps(igrid)%w+rk_alfa44*ps1(igrid)%w
709 if(stagger_grid) ps2(igrid)%ws=rk_alfa41*ps(igrid)%ws+rk_alfa44*ps1(igrid)%ws
710 end do
711 !$OMP END PARALLEL DO
712 call advect1(flux_method,rk_beta44, idim^lim,global_time+rk_c4*dt,ps1,global_time+rk_alfa44*rk_c4*dt,ps2)
713 !$OMP PARALLEL DO PRIVATE(igrid)
714 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
715 ps(igrid)%w=ps3(igrid)%w+rk_alfa55*ps2(igrid)%w &
716 +(rk_beta54/rk_beta44)*(ps2(igrid)%w-(rk_alfa41*ps(igrid)%w+rk_alfa44*ps1(igrid)%w))
717 if(stagger_grid) then
718 ps(igrid)%ws=ps3(igrid)%ws+rk_alfa55*ps2(igrid)%ws &
719 +(rk_beta54/rk_beta44)*(ps2(igrid)%ws-(rk_alfa41*ps(igrid)%ws+rk_alfa44*ps1(igrid)%ws))
720 endif
721 end do
722 !$OMP END PARALLEL DO
723 !bcexch = .true.
724 call advect1(flux_method,rk_beta55, idim^lim,global_time+rk_c5*dt,ps2,global_time+(1.0d0-rk_beta55)*dt,ps)
725
726 case default
727 call mpistop("unkown fivestep time_integrator in advect")
728 end select
729
730 case default
731 call mpistop("unkown time_stepper in advect")
732 end select
733
734 end subroutine advect
735
736 !> Implicit global update step within IMEX schemes, advance psa=psb+dtfactor*qdt*F_im(psa)
737 subroutine global_implicit_update(dtfactor,qdt,qtC,psa,psb)
741
742 type(state), target :: psa(max_blocks) !< Compute implicit part from this state and update it
743 type(state), target :: psb(max_blocks) !< Will be unchanged, as on entry
744 double precision, intent(in) :: qdt !< overall time step dt
745 double precision, intent(in) :: qtc !< Both states psa and psb at this time level
746 double precision, intent(in) :: dtfactor !< Advance psa=psb+dtfactor*qdt*F_im(psa)
747
748 integer :: iigrid, igrid
749
750 !> First copy all variables from a to b, this is necessary to account for
751 ! quantities in w with no implicit sourceterm
752 do iigrid=1,igridstail; igrid=igrids(iigrid);
753 psa(igrid)%w = psb(igrid)%w
754 if(stagger_grid) psa(igrid)%ws = psb(igrid)%ws
755 end do
756
757 if (associated(phys_implicit_update)) then
758 call phys_implicit_update(dtfactor,qdt,qtc,psa,psb)
759 end if
760
761 ! enforce boundary conditions for psa
762 call getbc(qtc,0.d0,psa,iwstart,nwgc)
763
764 end subroutine global_implicit_update
765
766 !> Evaluate Implicit part in place, i.e. psa==>F_im(psa)
767 subroutine evaluate_implicit(qtC,psa)
770 type(state), target :: psa(max_blocks) !< Compute implicit part from this state and update it
771 double precision, intent(in) :: qtc !< psa at this time level
772
773 if (associated(phys_evaluate_implicit)) then
774 call phys_evaluate_implicit(qtc,psa)
775 end if
776 end subroutine evaluate_implicit
777
778 !> Integrate all grids by one partial step
779 subroutine advect1(method,dtfactor,idim^LIM,qtC,psa,qt,psb)
783 use mod_physics
784 use mod_eos
785
786 integer, intent(in) :: idim^lim
787 type(state), target :: psa(max_blocks) !< Compute fluxes based on this state
788 type(state), target :: psb(max_blocks) !< Update solution on this state
789 double precision, intent(in) :: dtfactor !< Advance over dtfactor * dt
790 double precision, intent(in) :: qtc
791 double precision, intent(in) :: qt
792 integer, intent(in) :: method(nlevelshi)
793
794 double precision :: qdt
795 double precision :: lb_t0_advect1, lb_t0_block
796 integer :: iigrid, igrid
797
798 istep = istep+1
799
800 if(associated(phys_special_advance)) then
801 call phys_special_advance(qtc,psa)
802 end if
803
804 qdt=dtfactor*dt
805 ! opedit: Just advance the active grids:
806 if (lb_diagnose) lb_t0_advect1 = mpi_wtime()
807 !$OMP PARALLEL DO PRIVATE(igrid,lb_t0_block)
808 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
809 if (lb_automatic) lb_t0_block = mpi_wtime()
810 block=>ps(igrid)
811 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
812 call eos%update_eos(ixg^ll,ixg^ll,psa(igrid)%w,psa(igrid)%x)
813 call advect1_grid(igrid,method(block%level),qdt,dtfactor,ixg^ll,idim^lim,&
814 qtc,psa(igrid),qt,psb(igrid),rnode(rpdx1_:rnodehi,igrid),ps(igrid)%x)
815 if (lb_automatic) block_cost(igrid) = block_cost(igrid) + (mpi_wtime() - lb_t0_block)
816 end do
817 !$OMP END PARALLEL DO
818 if (lb_diagnose) lb_compute_accum = lb_compute_accum + (mpi_wtime() - lb_t0_advect1)
819
820 ! opedit: Send flux for all grids, expects sends for all
821 ! nsend_fc(^D), set in connectivity.t.
822
823 if (fix_conserve_global .and. fix_conserve_at_step) then
824 call recvflux(idim^lim)
825 call sendflux(idim^lim)
826 call fix_conserve(psb,idim^lim,1,nwflux)
827 if(stagger_grid) then
828 call fix_edges(psb,idim^lim)
829 ! fill the cell-center values from the updated staggered variables
830 !$OMP PARALLEL DO PRIVATE(igrid)
831 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
832 call phys_face_to_center(ixm^ll,psb(igrid))
833 end do
834 !$OMP END PARALLEL DO
835 end if
836 end if
837
838 ! For all grids: fill ghost cells
839 call getbc(qt+qdt,qdt,psb,iwstart,nwgc)
840
841 end subroutine advect1
842
843 !> Advance a single grid over one partial time step
844 subroutine advect1_grid(igrid,method,qdt,dtfactor,ixI^L,idim^LIM,qtC,sCT,qt,s,dxs,x)
845
846 ! integrate one grid by one partial step
849 use mod_tvd
850 use mod_source, only: addsource2
853 use mod_comm_lib, only: mpistop
855
856 integer, intent(in) :: igrid,method
857 integer, intent(in) :: ixi^l, idim^lim
858 double precision, intent(in) :: qdt, dtfactor, qtc, qt, dxs(ndim), x(ixi^s,1:ndim)
859 type(state), target :: sct, s
860
861 ! cell face flux
862 double precision :: fc(ixi^s,1:nwflux,1:ndim)
863 ! cell edge flux
864 double precision :: fe(ixi^s,sdim:3)
865 double precision :: wprim(ixi^s,1:nw)
866 integer :: ixo^l
867
868 ! for mf module
869 if(iwstart>1) fc=0.d0
870
871 ixo^l=ixi^l^lsubnghostcells;
872 select case (method)
874 call finite_volume(method,qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
875 case (fs_cd,fs_cd4)
876 call centdiff(method,qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
877 case (fs_hancock)
878 call hancock(qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,dxs,x)
879 case (fs_fd)
880 call fd(qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
881 case (fs_tvd)
882 call centdiff(fs_cd,qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
883 call tvdlimit(method,qdt,ixi^l,ixo^l,idim^lim,sct,qt+qdt,s,fc,dxs,x)
884 case (fs_source)
885 fc=0.d0
886 fe=0.d0
887 wprim=sct%w
888 call phys_to_primitive(ixi^l,ixi^l,wprim,x)
889 call addsource2(qdt*dble(idimmax-idimmin+1)/dble(ndim),&
890 dtfactor*dble(idimmax-idimmin+1)/dble(ndim),&
891 ixi^l,ixo^l,1,nw,qtc,sct%w,wprim,qt,s%w,x,.false.)
892 case (fs_nul)
893 ! There is nothing to do
894 case default
895 call mpistop("unknown flux scheme in advect1_grid")
896 end select
897
898 ! opedit: Obviously, flux is stored only for active grids.
899 ! but we know in fix_conserve wether there is a passive neighbor
900 ! but we know in conserve_fix wether there is a passive neighbor
901 ! via neighbor_active(i^D,igrid) thus we skip the correction for those.
902 ! This violates strict conservation when the active/passive interface
903 ! coincides with a coarse/fine interface.
904 if (fix_conserve_global .and. fix_conserve_at_step) then
905 call store_flux(igrid,fc,idim^lim,nwflux)
906 if(stagger_grid) call store_edge(igrid,ixg^ll,fe,idim^lim)
907 end if
908
909 end subroutine advect1_grid
910
911 !> process is a user entry in time loop, before output and advance
912 !> allows to modify solution, add extra variables, etc.
913 !> Warning: CFL dt already determined (and is not recomputed)!
914 subroutine process(iit,qt)
918 ! .. scalars ..
919 integer,intent(in) :: iit
920 double precision, intent(in):: qt
921
922 integer:: iigrid, igrid
923
924 if (associated(usr_process_global)) then
925 call usr_process_global(iit,qt)
926 end if
927
928 if (associated(usr_process_grid)) then
929 !$OMP PARALLEL DO PRIVATE(igrid)
930 do iigrid=1,igridstail; igrid=igrids(iigrid);
931 ! next few lines ensure correct usage of routines like divvector etc
932 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
933 block=>ps(igrid)
934 call usr_process_grid(igrid,node(plevel_,igrid),ixg^ll,ixm^ll, &
935 qt,ps(igrid)%w,ps(igrid)%x)
936 end do
937 !$OMP END PARALLEL DO
938 call getbc(qt,dt,ps,iwstart,nwgc)
939 end if
940 end subroutine process
941
942 !> process_advanced is user entry in time loop, just after advance
943 !> allows to modify solution, add extra variables, etc.
944 !> added for handling two-way coupled PIC-MHD
945 !> Warning: w is now at global_time^(n+1), global time and iteration at global_time^n, it^n
946 subroutine process_advanced(iit,qt)
951 ! .. scalars ..
952 integer,intent(in) :: iit
953 double precision, intent(in):: qt
954
955 integer:: iigrid, igrid
956
957 if (associated(usr_process_adv_global)) then
958 call usr_process_adv_global(iit,qt)
959 end if
960
961 if (associated(usr_process_adv_grid)) then
962 !$OMP PARALLEL DO PRIVATE(igrid)
963 do iigrid=1,igridstail; igrid=igrids(iigrid);
964 ! next few lines ensure correct usage of routines like divvector etc
965 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
966 block=>ps(igrid)
967
968 call usr_process_adv_grid(igrid,node(plevel_,igrid),ixg^ll,ixm^ll, &
969 qt,ps(igrid)%w,ps(igrid)%x)
970 end do
971 !$OMP END PARALLEL DO
972 call getbc(qt,dt,ps,iwstart,nwgc)
973 end if
974 end subroutine process_advanced
975
976end module mod_advance
Module containing all the time stepping schemes.
Definition mod_advance.t:2
subroutine, public process_advanced(iit, qt)
process_advanced is user entry in time loop, just after advance allows to modify solution,...
subroutine, public advance(iit)
Advance all the grids over one time step, including all sources.
Definition mod_advance.t:23
subroutine, public process(iit, qt)
process is a user entry in time loop, before output and advance allows to modify solution,...
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Equation of state for AMRVAC, handled through a single eos_container object.
Definition mod_eos.t:30
Module with finite difference methods for fluxes.
subroutine, public fd(qdt, dtfactor, ixil, ixol, idimslim, qtc, sct, qt, snew, fc, fe, dxs, x)
subroutine, public centdiff(method, qdt, dtfactor, ixil, ixol, idimslim, qtc, sct, qt, s, fc, fe, dxs, x)
Module with finite volume methods for fluxes.
subroutine, public finite_volume(method, qdt, dtfactor, ixil, ixol, idimslim, qtc, sct, qt, snew, fc, fe, dxs, x)
finite volume method
subroutine, public hancock(qdt, dtfactor, ixil, ixol, idimslim, qtc, sct, qt, snew, dxs, x)
The non-conservative Hancock predictor for TVDLF.
Module for flux conservation near refinement boundaries.
subroutine, public init_comm_fix_conserve(idimlim, nwfluxin)
subroutine, public fix_edges(psuse, idimlim)
subroutine, public recvflux(idimlim)
subroutine, public sendflux(idimlim)
subroutine, public store_flux(igrid, fc, idimlim, nwfluxin)
subroutine, public store_edge(igrid, ixil, fe, idimlim)
subroutine, public fix_conserve(psb, idimlim, nw0, nwfluxin)
update ghost cells of all blocks including physical boundaries
subroutine getbc(time, qdt, psb, nwstart, nwbc)
do update ghost cells of all blocks including physical boundaries
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
integer, dimension(:), allocatable typepred1
The spatial discretization for the predictor step when using a two step PC method.
integer, parameter imex_euler
logical lb_diagnose
Per-rank load-balance timing diagnostic toggle (off by default). When .true., per-rank wall times are...
double precision, dimension(:), allocatable block_cost
Per-step per-block (per-rank, indexed by igrid) cost accumulator. Reset at start of each advance call...
double precision global_time
The global simulation time.
integer istep
Index of the sub-step in a multi-step time integrator.
integer it
Number of time steps taken.
double precision ars_gamma
IMEX_ARS3 parameter ars_gamma.
integer, parameter ndim
Number of spatial dimensions for grid variables.
integer, parameter nlevelshi
The maximum number of levels in the grid refinement.
logical stagger_grid
True for using stagger grid.
logical use_particles
Use particles module or not.
integer icomm
The MPI communicator.
integer, parameter imex_trapezoidal
integer mype
The rank of the current MPI task.
double precision dt
global time step
double precision imex222_lambda
IMEX-222(lambda) one-parameter family of schemes.
integer ierrmpi
A global MPI error return code.
integer, dimension(:), allocatable flux_method
Which flux scheme of spatial discretization to use (per grid level)
double precision, dimension(:), allocatable, parameter d
integer npe
The number of MPI tasks.
integer, parameter fs_hll
flux schemes
logical lb_automatic
Cost-weighted automatic load balancer toggle (off by default). When .true., the SFC partitioner cuts ...
logical time_advance
do time evolving
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision, dimension(:), allocatable block_cost_rt
Per-step per-block cost of the short-characteristics sweep, indexed by igrid. Separate from block_cos...
double precision rk_a21
RK2(alfa) method parameters from Butcher tableau.
integer, parameter predictor_corrector
integer, parameter sdim
starting dimension for electric field
integer, parameter forward_euler
logical fix_conserve_global
Whether to apply flux conservation at refinement boundaries.
character(len=std_len) typedimsplit
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
integer t_stepper
time stepper type
character(len=std_len) base_filename
Base file name for simulation output, which will be followed by a number.
integer, parameter rnodehi
grid location info (corner coordinates and grid spacing)
integer max_blocks
The maximum number of grid blocks in a processor.
double precision imex_a22
IMEX_CB3a extra parameters.
double precision lb_rt_accum
Per-rank wall time spent in the SC radiative-transfer KBA sweep this step, for the lb_diagnose rank-t...
integer t_integrator
time integrator method
integer, parameter fs_hancock
integer, dimension(:,:), allocatable node
integer, parameter imex_midpoint
Module containing all the particle routines.
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
procedure(sub_convert), pointer phys_to_primitive
Definition mod_physics.t:52
procedure(sub_evaluate_implicit), pointer phys_evaluate_implicit
Definition mod_physics.t:89
procedure(sub_implicit_update), pointer phys_implicit_update
Definition mod_physics.t:88
procedure(sub_face_to_center), pointer phys_face_to_center
Definition mod_physics.t:87
procedure(sub_special_advance), pointer phys_special_advance
Definition mod_physics.t:75
module radiative cooling – add optically thin radiative cooling
double precision, public lb_cool_accum
Per-rank cooling-only compute accumulator for lb_diagnose. Sums the wall time spent inside radiative_...
Module for handling split source terms (split from the fluxes)
Definition mod_source.t:2
subroutine, public addsource2(qdt, dtfactor, ixil, ixol, iwlim, qtc, wct, wctprim, qt, w, x, qsourcesplit, src_active)
Add source within ixO for iws: w=w+qdt*S[wCT].
Definition mod_source.t:138
subroutine, public add_split_source(prior)
Definition mod_source.t:24
Generic supertimestepping method which can be used for multiple source terms in the governing equatio...
double precision, public lb_tc_accum
Per-rank TC/STS compute accumulator for lb_diagnose. Sums the wall time spent inside the iigrid block...
Subroutines for TVD-MUSCL schemes.
Definition mod_tvd.t:2
subroutine, public tvdlimit(method, qdt, ixil, ixol, idimlim, s, qt, snew, fc, dxs, x)
Definition mod_tvd.t:14
Module with all the methods that users can customize in AMRVAC.
procedure(process_grid), pointer usr_process_grid
procedure(process_adv_grid), pointer usr_process_adv_grid
procedure(process_global), pointer usr_process_global
procedure(process_adv_global), pointer usr_process_adv_global