MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_errest.t
Go to the documentation of this file.
2 use mod_comm_lib, only: mpistop
3 implicit none
4 private
5
7
8contains
9
10 !> Do all local error estimation which determines (de)refinement
11 subroutine errest
12 use mod_forest, only: refine, buffer
14
15 double precision :: factor
16 integer :: igrid, iigrid, ixcog^l
17 logical, dimension(:,:), allocatable :: refine2
18
19 if (igridstail==0) return
20
21 select case (refine_criterion)
22 case (1)
23 ! all refinement solely based on user routine usr_refine_grid
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, &
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 double precision :: epsilon, threshold, wtol(1:nw), xtol(1:ndim)
72 double precision, dimension(ixM^T) :: numerator, denominator, error
73 double precision, dimension(ixG^T) :: tmp, tmp1, tmp2
74 double precision :: w(ixg^t,1:nw)
75 integer :: iflag, idims, idims2, level
76 integer :: ix^l, hx^l, jx^l, h2x^l, j2x^l, ix^d
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 .and. allocated(iw_mag)) 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
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 ! With logflag the differenced quantity is u = log10(w), for which
134 ! Lohner's eps*|u| filter is not meaningful: it is a relative floor,
135 ! scale-invariant for a linear variable but not for a log, where a
136 ! change of unit is additive and |u| becomes the distance from
137 ! w_code = 1. The fractional character is already carried by
138 ! d(log w), so the floor is constant and amr_wavefilter is in dex.
139 tmp=one
140 else
141 tmp=dabs(w(ixg^t,iflag))
142 end if
143 else
144 if (logflag(iflag)) then
145 tmp=one ! dex floor, as in the w-slot branch above
146 else
147 tmp=dabs(tmp1(ixg^t))
148 end if
149 end if
150 hx^l=ix^l-kr(^d,idims);
151 jx^l=ix^l+kr(^d,idims);
152 tmp2(ix^s)=tmp(jx^s)+tmp(hx^s)
153 hx^l=ixm^ll-2*kr(^d,idims);
154 jx^l=ixm^ll+2*kr(^d,idims);
155 if (iflag<=nw) then
156 if (logflag(iflag)) then
157 tmp(ixm^t)=dabs(dlog10(w(jx^s,iflag))&
158 -dlog10(w(ixm^t,iflag))) &
159 +dabs(dlog10(w(ixm^t,iflag))&
160 -dlog10(w(hx^s,iflag)))
161 else
162 tmp(ixm^t)=dabs(w(jx^s,iflag)-w(ixm^t,iflag)) &
163 +dabs(w(ixm^t,iflag)-w(hx^s,iflag))
164 end if
165 else
166 if (logflag(iflag)) then
167 tmp(ixm^t)=dabs(dlog10(tmp1(jx^s))-dlog10(tmp1(ixm^t))) &
168 +dabs(dlog10(tmp1(ixm^t))-dlog10(tmp1(hx^s)))
169 else
170 tmp(ixm^t)=dabs(tmp1(jx^s)-tmp1(ixm^t)) &
171 +dabs(tmp1(ixm^t)-tmp1(hx^s))
172 end if
173 end if
174 do idims2=1,ndim
175 h2x^l=ixm^ll-kr(^d,idims2);
176 j2x^l=ixm^ll+kr(^d,idims2);
177 denominator=denominator &
178 +(tmp(ixm^t)+amr_wavefilter(level)*(tmp2(j2x^s)+tmp2(h2x^s)))**2
179 end do
180 end do
181 error=error+w_refine_weight(iflag)*dsqrt(numerator/max(denominator,epsilon))
182 end do
183
184 refineflag=.false.
185 coarsenflag=.false.
186 threshold=refine_threshold(level)
187 {do ix^db=ixmlo^db,ixmhi^db\}
188
189 if (associated(usr_refine_threshold)) then
190 wtol(1:nw) = w(ix^d,1:nw)
191 xtol(1:ndim) = ps(igrid)%x(ix^d,1:ndim)
192 call usr_refine_threshold(wtol, xtol, threshold, global_time, level)
193 end if
194
195 if (error(ix^d) >= threshold) then
196 refineflag(ix^d) = .true.
197 else if (error(ix^d) <= derefine_ratio(level)*threshold) then
198 coarsenflag(ix^d) = .true.
199 end if
200 {end do\}
201
202 if (any(refineflag(ixm^t)).and.level<refine_max_level) refine(igrid,mype)=.true.
203 if (all(coarsenflag(ixm^t)).and.level>1) coarsen(igrid,mype)=.true.
204
205 end subroutine lohner_grid
206
207 subroutine lohner_orig_grid(igrid)
209 use mod_forest, only: coarsen, refine
211
212 integer, intent(in) :: igrid
213
214 double precision :: epsilon, threshold, wtol(1:nw), xtol(1:ndim)
215 double precision, dimension(ixM^T) :: numerator, denominator, error
216 double precision, dimension(ixG^T) :: dp, dm, dref, tmp1
217 integer :: iflag, idims, level
218 integer :: ix^l, hx^l, jx^l, ix^d
219 logical, dimension(ixG^T) :: refineflag, coarsenflag
220
221 epsilon=1.0d-6
222 level=node(plevel_,igrid)
223 ix^l=ixm^ll;
224
225 error=zero
226 do iflag=1,nw+1
227 if(w_refine_weight(iflag)==0.d0) cycle
228 numerator=zero
229 denominator=zero
230
231 if (iflag > nw) then
232 if (.not. associated(usr_var_for_errest)) then
233 call mpistop("usr_var_for_errest not defined")
234 else
235 call usr_var_for_errest(ixg^ll,ixg^ll,iflag,ps(igrid)%w,ps(igrid)%x,tmp1)
236 end if
237 end if
238
239 do idims=1,ndim
240 hx^l=ix^l-kr(^d,idims);
241 jx^l=ix^l+kr(^d,idims);
242 if (iflag<=nw) then
243 if (logflag(iflag)) then
244 dp(ix^s)=dlog10(ps(igrid)%w(jx^s,iflag))-dlog10(ps(igrid)%w(ix^s,iflag))
245 dm(ix^s)=dlog10(ps(igrid)%w(ix^s,iflag))-dlog10(ps(igrid)%w(hx^s,iflag))
246 dref(ixm^t)=dabs(dlog10(ps(igrid)%w(jx^s,iflag)))&
247 + 2.0d0 * dabs(dlog10(ps(igrid)%w(ixm^t,iflag))) &
248 + dabs(dlog10(ps(igrid)%w(hx^s,iflag)))
249 else
250 dp(ix^s)=ps(igrid)%w(jx^s,iflag)-ps(igrid)%w(ix^s,iflag)
251 dm(ix^s)=ps(igrid)%w(ix^s,iflag)-ps(igrid)%w(hx^s,iflag)
252 dref(ixm^t)=dabs(ps(igrid)%w(jx^s,iflag))+2.0d0*dabs(ps(igrid)%w(ixm^t,iflag)) &
253 +dabs(ps(igrid)%w(hx^s,iflag))
254 end if
255 else
256 if (logflag(iflag)) then
257 dp(ix^s)=dlog10(tmp1(jx^s))-dlog10(tmp1(ix^s))
258 dm(ix^s)=dlog10(tmp1(ix^s))-dlog10(tmp1(hx^s))
259 dref(ix^s)=dabs(dlog10(tmp1(jx^s)))&
260 + 2.0d0 * dabs(dlog10(tmp1(ix^s))) &
261 + dabs(dlog10(tmp1(hx^s)))
262 else
263 dp(ix^s)=tmp1(jx^s)-tmp1(ix^s)
264 dm(ix^s)=tmp1(ix^s)-tmp1(hx^s)
265 dref(ix^s)=dabs(tmp1(jx^s))+2.0d0*dabs(tmp1(ix^s)) &
266 +dabs(tmp1(hx^s))
267 end if
268 end if
269
270 numerator(ixm^t)=numerator+(dp(ixm^t)-dm(ixm^t))**2
271 denominator(ixm^t)=denominator &
272 + (dabs(dp(ixm^t)) + dabs(dm(ixm^t)) + amr_wavefilter(level)*dref(ixm^t))**2
273
274 end do
275 error=error+w_refine_weight(iflag)*dsqrt(numerator/max(denominator,epsilon))
276 end do
277
278 refineflag=.false.
279 coarsenflag=.false.
280
281 threshold=refine_threshold(level)
282 {do ix^db=ixmlo^db,ixmhi^db\}
283
284 if (associated(usr_refine_threshold)) then
285 wtol(1:nw) = ps(igrid)%w(ix^d,1:nw)
286 xtol(1:ndim) = ps(igrid)%x(ix^d,1:ndim)
287 call usr_refine_threshold(wtol, xtol, threshold, global_time, level)
288 end if
289
290 if (error(ix^d) >= threshold) then
291 refineflag(ix^d) = .true.
292 else if (error(ix^d) <= derefine_ratio(level)*threshold) then
293 coarsenflag(ix^d) = .true.
294 end if
295 {end do\}
296
297 if (any(refineflag(ixm^t)).and.level<refine_max_level) refine(igrid,mype)=.true.
298 if (all(coarsenflag(ixm^t)).and.level>1) coarsen(igrid,mype)=.true.
299
300 end subroutine lohner_orig_grid
301
302 subroutine forcedrefine_grid(igrid,w)
304 use mod_forest, only: coarsen, refine, buffer
306
307 integer, intent(in) :: igrid
308 double precision, intent(in) :: w(ixg^t,nw)
309
310 double precision :: qt
311 integer :: level
312 integer :: my_refine, my_coarsen
313 logical, dimension(ixG^T) :: refineflag
314
315 level=node(plevel_,igrid)
316
317 ! initialize to 0
318 my_refine = 0
319 my_coarsen = 0
320
321 if (time_advance) then
322 qt=global_time+dt
323 else
324 qt=global_time
325 end if
326
327 if (associated(usr_refine_grid)) then
328 call usr_refine_grid(igrid,level,ixg^ll,ixm^ll,qt,w,ps(igrid)%x, &
329 my_refine,my_coarsen)
330 end if
331
332 if (my_coarsen==1) then
333 if (level>1) then
334 refine(igrid,mype)=.false.
335 coarsen(igrid,mype)=.true.
336 else
337 refine(igrid,mype)=.false.
338 coarsen(igrid,mype)=.false.
339 end if
340 end if
341
342 if (my_coarsen==-1)then
343 coarsen(igrid,mype)=.false.
344 end if
345
346 if (my_refine==1) then
347 if (level<refine_max_level) then
348 refine(igrid,mype)=.true.
349 coarsen(igrid,mype)=.false.
350 else
351 refine(igrid,mype)=.false.
352 coarsen(igrid,mype)=.false.
353 end if
354 end if
355
356 if (my_refine==-1) then
357 refine(igrid,mype)=.false.
358 end if
359
360 if (nbufferx^d/=0|.or.) then
361 if (refine(igrid,mype) .and. .not.buffer(igrid,mype)) then
362 refineflag(ixm^t)=.true.
363 call refinebuffer(igrid,refineflag)
364 end if
365 end if
366
367 end subroutine forcedrefine_grid
368
369 subroutine forcedrefine_grid_io(igrid,w)
370 use mod_forest, only: coarsen, refine
372
373 integer, intent(in) :: igrid
374 double precision, intent(in) :: w(ixg^t,nw)
375
376 logical, dimension(ixG^T) :: refineflag
377 integer :: level, my_levmin, my_levmax
378
379 level=node(plevel_,igrid)
380
381 if (level_io > 0) then
382 my_levmin = level_io
383 my_levmax = level_io
384 else
385 my_levmin = max(1,level_io_min)
386 my_levmax = min(refine_max_level,level_io_max)
387 end if
388
389 if (level>my_levmax) then
390 refine(igrid,mype)=.false.
391 coarsen(igrid,mype)=.true.
392 elseif (level<my_levmin) then
393 refine(igrid,mype)=.true.
394 coarsen(igrid,mype)=.false.
395 end if
396
397 if (level==my_levmin .or. level==my_levmax) then
398 refine(igrid,mype)=.false.
399 coarsen(igrid,mype)=.false.
400 end if
401
402 if(refine(igrid,mype).and.level>=refine_max_level)refine(igrid,mype)=.false.
403 if(coarsen(igrid,mype).and.level<=1)coarsen(igrid,mype)=.false.
404
405 end subroutine forcedrefine_grid_io
406
407 subroutine refinebuffer(igrid,refineflag)
408 use mod_forest, only: refine, buffer
410
411 integer, intent(in) :: igrid
412 logical, dimension(ixG^T), intent(in) :: refineflag
413
414 integer :: ishiftbuf^d, i^d, ix^l, ineighbor, ipe_neighbor, level
415
416 ishiftbuf^d=ixmhi^d-ixmlo^d-nbufferx^d+1;
417 {do i^db=-1,1\}
418 ixmin^d=max(ixmlo^d,ixmlo^d+i^d*ishiftbuf^d);
419 ixmax^d=min(ixmhi^d,ixmhi^d+i^d*ishiftbuf^d);
420 if (ixmax^d<ixmin^d|.or.) cycle
421 if (any(refineflag(ix^s))) then
422 select case (neighbor_type(i^d,igrid))
423 case (neighbor_coarse)
424 ineighbor=neighbor(1,i^d,igrid)
425 ipe_neighbor=neighbor(2,i^d,igrid)
426 if (.not.refine(ineighbor,ipe_neighbor)) then
427 buffer(ineighbor,ipe_neighbor)=.true.
428 refine(ineighbor,ipe_neighbor)=.true.
429 end if
430 case (neighbor_sibling)
431 level=node(plevel_,igrid)
432 if (level<refine_max_level) then
433 ineighbor=neighbor(1,i^d,igrid)
434 ipe_neighbor=neighbor(2,i^d,igrid)
435 if (.not.refine(ineighbor,ipe_neighbor)) then
436 buffer(ineighbor,ipe_neighbor)=.true.
437 refine(ineighbor,ipe_neighbor)=.true.
438 end if
439 end if
440 end select
441 end if
442 {end do\}
443
444 end subroutine refinebuffer
445
446end module mod_errest
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
subroutine, public errest
Do all local error estimation which determines (de)refinement.
Definition mod_errest.t:12
subroutine, public forcedrefine_grid_io(igrid, w)
Definition mod_errest.t:370
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
integer, parameter ndim
Number of spatial dimensions for grid variables.
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.
double precision dt
global time step
integer refine_criterion
select types of refine criterion
integer ixm
the mesh range of a physical block without ghost cells
integer ierrmpi
A global MPI error return code.
double precision, dimension(:), allocatable, parameter d
integer npe
The number of MPI tasks.
logical time_advance
do time evolving
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
Error tolerance ratio for derefinement decision.
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:37
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