MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
setdt.t
Go to the documentation of this file.
1 !>setdt - set dt for all levels between levmin and levmax.
2 !> dtpar>0 --> use fixed dtpar for all level
3 !> dtpar<=0 --> determine CFL limited timestep
4 subroutine setdt()
6  use mod_physics
7  use mod_trac
8  use mod_usr_methods, only: usr_get_dt
10 
11  integer :: iigrid, igrid, ncycle, ncycle2, ifile, idim
12  double precision :: dtnew, qdtnew, dtmin_mype, factor, dx^D, dxmin^D
13 
14  double precision :: dtmax, dxmin, cmax_mype
15  double precision :: a2max_mype(ndim), tco_mype, tco_global, Tmax_mype, T_peak
16  double precision :: trac_alfa, trac_dmax, trac_tau
17 
18  integer, parameter :: niter_print = 2000
19 
20  if (dtpar<=zero) then
21  dtmin_mype=bigdouble
22  cmax_mype = zero
23  a2max_mype = zero
24  tco_mype = zero
25  tmax_mype = zero
26  !$OMP PARALLEL DO PRIVATE(igrid,qdtnew,dtnew,dx^D) REDUCTION(min:dtmin_mype) REDUCTION(max:cmax_mype,a2max_mype)
27  do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
28  dtnew=bigdouble
29  dx^d=rnode(rpdx^d_,igrid);
30  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
31  block=>ps(igrid)
32 
33  call getdt_courant(ps(igrid)%w,ixg^ll,ixm^ll,qdtnew,dx^d,ps(igrid)%x,&
34  cmax_mype,a2max_mype)
35  dtnew=min(dtnew,qdtnew)
36 
37  call phys_get_dt(ps(igrid)%w,ixg^ll,ixm^ll,qdtnew,dx^d,ps(igrid)%x)
38  dtnew=min(dtnew,qdtnew)
39 
40  if (associated(usr_get_dt)) then
41  call usr_get_dt(ps(igrid)%w,ixg^ll,ixm^ll,qdtnew,dx^d,ps(igrid)%x)
42  end if
43  dtnew = min(dtnew,qdtnew)
44  dtmin_mype = min(dtmin_mype,dtnew)
45  end do
46  !$OMP END PARALLEL DO
47  else
48  dtmin_mype=dtpar
49  end if
50 
51  if (dtmin_mype<dtmin) then
52  write(unitterm,*)"Error: Time step too small!", dtmin_mype
53  write(unitterm,*)"on processor:", mype, "at time:", global_time," step:", it
54  write(unitterm,*)"Lower limit of time step:", dtmin
55  crash=.true.
56  end if
57 
58  if (slowsteps>it-it_init+1) then
59  factor=one-(one-dble(it-it_init+1)/dble(slowsteps))**2
60  dtmin_mype=dtmin_mype*factor
61  end if
62 
63  if(final_dt_reduction)then
64  !if (dtmin_mype>time_max-global_time) then
65  ! write(unitterm,*)"WARNING final timestep artificially reduced!"
66  ! write(unitterm,*)"on processor:", mype, "at time:", global_time," step:", it
67  !endif
68  if(time_max-global_time<=dtmin) then
69  !write(unitterm,*)'Forcing to leave timeloop as time is reached!'
70  final_dt_exit=.true.
71  endif
72  dtmin_mype=min(dtmin_mype,time_max-global_time)
73  end if
74 
75  if (dtpar<=zero) then
76  call mpi_allreduce(dtmin_mype,dt,1,mpi_double_precision,mpi_min, &
77  icomm,ierrmpi)
78  else
79  dt=dtmin_mype
80  end if
81 
82  if(any(dtsave(1:nfile)<bigdouble).or.any(tsave(isavet(1:nfile),1:nfile)<bigdouble))then
83  dtmax = minval(ceiling(global_time/dtsave(1:nfile))*dtsave(1:nfile))-global_time
84  do ifile=1,nfile
85  dtmax = min(tsave(isavet(ifile),ifile)-global_time,dtmax)
86  end do
87  if(dtmax > smalldouble)then
88  dt=min(dt,dtmax)
89  else
90  ! dtmax=0 means dtsave is divisible by global_time
91  dt=min(dt,minval(dtsave(1:nfile)))
92  end if
93  end if
94 
95  if(mype==0) then
96  if(any(dtsave(1:nfile)<dt)) then
97  write(unitterm,*) 'Warning: timesteps: ',dt,' exceeding output intervals ', dtsave(1:nfile)
98  endif
99  endif
100 
101  if(is_sts_initialized()) then
103  qdtnew = 0.5d0 * dt
104  if (set_dt_sts_ncycles(qdtnew)) then
105  dt = 2.d0*qdtnew
106  !a quick way to print the reduction of time only every niter_print iterations
107  !Note that niter_print is a parameter variable hardcoded to the value of 200
108  if(mype==0 .and. mod(it-1, niter_print) .eq. 0) then
109  write(*,*) 'Max number of STS cycles exceeded, reducing dt to',dt
110  endif
111  endif
112  else
113  if(set_dt_sts_ncycles(dt))then
114  if(mype==0 .and. mod(it-1, niter_print) .eq. 0) then
115  write(*,*) 'Max number of STS cycles exceeded, reducing dt to',dt
116  endif
117  endif
118  endif
119  endif
120 
121  ! global Lax-Friedrich finite difference flux splitting needs fastest wave-speed
122  ! so does GLM:
123  if(need_global_cmax) call mpi_allreduce(cmax_mype,cmax_global,1,&
124  mpi_double_precision,mpi_max,icomm,ierrmpi)
125  if(need_global_a2max) call mpi_allreduce(a2max_mype,a2max_global,ndim,&
126  mpi_double_precision,mpi_max,icomm,ierrmpi)
127 
128  ! transition region adaptive thermal conduction (Johnston 2019 ApJL, 873, L22)
129  ! transition region adaptive thermal conduction (Johnston 2020 A&A, 635, 168)
130  if(phys_trac) then
132  call mpi_allreduce(tmax_mype,t_peak,1,mpi_double_precision,&
133  mpi_max,icomm,ierrmpi)
134  ! default lower limit of cutoff temperature
135  select case(phys_trac_type)
136  case(0)
137  !> Test case, fixed cutoff temperature
138  !> do nothing here
139  case(1)
140  !> 1D TRAC method
141  trac_dmax=0.1d0
142  trac_tau=1.d0/unit_time
143  trac_alfa=trac_dmax**(dt/trac_tau)
144  tco_global=zero
145  {^ifoned
146  call mpi_allreduce(tco_mype,tco_global,1,mpi_double_precision,&
147  mpi_max,icomm,ierrmpi)
148  }
149  call trac_simple(tco_global,trac_alfa,t_peak)
150  case(2)
151  !> LTRAC method, by iijima et al. 2021
152  !> do nothing here
153  call ltrac(t_peak)
154  case(3)
155  !> 2D or 3D TRACL(ine) method
156  call tracl(.false.,t_peak)
157  case(4)
158  !> 2D or 3D TRACB(lock) method
159  call tracb(.false.,t_peak)
160  case(5)
161  !> 2D or 3D TRACL(ine) method with mask
162  call tracl(.true.,t_peak)
163  case(6)
164  !> 2D or 3D TRACB(lock) method with mask
165  call tracb(.true.,t_peak)
166  case default
167  call mpistop("undefined TRAC method type")
168  end select
169  end if
170 
171  contains
172 
173  !> compute CFL limited dt (for variable time stepping)
174  subroutine getdt_courant(w,ixI^L,ixO^L,dtnew,dx^D,x,cmax_mype,a2max_mype)
177 
178  integer, intent(in) :: ixI^L, ixO^L
179  double precision, intent(in) :: x(ixI^S,1:ndim)
180  double precision, intent(in) :: dx^D
181  double precision, intent(inout) :: w(ixI^S,1:nw), dtnew, cmax_mype, a2max_mype(ndim)
182 
183  integer :: idims
184  double precision :: courantmax, dxinv(1:ndim), courantmaxtot, courantmaxtots
185  double precision :: cmax(ixI^S), cmaxtot(ixO^S)
186  double precision :: a2max(ndim),tco_local,Tmax_local
187 
188  dtnew=bigdouble
189  courantmax=zero
190  courantmaxtot=zero
191  courantmaxtots=zero
192 
193 
194  if(need_global_a2max) then
195  call phys_get_a2max(w,x,ixi^l,ixo^l,a2max)
196  do idims=1,ndim
197  a2max_mype(idims) = max(a2max_mype(idims),a2max(idims))
198  end do
199  end if
200  if(phys_trac) then
201  call phys_get_tcutoff(ixi^l,ixo^l,w,x,tco_local,tmax_local)
202  {^ifoned tco_mype=max(tco_mype,tco_local) }
203  tmax_mype=max(tmax_mype,tmax_local)
204  end if
205 
206  !if(slab_uniform) then
207  ! ^D&dxinv(^D)=one/dx^D;
208  ! do idims=1,ndim
209  ! call phys_get_cmax(w,x,ixI^L,ixO^L,idims,cmax)
210  ! if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixO^S)))
211  ! if(need_global_a2max) a2max_mype(idims) = max(a2max_mype(idims),a2max(idims))
212  ! cmaxtot(ixO^S)=cmaxtot(ixO^S)+cmax(ixO^S)*dxinv(idims)
213  ! courantmax=max(courantmax,maxval(cmax(ixO^S)*dxinv(idims)))
214  ! courantmaxtot=courantmaxtot+courantmax
215  ! end do
216  !else
217  ! do idims=1,ndim
218  ! call phys_get_cmax(w,x,ixI^L,ixO^L,idims,cmax)
219  ! if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixO^S)))
220  ! if(need_global_a2max) a2max_mype(idims) = max(a2max_mype(idims),a2max(idims))
221  ! tmp(ixO^S)=cmax(ixO^S)/block%ds(ixO^S,idims)
222  ! cmaxtot(ixO^S)=cmaxtot(ixO^S)+tmp(ixO^S)
223  ! courantmax=max(courantmax,maxval(tmp(ixO^S)))
224  ! courantmaxtot=courantmaxtot+courantmax
225  ! end do
226  !end if
227 
228  select case (type_courant)
229  case (type_maxsum)
230  cmaxtot(ixo^s)=zero
231  if(slab_uniform) then
232  ^d&dxinv(^d)=one/dx^d;
233  do idims=1,ndim
234  call phys_get_cmax(w,x,ixi^l,ixo^l,idims,cmax)
235  if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixo^s)))
236  cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)*dxinv(idims)
237  end do
238  else
239  do idims=1,ndim
240  call phys_get_cmax(w,x,ixi^l,ixo^l,idims,cmax)
241  if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixo^s)))
242  cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)/block%ds(ixo^s,idims)
243  end do
244  end if
245  ! courantmaxtots='max(summed c/dx)'
246  courantmaxtots=max(courantmaxtots,maxval(cmaxtot(ixo^s)))
247  if (courantmaxtots>smalldouble) dtnew=min(dtnew,courantpar/courantmaxtots)
248  case (type_summax)
249  if(slab_uniform) then
250  ^d&dxinv(^d)=one/dx^d;
251  do idims=1,ndim
252  call phys_get_cmax(w,x,ixi^l,ixo^l,idims,cmax)
253  if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixo^s)))
254  courantmax=max(courantmax,maxval(cmax(ixo^s)*dxinv(idims)))
255  courantmaxtot=courantmaxtot+courantmax
256  end do
257  else
258  do idims=1,ndim
259  call phys_get_cmax(w,x,ixi^l,ixo^l,idims,cmax)
260  if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixo^s)))
261  courantmax=max(courantmax,maxval(cmax(ixo^s)/block%ds(ixo^s,idims)))
262  courantmaxtot=courantmaxtot+courantmax
263  end do
264  end if
265  ! courantmaxtot='summed max(c/dx)'
266  if (courantmaxtot>smalldouble) dtnew=min(dtnew,courantpar/courantmaxtot)
267  case (type_minimum)
268  if(slab_uniform) then
269  ^d&dxinv(^d)=one/dx^d;
270  do idims=1,ndim
271  call phys_get_cmax(w,x,ixi^l,ixo^l,idims,cmax)
272  if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixo^s)))
273  courantmax=max(courantmax,maxval(cmax(ixo^s)*dxinv(idims)))
274  end do
275  else
276  do idims=1,ndim
277  call phys_get_cmax(w,x,ixi^l,ixo^l,idims,cmax)
278  if(need_global_cmax) cmax_mype = max(cmax_mype,maxval(cmax(ixo^s)))
279  courantmax=max(courantmax,maxval(cmax(ixo^s)/block%ds(ixo^s,idims)))
280  end do
281  end if
282  ! courantmax='max(c/dx)'
283  if (courantmax>smalldouble) dtnew=min(dtnew,courantpar/courantmax)
284  end select
285 
286  end subroutine getdt_courant
287 
288 end subroutine setdt
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
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.
double precision unit_time
Physical scaling factor for time.
double precision global_time
The global simulation time.
double precision time_max
End time for the simulation.
integer it
Number of time steps taken.
integer it_init
initial iteration count
integer, parameter type_maxsum
integer switchers for type courant
double precision cmax_global
global fastest wave speed needed in fd scheme and glm method
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
double precision dtpar
If dtpar is positive, it sets the timestep dt, otherwise courantpar is used to limit the time step ba...
logical need_global_a2max
global value for schmid scheme
double precision courantpar
The Courant (CFL) number used for the simulation.
integer ixm
the mesh range (within a block with ghost cells)
integer ierrmpi
A global MPI error return code.
integer slowsteps
If > 1, then in the first slowsteps-1 time steps dt is reduced by a factor .
integer type_courant
How to compute the CFL-limited time step.
integer, parameter unitterm
Unit for standard output.
double precision, dimension(nfile) dtsave
Repeatedly save output of type N when dtsave(N) simulation time has passed.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
logical final_dt_reduction
If true, allow final dt reduction for matching time_max on output.
integer, parameter type_summax
logical phys_trac
Use TRAC (Johnston 2019 ApJL, 873, L22) for MHD or 1D HD.
double precision, dimension(nsavehi, nfile) tsave
Save output of type N on times tsave(:, N)
logical need_global_cmax
need global maximal wave speed
logical crash
Save a snapshot before crash a run met unphysical values.
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
double precision dtmin
Stop the simulation when the time step becomes smaller than this value.
integer, parameter nfile
Number of output methods.
logical final_dt_exit
Force timeloop exit when final dt < dtmin.
integer, parameter type_minimum
double precision, dimension(ndim) dxlevel
integer, dimension(nfile) isavet
double precision, dimension(ndim) a2max_global
global largest a2 for schmid scheme
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
procedure(sub_get_a2max), pointer phys_get_a2max
Definition: mod_physics.t:62
procedure(sub_get_dt), pointer phys_get_dt
Definition: mod_physics.t:69
procedure(sub_get_tcutoff), pointer phys_get_tcutoff
Definition: mod_physics.t:63
procedure(sub_get_cmax), pointer phys_get_cmax
Definition: mod_physics.t:61
Generic supertimestepping method 1) in amrvac.par in sts_list set the following parameters which have...
integer, public sourcetype_sts
pure logical function, public is_sts_initialized()
logical function, public set_dt_sts_ncycles(my_dt)
This sets the explicit dt and calculates the number of cycles for each of the terms implemented with ...
integer, parameter, public sourcetype_sts_split
double precision t_bott
Definition: mod_trac.t:7
subroutine tracb(mask, T_peak)
Definition: mod_trac.t:219
subroutine ltrac(T_peak)
Definition: mod_trac.t:165
subroutine trac_simple(tco_global, trac_alfa, T_peak)
Definition: mod_trac.t:143
subroutine tracl(mask, T_peak)
Definition: mod_trac.t:181
Module with all the methods that users can customize in AMRVAC.
procedure(get_dt), pointer usr_get_dt
subroutine setdt()
setdt - set dt for all levels between levmin and levmax. dtpar>0 --> use fixed dtpar for all level dt...
Definition: setdt.t:5
subroutine getdt_courant(w, ixIL, ixOL, dtnew, dxD, x, cmax_mype, a2max_mype)
compute CFL limited dt (for variable time stepping)
Definition: setdt.t:175