MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_ghostcells_update.t
Go to the documentation of this file.
1!> update ghost cells of all blocks including physical boundaries
3
4 implicit none
5
6 ! The number of interleaving sending buffers for ghost cells
7 integer, parameter :: npwbuf=2
8
9 integer :: ixm^l, ixcog^l, ixcom^l, ixcogs^l
10
11 ! index ranges to send (S) to sibling blocks, receive (R) from sibling blocks
12 integer, dimension(-1:1) :: ixs_srl_^l, ixr_srl_^l
13
14 ! index ranges of staggered variables to send (S) to sibling blocks, receive (R) from sibling blocks
15 integer, dimension(^ND,-1:1) :: ixs_srl_stg_^l, ixr_srl_stg_^l
16
17 ! index ranges to send (S) restricted (r) ghost cells to coarser blocks
18 integer, dimension(-1:1) :: ixs_r_^l
19
20 ! index ranges of staggered variables to send (S) restricted (r) ghost cells to coarser blocks
21 integer, dimension(^ND,-1:1) :: ixs_r_stg_^l
22
23 ! index ranges to receive restriced ghost cells from finer blocks
24 integer, dimension(0:3) :: ixr_r_^l
25
26 ! index ranges of staggered variables to receive restriced ghost cells from finer blocks
27 integer, dimension(^ND,0:3) :: ixr_r_stg_^l
28
29 ! send prolongated (p) ghost cells to finer blocks, receive prolongated from coarser blocks
30 integer, dimension(0:3) :: ixs_p_^l, ixr_p_^l
31
32 ! send prolongated (p) staggered ghost cells to finer blocks, receive prolongated from coarser blocks
33 integer, dimension(^ND,0:3) :: ixs_p_stg_^l, ixr_p_stg_^l
34
35 ! number of MPI receive-send pairs, srl: same refinement level; r: restrict; p: prolong
37
38 ! record index position of buffer arrays
40
41 ! count of times of send and receive
43
44 ! count of times of send and receive for cell center ghost cells
45 integer :: isend_c, irecv_c
46
47 ! tag of MPI send and recv
48 integer, private :: itag
49
50 ! total sizes = cell-center normal flux + stagger-grid flux of send and receive
51 integer, dimension(-1:1^D&) :: sizes_srl_send_total, sizes_srl_recv_total
52
53 ! sizes of buffer arrays for center-grid variable for siblings and restrict
54 integer, dimension(:), allocatable :: recvrequest_c_sr, sendrequest_c_sr
55 integer, dimension(:,:), allocatable :: recvstatus_c_sr, sendstatus_c_sr
56
57 ! sizes of buffer arrays for center-grid variable for prolongation
58 integer, dimension(:), allocatable :: recvrequest_c_p, sendrequest_c_p
59 integer, dimension(:,:), allocatable :: recvstatus_c_p, sendstatus_c_p
60
61 ! sizes of buffer arrays for stagger-grid variable
62 integer, dimension(^ND,-1:1^D&) :: sizes_srl_send_stg, sizes_srl_recv_stg
63
64 integer, dimension(:), allocatable :: recvrequest_srl, sendrequest_srl
65 integer, dimension(:,:), allocatable :: recvstatus_srl, sendstatus_srl
66
67 ! buffer arrays for send and receive of siblings, allocate in build_connectivity
68 double precision, dimension(:), allocatable :: recvbuffer_srl, sendbuffer_srl
69
70 integer, dimension(:), allocatable :: recvrequest_r, sendrequest_r
71 integer, dimension(:,:), allocatable :: recvstatus_r, sendstatus_r
72
73 ! buffer arrays for send and receive in restriction
74 double precision, dimension(:), allocatable :: recvbuffer_r, sendbuffer_r
75
76 integer, dimension(:), allocatable :: recvrequest_p, sendrequest_p
77 integer, dimension(:,:), allocatable :: recvstatus_p, sendstatus_p
78
79 ! buffer arrays for send and receive in prolongation
80 double precision, dimension(:), allocatable :: recvbuffer_p, sendbuffer_p
81
82 ! sizes to allocate buffer arrays for send and receive for restriction
83 integer, dimension(-1:1^D&) :: sizes_r_send_total
84 integer, dimension(0:3^D&) :: sizes_r_recv_total
85 integer, dimension(^ND,-1:1^D&) :: sizes_r_send_stg
86 integer, dimension(^ND,0:3^D&) :: sizes_r_recv_stg
87
88 ! sizes to allocate buffer arrays for send and receive for restriction
89 integer, dimension(0:3^D&) :: sizes_p_send_total, sizes_p_recv_total
90 integer, dimension(^ND,0:3^D&) :: sizes_p_send_stg, sizes_p_recv_stg
91
92 ! There are two variants, _f indicates that all flux variables are filled,
93 ! whereas _p means that part of the variables is filled
94 ! Furthermore _r_ stands for restrict, _p_ for prolongation.
95 integer, dimension(-1:1^D&), target :: type_send_srl_f, type_recv_srl_f
96 integer, dimension(-1:1^D&), target :: type_send_r_f
97 integer, dimension( 0:3^D&), target :: type_recv_r_f, type_send_p_f, type_recv_p_f
98 integer, dimension(-1:1^D&), target :: type_send_srl_p1, type_recv_srl_p1
99 integer, dimension(-1:1^D&), target :: type_send_r_p1
100 integer, dimension( 0:3^D&), target :: type_recv_r_p1, type_send_p_p1, type_recv_p_p1
101 integer, dimension(-1:1^D&), target :: type_send_srl_p2, type_recv_srl_p2
102 integer, dimension(-1:1^D&), target :: type_send_r_p2
103 integer, dimension( 0:3^D&), target :: type_recv_r_p2, type_send_p_p2, type_recv_p_p2
104 integer, dimension( :^D&), pointer :: type_send_srl, type_recv_srl, type_send_r
105 integer, dimension( :^D&), pointer :: type_recv_r, type_send_p, type_recv_p
106
107 ! A switch of update physical boundary or not
108 logical, public :: bcphys=.true.
109 ! Special buffer for pole copy
111 double precision, dimension(:^D&,:), allocatable :: w
112 end type wbuffer
113
114 abstract interface
115 subroutine update_eos_bc_sub(ixI^L, ixO^L, w, x)
117 integer, intent(in) :: ixI^L, ixO^L
118 double precision, intent(inout) :: w(ixI^S, nw)
119 double precision, intent(in) :: x(ixI^S, 1:ndim)
120 end subroutine update_eos_bc_sub
121 end interface
122
123 procedure(update_eos_bc_sub), pointer :: update_eos_4_bc => null()
124
125contains
126
127 subroutine init_bc()
129 use mod_physics, only: physics_type
130 use mod_comm_lib, only: mpistop
131
132 integer :: nghostcellsCo, interpolation_order
133 integer :: nx^D, nxCo^D, ixG^L, i^D, idir
134
135 ixg^l=ixg^ll;
136 ixm^l=ixg^l^lsubnghostcells;
137 ixcogmin^d=1;
138 ixcogmax^d=(ixghi^d-2*nghostcells)/2+2*nghostcells;
139 ixcogsmin^d=0;
140 ixcogsmax^d=ixcogmax^d;
141
142 ixcom^l=ixcog^l^lsubnghostcells;
143
144 nx^d=ixmmax^d-ixmmin^d+1;
145 nxco^d=nx^d/2;
146
147 if(ghost_copy) then
148 interpolation_order=1
149 else
150 interpolation_order=2
151 end if
152 nghostcellsco=int((nghostcells+1)/2)
153
154 if (nghostcellsco+interpolation_order-1>nghostcells) then
155 call mpistop("interpolation order for prolongation in getbc too high")
156 end if
157
158 ! i=-1 means subregion prepared for the neighbor at its minimum side
159 ! i= 1 means subregion prepared for the neighbor at its maximum side
160 {
161 ixs_srl_min^d(-1)=ixmmin^d
162 ixs_srl_min^d( 0)=ixmmin^d
163 ixs_srl_min^d( 1)=ixmmax^d+1-nghostcells
164 ixs_srl_max^d(-1)=ixmmin^d-1+nghostcells
165 ixs_srl_max^d( 0)=ixmmax^d
166 ixs_srl_max^d( 1)=ixmmax^d
167
168 ixr_srl_min^d(-1)=1
169 ixr_srl_min^d( 0)=ixmmin^d
170 ixr_srl_min^d( 1)=ixmmax^d+1
171 ixr_srl_max^d(-1)=nghostcells
172 ixr_srl_max^d( 0)=ixmmax^d
173 ixr_srl_max^d( 1)=ixgmax^d
174
175 ixs_r_min^d(-1)=ixcommin^d
176 ixs_r_min^d( 0)=ixcommin^d
177 ixs_r_min^d( 1)=ixcommax^d+1-nghostcells
178 ixs_r_max^d(-1)=ixcommin^d-1+nghostcells
179 ixs_r_max^d( 0)=ixcommax^d
180 ixs_r_max^d( 1)=ixcommax^d
181
182 ixr_r_min^d(0)=1
183 ixr_r_min^d(1)=ixmmin^d
184 ixr_r_min^d(2)=ixmmin^d+nxco^d
185 ixr_r_min^d(3)=ixmmax^d+1
186 ixr_r_max^d(0)=nghostcells
187 ixr_r_max^d(1)=ixmmin^d-1+nxco^d
188 ixr_r_max^d(2)=ixmmax^d
189 ixr_r_max^d(3)=ixgmax^d
190
191 ixs_p_min^d(0)=ixmmin^d-(interpolation_order-1)
192 ixs_p_min^d(1)=ixmmin^d-(interpolation_order-1)
193 ixs_p_min^d(2)=ixmmin^d+nxco^d-nghostcellsco-(interpolation_order-1)
194 ixs_p_min^d(3)=ixmmax^d+1-nghostcellsco-(interpolation_order-1)
195 ixs_p_max^d(0)=ixmmin^d-1+nghostcellsco+(interpolation_order-1)
196 ixs_p_max^d(1)=ixmmin^d-1+nxco^d+nghostcellsco+(interpolation_order-1)
197 ixs_p_max^d(2)=ixmmax^d+(interpolation_order-1)
198 ixs_p_max^d(3)=ixmmax^d+(interpolation_order-1)
199
200 ixr_p_min^d(0)=ixcommin^d-nghostcellsco-(interpolation_order-1)
201 ixr_p_min^d(1)=ixcommin^d-(interpolation_order-1)
202 ixr_p_min^d(2)=ixcommin^d-nghostcellsco-(interpolation_order-1)
203 ixr_p_min^d(3)=ixcommax^d+1-(interpolation_order-1)
204 ixr_p_max^d(0)=nghostcells+(interpolation_order-1)
205 ixr_p_max^d(1)=ixcommax^d+nghostcellsco+(interpolation_order-1)
206 ixr_p_max^d(2)=ixcommax^d+(interpolation_order-1)
207 ixr_p_max^d(3)=ixcommax^d+nghostcellsco+(interpolation_order-1)
208
209 \}
210
211 if (stagger_grid) then
212 allocate(pole_buf%ws(ixgs^t,nws))
213 ! Staggered (face-allocated) variables
214 do idir=1,ndim
215 { ixs_srl_stg_min^d(idir,-1)=ixmmin^d-kr(idir,^d)
216 ixs_srl_stg_max^d(idir,-1)=ixmmin^d-1+nghostcells
217 ixs_srl_stg_min^d(idir,0) =ixmmin^d-kr(idir,^d)
218 ixs_srl_stg_max^d(idir,0) =ixmmax^d
219 ixs_srl_stg_min^d(idir,1) =ixmmax^d-nghostcells+1-kr(idir,^d)
220 ixs_srl_stg_max^d(idir,1) =ixmmax^d
221
222 ixr_srl_stg_min^d(idir,-1)=1-kr(idir,^d)
223 ixr_srl_stg_max^d(idir,-1)=nghostcells
224 ixr_srl_stg_min^d(idir,0) =ixmmin^d-kr(idir,^d)
225 ixr_srl_stg_max^d(idir,0) =ixmmax^d
226 ixr_srl_stg_min^d(idir,1) =ixmmax^d+1-kr(idir,^d)
227 ixr_srl_stg_max^d(idir,1) =ixgmax^d
228
229 ixs_r_stg_min^d(idir,-1)=ixcommin^d-kr(idir,^d)
230 ixs_r_stg_max^d(idir,-1)=ixcommin^d-1+nghostcells
231 ixs_r_stg_min^d(idir,0) =ixcommin^d-kr(idir,^d)
232 ixs_r_stg_max^d(idir,0) =ixcommax^d
233 ixs_r_stg_min^d(idir,1) =ixcommax^d+1-nghostcells-kr(idir,^d)
234 ixs_r_stg_max^d(idir,1) =ixcommax^d
235
236 ixr_r_stg_min^d(idir,0)=1-kr(idir,^d)
237 ixr_r_stg_max^d(idir,0)=nghostcells
238 ixr_r_stg_min^d(idir,1)=ixmmin^d-kr(idir,^d)
239 ixr_r_stg_max^d(idir,1)=ixmmin^d-1+nxco^d
240 ixr_r_stg_min^d(idir,2)=ixmmin^d+nxco^d-kr(idir,^d)
241 ixr_r_stg_max^d(idir,2)=ixmmax^d
242 ixr_r_stg_min^d(idir,3)=ixmmax^d+1-kr(idir,^d)
243 ixr_r_stg_max^d(idir,3)=ixgmax^d
244 \}
245 {if (idir==^d) then
246 ! Parallel components
247 {
248 ixs_p_stg_min^d(idir,0)=ixmmin^d-1 ! -1 to make redundant
249 ixs_p_stg_max^d(idir,0)=ixmmin^d-1+nghostcellsco
250 ixs_p_stg_min^d(idir,1)=ixmmin^d-1 ! -1 to make redundant
251 ixs_p_stg_max^d(idir,1)=ixmmin^d-1+nxco^d+nghostcellsco
252 ixs_p_stg_min^d(idir,2)=ixmmax^d-nxco^d-nghostcellsco
253 ixs_p_stg_max^d(idir,2)=ixmmax^d
254 ixs_p_stg_min^d(idir,3)=ixmmax^d-nghostcellsco
255 ixs_p_stg_max^d(idir,3)=ixmmax^d
256
257 ixr_p_stg_min^d(idir,0)=ixcommin^d-1-nghostcellsco
258 ixr_p_stg_max^d(idir,0)=ixcommin^d-1
259 ixr_p_stg_min^d(idir,1)=ixcommin^d-1 ! -1 to make redundant
260 ixr_p_stg_max^d(idir,1)=ixcommax^d+nghostcellsco
261 ixr_p_stg_min^d(idir,2)=ixcommin^d-1-nghostcellsco
262 ixr_p_stg_max^d(idir,2)=ixcommax^d
263 ixr_p_stg_min^d(idir,3)=ixcommax^d+1-1 ! -1 to make redundant
264 ixr_p_stg_max^d(idir,3)=ixcommax^d+nghostcellsco
265 \}
266 else
267 {
268 ! Perpendicular component
269 ixs_p_stg_min^d(idir,0)=ixmmin^d
270 ixs_p_stg_max^d(idir,0)=ixmmin^d-1+nghostcellsco+(interpolation_order-1)
271 ixs_p_stg_min^d(idir,1)=ixmmin^d
272 ixs_p_stg_max^d(idir,1)=ixmmin^d-1+nxco^d+nghostcellsco+(interpolation_order-1)
273 ixs_p_stg_min^d(idir,2)=ixmmax^d+1-nxco^d-nghostcellsco-(interpolation_order-1)
274 ixs_p_stg_max^d(idir,2)=ixmmax^d
275 ixs_p_stg_min^d(idir,3)=ixmmax^d+1-nghostcellsco-(interpolation_order-1)
276 ixs_p_stg_max^d(idir,3)=ixmmax^d
277
278 ixr_p_stg_min^d(idir,0)=ixcommin^d-nghostcellsco-(interpolation_order-1)
279 ixr_p_stg_max^d(idir,0)=ixcommin^d-1
280 ixr_p_stg_min^d(idir,1)=ixcommin^d
281 ixr_p_stg_max^d(idir,1)=ixcommax^d+nghostcellsco+(interpolation_order-1)
282 ixr_p_stg_min^d(idir,2)=ixcommin^d-nghostcellsco-(interpolation_order-1)
283 ixr_p_stg_max^d(idir,2)=ixcommax^d
284 ixr_p_stg_min^d(idir,3)=ixcommax^d+1
285 ixr_p_stg_max^d(idir,3)=ixcommax^d+nghostcellsco+(interpolation_order-1)
286 \}
287 end if
288 }
289 end do
290 ! calculate sizes for buffer arrays for siblings
291 {do i^db=-1,1\}
292 ! Staggered (face-allocated) variables
293 do idir=1,ndim
294 sizes_srl_send_stg(idir,i^d)={(ixs_srl_stg_max^d(idir,i^d)-ixs_srl_stg_min^d(idir,i^d)+1)|*}
295 sizes_srl_recv_stg(idir,i^d)={(ixr_srl_stg_max^d(idir,i^d)-ixr_srl_stg_min^d(idir,i^d)+1)|*}
296 sizes_r_send_stg(idir,i^d)={(ixs_r_stg_max^d(idir,i^d)-ixs_r_stg_min^d(idir,i^d)+1)|*}
297 end do
300 sizes_r_send_total(i^d)=sum(sizes_r_send_stg(:,i^d))
301 {end do\}
302
303 {do i^db=0,3\}
304 ! Staggered (face-allocated) variables
305 do idir=1,ndim
306 sizes_r_recv_stg(idir,i^d)={(ixr_r_stg_max^d(idir,i^d)-ixr_r_stg_min^d(idir,i^d)+1)|*}
307 sizes_p_send_stg(idir,i^d)={(ixs_p_stg_max^d(idir,i^d)-ixs_p_stg_min^d(idir,i^d)+1)|*}
308 sizes_p_recv_stg(idir,i^d)={(ixr_p_stg_max^d(idir,i^d)-ixr_p_stg_min^d(idir,i^d)+1)|*}
309 end do
310 sizes_r_recv_total(i^d)=sum(sizes_r_recv_stg(:,i^d))
311 sizes_p_send_total(i^d)=sum(sizes_p_send_stg(:,i^d))
312 sizes_p_recv_total(i^d)=sum(sizes_p_recv_stg(:,i^d))
313 {end do\}
314 end if
315
316 end subroutine init_bc
317
318 subroutine create_bc_mpi_datatype(nwstart,nwbc)
320
321 integer, intent(in) :: nwstart, nwbc
322 integer :: i^D, ic^D, inc^D
323
324 {do i^db=-1,1\}
325 if(i^d==0|.and.) cycle
326 call get_bc_comm_type(type_send_srl(i^d),ixs_srl_^l(i^d),ixg^ll,nwstart,nwbc)
327 call get_bc_comm_type(type_recv_srl(i^d),ixr_srl_^l(i^d),ixg^ll,nwstart,nwbc)
328 call get_bc_comm_type(type_send_r(i^d), ixs_r_^l(i^d),ixcog^l,nwstart,nwbc)
329 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
330 inc^db=2*i^db+ic^db\}
331 call get_bc_comm_type(type_recv_r(inc^d),ixr_r_^l(inc^d), ixg^ll,nwstart,nwbc)
332 call get_bc_comm_type(type_send_p(inc^d),ixs_p_^l(inc^d), ixg^ll,nwstart,nwbc)
333 call get_bc_comm_type(type_recv_p(inc^d),ixr_p_^l(inc^d),ixcog^l,nwstart,nwbc)
334 {end do\}
335 {end do\}
336
337 end subroutine create_bc_mpi_datatype
338
339 subroutine get_bc_comm_type(comm_type,ix^L,ixG^L,nwstart,nwbc)
341
342 integer, intent(inout) :: comm_type
343 integer, intent(in) :: ix^L, ixG^L, nwstart, nwbc
344
345 integer, dimension(ndim+1) :: fullsize, subsize, start
346
347 ^d&fullsize(^d)=ixgmax^d;
348 fullsize(ndim+1)=nw
349 ^d&subsize(^d)=ixmax^d-ixmin^d+1;
350 subsize(ndim+1)=nwbc
351 ^d&start(^d)=ixmin^d-1;
352 start(ndim+1)=nwstart-1
353
354 call mpi_type_create_subarray(ndim+1,fullsize,subsize,start,mpi_order_fortran, &
355 mpi_double_precision,comm_type,ierrmpi)
356 call mpi_type_commit(comm_type,ierrmpi)
357
358 end subroutine get_bc_comm_type
359
360 !> do update ghost cells of all blocks including physical boundaries
361 subroutine getbc(time,qdt,psb,nwstart,nwbc)
363 use mod_physics
365 use mod_coarsen, only: coarsen_grid
367 use mod_comm_lib, only: mpistop
368
369 double precision, intent(in) :: time, qdt
370 type(state), target :: psb(max_blocks)
371 integer, intent(in) :: nwstart ! Fill from nwstart
372 integer, intent(in) :: nwbc ! Number of variables to fill
373
374 double precision :: time_bcin
375 integer :: nwhead, nwtail
376 integer :: iigrid, igrid, isizes, i^D
377 integer :: isend_buf(npwbuf), ipwbuf, nghostcellsco
378 ! index pointer for buffer arrays as a start for a segment
379 integer :: ibuf_start, ibuf_next
380 ! shapes of reshape
381 integer, dimension(1) :: shapes
382 type(wbuffer) :: pwbuf(npwbuf)
383
384 time_bcin=mpi_wtime()
385
386 nwhead=nwstart
387 nwtail=nwstart+nwbc-1
388
389 ! fill internal physical boundary
390 if (internalboundary) then
391 call getintbc(time,qdt,ixg^ll)
392 end if
393
394 ! prepare coarse values to send to coarser neighbors
395 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
396 do iigrid=1,igridstail; igrid=igrids(iigrid);
397 if(any(neighbor_type(:^d&,igrid)==neighbor_coarse)) then
398 call coarsen_grid(psb(igrid),ixg^ll,ixm^l,psc(igrid),ixcog^l,ixcom^l)
399 end if
400 end do
401 !$OMP END PARALLEL DO
402
403 ! default : no singular axis
404 irecv_c=0
405 isend_c=0
406 isend_buf=0
407 ipwbuf=1
408
409 if(stagger_grid) then
416 irecv_srl=0
417 irecv_r=0
418 irecv_p=0
419 isend_srl=0
420 isend_r=0
421 isend_p=0
422 end if
423
424 !$OMP PARALLEL SECTIONS PRIVATE(iigrid,igrid,i^D)
425 !$OMP SECTION
426 ! MPI receive ghost-cell values from sibling blocks and finer neighbors in different processors
427 do iigrid=1,igridstail; igrid=igrids(iigrid);
428 {do i^db=-1,1\}
429 if (skip_direction([ i^d ])) cycle
430 select case (neighbor_type(i^d,igrid))
431 case (neighbor_sibling)
432 call bc_recv_srl(igrid,i^d)
433 case (neighbor_fine)
434 call bc_recv_restrict(igrid,i^d)
435 end select
436 {end do\}
437 end do
438
439 ! MPI send ghost-cell values to sibling blocks and coarser neighbors in different processors
440 do iigrid=1,igridstail; igrid=igrids(iigrid);
441 {do i^db=-1,1\}
442 if(skip_direction([ i^d ])) cycle
443 select case (neighbor_type(i^d,igrid))
444 case (neighbor_sibling)
445 call bc_send_srl(igrid,i^d)
446 case (neighbor_coarse)
447 call bc_send_restrict(igrid,i^d)
448 end select
449 {end do\}
450 end do
451
452 call mpi_waitall(irecv_c,recvrequest_c_sr,recvstatus_c_sr,ierrmpi)
453 call mpi_waitall(isend_c,sendrequest_c_sr,sendstatus_c_sr,ierrmpi)
454 if(stagger_grid) then
455 call mpi_waitall(nrecv_bc_srl,recvrequest_srl,recvstatus_srl,ierrmpi)
456 call mpi_waitall(nsend_bc_srl,sendrequest_srl,sendstatus_srl,ierrmpi)
457 call mpi_waitall(nrecv_bc_r,recvrequest_r,recvstatus_r,ierrmpi)
458 call mpi_waitall(nsend_bc_r,sendrequest_r,sendstatus_r,ierrmpi)
459 end if
460
461 do ipwbuf=1,npwbuf
462 if (isend_buf(ipwbuf)/=0) deallocate(pwbuf(ipwbuf)%w)
463 end do
464 !$OMP SECTION
465 ! fill ghost-cell values of sibling blocks and coarser neighbors in the same processor
466 do iigrid=1,igridstail; igrid=igrids(iigrid);
467 {do i^db=-1,1\}
468 if(skip_direction([ i^d ])) cycle
469 select case (neighbor_type(i^d,igrid))
470 case(neighbor_sibling)
471 call bc_fill_srl(igrid,i^d)
472 case(neighbor_coarse)
473 call bc_fill_restrict(igrid,i^d)
474 end select
475 {end do\}
476 end do
477 !$OMP END PARALLEL SECTIONS
478
479 if(stagger_grid) then
480 ! unpack the received data from sibling blocks and finer neighbors to fill ghost-cell staggered values
483 do iigrid=1,igridstail; igrid=igrids(iigrid);
484 {do i^db=-1,1\}
485 if (skip_direction([ i^d ])) cycle
486 select case (neighbor_type(i^d,igrid))
487 case (neighbor_sibling)
488 call bc_fill_srl_stg(igrid,i^d)
489 case (neighbor_fine)
490 call bc_fill_restrict_stg(igrid,i^d)
491 end select
492 {end do\}
493 end do
494 end if
495
496 irecv_c=0
497 isend_c=0
498 isend_buf=0
499 ipwbuf=1
500
501 !$OMP PARALLEL SECTIONS PRIVATE(iigrid,igrid,i^D)
502 !$OMP SECTION
503 ! MPI receive ghost-cell values from coarser neighbors in different processors
504 do iigrid=1,igridstail; igrid=igrids(iigrid);
505 {do i^db=-1,1\}
506 if (skip_direction([ i^d ])) cycle
507 if (neighbor_type(i^d,igrid)==neighbor_coarse) call bc_recv_prolong(igrid,i^d)
508 {end do\}
509 end do
510 ! MPI send ghost-cell values to finer neighbors in different processors
511 do iigrid=1,igridstail; igrid=igrids(iigrid);
512 {do i^db=-1,1\}
513 if (skip_direction([ i^d ])) cycle
514 if (neighbor_type(i^d,igrid)==neighbor_fine) call bc_send_prolong(igrid,i^d)
515 {end do\}
516 end do
517
518 call mpi_waitall(irecv_c,recvrequest_c_p,recvstatus_c_p,ierrmpi)
519 call mpi_waitall(isend_c,sendrequest_c_p,sendstatus_c_p,ierrmpi)
520
521 if(stagger_grid) then
522 call mpi_waitall(nrecv_bc_p,recvrequest_p,recvstatus_p,ierrmpi)
523 call mpi_waitall(nsend_bc_p,sendrequest_p,sendstatus_p,ierrmpi)
524 end if
525
526 do ipwbuf=1,npwbuf
527 if (isend_buf(ipwbuf)/=0) deallocate(pwbuf(ipwbuf)%w)
528 end do
529
530 !$OMP SECTION
531 ! fill coarse ghost-cell values of finer neighbors in the same processor
532 do iigrid=1,igridstail; igrid=igrids(iigrid);
533 {do i^db=-1,1\}
534 if (skip_direction([ i^d ])) cycle
535 if (neighbor_type(i^d,igrid)==neighbor_fine) call bc_fill_prolong(igrid,i^d)
536 {end do\}
537 end do
538 !$OMP END PARALLEL SECTIONS
539
540 if(stagger_grid) then
541 ! fill coarser representative ghost cells after receipt
543 do iigrid=1,igridstail; igrid=igrids(iigrid);
544 {do i^db=-1,1\}
545 if (skip_direction([ i^d ])) cycle
546 if(neighbor_type(i^d,igrid)==neighbor_coarse) call bc_fill_prolong_stg(igrid,i^d)
547 {end do\}
548 end do
549 end if
550 ! do prolongation on the ghost-cell values based on the received coarse values from coarser neighbors
551 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
552 do iigrid=1,igridstail; igrid=igrids(iigrid);
553 call gc_prolong(igrid)
554 end do
555 !$OMP END PARALLEL DO
556
557 ! fill physical boundary ghost cells after internal ghost-cell values exchange
558 if(bcphys) then
559 if(associated(usr_prepare_boundary)) then
560 call usr_prepare_boundary(time, qdt)
561 endif
562 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
563 do iigrid=1,igridstail; igrid=igrids(iigrid);
564 if(.not.phyboundblock(igrid)) cycle
565 call fill_boundary_after_gc(igrid)
566 end do
567 !$OMP END PARALLEL DO
568 end if
569
570 ! modify normal component of magnetic field to fix divB=0
571 if(bcphys.and.associated(phys_boundary_adjust)) then
572 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
573 do iigrid=1,igridstail; igrid=igrids(iigrid);
574 if(.not.phyboundblock(igrid)) cycle
575 call phys_boundary_adjust(igrid,psb)
576 end do
577 !$OMP END PARALLEL DO
578 end if
579
580 time_bc=time_bc+(mpi_wtime()-time_bcin)
581
582 contains
583
584 logical function skip_direction(dir)
585 integer, intent(in) :: dir(^nd)
586
587 if (all(dir == 0)) then
588 skip_direction = .true.
589 else
590 skip_direction = .false.
591 end if
592 end function skip_direction
593
594 !> Physical boundary conditions
595 subroutine fill_boundary_after_gc(igrid)
596
597 integer, intent(in) :: igrid
598
599 integer :: idims,iside,i^d,k^l,ixb^l
600
601 block=>psb(igrid)
602 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
603 do idims=1,ndim
604 ! to avoid using as yet unknown corner info in more than 1D, we
605 ! fill only interior mesh ranges of the ghost cell ranges at first,
606 ! and progressively enlarge the ranges to include corners later
607 kmin1=0; kmax1=0;
608 {^iftwod
609 kmin2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0,-1,igrid)==1)
610 kmax2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0, 1,igrid)==1)}
611 {^ifthreed
612 kmin2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0,-1,0,igrid)==1)
613 kmax2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0, 1,0,igrid)==1)
614 kmin3=merge(1, 0, idims .lt. 3 .and. neighbor_type(0,0,-1,igrid)==1)
615 kmax3=merge(1, 0, idims .lt. 3 .and. neighbor_type(0,0, 1,igrid)==1)}
616 ixbmin^d=ixglo^d+kmin^d*nghostcells;
617 ixbmax^d=ixghi^d-kmax^d*nghostcells;
618 do iside=1,2
619 i^d=kr(^d,idims)*(2*iside-3);
620 if (aperiodb(idims)) then
621 if (neighbor_type(i^d,igrid) /= neighbor_boundary .and. &
622 .not. psb(igrid)%is_physical_boundary(2*idims-2+iside)) cycle
623 else
624 if (neighbor_type(i^d,igrid) /= neighbor_boundary) cycle
625 end if
626 !> Refresh the EoS-derived ghost fields before extrapolation; the hook
627 !> is set (in amrvac.t) only when the EoS needs it, e.g. LTE.
628 if (associated(update_eos_4_bc)) &
629 call update_eos_4_bc(ixg^ll,ixm^ll,psb(igrid)%w,psb(igrid)%x)
630 call bc_phys(iside,idims,time,qdt,psb(igrid),ixg^ll,ixb^l)
631 end do
632 end do
633
634 end subroutine fill_boundary_after_gc
635
636 !> MPI receive from sibling at same refinement level
637 subroutine bc_recv_srl(igrid,i^D)
638 integer, intent(in) :: igrid,i^d
639
640 integer :: ipe_neighbor
641
642 ipe_neighbor=neighbor(2,i^d,igrid)
643 if (ipe_neighbor/=mype) then
645 itag=(3**^nd+4**^nd)*(igrid-1)+{(i^d+1)*3**(^d-1)+}
646 call mpi_irecv(psb(igrid)%w,1,type_recv_srl(i^d), &
647 ipe_neighbor,itag,icomm,recvrequest_c_sr(irecv_c),ierrmpi)
648 if(stagger_grid) then
650 call mpi_irecv(recvbuffer_srl(ibuf_recv_srl),sizes_srl_recv_total(i^d),mpi_double_precision, &
651 ipe_neighbor,itag,icomm,recvrequest_srl(irecv_srl),ierrmpi)
653 end if
654 end if
655
656 end subroutine bc_recv_srl
657
658 !> MPI receive from fine neighbor
659 subroutine bc_recv_restrict(igrid,i^D)
660 integer, intent(in) :: igrid,i^d
661
662 integer :: ic^d,inc^d,ipe_neighbor
663
664 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
665 inc^db=2*i^db+ic^db\}
666 ipe_neighbor=neighbor_child(2,inc^d,igrid)
667 if (ipe_neighbor/=mype) then
669 itag=(3**^nd+4**^nd)*(igrid-1)+3**^nd+{inc^d*4**(^d-1)+}
670 call mpi_irecv(psb(igrid)%w,1,type_recv_r(inc^d), &
671 ipe_neighbor,itag,icomm,recvrequest_c_sr(irecv_c),ierrmpi)
672 if(stagger_grid) then
674 call mpi_irecv(recvbuffer_r(ibuf_recv_r),sizes_r_recv_total(inc^d), &
675 mpi_double_precision,ipe_neighbor,itag, &
676 icomm,recvrequest_r(irecv_r),ierrmpi)
678 end if
679 end if
680 {end do\}
681
682 end subroutine bc_recv_restrict
683
684 !> MPI send to sibling at same refinement level
685 subroutine bc_send_srl(igrid,i^D)
686 integer, intent(in) :: igrid,i^d
687
688 integer :: n_i^d,ipole,idir,ineighbor,ipe_neighbor,ixs^l
689
690 ipe_neighbor=neighbor(2,i^d,igrid)
691 if(ipe_neighbor/=mype) then
692 ineighbor=neighbor(1,i^d,igrid)
693 ipole=neighbor_pole(i^d,igrid)
694 if(ipole==0) then
695 n_i^d=-i^d;
697 itag=(3**^nd+4**^nd)*(ineighbor-1)+{(n_i^d+1)*3**(^d-1)+}
698 call mpi_isend(psb(igrid)%w,1,type_send_srl(i^d), &
699 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
700 if(stagger_grid) then
701 ibuf_start=ibuf_send_srl
702 do idir=1,ndim
703 ixs^l=ixs_srl_stg_^l(idir,i^d);
704 ibuf_next=ibuf_start+sizes_srl_send_stg(idir,i^d)
705 shapes=(/sizes_srl_send_stg(idir,i^d)/)
706 sendbuffer_srl(ibuf_start:ibuf_next-1)=&
707 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
708 ibuf_start=ibuf_next
709 end do
712 mpi_double_precision, ipe_neighbor,itag,icomm,sendrequest_srl(isend_srl),ierrmpi)
713 ibuf_send_srl=ibuf_next
714 end if
715 else
716 ixs^l=ixs_srl_^l(i^d);
717 select case (ipole)
718 {case (^d)
719 n_i^d=i^d^d%n_i^dd=-i^dd;\}
720 end select
721 if (isend_buf(ipwbuf)/=0) then
722 call mpi_wait(sendrequest_c_sr(isend_buf(ipwbuf)), &
723 sendstatus_c_sr(:,isend_buf(ipwbuf)),ierrmpi)
724 deallocate(pwbuf(ipwbuf)%w)
725 end if
726 allocate(pwbuf(ipwbuf)%w(ixs^s,nwhead:nwtail))
727 call pole_buffer(pwbuf(ipwbuf)%w,ixs^l,ixs^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
729 isend_buf(ipwbuf)=isend_c
730 itag=(3**^nd+4**^nd)*(ineighbor-1)+{(n_i^d+1)*3**(^d-1)+}
731 isizes={(ixsmax^d-ixsmin^d+1)*}*nwbc
732 call mpi_isend(pwbuf(ipwbuf)%w,isizes,mpi_double_precision, &
733 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
734 ipwbuf=1+modulo(ipwbuf,npwbuf)
735 if(stagger_grid) then
736 ibuf_start=ibuf_send_srl
737 do idir=1,ndim
738 ixs^l=ixs_srl_stg_^l(idir,i^d);
739 ibuf_next=ibuf_start+sizes_srl_send_stg(idir,i^d)
740 shapes=(/sizes_srl_send_stg(idir,i^d)/)
741 sendbuffer_srl(ibuf_start:ibuf_next-1)=&
742 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
743 ibuf_start=ibuf_next
744 end do
747 mpi_double_precision, ipe_neighbor,itag,icomm,sendrequest_srl(isend_srl),ierrmpi)
748 ibuf_send_srl=ibuf_next
749 end if
750 end if
751 end if
752
753 end subroutine bc_send_srl
754
755 !> MPI send to coarser neighbor's ghost cells
756 subroutine bc_send_restrict(igrid,i^D)
757 integer, intent(in) :: igrid,i^d
758
759 integer :: ic^d,n_inc^d,ipole,idir,ineighbor,ipe_neighbor,ixs^l
760
761 ipe_neighbor=neighbor(2,i^d,igrid)
762 if(ipe_neighbor/=mype) then
763 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
764 if({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
765 ineighbor=neighbor(1,i^d,igrid)
766 ipole=neighbor_pole(i^d,igrid)
767 if(ipole==0) then
768 n_inc^d=-2*i^d+ic^d;
770 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
771 call mpi_isend(psc(igrid)%w,1,type_send_r(i^d), &
772 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
773 if(stagger_grid) then
774 ibuf_start=ibuf_send_r
775 do idir=1,ndim
776 ixs^l=ixs_r_stg_^l(idir,i^d);
777 ibuf_next=ibuf_start+sizes_r_send_stg(idir,i^d)
778 shapes=(/sizes_r_send_stg(idir,i^d)/)
779 sendbuffer_r(ibuf_start:ibuf_next-1)=&
780 reshape(psc(igrid)%ws(ixs^s,idir),shapes)
781 ibuf_start=ibuf_next
782 end do
784 call mpi_isend(sendbuffer_r(ibuf_send_r),sizes_r_send_total(i^d),&
785 mpi_double_precision,ipe_neighbor,itag, &
786 icomm,sendrequest_r(isend_r),ierrmpi)
787 ibuf_send_r=ibuf_next
788 end if
789 else
790 ixs^l=ixs_r_^l(i^d);
791 select case (ipole)
792 {case (^d)
793 n_inc^d=2*i^d+(3-ic^d)^d%n_inc^dd=-2*i^dd+ic^dd;\}
794 end select
795 if(isend_buf(ipwbuf)/=0) then
796 call mpi_wait(sendrequest_c_sr(isend_buf(ipwbuf)), &
797 sendstatus_c_sr(:,isend_buf(ipwbuf)),ierrmpi)
798 deallocate(pwbuf(ipwbuf)%w)
799 end if
800 allocate(pwbuf(ipwbuf)%w(ixs^s,nwhead:nwtail))
801 call pole_buffer(pwbuf(ipwbuf)%w,ixs^l,ixs^l,psc(igrid)%w,ixcog^l,ixs^l,ipole)
803 isend_buf(ipwbuf)=isend_c
804 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
805 isizes={(ixsmax^d-ixsmin^d+1)*}*nwbc
806 call mpi_isend(pwbuf(ipwbuf)%w,isizes,mpi_double_precision, &
807 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
808 ipwbuf=1+modulo(ipwbuf,npwbuf)
809 if(stagger_grid) then
810 ibuf_start=ibuf_send_r
811 do idir=1,ndim
812 ixs^l=ixs_r_stg_^l(idir,i^d);
813 ibuf_next=ibuf_start+sizes_r_send_stg(idir,i^d)
814 shapes=(/sizes_r_send_stg(idir,i^d)/)
815 sendbuffer_r(ibuf_start:ibuf_next-1)=&
816 reshape(psc(igrid)%ws(ixs^s,idir),shapes)
817 ibuf_start=ibuf_next
818 end do
820 call mpi_isend(sendbuffer_r(ibuf_send_r),sizes_r_send_total(i^d),&
821 mpi_double_precision,ipe_neighbor,itag, &
822 icomm,sendrequest_r(isend_r),ierrmpi)
823 ibuf_send_r=ibuf_next
824 end if
825 end if
826 end if
827
828 end subroutine bc_send_restrict
829
830 !> fill same-level neighbor's ghost cells in the same processor
831 subroutine bc_fill_srl(igrid,i^D)
832 integer, intent(in) :: igrid,i^d
833
834 integer :: ineighbor,ipe_neighbor,ipole,ixs^l,ixr^l,n_i^d,idir
835
836 ipe_neighbor=neighbor(2,i^d,igrid)
837 if(ipe_neighbor==mype) then
838 ineighbor=neighbor(1,i^d,igrid)
839 ipole=neighbor_pole(i^d,igrid)
840 if(ipole==0) then
841 n_i^d=-i^d;
842 ixs^l=ixs_srl_^l(i^d);
843 ixr^l=ixr_srl_^l(n_i^d);
844 psb(ineighbor)%w(ixr^s,nwhead:nwtail)=&
845 psb(igrid)%w(ixs^s,nwhead:nwtail)
846 if(stagger_grid) then
847 do idir=1,ndim
848 ixs^l=ixs_srl_stg_^l(idir,i^d);
849 ixr^l=ixr_srl_stg_^l(idir,n_i^d);
850 psb(ineighbor)%ws(ixr^s,idir)=psb(igrid)%ws(ixs^s,idir)
851 end do
852 end if
853 else
854 ixs^l=ixs_srl_^l(i^d);
855 select case (ipole)
856 {case (^d)
857 n_i^d=i^d^d%n_i^dd=-i^dd;\}
858 end select
859 ixr^l=ixr_srl_^l(n_i^d);
860 call pole_copy(psb(ineighbor)%w,ixg^ll,ixr^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
861 if(stagger_grid) then
862 do idir=1,ndim
863 ixs^l=ixs_srl_stg_^l(idir,i^d);
864 ixr^l=ixr_srl_stg_^l(idir,n_i^d);
865 call pole_copy_stg(psb(ineighbor)%ws,ixgs^ll,ixr^l,psb(igrid)%ws,ixgs^ll,ixs^l,idir,ipole)
866 end do
867 end if
868 end if
869 end if
870
871 end subroutine bc_fill_srl
872
873 !> fill coarser neighbor's ghost cells in the same processor
874 subroutine bc_fill_restrict(igrid,i^D)
875 integer, intent(in) :: igrid,i^d
876
877 integer :: ic^d,n_inc^d,ixs^l,ixr^l,ipe_neighbor,ineighbor,ipole,idir
878
879 ipe_neighbor=neighbor(2,i^d,igrid)
880 if(ipe_neighbor==mype) then
881 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
882 if({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
883 ineighbor=neighbor(1,i^d,igrid)
884 ipole=neighbor_pole(i^d,igrid)
885 if(ipole==0) then
886 n_inc^d=-2*i^d+ic^d;
887 ixs^l=ixs_r_^l(i^d);
888 ixr^l=ixr_r_^l(n_inc^d);
889 psb(ineighbor)%w(ixr^s,nwhead:nwtail)=&
890 psc(igrid)%w(ixs^s,nwhead:nwtail)
891 if(stagger_grid) then
892 do idir=1,ndim
893 ixs^l=ixs_r_stg_^l(idir,i^d);
894 ixr^l=ixr_r_stg_^l(idir,n_inc^d);
895 psb(ineighbor)%ws(ixr^s,idir)=psc(igrid)%ws(ixs^s,idir)
896 end do
897 end if
898 else
899 ixs^l=ixs_r_^l(i^d);
900 select case (ipole)
901 {case (^d)
902 n_inc^d=2*i^d+(3-ic^d)^d%n_inc^dd=-2*i^dd+ic^dd;\}
903 end select
904 ixr^l=ixr_r_^l(n_inc^d);
905 call pole_copy(psb(ineighbor)%w,ixg^ll,ixr^l,psc(igrid)%w,ixcog^l,ixs^l,ipole)
906 if(stagger_grid) then
907 do idir=1,ndim
908 ixs^l=ixs_r_stg_^l(idir,i^d);
909 ixr^l=ixr_r_stg_^l(idir,n_inc^d);
910 !! Fill ghost cells
911 call pole_copy_stg(psb(ineighbor)%ws,ixgs^ll,ixr^l,psc(igrid)%ws,ixcogs^l,ixs^l,idir,ipole)
912 end do
913 end if
914 end if
915 end if
916
917 end subroutine bc_fill_restrict
918
919 !> fill siblings ghost cells with received data
920 subroutine bc_fill_srl_stg(igrid,i^D)
921 integer, intent(in) :: igrid,i^d
922
923 integer :: ixs^l,ixr^l,n_i^d,idir,ineighbor,ipe_neighbor,ipole
924
925 ipe_neighbor=neighbor(2,i^d,igrid)
926 if(ipe_neighbor/=mype) then
927 ineighbor=neighbor(1,i^d,igrid)
928 ipole=neighbor_pole(i^d,igrid)
929
930 !! Now the special treatment of the pole is done here, at the receive step
931 if (ipole==0) then
932 ixr^l=ixr_srl_^l(i^d);
933 !! Unpack the buffer and fill the ghost cells
934 n_i^d=-i^d;
935 do idir=1,ndim
936 ixs^l=ixs_srl_stg_^l(idir,n_i^d);
937 ixr^l=ixr_srl_stg_^l(idir,i^d);
938 ibuf_next=ibuf_recv_srl+sizes_srl_recv_stg(idir,i^d)
939 psb(igrid)%ws(ixr^s,idir)=reshape(source=recvbuffer_srl(ibuf_recv_srl:ibuf_next-1),&
940 shape=shape(psb(igrid)%ws(ixs^s,idir)))
941 ibuf_recv_srl=ibuf_next
942 end do
943 else ! There is a pole
944 select case (ipole)
945 {case (^d)
946 n_i^d=i^d^d%n_i^dd=-i^dd;\}
947 end select
948 pole_buf%ws=zero
949 do idir=1,ndim
950 ixr^l=ixr_srl_stg_^l(idir,i^d);
951 ixs^l=ixs_srl_stg_^l(idir,n_i^d);
952 ibuf_next=ibuf_recv_srl+sizes_srl_recv_stg(idir,i^d)
953 pole_buf%ws(ixs^s,idir)=reshape(source=recvbuffer_srl(ibuf_recv_srl:ibuf_next-1),&
954 shape=shape(psb(igrid)%ws(ixs^s,idir)))
955 ibuf_recv_srl=ibuf_next
956 call pole_copy_stg(psb(igrid)%ws,ixgs^ll,ixr^l,pole_buf%ws,ixgs^ll,ixs^l,idir,ipole)
957 end do
958 end if
959 end if
960
961 end subroutine bc_fill_srl_stg
962
963 !> fill restricted ghost cells after receipt
964 subroutine bc_fill_restrict_stg(igrid,i^D)
965 integer, intent(in) :: igrid,i^d
966
967 integer :: ipole,ic^d,inc^d,ineighbor,ipe_neighbor,ixs^l,ixr^l,n_i^d,idir
968
969 ipole=neighbor_pole(i^d,igrid)
970 if (ipole==0) then
971 ! Loop over the children ic^D to and their neighbors inc^D
972 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
973 inc^db=2*i^db+ic^db\}
974 ipe_neighbor=neighbor_child(2,inc^d,igrid)
975 if(ipe_neighbor/=mype) then
976 ineighbor=neighbor_child(1,inc^d,igrid)
977 n_i^d=-i^d;
978 !! Unpack the buffer and fill the ghost cells
979 do idir=1,ndim
980 ixr^l=ixr_r_stg_^l(idir,inc^d);
981 ibuf_next=ibuf_recv_r+sizes_r_recv_stg(idir,inc^d)
982 psb(igrid)%ws(ixr^s,idir)=reshape(source=recvbuffer_r(ibuf_recv_r:ibuf_next-1),&
983 shape=shape(psb(igrid)%ws(ixr^s,idir)))
984 ibuf_recv_r=ibuf_next
985 end do
986 end if
987 {end do\}
988 else !! There is a pole
989 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
990 inc^db=2*i^db+ic^db\}
991 ipe_neighbor=neighbor_child(2,inc^d,igrid)
992 if(ipe_neighbor/=mype) then
993 ineighbor=neighbor_child(1,inc^d,igrid)
994 select case(ipole)
995 {case (^d)
996 n_i^d=i^d^d%n_i^dd=-i^dd;\}
997 end select
998 ixr^l=ixr_r_^l(inc^d);
999 !! Unpack the buffer and fill an auxiliary array
1000 pole_buf%ws=zero
1001 do idir=1,ndim
1002 ixs^l=ixs_r_stg_^l(idir,n_i^d);
1003 ixr^l=ixr_r_stg_^l(idir,inc^d);
1004 ibuf_next=ibuf_recv_r+sizes_r_recv_stg(idir,inc^d)
1005 pole_buf%ws(ixr^s,idir)=reshape(source=recvbuffer_r(ibuf_recv_r:ibuf_next-1),&
1006 shape=shape(psb(igrid)%ws(ixr^s,idir)))
1007 call pole_copy_stg(psb(igrid)%ws,ixgs^ll,ixr^l,pole_buf%ws,ixgs^ll,ixr^l,idir,ipole)
1008 ibuf_recv_r=ibuf_next
1009 end do
1010 end if
1011 {end do\}
1012 end if
1013
1014 end subroutine bc_fill_restrict_stg
1015
1016 !> Receive from coarse neighbor
1017 subroutine bc_recv_prolong(igrid,i^D)
1018 integer, intent(in) :: igrid,i^d
1019
1020 integer :: ic^d,ipe_neighbor,inc^d
1021
1022 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
1023 if ({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
1024
1025 ipe_neighbor=neighbor(2,i^d,igrid)
1026 if (ipe_neighbor/=mype) then
1028 inc^d=ic^d+i^d;
1029 itag=(3**^nd+4**^nd)*(igrid-1)+3**^nd+{inc^d*4**(^d-1)+}
1030 call mpi_irecv(psc(igrid)%w,1,type_recv_p(inc^d), &
1031 ipe_neighbor,itag,icomm,recvrequest_c_p(irecv_c),ierrmpi)
1032 if(stagger_grid) then
1034 call mpi_irecv(recvbuffer_p(ibuf_recv_p),sizes_p_recv_total(inc^d),&
1035 mpi_double_precision,ipe_neighbor,itag,&
1036 icomm,recvrequest_p(irecv_p),ierrmpi)
1038 end if
1039 end if
1040
1041 end subroutine bc_recv_prolong
1042
1043 !> Send to finer neighbor
1044 subroutine bc_send_prolong(igrid,i^D)
1045 integer, intent(in) :: igrid,i^d
1046
1047 integer :: ic^d,inc^d,n_i^d,n_inc^d,ineighbor,ipe_neighbor,ixs^l,ipole,idir
1048
1049 ipole=neighbor_pole(i^d,igrid)
1050
1051 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1052 inc^db=2*i^db+ic^db\}
1053 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1054 if(ipe_neighbor/=mype) then
1055 ineighbor=neighbor_child(1,inc^d,igrid)
1056 if(ipole==0) then
1057 n_i^d=-i^d;
1058 n_inc^d=ic^d+n_i^d;
1060 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
1061 call mpi_isend(psb(igrid)%w,1,type_send_p(inc^d), &
1062 ipe_neighbor,itag,icomm,sendrequest_c_p(isend_c),ierrmpi)
1063 if(stagger_grid) then
1064 ibuf_start=ibuf_send_p
1065 do idir=1,ndim
1066 ixs^l=ixs_p_stg_^l(idir,inc^d);
1067 ibuf_next=ibuf_start+sizes_p_send_stg(idir,inc^d)
1068 shapes=(/sizes_p_send_stg(idir,inc^d)/)
1069 sendbuffer_p(ibuf_start:ibuf_next-1)=&
1070 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
1071 ibuf_start=ibuf_next
1072 end do
1074 call mpi_isend(sendbuffer_p(ibuf_send_p),sizes_p_send_total(inc^d),&
1075 mpi_double_precision,ipe_neighbor,itag, &
1076 icomm,sendrequest_p(isend_p),ierrmpi)
1077 ibuf_send_p=ibuf_next
1078 end if
1079 else
1080 ixs^l=ixs_p_^l(inc^d);
1081 select case (ipole)
1082 {case (^d)
1083 n_inc^d=inc^d^d%n_inc^dd=ic^dd-i^dd;\}
1084 end select
1085 if(isend_buf(ipwbuf)/=0) then
1086 call mpi_wait(sendrequest_c_p(isend_buf(ipwbuf)), &
1087 sendstatus_c_p(:,isend_buf(ipwbuf)),ierrmpi)
1088 deallocate(pwbuf(ipwbuf)%w)
1089 end if
1090 allocate(pwbuf(ipwbuf)%w(ixs^s,nwhead:nwtail))
1091 call pole_buffer(pwbuf(ipwbuf)%w,ixs^l,ixs^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
1093 isend_buf(ipwbuf)=isend_c
1094 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
1095 isizes={(ixsmax^d-ixsmin^d+1)*}*nwbc
1096 call mpi_isend(pwbuf(ipwbuf)%w,isizes,mpi_double_precision, &
1097 ipe_neighbor,itag,icomm,sendrequest_c_p(isend_c),ierrmpi)
1098 ipwbuf=1+modulo(ipwbuf,npwbuf)
1099 if(stagger_grid) then
1100 ibuf_start=ibuf_send_p
1101 do idir=1,ndim
1102 ixs^l=ixs_p_stg_^l(idir,inc^d);
1103 ibuf_next=ibuf_start+sizes_p_send_stg(idir,inc^d)
1104 shapes=(/sizes_p_send_stg(idir,inc^d)/)
1105 sendbuffer_p(ibuf_start:ibuf_next-1)=&
1106 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
1107 ibuf_start=ibuf_next
1108 end do
1110 call mpi_isend(sendbuffer_p(ibuf_send_p),sizes_p_send_total(inc^d),&
1111 mpi_double_precision,ipe_neighbor,itag, &
1112 icomm,sendrequest_p(isend_p),ierrmpi)
1113 ibuf_send_p=ibuf_next
1114 end if
1115 end if
1116 end if
1117 {end do\}
1118
1119 end subroutine bc_send_prolong
1120
1121 !> Send to finer neighbor
1122 subroutine bc_fill_prolong(igrid,i^D)
1123 integer, intent(in) :: igrid,i^d
1124
1125 integer :: ipe_neighbor,ineighbor,ixs^l,ixr^l,ic^d,inc^d,n_i^d,n_inc^d,ipole,idir
1126
1127 ipole=neighbor_pole(i^d,igrid)
1128
1129 if(ipole==0) then
1130 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1131 inc^db=2*i^db+ic^db\}
1132 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1133 if(ipe_neighbor==mype) then
1134 ixs^l=ixs_p_^l(inc^d);
1135 ineighbor=neighbor_child(1,inc^d,igrid)
1136 n_i^d=-i^d;
1137 n_inc^d=ic^d+n_i^d;
1138 ixr^l=ixr_p_^l(n_inc^d);
1139 psc(ineighbor)%w(ixr^s,nwhead:nwtail) &
1140 =psb(igrid)%w(ixs^s,nwhead:nwtail)
1141 if(stagger_grid) then
1142 do idir=1,ndim
1143 ixs^l=ixs_p_stg_^l(idir,inc^d);
1144 ixr^l=ixr_p_stg_^l(idir,n_inc^d);
1145 psc(ineighbor)%ws(ixr^s,idir)=psb(igrid)%ws(ixs^s,idir)
1146 end do
1147 end if
1148 end if
1149 {end do\}
1150 else
1151 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1152 inc^db=2*i^db+ic^db\}
1153 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1154 if(ipe_neighbor==mype) then
1155 ixs^l=ixs_p_^l(inc^d);
1156 ineighbor=neighbor_child(1,inc^d,igrid)
1157 select case (ipole)
1158 {case (^d)
1159 n_inc^d=inc^d^d%n_inc^dd=ic^dd-i^dd;\}
1160 end select
1161 ixr^l=ixr_p_^l(n_inc^d);
1162 call pole_copy(psc(ineighbor)%w,ixcog^l,ixr^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
1163 if(stagger_grid) then
1164 do idir=1,ndim
1165 ixs^l=ixs_p_stg_^l(idir,inc^d);
1166 ixr^l=ixr_p_stg_^l(idir,n_inc^d);
1167 call pole_copy_stg(psc(ineighbor)%ws,ixcogs^l,ixr^l,psb(igrid)%ws,ixgs^ll,ixs^l,idir,ipole)
1168 end do
1169 end if
1170 end if
1171 {end do\}
1172 end if
1173 end subroutine bc_fill_prolong
1174
1175 subroutine gc_prolong(igrid)
1176 integer, intent(in) :: igrid
1177
1178 integer :: i^d,idims,iside
1179 logical,dimension(-1:1^D&) :: needprolong
1180
1181 needprolong=.false.
1182 {do i^db=-1,1\}
1183 if (skip_direction([ i^d ])) cycle
1184 if (neighbor_type(i^d,igrid)==neighbor_coarse) then
1185 call bc_prolong(igrid,i^d)
1186 needprolong(i^d)=.true.
1187 end if
1188 {end do\}
1189 if(stagger_grid) then
1190 ! Ghost cell prolongation for staggered variables
1191 ! must be done in a specific order.
1192 ! First the first neighbours, which have 2 indices=0 in 3D
1193 ! or one index=0 in 2D
1194 block=>psb(igrid)
1195 do idims=1,ndim
1196 i^d=0;
1197 select case(idims)
1198 {case(^d)
1199 do i^d=-1,1,2
1200 if (needprolong(i^dd)) call bc_prolong_stg(igrid,i^dd,needprolong)
1201 end do
1202 \}
1203 end select
1204 end do
1205 ! Then the second neighbours which have 1 index=0 in 3D
1206 ! (Only in 3D)
1207 {^ifthreed
1208 i1=0;
1209 do i2=-1,1,2
1210 do i3=-1,1,2
1211 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1212 end do
1213 end do
1214 i2=0;
1215 do i3=-1,1,2
1216 do i1=-1,1,2
1217 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1218 end do
1219 end do
1220 i3=0;
1221 do i1=-1,1,2
1222 do i2=-1,1,2
1223 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1224 end do
1225 end do
1226 }
1227 ! Finally, the corners, that have no index=0
1228 {do i^d=-1,1,2\}
1229 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1230 {end do\}
1231 end if
1232 end subroutine gc_prolong
1233
1234 !> fill coarser representative with data from coarser neighbors
1235 subroutine bc_fill_prolong_stg(igrid,i^D)
1236 integer, intent(in) :: igrid,i^d
1237
1238 integer :: ipe_neighbor,ineighbor,ipole,ixr^l,ic^d,inc^d,n_inc^d,idir
1239
1240 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
1241 if ({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
1242
1243 ipe_neighbor=neighbor(2,i^d,igrid)
1244 if(ipe_neighbor/=mype) then
1245 ineighbor=neighbor(1,i^d,igrid)
1246 ipole=neighbor_pole(i^d,igrid)
1247
1248 if (ipole==0) then !! There is no pole
1249 inc^d=ic^d+i^d;
1250 ixr^l=ixr_p_^l(inc^d);
1251 do idir=1,ndim
1252 ixr^l=ixr_p_stg_^l(idir,inc^d);
1253 ibuf_next=ibuf_recv_p+sizes_p_recv_stg(idir,inc^d)
1254 psc(igrid)%ws(ixr^s,idir)=reshape(source=recvbuffer_p(ibuf_recv_p:ibuf_next-1),&
1255 shape=shape(psc(igrid)%ws(ixr^s,idir)))
1256 ibuf_recv_p=ibuf_next
1257 end do
1258 else !! There is a pole
1259 inc^d=ic^d+i^d;
1260 select case (ipole)
1261 {case (^d)
1262 n_inc^d=2*i^d+(3-ic^d)^d%n_inc^dd=-2*i^dd+ic^dd;\}
1263 end select
1264 !! Unpack the buffer and fill an auxiliary array
1265 pole_buf%ws=zero
1266 do idir=1,ndim
1267 ixr^l=ixr_p_stg_^l(idir,inc^d);
1268 ibuf_next=ibuf_recv_p+sizes_p_recv_stg(idir,inc^d)
1269 pole_buf%ws(ixr^s,idir)=reshape(source=recvbuffer_p(ibuf_recv_p:ibuf_next-1),&
1270 shape=shape(psc(igrid)%ws(ixr^s,idir)))
1271 call pole_copy_stg(psc(igrid)%ws,ixcogs^l,ixr^l,pole_buf%ws,ixgs^ll,ixr^l,idir,ipole)
1272 ibuf_recv_p=ibuf_next
1273 end do
1274 end if
1275 end if
1276
1277 end subroutine bc_fill_prolong_stg
1278
1279 !> do prolongation for fine blocks after receipt data from coarse neighbors
1280 subroutine bc_prolong(igrid,i^D)
1283
1284 double precision :: dxfi^d, dxco^d, xfimin^d, xcomin^d, invdxco^d
1285 integer :: i^d,igrid
1286 integer :: ixfi^l,ixco^l,ii^d, idims,iside,ixb^l
1287
1288 ixfi^l=ixr_srl_^l(i^d);
1289 dxfi^d=rnode(rpdx^d_,igrid);
1290 dxco^d=two*dxfi^d;
1291 invdxco^d=1.d0/dxco^d;
1292
1293 ! compute the enlarged grid lower left corner coordinates
1294 ! these are true coordinates for an equidistant grid,
1295 ! but we can temporarily also use them for getting indices
1296 ! in stretched grids
1297 xfimin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxfi^d;
1298 xcomin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxco^d;
1299
1300 if(phyboundblock(igrid).and.bcphys) then
1301 block=>psc(igrid)
1302 do idims=1,ndim
1303 ixcomin^d=int((xfimin^d+(dble(ixfimin^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1-1;
1304 ixcomax^d=int((xfimin^d+(dble(ixfimax^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1+1;
1305 {^ifthreed
1306 ! avoid using undetermined ghost cells at physical boundary edges
1307 if(idims == 1) then
1308 if(neighbor_type(-1,0,0,igrid)==neighbor_boundary .or. &
1309 neighbor_type(1,0,0,igrid)==neighbor_boundary) then
1310 if(neighbor_type(0,-1,0,igrid)==neighbor_boundary) ixcomin2=ixcommin2
1311 if(neighbor_type(0,0,-1,igrid)==neighbor_boundary) ixcomin3=ixcommin3
1312 if(neighbor_type(0,1,0,igrid)==neighbor_boundary) ixcomax2=ixcommax2
1313 if(neighbor_type(0,0,1,igrid)==neighbor_boundary) ixcomax3=ixcommax3
1314 end if
1315 else if(idims == 2) then
1316 if(neighbor_type(0,-1,0,igrid)==neighbor_boundary .or. &
1317 neighbor_type(0,1,0,igrid)==neighbor_boundary) then
1318 if(neighbor_type(0,0,-1,igrid)==neighbor_boundary) ixcomin3=ixcommin3
1319 if(neighbor_type(0,0,1,igrid)==neighbor_boundary) ixcomax3=ixcommax3
1320 end if
1321 end if
1322 }
1323 do iside=1,2
1324 ii^d=kr(^d,idims)*(2*iside-3);
1325 if(neighbor_type(ii^d,igrid)/=neighbor_boundary) cycle
1326 if(( {(iside==1.and.idims==^d.and.ixcomin^d<ixcogmin^d+nghostcells)|.or.} ) &
1327 .or.( {(iside==2.and.idims==^d.and.ixcomax^d>ixcogmax^d-nghostcells)|.or. })) then
1328 {ixbmin^d=merge(ixcogmin^d,ixcomin^d,idims==^d);}
1329 {ixbmax^d=merge(ixcogmax^d,ixcomax^d,idims==^d);}
1330 call bc_phys(iside,idims,time,0.d0,psc(igrid),ixcog^l,ixb^l)
1331 end if
1332 end do
1333 end do
1334 end if
1335
1336 if(prolongprimitive) then
1337 block=>psc(igrid)
1338 ixcomin^d=int((xfimin^d+(dble(ixfimin^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1-1;
1339 ixcomax^d=int((xfimin^d+(dble(ixfimax^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1+1;
1340 call phys_to_primitive(ixcog^l,ixco^l,psc(igrid)%w,psc(igrid)%x)
1341 end if
1342
1343 if(ghost_copy) then
1344 call interpolation_copy(igrid,ixfi^l,dxfi^d,xfimin^d,dxco^d,invdxco^d,xcomin^d)
1345 else
1346 call interpolation_linear(igrid,ixfi^l,dxfi^d,xfimin^d,dxco^d,invdxco^d,xcomin^d)
1347 end if
1348
1349 if(prolongprimitive) then
1350 block=>psc(igrid)
1351 call phys_to_conserved(ixcog^l,ixco^l,psc(igrid)%w,psc(igrid)%x)
1352 end if
1353
1354 end subroutine bc_prolong
1355
1356 subroutine bc_prolong_stg(igrid,i^D,NeedProlong)
1357 use mod_amr_fct
1358 double precision :: dxfi^d,dxco^d,xfimin^d,xcomin^d,invdxco^d
1359 integer :: igrid,i^d
1360 integer :: ixfi^l,ixco^l
1361 logical,dimension(-1:1^D&) :: needprolong
1362 logical :: fine_^lin
1363 ! Check what is already at the desired level
1364 fine_^lin=.false.;
1365 {
1366 if(i^d>-1) fine_min^din=(.not.needprolong(i^dd-kr(^d,^dd)).and.neighbor_type(i^dd-kr(^d,^dd),igrid)/=1)
1367 if(i^d<1) fine_max^din=(.not.needprolong(i^dd+kr(^d,^dd)).and.neighbor_type(i^dd+kr(^d,^dd),igrid)/=1)
1368 \}
1369
1370 ixfi^l=ixr_srl_^l(i^d);
1371
1372 dxfi^d=rnode(rpdx^d_,igrid);
1373 dxco^d=two*dxfi^d;
1374 invdxco^d=1.d0/dxco^d;
1375
1376 xfimin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxfi^d;
1377 xcomin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxco^d;
1378
1379 ! moved the physical boundary filling here, to only fill the
1380 ! part needed
1381
1382 ixcomin^d=int((xfimin^d+(dble(ixfimin^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1-1;
1383 ixcomax^d=int((xfimin^d+(dble(ixfimax^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1+1;
1384
1385 if(prolongprimitive) call phys_to_primitive(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1386
1387 call prolong_2nd_stg(psc(igrid),psb(igrid),ixco^l,ixfi^l,dxco^d,xcomin^d,dxfi^d,xfimin^d,.true.,fine_^lin)
1388
1389 if(prolongprimitive) call phys_to_conserved(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1390
1391 ! The current region has already been refined, so it does not need to be prolonged again
1392 needprolong(i^d)=.false.
1393
1394 end subroutine bc_prolong_stg
1395
1396 subroutine interpolation_linear(igrid,ixFi^L,dxFi^D,xFimin^D, &
1397 dxCo^D,invdxCo^D,xComin^D)
1399 integer, intent(in) :: igrid, ixfi^l
1400 double precision, intent(in) :: dxfi^d, xfimin^d,dxco^d, invdxco^d, xcomin^d
1401
1402 double precision :: xco^d, xfi^d, eta^d
1403 double precision :: slopel, sloper, slopec, signc, signr
1404 double precision :: slope(1:nw,ndim)
1405 !!double precision :: local_invdxCo^D
1406 double precision :: signedfactorhalf^d
1407 integer :: ixco^d, jxco^d, hxco^d, ixfi^d, ix^d, iw, idims, nwmin,nwmax
1408 !integer :: ixshift^D, icase
1409
1410 !icase=mod(nghostcells,2)
1411
1412 if(prolongprimitive) then
1413 nwmin=1
1414 nwmax=nw
1415 else
1416 nwmin=nwhead
1417 nwmax=nwtail
1418 end if
1419
1420 {do ixfi^db = ixfi^lim^db
1421 ! cell-centered coordinates of fine grid point
1422 ! here we temporarily use an equidistant grid
1423 xfi^db=xfimin^db+(dble(ixfi^db)-half)*dxfi^db
1424
1425 ! indices of coarse cell which contains the fine cell
1426 ! since we computed lower left corner earlier
1427 ! in equidistant fashion: also ok for stretched case
1428 ixco^db=int((xfi^db-xcomin^db)*invdxco^db)+1
1429
1430 ! cell-centered coordinates of coarse grid point
1431 ! here we temporarily use an equidistant grid
1432 xco^db=xcomin^db+(dble(ixco^db)-half)*dxco^db \}
1433
1434 !if(.not.slab) then
1435 ! ^D&local_invdxCo^D=1.d0/psc(igrid)%dx({ixCo^DD},^D)\
1436 !endif
1437
1438 if(slab_uniform) then
1439 ! actual cell-centered coordinates of fine grid point
1440 !!^D&xFi^D=block%x({ixFi^DD},^D)\
1441 ! actual cell-centered coordinates of coarse grid point
1442 !!^D&xCo^D=psc(igrid)%x({ixCo^DD},^D)\
1443 ! normalized distance between fine/coarse cell center
1444 ! in coarse cell: ranges from -0.5 to 0.5 in each direction
1445 ! (origin is coarse cell center)
1446 ! this is essentially +1/4 or -1/4 on cartesian mesh
1447 eta^d=(xfi^d-xco^d)*invdxco^d;
1448 else
1449 !select case(icase)
1450 ! case(0)
1451 !{! here we assume an even number of ghostcells!!!
1452 !ixshift^D=2*(mod(ixFi^D,2)-1)+1
1453 !if(ixshift^D>0.0d0)then
1454 ! ! oneven fine grid points
1455 ! eta^D=-0.5d0*(one-block%dvolume(ixFi^DD) &
1456 ! /sum(block%dvolume(ixFi^D:ixFi^D+1^D%ixFi^DD)))
1457 !else
1458 ! ! even fine grid points
1459 ! eta^D=+0.5d0*(one-block%dvolume(ixFi^DD) &
1460 ! /sum(block%dvolume(ixFi^D-1:ixFi^D^D%ixFi^DD)))
1461 !endif\}
1462 ! case(1)
1463 !{! here we assume an odd number of ghostcells!!!
1464 !ixshift^D=2*(mod(ixFi^D,2)-1)+1
1465 !if(ixshift^D>0.0d0)then
1466 ! ! oneven fine grid points
1467 ! eta^D=+0.5d0*(one-block%dvolume(ixFi^DD) &
1468 ! /sum(block%dvolume(ixFi^D-1:ixFi^D^D%ixFi^DD)))
1469 !else
1470 ! ! even fine grid points
1471 ! eta^D=-0.5d0*(one-block%dvolume(ixFi^DD) &
1472 ! /sum(block%dvolume(ixFi^D:ixFi^D+1^D%ixFi^DD)))
1473 !endif\}
1474 ! case default
1475 ! call mpistop("no such case")
1476 !end select
1477 ! the different cases for even/uneven number of ghost cells
1478 ! are automatically handled using the relative index to ixMlo
1479 ! as well as the pseudo-coordinates xFi and xCo
1480 ! these latter differ from actual cell centers when stretching is used
1481 ix^d=2*int((ixfi^d+ixmlo^d)/2)-ixmlo^d;
1482 {if(xfi^d>xco^d) then
1483 signedfactorhalf^d=0.5d0
1484 else
1485 signedfactorhalf^d=-0.5d0
1486 end if
1487 eta^d=signedfactorhalf^d*(one-psb(igrid)%dvolume(ixfi^dd) &
1488 /sum(psb(igrid)%dvolume(ix^d:ix^d+1^d%ixFi^dd))) \}
1489 !{eta^D=(xFi^D-xCo^D)*invdxCo^D &
1490 ! *two*(one-block%dvolume(ixFi^DD) &
1491 ! /sum(block%dvolume(ix^D:ix^D+1^D%ixFi^DD))) \}
1492 end if
1493
1494 do idims=1,ndim
1495 hxco^d=ixco^d-kr(^d,idims)\
1496 jxco^d=ixco^d+kr(^d,idims)\
1497
1498 do iw=nwmin,nwmax
1499 slopel=psc(igrid)%w(ixco^d,iw)-psc(igrid)%w(hxco^d,iw)
1500 sloper=psc(igrid)%w(jxco^d,iw)-psc(igrid)%w(ixco^d,iw)
1501 slopec=half*(sloper+slopel)
1502
1503 ! get limited slope
1504 signr=sign(one,sloper)
1505 signc=sign(one,slopec)
1506 !select case(prolong_limiter)
1507 !case(1)
1508 ! ! unlimit
1509 ! slope(iw,idims)=slopeC
1510 !case(2)
1511 ! ! minmod
1512 ! slope(iw,idims)=signR*max(zero,min(dabs(slopeR), &
1513 ! signR*slopeL))
1514 !case(3)
1515 ! ! woodward
1516 ! slope(iw,idims)=two*signR*max(zero,min(dabs(slopeR), &
1517 ! signR*slopeL,signR*half*slopeC))
1518 !case(4)
1519 ! ! koren
1520 ! slope(iw,idims)=signR*max(zero,min(two*signR*slopeL, &
1521 ! (dabs(slopeR)+two*slopeL*signR)*third,two*dabs(slopeR)))
1522 !case default
1523 slope(iw,idims)=signc*max(zero,min(dabs(slopec), &
1524 signc*slopel,signc*sloper))
1525 !end select
1526 end do
1527 end do
1528
1529 ! Interpolate from coarse cell using limited slopes
1530 psb(igrid)%w(ixfi^d,nwmin:nwmax)=psc(igrid)%w(ixco^d,nwmin:nwmax)+&
1531 {(slope(nwmin:nwmax,^d)*eta^d)+}
1532
1533 {end do\}
1534
1535 if(prolongprimitive) then
1536 block=>psb(igrid)
1537 call phys_to_conserved(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1538 end if
1539
1540 end subroutine interpolation_linear
1541
1542 subroutine interpolation_copy(igrid, ixFi^L,dxFi^D,xFimin^D, &
1543 dxCo^D,invdxCo^D,xComin^D)
1545 integer, intent(in) :: igrid, ixfi^l
1546 double precision, intent(in) :: dxfi^d, xfimin^d,dxco^d, invdxco^d, xcomin^d
1547
1548 double precision :: xfi^d
1549 integer :: ixco^d, ixfi^d, nwmin,nwmax
1550
1551 if(prolongprimitive) then
1552 nwmin=1
1553 nwmax=nw
1554 else
1555 nwmin=nwhead
1556 nwmax=nwtail
1557 end if
1558
1559 {do ixfi^db = ixfi^lim^db
1560 ! cell-centered coordinates of fine grid point
1561 xfi^db=xfimin^db+(dble(ixfi^db)-half)*dxfi^db
1562
1563 ! indices of coarse cell which contains the fine cell
1564 ! note: this also works for stretched grids
1565 ixco^db=int((xfi^db-xcomin^db)*invdxco^db)+1\}
1566
1567 ! Copy from coarse cell
1568 psb(igrid)%w(ixfi^d,nwmin:nwmax)=psc(igrid)%w(ixco^d,nwmin:nwmax)
1569
1570 {end do\}
1571
1572 if(prolongprimitive) call phys_to_conserved(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1573
1574 end subroutine interpolation_copy
1575
1576 subroutine pole_copy(wrecv,ixIR^L,ixR^L,wsend,ixIS^L,ixS^L,ipole)
1577
1578 integer, intent(in) :: ixir^l,ixr^l,ixis^l,ixs^l,ipole
1579 double precision :: wrecv(ixir^s,1:nw), wsend(ixis^s,1:nw)
1580
1581 integer :: iw, iside, ib
1582
1583 select case (ipole)
1584 {case (^d)
1585 iside=int((i^d+3)/2)
1586 ib=2*(^d-1)+iside
1587 do iw=nwhead,nwtail
1588 select case (typeboundary(iw,ib))
1589 case (bc_symm)
1590 wrecv(ixr^s,iw) = wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1591 case (bc_asymm)
1592 wrecv(ixr^s,iw) =-wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1593 case default
1594 call mpistop("Pole boundary condition should be symm or asymm")
1595 end select
1596 end do \}
1597 end select
1598
1599 end subroutine pole_copy
1600
1601 subroutine pole_copy_stg(wrecv,ixIR^L,ixR^L,wsend,ixIS^L,ixS^L,idirs,ipole)
1602
1603 integer, intent(in) :: ixir^l,ixr^l,ixis^l,ixs^l,idirs,ipole
1604
1605 double precision :: wrecv(ixir^s,1:nws), wsend(ixis^s,1:nws)
1606 integer :: ib, iside
1607
1608 select case (ipole)
1609 {case (^d)
1610 iside=int((i^d+3)/2)
1611 ib=2*(^d-1)+iside
1612 select case (typeboundary(iw_mag(idirs),ib))
1613 case (bc_symm)
1614 wrecv(ixr^s,idirs) = wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,idirs)
1615 case (bc_asymm)
1616 wrecv(ixr^s,idirs) =-wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,idirs)
1617 case default
1618 call mpistop("Pole boundary condition should be symm or asymm")
1619 end select
1620 \}
1621 end select
1622
1623 end subroutine pole_copy_stg
1624
1625 subroutine pole_buffer(wrecv,ixIR^L,ixR^L,wsend,ixIS^L,ixS^L,ipole)
1626
1627 integer, intent(in) :: ixir^l,ixr^l,ixis^l,ixs^l,ipole
1628 double precision :: wrecv(ixir^s,nwhead:nwtail), wsend(ixis^s,1:nw)
1629
1630 integer :: iw, iside, ib
1631
1632 select case (ipole)
1633 {case (^d)
1634 iside=int((i^d+3)/2)
1635 ib=2*(^d-1)+iside
1636 do iw=nwhead,nwtail
1637 select case (typeboundary(iw,ib))
1638 case (bc_symm)
1639 wrecv(ixr^s,iw) = wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1640 case (bc_asymm)
1641 wrecv(ixr^s,iw) =-wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1642 case default
1643 call mpistop("Pole boundary condition should be symm or asymm")
1644 end select
1645 end do \}
1646 end select
1647
1648 end subroutine pole_buffer
1649
1650 end subroutine getbc
1651
1652end module mod_ghostcells_update
logical function skip_direction(dir)
subroutine, public prolong_2nd_stg(sco, sfi, ixcolin, ixfilin, dxcod, xcomind, dxfid, xfimind, ghost, fine_lin)
This subroutine performs a 2nd order prolongation for a staggered field F, preserving the divergence ...
Definition mod_amr_fct.t:41
subroutine, public bc_phys(iside, idims, time, qdt, s, ixgl, ixbl)
fill ghost cells at a physical boundary
subroutine, public getintbc(time, qdt, ixgl)
fill inner boundary values
subroutine, public coarsen_grid(sfi, ixfigl, ixfil, sco, ixcogl, ixcol)
coarsen one grid to its coarser representative
Definition mod_coarsen.t:13
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
update ghost cells of all blocks including physical boundaries
integer, dimension(0:3^d &), target type_recv_p_p1
integer, dimension( :^d &), pointer type_recv_r
integer, dimension(-1:1^d &), target type_send_srl_p1
integer, dimension(-1:1^d &) sizes_r_send_total
integer, dimension(^nd, 0:3) l
integer, dimension(-1:1^d &), target type_send_r_p2
integer, dimension(:), allocatable sendrequest_c_p
integer, dimension(^nd,-1:1) ixs_r_stg_
integer, dimension(^nd,-1:1) ixs_srl_stg_
integer, dimension(^nd, 0:3^d &) sizes_p_send_stg
subroutine getbc(time, qdt, psb, nwstart, nwbc)
do update ghost cells of all blocks including physical boundaries
integer, dimension(-1:1^d &) sizes_srl_send_total
integer, dimension(^nd, 0:3) ixr_r_stg_
integer, dimension(:), allocatable sendrequest_r
integer, dimension(:), allocatable recvrequest_r
double precision, dimension(:), allocatable sendbuffer_p
integer, dimension(:,:), allocatable sendstatus_c_p
integer, dimension(^nd,-1:1^d &) sizes_r_send_stg
integer, dimension(0:3) ixs_p_
integer, dimension(0:3) ixr_r_
integer, dimension(0:3^d &), target type_send_p_f
integer, dimension( :^d &), pointer type_send_p
integer, dimension(:,:), allocatable sendstatus_c_sr
integer, dimension(0:3^d &), target type_recv_p_p2
integer, dimension(0:3) ixr_p_
double precision, dimension(:), allocatable recvbuffer_r
integer, dimension( :^d &), pointer type_send_srl
integer, dimension(-1:1^d &), target type_send_r_p1
integer, dimension(:), allocatable recvrequest_c_p
integer, dimension(-1:1^d &), target type_send_srl_p2
subroutine create_bc_mpi_datatype(nwstart, nwbc)
integer, dimension(0:3^d &), target type_send_p_p2
integer, dimension(:), allocatable recvrequest_c_sr
integer, dimension(0:3^d &), target type_recv_r_f
integer, dimension(-1:1^d &), target type_recv_srl_f
integer, dimension(:), allocatable sendrequest_c_sr
integer, dimension(-1:1^d &), target type_send_r_f
double precision, dimension(:), allocatable recvbuffer_srl
integer, dimension(:,:), allocatable recvstatus_p
integer, dimension(^nd, 0:3) ixs_p_stg_
integer, dimension(-1:1^d &), target type_send_srl_f
integer, dimension(^nd, 0:3^d &) sizes_p_recv_stg
integer, dimension(0:3^d &), target type_send_p_p1
integer, dimension(^nd,-1:1^d &) sizes_srl_recv_stg
double precision, dimension(:), allocatable recvbuffer_p
integer, dimension(^nd,-1:1) ixr_srl_stg_
integer, dimension(-1:1) ixs_r_
procedure(update_eos_bc_sub), pointer update_eos_4_bc
integer, dimension( :^d &), pointer type_send_r
integer, dimension(-1:1) ixr_srl_
integer, dimension(0:3^d &), target type_recv_r_p1
double precision, dimension(:), allocatable sendbuffer_r
integer, dimension(0:3^d &), target type_recv_r_p2
integer, dimension(0:3^d &) sizes_p_recv_total
integer, dimension(:,:), allocatable recvstatus_c_sr
integer, dimension(0:3^d &) sizes_r_recv_total
integer, parameter npwbuf
integer, dimension(:), allocatable sendrequest_p
integer, dimension(^nd, 0:3^d &) sizes_r_recv_stg
integer, dimension(-1:1^d &), target type_recv_srl_p2
double precision, dimension(:), allocatable sendbuffer_srl
integer, dimension(-1:1) ixs_srl_
integer, dimension(:,:), allocatable sendstatus_srl
integer, dimension( :^d &), pointer type_recv_p
integer, dimension(:,:), allocatable recvstatus_srl
integer, dimension(:), allocatable sendrequest_srl
integer, dimension(:,:), allocatable recvstatus_r
integer, dimension(0:3^d &) sizes_p_send_total
integer, dimension(^nd, 0:3) ixr_p_stg_
integer, dimension(-1:1^d &), target type_recv_srl_p1
integer, dimension(:,:), allocatable sendstatus_r
integer, dimension(0:3^d &), target type_recv_p_f
integer, dimension( :^d &), pointer type_recv_srl
integer, dimension(:,:), allocatable sendstatus_p
integer, dimension(-1:1^d &) sizes_srl_recv_total
subroutine get_bc_comm_type(comm_type, ixl, ixgl, nwstart, nwbc)
integer, dimension(:), allocatable recvrequest_p
integer, dimension(:), allocatable recvrequest_srl
integer, dimension(^nd,-1:1^d &) sizes_srl_send_stg
integer, dimension(:,:), allocatable recvstatus_c_p
This module contains definitions of global parameters and variables and some generic functions/subrou...
logical internalboundary
if there is an internal boundary
integer ixghi
Upper index of grid block arrays.
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer, parameter ndim
Number of spatial dimensions for grid variables.
logical stagger_grid
True for using stagger grid.
logical ghost_copy
whether copy values instead of interpolation in ghost cells of finer blocks
integer ierrmpi
A global MPI error return code.
double precision, dimension(:), allocatable, parameter d
integer nghostcells
Number of ghost cells surrounding a grid.
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:52
procedure(sub_convert), pointer phys_to_prolong
Definition mod_physics.t:55
procedure(sub_convert), pointer phys_to_conserved
Definition mod_physics.t:51
character(len=name_len) physics_type
String describing the physics type of the simulation.
Definition mod_physics.t:47
procedure(sub_convert), pointer phys_from_prolong
Definition mod_physics.t:56
Module with all the methods that users can customize in AMRVAC.
procedure(special_prepare_bc), pointer usr_prepare_boundary