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.)
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.)
125
126 if(use_particles) call handle_particles
127
128 ! Cost-weighted load balancer: per-block measurements in block_cost
129 ! (per-rank, per-igrid) are folded into the global Morton-indexed
130 ! costlist via EWMA blend inside get_Morton_range_costed when
131 ! load_balance is next invoked. No end-of-advance work needed here.
132
133 if (lb_diagnose) then
134 t_advance_local = mpi_wtime() - t_advance_start
135 if (mype==0) then
136 call mpi_gather(t_advance_local,1,mpi_double_precision, &
137 t_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
138 call mpi_gather(lb_compute_accum,1,mpi_double_precision, &
139 c_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
140 call mpi_gather(lb_tc_accum,1,mpi_double_precision, &
141 tc_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
142 call mpi_gather(lb_cool_accum,1,mpi_double_precision, &
143 cool_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
144 call mpi_gather(lb_rt_accum,1,mpi_double_precision, &
145 rt_all_ranks,1,mpi_double_precision,0,icomm,ierrmpi)
146 tmax = maxval(t_all_ranks)
147 tmean = sum(t_all_ranks)/dble(npe)
148 cmax = maxval(c_all_ranks)
149 cmean = sum(c_all_ranks)/dble(npe)
150 tcmax = maxval(tc_all_ranks)
151 tcmean = sum(tc_all_ranks)/dble(npe)
152 coolmax = maxval(cool_all_ranks)
153 coolmean = sum(cool_all_ranks)/dble(npe)
154 rtmax = maxval(rt_all_ranks)
155 rtmean = sum(rt_all_ranks)/dble(npe)
156 if (tmean > 0.0d0) then
157 ratio = tmax/tmean
158 else
159 ratio = 1.0d0
160 end if
161 if (cmean > 0.0d0) then
162 ratioc = cmax/cmean
163 else
164 ratioc = 1.0d0
165 end if
166 if (tcmean > 0.0d0) then
167 ratiotc = tcmax/tcmean
168 else
169 ratiotc = 1.0d0
170 end if
171 if (coolmean > 0.0d0) then
172 ratiocool = coolmax/coolmean
173 else
174 ratiocool = 1.0d0
175 end if
176 if (rtmean > 0.0d0) then
177 ratiort = rtmax/rtmean
178 else
179 ratiort = 1.0d0
180 end if
181 write(lb_log_unit,'(i10,1x,es16.8,1x)',advance='no') it, global_time
182 do ipe=1,npe
183 write(lb_log_unit,'(es14.6,1x)',advance='no') t_all_ranks(ipe)
184 end do
185 do ipe=1,npe
186 write(lb_log_unit,'(es14.6,1x)',advance='no') c_all_ranks(ipe)
187 end do
188 do ipe=1,npe
189 write(lb_log_unit,'(es14.6,1x)',advance='no') tc_all_ranks(ipe)
190 end do
191 do ipe=1,npe
192 write(lb_log_unit,'(es14.6,1x)',advance='no') cool_all_ranks(ipe)
193 end do
194 do ipe=1,npe
195 write(lb_log_unit,'(es14.6,1x)',advance='no') rt_all_ranks(ipe)
196 end do
197 write(lb_log_unit,'(15(es14.6,1x))') &
198 tmax, tmean, ratio, cmax, cmean, ratioc, &
199 tcmax, tcmean, ratiotc, coolmax, coolmean, ratiocool, &
200 rtmax, rtmean, ratiort
201 flush(lb_log_unit)
202 else
203 call mpi_gather(t_advance_local,1,mpi_double_precision, &
204 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
205 call mpi_gather(lb_compute_accum,1,mpi_double_precision, &
206 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
207 call mpi_gather(lb_tc_accum,1,mpi_double_precision, &
208 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
209 call mpi_gather(lb_cool_accum,1,mpi_double_precision, &
210 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
211 call mpi_gather(lb_rt_accum,1,mpi_double_precision, &
212 t_dummy,1,mpi_double_precision,0,icomm,ierrmpi)
213 end if
214 ! The sweep accumulates before advance is entered, so it is cleared here,
215 ! after the gather, rather than in the reset block at the top.
216 lb_rt_accum = 0.0d0
217 end if
218
219 end subroutine advance
220
221 !> Advance all grids over one time step, but without taking dimensional
222 !> splitting or split source terms into account
223 subroutine advect(idim^LIM)
227 use mod_comm_lib, only: mpistop
228
229 integer, intent(in) :: idim^lim
230 integer :: iigrid, igrid
231
232 call init_comm_fix_conserve(idim^lim,nwflux)
233 fix_conserve_at_step = time_advance .and. levmax>levmin
234
235 ! copy w instead of wold because of potential use of dimsplit or sourcesplit
236 !$OMP PARALLEL DO PRIVATE(igrid)
237 do iigrid=1,igridstail; igrid=igrids(iigrid);
238 ps1(igrid)%w=ps(igrid)%w
239 if(stagger_grid) ps1(igrid)%ws=ps(igrid)%ws
240 end do
241 !$OMP END PARALLEL DO
242
243 istep = 0
244
245 select case (t_stepper)
246 case (onestep)
247 select case (t_integrator)
248 case (forward_euler)
249 call advect1(flux_method,one,idim^lim,global_time,ps1,global_time,ps)
250
251 case (imex_euler)
252 call advect1(flux_method,one,idim^lim,global_time,ps,global_time,ps1)
253 call global_implicit_update(one,dt,global_time+dt,ps,ps1)
254
255 case (imex_sp)
256 call global_implicit_update(one,dt,global_time,ps,ps1)
257 !$OMP PARALLEL DO PRIVATE(igrid)
258 do iigrid=1,igridstail; igrid=igrids(iigrid);
259 ps1(igrid)%w=ps(igrid)%w
260 if(stagger_grid) ps1(igrid)%ws=ps(igrid)%ws
261 end do
262 !$OMP END PARALLEL DO
263 call advect1(flux_method,one,idim^lim,global_time,ps1,global_time,ps)
264
265 case default
266 call mpistop("unkown onestep time_integrator in advect")
267 end select
268
269 case (twostep)
270 select case (t_integrator)
272 ! PC or explicit midpoint
273 ! predictor step
274 fix_conserve_at_step = .false.
275 call advect1(typepred1,half,idim^lim,global_time,ps,global_time,ps1)
276 ! corrector step
277 fix_conserve_at_step = time_advance .and. levmax>levmin
278 call advect1(flux_method,one,idim^lim,global_time+half*dt,ps1,global_time,ps)
279
280 case (rk2_alf)
281 ! RK2 with alfa parameter, where rk_a21=alfa
282 call advect1(flux_method,rk_a21, idim^lim,global_time,ps,global_time,ps1)
283 !$OMP PARALLEL DO PRIVATE(igrid)
284 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
285 ps(igrid)%w = ps(igrid)%w+rk_b1*(ps1(igrid)%w-ps(igrid)%w)/rk_a21
286 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws+(one-rk_b2)*(ps1(igrid)%ws-ps(igrid)%ws)/rk_a21
287 end do
288 !$OMP END PARALLEL DO
289 call advect1(flux_method,rk_b2,idim^lim,global_time+rk_a21*dt,ps1,global_time+rk_b1*dt,ps)
290
291 case (ssprk2)
292 ! ssprk2 or Heun's method
293 call advect1(flux_method,one, idim^lim,global_time,ps,global_time,ps1)
294 !$OMP PARALLEL DO PRIVATE(igrid)
295 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
296 ps(igrid)%w = half*ps(igrid)%w+half*ps1(igrid)%w
297 if(stagger_grid) ps(igrid)%ws = half*ps(igrid)%ws+half*ps1(igrid)%ws
298 end do
299 !$OMP END PARALLEL DO
300 call advect1(flux_method,half,idim^lim,global_time+dt,ps1,global_time+half*dt,ps)
301
302 case (imex_midpoint)
303 call advect1(flux_method,half, idim^lim,global_time,ps,global_time,ps1)
304 call global_implicit_update(half,dt,global_time+half*dt,ps2,ps1)
305 !$OMP PARALLEL DO PRIVATE(igrid)
306 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
307 ps(igrid)%w = ps(igrid)%w+2.0d0*(ps2(igrid)%w-ps1(igrid)%w)
308 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws+2.0d0*(ps2(igrid)%ws-ps1(igrid)%ws)
309 end do
310 !$OMP END PARALLEL DO
311 call advect1(flux_method,one, idim^lim,global_time+half*dt,ps2,global_time,ps)
312
313 case (imex_trapezoidal)
314 call advect1(flux_method,one, idim^lim,global_time,ps,global_time,ps1)
315 !$OMP PARALLEL DO PRIVATE(igrid)
316 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
317 ps2(igrid)%w = half*(ps(igrid)%w+ps1(igrid)%w)
318 if(stagger_grid) ps2(igrid)%ws = half*(ps(igrid)%ws+ps1(igrid)%ws)
319 end do
320 !$OMP END PARALLEL DO
321 call evaluate_implicit(global_time,ps)
322 !$OMP PARALLEL DO PRIVATE(igrid)
323 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
324 ps1(igrid)%w = ps1(igrid)%w+half*dt*ps(igrid)%w
325 if(stagger_grid) ps1(igrid)%ws = ps1(igrid)%ws+half*dt*ps(igrid)%ws
326 end do
327 !$OMP END PARALLEL DO
328 !$OMP PARALLEL DO PRIVATE(igrid)
329 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
330 ps(igrid)%w = ps2(igrid)%w+half*dt*ps(igrid)%w
331 if(stagger_grid) ps(igrid)%ws = ps2(igrid)%ws+half*dt*ps(igrid)%ws
332 end do
333 !$OMP END PARALLEL DO
334 call getbc(global_time+dt,dt,ps1,iwstart,nwgc)
335 call global_implicit_update(half,dt,global_time+dt,ps2,ps1)
336 !$OMP PARALLEL DO PRIVATE(igrid)
337 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
338 ps(igrid)%w = ps(igrid)%w+ps2(igrid)%w-ps1(igrid)%w
339 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws+ps2(igrid)%ws-ps1(igrid)%ws
340 end do
341 !$OMP END PARALLEL DO
342 call advect1(flux_method,half, idim^lim,global_time+dt,ps2,global_time+half*dt,ps)
343
344 case (imex_222)
345 ! One-parameter family of schemes (parameter is imex222_lambda) from
346 ! Pareschi&Russo 2005, which is L-stable (for default lambda) and
347 ! asymptotically SSP.
348 ! See doi.org/10.1007/s10915-004-4636-4 (table II)
349 ! See doi.org/10.1016/j.apnum.2016.10.018 for interesting values of lambda
350
351 ! Preallocate ps2 as y^n for the implicit update
352 !$OMP PARALLEL DO PRIVATE(igrid)
353 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
354 ps2(igrid)%w = ps(igrid)%w
355 if(stagger_grid) ps2(igrid)%ws = ps(igrid)%ws
356 end do
357 !$OMP END PARALLEL DO
358 ! Solve xi1 = y^n + lambda.dt.F_im(xi1)
359 call global_implicit_update(imex222_lambda, dt, global_time, ps2, ps)
360
361 ! Set ps1 = y^n + dt.F_ex(xi1)
362 call advect1(flux_method, one, idim^lim, global_time, ps2, global_time, ps1)
363 ! Set ps2 = dt.F_im(xi1) (is at t^n)
364 ! Set ps = y^n + dt/2 . F(xi1) (is at t^n+dt/2)
365 ! Set ps1 = y^n + dt.F_ex(xi1) + (1-2.lambda).dt.F_im(xi1) and enforce BC (at t^n+dt)
366 !$OMP PARALLEL DO PRIVATE(igrid)
367 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
368 ps2(igrid)%w = (ps2(igrid)%w - ps(igrid)%w) / imex222_lambda
369 if(stagger_grid) ps2(igrid)%ws = (ps2(igrid)%ws - ps(igrid)%ws) / imex222_lambda
370 end do
371 !$OMP END PARALLEL DO
372 !$OMP PARALLEL DO PRIVATE(igrid)
373 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
374 ps(igrid)%w = half*(ps(igrid)%w + ps1(igrid)%w + ps2(igrid)%w)
375 if(stagger_grid) ps(igrid)%ws = half*(ps(igrid)%ws + ps1(igrid)%ws + ps2(igrid)%ws)
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 ps1(igrid)%w = ps1(igrid)%w + (1.0d0 - 2.0d0*imex222_lambda)*ps2(igrid)%w
381 if(stagger_grid) ps1(igrid)%ws = ps1(igrid)%ws + (1.0d0 - 2.0d0*imex222_lambda)*ps2(igrid)%ws
382 end do
383 !$OMP END PARALLEL DO
384 call getbc(global_time+dt,dt,ps1,iwstart,nwgc)
385
386 ! Preallocate ps2 as xi1 for the implicit update (is at t^n)
387 !$OMP PARALLEL DO PRIVATE(igrid)
388 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
389 ps2(igrid)%w = 2.0d0*ps2(igrid)%w - ps1(igrid)%w - imex222_lambda*ps2(igrid)%w
390 if(stagger_grid) ps2(igrid)%ws = 2.0d0*ps2(igrid)%ws - ps1(igrid)%ws - imex222_lambda*ps2(igrid)%ws
391 end do
392 !$OMP END PARALLEL DO
393 ! Solve xi2 = (ps1) + lambda.dt.F_im(xi2)
394 call global_implicit_update(imex222_lambda, dt, global_time, ps2, ps1)
395
396 ! Add dt/2.F_im(xi2) to ps
397 !$OMP PARALLEL DO PRIVATE(igrid)
398 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
399 ps(igrid)%w = ps(igrid)%w + (ps2(igrid)%w - ps1(igrid)%w) / (2.0d0 * imex222_lambda)
400 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + (ps2(igrid)%ws - ps1(igrid)%ws) / (2.0d0 * imex222_lambda)
401 end do
402 !$OMP END PARALLEL DO
403 ! Set ps = y^n + dt/2.(F(xi1)+F(xi2)) = y^(n+1)
404 call advect1(flux_method, half, idim^lim, global_time+dt, ps2, global_time+half*dt, ps)
405
406 case default
407 call mpistop("unkown twostep time_integrator in advect")
408 end select
409
410 case (threestep)
411 select case (t_integrator)
412 case (ssprk3)
413 ! this is SSPRK(3,3) Gottlieb-Shu 1998 or SSP(3,2) depending on ssprk_order (3 vs 2)
414 call advect1(flux_method,rk_beta11, idim^lim,global_time,ps,global_time,ps1)
415 !$OMP PARALLEL DO PRIVATE(igrid)
416 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
417 ps2(igrid)%w=rk_alfa21*ps(igrid)%w+rk_alfa22*ps1(igrid)%w
418 if(stagger_grid) ps2(igrid)%ws=rk_alfa21*ps(igrid)%ws+rk_alfa22*ps1(igrid)%ws
419 end do
420 !$OMP END PARALLEL DO
421 call advect1(flux_method,rk_beta22, idim^lim,global_time+rk_c2*dt,ps1,global_time+rk_alfa22*rk_c2*dt,ps2)
422 !$OMP PARALLEL DO PRIVATE(igrid)
423 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
424 ps(igrid)%w=rk_alfa31*ps(igrid)%w+rk_alfa33*ps2(igrid)%w
425 if(stagger_grid) ps(igrid)%ws=rk_alfa31*ps(igrid)%ws+rk_alfa33*ps2(igrid)%ws
426 end do
427 !$OMP END PARALLEL DO
428 call advect1(flux_method,rk_beta33, idim^lim,global_time+rk_c3*dt,ps2,global_time+(1.0d0-rk_beta33)*dt,ps)
429
430 case (rk3_bt)
431 ! this is a general threestep RK according to its Butcher Table
432 call advect1(flux_method,rk3_a21, idim^lim,global_time,ps,global_time,ps1)
433 !$OMP PARALLEL DO PRIVATE(igrid)
434 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
435 ps3(igrid)%w=(ps1(igrid)%w-ps(igrid)%w)/rk3_a21
436 if(stagger_grid) ps3(igrid)%ws=(ps1(igrid)%ws-ps(igrid)%ws)/rk3_a21
437 end do
438 !$OMP END PARALLEL DO
439 !$OMP PARALLEL DO PRIVATE(igrid)
440 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
441 ps2(igrid)%w=ps(igrid)%w+rk3_a31*ps3(igrid)%w
442 if(stagger_grid) ps2(igrid)%ws=ps(igrid)%ws+rk3_a31*ps3(igrid)%ws
443 end do
444 !$OMP END PARALLEL DO
445 call advect1(flux_method,rk3_a32, idim^lim,global_time+rk3_c2*dt,ps1,global_time+rk3_a31*dt,ps2)
446 !$OMP PARALLEL DO PRIVATE(igrid)
447 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
448 ps(igrid)%w=ps(igrid)%w+rk3_b1*ps3(igrid)%w &
449 +rk3_b2*(ps2(igrid)%w-(ps(igrid)%w+rk3_a31*ps3(igrid)%w))/rk3_a32
450 if(stagger_grid)then
451 ps(igrid)%ws=ps(igrid)%ws+rk3_b1*ps3(igrid)%ws &
452 +rk3_b2*(ps2(igrid)%ws-(ps(igrid)%ws+rk3_a31*ps3(igrid)%ws))/rk3_a32
453 endif
454 end do
455 !$OMP END PARALLEL DO
456 call advect1(flux_method,rk3_b3, idim^lim,global_time+rk3_c3*dt,ps2,global_time+(1.0d0-rk3_b3)*dt,ps)
457
458 case (imex_ars3)
459 ! this is IMEX scheme ARS3
460 call advect1(flux_method,ars_gamma, idim^lim,global_time,ps,global_time,ps1)
461 !$OMP PARALLEL DO PRIVATE(igrid)
462 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
463 ps4(igrid)%w=(ps1(igrid)%w-ps(igrid)%w)/ars_gamma
464 if(stagger_grid) ps4(igrid)%ws=(ps1(igrid)%ws-ps(igrid)%ws)/ars_gamma
465 end do
466 !$OMP END PARALLEL DO
467 call global_implicit_update(ars_gamma,dt,global_time+ars_gamma*dt,ps2,ps1)
468 !$OMP PARALLEL DO PRIVATE(igrid)
469 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
470 ps1(igrid)%w=(ps2(igrid)%w-ps1(igrid)%w)/ars_gamma
471 if(stagger_grid) ps1(igrid)%ws=(ps2(igrid)%ws-ps1(igrid)%ws)/ars_gamma
472 end do
473 !$OMP END PARALLEL DO
474 !$OMP PARALLEL DO PRIVATE(igrid)
475 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
476 ps3(igrid)%w=ps(igrid)%w+(ars_gamma-1.0d0)*ps4(igrid)%w+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%w
477 if(stagger_grid) then
478 ps3(igrid)%ws=ps(igrid)%ws+(ars_gamma-1.0d0)*ps4(igrid)%ws+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%ws
479 endif
480 end do
481 !$OMP END PARALLEL DO
482 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)
483 !$OMP PARALLEL DO PRIVATE(igrid)
484 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
485 ps2(igrid)%w=ps1(igrid)%w+(ps3(igrid)%w-(ps(igrid)%w+ &
486 (ars_gamma-1.0d0)*ps4(igrid)%w+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%w))/(2.0d0*(1.0d0-ars_gamma))
487 if(stagger_grid) then
488 ps2(igrid)%ws=ps1(igrid)%ws+(ps3(igrid)%ws-(ps(igrid)%ws+ &
489 (ars_gamma-1.0d0)*ps4(igrid)%ws+(1.0d0-2.0d0*ars_gamma)*ps1(igrid)%ws))/(2.0d0*(1.0d0-ars_gamma))
490 endif
491 end do
492 !$OMP END PARALLEL DO
493 call global_implicit_update(ars_gamma,dt,global_time+(1.0d0-ars_gamma)*dt,ps4,ps3)
494 !$OMP PARALLEL DO PRIVATE(igrid)
495 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
496 ps(igrid)%w=ps(igrid)%w+half*ps2(igrid)%w &
497 +half*(ps4(igrid)%w-ps3(igrid)%w)/ars_gamma
498 if(stagger_grid) then
499 ps(igrid)%ws=ps(igrid)%ws+half*ps2(igrid)%ws &
500 +half*(ps4(igrid)%ws-ps3(igrid)%ws)/ars_gamma
501 endif
502 end do
503 !$OMP END PARALLEL DO
504 call advect1(flux_method,half, idim^lim,global_time+(1.0d0-ars_gamma)*dt,ps4,global_time+half*dt,ps)
505
506 case (imex_232)
507 ! this is IMEX_ARK(2,3,2) or IMEX_SSP(2,3,2)
508 call advect1(flux_method,imex_a21, idim^lim,global_time,ps,global_time,ps1)
509 !$OMP PARALLEL DO PRIVATE(igrid)
510 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
511 ps4(igrid)%w=(ps1(igrid)%w-ps(igrid)%w)/imex_a21
512 ps3(igrid)%w=ps(igrid)%w
513 if(stagger_grid) then
514 ps4(igrid)%ws=(ps1(igrid)%ws-ps(igrid)%ws)/imex_a21
515 ps3(igrid)%ws=ps(igrid)%ws
516 endif
517 end do
518 !$OMP END PARALLEL DO
519 call evaluate_implicit(global_time,ps3)
520 !$OMP PARALLEL DO PRIVATE(igrid)
521 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
522 ps1(igrid)%w=ps1(igrid)%w+imex_ha21*dt*ps3(igrid)%w
523 if(stagger_grid) ps1(igrid)%ws=ps1(igrid)%ws+imex_ha21*dt*ps3(igrid)%ws
524 end do
525 !$OMP END PARALLEL DO
526 call getbc(global_time+imex_a21*dt,dt,ps1,iwstart,nwgc)
527 call global_implicit_update(imex_ha22,dt,global_time+imex_c2*dt,ps2,ps1)
528 !$OMP PARALLEL DO PRIVATE(igrid)
529 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
530 ps(igrid)%w=ps(igrid)%w+imex_a31*ps4(igrid)%w &
531 +imex_b1*dt*ps3(igrid)%w+imex_b2*(ps2(igrid)%w-ps1(igrid)%w)/imex_ha22
532 if(stagger_grid) then
533 ps(igrid)%ws=ps(igrid)%ws+imex_a31*ps4(igrid)%ws &
534 +imex_b1*dt*ps3(igrid)%ws+imex_b2*(ps2(igrid)%ws-ps1(igrid)%ws)/imex_ha22
535 endif
536 end do
537 !$OMP END PARALLEL DO
538 !$OMP PARALLEL DO PRIVATE(igrid)
539 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
540 ps3(igrid)%w=ps1(igrid)%w-imex_a21*ps4(igrid)%w &
541 -imex_ha21*dt*ps3(igrid)%w+imex_b1*dt*ps3(igrid)%w
542 if(stagger_grid) then
543 ps3(igrid)%ws=ps1(igrid)%ws-imex_a21*ps4(igrid)%ws &
544 -imex_ha21*dt*ps3(igrid)%ws+imex_b1*dt*ps3(igrid)%ws
545 endif
546 end do
547 !$OMP END PARALLEL DO
548 call advect1(flux_method,imex_a32, idim^lim,global_time+imex_c2*dt,ps2,global_time+imex_a31*dt,ps)
549 !$OMP PARALLEL DO PRIVATE(igrid)
550 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
551 ps2(igrid)%w=(ps(igrid)%w-ps3(igrid)%w-imex_a31*ps4(igrid)%w)/imex_a32 &
552 +(1.0d0-imex_b2/imex_a32)*(ps2(igrid)%w-ps1(igrid)%w)/imex_ha22
553 if(stagger_grid) then
554 ps2(igrid)%ws=(ps(igrid)%ws-ps3(igrid)%ws-imex_a31*ps4(igrid)%ws)/imex_a32 &
555 +(1.0d0-imex_b2/imex_a32)*(ps2(igrid)%ws-ps1(igrid)%ws)/imex_ha22
556 endif
557 end do
558 !$OMP END PARALLEL DO
559 !$OMP PARALLEL DO PRIVATE(igrid)
560 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
561 ps1(igrid)%w=ps3(igrid)%w+imex_b1*ps4(igrid)%w+imex_b2*ps2(igrid)%w
562 if(stagger_grid) then
563 ps1(igrid)%ws=ps3(igrid)%ws+imex_b1*ps4(igrid)%ws+imex_b2*ps2(igrid)%ws
564 endif
565 end do
566 !$OMP END PARALLEL DO
567 call global_implicit_update(imex_b3,dt,global_time+imex_c3*dt,ps2,ps)
568 !$OMP PARALLEL DO PRIVATE(igrid)
569 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
570 ps(igrid)%w=ps1(igrid)%w+ps2(igrid)%w-ps(igrid)%w
571 if(stagger_grid) then
572 ps(igrid)%ws=ps1(igrid)%ws+ps2(igrid)%ws-ps(igrid)%ws
573 endif
574 end do
575 !$OMP END PARALLEL DO
576 call advect1(flux_method,imex_b3, idim^lim,global_time+imex_c3*dt,ps2,global_time+(1.0d0-imex_b3)*dt,ps)
577
578 case (imex_cb3a)
579 ! Third order IMEX scheme with low-storage implementation (4 registers).
580 ! From Cavaglieri&Bewley 2015, see doi.org/10.1016/j.jcp.2015.01.031
581 ! (scheme called "IMEXRKCB3a" there). Uses 3 explicit and 2 implicit stages.
582 ! Parameters are in imex_bj, imex_cj (same for implicit/explicit),
583 ! imex_aij (implicit tableau) and imex_haij (explicit tableau).
584 call advect1(flux_method, imex_ha21, idim^lim, global_time, ps, global_time, ps1)
585 call global_implicit_update(imex_a22, dt, global_time+imex_c2*dt, ps2, ps1)
586 !$OMP PARALLEL DO PRIVATE(igrid)
587 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
588 ps3(igrid)%w = ps(igrid)%w + imex_a32/imex_a22 * (ps2(igrid)%w - ps1(igrid)%w)
589 ps(igrid)%w = ps(igrid)%w + imex_b2 /imex_a22 * (ps2(igrid)%w - ps1(igrid)%w)
590 ps1(igrid)%w = ps3(igrid)%w
591 if(stagger_grid) ps3(igrid)%ws = ps(igrid)%ws + imex_a32/imex_a22 * (ps2(igrid)%ws - ps1(igrid)%ws)
592 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + imex_b2 /imex_a22 * (ps2(igrid)%ws - ps1(igrid)%ws)
593 if(stagger_grid) ps1(igrid)%ws = ps3(igrid)%ws
594 end do
595 !$OMP END PARALLEL DO
596 call advect1(flux_method, imex_ha32, idim^lim, global_time+imex_c2*dt, ps2, global_time, ps3)
597 !$OMP PARALLEL DO PRIVATE(igrid)
598 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
599 ps(igrid)%w = ps(igrid)%w + imex_b2 /imex_ha32 * (ps3(igrid)%w - ps1(igrid)%w)
600 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + imex_b2 /imex_ha32 * (ps3(igrid)%ws - ps1(igrid)%ws)
601 end do
602 call global_implicit_update(imex_a33, dt, global_time+imex_c3*dt, ps1, 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_b3 /imex_a33 * (ps1(igrid)%w - ps3(igrid)%w)
606 if(stagger_grid) ps(igrid)%ws = ps(igrid)%ws + imex_b3 /imex_a33 * (ps1(igrid)%ws - ps3(igrid)%ws)
607 end do
608 !$OMP END PARALLEL DO
609 call advect1(flux_method, imex_b3, idim^lim, global_time+imex_c3*dt, ps1, global_time+imex_b2*dt, ps)
610
611 case default
612 call mpistop("unkown threestep time_integrator in advect")
613 end select
614
615 case (fourstep)
616 select case (t_integrator)
617 case (ssprk4)
618 ! SSPRK(4,3) or SSP(4,2) depending on ssprk_order (3 vs 2)
619 ! ssprk43: Strong stability preserving 4 stage RK 3rd order by Ruuth and Spiteri
620 ! Ruuth & Spiteri J. S C, 17 (2002) p. 211 - 220
621 ! supposed to be stable up to CFL=2.
622 ! ssp42: stable up to CFL=3
623 call advect1(flux_method,rk_beta11, idim^lim,global_time,ps,global_time,ps1)
624 !$OMP PARALLEL DO PRIVATE(igrid)
625 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
626 ps2(igrid)%w=rk_alfa21*ps(igrid)%w+rk_alfa22*ps1(igrid)%w
627 if(stagger_grid) ps2(igrid)%ws=rk_alfa21*ps(igrid)%ws+rk_alfa22*ps1(igrid)%ws
628 end do
629 !$OMP END PARALLEL DO
630 call advect1(flux_method,rk_beta22, idim^lim,global_time+rk_c2*dt,ps1,global_time+rk_alfa22*rk_c2*dt,ps2)
631 !$OMP PARALLEL DO PRIVATE(igrid)
632 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
633 ps1(igrid)%w=rk_alfa31*ps(igrid)%w+rk_alfa33*ps2(igrid)%w
634 if(stagger_grid) ps1(igrid)%ws=rk_alfa31*ps(igrid)%ws+rk_alfa33*ps2(igrid)%ws
635 end do
636 !$OMP END PARALLEL DO
637 call advect1(flux_method,rk_beta33, idim^lim,global_time+rk_c3*dt,ps2,global_time+rk_alfa33*rk_c3*dt,ps1)
638 !$OMP PARALLEL DO PRIVATE(igrid)
639 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
640 ps(igrid)%w=rk_alfa41*ps(igrid)%w+rk_alfa44*ps1(igrid)%w
641 if(stagger_grid) ps(igrid)%ws=rk_alfa41*ps(igrid)%ws+rk_alfa44*ps1(igrid)%ws
642 end do
643 !$OMP END PARALLEL DO
644 call advect1(flux_method,rk_beta44, idim^lim,global_time+rk_c4*dt,ps1,global_time+(1.0d0-rk_beta44)*dt,ps)
645
646 case (rk4)
647 ! the standard RK(4,4) method
648 !$OMP PARALLEL DO PRIVATE(igrid)
649 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
650 ps2(igrid)%w=ps(igrid)%w
651 ps3(igrid)%w=ps(igrid)%w
652 if(stagger_grid) then
653 ps2(igrid)%ws=ps(igrid)%ws
654 ps3(igrid)%ws=ps(igrid)%ws
655 endif
656 end do
657 !$OMP END PARALLEL DO
658 call advect1(flux_method,half, idim^lim,global_time,ps,global_time,ps1)
659 call advect1(flux_method,half, idim^lim,global_time+half*dt,ps1,global_time,ps2)
660 call advect1(flux_method,1.0d0, idim^lim,global_time+half*dt,ps2,global_time,ps3)
661 !$OMP PARALLEL DO PRIVATE(igrid)
662 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
663 ps(igrid)%w=(1.0d0/3.0d0)*(-ps(igrid)%w+ps1(igrid)%w+2.0d0*ps2(igrid)%w+ps3(igrid)%w)
664 if(stagger_grid) ps(igrid)%ws=(1.0d0/3.0d0) &
665 *(-ps(igrid)%ws+ps1(igrid)%ws+2.0d0*ps2(igrid)%ws+ps3(igrid)%ws)
666 end do
667 !$OMP END PARALLEL DO
668 call advect1(flux_method,1.0d0/6.0d0, idim^lim,global_time+dt,ps3,global_time+dt*5.0d0/6.0d0,ps)
669
670 case default
671 call mpistop("unkown fourstep time_integrator in advect")
672 end select
673
674 case (fivestep)
675 select case (t_integrator)
676 case (ssprk5)
677 ! SSPRK(5,4) by Ruuth and Spiteri
678 !bcexch = .false.
679 call advect1(flux_method,rk_beta11, idim^lim,global_time,ps,global_time,ps1)
680 !$OMP PARALLEL DO PRIVATE(igrid)
681 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
682 ps2(igrid)%w=rk_alfa21*ps(igrid)%w+rk_alfa22*ps1(igrid)%w
683 if(stagger_grid) ps2(igrid)%ws=rk_alfa21*ps(igrid)%ws+rk_alfa22*ps1(igrid)%ws
684 end do
685 !$OMP END PARALLEL DO
686 call advect1(flux_method,rk_beta22, idim^lim,global_time+rk_c2*dt,ps1,global_time+rk_alfa22*rk_c2*dt,ps2)
687 !$OMP PARALLEL DO PRIVATE(igrid)
688 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
689 ps1(igrid)%w=rk_alfa31*ps(igrid)%w+rk_alfa33*ps2(igrid)%w
690 if(stagger_grid) ps1(igrid)%ws=rk_alfa31*ps(igrid)%ws+rk_alfa33*ps2(igrid)%ws
691 end do
692 !$OMP END PARALLEL DO
693 call advect1(flux_method,rk_beta33, idim^lim,global_time+rk_c3*dt,ps2,global_time+rk_alfa33*rk_c3*dt,ps1)
694 !$OMP PARALLEL DO PRIVATE(igrid)
695 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
696 ps3(igrid)%w=rk_alfa53*ps2(igrid)%w+rk_alfa54*ps1(igrid)%w
697 if(stagger_grid) ps3(igrid)%ws=rk_alfa53*ps2(igrid)%ws+rk_alfa54*ps1(igrid)%ws
698 end do
699 !$OMP END PARALLEL DO
700 !$OMP PARALLEL DO PRIVATE(igrid)
701 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
702 ps2(igrid)%w=rk_alfa41*ps(igrid)%w+rk_alfa44*ps1(igrid)%w
703 if(stagger_grid) ps2(igrid)%ws=rk_alfa41*ps(igrid)%ws+rk_alfa44*ps1(igrid)%ws
704 end do
705 !$OMP END PARALLEL DO
706 call advect1(flux_method,rk_beta44, idim^lim,global_time+rk_c4*dt,ps1,global_time+rk_alfa44*rk_c4*dt,ps2)
707 !$OMP PARALLEL DO PRIVATE(igrid)
708 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
709 ps(igrid)%w=ps3(igrid)%w+rk_alfa55*ps2(igrid)%w &
710 +(rk_beta54/rk_beta44)*(ps2(igrid)%w-(rk_alfa41*ps(igrid)%w+rk_alfa44*ps1(igrid)%w))
711 if(stagger_grid) then
712 ps(igrid)%ws=ps3(igrid)%ws+rk_alfa55*ps2(igrid)%ws &
713 +(rk_beta54/rk_beta44)*(ps2(igrid)%ws-(rk_alfa41*ps(igrid)%ws+rk_alfa44*ps1(igrid)%ws))
714 endif
715 end do
716 !$OMP END PARALLEL DO
717 !bcexch = .true.
718 call advect1(flux_method,rk_beta55, idim^lim,global_time+rk_c5*dt,ps2,global_time+(1.0d0-rk_beta55)*dt,ps)
719
720 case default
721 call mpistop("unkown fivestep time_integrator in advect")
722 end select
723
724 case default
725 call mpistop("unkown time_stepper in advect")
726 end select
727
728 end subroutine advect
729
730 !> Implicit global update step within IMEX schemes, advance psa=psb+dtfactor*qdt*F_im(psa)
731 subroutine global_implicit_update(dtfactor,qdt,qtC,psa,psb)
736
737 type(state), target :: psa(max_blocks) !< Compute implicit part from this state and update it
738 type(state), target :: psb(max_blocks) !< Will be unchanged, as on entry
739 double precision, intent(in) :: qdt !< overall time step dt
740 double precision, intent(in) :: qtc !< Both states psa and psb at this time level
741 double precision, intent(in) :: dtfactor !< Advance psa=psb+dtfactor*qdt*F_im(psa)
742
743 integer :: iigrid, igrid
744
745 !> First copy all variables from a to b, this is necessary to account for
746 ! quantities in w with no implicit sourceterm
747 do iigrid=1,igridstail; igrid=igrids(iigrid);
748 psa(igrid)%w = psb(igrid)%w
749 if(stagger_grid) psa(igrid)%ws = psb(igrid)%ws
750 end do
751
752 if (associated(phys_implicit_update)) then
753 call phys_implicit_update(dtfactor,qdt,qtc,psa,psb)
754 end if
755
756 ! enforce boundary conditions for psa
757 call getbc(qtc,0.d0,psa,iwstart,nwgc)
758 call prepare_eos_w_fields(psa)
759
760 end subroutine global_implicit_update
761
762 !> Evaluate Implicit part in place, i.e. psa==>F_im(psa)
763 subroutine evaluate_implicit(qtC,psa)
766 type(state), target :: psa(max_blocks) !< Compute implicit part from this state and update it
767 double precision, intent(in) :: qtc !< psa at this time level
768
769 if (associated(phys_evaluate_implicit)) then
770 call phys_evaluate_implicit(qtc,psa)
771 end if
772 end subroutine evaluate_implicit
773
774 !> Integrate all grids by one partial step
775 subroutine advect1(method,dtfactor,idim^LIM,qtC,psa,qt,psb)
779 use mod_physics
781
782 integer, intent(in) :: idim^lim
783 type(state), target :: psa(max_blocks) !< Compute fluxes based on this state
784 type(state), target :: psb(max_blocks) !< Update solution on this state
785 double precision, intent(in) :: dtfactor !< Advance over dtfactor * dt
786 double precision, intent(in) :: qtc
787 double precision, intent(in) :: qt
788 integer, intent(in) :: method(nlevelshi)
789
790 double precision :: qdt
791 double precision :: lb_t0_advect1, lb_t0_block
792 integer :: iigrid, igrid
793
794 istep = istep+1
795
796 if(associated(phys_special_advance)) then
797 call phys_special_advance(qtc,psa)
798 end if
799
800 qdt=dtfactor*dt
801 ! opedit: Just advance the active grids:
802 if (lb_diagnose) lb_t0_advect1 = mpi_wtime()
803 !$OMP PARALLEL DO PRIVATE(igrid,lb_t0_block)
804 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
805 if (lb_automatic) lb_t0_block = mpi_wtime()
806 block=>ps(igrid)
807 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
808 call advect1_grid(igrid,method(block%level),qdt,dtfactor,ixg^ll,idim^lim,&
809 qtc,psa(igrid),qt,psb(igrid),rnode(rpdx1_:rnodehi,igrid),ps(igrid)%x)
810 if (lb_automatic) block_cost(igrid) = block_cost(igrid) + (mpi_wtime() - lb_t0_block)
811 end do
812 !$OMP END PARALLEL DO
813 if (lb_diagnose) lb_compute_accum = lb_compute_accum + (mpi_wtime() - lb_t0_advect1)
814
815 ! opedit: Send flux for all grids, expects sends for all
816 ! nsend_fc(^D), set in connectivity.t.
817
818 if (fix_conserve_global .and. fix_conserve_at_step) then
819 call recvflux(idim^lim)
820 call sendflux(idim^lim)
821 call fix_conserve(psb,idim^lim,1,nwflux)
822 if(stagger_grid) then
823 call fix_edges(psb,idim^lim)
824 ! fill the cell-center values from the updated staggered variables
825 !$OMP PARALLEL DO PRIVATE(igrid)
826 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
827 call phys_face_to_center(ixm^ll,psb(igrid))
828 end do
829 !$OMP END PARALLEL DO
830 end if
831 end if
832
833 ! For all grids: fill ghost cells
834 call getbc(qt+qdt,qdt,psb,iwstart,nwgc)
835
836 ! update eos variables: Te (nH) including ghost cells
837 call prepare_eos_w_fields(psb)
838
839 end subroutine advect1
840
841 !> Advance a single grid over one partial time step
842 subroutine advect1_grid(igrid,method,qdt,dtfactor,ixI^L,idim^LIM,qtC,sCT,qt,s,dxs,x)
843
844 ! integrate one grid by one partial step
847 use mod_tvd
848 use mod_source, only: addsource2
851 use mod_comm_lib, only: mpistop
853
854 integer, intent(in) :: igrid,method
855 integer, intent(in) :: ixi^l, idim^lim
856 double precision, intent(in) :: qdt, dtfactor, qtc, qt, dxs(ndim), x(ixi^s,1:ndim)
857 type(state), target :: sct, s
858
859 ! cell face flux
860 double precision :: fc(ixi^s,1:nwflux,1:ndim)
861 ! cell edge flux
862 double precision :: fe(ixi^s,sdim:3)
863 double precision :: wprim(ixi^s,1:nw)
864 integer :: ixo^l
865
866 ! for mf module
867 if(iwstart>1) fc=0.d0
868
869 ixo^l=ixi^l^lsubnghostcells;
870 select case (method)
872 call finite_volume(method,qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
873 case (fs_cd,fs_cd4)
874 call centdiff(method,qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
875 case (fs_hancock)
876 call hancock(qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,dxs,x)
877 case (fs_fd)
878 call fd(qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
879 case (fs_tvd)
880 call centdiff(fs_cd,qdt,dtfactor,ixi^l,ixo^l,idim^lim,qtc,sct,qt,s,fc,fe,dxs,x)
881 call tvdlimit(method,qdt,ixi^l,ixo^l,idim^lim,sct,qt+qdt,s,fc,dxs,x)
882 case (fs_source)
883 fc=0.d0
884 fe=0.d0
885 wprim=sct%w
886 call phys_to_primitive(ixi^l,ixi^l,wprim,x)
887 call addsource2(qdt*dble(idimmax-idimmin+1)/dble(ndim),&
888 dtfactor*dble(idimmax-idimmin+1)/dble(ndim),&
889 ixi^l,ixo^l,1,nw,qtc,sct%w,wprim,qt,s%w,x,.false.)
890 case (fs_nul)
891 ! There is nothing to do
892 case default
893 call mpistop("unknown flux scheme in advect1_grid")
894 end select
895
896 ! opedit: Obviously, flux is stored only for active grids.
897 ! but we know in fix_conserve wether there is a passive neighbor
898 ! but we know in conserve_fix wether there is a passive neighbor
899 ! via neighbor_active(i^D,igrid) thus we skip the correction for those.
900 ! This violates strict conservation when the active/passive interface
901 ! coincides with a coarse/fine interface.
902 if (fix_conserve_global .and. fix_conserve_at_step) then
903 call store_flux(igrid,fc,idim^lim,nwflux)
904 if(stagger_grid) call store_edge(igrid,ixg^ll,fe,idim^lim)
905 end if
906
907 end subroutine advect1_grid
908
909 !> process is a user entry in time loop, before output and advance
910 !> allows to modify solution, add extra variables, etc.
911 !> Warning: CFL dt already determined (and is not recomputed)!
912 subroutine process(iit,qt)
916 ! .. scalars ..
917 integer,intent(in) :: iit
918 double precision, intent(in):: qt
919
920 integer:: iigrid, igrid
921
922 if (associated(usr_process_global)) then
923 call usr_process_global(iit,qt)
924 end if
925
926 if (associated(usr_process_grid)) then
927 !$OMP PARALLEL DO PRIVATE(igrid)
928 do iigrid=1,igridstail; igrid=igrids(iigrid);
929 ! next few lines ensure correct usage of routines like divvector etc
930 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
931 block=>ps(igrid)
932 call usr_process_grid(igrid,node(plevel_,igrid),ixg^ll,ixm^ll, &
933 qt,ps(igrid)%w,ps(igrid)%x)
934 end do
935 !$OMP END PARALLEL DO
936 call getbc(qt,dt,ps,iwstart,nwgc)
937 end if
938 end subroutine process
939
940 !> process_advanced is user entry in time loop, just after advance
941 !> allows to modify solution, add extra variables, etc.
942 !> added for handling two-way coupled PIC-MHD
943 !> Warning: w is now at global_time^(n+1), global time and iteration at global_time^n, it^n
944 subroutine process_advanced(iit,qt)
949 ! .. scalars ..
950 integer,intent(in) :: iit
951 double precision, intent(in):: qt
952
953 integer:: iigrid, igrid
954
955 if (associated(usr_process_adv_global)) then
956 call usr_process_adv_global(iit,qt)
957 end if
958
959 if (associated(usr_process_adv_grid)) then
960 !$OMP PARALLEL DO PRIVATE(igrid)
961 do iigrid=1,igridstail; igrid=igrids(iigrid);
962 ! next few lines ensure correct usage of routines like divvector etc
963 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
964 block=>ps(igrid)
965
966 call usr_process_adv_grid(igrid,node(plevel_,igrid),ixg^ll,ixm^ll, &
967 qt,ps(igrid)%w,ps(igrid)%x)
968 end do
969 !$OMP END PARALLEL DO
970 call getbc(qt,dt,ps,iwstart,nwgc)
971 end if
972 end subroutine process_advanced
973
974end 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
subroutine, public prepare_eos_w_fields(psx)
Definition mod_eos.t:419
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:54
procedure(sub_evaluate_implicit), pointer phys_evaluate_implicit
Definition mod_physics.t:91
procedure(sub_implicit_update), pointer phys_implicit_update
Definition mod_physics.t:90
procedure(sub_face_to_center), pointer phys_face_to_center
Definition mod_physics.t:89
procedure(sub_special_advance), pointer phys_special_advance
Definition mod_physics.t:77
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:20
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