MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
errest.t
Go to the documentation of this file.
1 !> Do all local error estimation which determines (de)refinement
2 subroutine errest
3  use mod_forest, only: refine, buffer
5 
6  integer :: igrid, iigrid, ixCoG^L
7  double precision :: factor
8  logical, dimension(:,:), allocatable :: refine2
9 
10  if (igridstail==0) return
11 
12  select case (refine_criterion)
13  case (0)
14  ! all refinement solely based on user routine usr_refine_grid
15  case (1)
16  ! simply compare w_n-1 with w_n and trigger refinement on relative
17  ! differences
18  !$OMP PARALLEL DO PRIVATE(igrid)
19  do iigrid=1,igridstail; igrid=igrids(iigrid);
20  block=>ps(igrid)
21  call compare1_grid(igrid,pso(igrid)%w,ps(igrid)%w)
22  end do
23  !$OMP END PARALLEL DO
24  case (2)
25  ! Error estimation is based on Lohner's original scheme
26  !$OMP PARALLEL DO PRIVATE(igrid)
27  do iigrid=1,igridstail; igrid=igrids(iigrid);
28  block=>ps(igrid)
29  call lohner_orig_grid(igrid)
30  end do
31  !$OMP END PARALLEL DO
32  case (3)
33  ! Error estimation is based on Lohner's scheme
34  !$OMP PARALLEL DO PRIVATE(igrid)
35  do iigrid=1,igridstail; igrid=igrids(iigrid);
36  block=>ps(igrid)
37  call lohner_grid(igrid)
38  end do
39  !$OMP END PARALLEL DO
40  case default
41  call mpistop("Unknown error estimator")
42  end select
43 
44  ! enforce additional refinement on e.g. coordinate and/or time info here
45  if (nbufferx^d/=0|.or.) then
46  allocate(refine2(max_blocks,npe))
47  call mpi_allreduce(refine,refine2,max_blocks*npe,mpi_logical,mpi_lor, &
48  icomm,ierrmpi)
49  refine=refine2
50  end if
51  !$OMP PARALLEL DO PRIVATE(igrid)
52  do iigrid=1,igridstail; igrid=igrids(iigrid);
53  block=>ps(igrid)
54  call forcedrefine_grid(igrid,ps(igrid)%w)
55  end do
56  !$OMP END PARALLEL DO
57 
58  if (nbufferx^d/=0|.or.) &
59  buffer=.false.
60 
61 end subroutine errest
62 
63 subroutine lohner_grid(igrid)
65  use mod_forest, only: coarsen, refine
66  use mod_physics, only: phys_energy
68 
69  integer, intent(in) :: igrid
70 
71  integer :: iflag, idims, idims2, level
72  integer :: ix^L, hx^L, jx^L, h2x^L, j2x^L, ix^D
73  double precision :: epsilon, threshold, wtol(1:nw), xtol(1:ndim)
74  double precision, dimension(ixM^T) :: numerator, denominator, error
75  double precision, dimension(ixG^T) :: tmp, tmp1, tmp2
76  double precision :: w(ixG^T,1:nw)
77  logical, dimension(ixG^T) :: refineflag, coarsenflag
78 
79  epsilon = 1.0d-6
80  level = node(plevel_,igrid)
81  ix^l=ixm^ll^ladd1;
82 
83  error=zero
84 
85  w(ixg^t,1:nw)=ps(igrid)%w(ixg^t,1:nw)
86 
87  if(b0field) then
88  if(phys_energy) &
89  w(ixg^t,iw_e)=w(ixg^t,iw_e)+0.5d0*sum(ps(igrid)%B0(ixg^t,:,0)**2,dim=ndim+1) &
90  + sum(w(ixg^t,iw_mag(:))*ps(igrid)%B0(ixg^t,:,0),dim=ndim+1)
91  w(ixg^t,iw_mag(:))=w(ixg^t,iw_mag(:))+ps(igrid)%B0(ixg^t,:,0)
92  end if
93 
94  do iflag=1,nw+1
95 
96  if(w_refine_weight(iflag)==0.d0) cycle
97  numerator=zero
98 
99  if (iflag > nw) then
100  if (.not. associated(usr_var_for_errest)) then
101  call mpistop("usr_var_for_errest not defined")
102  else
103  call usr_var_for_errest(ixg^ll,ixg^ll,iflag,ps(igrid)%w,ps(igrid)%x,tmp1)
104  end if
105  end if
106 
107  do idims=1,ndim
108  hx^l=ix^l-kr(^d,idims);
109  jx^l=ix^l+kr(^d,idims);
110  if (iflag<=nw) then
111  if (logflag(iflag)) then
112  tmp(ix^s)=dlog10(w(jx^s,iflag))-dlog10(w(hx^s,iflag))
113  else
114  tmp(ix^s)=w(jx^s,iflag)-w(hx^s,iflag)
115  end if
116  else
117  if (logflag(iflag)) then
118  tmp(ix^s)=dlog10(tmp1(jx^s))-dlog10(tmp1(hx^s))
119  else
120  tmp(ix^s)=tmp1(jx^s)-tmp1(hx^s)
121  end if
122  end if
123  do idims2=1,ndim
124  h2x^l=ixm^ll-kr(^d,idims2);
125  j2x^l=ixm^ll+kr(^d,idims2);
126  numerator=numerator+(tmp(j2x^s)-tmp(h2x^s))**2.0d0
127  end do
128  end do
129  denominator=zero
130  do idims=1,ndim
131  if (iflag<=nw) then
132  if (logflag(iflag)) then
133  tmp=dabs(dlog10(w(ixg^t,iflag)))
134  else
135  tmp=dabs(w(ixg^t,iflag))
136  end if
137  else
138  if (logflag(iflag)) then
139  tmp=dabs(dlog10(tmp1(ixg^t)))
140  else
141  tmp=dabs(tmp1(ixg^t))
142  end if
143  end if
144  hx^l=ix^l-kr(^d,idims);
145  jx^l=ix^l+kr(^d,idims);
146  tmp2(ix^s)=tmp(jx^s)+tmp(hx^s)
147  hx^l=ixm^ll-2*kr(^d,idims);
148  jx^l=ixm^ll+2*kr(^d,idims);
149  if (iflag<=nw) then
150  if (logflag(iflag)) then
151  tmp(ixm^t)=dabs(dlog10(w(jx^s,iflag))&
152  -dlog10(w(ixm^t,iflag))) &
153  +dabs(dlog10(w(ixm^t,iflag))&
154  -dlog10(w(hx^s,iflag)))
155  else
156  tmp(ixm^t)=dabs(w(jx^s,iflag)-w(ixm^t,iflag)) &
157  +dabs(w(ixm^t,iflag)-w(hx^s,iflag))
158  end if
159  else
160  if (logflag(iflag)) then
161  tmp(ixm^t)=dabs(dlog10(tmp1(jx^s))-dlog10(tmp1(ixm^t))) &
162  +dabs(dlog10(tmp1(ixm^t))-dlog10(tmp1(hx^s)))
163  else
164  tmp(ixm^t)=dabs(tmp1(jx^s)-tmp1(ixm^t)) &
165  +dabs(tmp1(ixm^t)-tmp1(hx^s))
166  end if
167  end if
168  do idims2=1,ndim
169  h2x^l=ixm^ll-kr(^d,idims2);
170  j2x^l=ixm^ll+kr(^d,idims2);
171  denominator=denominator &
172  +(tmp(ixm^t)+amr_wavefilter(level)*(tmp2(j2x^s)+tmp2(h2x^s)))**2
173  end do
174  end do
175  error=error+w_refine_weight(iflag)*dsqrt(numerator/max(denominator,epsilon))
176  end do
177 
178  refineflag=.false.
179  coarsenflag=.false.
180  threshold=refine_threshold(level)
181  {do ix^db=ixmlo^db,ixmhi^db\}
182 
183  if (associated(usr_refine_threshold)) then
184  wtol(1:nw) = w(ix^d,1:nw)
185  xtol(1:ndim) = ps(igrid)%x(ix^d,1:ndim)
186  call usr_refine_threshold(wtol, xtol, threshold, global_time, level)
187  end if
188 
189  if (error(ix^d) >= threshold) then
190  refineflag(ix^d) = .true.
191  else if (error(ix^d) <= derefine_ratio(level)*threshold) then
192  coarsenflag(ix^d) = .true.
193  end if
194  {end do\}
195 
196  if (any(refineflag(ixm^t)).and.level<refine_max_level) refine(igrid,mype)=.true.
197  if (all(coarsenflag(ixm^t)).and.level>1) coarsen(igrid,mype)=.true.
198 
199 end subroutine lohner_grid
200 
201 subroutine lohner_orig_grid(igrid)
203  use mod_forest, only: coarsen, refine
205 
206  integer, intent(in) :: igrid
207 
208  integer :: iflag, idims, level
209  integer :: ix^L, hx^L, jx^L, ix^D
210  double precision :: epsilon, threshold, wtol(1:nw), xtol(1:ndim)
211  double precision, dimension(ixM^T) :: numerator, denominator, error
212  double precision, dimension(ixG^T) :: dp, dm, dref, tmp1
213  logical, dimension(ixG^T) :: refineflag, coarsenflag
214 
215  epsilon=1.0d-6
216  level=node(plevel_,igrid)
217  ix^l=ixm^ll;
218 
219  error=zero
220  do iflag=1,nw+1
221  if(w_refine_weight(iflag)==0.d0) cycle
222  numerator=zero
223  denominator=zero
224 
225  if (iflag > nw) then
226  if (.not. associated(usr_var_for_errest)) then
227  call mpistop("usr_var_for_errest not defined")
228  else
229  call usr_var_for_errest(ixg^ll,ixg^ll,iflag,ps(igrid)%w,ps(igrid)%x,tmp1)
230  end if
231  end if
232 
233  do idims=1,ndim
234  hx^l=ix^l-kr(^d,idims);
235  jx^l=ix^l+kr(^d,idims);
236  if (iflag<=nw) then
237  if (logflag(iflag)) then
238  dp(ix^s)=dlog10(ps(igrid)%w(jx^s,iflag))-dlog10(ps(igrid)%w(ix^s,iflag))
239  dm(ix^s)=dlog10(ps(igrid)%w(ix^s,iflag))-dlog10(ps(igrid)%w(hx^s,iflag))
240  dref(ixm^t)=dabs(dlog10(ps(igrid)%w(jx^s,iflag)))&
241  + 2.0d0 * dabs(dlog10(ps(igrid)%w(ixm^t,iflag))) &
242  + dabs(dlog10(ps(igrid)%w(hx^s,iflag)))
243  else
244  dp(ix^s)=ps(igrid)%w(jx^s,iflag)-ps(igrid)%w(ix^s,iflag)
245  dm(ix^s)=ps(igrid)%w(ix^s,iflag)-ps(igrid)%w(hx^s,iflag)
246  dref(ixm^t)=dabs(ps(igrid)%w(jx^s,iflag))+2.0d0*dabs(ps(igrid)%w(ixm^t,iflag)) &
247  +dabs(ps(igrid)%w(hx^s,iflag))
248  end if
249  else
250  if (logflag(iflag)) then
251  dp(ix^s)=dlog10(tmp1(jx^s))-dlog10(tmp1(ix^s))
252  dm(ix^s)=dlog10(tmp1(ix^s))-dlog10(tmp1(hx^s))
253  dref(ix^s)=dabs(dlog10(tmp1(jx^s)))&
254  + 2.0d0 * dabs(dlog10(tmp1(ix^s))) &
255  + dabs(dlog10(tmp1(hx^s)))
256  else
257  dp(ix^s)=tmp1(jx^s)-tmp1(ix^s)
258  dm(ix^s)=tmp1(ix^s)-tmp1(hx^s)
259  dref(ix^s)=dabs(tmp1(jx^s))+2.0d0*dabs(tmp1(ix^s)) &
260  +dabs(tmp1(hx^s))
261  end if
262  end if
263 
264  numerator(ixm^t)=numerator+(dp(ixm^t)-dm(ixm^t))**2.0d0
265 
266  denominator(ixm^t)=denominator &
267  + (dabs(dp(ixm^t)) + dabs(dm(ixm^t)) + amr_wavefilter(level)*dref(ixm^t))**2.0d0
268 
269  end do
270  error=error+w_refine_weight(iflag)*dsqrt(numerator/max(denominator,epsilon))
271  end do
272 
273  refineflag=.false.
274  coarsenflag=.false.
275 
276  threshold=refine_threshold(level)
277  {do ix^db=ixmlo^db,ixmhi^db\}
278 
279  if (associated(usr_refine_threshold)) then
280  wtol(1:nw) = ps(igrid)%w(ix^d,1:nw)
281  xtol(1:ndim) = ps(igrid)%x(ix^d,1:ndim)
282  call usr_refine_threshold(wtol, xtol, threshold, global_time, level)
283  end if
284 
285  if (error(ix^d) >= threshold) then
286  refineflag(ix^d) = .true.
287  else if (error(ix^d) <= derefine_ratio(level)*threshold) then
288  coarsenflag(ix^d) = .true.
289  end if
290  {end do\}
291 
292  if (any(refineflag(ixm^t)).and.level<refine_max_level) refine(igrid,mype)=.true.
293  if (all(coarsenflag(ixm^t)).and.level>1) coarsen(igrid,mype)=.true.
294 
295 end subroutine lohner_orig_grid
296 
297 subroutine compare1_grid(igrid,wold,w)
299  use mod_forest, only: coarsen, refine
301 
302  integer, intent(in) :: igrid
303  double precision, intent(in) :: wold(ixG^T,1:nw), w(ixG^T,1:nw)
304 
305  integer :: ix^D, iflag, level
306  double precision :: epsilon, threshold, wtol(1:nw), xtol(1:ndim)
307  double precision :: average, error
308  double precision :: averages(nw)
309  logical, dimension(ixG^T) :: refineflag, coarsenflag
310 
311  ! identify the points to be flagged in two steps:
312  ! step I: compare w_n-1 with w_n solution, store w_for_refine in auxiliary
313  ! step II: transfer w_for_refine from auxiliary to refine and coarsen
314 
315  epsilon=1.0d-6
316 
317  refineflag(ixm^t) = .false.
318  coarsenflag(ixm^t) = .false.
319  level=node(plevel_,igrid)
320  threshold=refine_threshold(level)
321  {do ix^db=ixmlo^db,ixmhi^db \}
322  average=zero
323  error=zero
324  do iflag=1,nw+1
325  if(w_refine_weight(iflag)==0) cycle
326  averages(iflag) = w(ix^d,iflag)-wold(ix^d,iflag)
327  average=average+w_refine_weight(iflag)*abs(averages(iflag))
328  if (abs(wold(ix^d,iflag))<smalldouble)then
329  error=error+w_refine_weight(iflag)* &
330  abs(averages(iflag))/(abs(wold(ix^d,iflag))+epsilon)
331  else
332  error=error+w_refine_weight(iflag)* &
333  abs(averages(iflag))/(abs(wold(ix^d,iflag)))
334  end if
335  end do
336 
337  if (associated(usr_refine_threshold)) then
338  wtol(1:nw) = ps(igrid)%w(ix^d,1:nw)
339  xtol(1:ndim) = ps(igrid)%x(ix^d,1:ndim)
340  call usr_refine_threshold(wtol, xtol, threshold, global_time, level)
341  end if
342 
343  if (error >= threshold) then
344  refineflag(ix^d) = .true.
345  else if (error <= derefine_ratio(level)*threshold) then
346  coarsenflag(ix^d) = .true.
347  end if
348  {end do\}
349 
350  if (any(refineflag(ixm^t))) then
351  if (level<refine_max_level) refine(igrid,mype)=.true.
352  end if
353  if (time_advance) then
354  if (all(coarsenflag(ixm^t)).and.level>1) coarsen(igrid,mype)=.true.
355  end if
356 
357 end subroutine compare1_grid
358 
359 subroutine forcedrefine_grid(igrid,w)
361  use mod_forest, only: coarsen, refine, buffer
363 
364  integer, intent(in) :: igrid
365  double precision, intent(in) :: w(ixG^T,nw)
366 
367  integer :: level
368  integer :: my_refine, my_coarsen
369  double precision :: qt
370  logical, dimension(ixG^T) :: refineflag
371 
372  level=node(plevel_,igrid)
373 
374  ! initialize to 0
375  my_refine = 0
376  my_coarsen = 0
377 
378  if (time_advance) then
379  qt=global_time+dt
380  else
381  if (refine_criterion==1) then
382  qt=global_time+dt
383  else
384  qt=global_time
385  end if
386  end if
387 
388  if (associated(usr_refine_grid)) then
389  call usr_refine_grid(igrid,level,ixg^ll,ixm^ll,qt,w,ps(igrid)%x, &
390  my_refine,my_coarsen)
391  end if
392 
393  if (my_coarsen==1) then
394  if (level>1) then
395  refine(igrid,mype)=.false.
396  coarsen(igrid,mype)=.true.
397  else
398  refine(igrid,mype)=.false.
399  coarsen(igrid,mype)=.false.
400  end if
401  endif
402 
403  if (my_coarsen==-1)then
404  coarsen(igrid,mype)=.false.
405  end if
406 
407  if (my_refine==1) then
408  if (level<refine_max_level) then
409  refine(igrid,mype)=.true.
410  coarsen(igrid,mype)=.false.
411  else
412  refine(igrid,mype)=.false.
413  coarsen(igrid,mype)=.false.
414  end if
415  end if
416 
417  if (my_refine==-1) then
418  refine(igrid,mype)=.false.
419  end if
420 
421  if (nbufferx^d/=0|.or.) then
422  if (refine(igrid,mype) .and. .not.buffer(igrid,mype)) then
423  refineflag(ixm^t)=.true.
424  call refinebuffer(igrid,refineflag)
425  end if
426  end if
427 
428 end subroutine forcedrefine_grid
429 
430 subroutine forcedrefine_grid_io(igrid,w)
431  use mod_forest, only: coarsen, refine
433 
434  integer, intent(in) :: igrid
435  double precision, intent(in) :: w(ixG^T,nw)
436 
437  integer :: level, my_levmin, my_levmax
438  logical, dimension(ixG^T) :: refineflag
439 
440  level=node(plevel_,igrid)
441 
442  if (level_io > 0) then
443  my_levmin = level_io
444  my_levmax = level_io
445  else
446  my_levmin = max(1,level_io_min)
447  my_levmax = min(refine_max_level,level_io_max)
448  end if
449 
450 
451  if (level>my_levmax) then
452  refine(igrid,mype)=.false.
453  coarsen(igrid,mype)=.true.
454  elseif (level<my_levmin) then
455  refine(igrid,mype)=.true.
456  coarsen(igrid,mype)=.false.
457  end if
458 
459  if (level==my_levmin .or. level==my_levmax) then
460  refine(igrid,mype)=.false.
461  coarsen(igrid,mype)=.false.
462  end if
463 
464 
465  if(refine(igrid,mype).and.level>=refine_max_level)refine(igrid,mype)=.false.
466  if(coarsen(igrid,mype).and.level<=1)coarsen(igrid,mype)=.false.
467 
468 end subroutine forcedrefine_grid_io
469 
470 subroutine refinebuffer(igrid,refineflag)
471  use mod_forest, only: refine, buffer
473 
474  integer, intent(in) :: igrid
475  logical, dimension(ixG^T), intent(in) :: refineflag
476 
477  integer :: ishiftbuf^D, i^D, ix^L, ineighbor, ipe_neighbor, level
478 
479  ishiftbuf^d=ixmhi^d-ixmlo^d-nbufferx^d+1;
480  {do i^db=-1,1\}
481  ixmin^d=max(ixmlo^d,ixmlo^d+i^d*ishiftbuf^d);
482  ixmax^d=min(ixmhi^d,ixmhi^d+i^d*ishiftbuf^d);
483  if (ixmax^d<ixmin^d|.or.) cycle
484  if (any(refineflag(ix^s))) then
485  select case (neighbor_type(i^d,igrid))
486  case (neighbor_coarse)
487  ineighbor=neighbor(1,i^d,igrid)
488  ipe_neighbor=neighbor(2,i^d,igrid)
489  if (.not.refine(ineighbor,ipe_neighbor)) then
490  buffer(ineighbor,ipe_neighbor)=.true.
491  refine(ineighbor,ipe_neighbor)=.true.
492  end if
493  case (neighbor_sibling)
494  level=node(plevel_,igrid)
495  if (level<refine_max_level) then
496  ineighbor=neighbor(1,i^d,igrid)
497  ipe_neighbor=neighbor(2,i^d,igrid)
498  if (.not.refine(ineighbor,ipe_neighbor)) then
499  buffer(ineighbor,ipe_neighbor)=.true.
500  refine(ineighbor,ipe_neighbor)=.true.
501  end if
502  end if
503  end select
504  end if
505  {end do\}
506 
507 end subroutine refinebuffer
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
subroutine compare1_grid(igrid, wold, w)
Definition: errest.t:298
subroutine forcedrefine_grid(igrid, w)
Definition: errest.t:360
subroutine refinebuffer(igrid, refineflag)
Definition: errest.t:471
subroutine errest
Do all local error estimation which determines (de)refinement.
Definition: errest.t:3
subroutine lohner_grid(igrid)
Definition: errest.t:64
subroutine lohner_orig_grid(igrid)
Definition: errest.t:202
subroutine forcedrefine_grid_io(igrid, w)
Definition: errest.t:431
Module with basic grid data structures.
Definition: mod_forest.t:2
logical, dimension(:,:), allocatable, save refine
Definition: mod_forest.t:70
logical, dimension(:,:), allocatable, save buffer
Definition: mod_forest.t:70
logical, dimension(:,:), allocatable, save coarsen
AMR flags and grids-in-use identifier per processor (igrid,ipe)
Definition: mod_forest.t:70
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 global_time
The global simulation time.
integer, dimension(3, 3) kr
Kronecker delta tensor.
logical, dimension(:), allocatable logflag
double precision, dimension(:), allocatable amr_wavefilter
refinement: lohner estimate wavefilter setting
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
integer, parameter plevel_
integer, dimension(:), allocatable, parameter d
integer ixm
the mesh range (within a block with ghost cells)
integer ierrmpi
A global MPI error return code.
integer npe
The number of MPI tasks.
logical b0field
split magnetic field as background B0 field
integer nbufferx
Number of cells as buffer zone.
double precision, dimension(:), allocatable w_refine_weight
Weights of variables used to calculate error for mesh refinement.
double precision, dimension(:), allocatable refine_threshold
Error tolerance for refinement decision.
integer refine_max_level
Maximal number of AMR levels.
double precision, dimension(:), allocatable derefine_ratio
integer max_blocks
The maximum number of grid blocks in a processor.
integer, dimension(:,:), allocatable node
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
logical phys_energy
Solve energy equation or not.
Definition: mod_physics.t:30
Module with all the methods that users can customize in AMRVAC.
procedure(a_refine_threshold), pointer usr_refine_threshold
procedure(refine_grid), pointer usr_refine_grid
procedure(var_for_errest), pointer usr_var_for_errest