Afivo 0.3
All Classes Namespaces Functions Variables Pages
m_af_stencil.f90
1!> This module contains functionality for dealing with numerical stencils
3#include "cpp_macros.h"
4 use m_af_types
5
6 implicit none
7 private
8
9 !> Initial size of stencil list
10 integer, parameter :: stencil_list_initial_size = 10
11
12 integer, parameter, public :: stencil_constant = 1 !< Constant stencil
13 integer, parameter, public :: stencil_variable = 2 !< Variable stencil
14 integer, parameter, public :: stencil_sparse = 3 !< Sparse stencil
15
16 !> Number of predefined stencil shapes
17 integer, parameter, private :: num_shapes = 5
18
19 !> 3/5/7 point stencil in 1D/2D/3D
20 integer, parameter, public :: af_stencil_357 = 1
21
22 !> Prolongation stencil using nearest 2, 3, 4 neighbors in 1D-3D
23 integer, parameter, public :: af_stencil_p234 = 2
24
25 !> Prolongation stencil using nearest 2, 4, 8 neighbors in 1D-3D
26 integer, parameter, public :: af_stencil_p248 = 3
27
28 !> Stencil for direct neighbors
29 integer, parameter, public :: af_stencil_246 = 4
30
31 !> Stencil for masking
32 integer, parameter, public :: af_stencil_mask = 5
33
34 !> Number of coefficients in the stencils
35 integer, parameter, public :: af_stencil_sizes(num_shapes) = &
36 [2*ndim+1, ndim+1, 2**ndim, 2*ndim, 1]
37
38 abstract interface
39 !> Subroutine for setting a stencil on a box
40 subroutine af_subr_stencil(box, stencil)
41 import
42 type(box_t), intent(in) :: box !< Box to set stencil for
43 type(stencil_t), intent(inout) :: stencil !< Stencil to set
44 end subroutine af_subr_stencil
45 end interface
46
47 public :: af_stencil_print_info
48 public :: af_stencil_index
49 public :: af_stencil_prepare_store
50 public :: af_stencil_remove
51 public :: af_stencil_store_box
52 public :: af_stencil_check_box
53 public :: af_stencil_allocate_coeff
54 public :: af_stencil_store
55 public :: af_stencil_apply
56 public :: af_stencil_apply_box
57 public :: af_stencil_gsrb_box
58 public :: af_stencil_prolong_box
59 public :: af_stencil_get_box
60 public :: af_stencil_try_constant
61
62contains
63
64 !> Print statistics about the stencils in the tree
65 subroutine af_stencil_print_info(tree)
66 type(af_t), intent(in) :: tree
67 integer :: id, n_stencils_stored
68 integer :: n_boxes_with_stencils
69 integer :: n_constant_stored, n_variable_stored
70 integer :: n, n_stencils, n_sparse_stored
71
72 n_stencils_stored = 0
73 n_constant_stored = 0
74 n_variable_stored = 0
75 n_sparse_stored = 0
76 n_boxes_with_stencils = 0
77
78 do id = 1, tree%highest_id
79 if (.not. tree%boxes(id)%in_use) cycle
80
81 n_stencils = tree%boxes(id)%n_stencils
82 if (n_stencils > 0) then
83 n_boxes_with_stencils = n_boxes_with_stencils + 1
84 n_stencils_stored = n_stencils_stored + n_stencils
85
86 do n = 1, n_stencils
87 select case (tree%boxes(id)%stencils(n)%stype)
88 case (stencil_constant)
89 n_constant_stored = n_constant_stored + 1
90 case (stencil_variable)
91 n_variable_stored = n_variable_stored + 1
92 case (stencil_sparse)
93 n_sparse_stored = n_sparse_stored + 1
94 end select
95 end do
96 end if
97 end do
98
99 write(*, '(A)') ''
100 write(*, '(A)') ' ** Information about stencils **'
101 write(*, '(A, I0)') ' #boxes with stencils: ', n_boxes_with_stencils
102 write(*, '(A, I0)') ' #stencils stored: ', n_stencils_stored
103 write(*, '(A, I0)') ' #constant stencils: ', n_constant_stored
104 write(*, '(A, I0)') ' #variable stencils: ', n_variable_stored
105 write(*, '(A, I0)') ' #sparse stencils: ', n_sparse_stored
106 end subroutine af_stencil_print_info
107
108 !> Get index of a stencil, or af_stencil_none is not present
109 pure integer function af_stencil_index(box, key)
110 type(box_t), intent(in) :: box
111 integer, intent(in) :: key
112 integer :: i
113
114 af_stencil_index = af_stencil_none
115 do i = 1, box%n_stencils
116 if (box%stencils(i)%key == key) then
117 af_stencil_index = i
118 exit
119 end if
120 end do
121 end function af_stencil_index
122
123 !> Store a constant stencil
124 subroutine af_stencil_store(tree, key, set_stencil)
125 type(af_t), intent(inout) :: tree
126 integer, intent(in) :: key !< Stencil key
127 !> Method to set a stencil
128 procedure(af_subr_stencil) :: set_stencil
129 integer :: lvl, i, id
130
131 !$omp parallel private(lvl, i, id)
132 do lvl = 1, tree%highest_lvl
133 !$omp do
134 do i = 1, size(tree%lvls(lvl)%ids)
135 id = tree%lvls(lvl)%ids(i)
136 call af_stencil_store_box(tree%boxes(id), key, set_stencil)
137 end do
138 !$omp end do
139 end do
140 !$omp end parallel
141 end subroutine af_stencil_store
142
143 !> Prepare to store a stencil
144 subroutine af_stencil_prepare_store(box, key, ix)
145 type(box_t), intent(inout) :: box
146 integer, intent(in) :: key !< Stencil key
147 integer, intent(out) :: ix !< Index to store stencil
148 type(stencil_t), allocatable :: tmp(:)
149
150 ix = af_stencil_index(box, key)
151
152 if (ix == af_stencil_none) then
153 ! Allocate storage if necessary
154 if (.not. allocated(box%stencils)) then
155 allocate(box%stencils(stencil_list_initial_size))
156 else if (box%n_stencils == size(box%stencils)) then
157 allocate(tmp(2 * box%n_stencils))
158 tmp(1:box%n_stencils) = box%stencils
159 call move_alloc(tmp, box%stencils)
160 end if
161
162 box%n_stencils = box%n_stencils + 1
163 ix = box%n_stencils
164 box%stencils(ix)%key = key
165 else
166 error stop "Stencil with this key has already been stored"
167 end if
168 end subroutine af_stencil_prepare_store
169
170 !> Allocate storage for stencil coefficients
171 subroutine af_stencil_allocate_coeff(stencil, nc, use_f, n_sparse)
172 type(stencil_t), intent(inout) :: stencil !< Stencil
173 !> Number of cells per box dimension
174 integer, intent(in) :: nc
175 !> Whether storage for the extra arrays f and bc_correction is required
176 !> (only for variable stencils)
177 logical, intent(in), optional :: use_f
178 !> Number of entries for sparse stencil
179 integer, intent(in), optional :: n_sparse
180 logical :: allocate_f
181 integer :: n_coeff
182
183 allocate_f = .false.; if (present(use_f)) allocate_f = use_f
184 if (stencil%shape < 1 .or. stencil%shape > num_shapes) &
185 error stop "Unknown stencil shape"
186
187 n_coeff = af_stencil_sizes(stencil%shape)
188
189 select case (stencil%stype)
190 case (stencil_constant)
191 if (.not. allocated(stencil%c)) then
192 allocate(stencil%c(n_coeff))
193 else if (size(stencil%c) /= n_coeff) then
194 deallocate(stencil%c)
195 allocate(stencil%c(n_coeff))
196 end if
197
198 ! Clean up other storage if it is present
199 if (allocated(stencil%v)) deallocate(stencil%v)
200 if (allocated(stencil%f)) deallocate(stencil%f, stencil%bc_correction)
201 if (allocated(stencil%sparse_v)) &
202 deallocate(stencil%sparse_v, stencil%sparse_ix)
203 case (stencil_variable)
204 if (.not. allocated(stencil%v)) then
205 allocate(stencil%v(n_coeff, dtimes(nc)))
206 else if (size(stencil%v, 1) /= n_coeff) then
207 deallocate(stencil%v)
208 allocate(stencil%v(n_coeff, dtimes(nc)))
209 end if
210
211 if (allocate_f .and. .not. allocated(stencil%f)) then
212 allocate(stencil%f(dtimes(nc)))
213 allocate(stencil%bc_correction(dtimes(nc)))
214 else if (.not. allocate_f .and. allocated(stencil%f)) then
215 deallocate(stencil%f, stencil%bc_correction)
216 end if
217
218 ! Clean up other storage if it is present
219 if (allocated(stencil%c)) deallocate(stencil%c)
220 if (allocated(stencil%sparse_v)) &
221 deallocate(stencil%sparse_v, stencil%sparse_ix)
222 case (stencil_sparse)
223 if (.not. present(n_sparse)) error stop "n_sparse required"
224
225 if (.not. allocated(stencil%sparse_v)) then
226 allocate(stencil%sparse_ix(ndim, n_sparse))
227 allocate(stencil%sparse_v(n_coeff, n_sparse))
228 else if (any(size(stencil%sparse_v) /= [n_coeff, n_sparse])) then
229 deallocate(stencil%sparse_v)
230 deallocate(stencil%sparse_ix)
231 allocate(stencil%sparse_ix(ndim, n_sparse))
232 allocate(stencil%sparse_v(n_coeff, n_sparse))
233 end if
234
235 ! Clean up other storage if it is present
236 if (allocated(stencil%c)) deallocate(stencil%c)
237 if (allocated(stencil%v)) deallocate(stencil%v)
238 if (allocated(stencil%f)) deallocate(stencil%f, stencil%bc_correction)
239 case default
240 error stop "Unknow stencil%stype"
241 end select
242 end subroutine af_stencil_allocate_coeff
243
244 !> Remove a stencil
245 subroutine af_stencil_remove(tree, key)
246 type(af_t), intent(inout) :: tree
247 integer, intent(in) :: key !< Stencil key
248 integer :: lvl, i, id
249
250 !$omp parallel private(lvl, i, id)
251 do lvl = 1, tree%highest_lvl
252 !$omp do
253 do i = 1, size(tree%lvls(lvl)%ids)
254 id = tree%lvls(lvl)%ids(i)
255 call af_stencil_remove_box(tree%boxes(id), key)
256 end do
257 !$omp end do
258 end do
259 !$omp end parallel
260 end subroutine af_stencil_remove
261
262 !> Store a stencil for a box
263 subroutine af_stencil_store_box(box, key, set_stencil)
264 type(box_t), intent(inout) :: box
265 integer, intent(in) :: key !< Stencil key
266 !> Method to set a stencil
267 procedure(af_subr_stencil) :: set_stencil
268 integer :: ix
269
270 call af_stencil_prepare_store(box, key, ix)
271 call set_stencil(box, box%stencils(ix))
272 end subroutine af_stencil_store_box
273
274 !> Remove a stencil from a box. This will change the order of other stencils.
275 subroutine af_stencil_remove_box(box, key)
276 type(box_t), intent(inout) :: box
277 integer, intent(in) :: key !< Stencil key
278 integer :: ix
279 type(stencil_t) :: empty_stencil
280
281 ix = af_stencil_index(box, key)
282 if (ix == af_stencil_none) error stop "Stencil not present"
283
284 ! Ensure there are no gaps in the stencil list
285 if (ix == box%n_stencils) then
286 box%stencils(ix) = empty_stencil
287 else
288 box%stencils(ix) = box%stencils(box%n_stencils)
289 box%stencils(box%n_stencils) = empty_stencil
290 end if
291
292 box%n_stencils = box%n_stencils - 1
293 end subroutine af_stencil_remove_box
294
295 !> Check if a stencil was correctly stored for a box
296 subroutine af_stencil_check_box(box, key, ix)
297 type(box_t), intent(in) :: box !< Box
298 integer, intent(in) :: key !< Stencil key
299 integer, intent(in) :: ix !< Stencil index
300
301 if (key == af_stencil_none) &
302 error stop "key == af_stencil_none"
303
304 if (af_stencil_index(box, key) /= ix) &
305 error stop "Stencil with key not found at index"
306
307 associate(stencil => box%stencils(ix))
308 if (stencil%shape < 1 .or. stencil%shape > num_shapes) &
309 error stop "Unknown stencil shape"
310 select case (stencil%stype)
311 case (stencil_constant)
312 if (.not. allocated(stencil%c)) &
313 error stop "stencil%c not allocated"
314 case (stencil_variable)
315 if (.not. allocated(stencil%v)) &
316 error stop "stencil%v not allocated"
317 case (stencil_sparse)
318 if (.not. allocated(stencil%sparse_ix)) &
319 error stop "stencil%sparse_ix not allocated"
320 if (.not. allocated(stencil%sparse_v)) &
321 error stop "stencil%sparse_v not allocated"
322 case default
323 error stop "Unknow stencil%stype"
324 end select
325 end associate
326 end subroutine af_stencil_check_box
327
328 subroutine af_stencil_apply(tree, key, iv, i_out)
329 type(af_t), intent(inout) :: tree !< Operate on this box
330 integer, intent(in) :: key !< Stencil key
331 integer, intent(in) :: iv !< Input variable
332 integer, intent(in) :: i_out !< Output variable
333
334 integer :: lvl, i, id
335
336 !$omp parallel private(lvl, i, id)
337 do lvl = 1, tree%highest_lvl
338 !$omp do
339 do i = 1, size(tree%lvls(lvl)%ids)
340 id = tree%lvls(lvl)%ids(i)
341 call af_stencil_apply_box(tree%boxes(id), key, iv, i_out)
342 end do
343 !$omp end do
344 end do
345 !$omp end parallel
346 end subroutine af_stencil_apply
347
348 subroutine af_stencil_apply_box(box, key, iv, i_out)
349 type(box_t), intent(inout) :: box !< Operate on this box
350 integer, intent(in) :: key !< Stencil key
351 integer, intent(in) :: iv !< Input variable
352 integer, intent(in) :: i_out !< Output variable
353 integer :: i
354
355 i = af_stencil_index(box, key)
356 if (i == af_stencil_none) error stop "Stencil not stored"
357
358 select case (box%stencils(i)%shape)
359 case (af_stencil_357)
360 call stencil_apply_357(box, box%stencils(i), iv, i_out)
361 case default
362 error stop "Unknown stencil"
363 end select
364 end subroutine af_stencil_apply_box
365
366 !> Apply a 3/5/7-point stencil in 1D/2D/3D
367 subroutine stencil_apply_357(box, stencil, iv, i_out)
368 type(box_t), intent(inout) :: box !< Operate on this box
369 type(stencil_t), intent(in) :: stencil !< Stencil
370 integer, intent(in) :: iv !< Input variable
371 integer, intent(in) :: i_out !< Output variable
372 real(dp) :: c(2*NDIM+1)
373 integer :: IJK
374#if NDIM == 2
375 real(dp) :: rfac(2, box%n_cell), c_cyl(2*NDIM+1)
376 real(dp) :: cc_cyl(2*NDIM+1, box%n_cell)
377#endif
378
379 if (iv == i_out) error stop "Cannot have iv == i_out"
380 if (stencil%stype == stencil_sparse) error stop "sparse not implemented"
381
382 associate(cc => box%cc, nc => box%n_cell)
383
384#if NDIM == 1
385 if (stencil%stype == stencil_constant) then
386 c = stencil%c
387 do kji_do(1, nc)
388 cc(i, i_out) = &
389 c(1) * cc(i, iv) + c(2) * cc(i-1, iv) + c(3) * cc(i+1, iv)
390 end do; close_do
391 else
392 do kji_do(1, nc)
393 c = stencil%v(:, ijk)
394 cc(i, i_out) = &
395 c(1) * cc(i, iv) + c(2) * cc(i-1, iv) + c(3) * cc(i+1, iv)
396 end do; close_do
397 end if
398#elif NDIM == 2
399 if (stencil%cylindrical_gradient) then
400 ! Correct for cylindrical coordinates, assuming the elements correspond
401 ! to a gradient operation
402 call af_cyl_flux_factors(box, rfac)
403
404 if (stencil%stype == stencil_constant) then
405 c = stencil%c
406
407 ! Pre-compute coefficients for each i-index
408 do i = 1, nc
409 cc_cyl(2:3, i) = rfac(1:2, i) * c(2:3)
410 cc_cyl(1, i) = c(1) - (cc_cyl(2, i) - c(2)) &
411 - (cc_cyl(3, i) - c(3))
412 cc_cyl(4:, i) = c(4:)
413 end do
414
415 do kji_do(1, nc)
416 cc(i, j, i_out) = &
417 cc_cyl(1, i) * cc(i, j, iv) + &
418 cc_cyl(2, i) * cc(i-1, j, iv) + &
419 cc_cyl(3, i) * cc(i+1, j, iv) + &
420 cc_cyl(4, i) * cc(i, j-1, iv) + &
421 cc_cyl(5, i) * cc(i, j+1, iv)
422 end do; close_do
423 else
424 ! Variable stencil
425 do kji_do(1, nc)
426 c = stencil%v(:, ijk)
427 c_cyl(2:3) = rfac(1:2, i) * c(2:3)
428 c_cyl(1) = c(1) - (c_cyl(2) - c(2)) - (c_cyl(3) - c(3))
429 c_cyl(4:) = c(4:)
430 cc(i, j, i_out) = &
431 c_cyl(1) * cc(i, j, iv) + &
432 c_cyl(2) * cc(i-1, j, iv) + &
433 c_cyl(3) * cc(i+1, j, iv) + &
434 c_cyl(4) * cc(i, j-1, iv) + &
435 c_cyl(5) * cc(i, j+1, iv)
436 end do; close_do
437 end if
438 else
439 ! No cylindrical gradient correction
440 if (stencil%stype == stencil_constant) then
441 c = stencil%c
442 do kji_do(1, nc)
443 cc(i, j, i_out) = &
444 c(1) * cc(i, j, iv) + &
445 c(2) * cc(i-1, j, iv) + &
446 c(3) * cc(i+1, j, iv) + &
447 c(4) * cc(i, j-1, iv) + &
448 c(5) * cc(i, j+1, iv)
449 end do; close_do
450 else
451 do kji_do(1, nc)
452 c = stencil%v(:, ijk)
453 cc(i, j, i_out) = &
454 c(1) * cc(i, j, iv) + &
455 c(2) * cc(i-1, j, iv) + &
456 c(3) * cc(i+1, j, iv) + &
457 c(4) * cc(i, j-1, iv) + &
458 c(5) * cc(i, j+1, iv)
459 end do; close_do
460 end if
461 end if
462#elif NDIM == 3
463 if (stencil%stype == stencil_constant) then
464 c = stencil%c
465 do kji_do(1, nc)
466 cc(i, j, k, i_out) = &
467 c(1) * cc(i, j, k, iv) + &
468 c(2) * cc(i-1, j, k, iv) + &
469 c(3) * cc(i+1, j, k, iv) + &
470 c(4) * cc(i, j-1, k, iv) + &
471 c(5) * cc(i, j+1, k, iv) + &
472 c(6) * cc(i, j, k-1, iv) + &
473 c(7) * cc(i, j, k+1, iv)
474 end do; close_do
475 else
476 do kji_do(1, nc)
477 c = stencil%v(:, ijk)
478 cc(i, j, k, i_out) = &
479 c(1) * cc(i, j, k, iv) + &
480 c(2) * cc(i-1, j, k, iv) + &
481 c(3) * cc(i+1, j, k, iv) + &
482 c(4) * cc(i, j-1, k, iv) + &
483 c(5) * cc(i, j+1, k, iv) + &
484 c(6) * cc(i, j, k-1, iv) + &
485 c(7) * cc(i, j, k+1, iv)
486 end do; close_do
487 end if
488#endif
489
490 if (allocated(stencil%bc_correction)) then
491 cc(dtimes(1:nc), i_out) = cc(dtimes(1:nc), i_out) - &
492 stencil%bc_correction
493 end if
494 end associate
495
496 end subroutine stencil_apply_357
497
498 ! subroutine stencil_correct_bc_357(box, stencil, iv, tmp)
499 ! type(box_t), intent(inout) :: box !< Operate on this box
500 ! type(stencil_t), intent(in) :: stencil !< Stencil
501 ! integer, intent(in) :: iv !< Input variable
502 ! real(dp), intent(inout) :: tmp(DTIMES(box%n_cell))
503 ! integer :: bc_ix, bc_type, nb, lo(NDIM), hi(NDIM)
504 ! integer :: nb_dim, olo(NDIM), ohi(NDIM)
505 ! real(dp) :: bc_val(box%n_cell**(NDIM-1))
506 ! real(dp) :: stencil_coeffs(box%n_cell**(NDIM-1))
507 ! real(dp) :: values_inside(box%n_cell**(NDIM-1))
508 ! real(dp) :: values_outside(box%n_cell**(NDIM-1))
509
510 ! do bc_ix = 1, box%n_bc
511 ! nb = box%bc_index_to_nb(bc_ix)
512
513 ! bc_val = box%bc_val(:, iv, bc_ix)
514 ! bc_type = box%bc_type(iv, bc_ix)
515
516 ! ! Determine index range next to boundary
517 ! call af_get_index_bc_inside(nb, box%n_cell, 1, lo, hi)
518 ! call af_get_index_bc_outside(nb, box%n_cell, 1, olo, ohi)
519
520 ! ! Get stencil coefficients near boundary
521 ! if (stencil%constant) then
522 ! stencil_coeffs = stencil%c(nb+1)
523 ! else
524 ! stencil_coeffs = pack(stencil%v(nb+1, &
525 ! DSLICE(lo, hi)), .true.)
526 ! end if
527
528 ! values_inside = pack(box%cc(DSLICE(lo, hi), iv), .true.)
529 ! values_outside = pack(box%cc(DSLICE(olo, ohi), iv), .true.)
530
531 ! select case (bc_type)
532 ! case (af_bc_dirichlet)
533 ! ! Dirichlet value at cell face, so compute gradient over h/2
534 ! ! E.g. 1 -2 1 becomes 0 -3 1 for a 1D Laplacian
535 ! tmp(DSLICE(lo, hi)) = tmp(DSLICE(lo, hi)) &
536 ! + reshape(2 * stencil_coeffs * bc_val - &
537 ! stencil_coeffs * (values_inside + values_outside), &
538 ! hi - lo + 1)
539 ! case (af_bc_neumann)
540 ! nb_dim = af_neighb_dim(nb)
541 ! ! E.g. 1 -2 1 becomes 0 -1 1 for a 1D Laplacian
542 ! tmp(DSLICE(lo, hi)) = tmp(DSLICE(lo, hi)) &
543 ! - reshape(stencil_coeffs * (values_outside - values_inside) &
544 ! - stencil_coeffs * af_neighb_high_pm(nb) * box%dr(nb_dim) * &
545 ! bc_val, hi - lo + 1)
546 ! case default
547 ! error stop "unsupported boundary condition"
548 ! end select
549 ! end do
550 ! end subroutine stencil_correct_bc_357
551
552 subroutine af_stencil_prolong_box(box_p, box_c, key, iv, iv_to, add)
553 type(box_t), intent(in) :: box_p !< Parent box
554 type(box_t), intent(inout) :: box_c !< Child box
555 integer, intent(in) :: key !< Stencil key
556 integer, intent(in) :: iv !< Input variable
557 integer, intent(in) :: iv_to !< Destination variable
558 logical, intent(in), optional :: add !< Add to old values
559 logical :: add_to
560 integer :: i
561
562 add_to = .false.
563 if (present(add)) add_to = add
564
565 i = af_stencil_index(box_c, key)
566 if (i == af_stencil_none) error stop "Stencil not stored"
567
568 select case (box_c%stencils(i)%shape)
569 case (af_stencil_p234)
570 call stencil_prolong_234(box_p, box_c, box_c%stencils(i), &
571 iv, iv_to, add_to)
572 case (af_stencil_p248)
573 call stencil_prolong_248(box_p, box_c, box_c%stencils(i), &
574 iv, iv_to, add_to)
575 case default
576 print *, "box_c%stencils(i)%shape: ", box_c%stencils(i)%shape
577 error stop "Unknown stencil"
578 end select
579 end subroutine af_stencil_prolong_box
580
581 !> Linear prolongation using nearest NDIM+1 neighbors
582 subroutine stencil_prolong_234(box_p, box_c, stencil, iv, iv_to, add)
583 type(box_t), intent(in) :: box_p !< Parent box
584 type(box_t), intent(inout) :: box_c !< Child box
585 type(stencil_t), intent(in) :: stencil !< Stencil
586 integer, intent(in) :: iv !< Input variable
587 integer, intent(in) :: iv_to !< Destination variable
588 logical, intent(in) :: add !< Add to old values
589
590 integer :: nc, ix_offset(NDIM), IJK
591 integer :: IJK_(c1), IJK_(c2)
592 real(dp) :: c(NDIM+1)
593
594 nc = box_c%n_cell
595 ix_offset = af_get_child_offset(box_c)
596 if (stencil%stype == stencil_sparse) error stop "sparse not implemented"
597 if (.not. add) box_c%cc(dtimes(1:nc), iv_to) = 0
598
599 ! In these loops, we calculate the closest coarse index (_c1), and the
600 ! one-but-closest (_c2). The fine cell lies in between.
601#if NDIM == 1
602 if (stencil%stype == stencil_constant) then
603 c = stencil%c
604 do i = 1, nc
605 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
606 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
607 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
608 c(1) * box_p%cc(i_c1, iv) + &
609 c(2) * box_p%cc(i_c2, iv)
610 end do
611 else
612 do i = 1, nc
613 c = stencil%v(:, ijk)
614 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
615 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
616 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
617 c(1) * box_p%cc(i_c1, iv) + &
618 c(2) * box_p%cc(i_c2, iv)
619 end do
620 end if
621#elif NDIM == 2
622 if (stencil%stype == stencil_constant) then
623 c = stencil%c
624 do j = 1, nc
625 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
626 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
627 do i = 1, nc
628 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
629 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
630 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
631 c(1) * box_p%cc(i_c1, j_c1, iv) + &
632 c(2) * box_p%cc(i_c2, j_c1, iv) + &
633 c(3) * box_p%cc(i_c1, j_c2, iv)
634 end do
635 end do
636 else
637 do j = 1, nc
638 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
639 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
640 do i = 1, nc
641 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
642 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
643 c = stencil%v(:, ijk)
644 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
645 c(1) * box_p%cc(i_c1, j_c1, iv) + &
646 c(2) * box_p%cc(i_c2, j_c1, iv) + &
647 c(3) * box_p%cc(i_c1, j_c2, iv)
648 end do
649 end do
650 end if
651#elif NDIM == 3
652 if (stencil%stype == stencil_constant) then
653 c = stencil%c
654 do k = 1, nc
655 k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
656 k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
657 do j = 1, nc
658 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
659 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
660 do i = 1, nc
661 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
662 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
663 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
664 c(1) * box_p%cc(i_c1, j_c1, k_c1, iv) + &
665 c(2) * box_p%cc(i_c2, j_c1, k_c1, iv) + &
666 c(3) * box_p%cc(i_c1, j_c2, k_c1, iv) + &
667 c(4) * box_p%cc(i_c1, j_c1, k_c2, iv)
668 end do
669 end do
670 end do
671 else
672 do k = 1, nc
673 k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
674 k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
675 do j = 1, nc
676 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
677 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
678 do i = 1, nc
679 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
680 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
681 c = stencil%v(:, ijk)
682 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
683 c(1) * box_p%cc(i_c1, j_c1, k_c1, iv) + &
684 c(2) * box_p%cc(i_c2, j_c1, k_c1, iv) + &
685 c(3) * box_p%cc(i_c1, j_c2, k_c1, iv) + &
686 c(4) * box_p%cc(i_c1, j_c1, k_c2, iv)
687 end do
688 end do
689 end do
690 end if
691#endif
692 end subroutine stencil_prolong_234
693
694 !> (Bi-/tri-)linear prolongation using nearest 2**NDIM neighbors
695 subroutine stencil_prolong_248(box_p, box_c, stencil, iv, iv_to, add)
696 type(box_t), intent(in) :: box_p !< Parent box
697 type(box_t), intent(inout) :: box_c !< Child box
698 type(stencil_t), intent(in) :: stencil !< Stencil
699 integer, intent(in) :: iv !< Input variable
700 integer, intent(in) :: iv_to !< Destination variable
701 logical, intent(in) :: add !< Add to old values
702
703 integer :: nc, ix_offset(NDIM), IJK
704 integer :: IJK_(c1), IJK_(c2)
705 real(dp) :: c(2**NDIM)
706
707 nc = box_c%n_cell
708 ix_offset = af_get_child_offset(box_c)
709 if (stencil%stype == stencil_sparse) error stop "sparse not implemented"
710 if (.not. add) box_c%cc(dtimes(1:nc), iv_to) = 0
711
712 ! In these loops, we calculate the closest coarse index (_c1), and the
713 ! one-but-closest (_c2). The fine cell lies in between.
714#if NDIM == 1
715 if (stencil%stype == stencil_constant) then
716 c = stencil%c
717 do i = 1, nc
718 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
719 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
720 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
721 c(1) * box_p%cc(i_c1, iv) + &
722 c(2) * box_p%cc(i_c2, iv)
723 end do
724 else
725 do i = 1, nc
726 c = stencil%v(:, ijk)
727 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
728 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
729 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
730 c(1) * box_p%cc(i_c1, iv) + &
731 c(2) * box_p%cc(i_c2, iv)
732 end do
733 end if
734#elif NDIM == 2
735 if (stencil%stype == stencil_constant) then
736 c = stencil%c
737 do j = 1, nc
738 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
739 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
740 do i = 1, nc
741 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
742 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
743 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
744 c(1) * box_p%cc(i_c1, j_c1, iv) + &
745 c(2) * box_p%cc(i_c2, j_c1, iv) + &
746 c(3) * box_p%cc(i_c1, j_c2, iv) + &
747 c(4) * box_p%cc(i_c2, j_c2, iv)
748 end do
749 end do
750 else
751 do j = 1, nc
752 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
753 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
754 do i = 1, nc
755 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
756 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
757 c = stencil%v(:, ijk)
758 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
759 c(1) * box_p%cc(i_c1, j_c1, iv) + &
760 c(2) * box_p%cc(i_c2, j_c1, iv) + &
761 c(3) * box_p%cc(i_c1, j_c2, iv) + &
762 c(4) * box_p%cc(i_c2, j_c2, iv)
763 end do
764 end do
765 end if
766#elif NDIM == 3
767 if (stencil%stype == stencil_constant) then
768 c = stencil%c
769 do k = 1, nc
770 k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
771 k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
772 do j = 1, nc
773 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
774 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
775 do i = 1, nc
776 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
777 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
778 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
779 c(1) * box_p%cc(i_c1, j_c1, k_c1, iv) + &
780 c(2) * box_p%cc(i_c2, j_c1, k_c1, iv) + &
781 c(3) * box_p%cc(i_c1, j_c2, k_c1, iv) + &
782 c(4) * box_p%cc(i_c2, j_c2, k_c1, iv) + &
783 c(5) * box_p%cc(i_c1, j_c1, k_c2, iv) + &
784 c(6) * box_p%cc(i_c2, j_c1, k_c2, iv) + &
785 c(7) * box_p%cc(i_c1, j_c2, k_c2, iv) + &
786 c(8) * box_p%cc(i_c2, j_c2, k_c2, iv)
787 end do
788 end do
789 end do
790 else
791 do k = 1, nc
792 k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
793 k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
794 do j = 1, nc
795 j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
796 j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
797 do i = 1, nc
798 i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
799 i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
800 c = stencil%v(:, ijk)
801 box_c%cc(ijk, iv_to) = box_c%cc(ijk, iv_to) + &
802 c(1) * box_p%cc(i_c1, j_c1, k_c1, iv) + &
803 c(2) * box_p%cc(i_c2, j_c1, k_c1, iv) + &
804 c(3) * box_p%cc(i_c1, j_c2, k_c1, iv) + &
805 c(4) * box_p%cc(i_c2, j_c2, k_c1, iv) + &
806 c(5) * box_p%cc(i_c1, j_c1, k_c2, iv) + &
807 c(6) * box_p%cc(i_c2, j_c1, k_c2, iv) + &
808 c(7) * box_p%cc(i_c1, j_c2, k_c2, iv) + &
809 c(8) * box_p%cc(i_c2, j_c2, k_c2, iv)
810 end do
811 end do
812 end do
813 end if
814#endif
815 end subroutine stencil_prolong_248
816
817 !> Perform Gauss-Seidel red-black on a stencil
818 subroutine af_stencil_gsrb_box(box, key, redblack, iv, i_rhs)
819 type(box_t), intent(inout) :: box !< Operate on this box
820 integer, intent(in) :: key !< Stencil key
821 integer, intent(in) :: redblack !< Even or odd integer
822 integer, intent(in) :: iv !< Solve for variable
823 integer, intent(in) :: i_rhs !< Right-hand side
824 integer :: i
825
826 i = af_stencil_index(box, key)
827 if (i == af_stencil_none) error stop "Stencil not stored"
828
829 select case (box%stencils(i)%shape)
830 case (af_stencil_357)
831 call stencil_gsrb_357(box, box%stencils(i), redblack, iv, i_rhs)
832 case default
833 error stop "Unknown stencil"
834 end select
835 end subroutine af_stencil_gsrb_box
836
837 !> Perform Gauss-Seidel red-black on a 3/5/7-point stencil in 1D/2D/3D
838 subroutine stencil_gsrb_357(box, stencil, redblack, iv, i_rhs)
839 type(box_t), intent(inout) :: box !< Operate on this box
840 type(stencil_t), intent(in) :: stencil !< Stencil
841 integer, intent(in) :: redblack !< Even or odd integer
842 integer, intent(in) :: iv !< Solve for variable
843 integer, intent(in) :: i_rhs !< Right-hand side
844
845 real(dp) :: c(2*NDIM+1), inv_c1
846 integer :: IJK, i0, nc
847#if NDIM == 2
848 real(dp) :: rfac(2, box%n_cell), c_cyl(2*NDIM+1)
849 real(dp) :: cc_cyl(2*NDIM+1, box%n_cell), inv_cc1(box%n_cell)
850#endif
851
852 if (stencil%stype == stencil_sparse) error stop "sparse not implemented"
853 nc = box%n_cell
854
855 associate(cc => box%cc, nc => box%n_cell)
856 if (allocated(stencil%bc_correction)) then
857 cc(dtimes(1:nc), i_rhs) = cc(dtimes(1:nc), i_rhs) + &
858 stencil%bc_correction
859 end if
860
861#if NDIM == 1
862 i0 = 2 - iand(redblack, 1)
863 if (stencil%stype == stencil_constant) then
864 c = stencil%c
865 inv_c1 = 1 / c(1)
866
867 do i = i0, nc, 2
868 cc(ijk, iv) = (cc(ijk, i_rhs) &
869 - c(2) * cc(i-1, iv) &
870 - c(3) * cc(i+1, iv)) * inv_c1
871 end do
872 else
873 do i = i0, nc, 2
874 c = stencil%v(:, ijk)
875 cc(ijk, iv) = (cc(ijk, i_rhs) &
876 - c(2) * cc(i-1, iv) &
877 - c(3) * cc(i+1, iv)) / c(1)
878 end do
879 end if
880#elif NDIM == 2
881 if (stencil%cylindrical_gradient) then
882 ! Correct for cylindrical coordinates, assuming the elements correspond
883 ! to a gradient operation
884 call af_cyl_flux_factors(box, rfac)
885
886 if (stencil%stype == stencil_constant) then
887 c = stencil%c
888
889 ! Pre-compute coefficients for each i-index
890 do i = 1, nc
891 cc_cyl(2:3, i) = rfac(1:2, i) * c(2:3)
892 cc_cyl(1, i) = c(1) - (cc_cyl(2, i) - c(2)) &
893 - (cc_cyl(3, i) - c(3))
894 cc_cyl(4:, i) = c(4:)
895 inv_cc1(i) = 1 / cc_cyl(1, i)
896 end do
897
898 do j = 1, nc
899 i0 = 2 - iand(ieor(redblack, j), 1)
900 do i = i0, nc, 2
901 cc(ijk, iv) = (cc(ijk, i_rhs) &
902 - cc_cyl(2, i) * cc(i-1, j, iv) &
903 - cc_cyl(3, i) * cc(i+1, j, iv) &
904 - cc_cyl(4, i) * cc(i, j-1, iv) &
905 - cc_cyl(5, i) * cc(i, j+1, iv)) * inv_cc1(i)
906 end do
907 end do
908 else
909 ! Variable stencil
910 do j = 1, nc
911 i0 = 2 - iand(ieor(redblack, j), 1)
912 do i = i0, nc, 2
913 c = stencil%v(:, ijk)
914 c_cyl(2:3) = rfac(1:2, i) * c(2:3)
915 c_cyl(1) = c(1) - (c_cyl(2) - c(2)) - (c_cyl(3) - c(3))
916 c_cyl(4:) = c(4:)
917
918 cc(ijk, iv) = (cc(ijk, i_rhs) &
919 - c_cyl(2) * cc(i-1, j, iv) &
920 - c_cyl(3) * cc(i+1, j, iv) &
921 - c_cyl(4) * cc(i, j-1, iv) &
922 - c_cyl(5) * cc(i, j+1, iv)) / c_cyl(1)
923 end do
924 end do
925 end if
926 else ! No cylindrical gradient correction
927 if (stencil%stype == stencil_constant) then
928 c = stencil%c
929 inv_c1 = 1 / c(1)
930
931 do j = 1, nc
932 i0 = 2 - iand(ieor(redblack, j), 1)
933 do i = i0, nc, 2
934 cc(ijk, iv) = (cc(ijk, i_rhs) &
935 - c(2) * cc(i-1, j, iv) &
936 - c(3) * cc(i+1, j, iv) &
937 - c(4) * cc(i, j-1, iv) &
938 - c(5) * cc(i, j+1, iv)) * inv_c1
939 end do
940 end do
941 else
942 do j = 1, nc
943 i0 = 2 - iand(ieor(redblack, j), 1)
944 do i = i0, nc, 2
945 c = stencil%v(:, ijk)
946 cc(ijk, iv) = (cc(ijk, i_rhs) &
947 - c(2) * cc(i-1, j, iv) &
948 - c(3) * cc(i+1, j, iv) &
949 - c(4) * cc(i, j-1, iv) &
950 - c(5) * cc(i, j+1, iv)) / c(1)
951 end do
952 end do
953 end if
954 end if
955#elif NDIM == 3
956 if (stencil%stype == stencil_constant) then
957 c = stencil%c
958 inv_c1 = 1 / c(1)
959
960 do k = 1, nc
961 do j = 1, nc
962 i0 = 2 - iand(ieor(redblack, k+j), 1)
963 do i = i0, nc, 2
964 cc(ijk, iv) = (cc(ijk, i_rhs) &
965 - c(2) * cc(i-1, j, k, iv) &
966 - c(3) * cc(i+1, j, k, iv) &
967 - c(4) * cc(i, j-1, k, iv) &
968 - c(5) * cc(i, j+1, k, iv) &
969 - c(6) * cc(i, j, k-1, iv) &
970 - c(7) * cc(i, j, k+1, iv)) * inv_c1
971 end do
972 end do
973 end do
974 else
975 do k = 1, nc
976 do j = 1, nc
977 i0 = 2 - iand(ieor(redblack, k+j), 1)
978 do i = i0, nc, 2
979 c = stencil%v(:, ijk)
980 cc(ijk, iv) = (cc(ijk, i_rhs) &
981 - c(2) * cc(i-1, j, k, iv) &
982 - c(3) * cc(i+1, j, k, iv) &
983 - c(4) * cc(i, j-1, k, iv) &
984 - c(5) * cc(i, j+1, k, iv) &
985 - c(6) * cc(i, j, k-1, iv) &
986 - c(7) * cc(i, j, k+1, iv)) / c(1)
987 end do
988 end do
989 end do
990 end if
991#endif
992
993 if (allocated(stencil%bc_correction)) then
994 cc(dtimes(1:nc), i_rhs) = cc(dtimes(1:nc), i_rhs) - &
995 stencil%bc_correction
996 end if
997 end associate
998 end subroutine stencil_gsrb_357
999
1000 !> Convert a variable stencil to constant one if possible
1001 subroutine af_stencil_try_constant(box, ix, abs_tol, success)
1002 type(box_t), intent(inout) :: box
1003 integer, intent(in) :: ix !< Stencil index
1004 real(dp), intent(in) :: abs_tol !< Absolute tolerance
1005 logical :: success !< Whether the stencil was converted
1006 integer :: ijk, nc, n_coeff
1007
1008 if (box%stencils(ix)%stype == stencil_sparse) &
1009 error stop "sparse not implemented"
1010 if (.not. allocated(box%stencils(ix)%v)) &
1011 error stop "No variable stencil present"
1012
1013 nc = box%n_cell
1014 success = .false.
1015
1016 ! Check if all coefficients are the same, otherwise return
1017 do kji_do(1, nc)
1018 if (any(abs(box%stencils(ix)%v(:, ijk) - &
1019 box%stencils(ix)%v(:, dtimes(1))) > abs_tol)) return
1020 end do; close_do
1021
1022 box%stencils(ix)%stype = stencil_constant
1023 n_coeff = size(box%stencils(ix)%v, 1)
1024 allocate(box%stencils(ix)%c(n_coeff))
1025 box%stencils(ix)%c = box%stencils(ix)%v(:, dtimes(1))
1026 deallocate(box%stencils(ix)%v)
1027 success = .true.
1028 end subroutine af_stencil_try_constant
1029
1030 !> Get the stencil for a box
1031 subroutine af_stencil_get_box(box, key, v)
1032 type(box_t), intent(inout) :: box !< Operate on this box
1033 integer, intent(in) :: key !< Stencil key
1034 !> Stencil coefficients
1035 real(dp), intent(inout) :: v(:, dtimes(:))
1036 integer :: i
1037
1038 i = af_stencil_index(box, key)
1039 if (i == af_stencil_none) error stop "Stencil not stored"
1040
1041 select case (box%stencils(i)%shape)
1042 case (af_stencil_357)
1043 call stencil_get_357(box, box%stencils(i), v)
1044 case default
1045 error stop "Unknown stencil"
1046 end select
1047 end subroutine af_stencil_get_box
1048
1049 !> Get the stencil for all cells in a box
1050 subroutine stencil_get_357(box, stencil, v)
1051 type(box_t), intent(inout) :: box !< Box
1052 type(stencil_t), intent(in) :: stencil !< Stencil
1053 !> Stencil coefficients
1054 real(dp), intent(inout) :: v(:, DTIMES(:))
1055#if NDIM == 2
1056 real(dp) :: c_cyl(size(v, 1)), rfac(2, box%n_cell)
1057#endif
1058 integer :: IJK, nc
1059
1060 nc = box%n_cell
1061
1062 if (size(v, 1) /= af_stencil_sizes(stencil%shape)) &
1063 error stop "Argument v has wrong size"
1064
1065 if (stencil%stype == stencil_constant) then
1066 do kji_do(1, nc)
1067 v(:, ijk) = stencil%c
1068 end do; close_do
1069 else
1070 v = stencil%v
1071 end if
1072
1073#if NDIM == 2
1074 if (stencil%cylindrical_gradient) then
1075 ! Correct for cylindrical coordinates, assuming the elements correspond
1076 ! to a gradient operation
1077 call af_cyl_flux_factors(box, rfac)
1078 do kji_do(1, nc)
1079 c_cyl(2:3) = rfac(1:2, i) * v(2:3, ijk)
1080 c_cyl(1) = v(1, ijk) - (c_cyl(2) - v(2, ijk)) &
1081 - (c_cyl(3) - v(3, ijk))
1082 c_cyl(4:) = v(4:, ijk)
1083 v(:, ijk) = c_cyl
1084 end do; close_do
1085 end if
1086#endif
1087 end subroutine stencil_get_357
1088
1089end module m_af_stencil
Subroutine for setting a stencil on a box.
This module contains functionality for dealing with numerical stencils.
Definition: m_af_stencil.f90:2
This module contains the basic types and constants that are used in the NDIM-dimensional version of A...
Definition: m_af_types.f90:3
Type which stores all the boxes and levels, as well as some information about the number of boxes,...
Definition: m_af_types.f90:326
The basic building block of afivo: a box with cell-centered and face centered data,...
Definition: m_af_types.f90:286
Type for storing a numerical stencil for a box.
Definition: m_af_types.f90:260