Line data Source code
1 : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 :
3 : module ice_boundary
4 :
5 : ! This module contains data types and routines for updating halo
6 : ! regions (ghost cells) using MPI calls
7 : !
8 : ! 2007-07-19: Phil Jones, Yoshi Yoshida, John Dennis
9 : ! new naming conventions, optimizations during
10 : ! initialization, true multi-dimensional updates
11 : ! (rather than serial call to two-dimensional updates),
12 : ! fixes for non-existent blocks
13 : ! 2008-01-28: Elizabeth Hunke replaced old routines with new POP
14 : ! infrastructure
15 : !
16 : !-----------------------------------------------------------------------
17 : !
18 : ! Some notes on tripole, A-H below are gridpoints at i = 1:nx_global
19 : ! where nx_global=8. The schematics below show the general layout of the center
20 : ! points on the tripole fold. More complex pictures are needed to show
21 : ! relative orientation and offsets of east, north, and northeast points
22 : ! across the fold. See also appendix E of the NEMO_manual,
23 : ! https://zenodo.org/record/6334656#.YiYirhPMLXQ. Note the NFtype=T
24 : ! is the tripole u-fold grid with T-grid=center, U-grid=east, V-grid=north,
25 : ! and F-grid=northeast points in CICE. NFtype=F is similar to tripoleT
26 : ! except for the treatment of the poles. The CICE implementation also
27 : ! averages all degenerate points, NEMO's strategy seems to be to copy
28 : ! data from one side of the tripole to the other for degenerate points.
29 : !
30 : ! tripole: u-fold, fold is on north edge of ny_global
31 : ! north and northeast points on the fold are degenerate and averaged
32 : ! A,H,D,and E are pole points
33 : !
34 : ! ny_global+2 H G F E D C B A @ny_global-1
35 : ! ny_global+1 H G F E D C B A @ny_global
36 : ! ny_global A B C D E F G H
37 : ! ny_global-1 A B C D E F G H
38 : !
39 : ! tripoleT: t-fold, fold is thru center of ny_global
40 : ! center and east points at ny_global are degenerate and averaged
41 : ! north and northeast point at ny_global are not prognostic, they are halos
42 : ! A and E are pole points
43 : !
44 : ! ny_global+2 H G F E D C B A @ny_global-2
45 : ! ny_global+1 H G F E D C B A @ny_global-1
46 : ! ny_global A BH CG DF E FD GC HB A
47 : ! ny_global-1 A B C D E F G H
48 : ! ny_global-2 A B C D E F G H
49 : !
50 : !-----------------------------------------------------------------------
51 :
52 :
53 : use mpi ! MPI Fortran module
54 : use ice_kinds_mod
55 : use ice_communicate, only: my_task, mpiR4, mpiR8, mpitagHalo
56 : use ice_constants, only: field_type_scalar, &
57 : field_type_vector, field_type_angle, & ! LCOV_EXCL_LINE
58 : field_type_unknown, field_type_noupdate, & ! LCOV_EXCL_LINE
59 : field_loc_center, field_loc_NEcorner, & ! LCOV_EXCL_LINE
60 : field_loc_Nface, field_loc_Eface, & ! LCOV_EXCL_LINE
61 : field_loc_unknown, field_loc_noupdate
62 : use ice_global_reductions, only: global_maxval
63 : use ice_exit, only: abort_ice
64 : use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
65 :
66 : use ice_blocks, only: nx_block, ny_block, nghost, &
67 : nblocks_tot, ice_blocksNorth, & ! LCOV_EXCL_LINE
68 : ice_blocksSouth, ice_blocksEast, ice_blocksWest, & ! LCOV_EXCL_LINE
69 : ice_blocksEast2, ice_blocksWest2, & ! LCOV_EXCL_LINE
70 : ice_blocksNorthEast, ice_blocksNorthWest, & ! LCOV_EXCL_LINE
71 : ice_blocksEastNorthEast, ice_blocksWestNorthWest, & ! LCOV_EXCL_LINE
72 : ice_blocksSouthEast, ice_blocksSouthWest, & ! LCOV_EXCL_LINE
73 : ice_blocksGetNbrID, get_block_parameter
74 : use ice_distribution, only: distrb, &
75 : ice_distributionGetBlockLoc, ice_distributionGet
76 :
77 : implicit none
78 : private
79 :
80 : type, public :: ice_halo
81 : integer (int_kind) :: &
82 : communicator, &! communicator to use for update messages ! LCOV_EXCL_LINE
83 : numLocalBlocks, &! number of local blocks, needed for halo fill ! LCOV_EXCL_LINE
84 : numMsgSend, &! number of messages to send halo update ! LCOV_EXCL_LINE
85 : numMsgRecv, &! number of messages to recv halo update ! LCOV_EXCL_LINE
86 : numLocalCopies, &! num local copies for halo update ! LCOV_EXCL_LINE
87 : tripoleRows ! number of rows in tripole buffer
88 :
89 : logical (log_kind) :: &
90 : tripoleTFlag ! NS boundary is a tripole T-fold
91 :
92 : integer (int_kind), dimension(:), pointer :: &
93 : blockGlobalID, &! list of local block global IDs, needed for halo fill ! LCOV_EXCL_LINE
94 : recvTask, &! task from which to recv each msg ! LCOV_EXCL_LINE
95 : sendTask, &! task to which to send each msg ! LCOV_EXCL_LINE
96 : sizeSend, &! size of each sent message ! LCOV_EXCL_LINE
97 : sizeRecv, &! size of each recvd message ! LCOV_EXCL_LINE
98 : tripSend, &! send msg tripole flag, 0=non-zipper block ! LCOV_EXCL_LINE
99 : tripRecv ! recv msg tripole flag, for masked halos
100 :
101 : integer (int_kind), dimension(:,:), pointer :: &
102 : srcLocalAddr, &! src addresses for each local copy ! LCOV_EXCL_LINE
103 : dstLocalAddr ! dst addresses for each local copy
104 :
105 : integer (int_kind), dimension(:,:,:), pointer :: &
106 : sendAddr, &! src addresses for each sent message ! LCOV_EXCL_LINE
107 : recvAddr ! dst addresses for each recvd message
108 :
109 : end type
110 :
111 : public :: ice_HaloCreate, &
112 : ice_HaloMask, & ! LCOV_EXCL_LINE
113 : ice_HaloUpdate, & ! LCOV_EXCL_LINE
114 : ice_HaloUpdate_stress, & ! LCOV_EXCL_LINE
115 : ice_HaloExtrapolate, & ! LCOV_EXCL_LINE
116 : ice_HaloDestroy, & ! LCOV_EXCL_LINE
117 : primary_grid_lengths_global_ext
118 :
119 : interface ice_HaloUpdate ! generic interface
120 : module procedure ice_HaloUpdate2DR8, &
121 : ice_HaloUpdate2DR4, & ! LCOV_EXCL_LINE
122 : ice_HaloUpdate2DI4, & ! LCOV_EXCL_LINE
123 : ice_HaloUpdate2DL1, & ! LCOV_EXCL_LINE
124 : ice_HaloUpdate3DR8, & ! LCOV_EXCL_LINE
125 : ice_HaloUpdate3DR4, & ! LCOV_EXCL_LINE
126 : ice_HaloUpdate3DI4, & ! LCOV_EXCL_LINE
127 : ice_HaloUpdate4DR8, & ! LCOV_EXCL_LINE
128 : ice_HaloUpdate4DR4, & ! LCOV_EXCL_LINE
129 : ice_HaloUpdate4DI4
130 : end interface
131 :
132 : interface ice_HaloExtrapolate ! generic interface
133 : module procedure ice_HaloExtrapolate2DR8 !, &
134 : ! ice_HaloExtrapolate2DR4, & ! not yet ! LCOV_EXCL_LINE
135 : ! ice_HaloExtrapolate2DI4, & ! implemented ! LCOV_EXCL_LINE
136 : end interface
137 :
138 : !-----------------------------------------------------------------------
139 : !
140 : ! to prevent frequent allocate-deallocate for 2d halo updates, create
141 : ! a static 2d buffer to be allocated once at creation. if future
142 : ! creation needs larger buffer, resize during the creation.
143 : !
144 : !-----------------------------------------------------------------------
145 :
146 : integer (int_kind), public :: &
147 : bufSizeSend, &! max buffer size for send messages ! LCOV_EXCL_LINE
148 : bufSizeRecv ! max buffer size for recv messages
149 :
150 : integer (int_kind), dimension(:,:), allocatable, public :: &
151 : bufSendI4, &! buffer for use to send in 2D i4 halo updates ! LCOV_EXCL_LINE
152 : bufRecvI4 ! buffer for use to recv in 2D i4 halo updates
153 :
154 : real (real_kind), dimension(:,:), allocatable, public :: &
155 : bufSendR4, &! buffer for use to send in 2D r4 halo updates ! LCOV_EXCL_LINE
156 : bufRecvR4 ! buffer for use to recv in 2D r4 halo updates
157 :
158 : real (dbl_kind), dimension(:,:), allocatable, public :: &
159 : bufSendR8, &! buffer for use to send in 2D r8 halo updates ! LCOV_EXCL_LINE
160 : bufRecvR8 ! buffer for use to recv in 2D r8 halo updates
161 :
162 : !-----------------------------------------------------------------------
163 : !
164 : ! global buffers for tripole boundary
165 : !
166 : !-----------------------------------------------------------------------
167 :
168 : integer (int_kind), dimension(:,:), allocatable, public :: &
169 : bufTripoleI4
170 :
171 : real (real_kind), dimension(:,:), allocatable, public :: &
172 : bufTripoleR4
173 :
174 : real (dbl_kind), dimension(:,:), allocatable, public :: &
175 : bufTripoleR8
176 :
177 : !***********************************************************************
178 :
179 : contains
180 :
181 : !***********************************************************************
182 :
183 36 : function ice_HaloCreate(dist, nsBoundaryType, ewBoundaryType, &
184 : nxGlobal) result(halo)
185 :
186 : ! This routine creates a halo type with info necessary for
187 : ! performing a halo (ghost cell) update. This info is computed
188 : ! based on the input block distribution.
189 :
190 : type (distrb), intent(in) :: &
191 : dist ! distribution of blocks across procs
192 :
193 : character (*), intent(in) :: &
194 : nsBoundaryType, &! type of boundary to use in logical ns dir ! LCOV_EXCL_LINE
195 : ewBoundaryType ! type of boundary to use in logical ew dir
196 :
197 : integer (int_kind), intent(in) :: &
198 : nxGlobal ! global grid extent for tripole grids
199 :
200 : type (ice_halo) :: &
201 : halo ! a new halo type with info for halo updates
202 :
203 : !-----------------------------------------------------------------------
204 : !
205 : ! local variables
206 : !
207 : !-----------------------------------------------------------------------
208 :
209 : integer (int_kind) :: &
210 : istat, &! allocate status flag ! LCOV_EXCL_LINE
211 : numProcs, &! num of processors involved ! LCOV_EXCL_LINE
212 : communicator, &! communicator for message passing ! LCOV_EXCL_LINE
213 : iblock, &! block counter ! LCOV_EXCL_LINE
214 : eastBlock, westBlock, &! block id east, west neighbors ! LCOV_EXCL_LINE
215 : northBlock, southBlock, &! block id north, south neighbors ! LCOV_EXCL_LINE
216 : neBlock, nwBlock, &! block id northeast, northwest nbrs ! LCOV_EXCL_LINE
217 : seBlock, swBlock, &! block id southeast, southwest nbrs ! LCOV_EXCL_LINE
218 : srcProc, dstProc, &! source, dest processor locations ! LCOV_EXCL_LINE
219 : srcLocalID, dstLocalID, &! local block index of src,dst blocks ! LCOV_EXCL_LINE
220 : maxTmp, &! temp for global maxval ! LCOV_EXCL_LINE
221 : blockSizeX, &! size of default physical domain in X ! LCOV_EXCL_LINE
222 : blockSizeY, &! size of default physical domain in Y ! LCOV_EXCL_LINE
223 : maxSizeSend, maxSizeRecv, &! max buffer sizes ! LCOV_EXCL_LINE
224 : numMsgSend, numMsgRecv, &! number of messages for this halo ! LCOV_EXCL_LINE
225 : eastMsgSize, westMsgSize, &! nominal sizes for e-w msgs ! LCOV_EXCL_LINE
226 : northMsgSize, southMsgSize, &! nominal sizes for n-s msgs ! LCOV_EXCL_LINE
227 : tripoleMsgSize, &! size for tripole messages ! LCOV_EXCL_LINE
228 : tripoleMsgSizeOut, &! size for tripole messages ! LCOV_EXCL_LINE
229 : tripoleRows, &! number of rows in tripole buffer ! LCOV_EXCL_LINE
230 : cornerMsgSize, msgSize ! nominal size for corner msg
231 :
232 : integer (int_kind), dimension(:), allocatable :: &
233 36 : sendCount, recvCount ! count number of words to each proc
234 :
235 : logical (log_kind) :: &
236 : resize, &! flag for resizing buffers ! LCOV_EXCL_LINE
237 : tripoleBlock, &! flag for identifying north tripole blocks ! LCOV_EXCL_LINE
238 : tripoleTFlag ! flag for processing tripole buffer as T-fold
239 :
240 : character(len=*), parameter :: subname = '(ice_HaloCreate)'
241 :
242 : !-----------------------------------------------------------------------
243 : !
244 : ! Initialize some useful variables and return if this task not
245 : ! in the current distribution.
246 : !
247 : !-----------------------------------------------------------------------
248 :
249 : call ice_distributionGet(dist, &
250 : nprocs = numProcs, & ! LCOV_EXCL_LINE
251 36 : communicator = communicator)
252 :
253 36 : if (my_task >= numProcs) return
254 :
255 36 : halo%communicator = communicator
256 :
257 36 : blockSizeX = nx_block - 2*nghost
258 36 : blockSizeY = ny_block - 2*nghost
259 36 : eastMsgSize = nghost*blockSizeY
260 36 : westMsgSize = nghost*blockSizeY
261 36 : southMsgSize = nghost*blockSizeX
262 36 : northMsgSize = nghost*blockSizeX
263 36 : cornerMsgSize = nghost*nghost
264 36 : tripoleRows = nghost+1
265 :
266 : !*** store some block info to fill haloes properly
267 36 : call ice_distributionGet(dist, numLocalBlocks=halo%numLocalBlocks)
268 36 : allocate(halo%blockGlobalID(halo%numLocalBlocks))
269 36 : if (halo%numLocalBlocks > 0) then
270 36 : call ice_distributionGet(dist, blockGlobalID=halo%blockGlobalID)
271 : endif
272 :
273 36 : if (nsBoundaryType == 'tripole' .or. nsBoundaryType == 'tripoleT') then
274 0 : tripoleTFlag = (nsBoundaryType == 'tripoleT')
275 0 : if (tripoleTflag) tripoleRows = tripoleRows+1
276 :
277 : !*** allocate tripole message buffers if not already done
278 :
279 0 : if (.not. allocated(bufTripoleR8)) then
280 : allocate (bufTripoleI4(nxGlobal, tripoleRows), &
281 : bufTripoleR4(nxGlobal, tripoleRows), & ! LCOV_EXCL_LINE
282 : bufTripoleR8(nxGlobal, tripoleRows), & ! LCOV_EXCL_LINE
283 0 : stat=istat)
284 :
285 0 : if (istat > 0) then
286 0 : call abort_ice(subname//'ERROR: allocating tripole buffers')
287 0 : return
288 : endif
289 : endif
290 :
291 : else
292 36 : tripoleTFlag = .false.
293 : endif
294 36 : halo%tripoleTFlag = tripoleTFlag
295 36 : halo%tripoleRows = tripoleRows
296 36 : tripoleMsgSize = tripoleRows*blockSizeX
297 36 : tripoleMsgSizeOut = tripoleRows*nx_block
298 :
299 : !-----------------------------------------------------------------------
300 : !
301 : ! Count the number of messages to send/recv from each processor
302 : ! and number of words in each message. These quantities are
303 : ! necessary for allocating future arrays.
304 : !
305 : !-----------------------------------------------------------------------
306 :
307 36 : allocate (sendCount(numProcs), recvCount(numProcs), stat=istat)
308 :
309 36 : if (istat > 0) then
310 0 : call abort_ice(subname//'ERROR: allocating count arrays')
311 0 : return
312 : endif
313 :
314 276 : sendCount = 0
315 276 : recvCount = 0
316 :
317 1124 : msgCountLoop: do iblock=1,nblocks_tot
318 :
319 : call ice_distributionGetBlockLoc(dist, iblock, srcProc, &
320 1088 : srcLocalID)
321 :
322 : !*** find north neighbor block and add to message count
323 : !*** also set tripole block flag for later special cases
324 :
325 : northBlock = ice_blocksGetNbrID(iblock, ice_blocksNorth, &
326 1088 : ewBoundaryType, nsBoundaryType)
327 1088 : if (northBlock > 0) then
328 816 : tripoleBlock = .false.
329 816 : msgSize = northMsgSize
330 : call ice_distributionGetBlockLoc(dist, northBlock, dstProc, &
331 816 : dstLocalID)
332 272 : else if (northBlock < 0) then ! tripole north row, count block
333 0 : tripoleBlock = .true.
334 0 : msgSize = tripoleMsgSize
335 : call ice_distributionGetBlockLoc(dist, abs(northBlock), &
336 0 : dstProc, dstLocalID)
337 : else
338 272 : tripoleBlock = .false.
339 272 : msgSize = northMsgSize
340 272 : dstProc = 0
341 272 : dstLocalID = 0
342 : endif
343 :
344 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
345 1088 : srcProc, dstProc, msgSize)
346 :
347 : !*** if a tripole boundary block, also create a local
348 : !*** message into and out of tripole buffer
349 :
350 1088 : if (tripoleBlock) then
351 : !*** copy out of tripole buffer - includes halo
352 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
353 : srcProc, srcProc, & ! LCOV_EXCL_LINE
354 0 : tripoleMsgSizeOut)
355 :
356 : !*** copy in only required if dstProc not same as srcProc
357 0 : if (dstProc /= srcProc) then
358 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
359 : srcProc, srcProc, & ! LCOV_EXCL_LINE
360 0 : msgSize)
361 : endif
362 : endif
363 :
364 : !*** find south neighbor block and add to message count
365 :
366 : southBlock = ice_blocksGetNbrID(iblock, ice_blocksSouth, &
367 1088 : ewBoundaryType, nsBoundaryType)
368 :
369 1088 : if (southBlock > 0) then
370 : call ice_distributionGetBlockLoc(dist, southBlock, dstProc, &
371 816 : dstLocalID)
372 : else
373 272 : dstProc = 0
374 272 : dstLocalID = 0
375 : endif
376 :
377 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
378 1088 : srcProc, dstProc, southMsgSize)
379 :
380 : !*** find east neighbor block and add to message count
381 :
382 : eastBlock = ice_blocksGetNbrID(iblock, ice_blocksEast, &
383 1088 : ewBoundaryType, nsBoundaryType)
384 :
385 1088 : if (eastBlock > 0) then
386 : call ice_distributionGetBlockLoc(dist, eastBlock, dstProc, &
387 1088 : dstLocalID)
388 : else
389 0 : dstProc = 0
390 0 : dstLocalID = 0
391 : endif
392 :
393 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
394 1088 : srcProc, dstProc, eastMsgSize)
395 :
396 : !*** if a tripole boundary block, non-local east neighbor
397 : !*** needs a chunk of the north boundary, so add a message
398 : !*** for that
399 :
400 1088 : if (tripoleBlock .and. dstProc /= srcProc) then
401 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
402 0 : srcProc, dstProc, tripoleMsgSize)
403 : endif
404 :
405 : !*** find west neighbor block and add to message count
406 :
407 : westBlock = ice_blocksGetNbrID(iblock, ice_blocksWest, &
408 1088 : ewBoundaryType, nsBoundaryType)
409 :
410 1088 : if (westBlock > 0) then
411 : call ice_distributionGetBlockLoc(dist, westBlock, dstProc, &
412 1088 : dstLocalID)
413 : else
414 0 : dstProc = 0
415 0 : dstLocalID = 0
416 : endif
417 :
418 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
419 1088 : srcProc, dstProc, westMsgSize)
420 :
421 : !*** if a tripole boundary block, non-local west neighbor
422 : !*** needs a chunk of the north boundary, so add a message
423 : !*** for that
424 :
425 1088 : if (tripoleBlock .and. dstProc /= srcProc) then
426 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
427 0 : srcProc, dstProc, tripoleMsgSize)
428 : endif
429 :
430 : !*** find northeast neighbor block and add to message count
431 :
432 : neBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthEast, &
433 1088 : ewBoundaryType, nsBoundaryType)
434 :
435 1088 : if (neBlock > 0) then
436 816 : msgSize = cornerMsgSize ! normal corner message
437 :
438 : call ice_distributionGetBlockLoc(dist, neBlock, dstProc, &
439 816 : dstLocalID)
440 :
441 272 : else if (neBlock < 0) then ! tripole north row
442 0 : msgSize = tripoleMsgSize ! tripole needs whole top row of block
443 :
444 : call ice_distributionGetBlockLoc(dist, abs(neBlock), dstProc, &
445 0 : dstLocalID)
446 : else
447 272 : dstProc = 0
448 272 : dstLocalID = 0
449 : endif
450 :
451 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
452 1088 : srcProc, dstProc, msgSize)
453 :
454 : !*** find northwest neighbor block and add to message count
455 :
456 : nwBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthWest, &
457 1088 : ewBoundaryType, nsBoundaryType)
458 :
459 1088 : if (nwBlock > 0) then
460 816 : msgSize = cornerMsgSize ! normal NE corner update
461 :
462 : call ice_distributionGetBlockLoc(dist, nwBlock, dstProc, &
463 816 : dstLocalID)
464 :
465 272 : else if (nwBlock < 0) then ! tripole north row, count block
466 0 : msgSize = tripoleMsgSize ! tripole NE corner update - entire row needed
467 :
468 : call ice_distributionGetBlockLoc(dist, abs(nwBlock), dstProc, &
469 0 : dstLocalID)
470 :
471 : else
472 272 : dstProc = 0
473 272 : dstLocalID = 0
474 : endif
475 :
476 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
477 1088 : srcProc, dstProc, msgSize)
478 :
479 : !*** find southeast neighbor block and add to message count
480 :
481 : seBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthEast, &
482 1088 : ewBoundaryType, nsBoundaryType)
483 :
484 1088 : if (seBlock > 0) then
485 : call ice_distributionGetBlockLoc(dist, seBlock, dstProc, &
486 816 : dstLocalID)
487 : else
488 272 : dstProc = 0
489 272 : dstLocalID = 0
490 : endif
491 :
492 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
493 1088 : srcProc, dstProc, cornerMsgSize)
494 :
495 : !*** find southwest neighbor block and add to message count
496 :
497 : swBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthWest, &
498 1088 : ewBoundaryType, nsBoundaryType)
499 :
500 1088 : if (swBlock > 0) then
501 : call ice_distributionGetBlockLoc(dist, swBlock, dstProc, &
502 816 : dstLocalID)
503 : else
504 272 : dstProc = 0
505 272 : dstLocalID = 0
506 : endif
507 :
508 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
509 1088 : srcProc, dstProc, cornerMsgSize)
510 :
511 : !*** for tripole grids with padded domain, padding will
512 : !*** prevent tripole buffer from getting all the info
513 : !*** it needs - must extend footprint at top boundary
514 :
515 1088 : if (tripoleBlock .and. & !tripole
516 1124 : mod(nxGlobal,blockSizeX) /= 0) then !padding
517 :
518 : !*** find east2 neighbor block and add to message count
519 :
520 : eastBlock = ice_blocksGetNbrID(iBlock, ice_blocksEast2, &
521 0 : ewBoundaryType, nsBoundaryType)
522 :
523 0 : if (eastBlock > 0) then
524 : call ice_distributionGetBlockLoc(dist, eastBlock, dstProc, &
525 0 : dstLocalID)
526 : else
527 0 : dstProc = 0
528 0 : dstLocalID = 0
529 : endif
530 :
531 0 : if (dstProc /= srcProc) then
532 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
533 0 : srcProc, dstProc, tripoleMsgSize)
534 : endif
535 :
536 : !*** find EastNorthEast neighbor block and add to message count
537 :
538 : neBlock = ice_blocksGetNbrID(iBlock, ice_blocksEastNorthEast, &
539 0 : ewBoundaryType, nsBoundaryType)
540 :
541 0 : if (neBlock < 0) then ! tripole north row
542 0 : msgSize = tripoleMsgSize ! tripole needs whole top row of block
543 :
544 : call ice_distributionGetBlockLoc(dist, abs(neBlock), dstProc, &
545 0 : dstLocalID)
546 : else
547 0 : dstProc = 0
548 0 : dstLocalID = 0
549 : endif
550 :
551 0 : if (dstProc /= srcProc) then
552 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
553 0 : srcProc, dstProc, msgSize)
554 : endif
555 :
556 : !*** find west2 neighbor block and add to message count
557 :
558 : westBlock = ice_blocksGetNbrID(iBlock, ice_blocksWest2, &
559 0 : ewBoundaryType, nsBoundaryType)
560 :
561 0 : if (westBlock > 0) then
562 : call ice_distributionGetBlockLoc(dist, westBlock, dstProc, &
563 0 : dstLocalID)
564 : else
565 0 : dstProc = 0
566 0 : dstLocalID = 0
567 : endif
568 :
569 0 : if (dstProc /= srcProc) then
570 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
571 0 : srcProc, dstProc, tripoleMsgSize)
572 : endif
573 :
574 : !*** find WestNorthWest neighbor block and add to message count
575 :
576 : nwBlock = ice_blocksGetNbrID(iBlock, ice_blocksWestNorthWest, &
577 0 : ewBoundaryType, nsBoundaryType)
578 :
579 0 : if (nwBlock < 0) then ! tripole north row
580 0 : msgSize = tripoleMsgSize ! tripole needs whole top row of block
581 :
582 : call ice_distributionGetBlockLoc(dist, abs(nwBlock), dstProc, &
583 0 : dstLocalID)
584 : else
585 0 : dstProc = 0
586 0 : dstLocalID = 0
587 : endif
588 :
589 0 : if (dstProc /= srcProc) then
590 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
591 0 : srcProc, dstProc, msgSize)
592 : endif
593 :
594 : endif
595 :
596 : end do msgCountLoop
597 :
598 : !-----------------------------------------------------------------------
599 : !
600 : ! if messages are received from the same processor, the message is
601 : ! actually a local copy - count them and reset to zero
602 : !
603 : !-----------------------------------------------------------------------
604 :
605 36 : halo%numLocalCopies = recvCount(my_task+1)
606 :
607 36 : sendCount(my_task+1) = 0
608 36 : recvCount(my_task+1) = 0
609 :
610 : !-----------------------------------------------------------------------
611 : !
612 : ! now count the number of actual messages to be sent and received
613 : !
614 : !-----------------------------------------------------------------------
615 :
616 276 : numMsgSend = count(sendCount /= 0)
617 276 : numMsgRecv = count(recvCount /= 0)
618 36 : halo%numMsgSend = numMsgSend
619 36 : halo%numMsgRecv = numMsgRecv
620 :
621 : !-----------------------------------------------------------------------
622 : !
623 : ! allocate buffers for 2-d halo updates to save time later
624 : ! if the buffers are already allocated by previous create call,
625 : ! check to see if they need to be re-sized
626 : !
627 : !-----------------------------------------------------------------------
628 :
629 276 : maxTmp = maxval(sendCount)
630 36 : maxSizeSend = global_maxval(maxTmp, dist)
631 276 : maxTmp = maxval(recvCount)
632 36 : maxSizeRecv = global_maxval(maxTmp, dist)
633 :
634 36 : if (.not. allocated(bufSendR8)) then
635 :
636 36 : bufSizeSend = maxSizeSend
637 36 : bufSizeRecv = maxSizeRecv
638 :
639 : allocate(bufSendI4(bufSizeSend, numMsgSend), &
640 : bufRecvI4(bufSizeRecv, numMsgRecv), & ! LCOV_EXCL_LINE
641 : bufSendR4(bufSizeSend, numMsgSend), & ! LCOV_EXCL_LINE
642 : bufRecvR4(bufSizeRecv, numMsgRecv), & ! LCOV_EXCL_LINE
643 : bufSendR8(bufSizeSend, numMsgSend), & ! LCOV_EXCL_LINE
644 36 : bufRecvR8(bufSizeRecv, numMsgRecv), stat=istat)
645 :
646 36 : if (istat > 0) then
647 0 : call abort_ice(subname//'ERROR: allocating 2d buffers')
648 0 : return
649 : endif
650 :
651 : else
652 :
653 0 : resize = .false.
654 :
655 0 : if (maxSizeSend > bufSizeSend) then
656 0 : resize = .true.
657 0 : bufSizeSend = maxSizeSend
658 : endif
659 0 : if (maxSizeRecv > bufSizeRecv) then
660 0 : resize = .true.
661 0 : bufSizeRecv = maxSizeRecv
662 : endif
663 :
664 0 : if (numMsgSend > size(bufSendR8,dim=2)) resize = .true.
665 0 : if (numMsgRecv > size(bufRecvR8,dim=2)) resize = .true.
666 :
667 0 : if (resize) then
668 : deallocate(bufSendI4, bufRecvI4, bufSendR4, &
669 0 : bufRecvR4, bufSendR8, bufRecvR8, stat=istat)
670 :
671 0 : if (istat > 0) then
672 0 : call abort_ice(subname//'ERROR: deallocating 2d buffers')
673 0 : return
674 : endif
675 :
676 : allocate(bufSendI4(bufSizeSend, numMsgSend), &
677 : bufRecvI4(bufSizeRecv, numMsgRecv), & ! LCOV_EXCL_LINE
678 : bufSendR4(bufSizeSend, numMsgSend), & ! LCOV_EXCL_LINE
679 : bufRecvR4(bufSizeRecv, numMsgRecv), & ! LCOV_EXCL_LINE
680 : bufSendR8(bufSizeSend, numMsgSend), & ! LCOV_EXCL_LINE
681 0 : bufRecvR8(bufSizeRecv, numMsgRecv), stat=istat)
682 :
683 0 : if (istat > 0) then
684 0 : call abort_ice(subname//'ERROR: reallocating 2d buffers')
685 0 : return
686 : endif
687 :
688 : endif
689 :
690 : endif
691 :
692 : !-----------------------------------------------------------------------
693 : !
694 : ! allocate arrays for message information and initialize
695 : !
696 : !-----------------------------------------------------------------------
697 :
698 : allocate(halo%sendTask(numMsgSend), &
699 : halo%recvTask(numMsgRecv), & ! LCOV_EXCL_LINE
700 : halo%sizeSend(numMsgSend), & ! LCOV_EXCL_LINE
701 : halo%sizeRecv(numMsgRecv), & ! LCOV_EXCL_LINE
702 : halo%tripSend(numMsgSend), & ! LCOV_EXCL_LINE
703 : halo%tripRecv(numMsgRecv), & ! LCOV_EXCL_LINE
704 : halo%sendAddr(3,bufSizeSend,numMsgSend), & ! LCOV_EXCL_LINE
705 : halo%recvAddr(3,bufSizeRecv,numMsgRecv), & ! LCOV_EXCL_LINE
706 : halo%srcLocalAddr(3,halo%numLocalCopies), & ! LCOV_EXCL_LINE
707 : halo%dstLocalAddr(3,halo%numLocalCopies), & ! LCOV_EXCL_LINE
708 36 : stat = istat)
709 :
710 36 : if (istat > 0) then
711 0 : call abort_ice(subname//'ERROR: allocating halo message info arrays')
712 0 : return
713 : endif
714 :
715 208 : halo%sendTask = 0
716 208 : halo%recvTask = 0
717 208 : halo%sizeSend = 0
718 208 : halo%sizeRecv = 0
719 208 : halo%tripSend = 0
720 208 : halo%tripRecv = 0
721 103568 : halo%sendAddr = 0
722 103568 : halo%recvAddr = 0
723 14980 : halo%srcLocalAddr = 0
724 14980 : halo%dstLocalAddr = 0
725 :
726 36 : deallocate(sendCount, recvCount, stat=istat)
727 :
728 36 : if (istat > 0) then
729 0 : call abort_ice(subname//'ERROR: deallocating count arrays')
730 0 : return
731 : endif
732 :
733 : !-----------------------------------------------------------------------
734 : !
735 : ! repeat loop through blocks but this time, determine all the
736 : ! required message information for each message or local copy
737 : !
738 : !-----------------------------------------------------------------------
739 :
740 : !*** reset halo scalars to use as counters
741 :
742 36 : halo%numMsgSend = 0
743 36 : halo%numMsgRecv = 0
744 36 : halo%numLocalCopies = 0
745 :
746 1124 : msgConfigLoop: do iblock=1,nblocks_tot
747 :
748 : call ice_distributionGetBlockLoc(dist, iblock, srcProc, &
749 1088 : srcLocalID)
750 :
751 : !*** find north neighbor block and set msg info
752 : !*** also set tripole block flag for later special cases
753 :
754 : northBlock = ice_blocksGetNbrID(iblock, ice_blocksNorth, &
755 1088 : ewBoundaryType, nsBoundaryType)
756 :
757 1088 : if (northBlock > 0) then
758 816 : tripoleBlock = .false.
759 : call ice_distributionGetBlockLoc(dist, northBlock, dstProc, &
760 816 : dstLocalID)
761 272 : else if (northBlock < 0) then ! tripole north row, count block
762 0 : tripoleBlock = .true.
763 : call ice_distributionGetBlockLoc(dist, abs(northBlock), &
764 0 : dstProc, dstLocalID)
765 : else
766 272 : tripoleBlock = .false.
767 272 : dstProc = 0
768 272 : dstLocalID = 0
769 : endif
770 :
771 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
772 : northBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
773 1088 : 'north')
774 :
775 : !*** if a tripole boundary block, also create a local
776 : !*** message into and out of tripole buffer
777 :
778 1088 : if (tripoleBlock) then
779 : !*** copy out of tripole buffer - includes halo
780 : call ice_HaloMsgCreate(halo,-iblock, srcProc, srcLocalID, &
781 : iblock, srcProc, srcLocalID, & ! LCOV_EXCL_LINE
782 0 : 'north')
783 :
784 : !*** copy in only required if dstProc not same as srcProc
785 0 : if (dstProc /= srcProc) then
786 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
787 : -iblock, srcProc, srcLocalID, & ! LCOV_EXCL_LINE
788 0 : 'north')
789 :
790 : endif
791 : endif
792 :
793 : !*** find south neighbor block and add to message count
794 :
795 : southBlock = ice_blocksGetNbrID(iblock, ice_blocksSouth, &
796 1088 : ewBoundaryType, nsBoundaryType)
797 :
798 1088 : if (southBlock > 0) then
799 : call ice_distributionGetBlockLoc(dist, southBlock, dstProc, &
800 816 : dstLocalID)
801 :
802 : else
803 272 : dstProc = 0
804 272 : dstLocalID = 0
805 : endif
806 :
807 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
808 : southBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
809 1088 : 'south')
810 :
811 : !*** find east neighbor block and add to message count
812 :
813 : eastBlock = ice_blocksGetNbrID(iblock, ice_blocksEast, &
814 1088 : ewBoundaryType, nsBoundaryType)
815 :
816 1088 : if (eastBlock > 0) then
817 : call ice_distributionGetBlockLoc(dist, eastBlock, dstProc, &
818 1088 : dstLocalID)
819 :
820 : else
821 0 : dstProc = 0
822 0 : dstLocalID = 0
823 : endif
824 :
825 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
826 : eastBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
827 1088 : 'east')
828 :
829 : !*** if a tripole boundary block, non-local east neighbor
830 : !*** needs a chunk of the north boundary, so add a message
831 : !*** for that
832 :
833 1088 : if (tripoleBlock .and. dstProc /= srcProc) then
834 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
835 : -eastBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
836 0 : 'north')
837 :
838 : endif
839 :
840 : !*** find west neighbor block and add to message count
841 :
842 : westBlock = ice_blocksGetNbrID(iblock, ice_blocksWest, &
843 1088 : ewBoundaryType, nsBoundaryType)
844 :
845 1088 : if (westBlock > 0) then
846 : call ice_distributionGetBlockLoc(dist, westBlock, dstProc, &
847 1088 : dstLocalID)
848 :
849 : else
850 0 : dstProc = 0
851 0 : dstLocalID = 0
852 : endif
853 :
854 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
855 : westBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
856 1088 : 'west')
857 :
858 :
859 : !*** if a tripole boundary block, non-local west neighbor
860 : !*** needs a chunk of the north boundary, so add a message
861 : !*** for that
862 :
863 1088 : if (tripoleBlock .and. dstProc /= srcProc) then
864 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
865 : -westBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
866 0 : 'north')
867 :
868 : endif
869 :
870 : !*** find northeast neighbor block and add to message count
871 :
872 : neBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthEast, &
873 1088 : ewBoundaryType, nsBoundaryType)
874 :
875 1088 : if (neBlock /= 0) then
876 : call ice_distributionGetBlockLoc(dist, abs(neBlock), dstProc, &
877 816 : dstLocalID)
878 :
879 : else
880 272 : dstProc = 0
881 272 : dstLocalID = 0
882 : endif
883 :
884 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
885 : neBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
886 1088 : 'northeast')
887 :
888 : !*** find northwest neighbor block and add to message count
889 :
890 : nwBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthWest, &
891 1088 : ewBoundaryType, nsBoundaryType)
892 :
893 1088 : if (nwBlock /= 0) then
894 : call ice_distributionGetBlockLoc(dist, abs(nwBlock), dstProc, &
895 816 : dstLocalID)
896 :
897 : else
898 272 : dstProc = 0
899 272 : dstLocalID = 0
900 : endif
901 :
902 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
903 : nwBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
904 1088 : 'northwest')
905 :
906 : !*** find southeast neighbor block and add to message count
907 :
908 : seBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthEast, &
909 1088 : ewBoundaryType, nsBoundaryType)
910 :
911 1088 : if (seBlock > 0) then
912 : call ice_distributionGetBlockLoc(dist, seBlock, dstProc, &
913 816 : dstLocalID)
914 :
915 : else
916 272 : dstProc = 0
917 272 : dstLocalID = 0
918 : endif
919 :
920 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
921 : seBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
922 1088 : 'southeast')
923 :
924 : !*** find southwest neighbor block and add to message count
925 :
926 : swBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthWest, &
927 1088 : ewBoundaryType, nsBoundaryType)
928 :
929 1088 : if (swBlock > 0) then
930 : call ice_distributionGetBlockLoc(dist, swBlock, dstProc, &
931 816 : dstLocalID)
932 :
933 : else
934 272 : dstProc = 0
935 272 : dstLocalID = 0
936 : endif
937 :
938 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
939 : swBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
940 1088 : 'southwest')
941 :
942 : !*** for tripole grids with padded domain, padding will
943 : !*** prevent tripole buffer from getting all the info
944 : !*** it needs - must extend footprint at top boundary
945 :
946 1088 : if (tripoleBlock .and. & !tripole
947 1124 : mod(nxGlobal,blockSizeX) /= 0) then !padding
948 :
949 : !*** find east2 neighbor block and add to message count
950 :
951 : eastBlock = ice_blocksGetNbrID(iBlock, ice_blocksEast2, &
952 0 : ewBoundaryType, nsBoundaryType)
953 :
954 0 : if (eastBlock > 0) then
955 : call ice_distributionGetBlockLoc(dist, eastBlock, dstProc, &
956 0 : dstLocalID)
957 :
958 : else
959 0 : dstProc = 0
960 0 : dstLocalID = 0
961 : endif
962 :
963 0 : if (dstProc /= srcProc) then
964 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
965 : -eastBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
966 0 : 'north')
967 :
968 : endif
969 :
970 : !*** find EastNorthEast neighbor block and add to message count
971 :
972 : neBlock = ice_blocksGetNbrID(iBlock, ice_blocksEastNorthEast, &
973 0 : ewBoundaryType, nsBoundaryType)
974 :
975 0 : if (neBlock < 0) then ! tripole north row
976 0 : msgSize = tripoleMsgSize ! tripole needs whole top row of block
977 :
978 : call ice_distributionGetBlockLoc(dist, abs(neBlock), dstProc, &
979 0 : dstLocalID)
980 :
981 : else
982 0 : dstProc = 0
983 0 : dstLocalID = 0
984 : endif
985 :
986 0 : if (dstProc /= srcProc) then
987 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
988 : neBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
989 0 : 'north')
990 : endif
991 :
992 : !*** find west2 neighbor block and add to message count
993 :
994 : westBlock = ice_blocksGetNbrID(iBlock, ice_blocksWest2, &
995 0 : ewBoundaryType, nsBoundaryType)
996 :
997 0 : if (westBlock > 0) then
998 : call ice_distributionGetBlockLoc(dist, westBlock, dstProc, &
999 0 : dstLocalID)
1000 :
1001 : else
1002 0 : dstProc = 0
1003 0 : dstLocalID = 0
1004 : endif
1005 :
1006 0 : if (dstProc /= srcProc) then
1007 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
1008 : -westBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
1009 0 : 'north')
1010 :
1011 : endif
1012 :
1013 : !*** find WestNorthWest neighbor block and add to message count
1014 :
1015 : nwBlock = ice_blocksGetNbrID(iBlock, ice_blocksWestNorthWest, &
1016 0 : ewBoundaryType, nsBoundaryType)
1017 :
1018 0 : if (nwBlock < 0) then ! tripole north row
1019 0 : msgSize = tripoleMsgSize ! tripole needs whole top row of block
1020 :
1021 : call ice_distributionGetBlockLoc(dist, abs(nwBlock), dstProc, &
1022 0 : dstLocalID)
1023 :
1024 : else
1025 0 : dstProc = 0
1026 0 : dstLocalID = 0
1027 : endif
1028 :
1029 0 : if (dstProc /= srcProc) then
1030 : call ice_HaloMsgCreate(halo, iblock, srcProc, srcLocalID, &
1031 : nwBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
1032 0 : 'north')
1033 :
1034 : endif
1035 :
1036 : endif
1037 :
1038 : end do msgConfigLoop
1039 :
1040 : !-----------------------------------------------------------------------
1041 :
1042 72 : end function ice_HaloCreate
1043 :
1044 : !***********************************************************************
1045 :
1046 0 : subroutine ice_HaloMask(halo, basehalo, mask)
1047 :
1048 : ! This routine creates a halo type with info necessary for
1049 : ! performing a halo (ghost cell) update. This info is computed
1050 : ! based on a base halo already initialized and a mask
1051 :
1052 : use ice_domain_size, only: max_blocks
1053 :
1054 : type (ice_halo) :: &
1055 : basehalo ! basehalo to mask
1056 : integer (int_kind), intent(in) :: &
1057 : mask(nx_block,ny_block,max_blocks) ! mask of live points
1058 :
1059 : type (ice_halo) :: &
1060 : halo ! a new halo type with info for halo updates
1061 : character(len=*), parameter :: subname = '(ice_HaloMask)'
1062 :
1063 : !-----------------------------------------------------------------------
1064 : !
1065 : ! local variables
1066 : !
1067 : !-----------------------------------------------------------------------
1068 :
1069 : integer (int_kind) :: &
1070 : n,nmsg,scnt, &! counters ! LCOV_EXCL_LINE
1071 : icel,jcel,nblock, &! gridcell index ! LCOV_EXCL_LINE
1072 : istat, &! allocate status flag ! LCOV_EXCL_LINE
1073 : communicator, &! communicator for message passing ! LCOV_EXCL_LINE
1074 : numMsgSend, numMsgRecv, &! number of messages for this halo ! LCOV_EXCL_LINE
1075 : numLocalCopies, &! num local copies for halo update ! LCOV_EXCL_LINE
1076 : numLocalBlocks, &! num local blocks for halo fill ! LCOV_EXCL_LINE
1077 : tripoleRows, &! number of rows in tripole buffer ! LCOV_EXCL_LINE
1078 : lbufSizeSend, &! buffer size for send messages ! LCOV_EXCL_LINE
1079 : lbufSizeRecv ! buffer size for recv messages
1080 : logical (log_kind) :: &
1081 : tripoleTFlag, & ! flag for processing tripole buffer as T-fold ! LCOV_EXCL_LINE
1082 : tmpflag ! temporary flag for setting halomask along T-fold
1083 :
1084 : !-----------------------------------------------------------------------
1085 : !
1086 : ! allocate and initialize halo
1087 : ! always keep tripole zipper msgs
1088 : !
1089 : !-----------------------------------------------------------------------
1090 :
1091 0 : communicator = basehalo%communicator
1092 0 : tripoleRows = basehalo%tripoleRows
1093 0 : tripoleTFlag = basehalo%tripoleTFlag
1094 0 : numMsgSend = basehalo%numMsgSend
1095 0 : numMsgRecv = basehalo%numMsgRecv
1096 0 : numLocalCopies = basehalo%numLocalCopies
1097 0 : numLocalBlocks = basehalo%numLocalBlocks
1098 0 : lbufSizeSend = size(basehalo%sendAddr,dim=2)
1099 0 : lbufSizeRecv = size(basehalo%recvAddr,dim=2)
1100 :
1101 : allocate(halo%sendTask(numMsgSend), &
1102 : halo%recvTask(numMsgRecv), & ! LCOV_EXCL_LINE
1103 : halo%sizeSend(numMsgSend), & ! LCOV_EXCL_LINE
1104 : halo%sizeRecv(numMsgRecv), & ! LCOV_EXCL_LINE
1105 : halo%tripSend(numMsgSend), & ! LCOV_EXCL_LINE
1106 : halo%tripRecv(numMsgRecv), & ! LCOV_EXCL_LINE
1107 : halo%sendAddr(3,lbufSizeSend,numMsgSend), & ! LCOV_EXCL_LINE
1108 : halo%recvAddr(3,lbufSizeRecv,numMsgRecv), & ! LCOV_EXCL_LINE
1109 : halo%srcLocalAddr(3,numLocalCopies), & ! LCOV_EXCL_LINE
1110 : halo%dstLocalAddr(3,numLocalCopies), & ! LCOV_EXCL_LINE
1111 : halo%blockGlobalID(numLocalBlocks), & ! LCOV_EXCL_LINE
1112 0 : stat = istat)
1113 :
1114 0 : if (istat > 0) then
1115 0 : call abort_ice(subname//'ERROR: allocating halo message info arrays')
1116 0 : return
1117 : endif
1118 :
1119 0 : halo%communicator = communicator
1120 0 : halo%tripoleRows = tripoleRows
1121 0 : halo%tripoleTFlag = tripoleTFlag
1122 0 : halo%numLocalCopies = numLocalCopies
1123 0 : halo%numLocalBlocks = numLocalBlocks
1124 :
1125 0 : halo%srcLocalAddr = basehalo%srcLocalAddr(:,1:numLocalCopies)
1126 0 : halo%dstLocalAddr = basehalo%dstLocalAddr(:,1:numLocalCopies)
1127 :
1128 0 : halo%blockGlobalID = basehalo%blockGlobalID
1129 :
1130 0 : numMsgSend = 0
1131 0 : do nmsg=1,basehalo%numMsgSend
1132 0 : scnt = 0
1133 0 : do n=1,basehalo%sizeSend(nmsg)
1134 0 : icel = basehalo%sendAddr(1,n,nmsg)
1135 0 : jcel = basehalo%sendAddr(2,n,nmsg)
1136 0 : nblock = basehalo%sendAddr(3,n,nmsg)
1137 : ! the following line fails bounds check for mask when tripSend /= 0
1138 : ! if (mask(icel,jcel,abs(nblock)) /= 0 .or. basehalo%tripSend(nmsg) /= 0) then
1139 0 : tmpflag = .false.
1140 0 : if (basehalo%tripSend(nmsg) /= 0) then
1141 0 : tmpflag = .true.
1142 0 : elseif (mask(icel,jcel,abs(nblock)) /= 0) then
1143 0 : tmpflag = .true.
1144 : endif
1145 :
1146 0 : if (tmpflag) then
1147 0 : scnt = scnt + 1
1148 0 : if (scnt == 1) then
1149 0 : numMsgSend = numMsgSend + 1
1150 0 : halo%sendTask(numMsgSend) = basehalo%sendTask(nmsg)
1151 0 : halo%tripSend(numMsgSend) = basehalo%tripSend(nmsg)
1152 : endif
1153 0 : halo%sendAddr(1,scnt,numMsgSend) = icel
1154 0 : halo%sendAddr(2,scnt,numMsgSend) = jcel
1155 0 : halo%sendAddr(3,scnt,numMsgSend) = nblock
1156 0 : halo%sizeSend(numMsgSend) = scnt
1157 : endif
1158 : enddo
1159 : enddo
1160 0 : halo%numMsgSend = numMsgSend
1161 :
1162 0 : numMsgRecv = 0
1163 0 : do nmsg=1,basehalo%numMsgRecv
1164 0 : scnt = 0
1165 0 : do n=1,basehalo%sizeRecv(nmsg)
1166 0 : icel = basehalo%recvAddr(1,n,nmsg)
1167 0 : jcel = basehalo%recvAddr(2,n,nmsg)
1168 0 : nblock = basehalo%recvAddr(3,n,nmsg)
1169 : ! the following line fails bounds check for mask when tripRecv /= 0
1170 : ! if (mask(icel,jcel,abs(nblock)) /= 0 .or. basehalo%tripRecv(nmsg) /= 0) then
1171 0 : tmpflag = .false.
1172 0 : if (basehalo%tripRecv(nmsg) /= 0) then
1173 0 : tmpflag = .true.
1174 0 : elseif (mask(icel,jcel,abs(nblock)) /= 0) then
1175 0 : tmpflag = .true.
1176 : endif
1177 :
1178 0 : if (tmpflag) then
1179 0 : scnt = scnt + 1
1180 0 : if (scnt == 1) then
1181 0 : numMsgRecv = numMsgRecv + 1
1182 0 : halo%recvTask(numMsgRecv) = basehalo%recvTask(nmsg)
1183 0 : halo%tripRecv(numMsgRecv) = basehalo%tripRecv(nmsg)
1184 : endif
1185 0 : halo%recvAddr(1,scnt,numMsgRecv) = icel
1186 0 : halo%recvAddr(2,scnt,numMsgRecv) = jcel
1187 0 : halo%recvAddr(3,scnt,numMsgRecv) = nblock
1188 0 : halo%sizeRecv(numMsgRecv) = scnt
1189 : endif
1190 : enddo
1191 : enddo
1192 0 : halo%numMsgRecv = numMsgRecv
1193 :
1194 : !-----------------------------------------------------------------------
1195 :
1196 : end subroutine ice_HaloMask
1197 :
1198 : !***********************************************************************
1199 :
1200 2373984 : subroutine ice_HaloUpdate2DR8(array, halo, &
1201 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
1202 : fillValue, tripoleOnly)
1203 :
1204 : ! This routine updates ghost cells for an input array and is a
1205 : ! member of a group of routines under the generic interface
1206 : ! ice\_HaloUpdate. This routine is the specific interface
1207 : ! for 2d horizontal arrays of double precision.
1208 :
1209 : type (ice_halo), intent(in) :: &
1210 : halo ! precomputed halo structure containing all
1211 : ! information needed for halo update
1212 :
1213 : integer (int_kind), intent(in) :: &
1214 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
1215 : fieldLoc ! id for location on horizontal grid
1216 : ! (center, NEcorner, Nface, Eface)
1217 :
1218 : real (dbl_kind), intent(in), optional :: &
1219 : fillValue ! optional value to put in ghost cells
1220 : ! where neighbor points are unknown
1221 : ! (e.g. eliminated land blocks or
1222 : ! closed boundaries)
1223 :
1224 : logical (log_kind), intent(in), optional :: &
1225 : tripoleOnly ! optional flag to execute halo only across tripole seam.
1226 : ! this is required for a few fields where we just want to
1227 : ! ensure the tripole seam is synced up to preserve symmetry.
1228 : ! Added June, 2022 by tcraig. Only added to 2DR8 for now.
1229 :
1230 : real (dbl_kind), dimension(:,:,:), intent(inout) :: &
1231 : array ! array containing field for which halo
1232 : ! needs to be updated
1233 :
1234 : !-----------------------------------------------------------------------
1235 : !
1236 : ! local variables
1237 : !
1238 : !-----------------------------------------------------------------------
1239 :
1240 : integer (int_kind) :: &
1241 : i,j,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
1242 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
1243 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
1244 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
1245 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
1246 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
1247 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
1248 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
1249 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
1250 : isign ! sign factor for tripole grids
1251 :
1252 : integer (int_kind), dimension(:), allocatable :: &
1253 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
1254 2373984 : rcvRequest ! MPI request ids
1255 :
1256 : integer (int_kind), dimension(:,:), allocatable :: &
1257 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
1258 2373984 : rcvStatus ! MPI status flags
1259 :
1260 : real (dbl_kind) :: &
1261 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
1262 708672 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
1263 :
1264 : logical (log_kind) :: &
1265 : ltripoleOnly ! local tripoleOnly value
1266 :
1267 : integer (int_kind) :: len ! length of messages
1268 :
1269 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DR8)'
1270 :
1271 : !-----------------------------------------------------------------------
1272 : !
1273 : ! abort or return on unknown or noupdate field_loc or field_type
1274 : !
1275 : !-----------------------------------------------------------------------
1276 :
1277 2373984 : if (fieldLoc == field_loc_unknown .or. &
1278 : fieldKind == field_type_unknown) then
1279 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
1280 0 : return
1281 : endif
1282 :
1283 2373984 : if (fieldLoc == field_loc_noupdate .or. &
1284 : fieldKind == field_type_noupdate) then
1285 0 : return
1286 : endif
1287 :
1288 : !-----------------------------------------------------------------------
1289 : !
1290 : ! initialize error code and fill value
1291 : !
1292 : !-----------------------------------------------------------------------
1293 :
1294 2373984 : if (present(fillValue)) then
1295 612 : fill = fillValue
1296 : else
1297 2373372 : fill = 0.0_dbl_kind
1298 : endif
1299 :
1300 2373984 : if (present(tripoleOnly)) then
1301 288 : ltripoleOnly = tripoleOnly
1302 : else
1303 2373696 : ltripoleOnly = .false.
1304 : endif
1305 :
1306 2373984 : nxGlobal = 0
1307 2373984 : if (allocated(bufTripoleR8)) then
1308 0 : nxGlobal = size(bufTripoleR8,dim=1)
1309 0 : bufTripoleR8 = fill
1310 : endif
1311 :
1312 : !-----------------------------------------------------------------------
1313 : !
1314 : ! allocate request and status arrays for messages
1315 : !
1316 : !-----------------------------------------------------------------------
1317 :
1318 : allocate(sndRequest(halo%numMsgSend), &
1319 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
1320 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
1321 2373984 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
1322 :
1323 2373984 : if (ierr > 0) then
1324 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
1325 0 : return
1326 : endif
1327 :
1328 : !-----------------------------------------------------------------------
1329 : !
1330 : ! post receives
1331 : !
1332 : !-----------------------------------------------------------------------
1333 :
1334 12377472 : do nmsg=1,halo%numMsgRecv
1335 :
1336 10003488 : len = halo%SizeRecv(nmsg)
1337 0 : call MPI_IRECV(bufRecvR8(1:len,nmsg), len, mpiR8, &
1338 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
1339 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
1340 12377472 : halo%communicator, rcvRequest(nmsg), ierr)
1341 : end do
1342 :
1343 : !-----------------------------------------------------------------------
1344 : !
1345 : ! fill send buffer and post sends
1346 : !
1347 : !-----------------------------------------------------------------------
1348 :
1349 12377472 : do nmsg=1,halo%numMsgSend
1350 :
1351 417511968 : do n=1,halo%sizeSend(nmsg)
1352 407508480 : iSrc = halo%sendAddr(1,n,nmsg)
1353 407508480 : jSrc = halo%sendAddr(2,n,nmsg)
1354 407508480 : srcBlock = halo%sendAddr(3,n,nmsg)
1355 :
1356 417511968 : bufSendR8(n,nmsg) = array(iSrc,jSrc,srcBlock)
1357 : end do
1358 434167968 : do n=halo%sizeSend(nmsg)+1,bufSizeSend
1359 434167968 : bufSendR8(n,nmsg) = fill ! fill remainder of buffer
1360 : end do
1361 :
1362 10003488 : len = halo%SizeSend(nmsg)
1363 0 : call MPI_ISEND(bufSendR8(1:len,nmsg), len, mpiR8, &
1364 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
1365 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
1366 12377472 : halo%communicator, sndRequest(nmsg), ierr)
1367 : end do
1368 :
1369 : !-----------------------------------------------------------------------
1370 : !
1371 : ! while messages are being communicated, fill out halo region
1372 : ! needed for masked halos to ensure halo values are filled for
1373 : ! halo grid cells that are not updated
1374 : !
1375 : !-----------------------------------------------------------------------
1376 :
1377 2373984 : if (ltripoleOnly) then
1378 : ! skip fill, not needed since tripole seam always exists if running
1379 : ! on tripole grid and set tripoleOnly flag
1380 : else
1381 9102480 : do iblk = 1, halo%numLocalBlocks
1382 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
1383 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
1384 6728784 : jlo=jlo, jhi=jhi)
1385 13457568 : do j = 1,nghost
1386 205946496 : array(1:nx_block, jlo-j,iblk) = fill
1387 212675280 : array(1:nx_block, jhi+j,iblk) = fill
1388 : enddo
1389 22560048 : do i = 1,nghost
1390 223824384 : array(ilo-i, 1:ny_block,iblk) = fill
1391 230553168 : array(ihi+i, 1:ny_block,iblk) = fill
1392 : enddo
1393 : enddo
1394 : endif
1395 :
1396 : !-----------------------------------------------------------------------
1397 : !
1398 : ! do local copies while waiting for messages to complete
1399 : ! if srcBlock is zero, that denotes an eliminated land block or a
1400 : ! closed boundary where ghost cell values are undefined
1401 : ! if srcBlock is less than zero, the message is a copy out of the
1402 : ! tripole buffer and will be treated later
1403 : !
1404 : !-----------------------------------------------------------------------
1405 :
1406 301073568 : do nmsg=1,halo%numLocalCopies
1407 298699584 : iSrc = halo%srcLocalAddr(1,nmsg)
1408 298699584 : jSrc = halo%srcLocalAddr(2,nmsg)
1409 298699584 : srcBlock = halo%srcLocalAddr(3,nmsg)
1410 298699584 : iDst = halo%dstLocalAddr(1,nmsg)
1411 298699584 : jDst = halo%dstLocalAddr(2,nmsg)
1412 298699584 : dstBlock = halo%dstLocalAddr(3,nmsg)
1413 :
1414 301073568 : if (ltripoleOnly) then
1415 29888 : if (srcBlock > 0) then
1416 29312 : if (dstBlock < 0) then ! tripole copy into buffer
1417 0 : bufTripoleR8(iDst,jDst) = &
1418 0 : array(iSrc,jSrc,srcBlock)
1419 : endif
1420 : endif
1421 : else
1422 298669696 : if (srcBlock > 0) then
1423 298564864 : if (dstBlock > 0) then
1424 155893760 : array(iDst,jDst,dstBlock) = &
1425 298564864 : array(iSrc,jSrc,srcBlock)
1426 0 : else if (dstBlock < 0) then ! tripole copy into buffer
1427 0 : bufTripoleR8(iDst,jDst) = &
1428 0 : array(iSrc,jSrc,srcBlock)
1429 : endif
1430 104832 : else if (srcBlock == 0) then
1431 104832 : array(iDst,jDst,dstBlock) = fill
1432 : endif
1433 : endif
1434 : end do
1435 :
1436 : !-----------------------------------------------------------------------
1437 : !
1438 : ! wait for receives to finish and then unpack the recv buffer into
1439 : ! ghost cells
1440 : !
1441 : !-----------------------------------------------------------------------
1442 :
1443 2373984 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
1444 :
1445 12377472 : do nmsg=1,halo%numMsgRecv
1446 419885952 : do n=1,halo%sizeRecv(nmsg)
1447 407508480 : iDst = halo%recvAddr(1,n,nmsg)
1448 407508480 : jDst = halo%recvAddr(2,n,nmsg)
1449 407508480 : dstBlock = halo%recvAddr(3,n,nmsg)
1450 :
1451 417511968 : if (ltripoleOnly) then
1452 80640 : if (dstBlock < 0) then !tripole
1453 0 : bufTripoleR8(iDst,jDst) = bufRecvR8(n,nmsg)
1454 : endif
1455 : else
1456 407427840 : if (dstBlock > 0) then
1457 407427840 : array(iDst,jDst,dstBlock) = bufRecvR8(n,nmsg)
1458 0 : else if (dstBlock < 0) then !tripole
1459 0 : bufTripoleR8(iDst,jDst) = bufRecvR8(n,nmsg)
1460 : endif
1461 : endif
1462 : end do
1463 : end do
1464 :
1465 : !-----------------------------------------------------------------------
1466 : !
1467 : ! take care of northern boundary in tripole case
1468 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
1469 : ! (T-fold) of physical domain for entire (global) top row
1470 : !
1471 : !-----------------------------------------------------------------------
1472 :
1473 2373984 : if (nxGlobal > 0) then
1474 :
1475 0 : select case (fieldKind)
1476 : case (field_type_scalar)
1477 0 : isign = 1
1478 : case (field_type_vector)
1479 0 : isign = -1
1480 : case (field_type_angle)
1481 0 : isign = -1
1482 : case default
1483 0 : call abort_ice(subname//'ERROR: Unknown field kind')
1484 : end select
1485 :
1486 0 : if (halo%tripoleTFlag) then
1487 :
1488 0 : select case (fieldLoc)
1489 : case (field_loc_center) ! cell center location
1490 :
1491 0 : ioffset = -1
1492 0 : joffset = 0
1493 :
1494 : !*** top row is degenerate, so must enforce symmetry
1495 : !*** use average of two degenerate points for value
1496 :
1497 0 : do i = 2,nxGlobal/2
1498 0 : iDst = nxGlobal - i + 2
1499 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
1500 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
1501 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1502 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
1503 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
1504 : end do
1505 :
1506 : case (field_loc_NEcorner) ! cell corner location
1507 :
1508 0 : ioffset = 0
1509 0 : joffset = 1
1510 :
1511 : case (field_loc_Eface) ! cell center location
1512 :
1513 0 : ioffset = 0
1514 0 : joffset = 0
1515 :
1516 : !*** top row is degenerate, so must enforce symmetry
1517 : !*** use average of two degenerate points for value
1518 :
1519 0 : do i = 1,nxGlobal/2
1520 0 : iDst = nxGlobal + 1 - i
1521 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
1522 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
1523 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1524 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
1525 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
1526 : end do
1527 :
1528 : case (field_loc_Nface) ! cell corner (velocity) location
1529 :
1530 0 : ioffset = -1
1531 0 : joffset = 1
1532 :
1533 : case default
1534 0 : call abort_ice(subname//'ERROR: Unknown field location')
1535 : end select
1536 :
1537 : else ! tripole u-fold
1538 :
1539 0 : select case (fieldLoc)
1540 : case (field_loc_center) ! cell center location
1541 :
1542 0 : ioffset = 0
1543 0 : joffset = 0
1544 :
1545 : case (field_loc_NEcorner) ! cell corner location
1546 :
1547 0 : ioffset = 1
1548 0 : joffset = 1
1549 :
1550 : !*** top row is degenerate, so must enforce symmetry
1551 : !*** use average of two degenerate points for value
1552 :
1553 0 : do i = 1,nxGlobal/2 - 1
1554 0 : iDst = nxGlobal - i
1555 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
1556 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
1557 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1558 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
1559 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
1560 : end do
1561 :
1562 : case (field_loc_Eface) ! cell center location
1563 :
1564 0 : ioffset = 1
1565 0 : joffset = 0
1566 :
1567 : case (field_loc_Nface) ! cell corner (velocity) location
1568 :
1569 0 : ioffset = 0
1570 0 : joffset = 1
1571 :
1572 : !*** top row is degenerate, so must enforce symmetry
1573 : !*** use average of two degenerate points for value
1574 :
1575 0 : do i = 1,nxGlobal/2
1576 0 : iDst = nxGlobal + 1 - i
1577 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
1578 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
1579 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1580 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
1581 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
1582 : end do
1583 :
1584 : case default
1585 0 : call abort_ice(subname//'ERROR: Unknown field location')
1586 : end select
1587 :
1588 : endif
1589 :
1590 : !*** copy out of global tripole buffer into local
1591 : !*** ghost cells
1592 :
1593 : !*** look through local copies to find the copy out
1594 : !*** messages (srcBlock < 0)
1595 :
1596 0 : do nmsg=1,halo%numLocalCopies
1597 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
1598 :
1599 0 : if (srcBlock < 0) then
1600 :
1601 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
1602 0 : jSrc = halo%srcLocalAddr(2,nmsg)
1603 :
1604 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
1605 0 : jDst = halo%dstLocalAddr(2,nmsg)
1606 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
1607 :
1608 : !*** correct for offsets
1609 0 : iSrc = iSrc - ioffset
1610 0 : jSrc = jSrc - joffset
1611 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
1612 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
1613 :
1614 : !*** for center and Eface on u-fold, and NE corner and Nface
1615 : !*** on T-fold, do not need to replace
1616 : !*** top row of physical domain, so jSrc should be
1617 : !*** out of range and skipped
1618 : !*** otherwise do the copy
1619 :
1620 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
1621 0 : array(iDst,jDst,dstBlock) = isign*bufTripoleR8(iSrc,jSrc)
1622 : endif
1623 :
1624 : endif
1625 : end do
1626 :
1627 : endif
1628 :
1629 : !-----------------------------------------------------------------------
1630 : !
1631 : ! wait for sends to complete and deallocate arrays
1632 : !
1633 : !-----------------------------------------------------------------------
1634 :
1635 2373984 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
1636 :
1637 2373984 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
1638 :
1639 2373984 : if (ierr > 0) then
1640 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
1641 0 : return
1642 : endif
1643 :
1644 : !-----------------------------------------------------------------------
1645 :
1646 7121952 : end subroutine ice_HaloUpdate2DR8
1647 :
1648 : !***********************************************************************
1649 :
1650 0 : subroutine ice_HaloUpdate2DR4(array, halo, &
1651 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
1652 : fillValue)
1653 :
1654 : ! This routine updates ghost cells for an input array and is a
1655 : ! member of a group of routines under the generic interface
1656 : ! ice\_HaloUpdate. This routine is the specific interface
1657 : ! for 2d horizontal arrays of single precision.
1658 :
1659 : type (ice_halo), intent(in) :: &
1660 : halo ! precomputed halo structure containing all
1661 : ! information needed for halo update
1662 :
1663 : integer (int_kind), intent(in) :: &
1664 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
1665 : fieldLoc ! id for location on horizontal grid
1666 : ! (center, NEcorner, Nface, Eface)
1667 :
1668 : real (real_kind), intent(in), optional :: &
1669 : fillValue ! optional value to put in ghost cells
1670 : ! where neighbor points are unknown
1671 : ! (e.g. eliminated land blocks or
1672 : ! closed boundaries)
1673 :
1674 : real (real_kind), dimension(:,:,:), intent(inout) :: &
1675 : array ! array containing field for which halo
1676 : ! needs to be updated
1677 :
1678 : !-----------------------------------------------------------------------
1679 : !
1680 : ! local variables
1681 : !
1682 : !-----------------------------------------------------------------------
1683 :
1684 : integer (int_kind) :: &
1685 : i,j,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
1686 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
1687 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
1688 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
1689 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
1690 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
1691 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
1692 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
1693 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
1694 : isign ! sign factor for tripole grids
1695 :
1696 : integer (int_kind), dimension(:), allocatable :: &
1697 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
1698 0 : rcvRequest ! MPI request ids
1699 :
1700 : integer (int_kind), dimension(:,:), allocatable :: &
1701 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
1702 0 : rcvStatus ! MPI status flags
1703 :
1704 : real (real_kind) :: &
1705 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
1706 0 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
1707 :
1708 : integer (int_kind) :: len ! length of messages
1709 :
1710 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DR4)'
1711 :
1712 : !-----------------------------------------------------------------------
1713 : !
1714 : ! abort or return on unknown or noupdate field_loc or field_type
1715 : !
1716 : !-----------------------------------------------------------------------
1717 :
1718 0 : if (fieldLoc == field_loc_unknown .or. &
1719 : fieldKind == field_type_unknown) then
1720 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
1721 0 : return
1722 : endif
1723 :
1724 0 : if (fieldLoc == field_loc_noupdate .or. &
1725 : fieldKind == field_type_noupdate) then
1726 0 : return
1727 : endif
1728 :
1729 : !-----------------------------------------------------------------------
1730 : !
1731 : ! initialize error code and fill value
1732 : !
1733 : !-----------------------------------------------------------------------
1734 :
1735 0 : if (present(fillValue)) then
1736 0 : fill = fillValue
1737 : else
1738 0 : fill = 0.0_real_kind
1739 : endif
1740 :
1741 0 : nxGlobal = 0
1742 0 : if (allocated(bufTripoleR4)) then
1743 0 : nxGlobal = size(bufTripoleR4,dim=1)
1744 0 : bufTripoleR4 = fill
1745 : endif
1746 :
1747 : !-----------------------------------------------------------------------
1748 : !
1749 : ! allocate request and status arrays for messages
1750 : !
1751 : !-----------------------------------------------------------------------
1752 :
1753 : allocate(sndRequest(halo%numMsgSend), &
1754 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
1755 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
1756 0 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
1757 :
1758 0 : if (ierr > 0) then
1759 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
1760 0 : return
1761 : endif
1762 :
1763 : !-----------------------------------------------------------------------
1764 : !
1765 : ! post receives
1766 : !
1767 : !-----------------------------------------------------------------------
1768 :
1769 0 : do nmsg=1,halo%numMsgRecv
1770 :
1771 0 : len = halo%SizeRecv(nmsg)
1772 0 : call MPI_IRECV(bufRecvR4(1:len,nmsg), len, mpiR4, &
1773 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
1774 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
1775 0 : halo%communicator, rcvRequest(nmsg), ierr)
1776 : end do
1777 :
1778 : !-----------------------------------------------------------------------
1779 : !
1780 : ! fill send buffer and post sends
1781 : !
1782 : !-----------------------------------------------------------------------
1783 :
1784 0 : do nmsg=1,halo%numMsgSend
1785 :
1786 0 : do n=1,halo%sizeSend(nmsg)
1787 0 : iSrc = halo%sendAddr(1,n,nmsg)
1788 0 : jSrc = halo%sendAddr(2,n,nmsg)
1789 0 : srcBlock = halo%sendAddr(3,n,nmsg)
1790 :
1791 0 : bufSendR4(n,nmsg) = array(iSrc,jSrc,srcBlock)
1792 : end do
1793 0 : do n=halo%sizeSend(nmsg)+1,bufSizeSend
1794 0 : bufSendR4(n,nmsg) = fill ! fill remainder of buffer
1795 : end do
1796 :
1797 0 : len = halo%SizeSend(nmsg)
1798 0 : call MPI_ISEND(bufSendR4(1:len,nmsg), len, mpiR4, &
1799 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
1800 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
1801 0 : halo%communicator, sndRequest(nmsg), ierr)
1802 : end do
1803 :
1804 : !-----------------------------------------------------------------------
1805 : !
1806 : ! while messages are being communicated, fill out halo region
1807 : ! needed for masked halos to ensure halo values are filled for
1808 : ! halo grid cells that are not updated
1809 : !
1810 : !-----------------------------------------------------------------------
1811 :
1812 0 : do iblk = 1, halo%numLocalBlocks
1813 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
1814 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
1815 0 : jlo=jlo, jhi=jhi)
1816 0 : do j = 1,nghost
1817 0 : array(1:nx_block, jlo-j,iblk) = fill
1818 0 : array(1:nx_block, jhi+j,iblk) = fill
1819 : enddo
1820 0 : do i = 1,nghost
1821 0 : array(ilo-i, 1:ny_block,iblk) = fill
1822 0 : array(ihi+i, 1:ny_block,iblk) = fill
1823 : enddo
1824 : enddo
1825 :
1826 : !-----------------------------------------------------------------------
1827 : !
1828 : ! do local copies while waiting for messages to complete
1829 : ! if srcBlock is zero, that denotes an eliminated land block or a
1830 : ! closed boundary where ghost cell values are undefined
1831 : ! if srcBlock is less than zero, the message is a copy out of the
1832 : ! tripole buffer and will be treated later
1833 : !
1834 : !-----------------------------------------------------------------------
1835 :
1836 0 : do nmsg=1,halo%numLocalCopies
1837 0 : iSrc = halo%srcLocalAddr(1,nmsg)
1838 0 : jSrc = halo%srcLocalAddr(2,nmsg)
1839 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
1840 0 : iDst = halo%dstLocalAddr(1,nmsg)
1841 0 : jDst = halo%dstLocalAddr(2,nmsg)
1842 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
1843 :
1844 0 : if (srcBlock > 0) then
1845 0 : if (dstBlock > 0) then
1846 0 : array(iDst,jDst,dstBlock) = &
1847 0 : array(iSrc,jSrc,srcBlock)
1848 0 : else if (dstBlock < 0) then ! tripole copy into buffer
1849 0 : bufTripoleR4(iDst,jDst) = &
1850 0 : array(iSrc,jSrc,srcBlock)
1851 : endif
1852 0 : else if (srcBlock == 0) then
1853 0 : array(iDst,jDst,dstBlock) = fill
1854 : endif
1855 : end do
1856 :
1857 : !-----------------------------------------------------------------------
1858 : !
1859 : ! wait for receives to finish and then unpack the recv buffer into
1860 : ! ghost cells
1861 : !
1862 : !-----------------------------------------------------------------------
1863 :
1864 0 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
1865 :
1866 0 : do nmsg=1,halo%numMsgRecv
1867 0 : do n=1,halo%sizeRecv(nmsg)
1868 0 : iDst = halo%recvAddr(1,n,nmsg)
1869 0 : jDst = halo%recvAddr(2,n,nmsg)
1870 0 : dstBlock = halo%recvAddr(3,n,nmsg)
1871 :
1872 0 : if (dstBlock > 0) then
1873 0 : array(iDst,jDst,dstBlock) = bufRecvR4(n,nmsg)
1874 0 : else if (dstBlock < 0) then !tripole
1875 0 : bufTripoleR4(iDst,jDst) = bufRecvR4(n,nmsg)
1876 : endif
1877 : end do
1878 : end do
1879 :
1880 : !-----------------------------------------------------------------------
1881 : !
1882 : ! take care of northern boundary in tripole case
1883 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
1884 : ! (T-fold) of physical domain for entire (global) top row
1885 : !
1886 : !-----------------------------------------------------------------------
1887 :
1888 0 : if (nxGlobal > 0) then
1889 :
1890 0 : select case (fieldKind)
1891 : case (field_type_scalar)
1892 0 : isign = 1
1893 : case (field_type_vector)
1894 0 : isign = -1
1895 : case (field_type_angle)
1896 0 : isign = -1
1897 : case default
1898 0 : call abort_ice(subname//'ERROR: Unknown field kind')
1899 : end select
1900 :
1901 0 : if (halo%tripoleTFlag) then
1902 :
1903 0 : select case (fieldLoc)
1904 : case (field_loc_center) ! cell center location
1905 :
1906 0 : ioffset = -1
1907 0 : joffset = 0
1908 :
1909 : !*** top row is degenerate, so must enforce symmetry
1910 : !*** use average of two degenerate points for value
1911 :
1912 0 : do i = 2,nxGlobal/2
1913 0 : iDst = nxGlobal - i + 2
1914 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1915 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1916 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1917 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1918 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1919 : end do
1920 :
1921 : case (field_loc_NEcorner) ! cell corner location
1922 :
1923 0 : ioffset = 0
1924 0 : joffset = 1
1925 :
1926 : case (field_loc_Eface) ! cell center location
1927 :
1928 0 : ioffset = 0
1929 0 : joffset = 0
1930 :
1931 : !*** top row is degenerate, so must enforce symmetry
1932 : !*** use average of two degenerate points for value
1933 :
1934 0 : do i = 1,nxGlobal/2
1935 0 : iDst = nxGlobal + 1 - i
1936 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1937 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1938 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1939 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1940 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1941 : end do
1942 :
1943 : case (field_loc_Nface) ! cell corner (velocity) location
1944 :
1945 0 : ioffset = -1
1946 0 : joffset = 1
1947 :
1948 : case default
1949 0 : call abort_ice(subname//'ERROR: Unknown field location')
1950 : end select
1951 :
1952 : else ! tripole u-fold
1953 :
1954 0 : select case (fieldLoc)
1955 : case (field_loc_center) ! cell center location
1956 :
1957 0 : ioffset = 0
1958 0 : joffset = 0
1959 :
1960 : case (field_loc_NEcorner) ! cell corner location
1961 :
1962 0 : ioffset = 1
1963 0 : joffset = 1
1964 :
1965 : !*** top row is degenerate, so must enforce symmetry
1966 : !*** use average of two degenerate points for value
1967 :
1968 0 : do i = 1,nxGlobal/2 - 1
1969 0 : iDst = nxGlobal - i
1970 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1971 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1972 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1973 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1974 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1975 : end do
1976 :
1977 : case (field_loc_Eface) ! cell center location
1978 :
1979 0 : ioffset = 1
1980 0 : joffset = 0
1981 :
1982 : case (field_loc_Nface) ! cell corner (velocity) location
1983 :
1984 0 : ioffset = 0
1985 0 : joffset = 1
1986 :
1987 : !*** top row is degenerate, so must enforce symmetry
1988 : !*** use average of two degenerate points for value
1989 :
1990 0 : do i = 1,nxGlobal/2
1991 0 : iDst = nxGlobal + 1 - i
1992 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1993 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1994 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1995 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1996 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1997 : end do
1998 :
1999 : case default
2000 0 : call abort_ice(subname//'ERROR: Unknown field location')
2001 : end select
2002 :
2003 : endif
2004 :
2005 : !*** copy out of global tripole buffer into local
2006 : !*** ghost cells
2007 :
2008 : !*** look through local copies to find the copy out
2009 : !*** messages (srcBlock < 0)
2010 :
2011 0 : do nmsg=1,halo%numLocalCopies
2012 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2013 :
2014 0 : if (srcBlock < 0) then
2015 :
2016 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
2017 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2018 :
2019 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
2020 0 : jDst = halo%dstLocalAddr(2,nmsg)
2021 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2022 :
2023 : !*** correct for offsets
2024 0 : iSrc = iSrc - ioffset
2025 0 : jSrc = jSrc - joffset
2026 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
2027 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
2028 :
2029 : !*** for center and Eface on u-fold, and NE corner and Nface
2030 : !*** on T-fold, do not need to replace
2031 : !*** top row of physical domain, so jSrc should be
2032 : !*** out of range and skipped
2033 : !*** otherwise do the copy
2034 :
2035 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
2036 0 : array(iDst,jDst,dstBlock) = isign*bufTripoleR4(iSrc,jSrc)
2037 : endif
2038 :
2039 : endif
2040 : end do
2041 :
2042 : endif
2043 :
2044 : !-----------------------------------------------------------------------
2045 : !
2046 : ! wait for sends to complete and deallocate arrays
2047 : !
2048 : !-----------------------------------------------------------------------
2049 :
2050 0 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
2051 :
2052 0 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
2053 :
2054 0 : if (ierr > 0) then
2055 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
2056 0 : return
2057 : endif
2058 :
2059 : !-----------------------------------------------------------------------
2060 :
2061 0 : end subroutine ice_HaloUpdate2DR4
2062 :
2063 : !***********************************************************************
2064 :
2065 5760 : subroutine ice_HaloUpdate2DI4(array, halo, &
2066 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2067 : fillValue)
2068 :
2069 : ! This routine updates ghost cells for an input array and is a
2070 : ! member of a group of routines under the generic interface
2071 : ! ice\_HaloUpdate. This routine is the specific interface
2072 : ! for 2d horizontal integer arrays.
2073 :
2074 : type (ice_halo), intent(in) :: &
2075 : halo ! precomputed halo structure containing all
2076 : ! information needed for halo update
2077 :
2078 : integer (int_kind), intent(in) :: &
2079 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
2080 : fieldLoc ! id for location on horizontal grid
2081 : ! (center, NEcorner, Nface, Eface)
2082 :
2083 : integer (int_kind), intent(in), optional :: &
2084 : fillValue ! optional value to put in ghost cells
2085 : ! where neighbor points are unknown
2086 : ! (e.g. eliminated land blocks or
2087 : ! closed boundaries)
2088 :
2089 : integer (int_kind), dimension(:,:,:), intent(inout) :: &
2090 : array ! array containing field for which halo
2091 : ! needs to be updated
2092 :
2093 : !-----------------------------------------------------------------------
2094 : !
2095 : ! local variables
2096 : !
2097 : !-----------------------------------------------------------------------
2098 :
2099 : integer (int_kind) :: &
2100 : i,j,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
2101 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
2102 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
2103 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
2104 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
2105 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
2106 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
2107 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
2108 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
2109 : isign ! sign factor for tripole grids
2110 :
2111 : integer (int_kind), dimension(:), allocatable :: &
2112 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
2113 5760 : rcvRequest ! MPI request ids
2114 :
2115 : integer (int_kind), dimension(:,:), allocatable :: &
2116 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
2117 5760 : rcvStatus ! MPI status flags
2118 :
2119 : integer (int_kind) :: &
2120 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
2121 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
2122 :
2123 : integer (int_kind) :: len ! length of messages
2124 :
2125 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DI4)'
2126 :
2127 : !-----------------------------------------------------------------------
2128 : !
2129 : ! abort or return on unknown or noupdate field_loc or field_type
2130 : !
2131 : !-----------------------------------------------------------------------
2132 :
2133 5760 : if (fieldLoc == field_loc_unknown .or. &
2134 : fieldKind == field_type_unknown) then
2135 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
2136 0 : return
2137 : endif
2138 :
2139 5760 : if (fieldLoc == field_loc_noupdate .or. &
2140 : fieldKind == field_type_noupdate) then
2141 0 : return
2142 : endif
2143 :
2144 : !-----------------------------------------------------------------------
2145 : !
2146 : ! initialize error code and fill value
2147 : !
2148 : !-----------------------------------------------------------------------
2149 :
2150 5760 : if (present(fillValue)) then
2151 0 : fill = fillValue
2152 : else
2153 5760 : fill = 0_int_kind
2154 : endif
2155 :
2156 5760 : nxGlobal = 0
2157 5760 : if (allocated(bufTripoleI4)) then
2158 0 : nxGlobal = size(bufTripoleI4,dim=1)
2159 0 : bufTripoleI4 = fill
2160 : endif
2161 :
2162 : !-----------------------------------------------------------------------
2163 : !
2164 : ! allocate request and status arrays for messages
2165 : !
2166 : !-----------------------------------------------------------------------
2167 :
2168 : allocate(sndRequest(halo%numMsgSend), &
2169 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
2170 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
2171 5760 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
2172 :
2173 5760 : if (ierr > 0) then
2174 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
2175 0 : return
2176 : endif
2177 :
2178 : !-----------------------------------------------------------------------
2179 : !
2180 : ! post receives
2181 : !
2182 : !-----------------------------------------------------------------------
2183 :
2184 32640 : do nmsg=1,halo%numMsgRecv
2185 :
2186 26880 : len = halo%SizeRecv(nmsg)
2187 0 : call MPI_IRECV(bufRecvI4(1:len,nmsg), len, MPI_INTEGER, &
2188 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
2189 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
2190 32640 : halo%communicator, rcvRequest(nmsg), ierr)
2191 : end do
2192 :
2193 : !-----------------------------------------------------------------------
2194 : !
2195 : ! fill send buffer and post sends
2196 : !
2197 : !-----------------------------------------------------------------------
2198 :
2199 32640 : do nmsg=1,halo%numMsgSend
2200 :
2201 1479360 : do n=1,halo%sizeSend(nmsg)
2202 1452480 : iSrc = halo%sendAddr(1,n,nmsg)
2203 1452480 : jSrc = halo%sendAddr(2,n,nmsg)
2204 1452480 : srcBlock = halo%sendAddr(3,n,nmsg)
2205 :
2206 1479360 : bufSendI4(n,nmsg) = array(iSrc,jSrc,srcBlock)
2207 : end do
2208 2164800 : do n=halo%sizeSend(nmsg)+1,bufSizeSend
2209 2164800 : bufSendI4(n,nmsg) = fill ! fill remainder of buffer
2210 : end do
2211 :
2212 26880 : len = halo%SizeSend(nmsg)
2213 0 : call MPI_ISEND(bufSendI4(1:len,nmsg), len, MPI_INTEGER, &
2214 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
2215 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
2216 32640 : halo%communicator, sndRequest(nmsg), ierr)
2217 : end do
2218 :
2219 : !-----------------------------------------------------------------------
2220 : !
2221 : ! while messages are being communicated, fill out halo region
2222 : ! needed for masked halos to ensure halo values are filled for
2223 : ! halo grid cells that are not updated
2224 : !
2225 : !-----------------------------------------------------------------------
2226 :
2227 28680 : do iblk = 1, halo%numLocalBlocks
2228 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
2229 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
2230 22920 : jlo=jlo, jhi=jhi)
2231 45840 : do j = 1,nghost
2232 492480 : array(1:nx_block, jlo-j,iblk) = fill
2233 515400 : array(1:nx_block, jhi+j,iblk) = fill
2234 : enddo
2235 74520 : do i = 1,nghost
2236 750720 : array(ilo-i, 1:ny_block,iblk) = fill
2237 773640 : array(ihi+i, 1:ny_block,iblk) = fill
2238 : enddo
2239 : enddo
2240 :
2241 : !-----------------------------------------------------------------------
2242 : !
2243 : ! do local copies while waiting for messages to complete
2244 : ! if srcBlock is zero, that denotes an eliminated land block or a
2245 : ! closed boundary where ghost cell values are undefined
2246 : ! if srcBlock is less than zero, the message is a copy out of the
2247 : ! tripole buffer and will be treated later
2248 : !
2249 : !-----------------------------------------------------------------------
2250 :
2251 621120 : do nmsg=1,halo%numLocalCopies
2252 615360 : iSrc = halo%srcLocalAddr(1,nmsg)
2253 615360 : jSrc = halo%srcLocalAddr(2,nmsg)
2254 615360 : srcBlock = halo%srcLocalAddr(3,nmsg)
2255 615360 : iDst = halo%dstLocalAddr(1,nmsg)
2256 615360 : jDst = halo%dstLocalAddr(2,nmsg)
2257 615360 : dstBlock = halo%dstLocalAddr(3,nmsg)
2258 :
2259 621120 : if (srcBlock > 0) then
2260 606720 : if (dstBlock > 0) then
2261 316800 : array(iDst,jDst,dstBlock) = &
2262 606720 : array(iSrc,jSrc,srcBlock)
2263 0 : else if (dstBlock < 0) then ! tripole copy into buffer
2264 0 : bufTripoleI4(iDst,jDst) = &
2265 0 : array(iSrc,jSrc,srcBlock)
2266 : endif
2267 8640 : else if (srcBlock == 0) then
2268 8640 : array(iDst,jDst,dstBlock) = fill
2269 : endif
2270 : end do
2271 :
2272 : !-----------------------------------------------------------------------
2273 : !
2274 : ! wait for receives to finish and then unpack the recv buffer into
2275 : ! ghost cells
2276 : !
2277 : !-----------------------------------------------------------------------
2278 :
2279 5760 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
2280 :
2281 32640 : do nmsg=1,halo%numMsgRecv
2282 1485120 : do n=1,halo%sizeRecv(nmsg)
2283 1452480 : iDst = halo%recvAddr(1,n,nmsg)
2284 1452480 : jDst = halo%recvAddr(2,n,nmsg)
2285 1452480 : dstBlock = halo%recvAddr(3,n,nmsg)
2286 :
2287 1479360 : if (dstBlock > 0) then
2288 1452480 : array(iDst,jDst,dstBlock) = bufRecvI4(n,nmsg)
2289 0 : else if (dstBlock < 0) then !tripole
2290 0 : bufTripoleI4(iDst,jDst) = bufRecvI4(n,nmsg)
2291 : endif
2292 : end do
2293 : end do
2294 :
2295 : !-----------------------------------------------------------------------
2296 : !
2297 : ! take care of northern boundary in tripole case
2298 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
2299 : ! (T-fold) of physical domain for entire (global) top row
2300 : !
2301 : !-----------------------------------------------------------------------
2302 :
2303 5760 : if (nxGlobal > 0) then
2304 :
2305 0 : select case (fieldKind)
2306 : case (field_type_scalar)
2307 0 : isign = 1
2308 : case (field_type_vector)
2309 0 : isign = -1
2310 : case (field_type_angle)
2311 0 : isign = -1
2312 : case default
2313 0 : call abort_ice(subname//'ERROR: Unknown field kind')
2314 : end select
2315 :
2316 0 : if (halo%tripoleTFlag) then
2317 :
2318 0 : select case (fieldLoc)
2319 : case (field_loc_center) ! cell center location
2320 :
2321 0 : ioffset = -1
2322 0 : joffset = 0
2323 :
2324 : !*** top row is degenerate, so must enforce symmetry
2325 : !*** use average of two degenerate points for value
2326 :
2327 0 : do i = 2,nxGlobal/2
2328 0 : iDst = nxGlobal - i + 2
2329 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
2330 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
2331 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2332 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
2333 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
2334 : end do
2335 :
2336 : case (field_loc_NEcorner) ! cell corner location
2337 :
2338 0 : ioffset = 0
2339 0 : joffset = 1
2340 :
2341 : case (field_loc_Eface) ! cell center location
2342 :
2343 0 : ioffset = 0
2344 0 : joffset = 0
2345 :
2346 : !*** top row is degenerate, so must enforce symmetry
2347 : !*** use average of two degenerate points for value
2348 :
2349 0 : do i = 1,nxGlobal/2
2350 0 : iDst = nxGlobal + 1 - i
2351 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
2352 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
2353 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2354 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
2355 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
2356 : end do
2357 :
2358 : case (field_loc_Nface) ! cell corner (velocity) location
2359 :
2360 0 : ioffset = -1
2361 0 : joffset = 1
2362 :
2363 : case default
2364 0 : call abort_ice(subname//'ERROR: Unknown field location')
2365 : end select
2366 :
2367 : else ! tripole u-fold
2368 :
2369 0 : select case (fieldLoc)
2370 : case (field_loc_center) ! cell center location
2371 :
2372 0 : ioffset = 0
2373 0 : joffset = 0
2374 :
2375 : case (field_loc_NEcorner) ! cell corner location
2376 :
2377 0 : ioffset = 1
2378 0 : joffset = 1
2379 :
2380 : !*** top row is degenerate, so must enforce symmetry
2381 : !*** use average of two degenerate points for value
2382 :
2383 0 : do i = 1,nxGlobal/2 - 1
2384 0 : iDst = nxGlobal - i
2385 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
2386 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
2387 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2388 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
2389 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
2390 : end do
2391 :
2392 : case (field_loc_Eface) ! cell center location
2393 :
2394 0 : ioffset = 1
2395 0 : joffset = 0
2396 :
2397 : case (field_loc_Nface) ! cell corner (velocity) location
2398 :
2399 0 : ioffset = 0
2400 0 : joffset = 1
2401 :
2402 : !*** top row is degenerate, so must enforce symmetry
2403 : !*** use average of two degenerate points for value
2404 :
2405 0 : do i = 1,nxGlobal/2
2406 0 : iDst = nxGlobal + 1 - i
2407 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
2408 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
2409 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2410 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
2411 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
2412 : end do
2413 :
2414 : case default
2415 0 : call abort_ice(subname//'ERROR: Unknown field location')
2416 : end select
2417 :
2418 : endif
2419 :
2420 : !*** copy out of global tripole buffer into local
2421 : !*** ghost cells
2422 :
2423 : !*** look through local copies to find the copy out
2424 : !*** messages (srcBlock < 0)
2425 :
2426 0 : do nmsg=1,halo%numLocalCopies
2427 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2428 :
2429 0 : if (srcBlock < 0) then
2430 :
2431 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
2432 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2433 :
2434 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
2435 0 : jDst = halo%dstLocalAddr(2,nmsg)
2436 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2437 :
2438 : !*** correct for offsets
2439 0 : iSrc = iSrc - ioffset
2440 0 : jSrc = jSrc - joffset
2441 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
2442 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
2443 :
2444 : !*** for center and Eface on u-fold, and NE corner and Nface
2445 : !*** on T-fold, do not need to replace
2446 : !*** top row of physical domain, so jSrc should be
2447 : !*** out of range and skipped
2448 : !*** otherwise do the copy
2449 :
2450 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
2451 0 : array(iDst,jDst,dstBlock) = isign*bufTripoleI4(iSrc,jSrc)
2452 : endif
2453 :
2454 : endif
2455 : end do
2456 :
2457 : endif
2458 :
2459 : !-----------------------------------------------------------------------
2460 : !
2461 : ! wait for sends to complete and deallocate arrays
2462 : !
2463 : !-----------------------------------------------------------------------
2464 :
2465 5760 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
2466 :
2467 5760 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
2468 :
2469 5760 : if (ierr > 0) then
2470 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
2471 0 : return
2472 : endif
2473 :
2474 : !-----------------------------------------------------------------------
2475 :
2476 17280 : end subroutine ice_HaloUpdate2DI4
2477 :
2478 : !***********************************************************************
2479 :
2480 5760 : subroutine ice_HaloUpdate2DL1(array, halo, &
2481 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2482 : fillValue)
2483 :
2484 : ! This routine updates ghost cells for an input array and is a
2485 : ! member of a group of routines under the generic interface
2486 : ! ice\_HaloUpdate. This routine is the specific interface
2487 : ! for 2d horizontal logical arrays.
2488 :
2489 : type (ice_halo), intent(in) :: &
2490 : halo ! precomputed halo structure containing all
2491 : ! information needed for halo update
2492 :
2493 : integer (int_kind), intent(in) :: &
2494 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
2495 : fieldLoc ! id for location on horizontal grid
2496 : ! (center, NEcorner, Nface, Eface)
2497 :
2498 : integer (int_kind), intent(in), optional :: &
2499 : fillValue ! optional value to put in ghost cells
2500 : ! where neighbor points are unknown
2501 : ! (e.g. eliminated land blocks or
2502 : ! closed boundaries)
2503 :
2504 : logical (log_kind), dimension(:,:,:), intent(inout) :: &
2505 : array ! array containing field for which halo
2506 : ! needs to be updated
2507 :
2508 : !-----------------------------------------------------------------------
2509 : !
2510 : ! local variables
2511 : !
2512 : !-----------------------------------------------------------------------
2513 :
2514 : integer (int_kind), dimension(:,:,:), allocatable :: &
2515 5760 : iarray ! integer array for logical
2516 :
2517 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DL1)'
2518 :
2519 : !-----------------------------------------------------------------------
2520 : !
2521 : ! abort or return on unknown or noupdate field_loc or field_type
2522 : !
2523 : !-----------------------------------------------------------------------
2524 :
2525 5760 : if (fieldLoc == field_loc_unknown .or. &
2526 : fieldKind == field_type_unknown) then
2527 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
2528 0 : return
2529 : endif
2530 :
2531 5760 : if (fieldLoc == field_loc_noupdate .or. &
2532 : fieldKind == field_type_noupdate) then
2533 0 : return
2534 : endif
2535 :
2536 : !-----------------------------------------------------------------------
2537 : !
2538 : ! copy logical into integer array and call haloupdate on integer array
2539 : !
2540 : !-----------------------------------------------------------------------
2541 :
2542 5760 : allocate(iarray(size(array,dim=1),size(array,dim=2),size(array,dim=3)))
2543 15930240 : iarray(:,:,:) = 0
2544 15930240 : where (array) iarray = 1
2545 :
2546 : call ice_HaloUpdate(iarray, halo, &
2547 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2548 5760 : fillValue)
2549 :
2550 15930240 : array = .false.
2551 15930240 : where (iarray /= 0) array = .true.
2552 5760 : deallocate(iarray)
2553 :
2554 : !-----------------------------------------------------------------------
2555 :
2556 5760 : end subroutine ice_HaloUpdate2DL1
2557 :
2558 : !***********************************************************************
2559 :
2560 316908 : subroutine ice_HaloUpdate3DR8(array, halo, &
2561 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2562 : fillValue)
2563 :
2564 : ! This routine updates ghost cells for an input array and is a
2565 : ! member of a group of routines under the generic interface
2566 : ! ice\_HaloUpdate. This routine is the specific interface
2567 : ! for 3d horizontal arrays of double precision.
2568 :
2569 : type (ice_halo), intent(in) :: &
2570 : halo ! precomputed halo structure containing all
2571 : ! information needed for halo update
2572 :
2573 : integer (int_kind), intent(in) :: &
2574 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
2575 : fieldLoc ! id for location on horizontal grid
2576 : ! (center, NEcorner, Nface, Eface)
2577 :
2578 : real (dbl_kind), intent(in), optional :: &
2579 : fillValue ! optional value to put in ghost cells
2580 : ! where neighbor points are unknown
2581 : ! (e.g. eliminated land blocks or
2582 : ! closed boundaries)
2583 :
2584 : real (dbl_kind), dimension(:,:,:,:), intent(inout) :: &
2585 : array ! array containing field for which halo
2586 : ! needs to be updated
2587 :
2588 : !-----------------------------------------------------------------------
2589 : !
2590 : ! local variables
2591 : !
2592 : !-----------------------------------------------------------------------
2593 :
2594 : integer (int_kind) :: &
2595 : i,j,k,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
2596 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
2597 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
2598 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
2599 : nz, &! size of array in 3rd dimension ! LCOV_EXCL_LINE
2600 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
2601 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
2602 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
2603 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
2604 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
2605 : isign ! sign factor for tripole grids
2606 :
2607 : integer (int_kind), dimension(:), allocatable :: &
2608 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
2609 316908 : rcvRequest ! MPI request ids
2610 :
2611 : integer (int_kind), dimension(:,:), allocatable :: &
2612 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
2613 316908 : rcvStatus ! MPI status flags
2614 :
2615 : real (dbl_kind) :: &
2616 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
2617 21624 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
2618 :
2619 : real (dbl_kind), dimension(:,:), allocatable :: &
2620 316908 : bufSend, bufRecv ! 3d send,recv buffers
2621 :
2622 : real (dbl_kind), dimension(:,:,:), allocatable :: &
2623 316908 : bufTripole ! 3d tripole buffer
2624 :
2625 : integer (int_kind) :: len ! length of message
2626 :
2627 : character(len=*), parameter :: subname = '(ice_HaloUpdate3DR8)'
2628 :
2629 : !-----------------------------------------------------------------------
2630 : !
2631 : ! abort or return on unknown or noupdate field_loc or field_type
2632 : !
2633 : !-----------------------------------------------------------------------
2634 :
2635 316908 : if (fieldLoc == field_loc_unknown .or. &
2636 : fieldKind == field_type_unknown) then
2637 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
2638 0 : return
2639 : endif
2640 :
2641 316908 : if (fieldLoc == field_loc_noupdate .or. &
2642 : fieldKind == field_type_noupdate) then
2643 0 : return
2644 : endif
2645 :
2646 : !-----------------------------------------------------------------------
2647 : !
2648 : ! initialize error code and fill value
2649 : !
2650 : !-----------------------------------------------------------------------
2651 :
2652 316908 : if (present(fillValue)) then
2653 0 : fill = fillValue
2654 : else
2655 316908 : fill = 0.0_dbl_kind
2656 : endif
2657 :
2658 316908 : nxGlobal = 0
2659 316908 : if (allocated(bufTripoleR8)) nxGlobal = size(bufTripoleR8,dim=1)
2660 :
2661 : !-----------------------------------------------------------------------
2662 : !
2663 : ! allocate request and status arrays for messages
2664 : !
2665 : !-----------------------------------------------------------------------
2666 :
2667 : allocate(sndRequest(halo%numMsgSend), &
2668 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
2669 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
2670 316908 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
2671 :
2672 316908 : if (ierr > 0) then
2673 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
2674 0 : return
2675 : endif
2676 :
2677 : !-----------------------------------------------------------------------
2678 : !
2679 : ! allocate 3D buffers
2680 : !
2681 : !-----------------------------------------------------------------------
2682 :
2683 316908 : nz = size(array, dim=3)
2684 :
2685 : allocate(bufSend(bufSizeSend*nz, halo%numMsgSend), &
2686 : bufRecv(bufSizeRecv*nz, halo%numMsgRecv), & ! LCOV_EXCL_LINE
2687 : bufTripole(nxGlobal, halo%tripoleRows, nz), & ! LCOV_EXCL_LINE
2688 316908 : stat=ierr)
2689 :
2690 316908 : if (ierr > 0) then
2691 0 : call abort_ice(subname//'ERROR: allocating buffers')
2692 0 : return
2693 : endif
2694 :
2695 2945088 : bufTripole = fill
2696 :
2697 : !-----------------------------------------------------------------------
2698 : !
2699 : ! post receives
2700 : !
2701 : !-----------------------------------------------------------------------
2702 :
2703 2333424 : do nmsg=1,halo%numMsgRecv
2704 :
2705 2016516 : len = halo%SizeRecv(nmsg)*nz
2706 0 : call MPI_IRECV(bufRecv(1:len,nmsg), len, mpiR8, &
2707 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
2708 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
2709 2333424 : halo%communicator, rcvRequest(nmsg), ierr)
2710 : end do
2711 :
2712 : !-----------------------------------------------------------------------
2713 : !
2714 : ! fill send buffer and post sends
2715 : !
2716 : !-----------------------------------------------------------------------
2717 :
2718 2333424 : do nmsg=1,halo%numMsgSend
2719 :
2720 2016516 : i=0
2721 177510756 : do n=1,halo%sizeSend(nmsg)
2722 175494240 : iSrc = halo%sendAddr(1,n,nmsg)
2723 175494240 : jSrc = halo%sendAddr(2,n,nmsg)
2724 175494240 : srcBlock = halo%sendAddr(3,n,nmsg)
2725 :
2726 589594116 : do k=1,nz
2727 412083360 : i = i + 1
2728 587577600 : bufSend(i,nmsg) = array(iSrc,jSrc,k,srcBlock)
2729 : end do
2730 : end do
2731 784253556 : do n=i+1,bufSizeSend*nz
2732 784253556 : bufSend(n,nmsg) = fill ! fill remainder of buffer
2733 : end do
2734 :
2735 2016516 : len = halo%SizeSend(nmsg)*nz
2736 0 : call MPI_ISEND(bufSend(1:len,nmsg), len, mpiR8, &
2737 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
2738 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
2739 2333424 : halo%communicator, sndRequest(nmsg), ierr)
2740 : end do
2741 :
2742 : !-----------------------------------------------------------------------
2743 : !
2744 : ! while messages are being communicated, fill out halo region
2745 : ! needed for masked halos to ensure halo values are filled for
2746 : ! halo grid cells that are not updated
2747 : !
2748 : !-----------------------------------------------------------------------
2749 :
2750 2936385 : do iblk = 1, halo%numLocalBlocks
2751 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
2752 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
2753 2619477 : jlo=jlo, jhi=jhi)
2754 5238954 : do j = 1,nghost
2755 74527677 : array(1:nx_block, jlo-j,:,iblk) = fill
2756 77147154 : array(1:nx_block, jhi+j,:,iblk) = fill
2757 : enddo
2758 8175339 : do i = 1,nghost
2759 202361877 : array(ilo-i, 1:ny_block,:,iblk) = fill
2760 204981354 : array(ihi+i, 1:ny_block,:,iblk) = fill
2761 : enddo
2762 : enddo
2763 :
2764 : !-----------------------------------------------------------------------
2765 : !
2766 : ! do local copies while waiting for messages to complete
2767 : ! if srcBlock is zero, that denotes an eliminated land block or a
2768 : ! closed boundary where ghost cell values are undefined
2769 : ! if srcBlock is less than zero, the message is a copy out of the
2770 : ! tripole buffer and will be treated later
2771 : !
2772 : !-----------------------------------------------------------------------
2773 :
2774 11632116 : do nmsg=1,halo%numLocalCopies
2775 11315208 : iSrc = halo%srcLocalAddr(1,nmsg)
2776 11315208 : jSrc = halo%srcLocalAddr(2,nmsg)
2777 11315208 : srcBlock = halo%srcLocalAddr(3,nmsg)
2778 11315208 : iDst = halo%dstLocalAddr(1,nmsg)
2779 11315208 : jDst = halo%dstLocalAddr(2,nmsg)
2780 11315208 : dstBlock = halo%dstLocalAddr(3,nmsg)
2781 :
2782 11632116 : if (srcBlock > 0) then
2783 9111792 : if (dstBlock > 0) then
2784 52850592 : do k=1,nz
2785 22836000 : array(iDst,jDst,k,dstBlock) = &
2786 52850592 : array(iSrc,jSrc,k,srcBlock)
2787 : end do
2788 0 : else if (dstBlock < 0) then ! tripole copy into buffer
2789 0 : do k=1,nz
2790 0 : bufTripole(iDst,jDst,k) = &
2791 0 : array(iSrc,jSrc,k,srcBlock)
2792 : end do
2793 : endif
2794 2203416 : else if (srcBlock == 0) then
2795 6973776 : do k=1,nz
2796 6973776 : array(iDst,jDst,k,dstBlock) = fill
2797 : end do
2798 : endif
2799 : end do
2800 :
2801 : !-----------------------------------------------------------------------
2802 : !
2803 : ! wait for receives to finish and then unpack the recv buffer into
2804 : ! ghost cells
2805 : !
2806 : !-----------------------------------------------------------------------
2807 :
2808 316908 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
2809 :
2810 2333424 : do nmsg=1,halo%numMsgRecv
2811 2016516 : i = 0
2812 177827664 : do n=1,halo%sizeRecv(nmsg)
2813 175494240 : iDst = halo%recvAddr(1,n,nmsg)
2814 175494240 : jDst = halo%recvAddr(2,n,nmsg)
2815 175494240 : dstBlock = halo%recvAddr(3,n,nmsg)
2816 :
2817 177510756 : if (dstBlock > 0) then
2818 587577600 : do k=1,nz
2819 412083360 : i = i + 1
2820 587577600 : array(iDst,jDst,k,dstBlock) = bufRecv(i,nmsg)
2821 : end do
2822 0 : else if (dstBlock < 0) then !tripole
2823 0 : do k=1,nz
2824 0 : i = i + 1
2825 0 : bufTripole(iDst,jDst,k) = bufRecv(i,nmsg)
2826 : end do
2827 : endif
2828 : end do
2829 : end do
2830 :
2831 : !-----------------------------------------------------------------------
2832 : !
2833 : ! take care of northern boundary in tripole case
2834 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
2835 : ! (T-fold) of physical domain for entire (global) top row
2836 : !
2837 : !-----------------------------------------------------------------------
2838 :
2839 316908 : if (nxGlobal > 0) then
2840 :
2841 0 : select case (fieldKind)
2842 : case (field_type_scalar)
2843 0 : isign = 1
2844 : case (field_type_vector)
2845 0 : isign = -1
2846 : case (field_type_angle)
2847 0 : isign = -1
2848 : case default
2849 0 : call abort_ice(subname//'ERROR: Unknown field kind')
2850 : end select
2851 :
2852 0 : if (halo%tripoleTFlag) then
2853 :
2854 0 : select case (fieldLoc)
2855 : case (field_loc_center) ! cell center location
2856 :
2857 0 : ioffset = -1
2858 0 : joffset = 0
2859 :
2860 : !*** top row is degenerate, so must enforce symmetry
2861 : !*** use average of two degenerate points for value
2862 :
2863 0 : do k=1,nz
2864 0 : do i = 2,nxGlobal/2
2865 0 : iDst = nxGlobal - i + 2
2866 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2867 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2868 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2869 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2870 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2871 : end do
2872 : end do
2873 :
2874 : case (field_loc_NEcorner) ! cell corner location
2875 :
2876 0 : ioffset = 0
2877 0 : joffset = 1
2878 :
2879 : case (field_loc_Eface) ! cell center location
2880 :
2881 0 : ioffset = 0
2882 0 : joffset = 0
2883 :
2884 : !*** top row is degenerate, so must enforce symmetry
2885 : !*** use average of two degenerate points for value
2886 :
2887 0 : do k=1,nz
2888 0 : do i = 1,nxGlobal/2
2889 0 : iDst = nxGlobal + 1 - i
2890 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2891 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2892 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2893 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2894 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2895 : end do
2896 : end do
2897 :
2898 : case (field_loc_Nface) ! cell corner (velocity) location
2899 :
2900 0 : ioffset = -1
2901 0 : joffset = 1
2902 :
2903 : case default
2904 0 : call abort_ice(subname//'ERROR: Unknown field location')
2905 : end select
2906 :
2907 : else ! tripole u-fold
2908 :
2909 0 : select case (fieldLoc)
2910 : case (field_loc_center) ! cell center location
2911 :
2912 0 : ioffset = 0
2913 0 : joffset = 0
2914 :
2915 : case (field_loc_NEcorner) ! cell corner location
2916 :
2917 0 : ioffset = 1
2918 0 : joffset = 1
2919 :
2920 : !*** top row is degenerate, so must enforce symmetry
2921 : !*** use average of two degenerate points for value
2922 :
2923 0 : do k=1,nz
2924 0 : do i = 1,nxGlobal/2 - 1
2925 0 : iDst = nxGlobal - i
2926 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2927 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2928 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2929 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2930 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2931 : end do
2932 : end do
2933 :
2934 : case (field_loc_Eface) ! cell center location
2935 :
2936 0 : ioffset = 1
2937 0 : joffset = 0
2938 :
2939 : case (field_loc_Nface) ! cell corner (velocity) location
2940 :
2941 0 : ioffset = 0
2942 0 : joffset = 1
2943 :
2944 : !*** top row is degenerate, so must enforce symmetry
2945 : !*** use average of two degenerate points for value
2946 :
2947 0 : do k=1,nz
2948 0 : do i = 1,nxGlobal/2
2949 0 : iDst = nxGlobal + 1 - i
2950 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2951 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2952 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2953 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2954 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2955 : end do
2956 : end do
2957 :
2958 : case default
2959 0 : call abort_ice(subname//'ERROR: Unknown field location')
2960 : end select
2961 :
2962 : endif
2963 :
2964 : !*** copy out of global tripole buffer into local
2965 : !*** ghost cells
2966 :
2967 : !*** look through local copies to find the copy out
2968 : !*** messages (srcBlock < 0)
2969 :
2970 0 : do nmsg=1,halo%numLocalCopies
2971 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2972 :
2973 0 : if (srcBlock < 0) then
2974 :
2975 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
2976 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2977 :
2978 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
2979 0 : jDst = halo%dstLocalAddr(2,nmsg)
2980 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2981 :
2982 : !*** correct for offsets
2983 0 : iSrc = iSrc - ioffset
2984 0 : jSrc = jSrc - joffset
2985 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
2986 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
2987 :
2988 : !*** for center and Eface on u-fold, and NE corner and Nface
2989 : !*** on T-fold, do not need to replace
2990 : !*** top row of physical domain, so jSrc should be
2991 : !*** out of range and skipped
2992 : !*** otherwise do the copy
2993 :
2994 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
2995 0 : do k=1,nz
2996 0 : array(iDst,jDst,k,dstBlock) = isign* &
2997 0 : bufTripole(iSrc,jSrc,k)
2998 : end do
2999 : endif
3000 :
3001 : endif
3002 : end do
3003 :
3004 : endif
3005 :
3006 : !-----------------------------------------------------------------------
3007 : !
3008 : ! wait for sends to complete and deallocate arrays
3009 : !
3010 : !-----------------------------------------------------------------------
3011 :
3012 316908 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
3013 :
3014 316908 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
3015 :
3016 316908 : if (ierr > 0) then
3017 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
3018 0 : return
3019 : endif
3020 :
3021 316908 : deallocate(bufSend, bufRecv, bufTripole, stat=ierr)
3022 :
3023 316908 : if (ierr > 0) then
3024 0 : call abort_ice(subname//'ERROR: deallocating 3d buffers')
3025 0 : return
3026 : endif
3027 :
3028 : !-----------------------------------------------------------------------
3029 :
3030 950724 : end subroutine ice_HaloUpdate3DR8
3031 :
3032 : !***********************************************************************
3033 :
3034 0 : subroutine ice_HaloUpdate3DR4(array, halo, &
3035 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
3036 : fillValue)
3037 :
3038 : ! This routine updates ghost cells for an input array and is a
3039 : ! member of a group of routines under the generic interface
3040 : ! ice\_HaloUpdate. This routine is the specific interface
3041 : ! for 3d horizontal arrays of single precision.
3042 :
3043 : type (ice_halo), intent(in) :: &
3044 : halo ! precomputed halo structure containing all
3045 : ! information needed for halo update
3046 :
3047 : integer (int_kind), intent(in) :: &
3048 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
3049 : fieldLoc ! id for location on horizontal grid
3050 : ! (center, NEcorner, Nface, Eface)
3051 :
3052 : real (real_kind), intent(in), optional :: &
3053 : fillValue ! optional value to put in ghost cells
3054 : ! where neighbor points are unknown
3055 : ! (e.g. eliminated land blocks or
3056 : ! closed boundaries)
3057 :
3058 : real (real_kind), dimension(:,:,:,:), intent(inout) :: &
3059 : array ! array containing field for which halo
3060 : ! needs to be updated
3061 :
3062 : !-----------------------------------------------------------------------
3063 : !
3064 : ! local variables
3065 : !
3066 : !-----------------------------------------------------------------------
3067 :
3068 : integer (int_kind) :: &
3069 : i,j,k,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
3070 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
3071 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
3072 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
3073 : nz, &! size of array in 3rd dimension ! LCOV_EXCL_LINE
3074 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
3075 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
3076 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
3077 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
3078 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
3079 : isign ! sign factor for tripole grids
3080 :
3081 : integer (int_kind), dimension(:), allocatable :: &
3082 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
3083 0 : rcvRequest ! MPI request ids
3084 :
3085 : integer (int_kind), dimension(:,:), allocatable :: &
3086 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
3087 0 : rcvStatus ! MPI status flags
3088 :
3089 : real (real_kind) :: &
3090 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
3091 0 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
3092 :
3093 : real (real_kind), dimension(:,:), allocatable :: &
3094 0 : bufSend, bufRecv ! 3d send,recv buffers
3095 :
3096 : real (real_kind), dimension(:,:,:), allocatable :: &
3097 0 : bufTripole ! 3d tripole buffer
3098 :
3099 : integer (int_kind) :: len ! length of message
3100 :
3101 : character(len=*), parameter :: subname = '(ice_HaloUpdate3DR4)'
3102 :
3103 : !-----------------------------------------------------------------------
3104 : !
3105 : ! abort or return on unknown or noupdate field_loc or field_type
3106 : !
3107 : !-----------------------------------------------------------------------
3108 :
3109 0 : if (fieldLoc == field_loc_unknown .or. &
3110 : fieldKind == field_type_unknown) then
3111 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
3112 0 : return
3113 : endif
3114 :
3115 0 : if (fieldLoc == field_loc_noupdate .or. &
3116 : fieldKind == field_type_noupdate) then
3117 0 : return
3118 : endif
3119 :
3120 : !-----------------------------------------------------------------------
3121 : !
3122 : ! initialize error code and fill value
3123 : !
3124 : !-----------------------------------------------------------------------
3125 :
3126 0 : if (present(fillValue)) then
3127 0 : fill = fillValue
3128 : else
3129 0 : fill = 0.0_real_kind
3130 : endif
3131 :
3132 0 : nxGlobal = 0
3133 0 : if (allocated(bufTripoleR4)) nxGlobal = size(bufTripoleR4,dim=1)
3134 :
3135 : !-----------------------------------------------------------------------
3136 : !
3137 : ! allocate request and status arrays for messages
3138 : !
3139 : !-----------------------------------------------------------------------
3140 :
3141 : allocate(sndRequest(halo%numMsgSend), &
3142 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
3143 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
3144 0 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
3145 :
3146 0 : if (ierr > 0) then
3147 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
3148 0 : return
3149 : endif
3150 :
3151 : !-----------------------------------------------------------------------
3152 : !
3153 : ! allocate 3D buffers
3154 : !
3155 : !-----------------------------------------------------------------------
3156 :
3157 0 : nz = size(array, dim=3)
3158 :
3159 : allocate(bufSend(bufSizeSend*nz, halo%numMsgSend), &
3160 : bufRecv(bufSizeRecv*nz, halo%numMsgRecv), & ! LCOV_EXCL_LINE
3161 : bufTripole(nxGlobal, halo%tripoleRows, nz), & ! LCOV_EXCL_LINE
3162 0 : stat=ierr)
3163 :
3164 0 : if (ierr > 0) then
3165 0 : call abort_ice(subname//'ERROR: allocating buffers')
3166 0 : return
3167 : endif
3168 :
3169 0 : bufTripole = fill
3170 :
3171 : !-----------------------------------------------------------------------
3172 : !
3173 : ! post receives
3174 : !
3175 : !-----------------------------------------------------------------------
3176 :
3177 0 : do nmsg=1,halo%numMsgRecv
3178 :
3179 0 : len = halo%SizeRecv(nmsg)*nz
3180 0 : call MPI_IRECV(bufRecv(1:len,nmsg), len, mpiR4, &
3181 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
3182 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
3183 0 : halo%communicator, rcvRequest(nmsg), ierr)
3184 : end do
3185 :
3186 : !-----------------------------------------------------------------------
3187 : !
3188 : ! fill send buffer and post sends
3189 : !
3190 : !-----------------------------------------------------------------------
3191 :
3192 0 : do nmsg=1,halo%numMsgSend
3193 :
3194 0 : i=0
3195 0 : do n=1,halo%sizeSend(nmsg)
3196 0 : iSrc = halo%sendAddr(1,n,nmsg)
3197 0 : jSrc = halo%sendAddr(2,n,nmsg)
3198 0 : srcBlock = halo%sendAddr(3,n,nmsg)
3199 :
3200 0 : do k=1,nz
3201 0 : i = i + 1
3202 0 : bufSend(i,nmsg) = array(iSrc,jSrc,k,srcBlock)
3203 : end do
3204 : end do
3205 0 : do n=i+1,bufSizeSend*nz
3206 0 : bufSend(n,nmsg) = fill ! fill remainder of buffer
3207 : end do
3208 :
3209 0 : len = halo%SizeSend(nmsg)*nz
3210 0 : call MPI_ISEND(bufSend(1:len,nmsg), len, mpiR4, &
3211 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
3212 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
3213 0 : halo%communicator, sndRequest(nmsg), ierr)
3214 : end do
3215 :
3216 : !-----------------------------------------------------------------------
3217 : !
3218 : ! while messages are being communicated, fill out halo region
3219 : ! needed for masked halos to ensure halo values are filled for
3220 : ! halo grid cells that are not updated
3221 : !
3222 : !-----------------------------------------------------------------------
3223 :
3224 0 : do iblk = 1, halo%numLocalBlocks
3225 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
3226 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
3227 0 : jlo=jlo, jhi=jhi)
3228 0 : do j = 1,nghost
3229 0 : array(1:nx_block, jlo-j,:,iblk) = fill
3230 0 : array(1:nx_block, jhi+j,:,iblk) = fill
3231 : enddo
3232 0 : do i = 1,nghost
3233 0 : array(ilo-i, 1:ny_block,:,iblk) = fill
3234 0 : array(ihi+i, 1:ny_block,:,iblk) = fill
3235 : enddo
3236 : enddo
3237 :
3238 : !-----------------------------------------------------------------------
3239 : !
3240 : ! do local copies while waiting for messages to complete
3241 : ! if srcBlock is zero, that denotes an eliminated land block or a
3242 : ! closed boundary where ghost cell values are undefined
3243 : ! if srcBlock is less than zero, the message is a copy out of the
3244 : ! tripole buffer and will be treated later
3245 : !
3246 : !-----------------------------------------------------------------------
3247 :
3248 0 : do nmsg=1,halo%numLocalCopies
3249 0 : iSrc = halo%srcLocalAddr(1,nmsg)
3250 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3251 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3252 0 : iDst = halo%dstLocalAddr(1,nmsg)
3253 0 : jDst = halo%dstLocalAddr(2,nmsg)
3254 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3255 :
3256 0 : if (srcBlock > 0) then
3257 0 : if (dstBlock > 0) then
3258 0 : do k=1,nz
3259 0 : array(iDst,jDst,k,dstBlock) = &
3260 0 : array(iSrc,jSrc,k,srcBlock)
3261 : end do
3262 0 : else if (dstBlock < 0) then ! tripole copy into buffer
3263 0 : do k=1,nz
3264 0 : bufTripole(iDst,jDst,k) = &
3265 0 : array(iSrc,jSrc,k,srcBlock)
3266 : end do
3267 : endif
3268 0 : else if (srcBlock == 0) then
3269 0 : do k=1,nz
3270 0 : array(iDst,jDst,k,dstBlock) = fill
3271 : end do
3272 : endif
3273 : end do
3274 :
3275 : !-----------------------------------------------------------------------
3276 : !
3277 : ! wait for receives to finish and then unpack the recv buffer into
3278 : ! ghost cells
3279 : !
3280 : !-----------------------------------------------------------------------
3281 :
3282 0 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
3283 :
3284 0 : do nmsg=1,halo%numMsgRecv
3285 0 : i = 0
3286 0 : do n=1,halo%sizeRecv(nmsg)
3287 0 : iDst = halo%recvAddr(1,n,nmsg)
3288 0 : jDst = halo%recvAddr(2,n,nmsg)
3289 0 : dstBlock = halo%recvAddr(3,n,nmsg)
3290 :
3291 0 : if (dstBlock > 0) then
3292 0 : do k=1,nz
3293 0 : i = i + 1
3294 0 : array(iDst,jDst,k,dstBlock) = bufRecv(i,nmsg)
3295 : end do
3296 0 : else if (dstBlock < 0) then !tripole
3297 0 : do k=1,nz
3298 0 : i = i + 1
3299 0 : bufTripole(iDst,jDst,k) = bufRecv(i,nmsg)
3300 : end do
3301 : endif
3302 : end do
3303 : end do
3304 :
3305 : !-----------------------------------------------------------------------
3306 : !
3307 : ! take care of northern boundary in tripole case
3308 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
3309 : ! (T-fold) of physical domain for entire (global) top row
3310 : !
3311 : !-----------------------------------------------------------------------
3312 :
3313 0 : if (nxGlobal > 0) then
3314 :
3315 0 : select case (fieldKind)
3316 : case (field_type_scalar)
3317 0 : isign = 1
3318 : case (field_type_vector)
3319 0 : isign = -1
3320 : case (field_type_angle)
3321 0 : isign = -1
3322 : case default
3323 0 : call abort_ice(subname//'ERROR: Unknown field kind')
3324 : end select
3325 :
3326 0 : if (halo%tripoleTFlag) then
3327 :
3328 0 : select case (fieldLoc)
3329 : case (field_loc_center) ! cell center location
3330 :
3331 0 : ioffset = -1
3332 0 : joffset = 0
3333 :
3334 : !*** top row is degenerate, so must enforce symmetry
3335 : !*** use average of two degenerate points for value
3336 :
3337 0 : do k=1,nz
3338 0 : do i = 2,nxGlobal/2
3339 0 : iDst = nxGlobal - i + 2
3340 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3341 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3342 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3343 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3344 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3345 : end do
3346 : end do
3347 :
3348 : case (field_loc_NEcorner) ! cell corner location
3349 :
3350 0 : ioffset = 0
3351 0 : joffset = 1
3352 :
3353 : case (field_loc_Eface) ! cell center location
3354 :
3355 0 : ioffset = 0
3356 0 : joffset = 0
3357 :
3358 : !*** top row is degenerate, so must enforce symmetry
3359 : !*** use average of two degenerate points for value
3360 :
3361 0 : do k=1,nz
3362 0 : do i = 1,nxGlobal/2
3363 0 : iDst = nxGlobal + 1 - i
3364 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3365 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3366 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3367 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3368 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3369 : end do
3370 : end do
3371 :
3372 : case (field_loc_Nface) ! cell corner (velocity) location
3373 :
3374 0 : ioffset = -1
3375 0 : joffset = 1
3376 :
3377 : case default
3378 0 : call abort_ice(subname//'ERROR: Unknown field location')
3379 : end select
3380 :
3381 : else ! tripole u-fold
3382 :
3383 0 : select case (fieldLoc)
3384 : case (field_loc_center) ! cell center location
3385 :
3386 0 : ioffset = 0
3387 0 : joffset = 0
3388 :
3389 : case (field_loc_NEcorner) ! cell corner location
3390 :
3391 0 : ioffset = 1
3392 0 : joffset = 1
3393 :
3394 : !*** top row is degenerate, so must enforce symmetry
3395 : !*** use average of two degenerate points for value
3396 :
3397 0 : do k=1,nz
3398 0 : do i = 1,nxGlobal/2 - 1
3399 0 : iDst = nxGlobal - i
3400 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3401 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3402 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3403 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3404 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3405 : end do
3406 : end do
3407 :
3408 : case (field_loc_Eface) ! cell center location
3409 :
3410 0 : ioffset = 1
3411 0 : joffset = 0
3412 :
3413 : case (field_loc_Nface) ! cell corner (velocity) location
3414 :
3415 0 : ioffset = 0
3416 0 : joffset = 1
3417 :
3418 : !*** top row is degenerate, so must enforce symmetry
3419 : !*** use average of two degenerate points for value
3420 :
3421 0 : do k=1,nz
3422 0 : do i = 1,nxGlobal/2
3423 0 : iDst = nxGlobal + 1 - i
3424 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3425 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3426 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3427 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3428 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3429 : end do
3430 : end do
3431 :
3432 : case default
3433 0 : call abort_ice(subname//'ERROR: Unknown field location')
3434 : end select
3435 :
3436 : endif
3437 :
3438 : !*** copy out of global tripole buffer into local
3439 : !*** ghost cells
3440 :
3441 : !*** look through local copies to find the copy out
3442 : !*** messages (srcBlock < 0)
3443 :
3444 0 : do nmsg=1,halo%numLocalCopies
3445 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3446 :
3447 0 : if (srcBlock < 0) then
3448 :
3449 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
3450 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3451 :
3452 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
3453 0 : jDst = halo%dstLocalAddr(2,nmsg)
3454 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3455 :
3456 : !*** correct for offsets
3457 0 : iSrc = iSrc - ioffset
3458 0 : jSrc = jSrc - joffset
3459 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
3460 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
3461 :
3462 : !*** for center and Eface on u-fold, and NE corner and Nface
3463 : !*** on T-fold, do not need to replace
3464 : !*** top row of physical domain, so jSrc should be
3465 : !*** out of range and skipped
3466 : !*** otherwise do the copy
3467 :
3468 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
3469 0 : do k=1,nz
3470 0 : array(iDst,jDst,k,dstBlock) = isign* &
3471 0 : bufTripole(iSrc,jSrc,k)
3472 : end do
3473 : endif
3474 :
3475 : endif
3476 : end do
3477 :
3478 : endif
3479 :
3480 : !-----------------------------------------------------------------------
3481 : !
3482 : ! wait for sends to complete and deallocate arrays
3483 : !
3484 : !-----------------------------------------------------------------------
3485 :
3486 0 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
3487 :
3488 0 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
3489 :
3490 0 : if (ierr > 0) then
3491 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
3492 0 : return
3493 : endif
3494 :
3495 0 : deallocate(bufSend, bufRecv, bufTripole, stat=ierr)
3496 :
3497 0 : if (ierr > 0) then
3498 0 : call abort_ice(subname//'ERROR: deallocating 3d buffers')
3499 0 : return
3500 : endif
3501 :
3502 : !-----------------------------------------------------------------------
3503 :
3504 0 : end subroutine ice_HaloUpdate3DR4
3505 :
3506 : !***********************************************************************
3507 :
3508 0 : subroutine ice_HaloUpdate3DI4(array, halo, &
3509 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
3510 : fillValue)
3511 :
3512 : ! This routine updates ghost cells for an input array and is a
3513 : ! member of a group of routines under the generic interface
3514 : ! ice\_HaloUpdate. This routine is the specific interface
3515 : ! for 3d horizontal arrays of double precision.
3516 :
3517 : type (ice_halo), intent(in) :: &
3518 : halo ! precomputed halo structure containing all
3519 : ! information needed for halo update
3520 :
3521 : integer (int_kind), intent(in) :: &
3522 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
3523 : fieldLoc ! id for location on horizontal grid
3524 : ! (center, NEcorner, Nface, Eface)
3525 :
3526 : integer (int_kind), intent(in), optional :: &
3527 : fillValue ! optional value to put in ghost cells
3528 : ! where neighbor points are unknown
3529 : ! (e.g. eliminated land blocks or
3530 : ! closed boundaries)
3531 :
3532 : integer (int_kind), dimension(:,:,:,:), intent(inout) :: &
3533 : array ! array containing field for which halo
3534 : ! needs to be updated
3535 :
3536 : !-----------------------------------------------------------------------
3537 : !
3538 : ! local variables
3539 : !
3540 : !-----------------------------------------------------------------------
3541 :
3542 : integer (int_kind) :: &
3543 : i,j,k,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
3544 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
3545 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
3546 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
3547 : nz, &! size of array in 3rd dimension ! LCOV_EXCL_LINE
3548 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
3549 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
3550 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
3551 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
3552 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
3553 : isign ! sign factor for tripole grids
3554 :
3555 : integer (int_kind), dimension(:), allocatable :: &
3556 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
3557 0 : rcvRequest ! MPI request ids
3558 :
3559 : integer (int_kind), dimension(:,:), allocatable :: &
3560 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
3561 0 : rcvStatus ! MPI status flags
3562 :
3563 : integer (int_kind) :: &
3564 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
3565 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
3566 :
3567 : integer (int_kind), dimension(:,:), allocatable :: &
3568 0 : bufSend, bufRecv ! 3d send,recv buffers
3569 :
3570 : integer (int_kind), dimension(:,:,:), allocatable :: &
3571 0 : bufTripole ! 3d tripole buffer
3572 :
3573 : integer (int_kind) :: len ! length of message
3574 :
3575 : character(len=*), parameter :: subname = '(ice_HaloUpdate3DI4)'
3576 :
3577 : !-----------------------------------------------------------------------
3578 : !
3579 : ! abort or return on unknown or noupdate field_loc or field_type
3580 : !
3581 : !-----------------------------------------------------------------------
3582 :
3583 0 : if (fieldLoc == field_loc_unknown .or. &
3584 : fieldKind == field_type_unknown) then
3585 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
3586 0 : return
3587 : endif
3588 :
3589 0 : if (fieldLoc == field_loc_noupdate .or. &
3590 : fieldKind == field_type_noupdate) then
3591 0 : return
3592 : endif
3593 :
3594 : !-----------------------------------------------------------------------
3595 : !
3596 : ! initialize error code and fill value
3597 : !
3598 : !-----------------------------------------------------------------------
3599 :
3600 0 : if (present(fillValue)) then
3601 0 : fill = fillValue
3602 : else
3603 0 : fill = 0_int_kind
3604 : endif
3605 :
3606 0 : nxGlobal = 0
3607 0 : if (allocated(bufTripoleI4)) nxGlobal = size(bufTripoleI4,dim=1)
3608 :
3609 : !-----------------------------------------------------------------------
3610 : !
3611 : ! allocate request and status arrays for messages
3612 : !
3613 : !-----------------------------------------------------------------------
3614 :
3615 : allocate(sndRequest(halo%numMsgSend), &
3616 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
3617 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
3618 0 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
3619 :
3620 0 : if (ierr > 0) then
3621 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
3622 0 : return
3623 : endif
3624 :
3625 : !-----------------------------------------------------------------------
3626 : !
3627 : ! allocate 3D buffers
3628 : !
3629 : !-----------------------------------------------------------------------
3630 :
3631 0 : nz = size(array, dim=3)
3632 :
3633 : allocate(bufSend(bufSizeSend*nz, halo%numMsgSend), &
3634 : bufRecv(bufSizeRecv*nz, halo%numMsgRecv), & ! LCOV_EXCL_LINE
3635 : bufTripole(nxGlobal, halo%tripoleRows, nz), & ! LCOV_EXCL_LINE
3636 0 : stat=ierr)
3637 :
3638 0 : if (ierr > 0) then
3639 0 : call abort_ice(subname//'ERROR: allocating buffers')
3640 0 : return
3641 : endif
3642 :
3643 0 : bufTripole = fill
3644 :
3645 : !-----------------------------------------------------------------------
3646 : !
3647 : ! post receives
3648 : !
3649 : !-----------------------------------------------------------------------
3650 :
3651 0 : do nmsg=1,halo%numMsgRecv
3652 :
3653 0 : len = halo%SizeRecv(nmsg)*nz
3654 0 : call MPI_IRECV(bufRecv(1:len,nmsg), len, MPI_INTEGER, &
3655 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
3656 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
3657 0 : halo%communicator, rcvRequest(nmsg), ierr)
3658 : end do
3659 :
3660 : !-----------------------------------------------------------------------
3661 : !
3662 : ! fill send buffer and post sends
3663 : !
3664 : !-----------------------------------------------------------------------
3665 :
3666 0 : do nmsg=1,halo%numMsgSend
3667 :
3668 0 : i=0
3669 0 : do n=1,halo%sizeSend(nmsg)
3670 0 : iSrc = halo%sendAddr(1,n,nmsg)
3671 0 : jSrc = halo%sendAddr(2,n,nmsg)
3672 0 : srcBlock = halo%sendAddr(3,n,nmsg)
3673 :
3674 0 : do k=1,nz
3675 0 : i = i + 1
3676 0 : bufSend(i,nmsg) = array(iSrc,jSrc,k,srcBlock)
3677 : end do
3678 : end do
3679 0 : do n=i+1,bufSizeSend*nz
3680 0 : bufSend(n,nmsg) = fill ! fill remainder of buffer
3681 : end do
3682 :
3683 0 : len = halo%SizeSend(nmsg)*nz
3684 0 : call MPI_ISEND(bufSend(1:len,nmsg), len, MPI_INTEGER, &
3685 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
3686 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
3687 0 : halo%communicator, sndRequest(nmsg), ierr)
3688 : end do
3689 :
3690 : !-----------------------------------------------------------------------
3691 : !
3692 : ! while messages are being communicated, fill out halo region
3693 : ! needed for masked halos to ensure halo values are filled for
3694 : ! halo grid cells that are not updated
3695 : !
3696 : !-----------------------------------------------------------------------
3697 :
3698 0 : do iblk = 1, halo%numLocalBlocks
3699 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
3700 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
3701 0 : jlo=jlo, jhi=jhi)
3702 0 : do j = 1,nghost
3703 0 : array(1:nx_block, jlo-j,:,iblk) = fill
3704 0 : array(1:nx_block, jhi+j,:,iblk) = fill
3705 : enddo
3706 0 : do i = 1,nghost
3707 0 : array(ilo-i, 1:ny_block,:,iblk) = fill
3708 0 : array(ihi+i, 1:ny_block,:,iblk) = fill
3709 : enddo
3710 : enddo
3711 :
3712 : !-----------------------------------------------------------------------
3713 : !
3714 : ! do local copies while waiting for messages to complete
3715 : ! if srcBlock is zero, that denotes an eliminated land block or a
3716 : ! closed boundary where ghost cell values are undefined
3717 : ! if srcBlock is less than zero, the message is a copy out of the
3718 : ! tripole buffer and will be treated later
3719 : !
3720 : !-----------------------------------------------------------------------
3721 :
3722 0 : do nmsg=1,halo%numLocalCopies
3723 0 : iSrc = halo%srcLocalAddr(1,nmsg)
3724 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3725 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3726 0 : iDst = halo%dstLocalAddr(1,nmsg)
3727 0 : jDst = halo%dstLocalAddr(2,nmsg)
3728 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3729 :
3730 0 : if (srcBlock > 0) then
3731 0 : if (dstBlock > 0) then
3732 0 : do k=1,nz
3733 0 : array(iDst,jDst,k,dstBlock) = &
3734 0 : array(iSrc,jSrc,k,srcBlock)
3735 : end do
3736 0 : else if (dstBlock < 0) then ! tripole copy into buffer
3737 0 : do k=1,nz
3738 0 : bufTripole(iDst,jDst,k) = &
3739 0 : array(iSrc,jSrc,k,srcBlock)
3740 : end do
3741 : endif
3742 0 : else if (srcBlock == 0) then
3743 0 : do k=1,nz
3744 0 : array(iDst,jDst,k,dstBlock) = fill
3745 : end do
3746 : endif
3747 : end do
3748 :
3749 : !-----------------------------------------------------------------------
3750 : !
3751 : ! wait for receives to finish and then unpack the recv buffer into
3752 : ! ghost cells
3753 : !
3754 : !-----------------------------------------------------------------------
3755 :
3756 0 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
3757 :
3758 0 : do nmsg=1,halo%numMsgRecv
3759 0 : i = 0
3760 0 : do n=1,halo%sizeRecv(nmsg)
3761 0 : iDst = halo%recvAddr(1,n,nmsg)
3762 0 : jDst = halo%recvAddr(2,n,nmsg)
3763 0 : dstBlock = halo%recvAddr(3,n,nmsg)
3764 :
3765 0 : if (dstBlock > 0) then
3766 0 : do k=1,nz
3767 0 : i = i + 1
3768 0 : array(iDst,jDst,k,dstBlock) = bufRecv(i,nmsg)
3769 : end do
3770 0 : else if (dstBlock < 0) then !tripole
3771 0 : do k=1,nz
3772 0 : i = i + 1
3773 0 : bufTripole(iDst,jDst,k) = bufRecv(i,nmsg)
3774 : end do
3775 : endif
3776 : end do
3777 : end do
3778 :
3779 : !-----------------------------------------------------------------------
3780 : !
3781 : ! take care of northern boundary in tripole case
3782 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
3783 : ! (T-fold) of physical domain for entire (global) top row
3784 : !
3785 : !-----------------------------------------------------------------------
3786 :
3787 0 : if (nxGlobal > 0) then
3788 :
3789 0 : select case (fieldKind)
3790 : case (field_type_scalar)
3791 0 : isign = 1
3792 : case (field_type_vector)
3793 0 : isign = -1
3794 : case (field_type_angle)
3795 0 : isign = -1
3796 : case default
3797 0 : call abort_ice(subname//'ERROR: Unknown field kind')
3798 : end select
3799 :
3800 0 : if (halo%tripoleTFlag) then
3801 :
3802 0 : select case (fieldLoc)
3803 : case (field_loc_center) ! cell center location
3804 :
3805 0 : ioffset = -1
3806 0 : joffset = 0
3807 :
3808 : !*** top row is degenerate, so must enforce symmetry
3809 : !*** use average of two degenerate points for value
3810 :
3811 0 : do k=1,nz
3812 0 : do i = 2,nxGlobal/2
3813 0 : iDst = nxGlobal - i + 2
3814 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3815 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3816 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3817 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3818 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3819 : end do
3820 : end do
3821 :
3822 : case (field_loc_NEcorner) ! cell corner location
3823 :
3824 0 : ioffset = 0
3825 0 : joffset = 1
3826 :
3827 : case (field_loc_Eface) ! cell center location
3828 :
3829 0 : ioffset = 0
3830 0 : joffset = 0
3831 :
3832 : !*** top row is degenerate, so must enforce symmetry
3833 : !*** use average of two degenerate points for value
3834 :
3835 0 : do k=1,nz
3836 0 : do i = 1,nxGlobal/2
3837 0 : iDst = nxGlobal + 1 - i
3838 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3839 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3840 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3841 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3842 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3843 : end do
3844 : end do
3845 :
3846 : case (field_loc_Nface) ! cell corner (velocity) location
3847 :
3848 0 : ioffset = -1
3849 0 : joffset = 1
3850 :
3851 : case default
3852 0 : call abort_ice(subname//'ERROR: Unknown field location')
3853 : end select
3854 :
3855 : else ! tripole u-fold
3856 :
3857 0 : select case (fieldLoc)
3858 : case (field_loc_center) ! cell center location
3859 :
3860 0 : ioffset = 0
3861 0 : joffset = 0
3862 :
3863 : case (field_loc_NEcorner) ! cell corner location
3864 :
3865 0 : ioffset = 1
3866 0 : joffset = 1
3867 :
3868 : !*** top row is degenerate, so must enforce symmetry
3869 : !*** use average of two degenerate points for value
3870 :
3871 0 : do k=1,nz
3872 0 : do i = 1,nxGlobal/2 - 1
3873 0 : iDst = nxGlobal - i
3874 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3875 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3876 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3877 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3878 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3879 : end do
3880 : end do
3881 :
3882 : case (field_loc_Eface) ! cell center location
3883 :
3884 0 : ioffset = 1
3885 0 : joffset = 0
3886 :
3887 : case (field_loc_Nface) ! cell corner (velocity) location
3888 :
3889 0 : ioffset = 0
3890 0 : joffset = 1
3891 :
3892 : !*** top row is degenerate, so must enforce symmetry
3893 : !*** use average of two degenerate points for value
3894 :
3895 0 : do k=1,nz
3896 0 : do i = 1,nxGlobal/2
3897 0 : iDst = nxGlobal + 1 - i
3898 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
3899 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
3900 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3901 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
3902 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
3903 : end do
3904 : end do
3905 :
3906 : case default
3907 0 : call abort_ice(subname//'ERROR: Unknown field location')
3908 : end select
3909 :
3910 : endif
3911 :
3912 : !*** copy out of global tripole buffer into local
3913 : !*** ghost cells
3914 :
3915 : !*** look through local copies to find the copy out
3916 : !*** messages (srcBlock < 0)
3917 :
3918 0 : do nmsg=1,halo%numLocalCopies
3919 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3920 :
3921 0 : if (srcBlock < 0) then
3922 :
3923 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
3924 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3925 :
3926 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
3927 0 : jDst = halo%dstLocalAddr(2,nmsg)
3928 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3929 :
3930 : !*** correct for offsets
3931 0 : iSrc = iSrc - ioffset
3932 0 : jSrc = jSrc - joffset
3933 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
3934 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
3935 :
3936 : !*** for center and Eface on u-fold, and NE corner and Nface
3937 : !*** on T-fold, do not need to replace
3938 : !*** top row of physical domain, so jSrc should be
3939 : !*** out of range and skipped
3940 : !*** otherwise do the copy
3941 :
3942 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
3943 0 : do k=1,nz
3944 0 : array(iDst,jDst,k,dstBlock) = isign* &
3945 0 : bufTripole(iSrc,jSrc,k)
3946 : end do
3947 : endif
3948 :
3949 : endif
3950 : end do
3951 :
3952 : endif
3953 :
3954 : !-----------------------------------------------------------------------
3955 : !
3956 : ! wait for sends to complete and deallocate arrays
3957 : !
3958 : !-----------------------------------------------------------------------
3959 :
3960 0 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
3961 :
3962 0 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
3963 :
3964 0 : if (ierr > 0) then
3965 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
3966 0 : return
3967 : endif
3968 :
3969 0 : deallocate(bufSend, bufRecv, bufTripole, stat=ierr)
3970 :
3971 0 : if (ierr > 0) then
3972 0 : call abort_ice(subname//'ERROR: deallocating 3d buffers')
3973 0 : return
3974 : endif
3975 :
3976 : !-----------------------------------------------------------------------
3977 :
3978 0 : end subroutine ice_HaloUpdate3DI4
3979 :
3980 : !***********************************************************************
3981 :
3982 34596 : subroutine ice_HaloUpdate4DR8(array, halo, &
3983 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
3984 : fillValue)
3985 :
3986 : ! This routine updates ghost cells for an input array and is a
3987 : ! member of a group of routines under the generic interface
3988 : ! ice\_HaloUpdate. This routine is the specific interface
3989 : ! for 4d horizontal arrays of double precision.
3990 :
3991 : type (ice_halo), intent(in) :: &
3992 : halo ! precomputed halo structure containing all
3993 : ! information needed for halo update
3994 :
3995 : integer (int_kind), intent(in) :: &
3996 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
3997 : fieldLoc ! id for location on horizontal grid
3998 : ! (center, NEcorner, Nface, Eface)
3999 :
4000 : real (dbl_kind), intent(in), optional :: &
4001 : fillValue ! optional value to put in ghost cells
4002 : ! where neighbor points are unknown
4003 : ! (e.g. eliminated land blocks or
4004 : ! closed boundaries)
4005 :
4006 : real (dbl_kind), dimension(:,:,:,:,:), intent(inout) :: &
4007 : array ! array containing field for which halo
4008 : ! needs to be updated
4009 :
4010 : !-----------------------------------------------------------------------
4011 : !
4012 : ! local variables
4013 : !
4014 : !-----------------------------------------------------------------------
4015 :
4016 : integer (int_kind) :: &
4017 : i,j,k,l,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
4018 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
4019 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
4020 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
4021 : nz, nt, &! size of array in 3rd,4th dimensions ! LCOV_EXCL_LINE
4022 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
4023 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
4024 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
4025 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
4026 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
4027 : isign ! sign factor for tripole grids
4028 :
4029 : integer (int_kind), dimension(:), allocatable :: &
4030 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
4031 34596 : rcvRequest ! MPI request ids
4032 :
4033 : integer (int_kind), dimension(:,:), allocatable :: &
4034 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
4035 34596 : rcvStatus ! MPI status flags
4036 :
4037 : real (dbl_kind) :: &
4038 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
4039 8648 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
4040 :
4041 : real (dbl_kind), dimension(:,:), allocatable :: &
4042 34596 : bufSend, bufRecv ! 4d send,recv buffers
4043 :
4044 : real (dbl_kind), dimension(:,:,:,:), allocatable :: &
4045 34596 : bufTripole ! 4d tripole buffer
4046 :
4047 : integer (int_kind) :: len ! length of message
4048 :
4049 : character(len=*), parameter :: subname = '(ice_HaloUpdate4DR8)'
4050 :
4051 : !-----------------------------------------------------------------------
4052 : !
4053 : ! abort or return on unknown or noupdate field_loc or field_type
4054 : !
4055 : !-----------------------------------------------------------------------
4056 :
4057 34596 : if (fieldLoc == field_loc_unknown .or. &
4058 : fieldKind == field_type_unknown) then
4059 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
4060 0 : return
4061 : endif
4062 :
4063 34596 : if (fieldLoc == field_loc_noupdate .or. &
4064 : fieldKind == field_type_noupdate) then
4065 0 : return
4066 : endif
4067 :
4068 : !-----------------------------------------------------------------------
4069 : !
4070 : ! initialize error code and fill value
4071 : !
4072 : !-----------------------------------------------------------------------
4073 :
4074 34596 : if (present(fillValue)) then
4075 0 : fill = fillValue
4076 : else
4077 34596 : fill = 0.0_dbl_kind
4078 : endif
4079 :
4080 34596 : nxGlobal = 0
4081 34596 : if (allocated(bufTripoleR8)) nxGlobal = size(bufTripoleR8,dim=1)
4082 :
4083 : !-----------------------------------------------------------------------
4084 : !
4085 : ! allocate request and status arrays for messages
4086 : !
4087 : !-----------------------------------------------------------------------
4088 :
4089 : allocate(sndRequest(halo%numMsgSend), &
4090 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
4091 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
4092 34596 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
4093 :
4094 34596 : if (ierr > 0) then
4095 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
4096 0 : return
4097 : endif
4098 :
4099 : !-----------------------------------------------------------------------
4100 : !
4101 : ! allocate 4D buffers
4102 : !
4103 : !-----------------------------------------------------------------------
4104 :
4105 34596 : nz = size(array, dim=3)
4106 34596 : nt = size(array, dim=4)
4107 :
4108 : allocate(bufSend(bufSizeSend*nz*nt, halo%numMsgSend), &
4109 : bufRecv(bufSizeRecv*nz*nt, halo%numMsgRecv), & ! LCOV_EXCL_LINE
4110 : bufTripole(nxGlobal, halo%tripoleRows, nz, nt), & ! LCOV_EXCL_LINE
4111 34596 : stat=ierr)
4112 :
4113 34596 : if (ierr > 0) then
4114 0 : call abort_ice(subname//'ERROR: allocating buffers')
4115 0 : return
4116 : endif
4117 :
4118 13180536 : bufTripole = fill
4119 :
4120 : !-----------------------------------------------------------------------
4121 : !
4122 : ! post receives
4123 : !
4124 : !-----------------------------------------------------------------------
4125 :
4126 196048 : do nmsg=1,halo%numMsgRecv
4127 :
4128 161452 : len = halo%SizeRecv(nmsg)*nz*nt
4129 0 : call MPI_IRECV(bufRecv(1:len,nmsg), len, mpiR8, &
4130 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
4131 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
4132 196048 : halo%communicator, rcvRequest(nmsg), ierr)
4133 : end do
4134 :
4135 : !-----------------------------------------------------------------------
4136 : !
4137 : ! fill send buffer and post sends
4138 : !
4139 : !-----------------------------------------------------------------------
4140 :
4141 196048 : do nmsg=1,halo%numMsgSend
4142 :
4143 161452 : i=0
4144 8886412 : do n=1,halo%sizeSend(nmsg)
4145 8724960 : iSrc = halo%sendAddr(1,n,nmsg)
4146 8724960 : jSrc = halo%sendAddr(2,n,nmsg)
4147 8724960 : srcBlock = halo%sendAddr(3,n,nmsg)
4148 :
4149 52511212 : do l=1,nt
4150 1142919360 : do k=1,nz
4151 1090569600 : i = i + 1
4152 1134194400 : bufSend(i,nmsg) = array(iSrc,jSrc,k,l,srcBlock)
4153 : end do
4154 : end do
4155 : end do
4156 :
4157 1605492652 : do n=i+1,bufSizeSend*nz*nt
4158 1605492652 : bufSend(n,nmsg) = fill ! fill remainder of buffer
4159 : end do
4160 :
4161 161452 : len = halo%SizeSend(nmsg)*nz*nt
4162 0 : call MPI_ISEND(bufSend(1:len,nmsg), len, mpiR8, &
4163 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
4164 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
4165 196048 : halo%communicator, sndRequest(nmsg), ierr)
4166 : end do
4167 :
4168 : !-----------------------------------------------------------------------
4169 : !
4170 : ! while messages are being communicated, fill out halo region
4171 : ! needed for masked halos to ensure halo values are filled for
4172 : ! halo grid cells that are not updated
4173 : !
4174 : !-----------------------------------------------------------------------
4175 :
4176 172275 : do iblk = 1, halo%numLocalBlocks
4177 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
4178 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
4179 137679 : jlo=jlo, jhi=jhi)
4180 275358 : do j = 1,nghost
4181 370557594 : array(1:nx_block, jlo-j,:,:,iblk) = fill
4182 370695273 : array(1:nx_block, jhi+j,:,:,iblk) = fill
4183 : enddo
4184 447633 : do i = 1,nghost
4185 564488154 : array(ilo-i, 1:ny_block,:,:,iblk) = fill
4186 564625833 : array(ihi+i, 1:ny_block,:,:,iblk) = fill
4187 : enddo
4188 : enddo
4189 :
4190 : !-----------------------------------------------------------------------
4191 : !
4192 : ! do local copies while waiting for messages to complete
4193 : ! if srcBlock is zero, that denotes an eliminated land block or a
4194 : ! closed boundary where ghost cell values are undefined
4195 : ! if srcBlock is less than zero, the message is a copy out of the
4196 : ! tripole buffer and will be treated later
4197 : !
4198 : !-----------------------------------------------------------------------
4199 :
4200 3730492 : do nmsg=1,halo%numLocalCopies
4201 3695896 : iSrc = halo%srcLocalAddr(1,nmsg)
4202 3695896 : jSrc = halo%srcLocalAddr(2,nmsg)
4203 3695896 : srcBlock = halo%srcLocalAddr(3,nmsg)
4204 3695896 : iDst = halo%dstLocalAddr(1,nmsg)
4205 3695896 : jDst = halo%dstLocalAddr(2,nmsg)
4206 3695896 : dstBlock = halo%dstLocalAddr(3,nmsg)
4207 :
4208 3730492 : if (srcBlock > 0) then
4209 3643984 : if (dstBlock > 0) then
4210 21863904 : do l=1,nt
4211 477343584 : do k=1,nz
4212 237811200 : array(iDst,jDst,k,l,dstBlock) = &
4213 473699600 : array(iSrc,jSrc,k,l,srcBlock)
4214 : end do
4215 : end do
4216 0 : else if (dstBlock < 0) then ! tripole copy into buffer
4217 0 : do l=1,nt
4218 0 : do k=1,nz
4219 0 : bufTripole(iDst,jDst,k,l) = &
4220 0 : array(iSrc,jSrc,k,l,srcBlock)
4221 : end do
4222 : end do
4223 : endif
4224 51912 : else if (srcBlock == 0) then
4225 311472 : do l=1,nt
4226 6800112 : do k=1,nz
4227 6748200 : array(iDst,jDst,k,l,dstBlock) = fill
4228 : end do
4229 : end do
4230 : endif
4231 : end do
4232 :
4233 : !-----------------------------------------------------------------------
4234 : !
4235 : ! wait for receives to finish and then unpack the recv buffer into
4236 : ! ghost cells
4237 : !
4238 : !-----------------------------------------------------------------------
4239 :
4240 34596 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
4241 :
4242 196048 : do nmsg=1,halo%numMsgRecv
4243 161452 : i = 0
4244 8921008 : do n=1,halo%sizeRecv(nmsg)
4245 8724960 : iDst = halo%recvAddr(1,n,nmsg)
4246 8724960 : jDst = halo%recvAddr(2,n,nmsg)
4247 8724960 : dstBlock = halo%recvAddr(3,n,nmsg)
4248 :
4249 8886412 : if (dstBlock > 0) then
4250 52349760 : do l=1,nt
4251 1142919360 : do k=1,nz
4252 1090569600 : i = i + 1
4253 1134194400 : array(iDst,jDst,k,l,dstBlock) = bufRecv(i,nmsg)
4254 : end do
4255 : end do
4256 0 : else if (dstBlock < 0) then !tripole
4257 0 : do l=1,nt
4258 0 : do k=1,nz
4259 0 : i = i + 1
4260 0 : bufTripole(iDst,jDst,k,l) = bufRecv(i,nmsg)
4261 : end do
4262 : end do
4263 : endif
4264 : end do
4265 : end do
4266 :
4267 : !-----------------------------------------------------------------------
4268 : !
4269 : ! take care of northern boundary in tripole case
4270 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
4271 : ! (T-fold) of physical domain for entire (global) top row
4272 : !
4273 : !-----------------------------------------------------------------------
4274 :
4275 34596 : if (nxGlobal > 0) then
4276 :
4277 0 : select case (fieldKind)
4278 : case (field_type_scalar)
4279 0 : isign = 1
4280 : case (field_type_vector)
4281 0 : isign = -1
4282 : case (field_type_angle)
4283 0 : isign = -1
4284 : case default
4285 0 : call abort_ice(subname//'ERROR: Unknown field kind')
4286 : end select
4287 :
4288 0 : if (halo%tripoleTFlag) then
4289 :
4290 0 : select case (fieldLoc)
4291 : case (field_loc_center) ! cell center location
4292 :
4293 0 : ioffset = -1
4294 0 : joffset = 0
4295 :
4296 : !*** top row is degenerate, so must enforce symmetry
4297 : !*** use average of two degenerate points for value
4298 :
4299 0 : do l=1,nt
4300 0 : do k=1,nz
4301 0 : do i = 2,nxGlobal/2
4302 0 : iDst = nxGlobal - i + 2
4303 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4304 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4305 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
4306 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4307 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4308 : end do
4309 : end do
4310 : end do
4311 :
4312 : case (field_loc_NEcorner) ! cell corner location
4313 :
4314 0 : ioffset = 0
4315 0 : joffset = 1
4316 :
4317 : case (field_loc_Eface) ! cell center location
4318 :
4319 0 : ioffset = 0
4320 0 : joffset = 0
4321 :
4322 : !*** top row is degenerate, so must enforce symmetry
4323 : !*** use average of two degenerate points for value
4324 :
4325 0 : do l=1,nt
4326 0 : do k=1,nz
4327 0 : do i = 1,nxGlobal/2
4328 0 : iDst = nxGlobal + 1 - i
4329 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4330 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4331 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
4332 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4333 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4334 : end do
4335 : end do
4336 : end do
4337 :
4338 : case (field_loc_Nface) ! cell corner (velocity) location
4339 :
4340 0 : ioffset = -1
4341 0 : joffset = 1
4342 :
4343 : case default
4344 0 : call abort_ice(subname//'ERROR: Unknown field location')
4345 : end select
4346 :
4347 : else ! tripole u-fold
4348 :
4349 0 : select case (fieldLoc)
4350 : case (field_loc_center) ! cell center location
4351 :
4352 0 : ioffset = 0
4353 0 : joffset = 0
4354 :
4355 : case (field_loc_NEcorner) ! cell corner location
4356 :
4357 0 : ioffset = 1
4358 0 : joffset = 1
4359 :
4360 : !*** top row is degenerate, so must enforce symmetry
4361 : !*** use average of two degenerate points for value
4362 :
4363 0 : do l=1,nt
4364 0 : do k=1,nz
4365 0 : do i = 1,nxGlobal/2 - 1
4366 0 : iDst = nxGlobal - i
4367 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4368 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4369 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
4370 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4371 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4372 : end do
4373 : end do
4374 : end do
4375 :
4376 : case (field_loc_Eface) ! cell center location
4377 :
4378 0 : ioffset = 1
4379 0 : joffset = 0
4380 :
4381 : case (field_loc_Nface) ! cell corner (velocity) location
4382 :
4383 0 : ioffset = 0
4384 0 : joffset = 1
4385 :
4386 : !*** top row is degenerate, so must enforce symmetry
4387 : !*** use average of two degenerate points for value
4388 :
4389 0 : do l=1,nt
4390 0 : do k=1,nz
4391 0 : do i = 1,nxGlobal/2
4392 0 : iDst = nxGlobal + 1 - i
4393 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4394 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4395 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
4396 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4397 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4398 : end do
4399 : end do
4400 : end do
4401 :
4402 : case default
4403 0 : call abort_ice(subname//'ERROR: Unknown field location')
4404 : end select
4405 :
4406 : endif
4407 :
4408 : !*** copy out of global tripole buffer into local
4409 : !*** ghost cells
4410 :
4411 : !*** look through local copies to find the copy out
4412 : !*** messages (srcBlock < 0)
4413 :
4414 0 : do nmsg=1,halo%numLocalCopies
4415 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
4416 :
4417 0 : if (srcBlock < 0) then
4418 :
4419 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
4420 0 : jSrc = halo%srcLocalAddr(2,nmsg)
4421 :
4422 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
4423 0 : jDst = halo%dstLocalAddr(2,nmsg)
4424 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
4425 :
4426 : !*** correct for offsets
4427 0 : iSrc = iSrc - ioffset
4428 0 : jSrc = jSrc - joffset
4429 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
4430 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
4431 :
4432 : !*** for center and Eface on u-fold, and NE corner and Nface
4433 : !*** on T-fold, do not need to replace
4434 : !*** top row of physical domain, so jSrc should be
4435 : !*** out of range and skipped
4436 : !*** otherwise do the copy
4437 :
4438 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
4439 0 : do l=1,nt
4440 0 : do k=1,nz
4441 0 : array(iDst,jDst,k,l,dstBlock) = isign* &
4442 0 : bufTripole(iSrc,jSrc,k,l)
4443 : end do
4444 : end do
4445 : endif
4446 :
4447 : endif
4448 : end do
4449 :
4450 : endif
4451 :
4452 : !-----------------------------------------------------------------------
4453 : !
4454 : ! wait for sends to complete and deallocate arrays
4455 : !
4456 : !-----------------------------------------------------------------------
4457 :
4458 34596 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
4459 :
4460 34596 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
4461 :
4462 34596 : if (ierr > 0) then
4463 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
4464 0 : return
4465 : endif
4466 :
4467 34596 : deallocate(bufSend, bufRecv, bufTripole, stat=ierr)
4468 :
4469 34596 : if (ierr > 0) then
4470 0 : call abort_ice(subname//'ERROR: deallocating 4d buffers')
4471 0 : return
4472 : endif
4473 :
4474 : !-----------------------------------------------------------------------
4475 :
4476 103788 : end subroutine ice_HaloUpdate4DR8
4477 :
4478 : !***********************************************************************
4479 :
4480 0 : subroutine ice_HaloUpdate4DR4(array, halo, &
4481 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
4482 : fillValue)
4483 :
4484 : ! This routine updates ghost cells for an input array and is a
4485 : ! member of a group of routines under the generic interface
4486 : ! ice\_HaloUpdate. This routine is the specific interface
4487 : ! for 4d horizontal arrays of single precision.
4488 :
4489 : type (ice_halo), intent(in) :: &
4490 : halo ! precomputed halo structure containing all
4491 : ! information needed for halo update
4492 :
4493 : integer (int_kind), intent(in) :: &
4494 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
4495 : fieldLoc ! id for location on horizontal grid
4496 : ! (center, NEcorner, Nface, Eface)
4497 :
4498 : real (real_kind), intent(in), optional :: &
4499 : fillValue ! optional value to put in ghost cells
4500 : ! where neighbor points are unknown
4501 : ! (e.g. eliminated land blocks or
4502 : ! closed boundaries)
4503 :
4504 : real (real_kind), dimension(:,:,:,:,:), intent(inout) :: &
4505 : array ! array containing field for which halo
4506 : ! needs to be updated
4507 :
4508 : !-----------------------------------------------------------------------
4509 : !
4510 : ! local variables
4511 : !
4512 : !-----------------------------------------------------------------------
4513 :
4514 : integer (int_kind) :: &
4515 : i,j,k,l,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
4516 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
4517 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
4518 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
4519 : nz, nt, &! size of array in 3rd,4th dimensions ! LCOV_EXCL_LINE
4520 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
4521 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
4522 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
4523 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
4524 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
4525 : isign ! sign factor for tripole grids
4526 :
4527 : integer (int_kind), dimension(:), allocatable :: &
4528 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
4529 0 : rcvRequest ! MPI request ids
4530 :
4531 : integer (int_kind), dimension(:,:), allocatable :: &
4532 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
4533 0 : rcvStatus ! MPI status flags
4534 :
4535 : real (real_kind) :: &
4536 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
4537 0 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
4538 :
4539 : real (real_kind), dimension(:,:), allocatable :: &
4540 0 : bufSend, bufRecv ! 4d send,recv buffers
4541 :
4542 : real (real_kind), dimension(:,:,:,:), allocatable :: &
4543 0 : bufTripole ! 4d tripole buffer
4544 :
4545 : integer (int_kind) :: len ! length of message
4546 :
4547 : character(len=*), parameter :: subname = '(ice_HaloUpdate4DR4)'
4548 :
4549 : !-----------------------------------------------------------------------
4550 : !
4551 : ! abort or return on unknown or noupdate field_loc or field_type
4552 : !
4553 : !-----------------------------------------------------------------------
4554 :
4555 0 : if (fieldLoc == field_loc_unknown .or. &
4556 : fieldKind == field_type_unknown) then
4557 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
4558 0 : return
4559 : endif
4560 :
4561 0 : if (fieldLoc == field_loc_noupdate .or. &
4562 : fieldKind == field_type_noupdate) then
4563 0 : return
4564 : endif
4565 :
4566 : !-----------------------------------------------------------------------
4567 : !
4568 : ! initialize error code and fill value
4569 : !
4570 : !-----------------------------------------------------------------------
4571 :
4572 0 : if (present(fillValue)) then
4573 0 : fill = fillValue
4574 : else
4575 0 : fill = 0.0_real_kind
4576 : endif
4577 :
4578 0 : nxGlobal = 0
4579 0 : if (allocated(bufTripoleR4)) nxGlobal = size(bufTripoleR4,dim=1)
4580 :
4581 : !-----------------------------------------------------------------------
4582 : !
4583 : ! allocate request and status arrays for messages
4584 : !
4585 : !-----------------------------------------------------------------------
4586 :
4587 : allocate(sndRequest(halo%numMsgSend), &
4588 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
4589 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
4590 0 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
4591 :
4592 0 : if (ierr > 0) then
4593 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
4594 0 : return
4595 : endif
4596 :
4597 : !-----------------------------------------------------------------------
4598 : !
4599 : ! allocate 4D buffers
4600 : !
4601 : !-----------------------------------------------------------------------
4602 :
4603 0 : nz = size(array, dim=3)
4604 0 : nt = size(array, dim=4)
4605 :
4606 : allocate(bufSend(bufSizeSend*nz*nt, halo%numMsgSend), &
4607 : bufRecv(bufSizeRecv*nz*nt, halo%numMsgRecv), & ! LCOV_EXCL_LINE
4608 : bufTripole(nxGlobal, halo%tripoleRows, nz, nt), & ! LCOV_EXCL_LINE
4609 0 : stat=ierr)
4610 :
4611 0 : if (ierr > 0) then
4612 0 : call abort_ice(subname//'ERROR: allocating buffers')
4613 0 : return
4614 : endif
4615 :
4616 0 : bufTripole = fill
4617 :
4618 : !-----------------------------------------------------------------------
4619 : !
4620 : ! post receives
4621 : !
4622 : !-----------------------------------------------------------------------
4623 :
4624 0 : do nmsg=1,halo%numMsgRecv
4625 :
4626 0 : len = halo%SizeRecv(nmsg)*nz*nt
4627 0 : call MPI_IRECV(bufRecv(1:len,nmsg), len, mpiR4, &
4628 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
4629 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
4630 0 : halo%communicator, rcvRequest(nmsg), ierr)
4631 : end do
4632 :
4633 : !-----------------------------------------------------------------------
4634 : !
4635 : ! fill send buffer and post sends
4636 : !
4637 : !-----------------------------------------------------------------------
4638 :
4639 0 : do nmsg=1,halo%numMsgSend
4640 :
4641 0 : i=0
4642 0 : do n=1,halo%sizeSend(nmsg)
4643 0 : iSrc = halo%sendAddr(1,n,nmsg)
4644 0 : jSrc = halo%sendAddr(2,n,nmsg)
4645 0 : srcBlock = halo%sendAddr(3,n,nmsg)
4646 :
4647 0 : do l=1,nt
4648 0 : do k=1,nz
4649 0 : i = i + 1
4650 0 : bufSend(i,nmsg) = array(iSrc,jSrc,k,l,srcBlock)
4651 : end do
4652 : end do
4653 : end do
4654 :
4655 0 : do n=i+1,bufSizeSend*nz*nt
4656 0 : bufSend(n,nmsg) = fill ! fill remainder of buffer
4657 : end do
4658 :
4659 0 : len = halo%SizeSend(nmsg)*nz*nt
4660 0 : call MPI_ISEND(bufSend(1:len,nmsg), len, mpiR4, &
4661 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
4662 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
4663 0 : halo%communicator, sndRequest(nmsg), ierr)
4664 : end do
4665 :
4666 : !-----------------------------------------------------------------------
4667 : !
4668 : ! while messages are being communicated, fill out halo region
4669 : ! needed for masked halos to ensure halo values are filled for
4670 : ! halo grid cells that are not updated
4671 : !
4672 : !-----------------------------------------------------------------------
4673 :
4674 0 : do iblk = 1, halo%numLocalBlocks
4675 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
4676 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
4677 0 : jlo=jlo, jhi=jhi)
4678 0 : do j = 1,nghost
4679 0 : array(1:nx_block, jlo-j,:,:,iblk) = fill
4680 0 : array(1:nx_block, jhi+j,:,:,iblk) = fill
4681 : enddo
4682 0 : do i = 1,nghost
4683 0 : array(ilo-i, 1:ny_block,:,:,iblk) = fill
4684 0 : array(ihi+i, 1:ny_block,:,:,iblk) = fill
4685 : enddo
4686 : enddo
4687 :
4688 : !-----------------------------------------------------------------------
4689 : !
4690 : ! do local copies while waiting for messages to complete
4691 : ! if srcBlock is zero, that denotes an eliminated land block or a
4692 : ! closed boundary where ghost cell values are undefined
4693 : ! if srcBlock is less than zero, the message is a copy out of the
4694 : ! tripole buffer and will be treated later
4695 : !
4696 : !-----------------------------------------------------------------------
4697 :
4698 0 : do nmsg=1,halo%numLocalCopies
4699 0 : iSrc = halo%srcLocalAddr(1,nmsg)
4700 0 : jSrc = halo%srcLocalAddr(2,nmsg)
4701 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
4702 0 : iDst = halo%dstLocalAddr(1,nmsg)
4703 0 : jDst = halo%dstLocalAddr(2,nmsg)
4704 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
4705 :
4706 0 : if (srcBlock > 0) then
4707 0 : if (dstBlock > 0) then
4708 0 : do l=1,nt
4709 0 : do k=1,nz
4710 0 : array(iDst,jDst,k,l,dstBlock) = &
4711 0 : array(iSrc,jSrc,k,l,srcBlock)
4712 : end do
4713 : end do
4714 0 : else if (dstBlock < 0) then ! tripole copy into buffer
4715 0 : do l=1,nt
4716 0 : do k=1,nz
4717 0 : bufTripole(iDst,jDst,k,l) = &
4718 0 : array(iSrc,jSrc,k,l,srcBlock)
4719 : end do
4720 : end do
4721 : endif
4722 0 : else if (srcBlock == 0) then
4723 0 : do l=1,nt
4724 0 : do k=1,nz
4725 0 : array(iDst,jDst,k,l,dstBlock) = fill
4726 : end do
4727 : end do
4728 : endif
4729 : end do
4730 :
4731 : !-----------------------------------------------------------------------
4732 : !
4733 : ! wait for receives to finish and then unpack the recv buffer into
4734 : ! ghost cells
4735 : !
4736 : !-----------------------------------------------------------------------
4737 :
4738 0 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
4739 :
4740 0 : do nmsg=1,halo%numMsgRecv
4741 0 : i = 0
4742 0 : do n=1,halo%sizeRecv(nmsg)
4743 0 : iDst = halo%recvAddr(1,n,nmsg)
4744 0 : jDst = halo%recvAddr(2,n,nmsg)
4745 0 : dstBlock = halo%recvAddr(3,n,nmsg)
4746 :
4747 0 : if (dstBlock > 0) then
4748 0 : do l=1,nt
4749 0 : do k=1,nz
4750 0 : i = i + 1
4751 0 : array(iDst,jDst,k,l,dstBlock) = bufRecv(i,nmsg)
4752 : end do
4753 : end do
4754 0 : else if (dstBlock < 0) then !tripole
4755 0 : do l=1,nt
4756 0 : do k=1,nz
4757 0 : i = i + 1
4758 0 : bufTripole(iDst,jDst,k,l) = bufRecv(i,nmsg)
4759 : end do
4760 : end do
4761 : endif
4762 : end do
4763 : end do
4764 :
4765 : !-----------------------------------------------------------------------
4766 : !
4767 : ! take care of northern boundary in tripole case
4768 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
4769 : ! (T-fold) of physical domain for entire (global) top row
4770 : !
4771 : !-----------------------------------------------------------------------
4772 :
4773 0 : if (nxGlobal > 0) then
4774 :
4775 0 : select case (fieldKind)
4776 : case (field_type_scalar)
4777 0 : isign = 1
4778 : case (field_type_vector)
4779 0 : isign = -1
4780 : case (field_type_angle)
4781 0 : isign = -1
4782 : case default
4783 0 : call abort_ice(subname//'ERROR: Unknown field kind')
4784 : end select
4785 :
4786 0 : if (halo%tripoleTFlag) then
4787 :
4788 0 : select case (fieldLoc)
4789 : case (field_loc_center) ! cell center location
4790 :
4791 0 : ioffset = -1
4792 0 : joffset = 0
4793 :
4794 : !*** top row is degenerate, so must enforce symmetry
4795 : !*** use average of two degenerate points for value
4796 :
4797 0 : do l=1,nt
4798 0 : do k=1,nz
4799 0 : do i = 2,nxGlobal/2
4800 0 : iDst = nxGlobal - i + 2
4801 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4802 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4803 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
4804 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4805 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4806 : end do
4807 : end do
4808 : end do
4809 :
4810 : case (field_loc_NEcorner) ! cell corner location
4811 :
4812 0 : ioffset = 0
4813 0 : joffset = 1
4814 :
4815 : case (field_loc_Eface) ! cell center location
4816 :
4817 0 : ioffset = 0
4818 0 : joffset = 0
4819 :
4820 : !*** top row is degenerate, so must enforce symmetry
4821 : !*** use average of two degenerate points for value
4822 :
4823 0 : do l=1,nt
4824 0 : do k=1,nz
4825 0 : do i = 1,nxGlobal/2
4826 0 : iDst = nxGlobal + 1 - i
4827 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4828 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4829 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
4830 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4831 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4832 : end do
4833 : end do
4834 : end do
4835 :
4836 : case (field_loc_Nface) ! cell corner (velocity) location
4837 :
4838 0 : ioffset = -1
4839 0 : joffset = 1
4840 :
4841 : case default
4842 0 : call abort_ice(subname//'ERROR: Unknown field location')
4843 : end select
4844 :
4845 : else ! tripole u-fold
4846 :
4847 0 : select case (fieldLoc)
4848 : case (field_loc_center) ! cell center location
4849 :
4850 0 : ioffset = 0
4851 0 : joffset = 0
4852 :
4853 : case (field_loc_NEcorner) ! cell corner location
4854 :
4855 0 : ioffset = 1
4856 0 : joffset = 1
4857 :
4858 : !*** top row is degenerate, so must enforce symmetry
4859 : !*** use average of two degenerate points for value
4860 :
4861 0 : do l=1,nt
4862 0 : do k=1,nz
4863 0 : do i = 1,nxGlobal/2 - 1
4864 0 : iDst = nxGlobal - i
4865 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4866 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4867 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
4868 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4869 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4870 : end do
4871 : end do
4872 : end do
4873 :
4874 : case (field_loc_Eface) ! cell center location
4875 :
4876 0 : ioffset = 1
4877 0 : joffset = 0
4878 :
4879 : case (field_loc_Nface) ! cell corner (velocity) location
4880 :
4881 0 : ioffset = 0
4882 0 : joffset = 1
4883 :
4884 : !*** top row is degenerate, so must enforce symmetry
4885 : !*** use average of two degenerate points for value
4886 :
4887 0 : do l=1,nt
4888 0 : do k=1,nz
4889 0 : do i = 1,nxGlobal/2
4890 0 : iDst = nxGlobal + 1 - i
4891 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
4892 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
4893 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
4894 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
4895 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
4896 : end do
4897 : end do
4898 : end do
4899 :
4900 : case default
4901 0 : call abort_ice(subname//'ERROR: Unknown field location')
4902 : end select
4903 :
4904 : endif
4905 :
4906 : !*** copy out of global tripole buffer into local
4907 : !*** ghost cells
4908 :
4909 : !*** look through local copies to find the copy out
4910 : !*** messages (srcBlock < 0)
4911 :
4912 0 : do nmsg=1,halo%numLocalCopies
4913 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
4914 :
4915 0 : if (srcBlock < 0) then
4916 :
4917 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
4918 0 : jSrc = halo%srcLocalAddr(2,nmsg)
4919 :
4920 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
4921 0 : jDst = halo%dstLocalAddr(2,nmsg)
4922 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
4923 :
4924 : !*** correct for offsets
4925 0 : iSrc = iSrc - ioffset
4926 0 : jSrc = jSrc - joffset
4927 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
4928 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
4929 :
4930 : !*** for center and Eface on u-fold, and NE corner and Nface
4931 : !*** on T-fold, do not need to replace
4932 : !*** top row of physical domain, so jSrc should be
4933 : !*** out of range and skipped
4934 : !*** otherwise do the copy
4935 :
4936 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
4937 0 : do l=1,nt
4938 0 : do k=1,nz
4939 0 : array(iDst,jDst,k,l,dstBlock) = isign* &
4940 0 : bufTripole(iSrc,jSrc,k,l)
4941 : end do
4942 : end do
4943 : endif
4944 :
4945 : endif
4946 : end do
4947 :
4948 : endif
4949 :
4950 : !-----------------------------------------------------------------------
4951 : !
4952 : ! wait for sends to complete and deallocate arrays
4953 : !
4954 : !-----------------------------------------------------------------------
4955 :
4956 0 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
4957 :
4958 0 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
4959 :
4960 0 : if (ierr > 0) then
4961 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
4962 0 : return
4963 : endif
4964 :
4965 0 : deallocate(bufSend, bufRecv, bufTripole, stat=ierr)
4966 :
4967 0 : if (ierr > 0) then
4968 0 : call abort_ice(subname//'ERROR: deallocating 4d buffers')
4969 0 : return
4970 : endif
4971 :
4972 : !-----------------------------------------------------------------------
4973 :
4974 0 : end subroutine ice_HaloUpdate4DR4
4975 :
4976 : !***********************************************************************
4977 :
4978 0 : subroutine ice_HaloUpdate4DI4(array, halo, &
4979 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
4980 : fillValue)
4981 :
4982 : ! This routine updates ghost cells for an input array and is a
4983 : ! member of a group of routines under the generic interface
4984 : ! ice\_HaloUpdate. This routine is the specific interface
4985 : ! for 4d horizontal integer arrays.
4986 :
4987 : type (ice_halo), intent(in) :: &
4988 : halo ! precomputed halo structure containing all
4989 : ! information needed for halo update
4990 :
4991 : integer (int_kind), intent(in) :: &
4992 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
4993 : fieldLoc ! id for location on horizontal grid
4994 : ! (center, NEcorner, Nface, Eface)
4995 :
4996 : integer (int_kind), intent(in), optional :: &
4997 : fillValue ! optional value to put in ghost cells
4998 : ! where neighbor points are unknown
4999 : ! (e.g. eliminated land blocks or
5000 : ! closed boundaries)
5001 :
5002 : integer (int_kind), dimension(:,:,:,:,:), intent(inout) :: &
5003 : array ! array containing field for which halo
5004 : ! needs to be updated
5005 :
5006 : !-----------------------------------------------------------------------
5007 : !
5008 : ! local variables
5009 : !
5010 : !-----------------------------------------------------------------------
5011 :
5012 : integer (int_kind) :: &
5013 : i,j,k,l,n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
5014 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
5015 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
5016 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
5017 : nz, nt, &! size of array in 3rd,4th dimensions ! LCOV_EXCL_LINE
5018 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
5019 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
5020 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
5021 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
5022 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
5023 : isign ! sign factor for tripole grids
5024 :
5025 : integer (int_kind), dimension(:), allocatable :: &
5026 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
5027 0 : rcvRequest ! MPI request ids
5028 :
5029 : integer (int_kind), dimension(:,:), allocatable :: &
5030 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
5031 0 : rcvStatus ! MPI status flags
5032 :
5033 : integer (int_kind) :: &
5034 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
5035 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
5036 :
5037 : integer (int_kind), dimension(:,:), allocatable :: &
5038 0 : bufSend, bufRecv ! 4d send,recv buffers
5039 :
5040 : integer (int_kind), dimension(:,:,:,:), allocatable :: &
5041 0 : bufTripole ! 4d tripole buffer
5042 :
5043 : integer (int_kind) :: len ! length of messages
5044 :
5045 : character(len=*), parameter :: subname = '(ice_HaloUpdate4DI4)'
5046 :
5047 : !-----------------------------------------------------------------------
5048 : !
5049 : ! abort or return on unknown or noupdate field_loc or field_type
5050 : !
5051 : !-----------------------------------------------------------------------
5052 :
5053 0 : if (fieldLoc == field_loc_unknown .or. &
5054 : fieldKind == field_type_unknown) then
5055 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
5056 0 : return
5057 : endif
5058 :
5059 0 : if (fieldLoc == field_loc_noupdate .or. &
5060 : fieldKind == field_type_noupdate) then
5061 0 : return
5062 : endif
5063 :
5064 : !-----------------------------------------------------------------------
5065 : !
5066 : ! initialize error code and fill value
5067 : !
5068 : !-----------------------------------------------------------------------
5069 :
5070 0 : if (present(fillValue)) then
5071 0 : fill = fillValue
5072 : else
5073 0 : fill = 0_int_kind
5074 : endif
5075 :
5076 0 : nxGlobal = 0
5077 0 : if (allocated(bufTripoleI4)) nxGlobal = size(bufTripoleI4,dim=1)
5078 :
5079 : !-----------------------------------------------------------------------
5080 : !
5081 : ! allocate request and status arrays for messages
5082 : !
5083 : !-----------------------------------------------------------------------
5084 :
5085 : allocate(sndRequest(halo%numMsgSend), &
5086 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
5087 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
5088 0 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
5089 :
5090 0 : if (ierr > 0) then
5091 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
5092 0 : return
5093 : endif
5094 :
5095 : !-----------------------------------------------------------------------
5096 : !
5097 : ! allocate 4D buffers
5098 : !
5099 : !-----------------------------------------------------------------------
5100 :
5101 0 : nz = size(array, dim=3)
5102 0 : nt = size(array, dim=4)
5103 :
5104 : allocate(bufSend(bufSizeSend*nz*nt, halo%numMsgSend), &
5105 : bufRecv(bufSizeRecv*nz*nt, halo%numMsgRecv), & ! LCOV_EXCL_LINE
5106 : bufTripole(nxGlobal, halo%tripoleRows, nz, nt), & ! LCOV_EXCL_LINE
5107 0 : stat=ierr)
5108 :
5109 0 : if (ierr > 0) then
5110 0 : call abort_ice(subname//'ERROR: allocating buffers')
5111 0 : return
5112 : endif
5113 :
5114 0 : bufTripole = fill
5115 :
5116 : !-----------------------------------------------------------------------
5117 : !
5118 : ! post receives
5119 : !
5120 : !-----------------------------------------------------------------------
5121 :
5122 0 : do nmsg=1,halo%numMsgRecv
5123 :
5124 0 : len = halo%SizeRecv(nmsg)*nz*nt
5125 0 : call MPI_IRECV(bufRecv(1:len,nmsg), len, MPI_INTEGER, &
5126 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
5127 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
5128 0 : halo%communicator, rcvRequest(nmsg), ierr)
5129 : end do
5130 :
5131 : !-----------------------------------------------------------------------
5132 : !
5133 : ! fill send buffer and post sends
5134 : !
5135 : !-----------------------------------------------------------------------
5136 :
5137 0 : do nmsg=1,halo%numMsgSend
5138 :
5139 0 : i=0
5140 0 : do n=1,halo%sizeSend(nmsg)
5141 0 : iSrc = halo%sendAddr(1,n,nmsg)
5142 0 : jSrc = halo%sendAddr(2,n,nmsg)
5143 0 : srcBlock = halo%sendAddr(3,n,nmsg)
5144 :
5145 0 : do l=1,nt
5146 0 : do k=1,nz
5147 0 : i = i + 1
5148 0 : bufSend(i,nmsg) = array(iSrc,jSrc,k,l,srcBlock)
5149 : end do
5150 : end do
5151 : end do
5152 :
5153 0 : do n=i+1,bufSizeSend*nz*nt
5154 0 : bufSend(n,nmsg) = fill ! fill remainder of buffer
5155 : end do
5156 :
5157 0 : len = halo%SizeSend(nmsg)*nz*nt
5158 0 : call MPI_ISEND(bufSend(1:len,nmsg), len, MPI_INTEGER, &
5159 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
5160 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
5161 0 : halo%communicator, sndRequest(nmsg), ierr)
5162 : end do
5163 :
5164 : !-----------------------------------------------------------------------
5165 : !
5166 : ! while messages are being communicated, fill out halo region
5167 : ! needed for masked halos to ensure halo values are filled for
5168 : ! halo grid cells that are not updated
5169 : !
5170 : !-----------------------------------------------------------------------
5171 :
5172 0 : do iblk = 1, halo%numLocalBlocks
5173 0 : call get_block_parameter(halo%blockGlobalID(iblk), &
5174 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
5175 0 : jlo=jlo, jhi=jhi)
5176 0 : do j = 1,nghost
5177 0 : array(1:nx_block, jlo-j,:,:,iblk) = fill
5178 0 : array(1:nx_block, jhi+j,:,:,iblk) = fill
5179 : enddo
5180 0 : do i = 1,nghost
5181 0 : array(ilo-i, 1:ny_block,:,:,iblk) = fill
5182 0 : array(ihi+i, 1:ny_block,:,:,iblk) = fill
5183 : enddo
5184 : enddo
5185 :
5186 : !-----------------------------------------------------------------------
5187 : !
5188 : ! do local copies while waiting for messages to complete
5189 : ! if srcBlock is zero, that denotes an eliminated land block or a
5190 : ! closed boundary where ghost cell values are undefined
5191 : ! if srcBlock is less than zero, the message is a copy out of the
5192 : ! tripole buffer and will be treated later
5193 : !
5194 : !-----------------------------------------------------------------------
5195 :
5196 0 : do nmsg=1,halo%numLocalCopies
5197 0 : iSrc = halo%srcLocalAddr(1,nmsg)
5198 0 : jSrc = halo%srcLocalAddr(2,nmsg)
5199 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
5200 0 : iDst = halo%dstLocalAddr(1,nmsg)
5201 0 : jDst = halo%dstLocalAddr(2,nmsg)
5202 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
5203 :
5204 0 : if (srcBlock > 0) then
5205 0 : if (dstBlock > 0) then
5206 0 : do l=1,nt
5207 0 : do k=1,nz
5208 0 : array(iDst,jDst,k,l,dstBlock) = &
5209 0 : array(iSrc,jSrc,k,l,srcBlock)
5210 : end do
5211 : end do
5212 0 : else if (dstBlock < 0) then ! tripole copy into buffer
5213 0 : do l=1,nt
5214 0 : do k=1,nz
5215 0 : bufTripole(iDst,jDst,k,l) = &
5216 0 : array(iSrc,jSrc,k,l,srcBlock)
5217 : end do
5218 : end do
5219 : endif
5220 0 : else if (srcBlock == 0) then
5221 0 : do l=1,nt
5222 0 : do k=1,nz
5223 0 : array(iDst,jDst,k,l,dstBlock) = fill
5224 : end do
5225 : end do
5226 : endif
5227 : end do
5228 :
5229 : !-----------------------------------------------------------------------
5230 : !
5231 : ! wait for receives to finish and then unpack the recv buffer into
5232 : ! ghost cells
5233 : !
5234 : !-----------------------------------------------------------------------
5235 :
5236 0 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
5237 :
5238 0 : do nmsg=1,halo%numMsgRecv
5239 0 : i = 0
5240 0 : do n=1,halo%sizeRecv(nmsg)
5241 0 : iDst = halo%recvAddr(1,n,nmsg)
5242 0 : jDst = halo%recvAddr(2,n,nmsg)
5243 0 : dstBlock = halo%recvAddr(3,n,nmsg)
5244 :
5245 0 : if (dstBlock > 0) then
5246 0 : do l=1,nt
5247 0 : do k=1,nz
5248 0 : i = i + 1
5249 0 : array(iDst,jDst,k,l,dstBlock) = bufRecv(i,nmsg)
5250 : end do
5251 : end do
5252 0 : else if (dstBlock < 0) then !tripole
5253 0 : do l=1,nt
5254 0 : do k=1,nz
5255 0 : i = i + 1
5256 0 : bufTripole(iDst,jDst,k,l) = bufRecv(i,nmsg)
5257 : end do
5258 : end do
5259 : endif
5260 : end do
5261 : end do
5262 :
5263 : !-----------------------------------------------------------------------
5264 : !
5265 : ! take care of northern boundary in tripole case
5266 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
5267 : ! (T-fold) of physical domain for entire (global) top row
5268 : !
5269 : !-----------------------------------------------------------------------
5270 :
5271 0 : if (nxGlobal > 0) then
5272 :
5273 0 : select case (fieldKind)
5274 : case (field_type_scalar)
5275 0 : isign = 1
5276 : case (field_type_vector)
5277 0 : isign = -1
5278 : case (field_type_angle)
5279 0 : isign = -1
5280 : case default
5281 0 : call abort_ice(subname//'ERROR: Unknown field kind')
5282 : end select
5283 :
5284 0 : if (halo%tripoleTFlag) then
5285 :
5286 0 : select case (fieldLoc)
5287 : case (field_loc_center) ! cell center location
5288 :
5289 0 : ioffset = -1
5290 0 : joffset = 0
5291 :
5292 : !*** top row is degenerate, so must enforce symmetry
5293 : !*** use average of two degenerate points for value
5294 :
5295 0 : do l=1,nt
5296 0 : do k=1,nz
5297 0 : do i = 2,nxGlobal/2
5298 0 : iDst = nxGlobal - i + 2
5299 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
5300 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
5301 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
5302 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
5303 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
5304 : end do
5305 : end do
5306 : end do
5307 :
5308 : case (field_loc_NEcorner) ! cell corner location
5309 :
5310 0 : ioffset = 0
5311 0 : joffset = 1
5312 :
5313 : case (field_loc_Eface) ! cell center location
5314 :
5315 0 : ioffset = 0
5316 0 : joffset = 0
5317 :
5318 : !*** top row is degenerate, so must enforce symmetry
5319 : !*** use average of two degenerate points for value
5320 :
5321 0 : do l=1,nt
5322 0 : do k=1,nz
5323 0 : do i = 1,nxGlobal/2
5324 0 : iDst = nxGlobal + 1 - i
5325 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
5326 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
5327 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
5328 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
5329 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
5330 : end do
5331 : end do
5332 : end do
5333 :
5334 : case (field_loc_Nface) ! cell corner (velocity) location
5335 :
5336 0 : ioffset = -1
5337 0 : joffset = 1
5338 :
5339 : case default
5340 0 : call abort_ice(subname//'ERROR: Unknown field location')
5341 : end select
5342 :
5343 : else ! tripole u-fold
5344 :
5345 0 : select case (fieldLoc)
5346 : case (field_loc_center) ! cell center location
5347 :
5348 0 : ioffset = 0
5349 0 : joffset = 0
5350 :
5351 : case (field_loc_NEcorner) ! cell corner location
5352 :
5353 0 : ioffset = 1
5354 0 : joffset = 1
5355 :
5356 : !*** top row is degenerate, so must enforce symmetry
5357 : !*** use average of two degenerate points for value
5358 :
5359 0 : do l=1,nt
5360 0 : do k=1,nz
5361 0 : do i = 1,nxGlobal/2 - 1
5362 0 : iDst = nxGlobal - i
5363 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
5364 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
5365 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
5366 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
5367 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
5368 : end do
5369 : end do
5370 : end do
5371 :
5372 : case (field_loc_Eface) ! cell center location
5373 :
5374 0 : ioffset = 1
5375 0 : joffset = 0
5376 :
5377 : case (field_loc_Nface) ! cell corner (velocity) location
5378 :
5379 0 : ioffset = 0
5380 0 : joffset = 1
5381 :
5382 : !*** top row is degenerate, so must enforce symmetry
5383 : !*** use average of two degenerate points for value
5384 :
5385 0 : do l=1,nt
5386 0 : do k=1,nz
5387 0 : do i = 1,nxGlobal/2
5388 0 : iDst = nxGlobal + 1 - i
5389 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
5390 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
5391 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
5392 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
5393 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
5394 : end do
5395 : end do
5396 : end do
5397 :
5398 : case default
5399 0 : call abort_ice(subname//'ERROR: Unknown field location')
5400 : end select
5401 :
5402 : endif
5403 :
5404 : !*** copy out of global tripole buffer into local
5405 : !*** ghost cells
5406 :
5407 : !*** look through local copies to find the copy out
5408 : !*** messages (srcBlock < 0)
5409 :
5410 0 : do nmsg=1,halo%numLocalCopies
5411 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
5412 :
5413 0 : if (srcBlock < 0) then
5414 :
5415 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
5416 0 : jSrc = halo%srcLocalAddr(2,nmsg)
5417 :
5418 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
5419 0 : jDst = halo%dstLocalAddr(2,nmsg)
5420 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
5421 :
5422 : !*** correct for offsets
5423 0 : iSrc = iSrc - ioffset
5424 0 : jSrc = jSrc - joffset
5425 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
5426 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
5427 :
5428 : !*** for center and Eface on u-fold, and NE corner and Nface
5429 : !*** on T-fold, do not need to replace
5430 : !*** top row of physical domain, so jSrc should be
5431 : !*** out of range and skipped
5432 : !*** otherwise do the copy
5433 :
5434 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
5435 0 : do l=1,nt
5436 0 : do k=1,nz
5437 0 : array(iDst,jDst,k,l,dstBlock) = isign* &
5438 0 : bufTripole(iSrc,jSrc,k,l)
5439 : end do
5440 : end do
5441 : endif
5442 :
5443 : endif
5444 : end do
5445 :
5446 : endif
5447 :
5448 : !-----------------------------------------------------------------------
5449 : !
5450 : ! wait for sends to complete and deallocate arrays
5451 : !
5452 : !-----------------------------------------------------------------------
5453 :
5454 0 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
5455 :
5456 0 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
5457 :
5458 0 : if (ierr > 0) then
5459 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
5460 0 : return
5461 : endif
5462 :
5463 0 : deallocate(bufSend, bufRecv, bufTripole, stat=ierr)
5464 :
5465 0 : if (ierr > 0) then
5466 0 : call abort_ice(subname//'ERROR: deallocating 4d buffers')
5467 0 : return
5468 : endif
5469 :
5470 : !-----------------------------------------------------------------------
5471 :
5472 0 : end subroutine ice_HaloUpdate4DI4
5473 :
5474 : !***********************************************************************
5475 : ! This routine updates ghost cells for an input array using
5476 : ! a second array as needed by the stress fields.
5477 : ! This is just like 2DR8 except no averaging and only on tripole
5478 :
5479 0 : subroutine ice_HaloUpdate_stress(array1, array2, halo, &
5480 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
5481 : fillValue)
5482 :
5483 : type (ice_halo), intent(in) :: &
5484 : halo ! precomputed halo structure containing all
5485 : ! information needed for halo update
5486 :
5487 : integer (int_kind), intent(in) :: &
5488 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
5489 : fieldLoc ! id for location on horizontal grid
5490 : ! (center, NEcorner, Nface, Eface)
5491 :
5492 : real (dbl_kind), intent(in), optional :: &
5493 : fillValue ! optional value to put in ghost cells
5494 : ! where neighbor points are unknown
5495 : ! (e.g. eliminated land blocks or
5496 : ! closed boundaries)
5497 :
5498 : real (dbl_kind), dimension(:,:,:), intent(inout) :: &
5499 : array1 ,& ! array containing field for which halo ! LCOV_EXCL_LINE
5500 : ! needs to be updated
5501 : array2 ! array containing field for which halo
5502 : ! in array1 needs to be updated
5503 :
5504 : ! local variables
5505 :
5506 : integer (int_kind) :: &
5507 : n,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
5508 : ierr, &! error or status flag for MPI,alloc ! LCOV_EXCL_LINE
5509 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
5510 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
5511 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
5512 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
5513 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
5514 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
5515 : isign ! sign factor for tripole grids
5516 :
5517 : integer (int_kind), dimension(:), allocatable :: &
5518 : sndRequest, &! MPI request ids ! LCOV_EXCL_LINE
5519 0 : rcvRequest ! MPI request ids
5520 :
5521 : integer (int_kind), dimension(:,:), allocatable :: &
5522 : sndStatus, &! MPI status flags ! LCOV_EXCL_LINE
5523 0 : rcvStatus ! MPI status flags
5524 :
5525 : real (dbl_kind) :: &
5526 0 : fill ! value to use for unknown points
5527 :
5528 : integer (int_kind) :: len ! length of messages
5529 :
5530 : character(len=*), parameter :: subname = '(ice_HaloUpdate_stress)'
5531 :
5532 : !-----------------------------------------------------------------------
5533 : !
5534 : ! abort or return on unknown or noupdate field_loc or field_type
5535 : !
5536 : !-----------------------------------------------------------------------
5537 :
5538 0 : if (fieldLoc == field_loc_unknown .or. &
5539 : fieldKind == field_type_unknown) then
5540 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
5541 0 : return
5542 : endif
5543 :
5544 0 : if (fieldLoc == field_loc_noupdate .or. &
5545 : fieldKind == field_type_noupdate) then
5546 0 : return
5547 : endif
5548 :
5549 : !-----------------------------------------------------------------------
5550 : !
5551 : ! initialize error code and fill value
5552 : !
5553 : !-----------------------------------------------------------------------
5554 :
5555 0 : if (present(fillValue)) then
5556 0 : fill = fillValue
5557 : else
5558 0 : fill = 0.0_dbl_kind
5559 : endif
5560 :
5561 0 : nxGlobal = 0
5562 0 : if (allocated(bufTripoleR8)) then
5563 0 : nxGlobal = size(bufTripoleR8,dim=1)
5564 0 : bufTripoleR8 = fill
5565 : endif
5566 :
5567 : !-----------------------------------------------------------------------
5568 : !
5569 : ! allocate request and status arrays for messages
5570 : !
5571 : !-----------------------------------------------------------------------
5572 :
5573 : allocate(sndRequest(halo%numMsgSend), &
5574 : rcvRequest(halo%numMsgRecv), & ! LCOV_EXCL_LINE
5575 : sndStatus(MPI_STATUS_SIZE,halo%numMsgSend), & ! LCOV_EXCL_LINE
5576 0 : rcvStatus(MPI_STATUS_SIZE,halo%numMsgRecv), stat=ierr)
5577 :
5578 0 : if (ierr > 0) then
5579 0 : call abort_ice(subname//'ERROR: allocating req,status arrays')
5580 0 : return
5581 : endif
5582 :
5583 : !-----------------------------------------------------------------------
5584 : !
5585 : ! post receives
5586 : !
5587 : !-----------------------------------------------------------------------
5588 :
5589 0 : do nmsg=1,halo%numMsgRecv
5590 :
5591 0 : len = halo%SizeRecv(nmsg)
5592 0 : call MPI_IRECV(bufRecvR8(1:len,nmsg), len, mpiR8, &
5593 : halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
5594 : mpitagHalo + halo%recvTask(nmsg), & ! LCOV_EXCL_LINE
5595 0 : halo%communicator, rcvRequest(nmsg), ierr)
5596 : end do
5597 :
5598 : !-----------------------------------------------------------------------
5599 : !
5600 : ! fill send buffer and post sends
5601 : !
5602 : !-----------------------------------------------------------------------
5603 :
5604 0 : do nmsg=1,halo%numMsgSend
5605 :
5606 0 : do n=1,halo%sizeSend(nmsg)
5607 0 : iSrc = halo%sendAddr(1,n,nmsg)
5608 0 : jSrc = halo%sendAddr(2,n,nmsg)
5609 0 : srcBlock = halo%sendAddr(3,n,nmsg)
5610 :
5611 0 : bufSendR8(n,nmsg) = array2(iSrc,jSrc,srcBlock)
5612 : end do
5613 0 : do n=halo%sizeSend(nmsg)+1,bufSizeSend
5614 0 : bufSendR8(n,nmsg) = fill ! fill remainder of buffer
5615 : end do
5616 :
5617 0 : len = halo%SizeSend(nmsg)
5618 0 : call MPI_ISEND(bufSendR8(1:len,nmsg), len, mpiR8, &
5619 : halo%sendTask(nmsg), & ! LCOV_EXCL_LINE
5620 : mpitagHalo + my_task, & ! LCOV_EXCL_LINE
5621 0 : halo%communicator, sndRequest(nmsg), ierr)
5622 : end do
5623 :
5624 : !-----------------------------------------------------------------------
5625 : !
5626 : ! while messages are being communicated,
5627 : ! do NOT zero the halo out, this halo update just updates
5628 : ! the tripole zipper as needed for stresses. if you zero
5629 : ! it out, all halo values will be wiped out.
5630 : !-----------------------------------------------------------------------
5631 : ! do iblk = 1, halo%numLocalBlocks
5632 : ! call get_block_parameter(halo%blockGlobalID(iblk), &
5633 : ! ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
5634 : ! jlo=jlo, jhi=jhi)
5635 : ! do j = 1,nghost
5636 : ! array(1:nx_block, jlo-j,iblk) = fill
5637 : ! array(1:nx_block, jhi+j,iblk) = fill
5638 : ! enddo
5639 : ! do i = 1,nghost
5640 : ! array(ilo-i, 1:ny_block,iblk) = fill
5641 : ! array(ihi+i, 1:ny_block,iblk) = fill
5642 : ! enddo
5643 : ! enddo
5644 :
5645 : !-----------------------------------------------------------------------
5646 : !
5647 : ! do local copies while waiting for messages to complete
5648 : ! if srcBlock is zero, that denotes an eliminated land block or a
5649 : ! closed boundary where ghost cell values are undefined
5650 : ! if srcBlock is less than zero, the message is a copy out of the
5651 : ! tripole buffer and will be treated later
5652 : !
5653 : !-----------------------------------------------------------------------
5654 :
5655 0 : do nmsg=1,halo%numLocalCopies
5656 0 : iSrc = halo%srcLocalAddr(1,nmsg)
5657 0 : jSrc = halo%srcLocalAddr(2,nmsg)
5658 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
5659 0 : iDst = halo%dstLocalAddr(1,nmsg)
5660 0 : jDst = halo%dstLocalAddr(2,nmsg)
5661 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
5662 :
5663 0 : if (srcBlock > 0) then
5664 0 : if (dstBlock < 0) then ! tripole copy into buffer
5665 0 : bufTripoleR8(iDst,jDst) = &
5666 0 : array2(iSrc,jSrc,srcBlock)
5667 : endif
5668 0 : else if (srcBlock == 0) then
5669 0 : array1(iDst,jDst,dstBlock) = fill
5670 : endif
5671 : end do
5672 :
5673 : !-----------------------------------------------------------------------
5674 : !
5675 : ! wait for receives to finish and then unpack the recv buffer into
5676 : ! ghost cells
5677 : !
5678 : !-----------------------------------------------------------------------
5679 :
5680 0 : call MPI_WAITALL(halo%numMsgRecv, rcvRequest, rcvStatus, ierr)
5681 :
5682 0 : do nmsg=1,halo%numMsgRecv
5683 0 : do n=1,halo%sizeRecv(nmsg)
5684 0 : iDst = halo%recvAddr(1,n,nmsg)
5685 0 : jDst = halo%recvAddr(2,n,nmsg)
5686 0 : dstBlock = halo%recvAddr(3,n,nmsg)
5687 :
5688 0 : if (dstBlock < 0) then !tripole
5689 0 : bufTripoleR8(iDst,jDst) = bufRecvR8(n,nmsg)
5690 : endif
5691 : end do
5692 : end do
5693 :
5694 : !-----------------------------------------------------------------------
5695 : !
5696 : ! take care of northern boundary in tripole case
5697 : ! bufTripole array contains the top haloWidth+1 rows of physical
5698 : ! domain for entire (global) top row
5699 : !
5700 : !-----------------------------------------------------------------------
5701 :
5702 0 : if (nxGlobal > 0) then
5703 :
5704 0 : select case (fieldKind)
5705 : case (field_type_scalar)
5706 0 : isign = 1
5707 : case (field_type_vector)
5708 0 : isign = -1
5709 : case (field_type_angle)
5710 0 : isign = -1
5711 : case default
5712 0 : call abort_ice(subname//'ERROR: Unknown field kind')
5713 : end select
5714 :
5715 0 : if (halo%tripoleTFlag) then
5716 :
5717 0 : select case (fieldLoc)
5718 : case (field_loc_center) ! cell center location
5719 :
5720 0 : ioffset = -1
5721 0 : joffset = 0
5722 :
5723 : case (field_loc_NEcorner) ! cell corner location
5724 :
5725 0 : ioffset = 0
5726 0 : joffset = 1
5727 :
5728 : case (field_loc_Eface) ! cell center location
5729 :
5730 0 : ioffset = 0
5731 0 : joffset = 0
5732 :
5733 : case (field_loc_Nface) ! cell corner (velocity) location
5734 :
5735 0 : ioffset = -1
5736 0 : joffset = 1
5737 :
5738 : case default
5739 0 : call abort_ice(subname//'ERROR: Unknown field location')
5740 : end select
5741 :
5742 : else ! tripole u-fold
5743 :
5744 0 : select case (fieldLoc)
5745 : case (field_loc_center) ! cell center location
5746 :
5747 0 : ioffset = 0
5748 0 : joffset = 0
5749 :
5750 : case (field_loc_NEcorner) ! cell corner location
5751 :
5752 0 : ioffset = 1
5753 0 : joffset = 1
5754 :
5755 : case (field_loc_Eface)
5756 :
5757 0 : ioffset = 1
5758 0 : joffset = 0
5759 :
5760 : case (field_loc_Nface)
5761 :
5762 0 : ioffset = 0
5763 0 : joffset = 1
5764 :
5765 : case default
5766 0 : call abort_ice(subname//'ERROR: Unknown field location')
5767 : end select
5768 :
5769 : endif
5770 :
5771 : !*** copy out of global tripole buffer into local
5772 : !*** ghost cells
5773 :
5774 : !*** look through local copies to find the copy out
5775 : !*** messages (srcBlock < 0)
5776 :
5777 0 : do nmsg=1,halo%numLocalCopies
5778 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
5779 :
5780 0 : if (srcBlock < 0) then
5781 :
5782 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
5783 0 : jSrc = halo%srcLocalAddr(2,nmsg)
5784 :
5785 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
5786 0 : jDst = halo%dstLocalAddr(2,nmsg)
5787 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
5788 :
5789 : !*** correct for offsets
5790 0 : iSrc = iSrc - ioffset
5791 0 : jSrc = jSrc - joffset
5792 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
5793 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
5794 :
5795 : !*** for center and Eface, do not need to replace
5796 : !*** top row of physical domain, so jSrc should be
5797 : !*** out of range and skipped
5798 : !*** otherwise do the copy
5799 :
5800 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
5801 0 : array1(iDst,jDst,dstBlock) = isign*bufTripoleR8(iSrc,jSrc)
5802 : endif
5803 :
5804 : endif
5805 : end do
5806 :
5807 : endif
5808 :
5809 : !-----------------------------------------------------------------------
5810 : !
5811 : ! wait for sends to complete and deallocate arrays
5812 : !
5813 : !-----------------------------------------------------------------------
5814 :
5815 0 : call MPI_WAITALL(halo%numMsgSend, sndRequest, sndStatus, ierr)
5816 :
5817 0 : deallocate(sndRequest, rcvRequest, sndStatus, rcvStatus, stat=ierr)
5818 :
5819 0 : if (ierr > 0) then
5820 0 : call abort_ice(subname//'ERROR: deallocating req,status arrays')
5821 0 : return
5822 : endif
5823 :
5824 : !-----------------------------------------------------------------------
5825 :
5826 0 : end subroutine ice_HaloUpdate_stress
5827 :
5828 : !***********************************************************************
5829 :
5830 8704 : subroutine ice_HaloIncrementMsgCount(sndCounter, rcvCounter, &
5831 : srcProc, dstProc, msgSize)
5832 :
5833 : ! This is a utility routine to increment the arrays for counting
5834 : ! whether messages are required. It checks the source and destination
5835 : ! task to see whether the current task needs to send, receive or
5836 : ! copy messages to fill halo regions (ghost cells).
5837 :
5838 : integer (int_kind), intent(in) :: &
5839 : srcProc, &! source processor for communication ! LCOV_EXCL_LINE
5840 : dstProc, &! destination processor for communication ! LCOV_EXCL_LINE
5841 : msgSize ! number of words for this message
5842 :
5843 : integer (int_kind), dimension(:), intent(inout) :: &
5844 : sndCounter, &! array for counting messages to be sent ! LCOV_EXCL_LINE
5845 : rcvCounter ! array for counting messages to be received
5846 :
5847 : character(len=*), parameter :: subname = '(ice_HaloIncrementMsgCount)'
5848 : !-----------------------------------------------------------------------
5849 : !
5850 : ! error check
5851 : !
5852 : !-----------------------------------------------------------------------
5853 :
5854 : if (srcProc < 0 .or. dstProc < 0 .or. &
5855 : srcProc > size(sndCounter) .or. & ! LCOV_EXCL_LINE
5856 1024 : dstProc > size(rcvCounter)) then
5857 0 : call abort_ice(subname//'ERROR: invalid processor number')
5858 0 : return
5859 : endif
5860 :
5861 : !-----------------------------------------------------------------------
5862 : !
5863 : ! if destination all land or outside closed boundary (dstProc = 0),
5864 : ! then no send is necessary, so do the rest only for dstProc /= 0
5865 : !
5866 : !-----------------------------------------------------------------------
5867 :
5868 8704 : if (dstProc == 0) return
5869 :
5870 : !-----------------------------------------------------------------------
5871 : !
5872 : ! if the current processor is the source, must send data
5873 : ! local copy if dstProc = srcProc
5874 : !
5875 : !-----------------------------------------------------------------------
5876 :
5877 7216 : if (srcProc == my_task + 1) sndCounter(dstProc) = &
5878 1232 : sndCounter(dstProc) + msgSize
5879 :
5880 : !-----------------------------------------------------------------------
5881 : !
5882 : ! if the current processor is the destination, must receive data
5883 : ! local copy if dstProc = srcProc
5884 : !
5885 : !-----------------------------------------------------------------------
5886 :
5887 7008 : if (dstProc == my_task + 1) then
5888 :
5889 1032 : if (srcProc > 0) then
5890 : !*** the source block has ocean points
5891 : !*** count as a receive from srcProc
5892 :
5893 1024 : rcvCounter(srcProc) = rcvCounter(srcProc) + msgSize
5894 :
5895 : else
5896 : !*** if the source block has been dropped, create
5897 : !*** a local copy to fill halo with a fill value
5898 :
5899 8 : rcvCounter(dstProc) = rcvCounter(dstProc) + msgSize
5900 :
5901 : endif
5902 : endif
5903 : !-----------------------------------------------------------------------
5904 :
5905 : end subroutine ice_HaloIncrementMsgCount
5906 :
5907 : !***********************************************************************
5908 :
5909 8704 : subroutine ice_HaloMsgCreate(halo, srcBlock, srcProc, srcLocalID, &
5910 : dstBlock, dstProc, dstLocalID, & ! LCOV_EXCL_LINE
5911 : direction)
5912 :
5913 : ! This is a utility routine to determine the required address and
5914 : ! message information for a particular pair of blocks.
5915 :
5916 : integer (int_kind), intent(in) :: &
5917 : srcBlock, dstBlock, & ! source,destination block id ! LCOV_EXCL_LINE
5918 : srcProc, dstProc, & ! source,destination processor location ! LCOV_EXCL_LINE
5919 : srcLocalID, dstLocalID ! source,destination local index
5920 :
5921 : character (*), intent(in) :: &
5922 : direction ! direction of neighbor block
5923 : ! (north,south,east,west,
5924 : ! and NE, NW, SE, SW)
5925 :
5926 : type (ice_halo), intent(inout) :: &
5927 : halo ! data structure containing halo info
5928 :
5929 : !-----------------------------------------------------------------------
5930 : !
5931 : ! local variables
5932 : !
5933 : !-----------------------------------------------------------------------
5934 :
5935 : integer (int_kind) :: &
5936 : msgIndx, &! message counter and index into msg array ! LCOV_EXCL_LINE
5937 : bufSize, &! size of message buffer ! LCOV_EXCL_LINE
5938 : ibSrc, ieSrc, jbSrc, jeSrc, &! phys domain info for source block ! LCOV_EXCL_LINE
5939 : ibDst, ieDst, jbDst, jeDst, &! phys domain info for dest block ! LCOV_EXCL_LINE
5940 : nxGlobal, &! size of global domain in e-w direction ! LCOV_EXCL_LINE
5941 : i,j,n ! dummy loop index
5942 :
5943 : integer (int_kind), dimension(:), pointer :: &
5944 : iGlobal ! global i index for location in tripole
5945 :
5946 : character(len=*), parameter :: subname = '(ice_HaloMsgCreate)'
5947 : !-----------------------------------------------------------------------
5948 : !
5949 : ! initialize
5950 : !
5951 : !-----------------------------------------------------------------------
5952 :
5953 0 : if (allocated(bufTripoleR8)) nxGlobal = size(bufTripoleR8,dim=1)
5954 :
5955 : !-----------------------------------------------------------------------
5956 : !
5957 : ! if destination all land or outside closed boundary (dstProc = 0),
5958 : ! then no send is necessary, so do the rest only for dstProc /= 0
5959 : !
5960 : !-----------------------------------------------------------------------
5961 :
5962 8704 : if (dstProc == 0) return
5963 :
5964 : !-----------------------------------------------------------------------
5965 : !
5966 : ! get block information if either block is local
5967 : !
5968 : !-----------------------------------------------------------------------
5969 :
5970 7008 : if (srcProc == my_task+1 .or. dstProc == my_task+1) then
5971 :
5972 1880 : if (srcBlock >= 0 .and. dstBlock >= 0) then
5973 : call get_block_parameter(srcBlock, &
5974 : ilo=ibSrc, ihi=ieSrc, & ! LCOV_EXCL_LINE
5975 1880 : jlo=jbSrc, jhi=jeSrc)
5976 : else ! tripole - need iGlobal info
5977 : call get_block_parameter(abs(srcBlock), &
5978 : ilo=ibSrc, ihi=ieSrc, & ! LCOV_EXCL_LINE
5979 : jlo=jbSrc, jhi=jeSrc, & ! LCOV_EXCL_LINE
5980 0 : i_glob=iGlobal)
5981 :
5982 : endif
5983 :
5984 1880 : if (dstBlock /= 0) then
5985 : call get_block_parameter(abs(dstBlock), &
5986 : ilo=ibDst, ihi=ieDst, & ! LCOV_EXCL_LINE
5987 1880 : jlo=jbDst, jhi=jeDst)
5988 : endif
5989 :
5990 : endif
5991 :
5992 : !-----------------------------------------------------------------------
5993 : !
5994 : ! if both blocks are local, create a local copy to fill halo
5995 : !
5996 : !-----------------------------------------------------------------------
5997 :
5998 7008 : if (srcProc == my_task+1 .and. &
5999 : dstProc == my_task+1) then
6000 :
6001 : !*** compute addresses based on direction
6002 :
6003 176 : msgIndx = halo%numLocalCopies
6004 :
6005 176 : if (msgIndx > size(halo%srcLocalAddr,dim=2) .or. &
6006 : msgIndx > size(halo%dstLocalAddr,dim=2)) then
6007 0 : call abort_ice(subname//'ERROR: msg count > array size')
6008 0 : return
6009 : endif
6010 :
6011 24 : select case (direction)
6012 : case ('east')
6013 :
6014 : !*** copy easternmost physical domain of src
6015 : !*** into westernmost halo of dst
6016 :
6017 744 : do j=1,jeSrc-jbSrc+1
6018 1416 : do i=1,nghost
6019 :
6020 696 : msgIndx = msgIndx + 1
6021 :
6022 696 : halo%srcLocalAddr(1,msgIndx) = ieSrc - nghost + i
6023 696 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
6024 696 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6025 :
6026 696 : halo%dstLocalAddr(1,msgIndx) = i
6027 696 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
6028 1392 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6029 :
6030 : end do
6031 : end do
6032 :
6033 : case ('west')
6034 :
6035 : !*** copy westernmost physical domain of src
6036 : !*** into easternmost halo of dst
6037 :
6038 744 : do j=1,jeSrc-jbSrc+1
6039 1416 : do i=1,nghost
6040 :
6041 696 : msgIndx = msgIndx + 1
6042 :
6043 696 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
6044 696 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
6045 696 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6046 :
6047 696 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
6048 696 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
6049 1392 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6050 :
6051 : end do
6052 : end do
6053 :
6054 : case ('north')
6055 :
6056 : !*** copy northern physical domain of src
6057 : !*** into southern halo of dst
6058 :
6059 40 : if (srcBlock > 0 .and. dstBlock > 0) then ! normal north boundary
6060 :
6061 80 : do j=1,nghost
6062 1192 : do i=1,ieSrc-ibSrc+1
6063 :
6064 1112 : msgIndx = msgIndx + 1
6065 :
6066 1112 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
6067 1112 : halo%srcLocalAddr(2,msgIndx) = jeSrc - nghost + j
6068 1112 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6069 :
6070 1112 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
6071 1112 : halo%dstLocalAddr(2,msgIndx) = j
6072 1152 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6073 :
6074 : end do
6075 : end do
6076 :
6077 0 : else if (srcBlock > 0 .and. dstBlock < 0) then
6078 :
6079 : !*** tripole grid - copy info into tripole buffer
6080 : !*** copy physical domain of top halo+1 rows
6081 : !*** into global buffer at src location
6082 :
6083 : !*** perform an error check to make sure the
6084 : !*** block has enough points to perform a tripole
6085 : !*** update
6086 :
6087 0 : if (jeSrc - jbSrc + 1 < halo%tripoleRows) then
6088 0 : call abort_ice(subname//'ERROR: not enough points in block for tripole')
6089 0 : return
6090 : endif
6091 :
6092 0 : do j=1,halo%tripoleRows
6093 0 : do i=1,ieSrc-ibSrc+1
6094 :
6095 0 : msgIndx = msgIndx + 1
6096 :
6097 0 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
6098 0 : halo%srcLocalAddr(2,msgIndx) = jeSrc-halo%tripoleRows+j
6099 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6100 :
6101 0 : halo%dstLocalAddr(1,msgIndx) = iGlobal(ibSrc + i - 1)
6102 0 : halo%dstLocalAddr(2,msgIndx) = j
6103 0 : halo%dstLocalAddr(3,msgIndx) = -dstLocalID
6104 :
6105 : end do
6106 : end do
6107 :
6108 0 : else if (srcBlock < 0 .and. dstBlock > 0) then
6109 :
6110 : !*** tripole grid - set up for copying out of
6111 : !*** tripole buffer into ghost cell domains
6112 : !*** include e-w ghost cells
6113 :
6114 0 : do j=1,halo%tripoleRows
6115 0 : do i=1,ieSrc+nghost
6116 :
6117 0 : msgIndx = msgIndx + 1
6118 :
6119 0 : halo%srcLocalAddr(1,msgIndx) = nxGlobal - iGlobal(i) + 1
6120 0 : halo%srcLocalAddr(2,msgIndx) = nghost + 3 - j
6121 0 : halo%srcLocalAddr(3,msgIndx) = -srcLocalID
6122 :
6123 0 : halo%dstLocalAddr(1,msgIndx) = i
6124 0 : if (j.gt.nghost+1) then
6125 0 : halo%dstLocalAddr(2,msgIndx) = -1 ! never used
6126 : else
6127 0 : halo%dstLocalAddr(2,msgIndx) = jeSrc + j - 1
6128 : endif
6129 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6130 :
6131 : end do
6132 : end do
6133 :
6134 : endif
6135 :
6136 : case ('south')
6137 :
6138 : !*** copy southern physical domain of src
6139 : !*** into northern halo of dst
6140 :
6141 120 : do j=1,nghost
6142 1192 : do i=1,ieSrc-ibSrc+1
6143 :
6144 1112 : msgIndx = msgIndx + 1
6145 :
6146 1112 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
6147 1112 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
6148 1112 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6149 :
6150 1112 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
6151 1112 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
6152 1152 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6153 :
6154 : end do
6155 : end do
6156 :
6157 : case ('northeast')
6158 :
6159 : !*** normal northeast boundary - just copy NE corner
6160 : !*** of physical domain into SW halo of NE nbr block
6161 :
6162 12 : if (dstBlock > 0) then
6163 :
6164 24 : do j=1,nghost
6165 36 : do i=1,nghost
6166 :
6167 12 : msgIndx = msgIndx + 1
6168 :
6169 12 : halo%srcLocalAddr(1,msgIndx) = ieSrc - nghost + i
6170 12 : halo%srcLocalAddr(2,msgIndx) = jeSrc - nghost + j
6171 12 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6172 :
6173 12 : halo%dstLocalAddr(1,msgIndx) = i
6174 12 : halo%dstLocalAddr(2,msgIndx) = j
6175 24 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6176 :
6177 : end do
6178 : end do
6179 :
6180 : else
6181 :
6182 : !*** tripole grid - this local copy should already
6183 : !*** have taken place for the north boundary
6184 :
6185 : endif
6186 :
6187 : case ('northwest')
6188 :
6189 : !*** normal northeast boundary - just copy NW corner
6190 : !*** of physical domain into SE halo of NW nbr block
6191 :
6192 12 : if (dstBlock > 0) then
6193 :
6194 24 : do j=1,nghost
6195 36 : do i=1,nghost
6196 :
6197 12 : msgIndx = msgIndx + 1
6198 :
6199 12 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
6200 12 : halo%srcLocalAddr(2,msgIndx) = jeSrc - nghost + j
6201 12 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6202 :
6203 12 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
6204 12 : halo%dstLocalAddr(2,msgIndx) = j
6205 24 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6206 :
6207 : end do
6208 : end do
6209 :
6210 : else
6211 :
6212 : !*** tripole grid - this local copy should already
6213 : !*** have taken place for the north boundary
6214 :
6215 : endif
6216 :
6217 : case ('southeast')
6218 :
6219 : !*** copy southeastern corner of src physical domain
6220 : !*** into northwestern halo of dst
6221 :
6222 36 : do j=1,nghost
6223 36 : do i=1,nghost
6224 :
6225 12 : msgIndx = msgIndx + 1
6226 :
6227 12 : halo%srcLocalAddr(1,msgIndx) = ieSrc - nghost + i
6228 12 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
6229 12 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6230 :
6231 12 : halo%dstLocalAddr(1,msgIndx) = i
6232 12 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
6233 24 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6234 :
6235 : end do
6236 : end do
6237 :
6238 : case ('southwest')
6239 :
6240 : !*** copy southwestern corner of src physical domain
6241 : !*** into northeastern halo of dst
6242 :
6243 36 : do j=1,nghost
6244 36 : do i=1,nghost
6245 :
6246 12 : msgIndx = msgIndx + 1
6247 :
6248 12 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
6249 12 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
6250 12 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
6251 :
6252 12 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
6253 12 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
6254 24 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6255 :
6256 : end do
6257 : end do
6258 :
6259 : case default
6260 :
6261 0 : call abort_ice(subname//'ERROR: unknown direction local copy')
6262 176 : return
6263 :
6264 : end select
6265 :
6266 176 : halo%numLocalCopies = msgIndx
6267 :
6268 176 : if (msgIndx > size(halo%srcLocalAddr,dim=2) .or. &
6269 : msgIndx > size(halo%dstLocalAddr,dim=2)) then
6270 0 : call abort_ice(subname//'ERROR: msg count > array size')
6271 0 : return
6272 : endif
6273 :
6274 : !-----------------------------------------------------------------------
6275 : !
6276 : ! if dest block is local and source block does not exist, create a
6277 : ! local copy to fill halo with a fill value
6278 : !
6279 : !-----------------------------------------------------------------------
6280 :
6281 6832 : else if (srcProc == 0 .and. dstProc == my_task+1) then
6282 :
6283 8 : msgIndx = halo%numLocalCopies
6284 :
6285 8 : if (msgIndx > size(halo%srcLocalAddr,dim=2) .or. &
6286 : msgIndx > size(halo%dstLocalAddr,dim=2)) then
6287 0 : call abort_ice(subname//'ERROR: msg count > array size')
6288 0 : return
6289 : endif
6290 :
6291 : !*** compute addresses based on direction
6292 :
6293 1 : select case (direction)
6294 : case ('east')
6295 :
6296 : !*** copy easternmost physical domain of src
6297 : !*** into westernmost halo of dst
6298 :
6299 31 : do j=1,jeSrc-jbSrc+1
6300 59 : do i=1,nghost
6301 :
6302 29 : msgIndx = msgIndx + 1
6303 :
6304 29 : halo%srcLocalAddr(1,msgIndx) = 0
6305 29 : halo%srcLocalAddr(2,msgIndx) = 0
6306 29 : halo%srcLocalAddr(3,msgIndx) = 0
6307 :
6308 29 : halo%dstLocalAddr(1,msgIndx) = i
6309 29 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
6310 58 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6311 :
6312 : end do
6313 : end do
6314 :
6315 : case ('west')
6316 :
6317 : !*** copy westernmost physical domain of src
6318 : !*** into easternmost halo of dst
6319 :
6320 31 : do j=1,jeSrc-jbSrc+1
6321 59 : do i=1,nghost
6322 :
6323 29 : msgIndx = msgIndx + 1
6324 :
6325 29 : halo%srcLocalAddr(1,msgIndx) = 0
6326 29 : halo%srcLocalAddr(2,msgIndx) = 0
6327 29 : halo%srcLocalAddr(3,msgIndx) = 0
6328 :
6329 29 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
6330 29 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
6331 58 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6332 :
6333 : end do
6334 : end do
6335 :
6336 : case ('north')
6337 :
6338 : !*** copy northern physical domain of src
6339 : !*** into southern halo of dst
6340 :
6341 1 : if (dstBlock > 0) then ! normal north boundary
6342 :
6343 2 : do j=1,nghost
6344 7 : do i=1,ieSrc-ibSrc+1
6345 :
6346 5 : msgIndx = msgIndx + 1
6347 :
6348 5 : halo%srcLocalAddr(1,msgIndx) = 0
6349 5 : halo%srcLocalAddr(2,msgIndx) = 0
6350 5 : halo%srcLocalAddr(3,msgIndx) = 0
6351 :
6352 5 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
6353 5 : halo%dstLocalAddr(2,msgIndx) = j
6354 6 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6355 :
6356 : end do
6357 : end do
6358 :
6359 : endif
6360 :
6361 : case ('south')
6362 :
6363 : !*** copy southern physical domain of src
6364 : !*** into northern halo of dst
6365 :
6366 3 : do j=1,nghost
6367 7 : do i=1,ieSrc-ibSrc+1
6368 :
6369 5 : msgIndx = msgIndx + 1
6370 :
6371 5 : halo%srcLocalAddr(1,msgIndx) = 0
6372 5 : halo%srcLocalAddr(2,msgIndx) = 0
6373 5 : halo%srcLocalAddr(3,msgIndx) = 0
6374 :
6375 5 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
6376 5 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
6377 6 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6378 :
6379 : end do
6380 : end do
6381 :
6382 : case ('northeast')
6383 :
6384 : !*** normal northeast boundary - just copy NE corner
6385 : !*** of physical domain into SW halo of NE nbr block
6386 :
6387 1 : if (dstBlock > 0) then
6388 :
6389 2 : do j=1,nghost
6390 3 : do i=1,nghost
6391 :
6392 1 : msgIndx = msgIndx + 1
6393 :
6394 1 : halo%srcLocalAddr(1,msgIndx) = 0
6395 1 : halo%srcLocalAddr(2,msgIndx) = 0
6396 1 : halo%srcLocalAddr(3,msgIndx) = 0
6397 :
6398 1 : halo%dstLocalAddr(1,msgIndx) = i
6399 1 : halo%dstLocalAddr(2,msgIndx) = j
6400 2 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6401 :
6402 : end do
6403 : end do
6404 :
6405 : endif
6406 :
6407 : case ('northwest')
6408 :
6409 : !*** normal northeast boundary - just copy NW corner
6410 : !*** of physical domain into SE halo of NW nbr block
6411 :
6412 1 : if (dstBlock > 0) then
6413 :
6414 2 : do j=1,nghost
6415 3 : do i=1,nghost
6416 :
6417 1 : msgIndx = msgIndx + 1
6418 :
6419 1 : halo%srcLocalAddr(1,msgIndx) = 0
6420 1 : halo%srcLocalAddr(2,msgIndx) = 0
6421 1 : halo%srcLocalAddr(3,msgIndx) = 0
6422 :
6423 1 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
6424 1 : halo%dstLocalAddr(2,msgIndx) = j
6425 2 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6426 :
6427 : end do
6428 : end do
6429 :
6430 : endif
6431 :
6432 : case ('southeast')
6433 :
6434 : !*** copy southeastern corner of src physical domain
6435 : !*** into northwestern halo of dst
6436 :
6437 3 : do j=1,nghost
6438 3 : do i=1,nghost
6439 :
6440 1 : msgIndx = msgIndx + 1
6441 :
6442 1 : halo%srcLocalAddr(1,msgIndx) = 0
6443 1 : halo%srcLocalAddr(2,msgIndx) = 0
6444 1 : halo%srcLocalAddr(3,msgIndx) = 0
6445 :
6446 1 : halo%dstLocalAddr(1,msgIndx) = i
6447 1 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
6448 2 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6449 :
6450 : end do
6451 : end do
6452 :
6453 : case ('southwest')
6454 :
6455 : !*** copy southwestern corner of src physical domain
6456 : !*** into northeastern halo of dst
6457 :
6458 3 : do j=1,nghost
6459 3 : do i=1,nghost
6460 :
6461 1 : msgIndx = msgIndx + 1
6462 :
6463 1 : halo%srcLocalAddr(1,msgIndx) = 0
6464 1 : halo%srcLocalAddr(2,msgIndx) = 0
6465 1 : halo%srcLocalAddr(3,msgIndx) = 0
6466 :
6467 1 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
6468 1 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
6469 2 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
6470 :
6471 : end do
6472 : end do
6473 :
6474 : case default
6475 :
6476 0 : call abort_ice(subname//'ERROR: unknown direction local copy')
6477 8 : return
6478 :
6479 : end select
6480 :
6481 8 : halo%numLocalCopies = msgIndx
6482 :
6483 8 : if (msgIndx > size(halo%srcLocalAddr,dim=2) .or. &
6484 : msgIndx > size(halo%dstLocalAddr,dim=2)) then
6485 0 : call abort_ice(subname//'ERROR: msg count > array size')
6486 0 : return
6487 : endif
6488 :
6489 : !-----------------------------------------------------------------------
6490 : !
6491 : ! if source block local and dest block remote, send a message
6492 : !
6493 : !-----------------------------------------------------------------------
6494 :
6495 : else if (srcProc == my_task+1 .and. &
6496 6824 : dstProc /= my_task+1 .and. dstProc > 0) then
6497 :
6498 : !*** first check to see if a message to this processor has
6499 : !*** already been defined
6500 : !*** if not, update counters and indices
6501 :
6502 848 : msgIndx = 0
6503 :
6504 2441 : srchSend: do n=1,halo%numMsgSend
6505 2441 : if (halo%sendTask(n) == dstProc - 1) then
6506 676 : msgIndx = n
6507 676 : bufSize = halo%sizeSend(n)
6508 676 : exit srchSend
6509 : endif
6510 : end do srchSend
6511 :
6512 848 : if (msgIndx == 0) then
6513 172 : msgIndx = halo%numMsgSend + 1
6514 172 : halo%numMsgSend = msgIndx
6515 172 : halo%sendTask(msgIndx) = dstProc - 1
6516 172 : bufSize = 0
6517 : endif
6518 :
6519 : !*** now compute message info based on msg direction
6520 :
6521 134 : select case (direction)
6522 : case ('east')
6523 :
6524 : !*** send easternmost physical domain of src
6525 : !*** into westernmost halo of dst
6526 :
6527 4116 : do j=1,jeSrc-jbSrc+1
6528 8098 : do i=1,nghost
6529 :
6530 3982 : bufSize = bufSize + 1
6531 :
6532 3982 : halo%sendAddr(1,bufSize,msgIndx) = ieSrc - nghost + i
6533 3982 : halo%sendAddr(2,bufSize,msgIndx) = jbSrc + j - 1
6534 7964 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6535 :
6536 : end do
6537 : end do
6538 :
6539 134 : halo%sizeSend(msgIndx) = bufSize
6540 :
6541 : case ('west')
6542 :
6543 : !*** copy westernmost physical domain of src
6544 : !*** into easternmost halo of dst
6545 :
6546 4116 : do j=1,jeSrc-jbSrc+1
6547 8098 : do i=1,nghost
6548 :
6549 3982 : bufSize = bufSize + 1
6550 :
6551 3982 : halo%sendAddr(1,bufSize,msgIndx) = ibSrc + i - 1
6552 3982 : halo%sendAddr(2,bufSize,msgIndx) = jbSrc + j - 1
6553 7964 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6554 :
6555 : end do
6556 : end do
6557 :
6558 134 : halo%sizeSend(msgIndx) = bufSize
6559 :
6560 : case ('north')
6561 :
6562 78 : if (dstBlock > 0) then
6563 :
6564 : !*** copy northern physical domain of src
6565 : !*** into southern halo of dst
6566 :
6567 156 : do j=1,nghost
6568 1002 : do i=1,ieSrc-ibSrc+1
6569 :
6570 846 : bufSize = bufSize + 1
6571 :
6572 846 : halo%sendAddr(1,bufSize,msgIndx) = ibSrc + i - 1
6573 846 : halo%sendAddr(2,bufSize,msgIndx) = jeSrc-nghost+j
6574 924 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6575 :
6576 : end do
6577 : end do
6578 :
6579 78 : halo%sizeSend(msgIndx) = bufSize
6580 :
6581 : else
6582 :
6583 : !*** tripole block - send top halo%tripoleRows rows of phys domain
6584 :
6585 0 : halo%tripSend(msgIndx) = 1
6586 0 : do j=1,halo%tripoleRows
6587 0 : do i=1,ieSrc-ibSrc+1
6588 :
6589 0 : bufSize = bufSize + 1
6590 :
6591 0 : halo%sendAddr(1,bufSize,msgIndx)=ibSrc + i - 1
6592 0 : halo%sendAddr(2,bufSize,msgIndx)=jeSrc-halo%tripoleRows+j
6593 0 : halo%sendAddr(3,bufSize,msgIndx)=srcLocalID
6594 :
6595 : end do
6596 : end do
6597 :
6598 0 : halo%sizeSend(msgIndx) = bufSize
6599 :
6600 : endif
6601 :
6602 : case ('south')
6603 :
6604 : !*** copy southern physical domain of src
6605 : !*** into northern halo of dst
6606 :
6607 156 : do j=1,nghost
6608 1002 : do i=1,ieSrc-ibSrc+1
6609 :
6610 846 : bufSize = bufSize + 1
6611 :
6612 846 : halo%sendAddr(1,bufSize,msgIndx) = ibSrc + i - 1
6613 846 : halo%sendAddr(2,bufSize,msgIndx) = jbSrc + j - 1
6614 924 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6615 :
6616 : end do
6617 : end do
6618 :
6619 78 : halo%sizeSend(msgIndx) = bufSize
6620 :
6621 : case ('northeast')
6622 :
6623 :
6624 106 : if (dstBlock > 0) then
6625 :
6626 : !*** normal northeast corner
6627 : !*** copy northeast corner of src physical domain
6628 : !*** into southwestern halo of dst
6629 :
6630 212 : do j=1,nghost
6631 318 : do i=1,nghost
6632 :
6633 106 : bufSize = bufSize + 1
6634 :
6635 106 : halo%sendAddr(1,bufSize,msgIndx) = ieSrc-nghost+i
6636 106 : halo%sendAddr(2,bufSize,msgIndx) = jeSrc-nghost+j
6637 212 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6638 :
6639 : end do
6640 : end do
6641 :
6642 106 : halo%sizeSend(msgIndx) = bufSize
6643 :
6644 : else
6645 :
6646 : !*** tripole block - send top halo%tripoleRows rows of phys domain
6647 :
6648 0 : halo%tripSend(msgIndx) = 1
6649 0 : do j=1,halo%tripoleRows
6650 0 : do i=1,ieSrc-ibSrc+1
6651 :
6652 0 : bufSize = bufSize + 1
6653 :
6654 0 : halo%sendAddr(1,bufSize,msgIndx)=ibSrc + i - 1
6655 0 : halo%sendAddr(2,bufSize,msgIndx)=jeSrc-halo%tripoleRows+j
6656 0 : halo%sendAddr(3,bufSize,msgIndx)=srcLocalID
6657 :
6658 : end do
6659 : end do
6660 :
6661 0 : halo%sizeSend(msgIndx) = bufSize
6662 :
6663 : endif
6664 :
6665 : case ('northwest')
6666 :
6667 106 : if (dstBlock > 0) then
6668 :
6669 : !*** normal northwest corner
6670 : !*** copy northwest corner of src physical domain
6671 : !*** into southeastern halo of dst
6672 :
6673 212 : do j=1,nghost
6674 318 : do i=1,nghost
6675 :
6676 106 : bufSize = bufSize + 1
6677 :
6678 106 : halo%sendAddr(1,bufSize,msgIndx) = ibSrc + i - 1
6679 106 : halo%sendAddr(2,bufSize,msgIndx) = jeSrc-nghost+j
6680 212 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6681 :
6682 : end do
6683 : end do
6684 :
6685 106 : halo%sizeSend(msgIndx) = bufSize
6686 :
6687 : else
6688 :
6689 : !*** tripole block - send top halo%tripoleRows rows of phys domain
6690 :
6691 0 : halo%tripSend(msgIndx) = 1
6692 0 : do j=1,halo%tripoleRows
6693 0 : do i=1,ieSrc-ibSrc+1
6694 :
6695 0 : bufSize = bufSize + 1
6696 :
6697 0 : halo%sendAddr(1,bufSize,msgIndx)=ibSrc + i - 1
6698 0 : halo%sendAddr(2,bufSize,msgIndx)=jeSrc-halo%tripoleRows+j
6699 0 : halo%sendAddr(3,bufSize,msgIndx)=srcLocalID
6700 :
6701 : end do
6702 : end do
6703 :
6704 0 : halo%sizeSend(msgIndx) = bufSize
6705 :
6706 : endif
6707 :
6708 : case ('southeast')
6709 :
6710 : !*** copy southeastern corner of src physical domain
6711 : !*** into northwestern halo of dst
6712 :
6713 212 : do j=1,nghost
6714 318 : do i=1,nghost
6715 :
6716 106 : bufSize = bufSize + 1
6717 :
6718 106 : halo%sendAddr(1,bufSize,msgIndx) = ieSrc - nghost + i
6719 106 : halo%sendAddr(2,bufSize,msgIndx) = jbSrc + j - 1
6720 212 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6721 :
6722 : end do
6723 : end do
6724 :
6725 106 : halo%sizeSend(msgIndx) = bufSize
6726 :
6727 : case ('southwest')
6728 :
6729 : !*** copy southwestern corner of src physical domain
6730 : !*** into northeastern halo of dst
6731 :
6732 212 : do j=1,nghost
6733 318 : do i=1,nghost
6734 :
6735 106 : bufSize = bufSize + 1
6736 :
6737 106 : halo%sendAddr(1,bufSize,msgIndx) = ibSrc + i - 1
6738 106 : halo%sendAddr(2,bufSize,msgIndx) = jbSrc + j - 1
6739 212 : halo%sendAddr(3,bufSize,msgIndx) = srcLocalID
6740 :
6741 : end do
6742 : end do
6743 :
6744 954 : halo%sizeSend(msgIndx) = bufSize
6745 :
6746 : case default
6747 :
6748 : !*** already checked in previous case construct
6749 :
6750 : end select
6751 :
6752 : !-----------------------------------------------------------------------
6753 : !
6754 : ! if source block remote and dest block local, recv a message
6755 : !
6756 : !-----------------------------------------------------------------------
6757 :
6758 : else if (dstProc == my_task+1 .and. &
6759 5976 : srcProc /= my_task+1 .and. srcProc > 0) then
6760 :
6761 : !*** first check to see if a message from this processor has
6762 : !*** already been defined
6763 : !*** if not, update counters and indices
6764 :
6765 848 : msgIndx = 0
6766 :
6767 2613 : srchRecv: do n=1,halo%numMsgRecv
6768 2613 : if (halo%recvTask(n) == srcProc - 1) then
6769 676 : msgIndx = n
6770 676 : bufSize = halo%sizeRecv(n)
6771 676 : exit srchRecv
6772 : endif
6773 : end do srchRecv
6774 :
6775 848 : if (msgIndx == 0) then
6776 172 : msgIndx = halo%numMsgRecv + 1
6777 172 : halo%numMsgRecv = msgIndx
6778 172 : halo%recvTask(msgIndx) = srcProc - 1
6779 172 : bufSize = 0
6780 : endif
6781 :
6782 : !*** now compute message info based on msg direction
6783 :
6784 134 : select case (direction)
6785 : case ('east')
6786 :
6787 : !*** send easternmost physical domain of src
6788 : !*** into westernmost halo of dst
6789 :
6790 4116 : do j=1,jeSrc-jbSrc+1
6791 8098 : do i=1,nghost
6792 :
6793 3982 : bufSize = bufSize + 1
6794 :
6795 3982 : halo%recvAddr(1,bufSize,msgIndx) = i
6796 3982 : halo%recvAddr(2,bufSize,msgIndx) = jbDst + j - 1
6797 7964 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6798 :
6799 : end do
6800 : end do
6801 :
6802 134 : halo%sizeRecv(msgIndx) = bufSize
6803 :
6804 : case ('west')
6805 :
6806 : !*** copy westernmost physical domain of src
6807 : !*** into easternmost halo of dst
6808 :
6809 4116 : do j=1,jeSrc-jbSrc+1
6810 8098 : do i=1,nghost
6811 :
6812 3982 : bufSize = bufSize + 1
6813 :
6814 3982 : halo%recvAddr(1,bufSize,msgIndx) = ieDst + i
6815 3982 : halo%recvAddr(2,bufSize,msgIndx) = jbDst + j - 1
6816 7964 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6817 :
6818 : end do
6819 : end do
6820 :
6821 134 : halo%sizeRecv(msgIndx) = bufSize
6822 :
6823 : case ('north')
6824 :
6825 78 : if (dstBlock > 0) then
6826 :
6827 : !*** copy northern physical domain of src
6828 : !*** into southern halo of dst
6829 :
6830 156 : do j=1,nghost
6831 1002 : do i=1,ieDst-ibDst+1
6832 :
6833 846 : bufSize = bufSize + 1
6834 :
6835 846 : halo%recvAddr(1,bufSize,msgIndx) = ibDst + i - 1
6836 846 : halo%recvAddr(2,bufSize,msgIndx) = j
6837 924 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6838 :
6839 : end do
6840 : end do
6841 :
6842 78 : halo%sizeRecv(msgIndx) = bufSize
6843 :
6844 : else
6845 :
6846 : !*** tripole block - receive into tripole buffer
6847 :
6848 0 : halo%tripRecv(msgIndx) = 1
6849 0 : do j=1,halo%tripoleRows
6850 0 : do i=1,ieSrc-ibSrc+1
6851 :
6852 0 : bufSize = bufSize + 1
6853 :
6854 0 : halo%recvAddr(1,bufSize,msgIndx) = iGlobal(ibSrc + i - 1)
6855 0 : halo%recvAddr(2,bufSize,msgIndx) = j
6856 0 : halo%recvAddr(3,bufSize,msgIndx) = -dstLocalID
6857 :
6858 : end do
6859 : end do
6860 :
6861 0 : halo%sizeRecv(msgIndx) = bufSize
6862 :
6863 : endif
6864 :
6865 : case ('south')
6866 :
6867 : !*** copy southern physical domain of src
6868 : !*** into northern halo of dst
6869 :
6870 156 : do j=1,nghost
6871 1002 : do i=1,ieSrc-ibSrc+1
6872 :
6873 846 : bufSize = bufSize + 1
6874 :
6875 846 : halo%recvAddr(1,bufSize,msgIndx) = ibDst + i - 1
6876 846 : halo%recvAddr(2,bufSize,msgIndx) = jeDst + j
6877 924 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6878 :
6879 : end do
6880 : end do
6881 :
6882 78 : halo%sizeRecv(msgIndx) = bufSize
6883 :
6884 : case ('northeast')
6885 :
6886 106 : if (dstBlock > 0) then
6887 :
6888 : !*** normal northeast neighbor
6889 : !*** copy northeast physical domain into
6890 : !*** into southwest halo of dst
6891 :
6892 212 : do j=1,nghost
6893 318 : do i=1,nghost
6894 :
6895 106 : bufSize = bufSize + 1
6896 :
6897 106 : halo%recvAddr(1,bufSize,msgIndx) = i
6898 106 : halo%recvAddr(2,bufSize,msgIndx) = j
6899 212 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6900 :
6901 : end do
6902 : end do
6903 :
6904 106 : halo%sizeRecv(msgIndx) = bufSize
6905 :
6906 : else
6907 :
6908 : !*** tripole block - receive into tripole buffer
6909 :
6910 0 : halo%tripRecv(msgIndx) = 1
6911 0 : do j=1,halo%tripoleRows
6912 0 : do i=1,ieSrc-ibSrc+1
6913 :
6914 0 : bufSize = bufSize + 1
6915 :
6916 0 : halo%recvAddr(1,bufSize,msgIndx) = iGlobal(ibSrc + i - 1)
6917 0 : halo%recvAddr(2,bufSize,msgIndx) = j
6918 0 : halo%recvAddr(3,bufSize,msgIndx) = -dstLocalID
6919 :
6920 : end do
6921 : end do
6922 :
6923 0 : halo%sizeRecv(msgIndx) = bufSize
6924 :
6925 : endif
6926 :
6927 : case ('northwest')
6928 :
6929 106 : if (dstBlock > 0) then
6930 :
6931 : !*** normal northwest neighbor
6932 : !*** copy northwest physical domain into
6933 : !*** into southeast halo of dst
6934 :
6935 212 : do j=1,nghost
6936 318 : do i=1,nghost
6937 :
6938 106 : bufSize = bufSize + 1
6939 :
6940 106 : halo%recvAddr(1,bufSize,msgIndx) = ieDst + i
6941 106 : halo%recvAddr(2,bufSize,msgIndx) = j
6942 212 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6943 :
6944 : end do
6945 : end do
6946 :
6947 106 : halo%sizeRecv(msgIndx) = bufSize
6948 :
6949 : else
6950 :
6951 : !*** tripole block - receive into tripole buffer
6952 :
6953 0 : halo%tripRecv(msgIndx) = 1
6954 0 : do j=1,halo%tripoleRows
6955 0 : do i=1,ieSrc-ibSrc+1
6956 :
6957 0 : bufSize = bufSize + 1
6958 :
6959 0 : halo%recvAddr(1,bufSize,msgIndx) = iGlobal(ibSrc + i - 1)
6960 0 : halo%recvAddr(2,bufSize,msgIndx) = j
6961 0 : halo%recvAddr(3,bufSize,msgIndx) = -dstLocalID
6962 :
6963 : end do
6964 : end do
6965 :
6966 0 : halo%sizeRecv(msgIndx) = bufSize
6967 :
6968 : endif
6969 :
6970 : case ('southeast')
6971 :
6972 : !*** copy southeastern corner of src physical domain
6973 : !*** into northwestern halo of dst
6974 :
6975 212 : do j=1,nghost
6976 318 : do i=1,nghost
6977 :
6978 106 : bufSize = bufSize + 1
6979 :
6980 106 : halo%recvAddr(1,bufSize,msgIndx) = i
6981 106 : halo%recvAddr(2,bufSize,msgIndx) = jeDst + j
6982 212 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
6983 :
6984 : end do
6985 : end do
6986 :
6987 106 : halo%sizeRecv(msgIndx) = bufSize
6988 :
6989 : case ('southwest')
6990 :
6991 : !*** copy southwestern corner of src physical domain
6992 : !*** into northeastern halo of dst
6993 :
6994 212 : do j=1,nghost
6995 318 : do i=1,nghost
6996 :
6997 106 : bufSize = bufSize + 1
6998 :
6999 106 : halo%recvAddr(1,bufSize,msgIndx) = ieDst + i
7000 106 : halo%recvAddr(2,bufSize,msgIndx) = jeDst + j
7001 212 : halo%recvAddr(3,bufSize,msgIndx) = dstLocalID
7002 :
7003 : end do
7004 : end do
7005 :
7006 954 : halo%sizeRecv(msgIndx) = bufSize
7007 :
7008 : case default
7009 :
7010 : !*** already checked in previous case construct
7011 :
7012 : end select
7013 :
7014 : !-----------------------------------------------------------------------
7015 : !
7016 : ! if none of the cases above, no message info required for this
7017 : ! block pair
7018 : !
7019 : !-----------------------------------------------------------------------
7020 :
7021 : endif
7022 :
7023 : !-----------------------------------------------------------------------
7024 :
7025 8704 : end subroutine ice_HaloMsgCreate
7026 :
7027 : !***********************************************************************
7028 :
7029 288 : subroutine ice_HaloExtrapolate2DR8(ARRAY,dist,ew_bndy_type,ns_bndy_type)
7030 :
7031 : ! This subroutine extrapolates ARRAY values into the first row or column
7032 : ! of ghost cells, and is intended for grid variables whose ghost cells
7033 : ! would otherwise be set using the default boundary conditions (Dirichlet
7034 : ! or Neumann).
7035 : ! Note: This routine will need to be modified for nghost > 1.
7036 : ! We assume padding occurs only on east and north edges.
7037 : !
7038 : ! This is the specific interface for double precision arrays
7039 : ! corresponding to the generic interface ice_HaloExtrapolate
7040 :
7041 : use ice_blocks, only: block, nblocks_x, nblocks_y, get_block
7042 : use ice_constants, only: c2
7043 : use ice_distribution, only: ice_distributionGetBlockID
7044 :
7045 : character (char_len) :: &
7046 : ew_bndy_type, &! type of domain bndy in each logical ! LCOV_EXCL_LINE
7047 : ns_bndy_type ! direction (ew is i, ns is j)
7048 :
7049 : type (distrb), intent(in) :: &
7050 : dist ! block distribution for array X
7051 :
7052 : real (dbl_kind), dimension(:,:,:), intent(inout) :: &
7053 : ARRAY ! array containing distributed field
7054 :
7055 : !-----------------------------------------------------------------------
7056 : !
7057 : ! local variables
7058 : !
7059 : !-----------------------------------------------------------------------
7060 :
7061 : integer (int_kind) :: &
7062 : i,j,iblk, &! dummy loop indices ! LCOV_EXCL_LINE
7063 : numBlocks, &! number of local blocks ! LCOV_EXCL_LINE
7064 : blockID, &! block location ! LCOV_EXCL_LINE
7065 : ibc ! ghost cell column or row
7066 :
7067 : type (block) :: &
7068 : this_block ! block info for current block
7069 :
7070 : character(len=*), parameter :: subname = '(ice_HaloExtrapolate2DR8)'
7071 : !-----------------------------------------------------------------------
7072 : !
7073 : ! Linear extrapolation
7074 : !
7075 : !-----------------------------------------------------------------------
7076 :
7077 : call ice_distributionGet(dist, &
7078 288 : numLocalBlocks = numBlocks)
7079 :
7080 1560 : do iblk = 1, numBlocks
7081 1272 : call ice_distributionGetBlockID(dist, iblk, blockID)
7082 1272 : this_block = get_block(blockID, blockID)
7083 :
7084 1272 : if (this_block%iblock == 1) then ! west edge
7085 192 : if (trim(ew_bndy_type) /= 'cyclic') then
7086 0 : do j = 1, ny_block
7087 0 : ARRAY(1,j,iblk) = c2*ARRAY(2,j,iblk) - ARRAY(3,j,iblk)
7088 : enddo
7089 : endif
7090 : endif
7091 :
7092 1272 : if (this_block%iblock == nblocks_x) then ! east edge
7093 192 : if (trim(ew_bndy_type) /= 'cyclic') then
7094 : ! locate ghost cell column (avoid padding)
7095 0 : ibc = nx_block
7096 0 : do i = nx_block, nghost + 1, -1
7097 0 : if (this_block%i_glob(i) == 0) ibc = ibc - 1
7098 : enddo
7099 0 : do j = 1, ny_block
7100 0 : ARRAY(ibc,j,iblk) = c2*ARRAY(ibc-1,j,iblk) - ARRAY(ibc-2,j,iblk)
7101 : enddo
7102 : endif
7103 : endif
7104 :
7105 1272 : if (this_block%jblock == 1) then ! south edge
7106 320 : if (trim(ns_bndy_type) /= 'cyclic') then
7107 6208 : do i = 1, nx_block
7108 6208 : ARRAY(i,1,iblk) = c2*ARRAY(i,2,iblk) - ARRAY(i,3,iblk)
7109 : enddo
7110 : endif
7111 : endif
7112 :
7113 2832 : if (this_block%jblock == nblocks_y) then ! north edge
7114 : if (trim(ns_bndy_type) /= 'cyclic' .and. &
7115 : trim(ns_bndy_type) /= 'tripole' .and. & ! LCOV_EXCL_LINE
7116 : trim(ns_bndy_type) /= 'tripoleT' ) then
7117 : ! locate ghost cell column (avoid padding)
7118 320 : ibc = ny_block
7119 10112 : do j = ny_block, nghost + 1, -1
7120 10112 : if (this_block%j_glob(j) == 0) ibc = ibc - 1
7121 : enddo
7122 6208 : do i = 1, nx_block
7123 6208 : ARRAY(i,ibc,iblk) = c2*ARRAY(i,ibc-1,iblk) - ARRAY(i,ibc-2,iblk)
7124 : enddo
7125 : endif
7126 : endif
7127 :
7128 : enddo ! iblk
7129 :
7130 : !-----------------------------------------------------------------------
7131 :
7132 288 : end subroutine ice_HaloExtrapolate2DR8
7133 :
7134 : !***********************************************************************
7135 :
7136 0 : subroutine ice_HaloDestroy(halo)
7137 :
7138 : ! This routine creates a halo type with info necessary for
7139 : ! performing a halo (ghost cell) update. This info is computed
7140 : ! based on the input block distribution.
7141 :
7142 : type (ice_halo) :: &
7143 : halo ! a new halo type with info for halo updates
7144 :
7145 : integer (int_kind) :: &
7146 : istat ! error or status flag for MPI,alloc
7147 :
7148 : character(len=*), parameter :: subname = '(ice_HaloDestroy)'
7149 : !-----------------------------------------------------------------------
7150 :
7151 : deallocate(halo%sendTask, &
7152 : halo%recvTask, & ! LCOV_EXCL_LINE
7153 : halo%sizeSend, & ! LCOV_EXCL_LINE
7154 : halo%sizeRecv, & ! LCOV_EXCL_LINE
7155 : halo%tripSend, & ! LCOV_EXCL_LINE
7156 : halo%tripRecv, & ! LCOV_EXCL_LINE
7157 : halo%srcLocalAddr, & ! LCOV_EXCL_LINE
7158 : halo%dstLocalAddr, & ! LCOV_EXCL_LINE
7159 : halo%sendAddr, & ! LCOV_EXCL_LINE
7160 : halo%recvAddr, & ! LCOV_EXCL_LINE
7161 0 : halo%blockGlobalID, stat=istat)
7162 :
7163 0 : if (istat > 0) then
7164 0 : call abort_ice(subname,' ERROR: deallocating')
7165 0 : return
7166 : endif
7167 : end subroutine ice_HaloDestroy
7168 :
7169 : !***********************************************************************
7170 :
7171 0 : subroutine primary_grid_lengths_global_ext( &
7172 0 : ARRAY_O, ARRAY_I, ew_boundary_type, ns_boundary_type)
7173 :
7174 : ! This subroutine adds ghost cells to global primary grid lengths array
7175 : ! ARRAY_I and outputs result to array ARRAY_O
7176 :
7177 : use ice_constants, only: c0
7178 : use ice_domain_size, only: nx_global, ny_global
7179 :
7180 : real (kind=dbl_kind), dimension(:,:), intent(in) :: &
7181 : ARRAY_I
7182 :
7183 : character (*), intent(in) :: &
7184 : ew_boundary_type, ns_boundary_type
7185 :
7186 : real (kind=dbl_kind), dimension(:,:), intent(out) :: &
7187 : ARRAY_O
7188 :
7189 : !-----------------------------------------------------------------------
7190 : !
7191 : ! local variables
7192 : !
7193 : !-----------------------------------------------------------------------
7194 :
7195 : integer (kind=int_kind) :: &
7196 : ii, io, ji, jo
7197 :
7198 : character(len=*), parameter :: &
7199 : subname = '(primary_grid_lengths_global_ext)'
7200 :
7201 : !-----------------------------------------------------------------------
7202 : !
7203 : ! add ghost cells to global primary grid lengths array
7204 : !
7205 : !-----------------------------------------------------------------------
7206 :
7207 0 : if (trim(ns_boundary_type) == 'tripole' .or. &
7208 : trim(ns_boundary_type) == 'tripoleT') then
7209 : call abort_ice(subname//' ERROR: '//ns_boundary_type &
7210 0 : //' boundary type not implemented for configuration')
7211 : endif
7212 :
7213 0 : do jo = 1,ny_global+2*nghost
7214 0 : ji = -nghost + jo
7215 :
7216 : !*** Southern ghost cells
7217 :
7218 0 : if (ji < 1) then
7219 0 : select case (trim(ns_boundary_type))
7220 : case ('cyclic')
7221 0 : ji = ji + ny_global
7222 : case ('open')
7223 0 : ji = nghost - jo + 1
7224 : case ('closed')
7225 0 : ji = 0
7226 : case default
7227 : call abort_ice( &
7228 0 : subname//' ERROR: unknown north-south boundary type')
7229 : end select
7230 : endif
7231 :
7232 : !*** Northern ghost cells
7233 :
7234 0 : if (ji > ny_global) then
7235 0 : select case (trim(ns_boundary_type))
7236 : case ('cyclic')
7237 0 : ji = ji - ny_global
7238 : case ('open')
7239 0 : ji = 2 * ny_global - ji + 1
7240 : case ('closed')
7241 0 : ji = 0
7242 : case default
7243 : call abort_ice( &
7244 0 : subname//' ERROR: unknown north-south boundary type')
7245 : end select
7246 : endif
7247 :
7248 0 : do io = 1,nx_global+2*nghost
7249 0 : ii = -nghost + io
7250 :
7251 : !*** Western ghost cells
7252 :
7253 0 : if (ii < 1) then
7254 0 : select case (trim(ew_boundary_type))
7255 : case ('cyclic')
7256 0 : ii = ii + nx_global
7257 : case ('open')
7258 0 : ii = nghost - io + 1
7259 : case ('closed')
7260 0 : ii = 0
7261 : case default
7262 : call abort_ice( &
7263 0 : subname//' ERROR: unknown east-west boundary type')
7264 : end select
7265 : endif
7266 :
7267 : !*** Eastern ghost cells
7268 :
7269 0 : if (ii > nx_global) then
7270 0 : select case (trim(ew_boundary_type))
7271 : case ('cyclic')
7272 0 : ii = ii - nx_global
7273 : case ('open')
7274 0 : ii = 2 * nx_global - ii + 1
7275 : case ('closed')
7276 0 : ii = 0
7277 : case default
7278 : call abort_ice( &
7279 0 : subname//' ERROR: unknown east-west boundary type')
7280 : end select
7281 : endif
7282 :
7283 0 : if (ii == 0 .or. ji == 0) then
7284 0 : ARRAY_O(io, jo) = c0
7285 : else
7286 0 : ARRAY_O(io, jo) = ARRAY_I(ii, ji)
7287 : endif
7288 :
7289 : enddo
7290 : enddo
7291 :
7292 : !-----------------------------------------------------------------------
7293 :
7294 0 : end subroutine primary_grid_lengths_global_ext
7295 :
7296 : !***********************************************************************
7297 :
7298 0 : end module ice_boundary
7299 :
7300 : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|