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 integer :: flushed_send_c, flushed_send_srl, flushed_send_r, flushed_send_p
379 ! index pointer for buffer arrays as a start for a segment
380 integer :: ibuf_start, ibuf_next
381 ! shapes of reshape
382 integer, dimension(1) :: shapes
383 type(wbuffer) :: pwbuf(npwbuf)
384
385 time_bcin=mpi_wtime()
386
387 nwhead=nwstart
388 nwtail=nwstart+nwbc-1
389
390 ! fill internal physical boundary
391 if (internalboundary) then
392 call getintbc(time,qdt,ixg^ll)
393 end if
394
395 ! prepare coarse values to send to coarser neighbors
396 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
397 do iigrid=1,igridstail; igrid=igrids(iigrid);
398 if(any(neighbor_type(:^d&,igrid)==neighbor_coarse)) then
399 call coarsen_grid(psb(igrid),ixg^ll,ixm^l,psc(igrid),ixcog^l,ixcom^l)
400 end if
401 end do
402 !$OMP END PARALLEL DO
403
404 ! default : no singular axis
405 irecv_c=0
406 isend_c=0
407 flushed_send_c=0
408 flushed_send_srl=0
409 flushed_send_r=0
410 flushed_send_p=0
411 isend_buf=0
412 ipwbuf=1
413
414 if(stagger_grid) then
421 irecv_srl=0
422 irecv_r=0
423 irecv_p=0
424 isend_srl=0
425 isend_r=0
426 isend_p=0
427 end if
428
429 !$OMP PARALLEL SECTIONS PRIVATE(iigrid,igrid,i^D)
430 !$OMP SECTION
431 ! MPI receive ghost-cell values from sibling blocks and finer neighbors in different processors
432 do iigrid=1,igridstail; igrid=igrids(iigrid);
433 {do i^db=-1,1\}
434 if (skip_direction([ i^d ])) cycle
435 select case (neighbor_type(i^d,igrid))
436 case (neighbor_sibling)
437 call bc_recv_srl(igrid,i^d)
438 case (neighbor_fine)
439 call bc_recv_restrict(igrid,i^d)
440 end select
441 {end do\}
442 end do
443
444 ! MPI send ghost-cell values to sibling blocks and coarser neighbors in different processors
445 do iigrid=1,igridstail; igrid=igrids(iigrid);
446 {do i^db=-1,1\}
447 if(skip_direction([ i^d ])) cycle
448 select case (neighbor_type(i^d,igrid))
449 case (neighbor_sibling)
450 call bc_send_srl(igrid,i^d)
451 case (neighbor_coarse)
452 call bc_send_restrict(igrid,i^d)
453 end select
454 {end do\}
455 end do
456
458 call waitall_pending(isend_c,flushed_send_c,sendrequest_c_sr,sendstatus_c_sr)
459 if(stagger_grid) then
461 call waitall_pending(nsend_bc_srl,flushed_send_srl,sendrequest_srl,sendstatus_srl)
463 call waitall_pending(nsend_bc_r,flushed_send_r,sendrequest_r,sendstatus_r)
464 end if
465
466 do ipwbuf=1,npwbuf
467 if (isend_buf(ipwbuf)/=0) deallocate(pwbuf(ipwbuf)%w)
468 end do
469 !$OMP SECTION
470 ! fill ghost-cell values of sibling blocks and coarser neighbors in the same processor
471 do iigrid=1,igridstail; igrid=igrids(iigrid);
472 {do i^db=-1,1\}
473 if(skip_direction([ i^d ])) cycle
474 select case (neighbor_type(i^d,igrid))
475 case(neighbor_sibling)
476 call bc_fill_srl(igrid,i^d)
477 case(neighbor_coarse)
478 call bc_fill_restrict(igrid,i^d)
479 end select
480 {end do\}
481 end do
482 !$OMP END PARALLEL SECTIONS
483
484 if(stagger_grid) then
485 ! unpack the received data from sibling blocks and finer neighbors to fill ghost-cell staggered values
488 do iigrid=1,igridstail; igrid=igrids(iigrid);
489 {do i^db=-1,1\}
490 if (skip_direction([ i^d ])) cycle
491 select case (neighbor_type(i^d,igrid))
492 case (neighbor_sibling)
493 call bc_fill_srl_stg(igrid,i^d)
494 case (neighbor_fine)
495 call bc_fill_restrict_stg(igrid,i^d)
496 end select
497 {end do\}
498 end do
499 end if
500
501 irecv_c=0
502 isend_c=0
503 flushed_send_c=0
504 flushed_send_p=0
505 isend_buf=0
506 ipwbuf=1
507
508 !$OMP PARALLEL SECTIONS PRIVATE(iigrid,igrid,i^D)
509 !$OMP SECTION
510 ! MPI receive ghost-cell values from coarser 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_coarse) call bc_recv_prolong(igrid,i^d)
515 {end do\}
516 end do
517 ! MPI send ghost-cell values to finer neighbors in different processors
518 do iigrid=1,igridstail; igrid=igrids(iigrid);
519 {do i^db=-1,1\}
520 if (skip_direction([ i^d ])) cycle
521 if (neighbor_type(i^d,igrid)==neighbor_fine) call bc_send_prolong(igrid,i^d)
522 {end do\}
523 end do
524
526 call waitall_pending(isend_c,flushed_send_c,sendrequest_c_p,sendstatus_c_p)
527
528 if(stagger_grid) then
530 call waitall_pending(nsend_bc_p,flushed_send_p,sendrequest_p,sendstatus_p)
531 end if
532
533 do ipwbuf=1,npwbuf
534 if (isend_buf(ipwbuf)/=0) deallocate(pwbuf(ipwbuf)%w)
535 end do
536
537 !$OMP SECTION
538 ! fill coarse ghost-cell values of finer neighbors in the same processor
539 do iigrid=1,igridstail; igrid=igrids(iigrid);
540 {do i^db=-1,1\}
541 if (skip_direction([ i^d ])) cycle
542 if (neighbor_type(i^d,igrid)==neighbor_fine) call bc_fill_prolong(igrid,i^d)
543 {end do\}
544 end do
545 !$OMP END PARALLEL SECTIONS
546
547 if(stagger_grid) then
548 ! fill coarser representative ghost cells after receipt
550 do iigrid=1,igridstail; igrid=igrids(iigrid);
551 {do i^db=-1,1\}
552 if (skip_direction([ i^d ])) cycle
553 if(neighbor_type(i^d,igrid)==neighbor_coarse) call bc_fill_prolong_stg(igrid,i^d)
554 {end do\}
555 end do
556 end if
557 ! do prolongation on the ghost-cell values based on the received coarse values from coarser neighbors
558 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
559 do iigrid=1,igridstail; igrid=igrids(iigrid);
560 call gc_prolong(igrid)
561 end do
562 !$OMP END PARALLEL DO
563
564 ! fill physical boundary ghost cells after internal ghost-cell values exchange
565 if(bcphys) then
566 if(associated(usr_prepare_boundary)) then
567 call usr_prepare_boundary(time, qdt)
568 endif
569 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
570 do iigrid=1,igridstail; igrid=igrids(iigrid);
571 if(.not.phyboundblock(igrid)) cycle
572 call fill_boundary_after_gc(igrid)
573 end do
574 !$OMP END PARALLEL DO
575 end if
576
577 ! modify normal component of magnetic field to fix divB=0
578 if(bcphys.and.associated(phys_boundary_adjust)) then
579 !$OMP PARALLEL DO SCHEDULE(dynamic) PRIVATE(igrid)
580 do iigrid=1,igridstail; igrid=igrids(iigrid);
581 if(.not.phyboundblock(igrid)) cycle
582 call phys_boundary_adjust(igrid,psb)
583 end do
584 !$OMP END PARALLEL DO
585 end if
586
587 time_bc=time_bc+(mpi_wtime()-time_bcin)
588
589 contains
590
591 subroutine waitall_limited(nrequest,requests,statuses)
592 integer, intent(in) :: nrequest
593 integer, intent(inout) :: requests(:)
594 integer, intent(inout) :: statuses(:,:)
595
596 if (ghostcell_comm_batched) then
597 call waitall_range(1,nrequest,requests,statuses)
598 else
599 call mpi_waitall(nrequest,requests,statuses,ierrmpi)
600 end if
601 end subroutine waitall_limited
602
603 subroutine waitall_range(ifirst,ilast,requests,statuses)
604 integer, intent(in) :: ifirst, ilast
605 integer, intent(inout) :: requests(:)
606 integer, intent(inout) :: statuses(:,:)
607
608 integer :: irequest,nwait
609
610 do irequest=ifirst,ilast,ghostcell_comm_batch_size
611 nwait=min(ghostcell_comm_batch_size,ilast-irequest+1)
612 call mpi_waitall(nwait,requests(irequest:irequest+nwait-1),&
613 statuses(:,irequest:irequest+nwait-1),ierrmpi)
614 end do
615 end subroutine waitall_range
616
617 subroutine waitall_pending(nrequest,nwaited,requests,statuses)
618 integer, intent(in) :: nrequest
619 integer, intent(inout) :: nwaited
620 integer, intent(inout) :: requests(:)
621 integer, intent(inout) :: statuses(:,:)
622
623 if (nrequest>nwaited) then
624 if (ghostcell_comm_batched) then
625 call waitall_range(nwaited+1,nrequest,requests,statuses)
626 else
627 call mpi_waitall(nrequest-nwaited,requests(nwaited+1:nrequest),&
628 statuses(:,nwaited+1:nrequest),ierrmpi)
629 end if
630 nwaited=nrequest
631 end if
632 end subroutine waitall_pending
633
634 subroutine wait_send_batch(nrequest,nwaited,requests,statuses)
635 integer, intent(in) :: nrequest
636 integer, intent(inout) :: nwaited
637 integer, intent(inout) :: requests(:)
638 integer, intent(inout) :: statuses(:,:)
639
640 if (ghostcell_comm_batched .and. &
641 nrequest-nwaited >= ghostcell_comm_batch_size) then
642 call waitall_range(nwaited+1,nrequest,requests,statuses)
643 nwaited=nrequest
644 end if
645 end subroutine wait_send_batch
646
647 logical function skip_direction(dir)
648 integer, intent(in) :: dir(^ND)
649
650 if (all(dir == 0)) then
651 skip_direction = .true.
652 else
653 skip_direction = .false.
654 end if
655 end function skip_direction
656
657 !> Physical boundary conditions
658 subroutine fill_boundary_after_gc(igrid)
659
660 integer, intent(in) :: igrid
661
662 integer :: idims,iside,i^D,k^L,ixB^L
663
664 block=>psb(igrid)
665 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
666 do idims=1,ndim
667 ! to avoid using as yet unknown corner info in more than 1D, we
668 ! fill only interior mesh ranges of the ghost cell ranges at first,
669 ! and progressively enlarge the ranges to include corners later
670 kmin1=0; kmax1=0;
671 {^iftwod
672 kmin2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0,-1,igrid)==1)
673 kmax2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0, 1,igrid)==1)}
674 {^ifthreed
675 kmin2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0,-1,0,igrid)==1)
676 kmax2=merge(1, 0, idims .lt. 2 .and. neighbor_type(0, 1,0,igrid)==1)
677 kmin3=merge(1, 0, idims .lt. 3 .and. neighbor_type(0,0,-1,igrid)==1)
678 kmax3=merge(1, 0, idims .lt. 3 .and. neighbor_type(0,0, 1,igrid)==1)}
679 ixbmin^d=ixglo^d+kmin^d*nghostcells;
680 ixbmax^d=ixghi^d-kmax^d*nghostcells;
681 do iside=1,2
682 i^d=kr(^d,idims)*(2*iside-3);
683 if (aperiodb(idims)) then
684 if (neighbor_type(i^d,igrid) /= neighbor_boundary .and. &
685 .not. psb(igrid)%is_physical_boundary(2*idims-2+iside)) cycle
686 else
687 if (neighbor_type(i^d,igrid) /= neighbor_boundary) cycle
688 end if
689 !> Refresh the EoS-derived ghost fields before extrapolation; the hook
690 !> is set (in amrvac.t) only when the EoS needs it, e.g. LTE.
691 if (associated(update_eos_4_bc)) &
692 call update_eos_4_bc(ixg^ll,ixm^ll,psb(igrid)%w,psb(igrid)%x)
693 call bc_phys(iside,idims,time,qdt,psb(igrid),ixg^ll,ixb^l)
694 end do
695 end do
696
697 end subroutine fill_boundary_after_gc
698
699 !> MPI receive from sibling at same refinement level
700 subroutine bc_recv_srl(igrid,i^D)
701 integer, intent(in) :: igrid,i^D
702
703 integer :: ipe_neighbor
704
705 ipe_neighbor=neighbor(2,i^d,igrid)
706 if (ipe_neighbor/=mype) then
708 itag=(3**^nd+4**^nd)*(igrid-1)+{(i^d+1)*3**(^d-1)+}
709 call mpi_irecv(psb(igrid)%w,1,type_recv_srl(i^d), &
710 ipe_neighbor,itag,icomm,recvrequest_c_sr(irecv_c),ierrmpi)
711 if(stagger_grid) then
713 call mpi_irecv(recvbuffer_srl(ibuf_recv_srl),sizes_srl_recv_total(i^d),mpi_double_precision, &
714 ipe_neighbor,itag,icomm,recvrequest_srl(irecv_srl),ierrmpi)
716 end if
717 end if
718
719 end subroutine bc_recv_srl
720
721 !> MPI receive from fine neighbor
722 subroutine bc_recv_restrict(igrid,i^D)
723 integer, intent(in) :: igrid,i^D
724
725 integer :: ic^D,inc^D,ipe_neighbor
726
727 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
728 inc^db=2*i^db+ic^db\}
729 ipe_neighbor=neighbor_child(2,inc^d,igrid)
730 if (ipe_neighbor/=mype) then
732 itag=(3**^nd+4**^nd)*(igrid-1)+3**^nd+{inc^d*4**(^d-1)+}
733 call mpi_irecv(psb(igrid)%w,1,type_recv_r(inc^d), &
734 ipe_neighbor,itag,icomm,recvrequest_c_sr(irecv_c),ierrmpi)
735 if(stagger_grid) then
737 call mpi_irecv(recvbuffer_r(ibuf_recv_r),sizes_r_recv_total(inc^d), &
738 mpi_double_precision,ipe_neighbor,itag, &
739 icomm,recvrequest_r(irecv_r),ierrmpi)
741 end if
742 end if
743 {end do\}
744
745 end subroutine bc_recv_restrict
746
747 !> MPI send to sibling at same refinement level
748 subroutine bc_send_srl(igrid,i^D)
749 integer, intent(in) :: igrid,i^D
750
751 integer :: n_i^D,ipole,idir,ineighbor,ipe_neighbor,ixS^L
752
753 ipe_neighbor=neighbor(2,i^d,igrid)
754 if(ipe_neighbor/=mype) then
755 ineighbor=neighbor(1,i^d,igrid)
756 ipole=neighbor_pole(i^d,igrid)
757 if(ipole==0) then
758 n_i^d=-i^d;
760 itag=(3**^nd+4**^nd)*(ineighbor-1)+{(n_i^d+1)*3**(^d-1)+}
761 call mpi_isend(psb(igrid)%w,1,type_send_srl(i^d), &
762 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
763 call wait_send_batch(isend_c,flushed_send_c,sendrequest_c_sr,sendstatus_c_sr)
764 if(stagger_grid) then
765 ibuf_start=ibuf_send_srl
766 do idir=1,ndim
767 ixs^l=ixs_srl_stg_^l(idir,i^d);
768 ibuf_next=ibuf_start+sizes_srl_send_stg(idir,i^d)
769 shapes=(/sizes_srl_send_stg(idir,i^d)/)
770 sendbuffer_srl(ibuf_start:ibuf_next-1)=&
771 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
772 ibuf_start=ibuf_next
773 end do
776 mpi_double_precision, ipe_neighbor,itag,icomm,sendrequest_srl(isend_srl),ierrmpi)
777 call wait_send_batch(isend_srl,flushed_send_srl,sendrequest_srl,sendstatus_srl)
778 ibuf_send_srl=ibuf_next
779 end if
780 else
781 ixs^l=ixs_srl_^l(i^d);
782 select case (ipole)
783 {case (^d)
784 n_i^d=i^d^d%n_i^dd=-i^dd;\}
785 end select
786 if (isend_buf(ipwbuf)/=0) then
787 call mpi_wait(sendrequest_c_sr(isend_buf(ipwbuf)), &
788 sendstatus_c_sr(:,isend_buf(ipwbuf)),ierrmpi)
789 deallocate(pwbuf(ipwbuf)%w)
790 end if
791 allocate(pwbuf(ipwbuf)%w(ixs^s,nwhead:nwtail))
792 call pole_buffer(pwbuf(ipwbuf)%w,ixs^l,ixs^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
794 isend_buf(ipwbuf)=isend_c
795 itag=(3**^nd+4**^nd)*(ineighbor-1)+{(n_i^d+1)*3**(^d-1)+}
796 isizes={(ixsmax^d-ixsmin^d+1)*}*nwbc
797 call mpi_isend(pwbuf(ipwbuf)%w,isizes,mpi_double_precision, &
798 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
799 call wait_send_batch(isend_c,flushed_send_c,sendrequest_c_sr,sendstatus_c_sr)
800 ipwbuf=1+modulo(ipwbuf,npwbuf)
801 if(stagger_grid) then
802 ibuf_start=ibuf_send_srl
803 do idir=1,ndim
804 ixs^l=ixs_srl_stg_^l(idir,i^d);
805 ibuf_next=ibuf_start+sizes_srl_send_stg(idir,i^d)
806 shapes=(/sizes_srl_send_stg(idir,i^d)/)
807 sendbuffer_srl(ibuf_start:ibuf_next-1)=&
808 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
809 ibuf_start=ibuf_next
810 end do
813 mpi_double_precision, ipe_neighbor,itag,icomm,sendrequest_srl(isend_srl),ierrmpi)
814 call wait_send_batch(isend_srl,flushed_send_srl,sendrequest_srl,sendstatus_srl)
815 ibuf_send_srl=ibuf_next
816 end if
817 end if
818 end if
819
820 end subroutine bc_send_srl
821
822 !> MPI send to coarser neighbor's ghost cells
823 subroutine bc_send_restrict(igrid,i^D)
824 integer, intent(in) :: igrid,i^D
825
826 integer :: ic^D,n_inc^D,ipole,idir,ineighbor,ipe_neighbor,ixS^L
827
828 ipe_neighbor=neighbor(2,i^d,igrid)
829 if(ipe_neighbor/=mype) then
830 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
831 if({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
832 ineighbor=neighbor(1,i^d,igrid)
833 ipole=neighbor_pole(i^d,igrid)
834 if(ipole==0) then
835 n_inc^d=-2*i^d+ic^d;
837 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
838 call mpi_isend(psc(igrid)%w,1,type_send_r(i^d), &
839 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
840 call wait_send_batch(isend_c,flushed_send_c,sendrequest_c_sr,sendstatus_c_sr)
841 if(stagger_grid) then
842 ibuf_start=ibuf_send_r
843 do idir=1,ndim
844 ixs^l=ixs_r_stg_^l(idir,i^d);
845 ibuf_next=ibuf_start+sizes_r_send_stg(idir,i^d)
846 shapes=(/sizes_r_send_stg(idir,i^d)/)
847 sendbuffer_r(ibuf_start:ibuf_next-1)=&
848 reshape(psc(igrid)%ws(ixs^s,idir),shapes)
849 ibuf_start=ibuf_next
850 end do
852 call mpi_isend(sendbuffer_r(ibuf_send_r),sizes_r_send_total(i^d),&
853 mpi_double_precision,ipe_neighbor,itag, &
854 icomm,sendrequest_r(isend_r),ierrmpi)
855 call wait_send_batch(isend_r,flushed_send_r,sendrequest_r,sendstatus_r)
856 ibuf_send_r=ibuf_next
857 end if
858 else
859 ixs^l=ixs_r_^l(i^d);
860 select case (ipole)
861 {case (^d)
862 n_inc^d=2*i^d+(3-ic^d)^d%n_inc^dd=-2*i^dd+ic^dd;\}
863 end select
864 if(isend_buf(ipwbuf)/=0) then
865 call mpi_wait(sendrequest_c_sr(isend_buf(ipwbuf)), &
866 sendstatus_c_sr(:,isend_buf(ipwbuf)),ierrmpi)
867 deallocate(pwbuf(ipwbuf)%w)
868 end if
869 allocate(pwbuf(ipwbuf)%w(ixs^s,nwhead:nwtail))
870 call pole_buffer(pwbuf(ipwbuf)%w,ixs^l,ixs^l,psc(igrid)%w,ixcog^l,ixs^l,ipole)
872 isend_buf(ipwbuf)=isend_c
873 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
874 isizes={(ixsmax^d-ixsmin^d+1)*}*nwbc
875 call mpi_isend(pwbuf(ipwbuf)%w,isizes,mpi_double_precision, &
876 ipe_neighbor,itag,icomm,sendrequest_c_sr(isend_c),ierrmpi)
877 call wait_send_batch(isend_c,flushed_send_c,sendrequest_c_sr,sendstatus_c_sr)
878 ipwbuf=1+modulo(ipwbuf,npwbuf)
879 if(stagger_grid) then
880 ibuf_start=ibuf_send_r
881 do idir=1,ndim
882 ixs^l=ixs_r_stg_^l(idir,i^d);
883 ibuf_next=ibuf_start+sizes_r_send_stg(idir,i^d)
884 shapes=(/sizes_r_send_stg(idir,i^d)/)
885 sendbuffer_r(ibuf_start:ibuf_next-1)=&
886 reshape(psc(igrid)%ws(ixs^s,idir),shapes)
887 ibuf_start=ibuf_next
888 end do
890 call mpi_isend(sendbuffer_r(ibuf_send_r),sizes_r_send_total(i^d),&
891 mpi_double_precision,ipe_neighbor,itag, &
892 icomm,sendrequest_r(isend_r),ierrmpi)
893 call wait_send_batch(isend_r,flushed_send_r,sendrequest_r,sendstatus_r)
894 ibuf_send_r=ibuf_next
895 end if
896 end if
897 end if
898
899 end subroutine bc_send_restrict
900
901 !> fill same-level neighbor's ghost cells in the same processor
902 subroutine bc_fill_srl(igrid,i^D)
903 integer, intent(in) :: igrid,i^D
904
905 integer :: ineighbor,ipe_neighbor,ipole,ixS^L,ixR^L,n_i^D,idir
906
907 ipe_neighbor=neighbor(2,i^d,igrid)
908 if(ipe_neighbor==mype) then
909 ineighbor=neighbor(1,i^d,igrid)
910 ipole=neighbor_pole(i^d,igrid)
911 if(ipole==0) then
912 n_i^d=-i^d;
913 ixs^l=ixs_srl_^l(i^d);
914 ixr^l=ixr_srl_^l(n_i^d);
915 psb(ineighbor)%w(ixr^s,nwhead:nwtail)=&
916 psb(igrid)%w(ixs^s,nwhead:nwtail)
917 if(stagger_grid) then
918 do idir=1,ndim
919 ixs^l=ixs_srl_stg_^l(idir,i^d);
920 ixr^l=ixr_srl_stg_^l(idir,n_i^d);
921 psb(ineighbor)%ws(ixr^s,idir)=psb(igrid)%ws(ixs^s,idir)
922 end do
923 end if
924 else
925 ixs^l=ixs_srl_^l(i^d);
926 select case (ipole)
927 {case (^d)
928 n_i^d=i^d^d%n_i^dd=-i^dd;\}
929 end select
930 ixr^l=ixr_srl_^l(n_i^d);
931 call pole_copy(psb(ineighbor)%w,ixg^ll,ixr^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
932 if(stagger_grid) then
933 do idir=1,ndim
934 ixs^l=ixs_srl_stg_^l(idir,i^d);
935 ixr^l=ixr_srl_stg_^l(idir,n_i^d);
936 call pole_copy_stg(psb(ineighbor)%ws,ixgs^ll,ixr^l,psb(igrid)%ws,ixgs^ll,ixs^l,idir,ipole)
937 end do
938 end if
939 end if
940 end if
941
942 end subroutine bc_fill_srl
943
944 !> fill coarser neighbor's ghost cells in the same processor
945 subroutine bc_fill_restrict(igrid,i^D)
946 integer, intent(in) :: igrid,i^D
947
948 integer :: ic^D,n_inc^D,ixS^L,ixR^L,ipe_neighbor,ineighbor,ipole,idir
949
950 ipe_neighbor=neighbor(2,i^d,igrid)
951 if(ipe_neighbor==mype) then
952 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
953 if({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
954 ineighbor=neighbor(1,i^d,igrid)
955 ipole=neighbor_pole(i^d,igrid)
956 if(ipole==0) then
957 n_inc^d=-2*i^d+ic^d;
958 ixs^l=ixs_r_^l(i^d);
959 ixr^l=ixr_r_^l(n_inc^d);
960 psb(ineighbor)%w(ixr^s,nwhead:nwtail)=&
961 psc(igrid)%w(ixs^s,nwhead:nwtail)
962 if(stagger_grid) then
963 do idir=1,ndim
964 ixs^l=ixs_r_stg_^l(idir,i^d);
965 ixr^l=ixr_r_stg_^l(idir,n_inc^d);
966 psb(ineighbor)%ws(ixr^s,idir)=psc(igrid)%ws(ixs^s,idir)
967 end do
968 end if
969 else
970 ixs^l=ixs_r_^l(i^d);
971 select case (ipole)
972 {case (^d)
973 n_inc^d=2*i^d+(3-ic^d)^d%n_inc^dd=-2*i^dd+ic^dd;\}
974 end select
975 ixr^l=ixr_r_^l(n_inc^d);
976 call pole_copy(psb(ineighbor)%w,ixg^ll,ixr^l,psc(igrid)%w,ixcog^l,ixs^l,ipole)
977 if(stagger_grid) then
978 do idir=1,ndim
979 ixs^l=ixs_r_stg_^l(idir,i^d);
980 ixr^l=ixr_r_stg_^l(idir,n_inc^d);
981 !! Fill ghost cells
982 call pole_copy_stg(psb(ineighbor)%ws,ixgs^ll,ixr^l,psc(igrid)%ws,ixcogs^l,ixs^l,idir,ipole)
983 end do
984 end if
985 end if
986 end if
987
988 end subroutine bc_fill_restrict
989
990 !> fill siblings ghost cells with received data
991 subroutine bc_fill_srl_stg(igrid,i^D)
992 integer, intent(in) :: igrid,i^D
993
994 integer :: ixS^L,ixR^L,n_i^D,idir,ineighbor,ipe_neighbor,ipole
995
996 ipe_neighbor=neighbor(2,i^d,igrid)
997 if(ipe_neighbor/=mype) then
998 ineighbor=neighbor(1,i^d,igrid)
999 ipole=neighbor_pole(i^d,igrid)
1000
1001 !! Now the special treatment of the pole is done here, at the receive step
1002 if (ipole==0) then
1003 ixr^l=ixr_srl_^l(i^d);
1004 !! Unpack the buffer and fill the ghost cells
1005 n_i^d=-i^d;
1006 do idir=1,ndim
1007 ixs^l=ixs_srl_stg_^l(idir,n_i^d);
1008 ixr^l=ixr_srl_stg_^l(idir,i^d);
1009 ibuf_next=ibuf_recv_srl+sizes_srl_recv_stg(idir,i^d)
1010 psb(igrid)%ws(ixr^s,idir)=reshape(source=recvbuffer_srl(ibuf_recv_srl:ibuf_next-1),&
1011 shape=shape(psb(igrid)%ws(ixs^s,idir)))
1012 ibuf_recv_srl=ibuf_next
1013 end do
1014 else ! There is a pole
1015 select case (ipole)
1016 {case (^d)
1017 n_i^d=i^d^d%n_i^dd=-i^dd;\}
1018 end select
1019 pole_buf%ws=zero
1020 do idir=1,ndim
1021 ixr^l=ixr_srl_stg_^l(idir,i^d);
1022 ixs^l=ixs_srl_stg_^l(idir,n_i^d);
1023 ibuf_next=ibuf_recv_srl+sizes_srl_recv_stg(idir,i^d)
1024 pole_buf%ws(ixs^s,idir)=reshape(source=recvbuffer_srl(ibuf_recv_srl:ibuf_next-1),&
1025 shape=shape(psb(igrid)%ws(ixs^s,idir)))
1026 ibuf_recv_srl=ibuf_next
1027 call pole_copy_stg(psb(igrid)%ws,ixgs^ll,ixr^l,pole_buf%ws,ixgs^ll,ixs^l,idir,ipole)
1028 end do
1029 end if
1030 end if
1031
1032 end subroutine bc_fill_srl_stg
1033
1034 !> fill restricted ghost cells after receipt
1035 subroutine bc_fill_restrict_stg(igrid,i^D)
1036 integer, intent(in) :: igrid,i^D
1037
1038 integer :: ipole,ic^D,inc^D,ineighbor,ipe_neighbor,ixS^L,ixR^L,n_i^D,idir
1039
1040 ipole=neighbor_pole(i^d,igrid)
1041 if (ipole==0) then
1042 ! Loop over the children ic^D to and their neighbors inc^D
1043 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1044 inc^db=2*i^db+ic^db\}
1045 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1046 if(ipe_neighbor/=mype) then
1047 ineighbor=neighbor_child(1,inc^d,igrid)
1048 n_i^d=-i^d;
1049 !! Unpack the buffer and fill the ghost cells
1050 do idir=1,ndim
1051 ixr^l=ixr_r_stg_^l(idir,inc^d);
1052 ibuf_next=ibuf_recv_r+sizes_r_recv_stg(idir,inc^d)
1053 psb(igrid)%ws(ixr^s,idir)=reshape(source=recvbuffer_r(ibuf_recv_r:ibuf_next-1),&
1054 shape=shape(psb(igrid)%ws(ixr^s,idir)))
1055 ibuf_recv_r=ibuf_next
1056 end do
1057 end if
1058 {end do\}
1059 else !! There is a pole
1060 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1061 inc^db=2*i^db+ic^db\}
1062 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1063 if(ipe_neighbor/=mype) then
1064 ineighbor=neighbor_child(1,inc^d,igrid)
1065 select case(ipole)
1066 {case (^d)
1067 n_i^d=i^d^d%n_i^dd=-i^dd;\}
1068 end select
1069 ixr^l=ixr_r_^l(inc^d);
1070 !! Unpack the buffer and fill an auxiliary array
1071 pole_buf%ws=zero
1072 do idir=1,ndim
1073 ixs^l=ixs_r_stg_^l(idir,n_i^d);
1074 ixr^l=ixr_r_stg_^l(idir,inc^d);
1075 ibuf_next=ibuf_recv_r+sizes_r_recv_stg(idir,inc^d)
1076 pole_buf%ws(ixr^s,idir)=reshape(source=recvbuffer_r(ibuf_recv_r:ibuf_next-1),&
1077 shape=shape(psb(igrid)%ws(ixr^s,idir)))
1078 call pole_copy_stg(psb(igrid)%ws,ixgs^ll,ixr^l,pole_buf%ws,ixgs^ll,ixr^l,idir,ipole)
1079 ibuf_recv_r=ibuf_next
1080 end do
1081 end if
1082 {end do\}
1083 end if
1084
1085 end subroutine bc_fill_restrict_stg
1086
1087 !> Receive from coarse neighbor
1088 subroutine bc_recv_prolong(igrid,i^D)
1089 integer, intent(in) :: igrid,i^D
1090
1091 integer :: ic^D,ipe_neighbor,inc^D
1092
1093 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
1094 if ({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
1095
1096 ipe_neighbor=neighbor(2,i^d,igrid)
1097 if (ipe_neighbor/=mype) then
1099 inc^d=ic^d+i^d;
1100 itag=(3**^nd+4**^nd)*(igrid-1)+3**^nd+{inc^d*4**(^d-1)+}
1101 call mpi_irecv(psc(igrid)%w,1,type_recv_p(inc^d), &
1102 ipe_neighbor,itag,icomm,recvrequest_c_p(irecv_c),ierrmpi)
1103 if(stagger_grid) then
1105 call mpi_irecv(recvbuffer_p(ibuf_recv_p),sizes_p_recv_total(inc^d),&
1106 mpi_double_precision,ipe_neighbor,itag,&
1107 icomm,recvrequest_p(irecv_p),ierrmpi)
1109 end if
1110 end if
1111
1112 end subroutine bc_recv_prolong
1113
1114 !> Send to finer neighbor
1115 subroutine bc_send_prolong(igrid,i^D)
1116 integer, intent(in) :: igrid,i^D
1117
1118 integer :: ic^D,inc^D,n_i^D,n_inc^D,ineighbor,ipe_neighbor,ixS^L,ipole,idir
1119
1120 ipole=neighbor_pole(i^d,igrid)
1121
1122 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1123 inc^db=2*i^db+ic^db\}
1124 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1125 if(ipe_neighbor/=mype) then
1126 ineighbor=neighbor_child(1,inc^d,igrid)
1127 if(ipole==0) then
1128 n_i^d=-i^d;
1129 n_inc^d=ic^d+n_i^d;
1131 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
1132 call mpi_isend(psb(igrid)%w,1,type_send_p(inc^d), &
1133 ipe_neighbor,itag,icomm,sendrequest_c_p(isend_c),ierrmpi)
1134 call wait_send_batch(isend_c,flushed_send_c,sendrequest_c_p,sendstatus_c_p)
1135 if(stagger_grid) then
1136 ibuf_start=ibuf_send_p
1137 do idir=1,ndim
1138 ixs^l=ixs_p_stg_^l(idir,inc^d);
1139 ibuf_next=ibuf_start+sizes_p_send_stg(idir,inc^d)
1140 shapes=(/sizes_p_send_stg(idir,inc^d)/)
1141 sendbuffer_p(ibuf_start:ibuf_next-1)=&
1142 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
1143 ibuf_start=ibuf_next
1144 end do
1146 call mpi_isend(sendbuffer_p(ibuf_send_p),sizes_p_send_total(inc^d),&
1147 mpi_double_precision,ipe_neighbor,itag, &
1148 icomm,sendrequest_p(isend_p),ierrmpi)
1149 call wait_send_batch(isend_p,flushed_send_p,sendrequest_p,sendstatus_p)
1150 ibuf_send_p=ibuf_next
1151 end if
1152 else
1153 ixs^l=ixs_p_^l(inc^d);
1154 select case (ipole)
1155 {case (^d)
1156 n_inc^d=inc^d^d%n_inc^dd=ic^dd-i^dd;\}
1157 end select
1158 if(isend_buf(ipwbuf)/=0) then
1159 call mpi_wait(sendrequest_c_p(isend_buf(ipwbuf)), &
1160 sendstatus_c_p(:,isend_buf(ipwbuf)),ierrmpi)
1161 deallocate(pwbuf(ipwbuf)%w)
1162 end if
1163 allocate(pwbuf(ipwbuf)%w(ixs^s,nwhead:nwtail))
1164 call pole_buffer(pwbuf(ipwbuf)%w,ixs^l,ixs^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
1166 isend_buf(ipwbuf)=isend_c
1167 itag=(3**^nd+4**^nd)*(ineighbor-1)+3**^nd+{n_inc^d*4**(^d-1)+}
1168 isizes={(ixsmax^d-ixsmin^d+1)*}*nwbc
1169 call mpi_isend(pwbuf(ipwbuf)%w,isizes,mpi_double_precision, &
1170 ipe_neighbor,itag,icomm,sendrequest_c_p(isend_c),ierrmpi)
1171 call wait_send_batch(isend_c,flushed_send_c,sendrequest_c_p,sendstatus_c_p)
1172 ipwbuf=1+modulo(ipwbuf,npwbuf)
1173 if(stagger_grid) then
1174 ibuf_start=ibuf_send_p
1175 do idir=1,ndim
1176 ixs^l=ixs_p_stg_^l(idir,inc^d);
1177 ibuf_next=ibuf_start+sizes_p_send_stg(idir,inc^d)
1178 shapes=(/sizes_p_send_stg(idir,inc^d)/)
1179 sendbuffer_p(ibuf_start:ibuf_next-1)=&
1180 reshape(psb(igrid)%ws(ixs^s,idir),shapes)
1181 ibuf_start=ibuf_next
1182 end do
1184 call mpi_isend(sendbuffer_p(ibuf_send_p),sizes_p_send_total(inc^d),&
1185 mpi_double_precision,ipe_neighbor,itag, &
1186 icomm,sendrequest_p(isend_p),ierrmpi)
1187 call wait_send_batch(isend_p,flushed_send_p,sendrequest_p,sendstatus_p)
1188 ibuf_send_p=ibuf_next
1189 end if
1190 end if
1191 end if
1192 {end do\}
1193
1194 end subroutine bc_send_prolong
1195
1196 !> Send to finer neighbor
1197 subroutine bc_fill_prolong(igrid,i^D)
1198 integer, intent(in) :: igrid,i^D
1199
1200 integer :: ipe_neighbor,ineighbor,ixS^L,ixR^L,ic^D,inc^D,n_i^D,n_inc^D,ipole,idir
1201
1202 ipole=neighbor_pole(i^d,igrid)
1203
1204 if(ipole==0) then
1205 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1206 inc^db=2*i^db+ic^db\}
1207 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1208 if(ipe_neighbor==mype) then
1209 ixs^l=ixs_p_^l(inc^d);
1210 ineighbor=neighbor_child(1,inc^d,igrid)
1211 n_i^d=-i^d;
1212 n_inc^d=ic^d+n_i^d;
1213 ixr^l=ixr_p_^l(n_inc^d);
1214 psc(ineighbor)%w(ixr^s,nwhead:nwtail) &
1215 =psb(igrid)%w(ixs^s,nwhead:nwtail)
1216 if(stagger_grid) then
1217 do idir=1,ndim
1218 ixs^l=ixs_p_stg_^l(idir,inc^d);
1219 ixr^l=ixr_p_stg_^l(idir,n_inc^d);
1220 psc(ineighbor)%ws(ixr^s,idir)=psb(igrid)%ws(ixs^s,idir)
1221 end do
1222 end if
1223 end if
1224 {end do\}
1225 else
1226 {do ic^db=1+int((1-i^db)/2),2-int((1+i^db)/2)
1227 inc^db=2*i^db+ic^db\}
1228 ipe_neighbor=neighbor_child(2,inc^d,igrid)
1229 if(ipe_neighbor==mype) then
1230 ixs^l=ixs_p_^l(inc^d);
1231 ineighbor=neighbor_child(1,inc^d,igrid)
1232 select case (ipole)
1233 {case (^d)
1234 n_inc^d=inc^d^d%n_inc^dd=ic^dd-i^dd;\}
1235 end select
1236 ixr^l=ixr_p_^l(n_inc^d);
1237 call pole_copy(psc(ineighbor)%w,ixcog^l,ixr^l,psb(igrid)%w,ixg^ll,ixs^l,ipole)
1238 if(stagger_grid) then
1239 do idir=1,ndim
1240 ixs^l=ixs_p_stg_^l(idir,inc^d);
1241 ixr^l=ixr_p_stg_^l(idir,n_inc^d);
1242 call pole_copy_stg(psc(ineighbor)%ws,ixcogs^l,ixr^l,psb(igrid)%ws,ixgs^ll,ixs^l,idir,ipole)
1243 end do
1244 end if
1245 end if
1246 {end do\}
1247 end if
1248 end subroutine bc_fill_prolong
1249
1250 subroutine gc_prolong(igrid)
1251 integer, intent(in) :: igrid
1252
1253 integer :: i^D,idims,iside
1254 logical,dimension(-1:1^D&) :: NeedProlong
1255
1256 needprolong=.false.
1257 {do i^db=-1,1\}
1258 if (skip_direction([ i^d ])) cycle
1259 if (neighbor_type(i^d,igrid)==neighbor_coarse) then
1260 call bc_prolong(igrid,i^d)
1261 needprolong(i^d)=.true.
1262 end if
1263 {end do\}
1264 if(stagger_grid) then
1265 ! Ghost cell prolongation for staggered variables
1266 ! must be done in a specific order.
1267 ! First the first neighbours, which have 2 indices=0 in 3D
1268 ! or one index=0 in 2D
1269 block=>psb(igrid)
1270 do idims=1,ndim
1271 i^d=0;
1272 select case(idims)
1273 {case(^d)
1274 do i^d=-1,1,2
1275 if (needprolong(i^dd)) call bc_prolong_stg(igrid,i^dd,needprolong)
1276 end do
1277 \}
1278 end select
1279 end do
1280 ! Then the second neighbours which have 1 index=0 in 3D
1281 ! (Only in 3D)
1282 {^ifthreed
1283 i1=0;
1284 do i2=-1,1,2
1285 do i3=-1,1,2
1286 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1287 end do
1288 end do
1289 i2=0;
1290 do i3=-1,1,2
1291 do i1=-1,1,2
1292 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1293 end do
1294 end do
1295 i3=0;
1296 do i1=-1,1,2
1297 do i2=-1,1,2
1298 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1299 end do
1300 end do
1301 }
1302 ! Finally, the corners, that have no index=0
1303 {do i^d=-1,1,2\}
1304 if (needprolong(i^d)) call bc_prolong_stg(igrid,i^d,needprolong)
1305 {end do\}
1306 end if
1307 end subroutine gc_prolong
1308
1309 !> fill coarser representative with data from coarser neighbors
1310 subroutine bc_fill_prolong_stg(igrid,i^D)
1311 integer, intent(in) :: igrid,i^D
1312
1313 integer :: ipe_neighbor,ineighbor,ipole,ixR^L,ic^D,inc^D,n_inc^D,idir
1314
1315 ic^d=1+modulo(node(pig^d_,igrid)-1,2);
1316 if ({.not.(i^d==0.or.i^d==2*ic^d-3)|.or.}) return
1317
1318 ipe_neighbor=neighbor(2,i^d,igrid)
1319 if(ipe_neighbor/=mype) then
1320 ineighbor=neighbor(1,i^d,igrid)
1321 ipole=neighbor_pole(i^d,igrid)
1322
1323 if (ipole==0) then !! There is no pole
1324 inc^d=ic^d+i^d;
1325 ixr^l=ixr_p_^l(inc^d);
1326 do idir=1,ndim
1327 ixr^l=ixr_p_stg_^l(idir,inc^d);
1328 ibuf_next=ibuf_recv_p+sizes_p_recv_stg(idir,inc^d)
1329 psc(igrid)%ws(ixr^s,idir)=reshape(source=recvbuffer_p(ibuf_recv_p:ibuf_next-1),&
1330 shape=shape(psc(igrid)%ws(ixr^s,idir)))
1331 ibuf_recv_p=ibuf_next
1332 end do
1333 else !! There is a pole
1334 inc^d=ic^d+i^d;
1335 select case (ipole)
1336 {case (^d)
1337 n_inc^d=2*i^d+(3-ic^d)^d%n_inc^dd=-2*i^dd+ic^dd;\}
1338 end select
1339 !! Unpack the buffer and fill an auxiliary array
1340 pole_buf%ws=zero
1341 do idir=1,ndim
1342 ixr^l=ixr_p_stg_^l(idir,inc^d);
1343 ibuf_next=ibuf_recv_p+sizes_p_recv_stg(idir,inc^d)
1344 pole_buf%ws(ixr^s,idir)=reshape(source=recvbuffer_p(ibuf_recv_p:ibuf_next-1),&
1345 shape=shape(psc(igrid)%ws(ixr^s,idir)))
1346 call pole_copy_stg(psc(igrid)%ws,ixcogs^l,ixr^l,pole_buf%ws,ixgs^ll,ixr^l,idir,ipole)
1347 ibuf_recv_p=ibuf_next
1348 end do
1349 end if
1350 end if
1351
1352 end subroutine bc_fill_prolong_stg
1353
1354 !> do prolongation for fine blocks after receipt data from coarse neighbors
1355 subroutine bc_prolong(igrid,i^D)
1358
1359 double precision :: dxFi^D, dxCo^D, xFimin^D, xComin^D, invdxCo^D
1360 integer :: i^D,igrid
1361 integer :: ixFi^L,ixCo^L,ii^D, idims,iside,ixB^L
1362
1363 ixfi^l=ixr_srl_^l(i^d);
1364 dxfi^d=rnode(rpdx^d_,igrid);
1365 dxco^d=two*dxfi^d;
1366 invdxco^d=1.d0/dxco^d;
1367
1368 ! compute the enlarged grid lower left corner coordinates
1369 ! these are true coordinates for an equidistant grid,
1370 ! but we can temporarily also use them for getting indices
1371 ! in stretched grids
1372 xfimin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxfi^d;
1373 xcomin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxco^d;
1374
1375 if(phyboundblock(igrid).and.bcphys) then
1376 block=>psc(igrid)
1377 do idims=1,ndim
1378 ixcomin^d=int((xfimin^d+(dble(ixfimin^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1-1;
1379 ixcomax^d=int((xfimin^d+(dble(ixfimax^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1+1;
1380 {^ifthreed
1381 ! avoid using undetermined ghost cells at physical boundary edges
1382 if(idims == 1) then
1383 if(neighbor_type(-1,0,0,igrid)==neighbor_boundary .or. &
1384 neighbor_type(1,0,0,igrid)==neighbor_boundary) then
1385 if(neighbor_type(0,-1,0,igrid)==neighbor_boundary) ixcomin2=ixcommin2
1386 if(neighbor_type(0,0,-1,igrid)==neighbor_boundary) ixcomin3=ixcommin3
1387 if(neighbor_type(0,1,0,igrid)==neighbor_boundary) ixcomax2=ixcommax2
1388 if(neighbor_type(0,0,1,igrid)==neighbor_boundary) ixcomax3=ixcommax3
1389 end if
1390 else if(idims == 2) then
1391 if(neighbor_type(0,-1,0,igrid)==neighbor_boundary .or. &
1392 neighbor_type(0,1,0,igrid)==neighbor_boundary) then
1393 if(neighbor_type(0,0,-1,igrid)==neighbor_boundary) ixcomin3=ixcommin3
1394 if(neighbor_type(0,0,1,igrid)==neighbor_boundary) ixcomax3=ixcommax3
1395 end if
1396 end if
1397 }
1398 do iside=1,2
1399 ii^d=kr(^d,idims)*(2*iside-3);
1400 if(neighbor_type(ii^d,igrid)/=neighbor_boundary) cycle
1401 if(( {(iside==1.and.idims==^d.and.ixcomin^d<ixcogmin^d+nghostcells)|.or.} ) &
1402 .or.( {(iside==2.and.idims==^d.and.ixcomax^d>ixcogmax^d-nghostcells)|.or. })) then
1403 {ixbmin^d=merge(ixcogmin^d,ixcomin^d,idims==^d);}
1404 {ixbmax^d=merge(ixcogmax^d,ixcomax^d,idims==^d);}
1405 call bc_phys(iside,idims,time,0.d0,psc(igrid),ixcog^l,ixb^l)
1406 end if
1407 end do
1408 end do
1409 end if
1410
1411 if(prolongprimitive) then
1412 block=>psc(igrid)
1413 ixcomin^d=int((xfimin^d+(dble(ixfimin^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1-1;
1414 ixcomax^d=int((xfimin^d+(dble(ixfimax^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1+1;
1415 call phys_to_primitive(ixcog^l,ixco^l,psc(igrid)%w,psc(igrid)%x)
1416 end if
1417
1418 if(ghost_copy) then
1419 call interpolation_copy(igrid,ixfi^l,dxfi^d,xfimin^d,dxco^d,invdxco^d,xcomin^d)
1420 else
1421 call interpolation_linear(igrid,ixfi^l,dxfi^d,xfimin^d,dxco^d,invdxco^d,xcomin^d)
1422 end if
1423
1424 if(prolongprimitive) then
1425 block=>psc(igrid)
1426 call phys_to_conserved(ixcog^l,ixco^l,psc(igrid)%w,psc(igrid)%x)
1427 end if
1428
1429 end subroutine bc_prolong
1430
1431 subroutine bc_prolong_stg(igrid,i^D,NeedProlong)
1432 use mod_amr_fct
1433 double precision :: dxFi^D,dxCo^D,xFimin^D,xComin^D,invdxCo^D
1434 integer :: igrid,i^D
1435 integer :: ixFi^L,ixCo^L
1436 logical,dimension(-1:1^D&) :: NeedProlong
1437 logical :: fine_^Lin
1438 ! Check what is already at the desired level
1439 fine_^lin=.false.;
1440 {
1441 if(i^d>-1) fine_min^din=(.not.needprolong(i^dd-kr(^d,^dd)).and.neighbor_type(i^dd-kr(^d,^dd),igrid)/=1)
1442 if(i^d<1) fine_max^din=(.not.needprolong(i^dd+kr(^d,^dd)).and.neighbor_type(i^dd+kr(^d,^dd),igrid)/=1)
1443 \}
1444
1445 ixfi^l=ixr_srl_^l(i^d);
1446
1447 dxfi^d=rnode(rpdx^d_,igrid);
1448 dxco^d=two*dxfi^d;
1449 invdxco^d=1.d0/dxco^d;
1450
1451 xfimin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxfi^d;
1452 xcomin^d=rnode(rpxmin^d_,igrid)-dble(nghostcells)*dxco^d;
1453
1454 ! moved the physical boundary filling here, to only fill the
1455 ! part needed
1456
1457 ixcomin^d=int((xfimin^d+(dble(ixfimin^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1-1;
1458 ixcomax^d=int((xfimin^d+(dble(ixfimax^d)-half)*dxfi^d-xcomin^d)*invdxco^d)+1+1;
1459
1460 if(prolongprimitive) call phys_to_primitive(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1461
1462 call prolong_2nd_stg(psc(igrid),psb(igrid),ixco^l,ixfi^l,dxco^d,xcomin^d,dxfi^d,xfimin^d,.true.,fine_^lin)
1463
1464 if(prolongprimitive) call phys_to_conserved(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1465
1466 ! The current region has already been refined, so it does not need to be prolonged again
1467 needprolong(i^d)=.false.
1468
1469 end subroutine bc_prolong_stg
1470
1471 subroutine interpolation_linear(igrid,ixFi^L,dxFi^D,xFimin^D, &
1472 dxCo^D,invdxCo^D,xComin^D)
1474 integer, intent(in) :: igrid, ixFi^L
1475 double precision, intent(in) :: dxFi^D, xFimin^D,dxCo^D, invdxCo^D, xComin^D
1476
1477 double precision :: xCo^D, xFi^D, eta^D
1478 double precision :: slopeL, slopeR, slopeC, signC, signR
1479 double precision :: slope(1:nw,ndim)
1480 !!double precision :: local_invdxCo^D
1481 double precision :: signedfactorhalf^D
1482 integer :: ixCo^D, jxCo^D, hxCo^D, ixFi^D, ix^D, iw, idims, nwmin,nwmax
1483 !integer :: ixshift^D, icase
1484
1485 !icase=mod(nghostcells,2)
1486
1487 if(prolongprimitive) then
1488 nwmin=1
1489 nwmax=nw
1490 else
1491 nwmin=nwhead
1492 nwmax=nwtail
1493 end if
1494
1495 {do ixfi^db = ixfi^lim^db
1496 ! cell-centered coordinates of fine grid point
1497 ! here we temporarily use an equidistant grid
1498 xfi^db=xfimin^db+(dble(ixfi^db)-half)*dxfi^db
1499
1500 ! indices of coarse cell which contains the fine cell
1501 ! since we computed lower left corner earlier
1502 ! in equidistant fashion: also ok for stretched case
1503 ixco^db=int((xfi^db-xcomin^db)*invdxco^db)+1
1504
1505 ! cell-centered coordinates of coarse grid point
1506 ! here we temporarily use an equidistant grid
1507 xco^db=xcomin^db+(dble(ixco^db)-half)*dxco^db \}
1508
1509 !if(.not.slab) then
1510 ! ^D&local_invdxCo^D=1.d0/psc(igrid)%dx({ixCo^DD},^D)\
1511 !endif
1512
1513 if(slab_uniform) then
1514 ! actual cell-centered coordinates of fine grid point
1515 !!^D&xFi^D=block%x({ixFi^DD},^D)\
1516 ! actual cell-centered coordinates of coarse grid point
1517 !!^D&xCo^D=psc(igrid)%x({ixCo^DD},^D)\
1518 ! normalized distance between fine/coarse cell center
1519 ! in coarse cell: ranges from -0.5 to 0.5 in each direction
1520 ! (origin is coarse cell center)
1521 ! this is essentially +1/4 or -1/4 on cartesian mesh
1522 eta^d=(xfi^d-xco^d)*invdxco^d;
1523 else
1524 !select case(icase)
1525 ! case(0)
1526 !{! here we assume an even number of ghostcells!!!
1527 !ixshift^D=2*(mod(ixFi^D,2)-1)+1
1528 !if(ixshift^D>0.0d0)then
1529 ! ! oneven fine grid points
1530 ! eta^D=-0.5d0*(one-block%dvolume(ixFi^DD) &
1531 ! /sum(block%dvolume(ixFi^D:ixFi^D+1^D%ixFi^DD)))
1532 !else
1533 ! ! even fine grid points
1534 ! eta^D=+0.5d0*(one-block%dvolume(ixFi^DD) &
1535 ! /sum(block%dvolume(ixFi^D-1:ixFi^D^D%ixFi^DD)))
1536 !endif\}
1537 ! case(1)
1538 !{! here we assume an odd number of ghostcells!!!
1539 !ixshift^D=2*(mod(ixFi^D,2)-1)+1
1540 !if(ixshift^D>0.0d0)then
1541 ! ! oneven fine grid points
1542 ! eta^D=+0.5d0*(one-block%dvolume(ixFi^DD) &
1543 ! /sum(block%dvolume(ixFi^D-1:ixFi^D^D%ixFi^DD)))
1544 !else
1545 ! ! even fine grid points
1546 ! eta^D=-0.5d0*(one-block%dvolume(ixFi^DD) &
1547 ! /sum(block%dvolume(ixFi^D:ixFi^D+1^D%ixFi^DD)))
1548 !endif\}
1549 ! case default
1550 ! call mpistop("no such case")
1551 !end select
1552 ! the different cases for even/uneven number of ghost cells
1553 ! are automatically handled using the relative index to ixMlo
1554 ! as well as the pseudo-coordinates xFi and xCo
1555 ! these latter differ from actual cell centers when stretching is used
1556 ix^d=2*int((ixfi^d+ixmlo^d)/2)-ixmlo^d;
1557 {if(xfi^d>xco^d) then
1558 signedfactorhalf^d=0.5d0
1559 else
1560 signedfactorhalf^d=-0.5d0
1561 end if
1562 eta^d=signedfactorhalf^d*(one-psb(igrid)%dvolume(ixfi^dd) &
1563 /sum(psb(igrid)%dvolume(ix^d:ix^d+1^d%ixFi^dd))) \}
1564 !{eta^D=(xFi^D-xCo^D)*invdxCo^D &
1565 ! *two*(one-block%dvolume(ixFi^DD) &
1566 ! /sum(block%dvolume(ix^D:ix^D+1^D%ixFi^DD))) \}
1567 end if
1568
1569 do idims=1,ndim
1570 hxco^d=ixco^d-kr(^d,idims)\
1571 jxco^d=ixco^d+kr(^d,idims)\
1572
1573 do iw=nwmin,nwmax
1574 slopel=psc(igrid)%w(ixco^d,iw)-psc(igrid)%w(hxco^d,iw)
1575 sloper=psc(igrid)%w(jxco^d,iw)-psc(igrid)%w(ixco^d,iw)
1576 slopec=half*(sloper+slopel)
1577
1578 ! get limited slope
1579 signr=sign(one,sloper)
1580 signc=sign(one,slopec)
1581 !select case(prolong_limiter)
1582 !case(1)
1583 ! ! unlimit
1584 ! slope(iw,idims)=slopeC
1585 !case(2)
1586 ! ! minmod
1587 ! slope(iw,idims)=signR*max(zero,min(dabs(slopeR), &
1588 ! signR*slopeL))
1589 !case(3)
1590 ! ! woodward
1591 ! slope(iw,idims)=two*signR*max(zero,min(dabs(slopeR), &
1592 ! signR*slopeL,signR*half*slopeC))
1593 !case(4)
1594 ! ! koren
1595 ! slope(iw,idims)=signR*max(zero,min(two*signR*slopeL, &
1596 ! (dabs(slopeR)+two*slopeL*signR)*third,two*dabs(slopeR)))
1597 !case default
1598 slope(iw,idims)=signc*max(zero,min(dabs(slopec), &
1599 signc*slopel,signc*sloper))
1600 !end select
1601 end do
1602 end do
1603
1604 ! Interpolate from coarse cell using limited slopes
1605 psb(igrid)%w(ixfi^d,nwmin:nwmax)=psc(igrid)%w(ixco^d,nwmin:nwmax)+&
1606 {(slope(nwmin:nwmax,^d)*eta^d)+}
1607
1608 {end do\}
1609
1610 if(prolongprimitive) then
1611 block=>psb(igrid)
1612 call phys_to_conserved(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1613 end if
1614
1615 end subroutine interpolation_linear
1616
1617 subroutine interpolation_copy(igrid, ixFi^L,dxFi^D,xFimin^D, &
1618 dxCo^D,invdxCo^D,xComin^D)
1620 integer, intent(in) :: igrid, ixFi^L
1621 double precision, intent(in) :: dxFi^D, xFimin^D,dxCo^D, invdxCo^D, xComin^D
1622
1623 double precision :: xFi^D
1624 integer :: ixCo^D, ixFi^D, nwmin,nwmax
1625
1626 if(prolongprimitive) then
1627 nwmin=1
1628 nwmax=nw
1629 else
1630 nwmin=nwhead
1631 nwmax=nwtail
1632 end if
1633
1634 {do ixfi^db = ixfi^lim^db
1635 ! cell-centered coordinates of fine grid point
1636 xfi^db=xfimin^db+(dble(ixfi^db)-half)*dxfi^db
1637
1638 ! indices of coarse cell which contains the fine cell
1639 ! note: this also works for stretched grids
1640 ixco^db=int((xfi^db-xcomin^db)*invdxco^db)+1\}
1641
1642 ! Copy from coarse cell
1643 psb(igrid)%w(ixfi^d,nwmin:nwmax)=psc(igrid)%w(ixco^d,nwmin:nwmax)
1644
1645 {end do\}
1646
1647 if(prolongprimitive) call phys_to_conserved(ixg^ll,ixfi^l,psb(igrid)%w,psb(igrid)%x)
1648
1649 end subroutine interpolation_copy
1650
1651 subroutine pole_copy(wrecv,ixIR^L,ixR^L,wsend,ixIS^L,ixS^L,ipole)
1652
1653 integer, intent(in) :: ixIR^L,ixR^L,ixIS^L,ixS^L,ipole
1654 double precision :: wrecv(ixIR^S,1:nw), wsend(ixIS^S,1:nw)
1655
1656 integer :: iw, iside, iB
1657
1658 select case (ipole)
1659 {case (^d)
1660 iside=int((i^d+3)/2)
1661 ib=2*(^d-1)+iside
1662 do iw=nwhead,nwtail
1663 select case (typeboundary(iw,ib))
1664 case (bc_symm)
1665 wrecv(ixr^s,iw) = wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1666 case (bc_asymm)
1667 wrecv(ixr^s,iw) =-wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1668 case default
1669 call mpistop("Pole boundary condition should be symm or asymm")
1670 end select
1671 end do \}
1672 end select
1673
1674 end subroutine pole_copy
1675
1676 subroutine pole_copy_stg(wrecv,ixIR^L,ixR^L,wsend,ixIS^L,ixS^L,idirs,ipole)
1677
1678 integer, intent(in) :: ixIR^L,ixR^L,ixIS^L,ixS^L,idirs,ipole
1679
1680 double precision :: wrecv(ixIR^S,1:nws), wsend(ixIS^S,1:nws)
1681 integer :: iB, iside
1682
1683 select case (ipole)
1684 {case (^d)
1685 iside=int((i^d+3)/2)
1686 ib=2*(^d-1)+iside
1687 select case (typeboundary(iw_mag(idirs),ib))
1688 case (bc_symm)
1689 wrecv(ixr^s,idirs) = wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,idirs)
1690 case (bc_asymm)
1691 wrecv(ixr^s,idirs) =-wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,idirs)
1692 case default
1693 call mpistop("Pole boundary condition should be symm or asymm")
1694 end select
1695 \}
1696 end select
1697
1698 end subroutine pole_copy_stg
1699
1700 subroutine pole_buffer(wrecv,ixIR^L,ixR^L,wsend,ixIS^L,ixS^L,ipole)
1701
1702 integer, intent(in) :: ixIR^L,ixR^L,ixIS^L,ixS^L,ipole
1703 double precision :: wrecv(ixIR^S,nwhead:nwtail), wsend(ixIS^S,1:nw)
1704
1705 integer :: iw, iside, iB
1706
1707 select case (ipole)
1708 {case (^d)
1709 iside=int((i^d+3)/2)
1710 ib=2*(^d-1)+iside
1711 do iw=nwhead,nwtail
1712 select case (typeboundary(iw,ib))
1713 case (bc_symm)
1714 wrecv(ixr^s,iw) = wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1715 case (bc_asymm)
1716 wrecv(ixr^s,iw) =-wsend(ixsmax^d:ixsmin^d:-1^d%ixS^s,iw)
1717 case default
1718 call mpistop("Pole boundary condition should be symm or asymm")
1719 end select
1720 end do \}
1721 end select
1722
1723 end subroutine pole_buffer
1724
1725 end subroutine getbc
1726
1727end module mod_ghostcells_update
subroutine waitall_limited(nrequest, requests, statuses)
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