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)
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 : ! 2023-03-09: Tony Craig updated the implementation to fix bug in
16 : ! tripoleT and reduce number of copies in tripole overall.
17 : ! Because all blocks are local, can fill the tripole
18 : ! buffer from "north" copies. This is not true for
19 : ! the MPI version.
20 :
21 : use ice_kinds_mod
22 : use ice_communicate, only: my_task
23 : use ice_constants, only: field_type_scalar, &
24 : field_type_vector, field_type_angle, & ! LCOV_EXCL_LINE
25 : field_type_unknown, field_type_noupdate, & ! LCOV_EXCL_LINE
26 : field_loc_center, field_loc_NEcorner, & ! LCOV_EXCL_LINE
27 : field_loc_Nface, field_loc_Eface, & ! LCOV_EXCL_LINE
28 : field_loc_unknown, field_loc_noupdate
29 : use ice_global_reductions, only: global_maxval
30 : use ice_exit, only: abort_ice
31 : use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
32 :
33 : use ice_blocks, only: nx_block, ny_block, nghost, &
34 : nblocks_tot, ice_blocksNorth, & ! LCOV_EXCL_LINE
35 : ice_blocksSouth, ice_blocksEast, ice_blocksWest, & ! LCOV_EXCL_LINE
36 : ice_blocksEast2, ice_blocksWest2, & ! LCOV_EXCL_LINE
37 : ice_blocksNorthEast, ice_blocksNorthWest, & ! LCOV_EXCL_LINE
38 : ice_blocksEastNorthEast, ice_blocksWestNorthWest, & ! LCOV_EXCL_LINE
39 : ice_blocksSouthEast, ice_blocksSouthWest, & ! LCOV_EXCL_LINE
40 : ice_blocksGetNbrID, get_block_parameter
41 : use ice_distribution, only: distrb, &
42 : ice_distributionGetBlockLoc, ice_distributionGet
43 :
44 : implicit none
45 : private
46 :
47 : type, public :: ice_halo
48 : integer (int_kind) :: &
49 : communicator, &! communicator to use for update messages ! LCOV_EXCL_LINE
50 : numLocalBlocks, &! number of local blocks, needed for halo fill ! LCOV_EXCL_LINE
51 : numLocalCopies, &! num local copies for halo update ! LCOV_EXCL_LINE
52 : tripoleRows ! number of rows in tripole buffer
53 :
54 : logical (log_kind) :: &
55 : tripoleTFlag ! NS boundary is a tripole T-fold
56 :
57 : integer (int_kind), dimension(:), pointer :: &
58 : blockGlobalID ! list of local block global IDs, needed for halo fill
59 :
60 : integer (int_kind), dimension(:,:), pointer :: &
61 : srcLocalAddr, &! src addresses for each local copy ! LCOV_EXCL_LINE
62 : dstLocalAddr ! dst addresses for each local copy
63 :
64 : end type
65 :
66 : public :: ice_HaloCreate, &
67 : ice_HaloMask, & ! LCOV_EXCL_LINE
68 : ice_HaloUpdate, & ! LCOV_EXCL_LINE
69 : ice_HaloUpdate_stress, & ! LCOV_EXCL_LINE
70 : ice_HaloExtrapolate, & ! LCOV_EXCL_LINE
71 : ice_HaloDestroy, & ! LCOV_EXCL_LINE
72 : primary_grid_lengths_global_ext
73 :
74 : interface ice_HaloUpdate ! generic interface
75 : module procedure ice_HaloUpdate2DR8, &
76 : ice_HaloUpdate2DR4, & ! LCOV_EXCL_LINE
77 : ice_HaloUpdate2DI4, & ! LCOV_EXCL_LINE
78 : ice_HaloUpdate2DL1, & ! LCOV_EXCL_LINE
79 : ice_HaloUpdate3DR8, & ! LCOV_EXCL_LINE
80 : ice_HaloUpdate3DR4, & ! LCOV_EXCL_LINE
81 : ice_HaloUpdate3DI4, & ! LCOV_EXCL_LINE
82 : ice_HaloUpdate4DR8, & ! LCOV_EXCL_LINE
83 : ice_HaloUpdate4DR4, & ! LCOV_EXCL_LINE
84 : ice_HaloUpdate4DI4
85 : end interface
86 :
87 : interface ice_HaloExtrapolate ! generic interface
88 : module procedure ice_HaloExtrapolate2DR8 !, &
89 : ! ice_HaloExtrapolate2DR4, & ! not yet ! LCOV_EXCL_LINE
90 : ! ice_HaloExtrapolate2DI4, & ! implemented ! LCOV_EXCL_LINE
91 : end interface
92 :
93 : !-----------------------------------------------------------------------
94 : !
95 : ! global buffers for tripole boundary
96 : !
97 : !-----------------------------------------------------------------------
98 :
99 : integer (int_kind), dimension(:,:), allocatable :: &
100 : bufTripoleI4
101 :
102 : real (real_kind), dimension(:,:), allocatable :: &
103 : bufTripoleR4
104 :
105 : real (dbl_kind), dimension(:,:), allocatable :: &
106 : bufTripoleR8
107 :
108 : !***********************************************************************
109 :
110 : contains
111 :
112 : !***********************************************************************
113 :
114 1 : function ice_HaloCreate(dist, nsBoundaryType, ewBoundaryType, &
115 : nxGlobal) result(halo)
116 :
117 : ! This routine creates a halo type with info necessary for
118 : ! performing a halo (ghost cell) update. This info is computed
119 : ! based on the input block distribution.
120 :
121 : type (distrb), intent(in) :: &
122 : dist ! distribution of blocks across procs
123 :
124 : character (*), intent(in) :: &
125 : nsBoundaryType, &! type of boundary to use in logical ns dir ! LCOV_EXCL_LINE
126 : ewBoundaryType ! type of boundary to use in logical ew dir
127 :
128 : integer (int_kind), intent(in) :: &
129 : nxGlobal ! global grid extent for tripole grids
130 :
131 : type (ice_halo) :: &
132 : halo ! a new halo type with info for halo updates
133 :
134 : !-----------------------------------------------------------------------
135 : !
136 : ! local variables
137 : !
138 : !-----------------------------------------------------------------------
139 :
140 : integer (int_kind) :: &
141 : istat, &! allocate status flag ! LCOV_EXCL_LINE
142 : numProcs, &! num of processors involved ! LCOV_EXCL_LINE
143 : communicator, &! communicator for message passing ! LCOV_EXCL_LINE
144 : iblock, &! block counter ! LCOV_EXCL_LINE
145 : eastBlock, westBlock, &! block id east, west neighbors ! LCOV_EXCL_LINE
146 : northBlock, southBlock, &! block id north, south neighbors ! LCOV_EXCL_LINE
147 : neBlock, nwBlock, &! block id northeast, northwest nbrs ! LCOV_EXCL_LINE
148 : seBlock, swBlock, &! block id southeast, southwest nbrs ! LCOV_EXCL_LINE
149 : srcProc, dstProc, &! source, dest processor locations ! LCOV_EXCL_LINE
150 : srcLocalID, dstLocalID, &! local block index of src,dst blocks ! LCOV_EXCL_LINE
151 : blockSizeX, &! size of default physical domain in X ! LCOV_EXCL_LINE
152 : blockSizeY, &! size of default physical domain in Y ! LCOV_EXCL_LINE
153 : eastMsgSize, westMsgSize, &! nominal sizes for e-w msgs ! LCOV_EXCL_LINE
154 : northMsgSize, southMsgSize, &! nominal sizes for n-s msgs ! LCOV_EXCL_LINE
155 : tripoleRows, &! number of rows in tripole buffer ! LCOV_EXCL_LINE
156 : cornerMsgSize, msgSize ! nominal size for corner msg
157 :
158 : integer (int_kind), dimension(:), allocatable :: &
159 1 : sendCount, recvCount ! count number of words to each proc
160 :
161 : logical (log_kind) :: &
162 : tripoleBlock, &! flag for identifying north tripole blocks ! LCOV_EXCL_LINE
163 : tripoleTFlag ! flag for processing tripole buffer as T-fold
164 :
165 : character(len=*), parameter :: subname = '(ice_HaloCreate)'
166 :
167 : !-----------------------------------------------------------------------
168 : !
169 : ! Initialize some useful variables and return if this task not
170 : ! in the current distribution.
171 : !
172 : !-----------------------------------------------------------------------
173 :
174 : call ice_distributionGet(dist, &
175 : nprocs = numProcs, & ! LCOV_EXCL_LINE
176 1 : communicator = communicator)
177 :
178 1 : if (my_task >= numProcs) return
179 :
180 1 : halo%communicator = communicator
181 :
182 1 : blockSizeX = nx_block - 2*nghost
183 1 : blockSizeY = ny_block - 2*nghost
184 1 : eastMsgSize = nghost*blockSizeY
185 1 : westMsgSize = nghost*blockSizeY
186 1 : southMsgSize = nghost*blockSizeX
187 1 : cornerMsgSize = nghost*nghost
188 1 : tripoleRows = nghost+1
189 :
190 : !*** store some block info to fill haloes properly
191 1 : call ice_distributionGet(dist, numLocalBlocks=halo%numLocalBlocks)
192 1 : if (halo%numLocalBlocks > 0) then
193 1 : allocate(halo%blockGlobalID(halo%numLocalBlocks))
194 1 : call ice_distributionGet(dist, blockGlobalID=halo%blockGlobalID)
195 : endif
196 :
197 1 : if (nsBoundaryType == 'tripole' .or. nsBoundaryType == 'tripoleT') then
198 0 : tripoleTFlag = (nsBoundaryType == 'tripoleT')
199 0 : if (tripoleTflag) tripoleRows = tripoleRows+1
200 0 : northMsgSize = tripoleRows*blockSizeX
201 :
202 : !*** allocate tripole message buffers if not already done
203 :
204 0 : if (.not. allocated(bufTripoleR8)) then
205 : allocate (bufTripoleI4(nxGlobal, tripoleRows), &
206 : bufTripoleR4(nxGlobal, tripoleRows), & ! LCOV_EXCL_LINE
207 : bufTripoleR8(nxGlobal, tripoleRows), & ! LCOV_EXCL_LINE
208 0 : stat=istat)
209 :
210 0 : if (istat > 0) then
211 0 : call abort_ice(subname//'ERROR: allocating tripole buffers')
212 0 : return
213 : endif
214 : endif
215 :
216 : else
217 1 : tripoleTFlag = .false.
218 1 : northMsgSize = nghost*blockSizeX
219 : endif
220 1 : halo%tripoleTFlag = tripoleTFlag
221 1 : halo%tripoleRows = tripoleRows
222 :
223 : !-----------------------------------------------------------------------
224 : !
225 : ! Count the number of messages to send/recv from each processor
226 : ! and number of words in each message. These quantities are
227 : ! necessary for allocating future arrays.
228 : !
229 : !-----------------------------------------------------------------------
230 :
231 1 : allocate (sendCount(numProcs), recvCount(numProcs), stat=istat)
232 :
233 1 : if (istat > 0) then
234 0 : call abort_ice(subname//'ERROR: allocating count arrays')
235 0 : return
236 : endif
237 :
238 2 : sendCount = 0
239 2 : recvCount = 0
240 :
241 2 : msgCountLoop: do iblock=1,nblocks_tot
242 :
243 : call ice_distributionGetBlockLoc(dist, iblock, srcProc, &
244 1 : srcLocalID)
245 :
246 : !*** find north neighbor block and add to message count
247 : !*** also set tripole block flag for later special cases
248 :
249 : northBlock = ice_blocksGetNbrID(iblock, ice_blocksNorth, &
250 1 : ewBoundaryType, nsBoundaryType)
251 1 : if (northBlock > 0) then
252 0 : tripoleBlock = .false.
253 : call ice_distributionGetBlockLoc(dist, northBlock, dstProc, &
254 0 : dstLocalID)
255 1 : else if (northBlock < 0) then ! tripole north row, count block
256 0 : tripoleBlock = .true.
257 : call ice_distributionGetBlockLoc(dist, abs(northBlock), &
258 0 : dstProc, dstLocalID)
259 : else
260 1 : tripoleBlock = .false.
261 1 : dstProc = 0
262 1 : dstLocalID = 0
263 : endif
264 :
265 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
266 1 : srcProc, dstProc, northMsgSize)
267 :
268 : !*** if a tripole boundary block, also create a local
269 : !*** message into and out of tripole buffer
270 :
271 1 : if (tripoleBlock) then
272 : !*** copy in
273 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
274 : srcProc, srcProc, & ! LCOV_EXCL_LINE
275 0 : northMsgSize)
276 :
277 : !*** copy out of tripole buffer - includes halo
278 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
279 : srcProc, srcProc, & ! LCOV_EXCL_LINE
280 0 : (nghost+1)*nx_block)
281 : endif
282 :
283 : !*** find south neighbor block and add to message count
284 :
285 : southBlock = ice_blocksGetNbrID(iblock, ice_blocksSouth, &
286 1 : ewBoundaryType, nsBoundaryType)
287 :
288 1 : if (southBlock > 0) then
289 : call ice_distributionGetBlockLoc(dist, southBlock, dstProc, &
290 0 : dstLocalID)
291 : else
292 1 : dstProc = 0
293 1 : dstLocalID = 0
294 : endif
295 :
296 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
297 1 : srcProc, dstProc, southMsgSize)
298 :
299 : !*** find east neighbor block and add to message count
300 :
301 : eastBlock = ice_blocksGetNbrID(iblock, ice_blocksEast, &
302 1 : ewBoundaryType, nsBoundaryType)
303 :
304 1 : if (eastBlock > 0) then
305 : call ice_distributionGetBlockLoc(dist, eastBlock, dstProc, &
306 1 : dstLocalID)
307 : else
308 0 : dstProc = 0
309 0 : dstLocalID = 0
310 : endif
311 :
312 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
313 1 : srcProc, dstProc, eastMsgSize)
314 :
315 : !*** if a tripole boundary block, non-local east neighbor
316 : !*** needs a chunk of the north boundary, so add a message
317 : !*** for that
318 :
319 : !echmod if (tripoleBlock .and. dstProc /= srcProc) then
320 : ! tcx,tcraig, 3/2023, this is not needed
321 : ! if (tripoleBlock) then
322 : ! call ice_HaloIncrementMsgCount(sendCount, recvCount, &
323 : ! srcProc, dstProc, northMsgSize)
324 : ! endif
325 :
326 : !*** find west neighbor block and add to message count
327 :
328 : westBlock = ice_blocksGetNbrID(iblock, ice_blocksWest, &
329 1 : ewBoundaryType, nsBoundaryType)
330 :
331 1 : if (westBlock > 0) then
332 : call ice_distributionGetBlockLoc(dist, westBlock, dstProc, &
333 1 : dstLocalID)
334 : else
335 0 : dstProc = 0
336 0 : dstLocalID = 0
337 : endif
338 :
339 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
340 1 : srcProc, dstProc, westMsgSize)
341 :
342 : !*** if a tripole boundary block, non-local west neighbor
343 : !*** needs a chunk of the north boundary, so add a message
344 : !*** for that
345 :
346 : !echmod if (tripoleBlock .and. dstProc /= srcProc) then
347 : ! tcx,tcraig, 3/2023, this is not needed
348 : ! if (tripoleBlock) then
349 : ! call ice_HaloIncrementMsgCount(sendCount, recvCount, &
350 : ! srcProc, dstProc, northMsgSize)
351 : ! endif
352 :
353 : !*** find northeast neighbor block and add to message count
354 :
355 : neBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthEast, &
356 1 : ewBoundaryType, nsBoundaryType)
357 :
358 1 : if (neBlock > 0) then
359 0 : msgSize = cornerMsgSize ! normal corner message
360 :
361 : call ice_distributionGetBlockLoc(dist, neBlock, dstProc, &
362 0 : dstLocalID)
363 :
364 : ! tcx,tcraig, 3/2023, this is not needed
365 : ! else if (neBlock < 0) then ! tripole north row
366 : ! msgSize = northMsgSize ! tripole needs whole top row of block
367 : !
368 : ! call ice_distributionGetBlockLoc(dist, abs(neBlock), dstProc, &
369 : ! dstLocalID)
370 : else
371 1 : dstProc = 0
372 1 : dstLocalID = 0
373 : endif
374 :
375 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
376 1 : srcProc, dstProc, msgSize)
377 :
378 : !*** find northwest neighbor block and add to message count
379 :
380 : nwBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthWest, &
381 1 : ewBoundaryType, nsBoundaryType)
382 :
383 1 : if (nwBlock > 0) then
384 0 : msgSize = cornerMsgSize ! normal NE corner update
385 :
386 : call ice_distributionGetBlockLoc(dist, nwBlock, dstProc, &
387 0 : dstLocalID)
388 :
389 : ! tcx,tcraig, 3/2023, this is not needed
390 : ! else if (nwBlock < 0) then ! tripole north row, count block
391 : ! msgSize = northMsgSize ! tripole NE corner update - entire row needed
392 : !
393 : ! call ice_distributionGetBlockLoc(dist, abs(nwBlock), dstProc, &
394 : ! dstLocalID)
395 :
396 : else
397 1 : dstProc = 0
398 1 : dstLocalID = 0
399 : endif
400 :
401 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
402 1 : srcProc, dstProc, msgSize)
403 :
404 : !*** find southeast neighbor block and add to message count
405 :
406 : seBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthEast, &
407 1 : ewBoundaryType, nsBoundaryType)
408 :
409 1 : if (seBlock > 0) then
410 : call ice_distributionGetBlockLoc(dist, seBlock, dstProc, &
411 0 : dstLocalID)
412 : else
413 1 : dstProc = 0
414 1 : dstLocalID = 0
415 : endif
416 :
417 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
418 1 : srcProc, dstProc, cornerMsgSize)
419 :
420 : !*** find southwest neighbor block and add to message count
421 :
422 : swBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthWest, &
423 1 : ewBoundaryType, nsBoundaryType)
424 :
425 1 : if (swBlock > 0) then
426 : call ice_distributionGetBlockLoc(dist, swBlock, dstProc, &
427 0 : dstLocalID)
428 : else
429 1 : dstProc = 0
430 1 : dstLocalID = 0
431 : endif
432 :
433 : call ice_HaloIncrementMsgCount(sendCount, recvCount, &
434 3 : srcProc, dstProc, cornerMsgSize)
435 :
436 : end do msgCountLoop
437 :
438 : !-----------------------------------------------------------------------
439 : !
440 : ! if messages are received from the same processor, the message is
441 : ! actually a local copy - count them and reset to zero
442 : !
443 : !-----------------------------------------------------------------------
444 :
445 1 : halo%numLocalCopies = recvCount(my_task+1)
446 :
447 1 : sendCount(my_task+1) = 0
448 1 : recvCount(my_task+1) = 0
449 :
450 : !-----------------------------------------------------------------------
451 : !
452 : ! allocate arrays for message information and initialize
453 : !
454 : !-----------------------------------------------------------------------
455 :
456 : allocate(halo%srcLocalAddr(3,halo%numLocalCopies), &
457 : halo%dstLocalAddr(3,halo%numLocalCopies), & ! LCOV_EXCL_LINE
458 1 : stat = istat)
459 :
460 1 : if (istat > 0) then
461 0 : call abort_ice(subname//'ERROR: allocating halo message info arrays')
462 0 : return
463 : endif
464 :
465 929 : halo%srcLocalAddr = 0
466 929 : halo%dstLocalAddr = 0
467 :
468 1 : deallocate(sendCount, recvCount, stat=istat)
469 :
470 1 : if (istat > 0) then
471 0 : call abort_ice(subname//'ERROR: deallocating count arrays')
472 0 : return
473 : endif
474 :
475 : !-----------------------------------------------------------------------
476 : !
477 : ! repeat loop through blocks but this time, determine all the
478 : ! required message information for each message or local copy
479 : !
480 : !-----------------------------------------------------------------------
481 :
482 : !*** reset halo scalars to use as counters
483 :
484 1 : halo%numLocalCopies = 0
485 :
486 2 : msgConfigLoop: do iblock=1,nblocks_tot
487 :
488 : call ice_distributionGetBlockLoc(dist, iblock, srcProc, &
489 1 : srcLocalID)
490 :
491 : !*** find north neighbor block
492 :
493 : northBlock = ice_blocksGetNbrID(iblock, ice_blocksNorth, &
494 1 : ewBoundaryType, nsBoundaryType)
495 :
496 : !*** set tripole flag and add two copies for inserting
497 : !*** and extracting info from the tripole buffer
498 :
499 1 : if (northBlock < 0) then
500 0 : tripoleBlock = .true.
501 0 : call ice_HaloMsgCreate(halo, dist, iblock, -iblock, 'north')
502 0 : call ice_HaloMsgCreate(halo, dist, -iblock, iblock, 'north')
503 : else
504 1 : tripoleBlock = .false.
505 1 : call ice_HaloMsgCreate(halo, dist, iblock, northBlock, 'north')
506 : endif
507 :
508 : !*** find south neighbor block
509 :
510 : southBlock = ice_blocksGetNbrID(iblock, ice_blocksSouth, &
511 1 : ewBoundaryType, nsBoundaryType)
512 :
513 1 : call ice_HaloMsgCreate(halo, dist, iblock, southBlock, 'south')
514 :
515 : !*** find east neighbor block
516 :
517 : eastBlock = ice_blocksGetNbrID(iblock, ice_blocksEast, &
518 1 : ewBoundaryType, nsBoundaryType)
519 :
520 1 : call ice_HaloMsgCreate(halo, dist, iblock, eastBlock, 'east')
521 :
522 : !*** for tripole grids, send a north tripole message to
523 : !*** the east block to make sure enough information is
524 : !*** available for tripole manipulations
525 :
526 : ! tcx,tcraig, 3/2023, this is not needed
527 : ! if (tripoleBlock) then
528 : ! call ice_HaloMsgCreate(halo, dist, iblock, -eastBlock, 'north')
529 : ! endif
530 :
531 : !*** find west neighbor block
532 :
533 : westBlock = ice_blocksGetNbrID(iblock, ice_blocksWest, &
534 1 : ewBoundaryType, nsBoundaryType)
535 :
536 1 : call ice_HaloMsgCreate(halo, dist, iblock, westBlock, 'west')
537 :
538 : !*** for tripole grids, send a north tripole message to
539 : !*** the west block to make sure enough information is
540 : !*** available for tripole manipulations
541 :
542 : ! tcx,tcraig, 3/2023, this is not needed
543 : ! if (tripoleBlock) then
544 : ! call ice_HaloMsgCreate(halo, dist, iblock, -westBlock, 'north')
545 : ! endif
546 :
547 : !*** find northeast neighbor block
548 :
549 : neBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthEast, &
550 1 : ewBoundaryType, nsBoundaryType)
551 :
552 1 : call ice_HaloMsgCreate(halo, dist, iblock, neBlock, 'northeast')
553 :
554 : !*** find northwest neighbor block
555 :
556 : nwBlock = ice_blocksGetNbrID(iblock, ice_blocksNorthWest, &
557 1 : ewBoundaryType, nsBoundaryType)
558 :
559 1 : call ice_HaloMsgCreate(halo, dist, iblock, nwBlock, 'northwest')
560 :
561 : !*** find southeast neighbor block
562 :
563 : seBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthEast, &
564 1 : ewBoundaryType, nsBoundaryType)
565 :
566 1 : call ice_HaloMsgCreate(halo, dist, iblock, seBlock, 'southeast')
567 :
568 : !*** find southwest neighbor block
569 :
570 : swBlock = ice_blocksGetNbrID(iblock, ice_blocksSouthWest, &
571 1 : ewBoundaryType, nsBoundaryType)
572 :
573 3 : call ice_HaloMsgCreate(halo, dist, iblock, swBlock, 'southwest')
574 :
575 : end do msgConfigLoop
576 :
577 : !-----------------------------------------------------------------------
578 :
579 2 : end function ice_HaloCreate
580 :
581 : !***********************************************************************
582 :
583 0 : subroutine ice_HaloMask(halo, basehalo, mask)
584 :
585 : ! This routine creates a halo type with info necessary for
586 : ! performing a halo (ghost cell) update. This info is computed
587 : ! based on a base halo already initialized and a mask
588 :
589 : use ice_domain_size, only: max_blocks
590 :
591 : type (ice_halo) :: &
592 : basehalo ! basehalo to mask
593 : integer (int_kind), intent(in) :: &
594 : mask(nx_block,ny_block,max_blocks) ! mask of live points
595 :
596 : type (ice_halo) :: &
597 : halo ! a new halo type with info for halo updates
598 :
599 : !-----------------------------------------------------------------------
600 : !
601 : ! local variables
602 : !
603 : !-----------------------------------------------------------------------
604 :
605 : integer (int_kind) :: &
606 : istat, &! allocate status flag ! LCOV_EXCL_LINE
607 : communicator, &! communicator for message passing ! LCOV_EXCL_LINE
608 : numLocalCopies, &! num local copies for halo update ! LCOV_EXCL_LINE
609 : numLocalBlocks, &! num local blocks for halo fill ! LCOV_EXCL_LINE
610 : tripoleRows ! number of rows in tripole buffer
611 :
612 : logical (log_kind) :: &
613 : tripoleTFlag ! flag for processing tripole buffer as T-fold
614 :
615 : character(len=*), parameter :: subname = '(ice_HaloMask)'
616 :
617 : !-----------------------------------------------------------------------
618 : !
619 : ! allocate and initialize halo
620 : ! halos are not masked for local copies
621 : !
622 : !-----------------------------------------------------------------------
623 :
624 0 : communicator = basehalo%communicator
625 0 : tripoleRows = basehalo%tripoleRows
626 0 : tripoleTFlag = basehalo%tripoleTFlag
627 0 : numLocalCopies = basehalo%numLocalCopies
628 0 : numLocalBlocks = basehalo%numLocalBlocks
629 :
630 : allocate(halo%srcLocalAddr(3,numLocalCopies), &
631 : halo%dstLocalAddr(3,numLocalCopies), & ! LCOV_EXCL_LINE
632 : halo%blockGlobalID(numLocalBlocks), & ! LCOV_EXCL_LINE
633 0 : stat = istat)
634 :
635 0 : if (istat > 0) then
636 0 : call abort_ice(subname//'ERROR: allocating halo message info arrays')
637 0 : return
638 : endif
639 :
640 0 : halo%communicator = communicator
641 0 : halo%tripoleRows = tripoleRows
642 0 : halo%tripoleTFlag = tripoleTFlag
643 0 : halo%numLocalCopies = numLocalCopies
644 0 : halo%numLocalBlocks = numLocalBlocks
645 :
646 0 : halo%srcLocalAddr = basehalo%srcLocalAddr
647 0 : halo%dstLocalAddr = basehalo%dstLocalAddr
648 :
649 0 : halo%blockGlobalID = basehalo%blockGlobalID
650 :
651 : !-----------------------------------------------------------------------
652 :
653 : end subroutine ice_HaloMask
654 :
655 : !***********************************************************************
656 :
657 11832 : subroutine ice_HaloUpdate2DR8(array, halo, &
658 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
659 : fillValue, tripoleOnly)
660 :
661 : ! This routine updates ghost cells for an input array and is a
662 : ! member of a group of routines under the generic interface
663 : ! POP\_HaloUpdate. This routine is the specific interface
664 : ! for 2d horizontal arrays of double precision.
665 :
666 : type (ice_halo), intent(in) :: &
667 : halo ! precomputed halo structure containing all
668 : ! information needed for halo update
669 :
670 : integer (int_kind), intent(in) :: &
671 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
672 : fieldLoc ! id for location on horizontal grid
673 : ! (center, NEcorner, Nface, Eface)
674 :
675 : real (dbl_kind), intent(in), optional :: &
676 : fillValue ! optional value to put in ghost cells
677 : ! where neighbor points are unknown
678 : ! (e.g. eliminated land blocks or
679 : ! closed boundaries)
680 :
681 : logical (log_kind), intent(in), optional :: &
682 : tripoleOnly ! optional flag to execute halo only across tripole seam
683 :
684 : real (dbl_kind), dimension(:,:,:), intent(inout) :: &
685 : array ! array containing field for which halo
686 : ! needs to be updated
687 :
688 : !-----------------------------------------------------------------------
689 : !
690 : ! local variables
691 : !
692 : !-----------------------------------------------------------------------
693 :
694 : integer (int_kind) :: &
695 : i,j,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
696 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
697 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
698 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
699 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
700 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
701 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
702 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
703 : isign ! sign factor for tripole grids
704 :
705 : real (dbl_kind) :: &
706 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
707 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
708 :
709 : logical (log_kind) :: &
710 : ltripoleOnly ! local tripoleOnly value
711 :
712 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DR8)'
713 :
714 : !-----------------------------------------------------------------------
715 : !
716 : ! abort or return on unknown or noupdate field_loc or field_type
717 : !
718 : !-----------------------------------------------------------------------
719 :
720 11832 : if (fieldLoc == field_loc_unknown .or. &
721 : fieldKind == field_type_unknown) then
722 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
723 0 : return
724 : endif
725 :
726 11832 : if (fieldLoc == field_loc_noupdate .or. &
727 : fieldKind == field_type_noupdate) then
728 0 : return
729 : endif
730 :
731 : !-----------------------------------------------------------------------
732 : !
733 : ! initialize error code and fill value
734 : !
735 : !-----------------------------------------------------------------------
736 :
737 11832 : if (present(fillValue)) then
738 17 : fill = fillValue
739 : else
740 11815 : fill = 0.0_dbl_kind
741 : endif
742 :
743 11832 : if (present(tripoleOnly)) then
744 8 : ltripoleOnly = tripoleOnly
745 : else
746 11824 : ltripoleOnly = .false.
747 : endif
748 :
749 11832 : nxGlobal = 0
750 11832 : if (allocated(bufTripoleR8)) then
751 0 : nxGlobal = size(bufTripoleR8,dim=1)
752 0 : bufTripoleR8 = fill
753 : endif
754 :
755 : !-----------------------------------------------------------------------
756 : !
757 : ! fill out halo region
758 : ! needed for masked halos to ensure halo values are filled for
759 : ! halo grid cells that are not updated
760 : !
761 : !-----------------------------------------------------------------------
762 :
763 11832 : if (ltripoleOnly) then
764 : ! skip fill, not needed since tripole seam always exists if running
765 : ! on tripole grid and set tripoleOnly flag
766 : else
767 23648 : do iblk = 1, halo%numLocalBlocks
768 : call get_block_parameter(halo%blockGlobalID(iblk), &
769 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
770 11824 : jlo=jlo, jhi=jhi)
771 23648 : do j = 1,nghost
772 1217872 : array(1:nx_block, jlo-j,iblk) = fill
773 1229696 : array(1:nx_block, jhi+j,iblk) = fill
774 : enddo
775 47296 : do i = 1,nghost
776 1407056 : array(ilo-i, 1:ny_block,iblk) = fill
777 1418880 : array(ihi+i, 1:ny_block,iblk) = fill
778 : enddo
779 : enddo
780 : endif
781 :
782 : !-----------------------------------------------------------------------
783 : !
784 : ! do local copies while waiting for messages to complete
785 : ! if srcBlock is zero, that denotes an eliminated land block or a
786 : ! closed boundary where ghost cell values are undefined
787 : ! if srcBlock is less than zero, the message is a copy out of the
788 : ! tripole buffer and will be treated later
789 : !
790 : !-----------------------------------------------------------------------
791 :
792 2756856 : do nmsg=1,halo%numLocalCopies
793 2745024 : iSrc = halo%srcLocalAddr(1,nmsg)
794 2745024 : jSrc = halo%srcLocalAddr(2,nmsg)
795 2745024 : srcBlock = halo%srcLocalAddr(3,nmsg)
796 2745024 : iDst = halo%dstLocalAddr(1,nmsg)
797 2745024 : jDst = halo%dstLocalAddr(2,nmsg)
798 2745024 : dstBlock = halo%dstLocalAddr(3,nmsg)
799 :
800 2756856 : if (ltripoleOnly) then
801 1856 : if (srcBlock > 0) then
802 1856 : if (dstBlock < 0) then ! tripole copy into buffer
803 : bufTripoleR8(iDst,jDst) = &
804 0 : array(iSrc,jSrc,srcBlock)
805 : endif
806 : endif
807 : else
808 2743168 : if (srcBlock > 0) then
809 2743168 : if (dstBlock > 0) then
810 : array(iDst,jDst,dstBlock) = &
811 2743168 : array(iSrc,jSrc,srcBlock)
812 0 : else if (dstBlock < 0) then ! tripole copy into buffer
813 : bufTripoleR8(iDst,jDst) = &
814 0 : array(iSrc,jSrc,srcBlock)
815 : endif
816 0 : else if (srcBlock == 0) then
817 0 : array(iDst,jDst,dstBlock) = fill
818 : endif
819 : endif
820 : end do
821 :
822 : !-----------------------------------------------------------------------
823 : !
824 : ! take care of northern boundary in tripole case
825 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
826 : ! (T-fold) of physical domain for entire (global) top row
827 : !
828 : !-----------------------------------------------------------------------
829 :
830 11832 : if (nxGlobal > 0) then
831 :
832 0 : select case (fieldKind)
833 : case (field_type_scalar)
834 0 : isign = 1
835 : case (field_type_vector)
836 0 : isign = -1
837 : case (field_type_angle)
838 0 : isign = -1
839 : case default
840 0 : call abort_ice(subname//'ERROR: Unknown field kind')
841 : end select
842 :
843 0 : if (halo%tripoleTFlag) then
844 :
845 0 : select case (fieldLoc)
846 : case (field_loc_center) ! cell center location
847 :
848 0 : ioffset = -1
849 0 : joffset = 0
850 :
851 : !*** top row is degenerate, so must enforce symmetry
852 : !*** use average of two degenerate points for value
853 :
854 0 : do i = 2,nxGlobal/2
855 0 : iDst = nxGlobal - i + 2
856 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
857 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
858 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
859 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
860 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
861 : end do
862 :
863 : case (field_loc_NEcorner) ! cell corner location
864 :
865 0 : ioffset = 0
866 0 : joffset = 1
867 :
868 : case (field_loc_Eface) ! cell center location
869 :
870 0 : ioffset = 0
871 0 : joffset = 0
872 :
873 : !*** top row is degenerate, so must enforce symmetry
874 : !*** use average of two degenerate points for value
875 :
876 0 : do i = 1,nxGlobal/2
877 0 : iDst = nxGlobal + 1 - i
878 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
879 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
880 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
881 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
882 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
883 : end do
884 :
885 : case (field_loc_Nface) ! cell corner (velocity) location
886 :
887 0 : ioffset = -1
888 0 : joffset = 1
889 :
890 : case default
891 0 : call abort_ice(subname//'ERROR: Unknown field location')
892 : end select
893 :
894 : else ! tripole u-fold
895 :
896 0 : select case (fieldLoc)
897 : case (field_loc_center) ! cell center location
898 :
899 0 : ioffset = 0
900 0 : joffset = 0
901 :
902 : case (field_loc_NEcorner) ! cell corner location
903 :
904 0 : ioffset = 1
905 0 : joffset = 1
906 :
907 : !*** top row is degenerate, so must enforce symmetry
908 : !*** use average of two degenerate points for value
909 :
910 0 : do i = 1,nxGlobal/2 - 1
911 0 : iDst = nxGlobal - i
912 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
913 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
914 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
915 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
916 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
917 : end do
918 :
919 : case (field_loc_Eface) ! cell center location
920 :
921 0 : ioffset = 1
922 0 : joffset = 0
923 :
924 : case (field_loc_Nface) ! cell corner (velocity) location
925 :
926 0 : ioffset = 0
927 0 : joffset = 1
928 :
929 : !*** top row is degenerate, so must enforce symmetry
930 : !*** use average of two degenerate points for value
931 :
932 0 : do i = 1,nxGlobal/2
933 0 : iDst = nxGlobal + 1 - i
934 0 : x1 = bufTripoleR8(i ,halo%tripoleRows)
935 0 : x2 = bufTripoleR8(iDst,halo%tripoleRows)
936 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
937 0 : bufTripoleR8(i ,halo%tripoleRows) = xavg
938 0 : bufTripoleR8(iDst,halo%tripoleRows) = isign*xavg
939 : end do
940 :
941 : case default
942 0 : call abort_ice(subname//'ERROR: Unknown field location')
943 : end select
944 :
945 : endif
946 :
947 : !*** copy out of global tripole buffer into local
948 : !*** ghost cells
949 :
950 : !*** look through local copies to find the copy out
951 : !*** messages (srcBlock < 0)
952 :
953 0 : do nmsg=1,halo%numLocalCopies
954 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
955 :
956 0 : if (srcBlock < 0) then
957 :
958 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
959 0 : jSrc = halo%srcLocalAddr(2,nmsg)
960 :
961 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
962 0 : jDst = halo%dstLocalAddr(2,nmsg)
963 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
964 :
965 : !*** correct for offsets
966 0 : iSrc = iSrc - ioffset
967 0 : jSrc = jSrc - joffset
968 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
969 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
970 :
971 : !*** for center and Eface on u-fold, and NE corner and Nface
972 : !*** on T-fold, do not need to replace
973 : !*** top row of physical domain, so jSrc should be
974 : !*** out of range and skipped
975 : !*** otherwise do the copy
976 :
977 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
978 0 : array(iDst,jDst,dstBlock) = isign*bufTripoleR8(iSrc,jSrc)
979 : endif
980 :
981 : endif
982 : end do
983 :
984 : endif
985 :
986 : !-----------------------------------------------------------------------
987 :
988 : end subroutine ice_HaloUpdate2DR8
989 :
990 : !***********************************************************************
991 :
992 0 : subroutine ice_HaloUpdate2DR4(array, halo, &
993 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
994 : fillValue)
995 :
996 : ! This routine updates ghost cells for an input array and is a
997 : ! member of a group of routines under the generic interface
998 : ! POP\_HaloUpdate. This routine is the specific interface
999 : ! for 2d horizontal arrays of single precision.
1000 :
1001 : type (ice_halo), intent(in) :: &
1002 : halo ! precomputed halo structure containing all
1003 : ! information needed for halo update
1004 :
1005 : integer (int_kind), intent(in) :: &
1006 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
1007 : fieldLoc ! id for location on horizontal grid
1008 : ! (center, NEcorner, Nface, Eface)
1009 :
1010 : real (real_kind), intent(in), optional :: &
1011 : fillValue ! optional value to put in ghost cells
1012 : ! where neighbor points are unknown
1013 : ! (e.g. eliminated land blocks or
1014 : ! closed boundaries)
1015 :
1016 : real (real_kind), dimension(:,:,:), intent(inout) :: &
1017 : array ! array containing field for which halo
1018 : ! needs to be updated
1019 :
1020 : !-----------------------------------------------------------------------
1021 : !
1022 : ! local variables
1023 : !
1024 : !-----------------------------------------------------------------------
1025 :
1026 : integer (int_kind) :: &
1027 : i,j,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
1028 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
1029 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
1030 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
1031 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
1032 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
1033 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
1034 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
1035 : isign ! sign factor for tripole grids
1036 :
1037 : real (real_kind) :: &
1038 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
1039 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
1040 :
1041 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DR4)'
1042 :
1043 : !-----------------------------------------------------------------------
1044 : !
1045 : ! abort or return on unknown or noupdate field_loc or field_type
1046 : !
1047 : !-----------------------------------------------------------------------
1048 :
1049 0 : if (fieldLoc == field_loc_unknown .or. &
1050 : fieldKind == field_type_unknown) then
1051 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
1052 0 : return
1053 : endif
1054 :
1055 0 : if (fieldLoc == field_loc_noupdate .or. &
1056 : fieldKind == field_type_noupdate) then
1057 0 : return
1058 : endif
1059 :
1060 : !-----------------------------------------------------------------------
1061 : !
1062 : ! initialize error code and fill value
1063 : !
1064 : !-----------------------------------------------------------------------
1065 :
1066 0 : if (present(fillValue)) then
1067 0 : fill = fillValue
1068 : else
1069 0 : fill = 0.0_real_kind
1070 : endif
1071 :
1072 0 : nxGlobal = 0
1073 0 : if (allocated(bufTripoleR4)) then
1074 0 : nxGlobal = size(bufTripoleR4,dim=1)
1075 0 : bufTripoleR4 = fill
1076 : endif
1077 :
1078 : !-----------------------------------------------------------------------
1079 : !
1080 : ! fill out halo region
1081 : ! needed for masked halos to ensure halo values are filled for
1082 : ! halo grid cells that are not updated
1083 : !
1084 : !-----------------------------------------------------------------------
1085 :
1086 0 : do iblk = 1, halo%numLocalBlocks
1087 : call get_block_parameter(halo%blockGlobalID(iblk), &
1088 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
1089 0 : jlo=jlo, jhi=jhi)
1090 0 : do j = 1,nghost
1091 0 : array(1:nx_block, jlo-j,iblk) = fill
1092 0 : array(1:nx_block, jhi+j,iblk) = fill
1093 : enddo
1094 0 : do i = 1,nghost
1095 0 : array(ilo-i, 1:ny_block,iblk) = fill
1096 0 : array(ihi+i, 1:ny_block,iblk) = fill
1097 : enddo
1098 : enddo
1099 :
1100 : !-----------------------------------------------------------------------
1101 : !
1102 : ! do local copies while waiting for messages to complete
1103 : ! if srcBlock is zero, that denotes an eliminated land block or a
1104 : ! closed boundary where ghost cell values are undefined
1105 : ! if srcBlock is less than zero, the message is a copy out of the
1106 : ! tripole buffer and will be treated later
1107 : !
1108 : !-----------------------------------------------------------------------
1109 :
1110 0 : do nmsg=1,halo%numLocalCopies
1111 0 : iSrc = halo%srcLocalAddr(1,nmsg)
1112 0 : jSrc = halo%srcLocalAddr(2,nmsg)
1113 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
1114 0 : iDst = halo%dstLocalAddr(1,nmsg)
1115 0 : jDst = halo%dstLocalAddr(2,nmsg)
1116 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
1117 :
1118 0 : if (srcBlock > 0) then
1119 0 : if (dstBlock > 0) then
1120 : array(iDst,jDst,dstBlock) = &
1121 0 : array(iSrc,jSrc,srcBlock)
1122 0 : else if (dstBlock < 0) then ! tripole copy into buffer
1123 : bufTripoleR4(iDst,jDst) = &
1124 0 : array(iSrc,jSrc,srcBlock)
1125 : endif
1126 0 : else if (srcBlock == 0) then
1127 0 : array(iDst,jDst,dstBlock) = fill
1128 : endif
1129 : end do
1130 :
1131 : !-----------------------------------------------------------------------
1132 : !
1133 : ! take care of northern boundary in tripole case
1134 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
1135 : ! (T-fold) of physical domain for entire (global) top row
1136 : !
1137 : !-----------------------------------------------------------------------
1138 :
1139 0 : if (nxGlobal > 0) then
1140 :
1141 0 : select case (fieldKind)
1142 : case (field_type_scalar)
1143 0 : isign = 1
1144 : case (field_type_vector)
1145 0 : isign = -1
1146 : case (field_type_angle)
1147 0 : isign = -1
1148 : case default
1149 0 : call abort_ice(subname//'ERROR: Unknown field kind')
1150 : end select
1151 :
1152 0 : if (halo%tripoleTFlag) then
1153 :
1154 0 : select case (fieldLoc)
1155 : case (field_loc_center) ! cell center location
1156 :
1157 0 : ioffset = -1
1158 0 : joffset = 0
1159 :
1160 : !*** top row is degenerate, so must enforce symmetry
1161 : !*** use average of two degenerate points for value
1162 :
1163 0 : do i = 2,nxGlobal/2
1164 0 : iDst = nxGlobal - i + 2
1165 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1166 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1167 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1168 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1169 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1170 : end do
1171 :
1172 : case (field_loc_NEcorner) ! cell corner location
1173 :
1174 0 : ioffset = 0
1175 0 : joffset = 1
1176 :
1177 : case (field_loc_Eface) ! cell center location
1178 :
1179 0 : ioffset = 0
1180 0 : joffset = 0
1181 :
1182 : !*** top row is degenerate, so must enforce symmetry
1183 : !*** use average of two degenerate points for value
1184 :
1185 0 : do i = 1,nxGlobal/2
1186 0 : iDst = nxGlobal + 1 - i
1187 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1188 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1189 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1190 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1191 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1192 : end do
1193 :
1194 : case (field_loc_Nface) ! cell corner (velocity) location
1195 :
1196 0 : ioffset = -1
1197 0 : joffset = 1
1198 :
1199 : case default
1200 0 : call abort_ice(subname//'ERROR: Unknown field location')
1201 : end select
1202 :
1203 : else ! tripole u-fold
1204 :
1205 0 : select case (fieldLoc)
1206 : case (field_loc_center) ! cell center location
1207 :
1208 0 : ioffset = 0
1209 0 : joffset = 0
1210 :
1211 : case (field_loc_NEcorner) ! cell corner location
1212 :
1213 0 : ioffset = 1
1214 0 : joffset = 1
1215 :
1216 : !*** top row is degenerate, so must enforce symmetry
1217 : !*** use average of two degenerate points for value
1218 :
1219 0 : do i = 1,nxGlobal/2 - 1
1220 0 : iDst = nxGlobal - i
1221 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1222 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1223 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1224 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1225 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1226 : end do
1227 :
1228 : case (field_loc_Eface) ! cell center location
1229 :
1230 0 : ioffset = 1
1231 0 : joffset = 0
1232 :
1233 : case (field_loc_Nface) ! cell corner (velocity) location
1234 :
1235 0 : ioffset = 0
1236 0 : joffset = 1
1237 :
1238 : !*** top row is degenerate, so must enforce symmetry
1239 : !*** use average of two degenerate points for value
1240 :
1241 0 : do i = 1,nxGlobal/2
1242 0 : iDst = nxGlobal + 1 - i
1243 0 : x1 = bufTripoleR4(i ,halo%tripoleRows)
1244 0 : x2 = bufTripoleR4(iDst,halo%tripoleRows)
1245 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
1246 0 : bufTripoleR4(i ,halo%tripoleRows) = xavg
1247 0 : bufTripoleR4(iDst,halo%tripoleRows) = isign*xavg
1248 : end do
1249 :
1250 : case default
1251 0 : call abort_ice(subname//'ERROR: Unknown field location')
1252 : end select
1253 :
1254 : endif
1255 :
1256 : !*** copy out of global tripole buffer into local
1257 : !*** ghost cells
1258 :
1259 : !*** look through local copies to find the copy out
1260 : !*** messages (srcBlock < 0)
1261 :
1262 0 : do nmsg=1,halo%numLocalCopies
1263 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
1264 :
1265 0 : if (srcBlock < 0) then
1266 :
1267 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
1268 0 : jSrc = halo%srcLocalAddr(2,nmsg)
1269 :
1270 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
1271 0 : jDst = halo%dstLocalAddr(2,nmsg)
1272 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
1273 :
1274 : !*** correct for offsets
1275 0 : iSrc = iSrc - ioffset
1276 0 : jSrc = jSrc - joffset
1277 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
1278 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
1279 :
1280 : !*** for center and Eface on u-fold, and NE corner and Nface
1281 : !*** on T-fold, do not need to replace
1282 : !*** top row of physical domain, so jSrc should be
1283 : !*** out of range and skipped
1284 : !*** otherwise do the copy
1285 :
1286 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
1287 0 : array(iDst,jDst,dstBlock) = isign*bufTripoleR4(iSrc,jSrc)
1288 : endif
1289 :
1290 : endif
1291 : end do
1292 :
1293 : endif
1294 :
1295 : !-----------------------------------------------------------------------
1296 :
1297 : end subroutine ice_HaloUpdate2DR4
1298 :
1299 : !***********************************************************************
1300 :
1301 24 : subroutine ice_HaloUpdate2DI4(array, halo, &
1302 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
1303 : fillValue)
1304 :
1305 : ! This routine updates ghost cells for an input array and is a
1306 : ! member of a group of routines under the generic interface
1307 : ! POP\_HaloUpdate. This routine is the specific interface
1308 : ! for 2d horizontal integer arrays.
1309 :
1310 : type (ice_halo), intent(in) :: &
1311 : halo ! precomputed halo structure containing all
1312 : ! information needed for halo update
1313 :
1314 : integer (int_kind), intent(in) :: &
1315 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
1316 : fieldLoc ! id for location on horizontal grid
1317 : ! (center, NEcorner, Nface, Eface)
1318 :
1319 : integer (int_kind), intent(in), optional :: &
1320 : fillValue ! optional value to put in ghost cells
1321 : ! where neighbor points are unknown
1322 : ! (e.g. eliminated land blocks or
1323 : ! closed boundaries)
1324 :
1325 : integer (int_kind), dimension(:,:,:), intent(inout) :: &
1326 : array ! array containing field for which halo
1327 : ! needs to be updated
1328 :
1329 : !-----------------------------------------------------------------------
1330 : !
1331 : ! local variables
1332 : !
1333 : !-----------------------------------------------------------------------
1334 :
1335 : integer (int_kind) :: &
1336 : i,j,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
1337 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
1338 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
1339 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
1340 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
1341 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
1342 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
1343 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
1344 : isign ! sign factor for tripole grids
1345 :
1346 : integer (int_kind) :: &
1347 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
1348 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
1349 :
1350 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DI4)'
1351 :
1352 : !-----------------------------------------------------------------------
1353 : !
1354 : ! abort or return on unknown or noupdate field_loc or field_type
1355 : !
1356 : !-----------------------------------------------------------------------
1357 :
1358 24 : if (fieldLoc == field_loc_unknown .or. &
1359 : fieldKind == field_type_unknown) then
1360 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
1361 0 : return
1362 : endif
1363 :
1364 24 : if (fieldLoc == field_loc_noupdate .or. &
1365 : fieldKind == field_type_noupdate) then
1366 0 : return
1367 : endif
1368 :
1369 : !-----------------------------------------------------------------------
1370 : !
1371 : ! initialize error code and fill value
1372 : !
1373 : !-----------------------------------------------------------------------
1374 :
1375 24 : if (present(fillValue)) then
1376 0 : fill = fillValue
1377 : else
1378 24 : fill = 0_int_kind
1379 : endif
1380 :
1381 24 : nxGlobal = 0
1382 24 : if (allocated(bufTripoleI4)) then
1383 0 : nxGlobal = size(bufTripoleI4,dim=1)
1384 0 : bufTripoleI4 = fill
1385 : endif
1386 :
1387 : !-----------------------------------------------------------------------
1388 : !
1389 : ! fill out halo region
1390 : ! needed for masked halos to ensure halo values are filled for
1391 : ! halo grid cells that are not updated
1392 : !
1393 : !-----------------------------------------------------------------------
1394 :
1395 48 : do iblk = 1, halo%numLocalBlocks
1396 : call get_block_parameter(halo%blockGlobalID(iblk), &
1397 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
1398 24 : jlo=jlo, jhi=jhi)
1399 48 : do j = 1,nghost
1400 2472 : array(1:nx_block, jlo-j,iblk) = fill
1401 2496 : array(1:nx_block, jhi+j,iblk) = fill
1402 : enddo
1403 96 : do i = 1,nghost
1404 2856 : array(ilo-i, 1:ny_block,iblk) = fill
1405 2880 : array(ihi+i, 1:ny_block,iblk) = fill
1406 : enddo
1407 : enddo
1408 :
1409 : !-----------------------------------------------------------------------
1410 : !
1411 : ! do local copies while waiting for messages to complete
1412 : ! if srcBlock is zero, that denotes an eliminated land block or a
1413 : ! closed boundary where ghost cell values are undefined
1414 : ! if srcBlock is less than zero, the message is a copy out of the
1415 : ! tripole buffer and will be treated later
1416 : !
1417 : !-----------------------------------------------------------------------
1418 :
1419 5592 : do nmsg=1,halo%numLocalCopies
1420 5568 : iSrc = halo%srcLocalAddr(1,nmsg)
1421 5568 : jSrc = halo%srcLocalAddr(2,nmsg)
1422 5568 : srcBlock = halo%srcLocalAddr(3,nmsg)
1423 5568 : iDst = halo%dstLocalAddr(1,nmsg)
1424 5568 : jDst = halo%dstLocalAddr(2,nmsg)
1425 5568 : dstBlock = halo%dstLocalAddr(3,nmsg)
1426 :
1427 5592 : if (srcBlock > 0) then
1428 5568 : if (dstBlock > 0) then
1429 : array(iDst,jDst,dstBlock) = &
1430 5568 : array(iSrc,jSrc,srcBlock)
1431 0 : else if (dstBlock < 0) then ! tripole copy into buffer
1432 : bufTripoleI4(iDst,jDst) = &
1433 0 : array(iSrc,jSrc,srcBlock)
1434 : endif
1435 0 : else if (srcBlock == 0) then
1436 0 : array(iDst,jDst,dstBlock) = fill
1437 : endif
1438 : end do
1439 :
1440 : !-----------------------------------------------------------------------
1441 : !
1442 : ! take care of northern boundary in tripole case
1443 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
1444 : ! (T-fold) of physical domain for entire (global) top row
1445 : !
1446 : !-----------------------------------------------------------------------
1447 :
1448 24 : if (nxGlobal > 0) then
1449 :
1450 0 : select case (fieldKind)
1451 : case (field_type_scalar)
1452 0 : isign = 1
1453 : case (field_type_vector)
1454 0 : isign = -1
1455 : case (field_type_angle)
1456 0 : isign = -1
1457 : case default
1458 0 : call abort_ice(subname//'ERROR: Unknown field kind')
1459 : end select
1460 :
1461 0 : if (halo%tripoleTFlag) then
1462 :
1463 0 : select case (fieldLoc)
1464 : case (field_loc_center) ! cell center location
1465 :
1466 0 : ioffset = -1
1467 0 : joffset = 0
1468 :
1469 : !*** top row is degenerate, so must enforce symmetry
1470 : !*** use average of two degenerate points for value
1471 :
1472 0 : do i = 2,nxGlobal/2
1473 0 : iDst = nxGlobal - i + 2
1474 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
1475 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
1476 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
1477 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
1478 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
1479 : end do
1480 :
1481 : case (field_loc_NEcorner) ! cell corner location
1482 :
1483 0 : ioffset = 0
1484 0 : joffset = 1
1485 :
1486 : case (field_loc_Eface) ! cell center location
1487 :
1488 0 : ioffset = 0
1489 0 : joffset = 0
1490 :
1491 : !*** top row is degenerate, so must enforce symmetry
1492 : !*** use average of two degenerate points for value
1493 :
1494 0 : do i = 1,nxGlobal/2
1495 0 : iDst = nxGlobal + 1 - i
1496 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
1497 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
1498 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
1499 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
1500 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
1501 : end do
1502 :
1503 : case (field_loc_Nface) ! cell corner (velocity) location
1504 :
1505 0 : ioffset = -1
1506 0 : joffset = 1
1507 :
1508 : case default
1509 0 : call abort_ice(subname//'ERROR: Unknown field location')
1510 : end select
1511 :
1512 : else ! tripole u-fold
1513 :
1514 0 : select case (fieldLoc)
1515 : case (field_loc_center) ! cell center location
1516 :
1517 0 : ioffset = 0
1518 0 : joffset = 0
1519 :
1520 : case (field_loc_NEcorner) ! cell corner location
1521 :
1522 0 : ioffset = 1
1523 0 : joffset = 1
1524 :
1525 : !*** top row is degenerate, so must enforce symmetry
1526 : !*** use average of two degenerate points for value
1527 :
1528 0 : do i = 1,nxGlobal/2 - 1
1529 0 : iDst = nxGlobal - i
1530 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
1531 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
1532 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
1533 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
1534 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
1535 : end do
1536 :
1537 : case (field_loc_Eface) ! cell center location
1538 :
1539 0 : ioffset = 1
1540 0 : joffset = 0
1541 :
1542 : case (field_loc_Nface) ! cell corner (velocity) location
1543 :
1544 0 : ioffset = 0
1545 0 : joffset = 1
1546 :
1547 : !*** top row is degenerate, so must enforce symmetry
1548 : !*** use average of two degenerate points for value
1549 :
1550 0 : do i = 1,nxGlobal/2
1551 0 : iDst = nxGlobal + 1 - i
1552 0 : x1 = bufTripoleI4(i ,halo%tripoleRows)
1553 0 : x2 = bufTripoleI4(iDst,halo%tripoleRows)
1554 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
1555 0 : bufTripoleI4(i ,halo%tripoleRows) = xavg
1556 0 : bufTripoleI4(iDst,halo%tripoleRows) = isign*xavg
1557 : end do
1558 :
1559 : case default
1560 0 : call abort_ice(subname//'ERROR: Unknown field location')
1561 : end select
1562 :
1563 : endif
1564 :
1565 : !*** copy out of global tripole buffer into local
1566 : !*** ghost cells
1567 :
1568 : !*** look through local copies to find the copy out
1569 : !*** messages (srcBlock < 0)
1570 :
1571 0 : do nmsg=1,halo%numLocalCopies
1572 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
1573 :
1574 0 : if (srcBlock < 0) then
1575 :
1576 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
1577 0 : jSrc = halo%srcLocalAddr(2,nmsg)
1578 :
1579 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
1580 0 : jDst = halo%dstLocalAddr(2,nmsg)
1581 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
1582 :
1583 : !*** correct for offsets
1584 0 : iSrc = iSrc - ioffset
1585 0 : jSrc = jSrc - joffset
1586 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
1587 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
1588 :
1589 : !*** for center and Eface on u-fold, and NE corner and Nface
1590 : !*** on T-fold, do not need to replace
1591 : !*** top row of physical domain, so jSrc should be
1592 : !*** out of range and skipped
1593 : !*** otherwise do the copy
1594 :
1595 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
1596 0 : array(iDst,jDst,dstBlock) = isign*bufTripoleI4(iSrc,jSrc)
1597 : endif
1598 :
1599 : endif
1600 : end do
1601 :
1602 : endif
1603 :
1604 : !-----------------------------------------------------------------------
1605 :
1606 : end subroutine ice_HaloUpdate2DI4
1607 :
1608 : !***********************************************************************
1609 :
1610 24 : subroutine ice_HaloUpdate2DL1(array, halo, &
1611 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
1612 : fillValue)
1613 :
1614 : ! This routine updates ghost cells for an input array and is a
1615 : ! member of a group of routines under the generic interface
1616 : ! ice\_HaloUpdate. This routine is the specific interface
1617 : ! for 2d horizontal logical arrays.
1618 :
1619 : type (ice_halo), intent(in) :: &
1620 : halo ! precomputed halo structure containing all
1621 : ! information needed for halo update
1622 :
1623 : integer (int_kind), intent(in) :: &
1624 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
1625 : fieldLoc ! id for location on horizontal grid
1626 : ! (center, NEcorner, Nface, Eface)
1627 :
1628 : integer (int_kind), intent(in), optional :: &
1629 : fillValue ! optional value to put in ghost cells
1630 : ! where neighbor points are unknown
1631 : ! (e.g. eliminated land blocks or
1632 : ! closed boundaries)
1633 :
1634 : logical (log_kind), dimension(:,:,:), intent(inout) :: &
1635 : array ! array containing field for which halo
1636 : ! needs to be updated
1637 :
1638 : !-----------------------------------------------------------------------
1639 : !
1640 : ! local variables
1641 : !
1642 : !-----------------------------------------------------------------------
1643 :
1644 : integer (int_kind), dimension(:,:,:), allocatable :: &
1645 24 : iarray ! integer array for logical
1646 :
1647 : character(len=*), parameter :: subname = '(ice_HaloUpdate2DL1)'
1648 :
1649 : !-----------------------------------------------------------------------
1650 : !
1651 : ! abort or return on unknown or noupdate field_loc or field_type
1652 : !
1653 : !-----------------------------------------------------------------------
1654 :
1655 24 : if (fieldLoc == field_loc_unknown .or. &
1656 : fieldKind == field_type_unknown) then
1657 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
1658 0 : return
1659 : endif
1660 :
1661 24 : if (fieldLoc == field_loc_noupdate .or. &
1662 : fieldKind == field_type_noupdate) then
1663 0 : return
1664 : endif
1665 :
1666 : !-----------------------------------------------------------------------
1667 : !
1668 : ! copy logical into integer array and call haloupdate on integer array
1669 : !
1670 : !-----------------------------------------------------------------------
1671 :
1672 24 : allocate(iarray(size(array,dim=1),size(array,dim=2),size(array,dim=3)))
1673 291744 : iarray(:,:,:) = 0
1674 291744 : where (array) iarray = 1
1675 :
1676 : call ice_HaloUpdate(iarray, halo, &
1677 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
1678 24 : fillValue)
1679 :
1680 291744 : array = .false.
1681 291744 : where (iarray /= 0) array = .true.
1682 24 : deallocate(iarray)
1683 :
1684 : !-----------------------------------------------------------------------
1685 :
1686 24 : end subroutine ice_HaloUpdate2DL1
1687 :
1688 : !***********************************************************************
1689 :
1690 363 : subroutine ice_HaloUpdate3DR8(array, halo, &
1691 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
1692 : fillValue)
1693 :
1694 : ! This routine updates ghost cells for an input array and is a
1695 : ! member of a group of routines under the generic interface
1696 : ! POP\_HaloUpdate. This routine is the specific interface
1697 : ! for 3d horizontal arrays of double precision.
1698 :
1699 : type (ice_halo), intent(in) :: &
1700 : halo ! precomputed halo structure containing all
1701 : ! information needed for halo update
1702 :
1703 : integer (int_kind), intent(in) :: &
1704 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
1705 : fieldLoc ! id for location on horizontal grid
1706 : ! (center, NEcorner, Nface, Eface)
1707 :
1708 : real (dbl_kind), intent(in), optional :: &
1709 : fillValue ! optional value to put in ghost cells
1710 : ! where neighbor points are unknown
1711 : ! (e.g. eliminated land blocks or
1712 : ! closed boundaries)
1713 :
1714 : real (dbl_kind), dimension(:,:,:,:), intent(inout) :: &
1715 : array ! array containing field for which halo
1716 : ! needs to be updated
1717 :
1718 : !-----------------------------------------------------------------------
1719 : !
1720 : ! local variables
1721 : !
1722 : !-----------------------------------------------------------------------
1723 :
1724 : integer (int_kind) :: &
1725 : i,j,k,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
1726 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
1727 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
1728 : nz, &! size of array in 3rd dimension ! LCOV_EXCL_LINE
1729 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
1730 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
1731 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
1732 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
1733 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
1734 : isign ! sign factor for tripole grids
1735 :
1736 : real (dbl_kind) :: &
1737 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
1738 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
1739 :
1740 : real (dbl_kind), dimension(:,:,:), allocatable :: &
1741 363 : bufTripole ! 3d tripole buffer
1742 :
1743 : character(len=*), parameter :: subname = '(ice_HaloUpdate3DR8)'
1744 :
1745 : !-----------------------------------------------------------------------
1746 : !
1747 : ! abort or return on unknown or noupdate field_loc or field_type
1748 : !
1749 : !-----------------------------------------------------------------------
1750 :
1751 363 : if (fieldLoc == field_loc_unknown .or. &
1752 : fieldKind == field_type_unknown) then
1753 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
1754 0 : return
1755 : endif
1756 :
1757 363 : if (fieldLoc == field_loc_noupdate .or. &
1758 : fieldKind == field_type_noupdate) then
1759 0 : return
1760 : endif
1761 :
1762 : !-----------------------------------------------------------------------
1763 : !
1764 : ! initialize error code and fill value
1765 : !
1766 : !-----------------------------------------------------------------------
1767 :
1768 363 : if (present(fillValue)) then
1769 0 : fill = fillValue
1770 : else
1771 363 : fill = 0.0_dbl_kind
1772 : endif
1773 :
1774 363 : nz = size(array, dim=3)
1775 :
1776 363 : nxGlobal = 0
1777 363 : if (allocated(bufTripoleR8)) then
1778 0 : nxGlobal = size(bufTripoleR8,dim=1)
1779 0 : allocate(bufTripole(nxGlobal,halo%tripoleRows,nz))
1780 0 : bufTripole = fill
1781 : endif
1782 :
1783 : !-----------------------------------------------------------------------
1784 : !
1785 : ! fill out halo region
1786 : ! needed for masked halos to ensure halo values are filled for
1787 : ! halo grid cells that are not updated
1788 : !
1789 : !-----------------------------------------------------------------------
1790 :
1791 726 : do iblk = 1, halo%numLocalBlocks
1792 : call get_block_parameter(halo%blockGlobalID(iblk), &
1793 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
1794 363 : jlo=jlo, jhi=jhi)
1795 726 : do j = 1,nghost
1796 179892 : array(1:nx_block, jlo-j,:,iblk) = fill
1797 180255 : array(1:nx_block, jhi+j,:,iblk) = fill
1798 : enddo
1799 1452 : do i = 1,nghost
1800 207780 : array(ilo-i, 1:ny_block,:,iblk) = fill
1801 208143 : array(ihi+i, 1:ny_block,:,iblk) = fill
1802 : enddo
1803 : enddo
1804 :
1805 : !-----------------------------------------------------------------------
1806 : !
1807 : ! do local copies
1808 : ! if srcBlock is zero, that denotes an eliminated land block or a
1809 : ! closed boundary where ghost cell values are undefined
1810 : ! if srcBlock is less than zero, the message is a copy out of the
1811 : ! tripole buffer and will be treated later
1812 : !
1813 : !-----------------------------------------------------------------------
1814 :
1815 84579 : do nmsg=1,halo%numLocalCopies
1816 84216 : iSrc = halo%srcLocalAddr(1,nmsg)
1817 84216 : jSrc = halo%srcLocalAddr(2,nmsg)
1818 84216 : srcBlock = halo%srcLocalAddr(3,nmsg)
1819 84216 : iDst = halo%dstLocalAddr(1,nmsg)
1820 84216 : jDst = halo%dstLocalAddr(2,nmsg)
1821 84216 : dstBlock = halo%dstLocalAddr(3,nmsg)
1822 :
1823 84579 : if (srcBlock > 0) then
1824 84216 : if (dstBlock > 0) then
1825 488592 : do k=1,nz
1826 : array(iDst,jDst,k,dstBlock) = &
1827 488592 : array(iSrc,jSrc,k,srcBlock)
1828 : end do
1829 0 : else if (dstBlock < 0) then ! tripole copy into buffer
1830 0 : do k=1,nz
1831 : bufTripole(iDst,jDst,k) = &
1832 0 : array(iSrc,jSrc,k,srcBlock)
1833 : end do
1834 : endif
1835 0 : else if (srcBlock == 0) then
1836 0 : do k=1,nz
1837 0 : array(iDst,jDst,k,dstBlock) = fill
1838 : end do
1839 : endif
1840 : end do
1841 :
1842 : !-----------------------------------------------------------------------
1843 : !
1844 : ! take care of northern boundary in tripole case
1845 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
1846 : ! (T-fold) of physical domain for entire (global) top row
1847 : !
1848 : !-----------------------------------------------------------------------
1849 :
1850 363 : if (nxGlobal > 0) then
1851 :
1852 0 : select case (fieldKind)
1853 : case (field_type_scalar)
1854 0 : isign = 1
1855 : case (field_type_vector)
1856 0 : isign = -1
1857 : case (field_type_angle)
1858 0 : isign = -1
1859 : case default
1860 0 : call abort_ice(subname//'ERROR: Unknown field kind')
1861 : end select
1862 :
1863 0 : if (halo%tripoleTFlag) then
1864 :
1865 0 : select case (fieldLoc)
1866 : case (field_loc_center) ! cell center location
1867 :
1868 0 : ioffset = -1
1869 0 : joffset = 0
1870 :
1871 : !*** top row is degenerate, so must enforce symmetry
1872 : !*** use average of two degenerate points for value
1873 :
1874 0 : do k=1,nz
1875 0 : do i = 2,nxGlobal/2
1876 0 : iDst = nxGlobal - i + 2
1877 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
1878 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
1879 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1880 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
1881 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
1882 : end do
1883 : end do
1884 :
1885 : case (field_loc_NEcorner) ! cell corner location
1886 :
1887 0 : ioffset = 0
1888 0 : joffset = 1
1889 :
1890 : case (field_loc_Eface) ! cell center location
1891 :
1892 0 : ioffset = 0
1893 0 : joffset = 0
1894 :
1895 : !*** top row is degenerate, so must enforce symmetry
1896 : !*** use average of two degenerate points for value
1897 :
1898 0 : do k=1,nz
1899 0 : do i = 1,nxGlobal/2
1900 0 : iDst = nxGlobal + 1 - i
1901 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
1902 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
1903 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1904 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
1905 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
1906 : end do
1907 : end do
1908 :
1909 : case (field_loc_Nface) ! cell corner (velocity) location
1910 :
1911 0 : ioffset = -1
1912 0 : joffset = 1
1913 :
1914 : case default
1915 0 : call abort_ice(subname//'ERROR: Unknown field location')
1916 : end select
1917 :
1918 : else ! tripole u-fold
1919 :
1920 0 : select case (fieldLoc)
1921 : case (field_loc_center) ! cell center location
1922 :
1923 0 : ioffset = 0
1924 0 : joffset = 0
1925 :
1926 : case (field_loc_NEcorner) ! cell corner location
1927 :
1928 0 : ioffset = 1
1929 0 : joffset = 1
1930 :
1931 : !*** top row is degenerate, so must enforce symmetry
1932 : !*** use average of two degenerate points for value
1933 :
1934 0 : do k=1,nz
1935 0 : do i = 1,nxGlobal/2 - 1
1936 0 : iDst = nxGlobal - i
1937 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
1938 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
1939 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1940 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
1941 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
1942 : end do
1943 : end do
1944 :
1945 : case (field_loc_Eface) ! cell center location
1946 :
1947 0 : ioffset = 1
1948 0 : joffset = 0
1949 :
1950 : case (field_loc_Nface) ! cell corner (velocity) location
1951 :
1952 0 : ioffset = 0
1953 0 : joffset = 1
1954 :
1955 : !*** top row is degenerate, so must enforce symmetry
1956 : !*** use average of two degenerate points for value
1957 :
1958 0 : do k=1,nz
1959 0 : do i = 1,nxGlobal/2
1960 0 : iDst = nxGlobal + 1 - i
1961 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
1962 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
1963 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
1964 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
1965 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
1966 : end do
1967 : end do
1968 :
1969 : case default
1970 0 : call abort_ice(subname//'ERROR: Unknown field location')
1971 : end select
1972 :
1973 : endif
1974 :
1975 : !*** copy out of global tripole buffer into local
1976 : !*** ghost cells
1977 :
1978 : !*** look through local copies to find the copy out
1979 : !*** messages (srcBlock < 0)
1980 :
1981 0 : do nmsg=1,halo%numLocalCopies
1982 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
1983 :
1984 0 : if (srcBlock < 0) then
1985 :
1986 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
1987 0 : jSrc = halo%srcLocalAddr(2,nmsg)
1988 :
1989 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
1990 0 : jDst = halo%dstLocalAddr(2,nmsg)
1991 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
1992 :
1993 : !*** correct for offsets
1994 0 : iSrc = iSrc - ioffset
1995 0 : jSrc = jSrc - joffset
1996 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
1997 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
1998 :
1999 : !*** for center and Eface on u-fold, and NE corner and Nface
2000 : !*** on T-fold, do not need to replace
2001 : !*** top row of physical domain, so jSrc should be
2002 : !*** out of range and skipped
2003 : !*** otherwise do the copy
2004 :
2005 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
2006 0 : do k=1,nz
2007 : array(iDst,jDst,k,dstBlock) = isign* &
2008 0 : bufTripole(iSrc,jSrc,k)
2009 : end do
2010 : endif
2011 :
2012 : endif
2013 : end do
2014 :
2015 : endif
2016 :
2017 363 : if (allocated(bufTripole)) deallocate(bufTripole)
2018 :
2019 : !-----------------------------------------------------------------------
2020 :
2021 363 : end subroutine ice_HaloUpdate3DR8
2022 :
2023 : !***********************************************************************
2024 :
2025 0 : subroutine ice_HaloUpdate3DR4(array, halo, &
2026 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2027 : fillValue)
2028 :
2029 : ! This routine updates ghost cells for an input array and is a
2030 : ! member of a group of routines under the generic interface
2031 : ! POP\_HaloUpdate. This routine is the specific interface
2032 : ! for 3d horizontal arrays of single precision.
2033 :
2034 : type (ice_halo), intent(in) :: &
2035 : halo ! precomputed halo structure containing all
2036 : ! information needed for halo update
2037 :
2038 : integer (int_kind), intent(in) :: &
2039 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
2040 : fieldLoc ! id for location on horizontal grid
2041 : ! (center, NEcorner, Nface, Eface)
2042 :
2043 : real (real_kind), intent(in), optional :: &
2044 : fillValue ! optional value to put in ghost cells
2045 : ! where neighbor points are unknown
2046 : ! (e.g. eliminated land blocks or
2047 : ! closed boundaries)
2048 :
2049 : real (real_kind), dimension(:,:,:,:), intent(inout) :: &
2050 : array ! array containing field for which halo
2051 : ! needs to be updated
2052 :
2053 : !-----------------------------------------------------------------------
2054 : !
2055 : ! local variables
2056 : !
2057 : !-----------------------------------------------------------------------
2058 :
2059 : integer (int_kind) :: &
2060 : i,j,k,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
2061 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
2062 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
2063 : nz, &! size of array in 3rd dimension ! LCOV_EXCL_LINE
2064 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
2065 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
2066 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
2067 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
2068 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
2069 : isign ! sign factor for tripole grids
2070 :
2071 : real (real_kind) :: &
2072 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
2073 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
2074 :
2075 : real (real_kind), dimension(:,:,:), allocatable :: &
2076 0 : bufTripole ! 3d tripole buffer
2077 :
2078 : character(len=*), parameter :: subname = '(ice_HaloUpdate3DR4)'
2079 :
2080 : !-----------------------------------------------------------------------
2081 : !
2082 : ! abort or return on unknown or noupdate field_loc or field_type
2083 : !
2084 : !-----------------------------------------------------------------------
2085 :
2086 0 : if (fieldLoc == field_loc_unknown .or. &
2087 : fieldKind == field_type_unknown) then
2088 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
2089 0 : return
2090 : endif
2091 :
2092 0 : if (fieldLoc == field_loc_noupdate .or. &
2093 : fieldKind == field_type_noupdate) then
2094 0 : return
2095 : endif
2096 :
2097 : !-----------------------------------------------------------------------
2098 : !
2099 : ! initialize error code and fill value
2100 : !
2101 : !-----------------------------------------------------------------------
2102 :
2103 0 : if (present(fillValue)) then
2104 0 : fill = fillValue
2105 : else
2106 0 : fill = 0.0_real_kind
2107 : endif
2108 :
2109 0 : nz = size(array, dim=3)
2110 :
2111 0 : nxGlobal = 0
2112 0 : if (allocated(bufTripoleR4)) then
2113 0 : nxGlobal = size(bufTripoleR4,dim=1)
2114 0 : allocate(bufTripole(nxGlobal,halo%tripoleRows,nz))
2115 0 : bufTripole = fill
2116 : endif
2117 :
2118 : !-----------------------------------------------------------------------
2119 : !
2120 : ! fill out halo region
2121 : ! needed for masked halos to ensure halo values are filled for
2122 : ! halo grid cells that are not updated
2123 : !
2124 : !-----------------------------------------------------------------------
2125 :
2126 0 : do iblk = 1, halo%numLocalBlocks
2127 : call get_block_parameter(halo%blockGlobalID(iblk), &
2128 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
2129 0 : jlo=jlo, jhi=jhi)
2130 0 : do j = 1,nghost
2131 0 : array(1:nx_block, jlo-j,:,iblk) = fill
2132 0 : array(1:nx_block, jhi+j,:,iblk) = fill
2133 : enddo
2134 0 : do i = 1,nghost
2135 0 : array(ilo-i, 1:ny_block,:,iblk) = fill
2136 0 : array(ihi+i, 1:ny_block,:,iblk) = fill
2137 : enddo
2138 : enddo
2139 :
2140 : !-----------------------------------------------------------------------
2141 : !
2142 : ! do local copies
2143 : ! if srcBlock is zero, that denotes an eliminated land block or a
2144 : ! closed boundary where ghost cell values are undefined
2145 : ! if srcBlock is less than zero, the message is a copy out of the
2146 : ! tripole buffer and will be treated later
2147 : !
2148 : !-----------------------------------------------------------------------
2149 :
2150 0 : do nmsg=1,halo%numLocalCopies
2151 0 : iSrc = halo%srcLocalAddr(1,nmsg)
2152 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2153 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2154 0 : iDst = halo%dstLocalAddr(1,nmsg)
2155 0 : jDst = halo%dstLocalAddr(2,nmsg)
2156 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2157 :
2158 0 : if (srcBlock > 0) then
2159 0 : if (dstBlock > 0) then
2160 0 : do k=1,nz
2161 : array(iDst,jDst,k,dstBlock) = &
2162 0 : array(iSrc,jSrc,k,srcBlock)
2163 : end do
2164 0 : else if (dstBlock < 0) then ! tripole copy into buffer
2165 0 : do k=1,nz
2166 : bufTripole(iDst,jDst,k) = &
2167 0 : array(iSrc,jSrc,k,srcBlock)
2168 : end do
2169 : endif
2170 0 : else if (srcBlock == 0) then
2171 0 : do k=1,nz
2172 0 : array(iDst,jDst,k,dstBlock) = fill
2173 : end do
2174 : endif
2175 : end do
2176 :
2177 : !-----------------------------------------------------------------------
2178 : !
2179 : ! take care of northern boundary in tripole case
2180 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
2181 : ! (T-fold) of physical domain for entire (global) top row
2182 : !
2183 : !-----------------------------------------------------------------------
2184 :
2185 0 : if (nxGlobal > 0) then
2186 :
2187 0 : select case (fieldKind)
2188 : case (field_type_scalar)
2189 0 : isign = 1
2190 : case (field_type_vector)
2191 0 : isign = -1
2192 : case (field_type_angle)
2193 0 : isign = -1
2194 : case default
2195 0 : call abort_ice(subname//'ERROR: Unknown field kind')
2196 : end select
2197 :
2198 0 : if (halo%tripoleTFlag) then
2199 :
2200 0 : select case (fieldLoc)
2201 : case (field_loc_center) ! cell center location
2202 :
2203 0 : ioffset = -1
2204 0 : joffset = 0
2205 :
2206 : !*** top row is degenerate, so must enforce symmetry
2207 : !*** use average of two degenerate points for value
2208 :
2209 0 : do k=1,nz
2210 0 : do i = 2,nxGlobal/2
2211 0 : iDst = nxGlobal - i + 2
2212 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2213 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2214 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
2215 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2216 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2217 : end do
2218 : end do
2219 :
2220 : case (field_loc_NEcorner) ! cell corner location
2221 :
2222 0 : ioffset = 0
2223 0 : joffset = 1
2224 :
2225 : case (field_loc_Eface) ! cell center location
2226 :
2227 0 : ioffset = 0
2228 0 : joffset = 0
2229 :
2230 : !*** top row is degenerate, so must enforce symmetry
2231 : !*** use average of two degenerate points for value
2232 :
2233 0 : do k=1,nz
2234 0 : do i = 1,nxGlobal/2
2235 0 : iDst = nxGlobal + 1 - i
2236 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2237 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2238 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
2239 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2240 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2241 : end do
2242 : end do
2243 :
2244 : case (field_loc_Nface) ! cell corner (velocity) location
2245 :
2246 0 : ioffset = -1
2247 0 : joffset = 1
2248 :
2249 : case default
2250 0 : call abort_ice(subname//'ERROR: Unknown field location')
2251 : end select
2252 :
2253 : else ! tripole u-fold
2254 :
2255 0 : select case (fieldLoc)
2256 : case (field_loc_center) ! cell center location
2257 :
2258 0 : ioffset = 0
2259 0 : joffset = 0
2260 :
2261 : case (field_loc_NEcorner) ! cell corner location
2262 :
2263 0 : ioffset = 1
2264 0 : joffset = 1
2265 :
2266 : !*** top row is degenerate, so must enforce symmetry
2267 : !*** use average of two degenerate points for value
2268 :
2269 0 : do k=1,nz
2270 0 : do i = 1,nxGlobal/2 - 1
2271 0 : iDst = nxGlobal - i
2272 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2273 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2274 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
2275 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2276 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2277 : end do
2278 : end do
2279 :
2280 : case (field_loc_Eface) ! cell center location
2281 :
2282 0 : ioffset = 1
2283 0 : joffset = 0
2284 :
2285 : case (field_loc_Nface) ! cell corner (velocity) location
2286 :
2287 0 : ioffset = 0
2288 0 : joffset = 1
2289 :
2290 : !*** top row is degenerate, so must enforce symmetry
2291 : !*** use average of two degenerate points for value
2292 :
2293 0 : do k=1,nz
2294 0 : do i = 1,nxGlobal/2
2295 0 : iDst = nxGlobal + 1 - i
2296 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2297 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2298 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
2299 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2300 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2301 : end do
2302 : end do
2303 :
2304 : case default
2305 0 : call abort_ice(subname//'ERROR: Unknown field location')
2306 : end select
2307 :
2308 : endif
2309 :
2310 : !*** copy out of global tripole buffer into local
2311 : !*** ghost cells
2312 :
2313 : !*** look through local copies to find the copy out
2314 : !*** messages (srcBlock < 0)
2315 :
2316 0 : do nmsg=1,halo%numLocalCopies
2317 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2318 :
2319 0 : if (srcBlock < 0) then
2320 :
2321 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
2322 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2323 :
2324 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
2325 0 : jDst = halo%dstLocalAddr(2,nmsg)
2326 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2327 :
2328 : !*** correct for offsets
2329 0 : iSrc = iSrc - ioffset
2330 0 : jSrc = jSrc - joffset
2331 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
2332 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
2333 :
2334 : !*** for center and Eface on u-fold, and NE corner and Nface
2335 : !*** on T-fold, do not need to replace
2336 : !*** top row of physical domain, so jSrc should be
2337 : !*** out of range and skipped
2338 : !*** otherwise do the copy
2339 :
2340 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
2341 0 : do k=1,nz
2342 : array(iDst,jDst,k,dstBlock) = isign* &
2343 0 : bufTripole(iSrc,jSrc,k)
2344 : end do
2345 : endif
2346 :
2347 : endif
2348 : end do
2349 :
2350 : endif
2351 :
2352 0 : if (allocated(bufTripole)) deallocate(bufTripole)
2353 :
2354 : !-----------------------------------------------------------------------
2355 :
2356 0 : end subroutine ice_HaloUpdate3DR4
2357 :
2358 : !***********************************************************************
2359 :
2360 0 : subroutine ice_HaloUpdate3DI4(array, halo, &
2361 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2362 : fillValue)
2363 :
2364 : ! This routine updates ghost cells for an input array and is a
2365 : ! member of a group of routines under the generic interface
2366 : ! POP\_HaloUpdate. This routine is the specific interface
2367 : ! for 3d horizontal arrays of double precision.
2368 :
2369 : type (ice_halo), intent(in) :: &
2370 : halo ! precomputed halo structure containing all
2371 : ! information needed for halo update
2372 :
2373 : integer (int_kind), intent(in) :: &
2374 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
2375 : fieldLoc ! id for location on horizontal grid
2376 : ! (center, NEcorner, Nface, Eface)
2377 :
2378 : integer (int_kind), intent(in), optional :: &
2379 : fillValue ! optional value to put in ghost cells
2380 : ! where neighbor points are unknown
2381 : ! (e.g. eliminated land blocks or
2382 : ! closed boundaries)
2383 :
2384 : integer (int_kind), dimension(:,:,:,:), intent(inout) :: &
2385 : array ! array containing field for which halo
2386 : ! needs to be updated
2387 :
2388 : !-----------------------------------------------------------------------
2389 : !
2390 : ! local variables
2391 : !
2392 : !-----------------------------------------------------------------------
2393 :
2394 : integer (int_kind) :: &
2395 : i,j,k,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
2396 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
2397 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
2398 : nz, &! size of array in 3rd dimension ! LCOV_EXCL_LINE
2399 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
2400 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
2401 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
2402 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
2403 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
2404 : isign ! sign factor for tripole grids
2405 :
2406 : integer (int_kind) :: &
2407 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
2408 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
2409 :
2410 : integer (int_kind), dimension(:,:,:), allocatable :: &
2411 0 : bufTripole ! 3d tripole buffer
2412 :
2413 : character(len=*), parameter :: subname = '(ice_HaloUpdate3DI4)'
2414 :
2415 : !-----------------------------------------------------------------------
2416 : !
2417 : ! abort or return on unknown or noupdate field_loc or field_type
2418 : !
2419 : !-----------------------------------------------------------------------
2420 :
2421 0 : if (fieldLoc == field_loc_unknown .or. &
2422 : fieldKind == field_type_unknown) then
2423 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
2424 0 : return
2425 : endif
2426 :
2427 0 : if (fieldLoc == field_loc_noupdate .or. &
2428 : fieldKind == field_type_noupdate) then
2429 0 : return
2430 : endif
2431 :
2432 : !-----------------------------------------------------------------------
2433 : !
2434 : ! initialize error code and fill value
2435 : !
2436 : !-----------------------------------------------------------------------
2437 :
2438 0 : if (present(fillValue)) then
2439 0 : fill = fillValue
2440 : else
2441 0 : fill = 0_int_kind
2442 : endif
2443 :
2444 0 : nz = size(array, dim=3)
2445 :
2446 0 : nxGlobal = 0
2447 0 : if (allocated(bufTripoleI4)) then
2448 0 : nxGlobal = size(bufTripoleI4,dim=1)
2449 0 : allocate(bufTripole(nxGlobal,halo%tripoleRows,nz))
2450 0 : bufTripole = fill
2451 : endif
2452 :
2453 : !-----------------------------------------------------------------------
2454 : !
2455 : ! fill out halo region
2456 : ! needed for masked halos to ensure halo values are filled for
2457 : ! halo grid cells that are not updated
2458 : !
2459 : !-----------------------------------------------------------------------
2460 :
2461 0 : do iblk = 1, halo%numLocalBlocks
2462 : call get_block_parameter(halo%blockGlobalID(iblk), &
2463 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
2464 0 : jlo=jlo, jhi=jhi)
2465 0 : do j = 1,nghost
2466 0 : array(1:nx_block, jlo-j,:,iblk) = fill
2467 0 : array(1:nx_block, jhi+j,:,iblk) = fill
2468 : enddo
2469 0 : do i = 1,nghost
2470 0 : array(ilo-i, 1:ny_block,:,iblk) = fill
2471 0 : array(ihi+i, 1:ny_block,:,iblk) = fill
2472 : enddo
2473 : enddo
2474 :
2475 : !-----------------------------------------------------------------------
2476 : !
2477 : ! do local copies
2478 : ! if srcBlock is zero, that denotes an eliminated land block or a
2479 : ! closed boundary where ghost cell values are undefined
2480 : ! if srcBlock is less than zero, the message is a copy out of the
2481 : ! tripole buffer and will be treated later
2482 : !
2483 : !-----------------------------------------------------------------------
2484 :
2485 0 : do nmsg=1,halo%numLocalCopies
2486 0 : iSrc = halo%srcLocalAddr(1,nmsg)
2487 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2488 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2489 0 : iDst = halo%dstLocalAddr(1,nmsg)
2490 0 : jDst = halo%dstLocalAddr(2,nmsg)
2491 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2492 :
2493 0 : if (srcBlock > 0) then
2494 0 : if (dstBlock > 0) then
2495 0 : do k=1,nz
2496 : array(iDst,jDst,k,dstBlock) = &
2497 0 : array(iSrc,jSrc,k,srcBlock)
2498 : end do
2499 0 : else if (dstBlock < 0) then ! tripole copy into buffer
2500 0 : do k=1,nz
2501 : bufTripole(iDst,jDst,k) = &
2502 0 : array(iSrc,jSrc,k,srcBlock)
2503 : end do
2504 : endif
2505 0 : else if (srcBlock == 0) then
2506 0 : do k=1,nz
2507 0 : array(iDst,jDst,k,dstBlock) = fill
2508 : end do
2509 : endif
2510 : end do
2511 :
2512 : !-----------------------------------------------------------------------
2513 : !
2514 : ! take care of northern boundary in tripole case
2515 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
2516 : ! (T-fold) of physical domain for entire (global) top row
2517 : !
2518 : !-----------------------------------------------------------------------
2519 :
2520 0 : if (nxGlobal > 0) then
2521 :
2522 0 : select case (fieldKind)
2523 : case (field_type_scalar)
2524 0 : isign = 1
2525 : case (field_type_vector)
2526 0 : isign = -1
2527 : case (field_type_angle)
2528 0 : isign = -1
2529 : case default
2530 0 : call abort_ice(subname//'ERROR: Unknown field kind')
2531 : end select
2532 :
2533 0 : if (halo%tripoleTFlag) then
2534 :
2535 0 : select case (fieldLoc)
2536 : case (field_loc_center) ! cell center location
2537 :
2538 0 : ioffset = -1
2539 0 : joffset = 0
2540 :
2541 : !*** top row is degenerate, so must enforce symmetry
2542 : !*** use average of two degenerate points for value
2543 :
2544 0 : do k=1,nz
2545 0 : do i = 2,nxGlobal/2
2546 0 : iDst = nxGlobal - i + 2
2547 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2548 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2549 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2550 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2551 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2552 : end do
2553 : end do
2554 :
2555 : case (field_loc_NEcorner) ! cell corner location
2556 :
2557 0 : ioffset = 0
2558 0 : joffset = 1
2559 :
2560 : case (field_loc_Eface) ! cell center location
2561 :
2562 0 : ioffset = 0
2563 0 : joffset = 0
2564 :
2565 : !*** top row is degenerate, so must enforce symmetry
2566 : !*** use average of two degenerate points for value
2567 :
2568 0 : do k=1,nz
2569 0 : do i = 1,nxGlobal/2
2570 0 : iDst = nxGlobal + 1 - i
2571 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2572 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2573 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2574 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2575 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2576 : end do
2577 : end do
2578 :
2579 : case (field_loc_Nface) ! cell corner (velocity) location
2580 :
2581 0 : ioffset = -1
2582 0 : joffset = 1
2583 :
2584 : case default
2585 0 : call abort_ice(subname//'ERROR: Unknown field location')
2586 : end select
2587 :
2588 : else ! tripole u-fold
2589 :
2590 0 : select case (fieldLoc)
2591 : case (field_loc_center) ! cell center location
2592 :
2593 0 : ioffset = 0
2594 0 : joffset = 0
2595 :
2596 : case (field_loc_NEcorner) ! cell corner location
2597 :
2598 0 : ioffset = 1
2599 0 : joffset = 1
2600 :
2601 : !*** top row is degenerate, so must enforce symmetry
2602 : !*** use average of two degenerate points for value
2603 :
2604 0 : do k=1,nz
2605 0 : do i = 1,nxGlobal/2 - 1
2606 0 : iDst = nxGlobal - i
2607 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2608 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2609 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2610 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2611 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2612 : end do
2613 : end do
2614 :
2615 : case (field_loc_Eface) ! cell center location
2616 :
2617 0 : ioffset = 1
2618 0 : joffset = 0
2619 :
2620 : case (field_loc_Nface) ! cell corner (velocity) location
2621 :
2622 0 : ioffset = 0
2623 0 : joffset = 1
2624 :
2625 : !*** top row is degenerate, so must enforce symmetry
2626 : !*** use average of two degenerate points for value
2627 :
2628 0 : do k=1,nz
2629 0 : do i = 1,nxGlobal/2
2630 0 : iDst = nxGlobal + 1 - i
2631 0 : x1 = bufTripole(i ,halo%tripoleRows,k)
2632 0 : x2 = bufTripole(iDst,halo%tripoleRows,k)
2633 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
2634 0 : bufTripole(i ,halo%tripoleRows,k) = xavg
2635 0 : bufTripole(iDst,halo%tripoleRows,k) = isign*xavg
2636 : end do
2637 : end do
2638 :
2639 : case default
2640 0 : call abort_ice(subname//'ERROR: Unknown field location')
2641 : end select
2642 :
2643 : endif
2644 :
2645 : !*** copy out of global tripole buffer into local
2646 : !*** ghost cells
2647 :
2648 : !*** look through local copies to find the copy out
2649 : !*** messages (srcBlock < 0)
2650 :
2651 0 : do nmsg=1,halo%numLocalCopies
2652 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
2653 :
2654 0 : if (srcBlock < 0) then
2655 :
2656 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
2657 0 : jSrc = halo%srcLocalAddr(2,nmsg)
2658 :
2659 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
2660 0 : jDst = halo%dstLocalAddr(2,nmsg)
2661 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
2662 :
2663 : !*** correct for offsets
2664 0 : iSrc = iSrc - ioffset
2665 0 : jSrc = jSrc - joffset
2666 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
2667 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
2668 :
2669 : !*** for center and Eface on u-fold, and NE corner and Nface
2670 : !*** on T-fold, do not need to replace
2671 : !*** top row of physical domain, so jSrc should be
2672 : !*** out of range and skipped
2673 : !*** otherwise do the copy
2674 :
2675 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
2676 0 : do k=1,nz
2677 : array(iDst,jDst,k,dstBlock) = isign* &
2678 0 : bufTripole(iSrc,jSrc,k)
2679 : end do
2680 : endif
2681 :
2682 : endif
2683 : end do
2684 :
2685 : endif
2686 :
2687 0 : if (allocated(bufTripole)) deallocate(bufTripole)
2688 :
2689 : !-----------------------------------------------------------------------
2690 :
2691 0 : end subroutine ice_HaloUpdate3DI4
2692 :
2693 : !***********************************************************************
2694 :
2695 145 : subroutine ice_HaloUpdate4DR8(array, halo, &
2696 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
2697 : fillValue)
2698 :
2699 : ! This routine updates ghost cells for an input array and is a
2700 : ! member of a group of routines under the generic interface
2701 : ! POP\_HaloUpdate. This routine is the specific interface
2702 : ! for 4d horizontal arrays of double precision.
2703 :
2704 : type (ice_halo), intent(in) :: &
2705 : halo ! precomputed halo structure containing all
2706 : ! information needed for halo update
2707 :
2708 : integer (int_kind), intent(in) :: &
2709 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
2710 : fieldLoc ! id for location on horizontal grid
2711 : ! (center, NEcorner, Nface, Eface)
2712 :
2713 : real (dbl_kind), intent(in), optional :: &
2714 : fillValue ! optional value to put in ghost cells
2715 : ! where neighbor points are unknown
2716 : ! (e.g. eliminated land blocks or
2717 : ! closed boundaries)
2718 :
2719 : real (dbl_kind), dimension(:,:,:,:,:), intent(inout) :: &
2720 : array ! array containing field for which halo
2721 : ! needs to be updated
2722 :
2723 : !-----------------------------------------------------------------------
2724 : !
2725 : ! local variables
2726 : !
2727 : !-----------------------------------------------------------------------
2728 :
2729 : integer (int_kind) :: &
2730 : i,j,k,l,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
2731 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
2732 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
2733 : nz, nt, &! size of array in 3rd,4th dimensions ! LCOV_EXCL_LINE
2734 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
2735 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
2736 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
2737 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
2738 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
2739 : isign ! sign factor for tripole grids
2740 :
2741 : real (dbl_kind) :: &
2742 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
2743 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
2744 :
2745 : real (dbl_kind), dimension(:,:,:,:), allocatable :: &
2746 145 : bufTripole ! 4d tripole buffer
2747 :
2748 : character(len=*), parameter :: subname = '(ice_HaloUpdate4DR8)'
2749 :
2750 : !-----------------------------------------------------------------------
2751 : !
2752 : ! abort or return on unknown or noupdate field_loc or field_type
2753 : !
2754 : !-----------------------------------------------------------------------
2755 :
2756 145 : if (fieldLoc == field_loc_unknown .or. &
2757 : fieldKind == field_type_unknown) then
2758 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
2759 0 : return
2760 : endif
2761 :
2762 145 : if (fieldLoc == field_loc_noupdate .or. &
2763 : fieldKind == field_type_noupdate) then
2764 0 : return
2765 : endif
2766 :
2767 : !-----------------------------------------------------------------------
2768 : !
2769 : ! initialize error code and fill value
2770 : !
2771 : !-----------------------------------------------------------------------
2772 :
2773 145 : if (present(fillValue)) then
2774 0 : fill = fillValue
2775 : else
2776 145 : fill = 0.0_dbl_kind
2777 : endif
2778 :
2779 145 : nz = size(array, dim=3)
2780 145 : nt = size(array, dim=4)
2781 :
2782 145 : nxGlobal = 0
2783 145 : if (allocated(bufTripoleR8)) then
2784 0 : nxGlobal = size(bufTripoleR8,dim=1)
2785 0 : allocate(bufTripole(nxGlobal,halo%tripoleRows,nz,nt))
2786 0 : bufTripole = fill
2787 : endif
2788 :
2789 : !-----------------------------------------------------------------------
2790 : !
2791 : ! fill out halo region
2792 : ! needed for masked halos to ensure halo values are filled for
2793 : ! halo grid cells that are not updated
2794 : !
2795 : !-----------------------------------------------------------------------
2796 :
2797 290 : do iblk = 1, halo%numLocalBlocks
2798 : call get_block_parameter(halo%blockGlobalID(iblk), &
2799 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
2800 145 : jlo=jlo, jhi=jhi)
2801 290 : do j = 1,nghost
2802 1867230 : array(1:nx_block, jlo-j,:,:,iblk) = fill
2803 1867375 : array(1:nx_block, jhi+j,:,:,iblk) = fill
2804 : enddo
2805 580 : do i = 1,nghost
2806 2157150 : array(ilo-i, 1:ny_block,:,:,iblk) = fill
2807 2157295 : array(ihi+i, 1:ny_block,:,:,iblk) = fill
2808 : enddo
2809 : enddo
2810 :
2811 : !-----------------------------------------------------------------------
2812 : !
2813 : ! do local copies
2814 : ! if srcBlock is zero, that denotes an eliminated land block or a
2815 : ! closed boundary where ghost cell values are undefined
2816 : ! if srcBlock is less than zero, the message is a copy out of the
2817 : ! tripole buffer and will be treated later
2818 : !
2819 : !-----------------------------------------------------------------------
2820 :
2821 33785 : do nmsg=1,halo%numLocalCopies
2822 33640 : iSrc = halo%srcLocalAddr(1,nmsg)
2823 33640 : jSrc = halo%srcLocalAddr(2,nmsg)
2824 33640 : srcBlock = halo%srcLocalAddr(3,nmsg)
2825 33640 : iDst = halo%dstLocalAddr(1,nmsg)
2826 33640 : jDst = halo%dstLocalAddr(2,nmsg)
2827 33640 : dstBlock = halo%dstLocalAddr(3,nmsg)
2828 :
2829 33785 : if (srcBlock > 0) then
2830 33640 : if (dstBlock > 0) then
2831 201840 : do l=1,nt
2832 4405680 : do k=1,nz
2833 : array(iDst,jDst,k,l,dstBlock) = &
2834 4372040 : array(iSrc,jSrc,k,l,srcBlock)
2835 : end do
2836 : end do
2837 0 : else if (dstBlock < 0) then ! tripole copy into buffer
2838 0 : do l=1,nt
2839 0 : do k=1,nz
2840 : bufTripole(iDst,jDst,k,l) = &
2841 0 : array(iSrc,jSrc,k,l,srcBlock)
2842 : end do
2843 : end do
2844 : endif
2845 0 : else if (srcBlock == 0) then
2846 0 : do l=1,nt
2847 0 : do k=1,nz
2848 0 : array(iDst,jDst,k,l,dstBlock) = fill
2849 : end do
2850 : end do
2851 : endif
2852 : end do
2853 :
2854 : !-----------------------------------------------------------------------
2855 : !
2856 : ! take care of northern boundary in tripole case
2857 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
2858 : ! (T-fold) of physical domain for entire (global) top row
2859 : !
2860 : !-----------------------------------------------------------------------
2861 :
2862 145 : if (nxGlobal > 0) then
2863 :
2864 0 : select case (fieldKind)
2865 : case (field_type_scalar)
2866 0 : isign = 1
2867 : case (field_type_vector)
2868 0 : isign = -1
2869 : case (field_type_angle)
2870 0 : isign = -1
2871 : case default
2872 0 : call abort_ice(subname//'ERROR: Unknown field kind')
2873 : end select
2874 :
2875 0 : if (halo%tripoleTFlag) then
2876 :
2877 0 : select case (fieldLoc)
2878 : case (field_loc_center) ! cell center location
2879 :
2880 0 : ioffset = -1
2881 0 : joffset = 0
2882 :
2883 : !*** top row is degenerate, so must enforce symmetry
2884 : !*** use average of two degenerate points for value
2885 :
2886 0 : do l=1,nt
2887 0 : do k=1,nz
2888 0 : do i = 2,nxGlobal/2
2889 0 : iDst = nxGlobal - i + 2
2890 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
2891 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
2892 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2893 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
2894 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
2895 : end do
2896 : end do
2897 : end do
2898 :
2899 : case (field_loc_NEcorner) ! cell corner location
2900 :
2901 0 : ioffset = 0
2902 0 : joffset = 1
2903 :
2904 : case (field_loc_Eface) ! cell center location
2905 :
2906 0 : ioffset = 0
2907 0 : joffset = 0
2908 :
2909 : !*** top row is degenerate, so must enforce symmetry
2910 : !*** use average of two degenerate points for value
2911 :
2912 0 : do l=1,nt
2913 0 : do k=1,nz
2914 0 : do i = 1,nxGlobal/2
2915 0 : iDst = nxGlobal + 1 - i
2916 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
2917 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
2918 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2919 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
2920 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
2921 : end do
2922 : end do
2923 : end do
2924 :
2925 : case (field_loc_Nface) ! cell corner (velocity) location
2926 :
2927 0 : ioffset = -1
2928 0 : joffset = 1
2929 :
2930 : case default
2931 0 : call abort_ice(subname//'ERROR: Unknown field location')
2932 : end select
2933 :
2934 : else ! tripole u-fold
2935 :
2936 0 : select case (fieldLoc)
2937 : case (field_loc_center) ! cell center location
2938 :
2939 0 : ioffset = 0
2940 0 : joffset = 0
2941 :
2942 : case (field_loc_NEcorner) ! cell corner location
2943 :
2944 0 : ioffset = 1
2945 0 : joffset = 1
2946 :
2947 : !*** top row is degenerate, so must enforce symmetry
2948 : !*** use average of two degenerate points for value
2949 :
2950 0 : do l=1,nt
2951 0 : do k=1,nz
2952 0 : do i = 1,nxGlobal/2 - 1
2953 0 : iDst = nxGlobal - i
2954 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
2955 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
2956 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2957 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
2958 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
2959 : end do
2960 : end do
2961 : end do
2962 :
2963 : case (field_loc_Eface) ! cell center location
2964 :
2965 0 : ioffset = 1
2966 0 : joffset = 0
2967 :
2968 : case (field_loc_Nface) ! cell corner (velocity) location
2969 :
2970 0 : ioffset = 0
2971 0 : joffset = 1
2972 :
2973 : !*** top row is degenerate, so must enforce symmetry
2974 : !*** use average of two degenerate points for value
2975 :
2976 0 : do l=1,nt
2977 0 : do k=1,nz
2978 0 : do i = 1,nxGlobal/2
2979 0 : iDst = nxGlobal + 1 - i
2980 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
2981 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
2982 0 : xavg = 0.5_dbl_kind*(x1 + isign*x2)
2983 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
2984 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
2985 : end do
2986 : end do
2987 : end do
2988 :
2989 : case default
2990 0 : call abort_ice(subname//'ERROR: Unknown field location')
2991 : end select
2992 :
2993 : endif
2994 :
2995 : !*** copy out of global tripole buffer into local
2996 : !*** ghost cells
2997 :
2998 : !*** look through local copies to find the copy out
2999 : !*** messages (srcBlock < 0)
3000 :
3001 0 : do nmsg=1,halo%numLocalCopies
3002 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3003 :
3004 0 : if (srcBlock < 0) then
3005 :
3006 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
3007 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3008 :
3009 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
3010 0 : jDst = halo%dstLocalAddr(2,nmsg)
3011 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3012 :
3013 : !*** correct for offsets
3014 0 : iSrc = iSrc - ioffset
3015 0 : jSrc = jSrc - joffset
3016 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
3017 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
3018 :
3019 : !*** for center and Eface on u-fold, and NE corner and Nface
3020 : !*** on T-fold, do not need to replace
3021 : !*** top row of physical domain, so jSrc should be
3022 : !*** out of range and skipped
3023 : !*** otherwise do the copy
3024 :
3025 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
3026 0 : do l=1,nt
3027 0 : do k=1,nz
3028 : array(iDst,jDst,k,l,dstBlock) = isign* &
3029 0 : bufTripole(iSrc,jSrc,k,l)
3030 : end do
3031 : end do
3032 : endif
3033 :
3034 : endif
3035 : end do
3036 :
3037 : endif
3038 :
3039 145 : if (allocated(bufTripole)) deallocate(bufTripole)
3040 :
3041 : !-----------------------------------------------------------------------
3042 :
3043 145 : end subroutine ice_HaloUpdate4DR8
3044 :
3045 : !***********************************************************************
3046 :
3047 0 : subroutine ice_HaloUpdate4DR4(array, halo, &
3048 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
3049 : fillValue)
3050 :
3051 : ! This routine updates ghost cells for an input array and is a
3052 : ! member of a group of routines under the generic interface
3053 : ! POP\_HaloUpdate. This routine is the specific interface
3054 : ! for 4d horizontal arrays of single precision.
3055 :
3056 : type (ice_halo), intent(in) :: &
3057 : halo ! precomputed halo structure containing all
3058 : ! information needed for halo update
3059 :
3060 : integer (int_kind), intent(in) :: &
3061 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
3062 : fieldLoc ! id for location on horizontal grid
3063 : ! (center, NEcorner, Nface, Eface)
3064 :
3065 : real (real_kind), intent(in), optional :: &
3066 : fillValue ! optional value to put in ghost cells
3067 : ! where neighbor points are unknown
3068 : ! (e.g. eliminated land blocks or
3069 : ! closed boundaries)
3070 :
3071 : real (real_kind), dimension(:,:,:,:,:), intent(inout) :: &
3072 : array ! array containing field for which halo
3073 : ! needs to be updated
3074 :
3075 : !-----------------------------------------------------------------------
3076 : !
3077 : ! local variables
3078 : !
3079 : !-----------------------------------------------------------------------
3080 :
3081 : integer (int_kind) :: &
3082 : i,j,k,l,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
3083 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
3084 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
3085 : nz, nt, &! size of array in 3rd,4th dimensions ! LCOV_EXCL_LINE
3086 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
3087 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
3088 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
3089 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
3090 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
3091 : isign ! sign factor for tripole grids
3092 :
3093 : real (real_kind) :: &
3094 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
3095 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
3096 :
3097 : real (real_kind), dimension(:,:,:,:), allocatable :: &
3098 0 : bufTripole ! 4d tripole buffer
3099 :
3100 : character(len=*), parameter :: subname = '(ice_HaloUpdate4DR4)'
3101 :
3102 : !-----------------------------------------------------------------------
3103 : !
3104 : ! abort or return on unknown or noupdate field_loc or field_type
3105 : !
3106 : !-----------------------------------------------------------------------
3107 :
3108 0 : if (fieldLoc == field_loc_unknown .or. &
3109 : fieldKind == field_type_unknown) then
3110 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
3111 0 : return
3112 : endif
3113 :
3114 0 : if (fieldLoc == field_loc_noupdate .or. &
3115 : fieldKind == field_type_noupdate) then
3116 0 : return
3117 : endif
3118 :
3119 : !-----------------------------------------------------------------------
3120 : !
3121 : ! initialize error code and fill value
3122 : !
3123 : !-----------------------------------------------------------------------
3124 :
3125 0 : if (present(fillValue)) then
3126 0 : fill = fillValue
3127 : else
3128 0 : fill = 0.0_real_kind
3129 : endif
3130 :
3131 0 : nz = size(array, dim=3)
3132 0 : nt = size(array, dim=4)
3133 :
3134 0 : nxGlobal = 0
3135 0 : if (allocated(bufTripoleR4)) then
3136 0 : nxGlobal = size(bufTripoleR4,dim=1)
3137 0 : allocate(bufTripole(nxGlobal,halo%tripoleRows,nz,nt))
3138 0 : bufTripole = fill
3139 : endif
3140 :
3141 : !-----------------------------------------------------------------------
3142 : !
3143 : ! fill out halo region
3144 : ! needed for masked halos to ensure halo values are filled for
3145 : ! halo grid cells that are not updated
3146 : !
3147 : !-----------------------------------------------------------------------
3148 :
3149 0 : do iblk = 1, halo%numLocalBlocks
3150 : call get_block_parameter(halo%blockGlobalID(iblk), &
3151 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
3152 0 : jlo=jlo, jhi=jhi)
3153 0 : do j = 1,nghost
3154 0 : array(1:nx_block, jlo-j,:,:,iblk) = fill
3155 0 : array(1:nx_block, jhi+j,:,:,iblk) = fill
3156 : enddo
3157 0 : do i = 1,nghost
3158 0 : array(ilo-i, 1:ny_block,:,:,iblk) = fill
3159 0 : array(ihi+i, 1:ny_block,:,:,iblk) = fill
3160 : enddo
3161 : enddo
3162 :
3163 : !-----------------------------------------------------------------------
3164 : !
3165 : ! do local copies
3166 : ! if srcBlock is zero, that denotes an eliminated land block or a
3167 : ! closed boundary where ghost cell values are undefined
3168 : ! if srcBlock is less than zero, the message is a copy out of the
3169 : ! tripole buffer and will be treated later
3170 : !
3171 : !-----------------------------------------------------------------------
3172 :
3173 0 : do nmsg=1,halo%numLocalCopies
3174 0 : iSrc = halo%srcLocalAddr(1,nmsg)
3175 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3176 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3177 0 : iDst = halo%dstLocalAddr(1,nmsg)
3178 0 : jDst = halo%dstLocalAddr(2,nmsg)
3179 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3180 :
3181 0 : if (srcBlock > 0) then
3182 0 : if (dstBlock > 0) then
3183 0 : do l=1,nt
3184 0 : do k=1,nz
3185 : array(iDst,jDst,k,l,dstBlock) = &
3186 0 : array(iSrc,jSrc,k,l,srcBlock)
3187 : end do
3188 : end do
3189 0 : else if (dstBlock < 0) then ! tripole copy into buffer
3190 0 : do l=1,nt
3191 0 : do k=1,nz
3192 : bufTripole(iDst,jDst,k,l) = &
3193 0 : array(iSrc,jSrc,k,l,srcBlock)
3194 : end do
3195 : end do
3196 : endif
3197 0 : else if (srcBlock == 0) then
3198 0 : do l=1,nt
3199 0 : do k=1,nz
3200 0 : array(iDst,jDst,k,l,dstBlock) = fill
3201 : end do
3202 : end do
3203 : endif
3204 : end do
3205 :
3206 : !-----------------------------------------------------------------------
3207 : !
3208 : ! take care of northern boundary in tripole case
3209 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
3210 : ! (T-fold) of physical domain for entire (global) top row
3211 : !
3212 : !-----------------------------------------------------------------------
3213 :
3214 0 : if (nxGlobal > 0) then
3215 :
3216 0 : select case (fieldKind)
3217 : case (field_type_scalar)
3218 0 : isign = 1
3219 : case (field_type_vector)
3220 0 : isign = -1
3221 : case (field_type_angle)
3222 0 : isign = -1
3223 : case default
3224 0 : call abort_ice(subname//'ERROR: Unknown field kind')
3225 : end select
3226 :
3227 0 : if (halo%tripoleTFlag) then
3228 :
3229 0 : select case (fieldLoc)
3230 : case (field_loc_center) ! cell center location
3231 :
3232 0 : ioffset = -1
3233 0 : joffset = 0
3234 :
3235 : !*** top row is degenerate, so must enforce symmetry
3236 : !*** use average of two degenerate points for value
3237 :
3238 0 : do l=1,nt
3239 0 : do k=1,nz
3240 0 : do i = 2,nxGlobal/2
3241 0 : iDst = nxGlobal - i + 2
3242 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3243 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3244 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3245 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3246 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3247 : end do
3248 : end do
3249 : end do
3250 :
3251 : case (field_loc_NEcorner) ! cell corner location
3252 :
3253 0 : ioffset = 0
3254 0 : joffset = 1
3255 :
3256 : case (field_loc_Eface) ! cell center location
3257 :
3258 0 : ioffset = 0
3259 0 : joffset = 0
3260 :
3261 : !*** top row is degenerate, so must enforce symmetry
3262 : !*** use average of two degenerate points for value
3263 :
3264 0 : do l=1,nt
3265 0 : do k=1,nz
3266 0 : do i = 1,nxGlobal/2
3267 0 : iDst = nxGlobal + 1 - i
3268 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3269 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3270 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3271 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3272 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3273 : end do
3274 : end do
3275 : end do
3276 :
3277 : case (field_loc_Nface) ! cell corner (velocity) location
3278 :
3279 0 : ioffset = -1
3280 0 : joffset = 1
3281 :
3282 : case default
3283 0 : call abort_ice(subname//'ERROR: Unknown field location')
3284 : end select
3285 :
3286 : else ! tripole u-fold
3287 :
3288 0 : select case (fieldLoc)
3289 : case (field_loc_center) ! cell center location
3290 :
3291 0 : ioffset = 0
3292 0 : joffset = 0
3293 :
3294 : case (field_loc_NEcorner) ! cell corner location
3295 :
3296 0 : ioffset = 1
3297 0 : joffset = 1
3298 :
3299 : !*** top row is degenerate, so must enforce symmetry
3300 : !*** use average of two degenerate points for value
3301 :
3302 0 : do l=1,nt
3303 0 : do k=1,nz
3304 0 : do i = 1,nxGlobal/2 - 1
3305 0 : iDst = nxGlobal - i
3306 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3307 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3308 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3309 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3310 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3311 : end do
3312 : end do
3313 : end do
3314 :
3315 : case (field_loc_Eface) ! cell center location
3316 :
3317 0 : ioffset = 1
3318 0 : joffset = 0
3319 :
3320 : case (field_loc_Nface) ! cell corner (velocity) location
3321 :
3322 0 : ioffset = 0
3323 0 : joffset = 1
3324 :
3325 : !*** top row is degenerate, so must enforce symmetry
3326 : !*** use average of two degenerate points for value
3327 :
3328 0 : do l=1,nt
3329 0 : do k=1,nz
3330 0 : do i = 1,nxGlobal/2
3331 0 : iDst = nxGlobal + 1 - i
3332 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3333 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3334 0 : xavg = 0.5_real_kind*(x1 + isign*x2)
3335 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3336 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3337 : end do
3338 : end do
3339 : end do
3340 :
3341 : case default
3342 0 : call abort_ice(subname//'ERROR: Unknown field location')
3343 : end select
3344 :
3345 : endif
3346 :
3347 : !*** copy out of global tripole buffer into local
3348 : !*** ghost cells
3349 :
3350 : !*** look through local copies to find the copy out
3351 : !*** messages (srcBlock < 0)
3352 :
3353 0 : do nmsg=1,halo%numLocalCopies
3354 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3355 :
3356 0 : if (srcBlock < 0) then
3357 :
3358 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
3359 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3360 :
3361 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
3362 0 : jDst = halo%dstLocalAddr(2,nmsg)
3363 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3364 :
3365 : !*** correct for offsets
3366 0 : iSrc = iSrc - ioffset
3367 0 : jSrc = jSrc - joffset
3368 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
3369 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
3370 :
3371 : !*** for center and Eface on u-fold, and NE corner and Nface
3372 : !*** on T-fold, do not need to replace
3373 : !*** top row of physical domain, so jSrc should be
3374 : !*** out of range and skipped
3375 : !*** otherwise do the copy
3376 :
3377 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
3378 0 : do l=1,nt
3379 0 : do k=1,nz
3380 : array(iDst,jDst,k,l,dstBlock) = isign* &
3381 0 : bufTripole(iSrc,jSrc,k,l)
3382 : end do
3383 : end do
3384 : endif
3385 :
3386 : endif
3387 : end do
3388 :
3389 : endif
3390 :
3391 0 : if (allocated(bufTripole)) deallocate(bufTripole)
3392 :
3393 : !-----------------------------------------------------------------------
3394 :
3395 0 : end subroutine ice_HaloUpdate4DR4
3396 :
3397 : !***********************************************************************
3398 :
3399 0 : subroutine ice_HaloUpdate4DI4(array, halo, &
3400 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
3401 : fillValue)
3402 :
3403 : ! This routine updates ghost cells for an input array and is a
3404 : ! member of a group of routines under the generic interface
3405 : ! POP\_HaloUpdate. This routine is the specific interface
3406 : ! for 4d horizontal integer arrays.
3407 :
3408 : type (ice_halo), intent(in) :: &
3409 : halo ! precomputed halo structure containing all
3410 : ! information needed for halo update
3411 :
3412 : integer (int_kind), intent(in) :: &
3413 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
3414 : fieldLoc ! id for location on horizontal grid
3415 : ! (center, NEcorner, Nface, Eface)
3416 :
3417 : integer (int_kind), intent(in), optional :: &
3418 : fillValue ! optional value to put in ghost cells
3419 : ! where neighbor points are unknown
3420 : ! (e.g. eliminated land blocks or
3421 : ! closed boundaries)
3422 :
3423 : integer (int_kind), dimension(:,:,:,:,:), intent(inout) :: &
3424 : array ! array containing field for which halo
3425 : ! needs to be updated
3426 :
3427 : !-----------------------------------------------------------------------
3428 : !
3429 : ! local variables
3430 : !
3431 : !-----------------------------------------------------------------------
3432 :
3433 : integer (int_kind) :: &
3434 : i,j,k,l,nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
3435 : iblk,ilo,ihi,jlo,jhi, &! block sizes for fill ! LCOV_EXCL_LINE
3436 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
3437 : nz, nt, &! size of array in 3rd,4th dimensions ! LCOV_EXCL_LINE
3438 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
3439 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
3440 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
3441 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
3442 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
3443 : isign ! sign factor for tripole grids
3444 :
3445 : integer (int_kind) :: &
3446 : fill, &! value to use for unknown points ! LCOV_EXCL_LINE
3447 : x1,x2,xavg ! scalars for enforcing symmetry at U pts
3448 :
3449 : integer (int_kind), dimension(:,:,:,:), allocatable :: &
3450 0 : bufTripole ! 4d tripole buffer
3451 :
3452 : character(len=*), parameter :: subname = '(ice_HaloUpdate4DI4)'
3453 :
3454 : !-----------------------------------------------------------------------
3455 : !
3456 : ! abort or return on unknown or noupdate field_loc or field_type
3457 : !
3458 : !-----------------------------------------------------------------------
3459 :
3460 0 : if (fieldLoc == field_loc_unknown .or. &
3461 : fieldKind == field_type_unknown) then
3462 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
3463 0 : return
3464 : endif
3465 :
3466 0 : if (fieldLoc == field_loc_noupdate .or. &
3467 : fieldKind == field_type_noupdate) then
3468 0 : return
3469 : endif
3470 :
3471 : !-----------------------------------------------------------------------
3472 : !
3473 : ! initialize error code and fill value
3474 : !
3475 : !-----------------------------------------------------------------------
3476 :
3477 0 : if (present(fillValue)) then
3478 0 : fill = fillValue
3479 : else
3480 0 : fill = 0_int_kind
3481 : endif
3482 :
3483 0 : nz = size(array, dim=3)
3484 0 : nt = size(array, dim=4)
3485 :
3486 0 : nxGlobal = 0
3487 0 : if (allocated(bufTripoleI4)) then
3488 0 : nxGlobal = size(bufTripoleI4,dim=1)
3489 0 : allocate(bufTripole(nxGlobal,halo%tripoleRows,nz,nt))
3490 0 : bufTripole = fill
3491 : endif
3492 :
3493 : !-----------------------------------------------------------------------
3494 : !
3495 : ! fill out halo region
3496 : ! needed for masked halos to ensure halo values are filled for
3497 : ! halo grid cells that are not updated
3498 : !
3499 : !-----------------------------------------------------------------------
3500 :
3501 0 : do iblk = 1, halo%numLocalBlocks
3502 : call get_block_parameter(halo%blockGlobalID(iblk), &
3503 : ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
3504 0 : jlo=jlo, jhi=jhi)
3505 0 : do j = 1,nghost
3506 0 : array(1:nx_block, jlo-j,:,:,iblk) = fill
3507 0 : array(1:nx_block, jhi+j,:,:,iblk) = fill
3508 : enddo
3509 0 : do i = 1,nghost
3510 0 : array(ilo-i, 1:ny_block,:,:,iblk) = fill
3511 0 : array(ihi+i, 1:ny_block,:,:,iblk) = fill
3512 : enddo
3513 : enddo
3514 :
3515 : !-----------------------------------------------------------------------
3516 : !
3517 : ! do local copies
3518 : ! if srcBlock is zero, that denotes an eliminated land block or a
3519 : ! closed boundary where ghost cell values are undefined
3520 : ! if srcBlock is less than zero, the message is a copy out of the
3521 : ! tripole buffer and will be treated later
3522 : !
3523 : !-----------------------------------------------------------------------
3524 :
3525 0 : do nmsg=1,halo%numLocalCopies
3526 0 : iSrc = halo%srcLocalAddr(1,nmsg)
3527 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3528 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3529 0 : iDst = halo%dstLocalAddr(1,nmsg)
3530 0 : jDst = halo%dstLocalAddr(2,nmsg)
3531 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3532 :
3533 0 : if (srcBlock > 0) then
3534 0 : if (dstBlock > 0) then
3535 0 : do l=1,nt
3536 0 : do k=1,nz
3537 : array(iDst,jDst,k,l,dstBlock) = &
3538 0 : array(iSrc,jSrc,k,l,srcBlock)
3539 : end do
3540 : end do
3541 0 : else if (dstBlock < 0) then ! tripole copy into buffer
3542 0 : do l=1,nt
3543 0 : do k=1,nz
3544 : bufTripole(iDst,jDst,k,l) = &
3545 0 : array(iSrc,jSrc,k,l,srcBlock)
3546 : end do
3547 : end do
3548 : endif
3549 0 : else if (srcBlock == 0) then
3550 0 : do l=1,nt
3551 0 : do k=1,nz
3552 0 : array(iDst,jDst,k,l,dstBlock) = fill
3553 : end do
3554 : end do
3555 : endif
3556 : end do
3557 :
3558 : !-----------------------------------------------------------------------
3559 : !
3560 : ! take care of northern boundary in tripole case
3561 : ! bufTripole array contains the top nghost+1 rows (u-fold) or nghost+2 rows
3562 : ! (T-fold) of physical domain for entire (global) top row
3563 : !
3564 : !-----------------------------------------------------------------------
3565 :
3566 0 : if (nxGlobal > 0) then
3567 :
3568 0 : select case (fieldKind)
3569 : case (field_type_scalar)
3570 0 : isign = 1
3571 : case (field_type_vector)
3572 0 : isign = -1
3573 : case (field_type_angle)
3574 0 : isign = -1
3575 : case default
3576 0 : call abort_ice(subname//'ERROR: Unknown field kind')
3577 : end select
3578 :
3579 0 : if (halo%tripoleTFlag) then
3580 :
3581 0 : select case (fieldLoc)
3582 : case (field_loc_center) ! cell center location
3583 :
3584 0 : ioffset = -1
3585 0 : joffset = 0
3586 :
3587 : !*** top row is degenerate, so must enforce symmetry
3588 : !*** use average of two degenerate points for value
3589 :
3590 0 : do l=1,nt
3591 0 : do k=1,nz
3592 0 : do i = 2,nxGlobal/2
3593 0 : iDst = nxGlobal - i + 2
3594 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3595 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3596 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3597 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3598 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3599 : end do
3600 : end do
3601 : end do
3602 :
3603 : case (field_loc_NEcorner) ! cell corner location
3604 :
3605 0 : ioffset = 0
3606 0 : joffset = 1
3607 :
3608 : case (field_loc_Eface) ! cell center location
3609 :
3610 0 : ioffset = 0
3611 0 : joffset = 0
3612 :
3613 : !*** top row is degenerate, so must enforce symmetry
3614 : !*** use average of two degenerate points for value
3615 :
3616 0 : do l=1,nt
3617 0 : do k=1,nz
3618 0 : do i = 1,nxGlobal/2
3619 0 : iDst = nxGlobal + 1 - i
3620 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3621 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3622 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3623 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3624 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3625 : end do
3626 : end do
3627 : end do
3628 :
3629 : case (field_loc_Nface) ! cell corner (velocity) location
3630 :
3631 0 : ioffset = -1
3632 0 : joffset = 1
3633 :
3634 : case default
3635 0 : call abort_ice(subname//'ERROR: Unknown field location')
3636 : end select
3637 :
3638 : else ! tripole u-fold
3639 :
3640 0 : select case (fieldLoc)
3641 : case (field_loc_center) ! cell center location
3642 :
3643 0 : ioffset = 0
3644 0 : joffset = 0
3645 :
3646 : case (field_loc_NEcorner) ! cell corner location
3647 :
3648 0 : ioffset = 1
3649 0 : joffset = 1
3650 :
3651 : !*** top row is degenerate, so must enforce symmetry
3652 : !*** use average of two degenerate points for value
3653 :
3654 0 : do l=1,nt
3655 0 : do k=1,nz
3656 0 : do i = 1,nxGlobal/2 - 1
3657 0 : iDst = nxGlobal - i
3658 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3659 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3660 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3661 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3662 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3663 : end do
3664 : end do
3665 : end do
3666 :
3667 : case (field_loc_Eface) ! cell center location
3668 :
3669 0 : ioffset = 1
3670 0 : joffset = 0
3671 :
3672 : case (field_loc_Nface) ! cell corner (velocity) location
3673 :
3674 0 : ioffset = 0
3675 0 : joffset = 1
3676 :
3677 : !*** top row is degenerate, so must enforce symmetry
3678 : !*** use average of two degenerate points for value
3679 :
3680 0 : do l=1,nt
3681 0 : do k=1,nz
3682 0 : do i = 1,nxGlobal/2
3683 0 : iDst = nxGlobal + 1 - i
3684 0 : x1 = bufTripole(i ,halo%tripoleRows,k,l)
3685 0 : x2 = bufTripole(iDst,halo%tripoleRows,k,l)
3686 0 : xavg = nint(0.5_dbl_kind*(x1 + isign*x2))
3687 0 : bufTripole(i ,halo%tripoleRows,k,l) = xavg
3688 0 : bufTripole(iDst,halo%tripoleRows,k,l) = isign*xavg
3689 : end do
3690 : end do
3691 : end do
3692 :
3693 : case default
3694 0 : call abort_ice(subname//'ERROR: Unknown field location')
3695 : end select
3696 :
3697 : endif
3698 :
3699 : !*** copy out of global tripole buffer into local
3700 : !*** ghost cells
3701 :
3702 : !*** look through local copies to find the copy out
3703 : !*** messages (srcBlock < 0)
3704 :
3705 0 : do nmsg=1,halo%numLocalCopies
3706 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3707 :
3708 0 : if (srcBlock < 0) then
3709 :
3710 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
3711 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3712 :
3713 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
3714 0 : jDst = halo%dstLocalAddr(2,nmsg)
3715 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3716 :
3717 : !*** correct for offsets
3718 0 : iSrc = iSrc - ioffset
3719 0 : jSrc = jSrc - joffset
3720 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
3721 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
3722 :
3723 : !*** for center and Eface on u-fold, and NE corner and Nface
3724 : !*** on T-fold, do not need to replace
3725 : !*** top row of physical domain, so jSrc should be
3726 : !*** out of range and skipped
3727 : !*** otherwise do the copy
3728 :
3729 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
3730 0 : do l=1,nt
3731 0 : do k=1,nz
3732 : array(iDst,jDst,k,l,dstBlock) = isign* &
3733 0 : bufTripole(iSrc,jSrc,k,l)
3734 : end do
3735 : end do
3736 : endif
3737 :
3738 : endif
3739 : end do
3740 :
3741 : endif
3742 :
3743 0 : if (allocated(bufTripole)) deallocate(bufTripole)
3744 :
3745 : !-----------------------------------------------------------------------
3746 :
3747 0 : end subroutine ice_HaloUpdate4DI4
3748 :
3749 : !***********************************************************************
3750 : ! This routine updates ghost cells for an input array using
3751 : ! a second array as needed by the stress fields.
3752 : ! This is just like 2DR8 except no averaging and only on tripole
3753 :
3754 0 : subroutine ice_HaloUpdate_stress(array1, array2, halo, &
3755 : fieldLoc, fieldKind, & ! LCOV_EXCL_LINE
3756 : fillValue)
3757 :
3758 : type (ice_halo), intent(in) :: &
3759 : halo ! precomputed halo structure containing all
3760 : ! information needed for halo update
3761 :
3762 : integer (int_kind), intent(in) :: &
3763 : fieldKind, &! id for type of field (scalar, vector, angle) ! LCOV_EXCL_LINE
3764 : fieldLoc ! id for location on horizontal grid
3765 : ! (center, NEcorner, Nface, Eface)
3766 :
3767 : real (dbl_kind), intent(in), optional :: &
3768 : fillValue ! optional value to put in ghost cells
3769 : ! where neighbor points are unknown
3770 : ! (e.g. eliminated land blocks or
3771 : ! closed boundaries)
3772 :
3773 : real (dbl_kind), dimension(:,:,:), intent(inout) :: &
3774 : array1 ,& ! array containing field for which halo ! LCOV_EXCL_LINE
3775 : ! needs to be updated
3776 : array2 ! array containing field for which halo
3777 : ! in array1 needs to be updated
3778 :
3779 : ! local variables
3780 :
3781 : integer (int_kind) :: &
3782 : nmsg, &! dummy loop indices ! LCOV_EXCL_LINE
3783 : nxGlobal, &! global domain size in x (tripole) ! LCOV_EXCL_LINE
3784 : iSrc,jSrc, &! source addresses for message ! LCOV_EXCL_LINE
3785 : iDst,jDst, &! dest addresses for message ! LCOV_EXCL_LINE
3786 : srcBlock, &! local block number for source ! LCOV_EXCL_LINE
3787 : dstBlock, &! local block number for destination ! LCOV_EXCL_LINE
3788 : ioffset, joffset, &! address shifts for tripole ! LCOV_EXCL_LINE
3789 : isign ! sign factor for tripole grids
3790 :
3791 : real (dbl_kind) :: &
3792 : fill ! value to use for unknown points
3793 :
3794 : character(len=*), parameter :: subname = '(ice_HaloUpdate_stress)'
3795 :
3796 : !-----------------------------------------------------------------------
3797 : !
3798 : ! abort or return on unknown or noupdate field_loc or field_type
3799 : !
3800 : !-----------------------------------------------------------------------
3801 :
3802 0 : if (fieldLoc == field_loc_unknown .or. &
3803 : fieldKind == field_type_unknown) then
3804 0 : call abort_ice(subname//'ERROR: use of field_loc/type_unknown not allowed')
3805 0 : return
3806 : endif
3807 :
3808 0 : if (fieldLoc == field_loc_noupdate .or. &
3809 : fieldKind == field_type_noupdate) then
3810 0 : return
3811 : endif
3812 :
3813 : !-----------------------------------------------------------------------
3814 : !
3815 : ! initialize error code and fill value
3816 : !
3817 : !-----------------------------------------------------------------------
3818 :
3819 0 : if (present(fillValue)) then
3820 0 : fill = fillValue
3821 : else
3822 0 : fill = 0.0_dbl_kind
3823 : endif
3824 :
3825 0 : nxGlobal = 0
3826 0 : if (allocated(bufTripoleR8)) then
3827 0 : nxGlobal = size(bufTripoleR8,dim=1)
3828 0 : bufTripoleR8 = fill
3829 : endif
3830 :
3831 : !-----------------------------------------------------------------------
3832 : !
3833 : ! do NOT zero the halo out, this halo update just updates
3834 : ! the tripole zipper as needed for stresses. if you zero
3835 : ! it out, all halo values will be wiped out.
3836 : !-----------------------------------------------------------------------
3837 : ! do iblk = 1, halo%numLocalBlocks
3838 : ! call get_block_parameter(halo%blockGlobalID(iblk), &
3839 : ! ilo=ilo, ihi=ihi, & ! LCOV_EXCL_LINE
3840 : ! jlo=jlo, jhi=jhi)
3841 : ! do j = 1,nghost
3842 : ! array(1:nx_block, jlo-j,iblk) = fill
3843 : ! array(1:nx_block, jhi+j,iblk) = fill
3844 : ! enddo
3845 : ! do i = 1,nghost
3846 : ! array(ilo-i, 1:ny_block,iblk) = fill
3847 : ! array(ihi+i, 1:ny_block,iblk) = fill
3848 : ! enddo
3849 : ! enddo
3850 :
3851 : !-----------------------------------------------------------------------
3852 : !
3853 : ! do local copies
3854 : ! if srcBlock is zero, that denotes an eliminated land block or a
3855 : ! closed boundary where ghost cell values are undefined
3856 : ! if srcBlock is less than zero, the message is a copy out of the
3857 : ! tripole buffer and will be treated later
3858 : !
3859 : !-----------------------------------------------------------------------
3860 :
3861 0 : do nmsg=1,halo%numLocalCopies
3862 0 : iSrc = halo%srcLocalAddr(1,nmsg)
3863 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3864 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3865 0 : iDst = halo%dstLocalAddr(1,nmsg)
3866 0 : jDst = halo%dstLocalAddr(2,nmsg)
3867 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3868 :
3869 0 : if (srcBlock > 0) then
3870 0 : if (dstBlock < 0) then ! tripole copy into buffer
3871 : bufTripoleR8(iDst,jDst) = &
3872 0 : array2(iSrc,jSrc,srcBlock)
3873 : endif
3874 0 : else if (srcBlock == 0) then
3875 0 : array1(iDst,jDst,dstBlock) = fill
3876 : endif
3877 : end do
3878 :
3879 : !-----------------------------------------------------------------------
3880 : !
3881 : ! take care of northern boundary in tripole case
3882 : ! bufTripole array contains the top haloWidth+1 rows of physical
3883 : ! domain for entire (global) top row
3884 : !
3885 : !-----------------------------------------------------------------------
3886 :
3887 0 : if (nxGlobal > 0) then
3888 :
3889 0 : select case (fieldKind)
3890 : case (field_type_scalar)
3891 0 : isign = 1
3892 : case (field_type_vector)
3893 0 : isign = -1
3894 : case (field_type_angle)
3895 0 : isign = -1
3896 : case default
3897 0 : call abort_ice(subname//'ERROR: Unknown field kind')
3898 : end select
3899 :
3900 0 : if (halo%tripoleTFlag) then
3901 :
3902 0 : select case (fieldLoc)
3903 : case (field_loc_center) ! cell center location
3904 :
3905 0 : ioffset = -1
3906 0 : joffset = 0
3907 :
3908 : case (field_loc_NEcorner) ! cell corner location
3909 :
3910 0 : ioffset = 0
3911 0 : joffset = 1
3912 :
3913 : case (field_loc_Eface) ! cell center location
3914 :
3915 0 : ioffset = 0
3916 0 : joffset = 0
3917 :
3918 : case (field_loc_Nface) ! cell corner (velocity) location
3919 :
3920 0 : ioffset = -1
3921 0 : joffset = 1
3922 :
3923 : case default
3924 0 : call abort_ice(subname//'ERROR: Unknown field location')
3925 : end select
3926 :
3927 : else ! tripole u-fold
3928 :
3929 0 : select case (fieldLoc)
3930 : case (field_loc_center) ! cell center location
3931 :
3932 0 : ioffset = 0
3933 0 : joffset = 0
3934 :
3935 : case (field_loc_NEcorner) ! cell corner location
3936 :
3937 0 : ioffset = 1
3938 0 : joffset = 1
3939 :
3940 : case (field_loc_Eface)
3941 :
3942 0 : ioffset = 1
3943 0 : joffset = 0
3944 :
3945 : case (field_loc_Nface)
3946 :
3947 0 : ioffset = 0
3948 0 : joffset = 1
3949 :
3950 : case default
3951 0 : call abort_ice(subname//'ERROR: Unknown field location')
3952 : end select
3953 :
3954 : endif
3955 :
3956 : !*** copy out of global tripole buffer into local
3957 : !*** ghost cells
3958 :
3959 : !*** look through local copies to find the copy out
3960 : !*** messages (srcBlock < 0)
3961 :
3962 0 : do nmsg=1,halo%numLocalCopies
3963 0 : srcBlock = halo%srcLocalAddr(3,nmsg)
3964 :
3965 0 : if (srcBlock < 0) then
3966 :
3967 0 : iSrc = halo%srcLocalAddr(1,nmsg) ! tripole buffer addr
3968 0 : jSrc = halo%srcLocalAddr(2,nmsg)
3969 :
3970 0 : iDst = halo%dstLocalAddr(1,nmsg) ! local block addr
3971 0 : jDst = halo%dstLocalAddr(2,nmsg)
3972 0 : dstBlock = halo%dstLocalAddr(3,nmsg)
3973 :
3974 : !*** correct for offsets
3975 0 : iSrc = iSrc - ioffset
3976 0 : jSrc = jSrc - joffset
3977 0 : if (iSrc < 1 ) iSrc = iSrc + nxGlobal
3978 0 : if (iSrc > nxGlobal) iSrc = iSrc - nxGlobal
3979 :
3980 : !*** for center and Eface, do not need to replace
3981 : !*** top row of physical domain, so jSrc should be
3982 : !*** out of range and skipped
3983 : !*** otherwise do the copy
3984 :
3985 0 : if (jSrc <= halo%tripoleRows .and. jSrc>0 .and. jDst>0) then
3986 0 : array1(iDst,jDst,dstBlock) = isign*bufTripoleR8(iSrc,jSrc)
3987 : endif
3988 :
3989 : endif
3990 : end do
3991 :
3992 : endif
3993 :
3994 : !-----------------------------------------------------------------------
3995 :
3996 : end subroutine ice_HaloUpdate_stress
3997 :
3998 : !***********************************************************************
3999 :
4000 8 : subroutine ice_HaloIncrementMsgCount(sndCounter, rcvCounter, &
4001 : srcProc, dstProc, msgSize)
4002 :
4003 : ! This is a utility routine to increment the arrays for counting
4004 : ! whether messages are required. It checks the source and destination
4005 : ! task to see whether the current task needs to send, receive or
4006 : ! copy messages to fill halo regions (ghost cells).
4007 :
4008 : integer (int_kind), intent(in) :: &
4009 : srcProc, &! source processor for communication ! LCOV_EXCL_LINE
4010 : dstProc, &! destination processor for communication ! LCOV_EXCL_LINE
4011 : msgSize ! number of words for this message
4012 :
4013 : integer (int_kind), dimension(:), intent(inout) :: &
4014 : sndCounter, &! array for counting messages to be sent ! LCOV_EXCL_LINE
4015 : rcvCounter ! array for counting messages to be received
4016 :
4017 : character(len=*), parameter :: subname = '(ice_HaloIncrementMsgCount)'
4018 :
4019 : !-----------------------------------------------------------------------
4020 : !
4021 : ! error check
4022 : !
4023 : !-----------------------------------------------------------------------
4024 :
4025 : if (srcProc < 0 .or. dstProc < 0 .or. &
4026 : srcProc > size(sndCounter) .or. & ! LCOV_EXCL_LINE
4027 : dstProc > size(rcvCounter)) then
4028 0 : call abort_ice(subname//'ERROR: invalid processor number')
4029 0 : return
4030 : endif
4031 :
4032 : !-----------------------------------------------------------------------
4033 : !
4034 : ! if destination all land or outside closed boundary (dstProc = 0),
4035 : ! then no send is necessary, so do the rest only for dstProc /= 0
4036 : !
4037 : !-----------------------------------------------------------------------
4038 :
4039 8 : if (dstProc == 0) return
4040 :
4041 : !-----------------------------------------------------------------------
4042 : !
4043 : ! if the current processor is the source, must send data
4044 : ! local copy if dstProc = srcProc
4045 : !
4046 : !-----------------------------------------------------------------------
4047 :
4048 2 : if (srcProc == my_task + 1) sndCounter(dstProc) = &
4049 2 : sndCounter(dstProc) + msgSize
4050 :
4051 : !-----------------------------------------------------------------------
4052 : !
4053 : ! if the current processor is the destination, must receive data
4054 : ! local copy if dstProc = srcProc
4055 : !
4056 : !-----------------------------------------------------------------------
4057 :
4058 2 : if (dstProc == my_task + 1) then
4059 :
4060 2 : if (srcProc > 0) then
4061 : !*** the source block has ocean points
4062 : !*** count as a receive from srcProc
4063 :
4064 2 : rcvCounter(srcProc) = rcvCounter(srcProc) + msgSize
4065 :
4066 : else
4067 : !*** if the source block has been dropped, create
4068 : !*** a local copy to fill halo with a fill value
4069 :
4070 0 : rcvCounter(dstProc) = rcvCounter(dstProc) + msgSize
4071 :
4072 : endif
4073 : endif
4074 : !-----------------------------------------------------------------------
4075 :
4076 : end subroutine ice_HaloIncrementMsgCount
4077 :
4078 : !***********************************************************************
4079 :
4080 8 : subroutine ice_HaloMsgCreate(halo, dist, srcBlock, dstBlock, direction)
4081 :
4082 : ! This is a utility routine to determine the required address and
4083 : ! message information for a particular pair of blocks.
4084 :
4085 : type (distrb), intent(in) :: &
4086 : dist ! distribution of blocks across procs
4087 :
4088 : integer (int_kind), intent(in) :: &
4089 : srcBlock, dstBlock ! source,destination block id
4090 :
4091 : character (*), intent(in) :: &
4092 : direction ! direction of neighbor block
4093 : ! (north,south,east,west,
4094 : ! and NE, NW, SE, SW)
4095 :
4096 : type (ice_halo), intent(inout) :: &
4097 : halo ! data structure containing halo info
4098 :
4099 : !-----------------------------------------------------------------------
4100 : !
4101 : ! local variables
4102 : !
4103 : !-----------------------------------------------------------------------
4104 :
4105 : integer (int_kind) :: &
4106 : srcProc, srcLocalID, &! source block location in distribution ! LCOV_EXCL_LINE
4107 : dstProc, dstLocalID, &! source block location in distribution ! LCOV_EXCL_LINE
4108 : msgIndx, &! message counter and index into msg array ! LCOV_EXCL_LINE
4109 : ibSrc, ieSrc, jbSrc, jeSrc, &! phys domain info for source block ! LCOV_EXCL_LINE
4110 : ibDst, ieDst, jbDst, jeDst, &! phys domain info for dest block ! LCOV_EXCL_LINE
4111 : nxGlobal, &! size of global domain in e-w direction ! LCOV_EXCL_LINE
4112 : i,j ! dummy loop index
4113 :
4114 : integer (int_kind), dimension(:), pointer :: &
4115 : iGlobal ! global i index for location in tripole
4116 :
4117 : character(len=*), parameter :: subname = '(ice_HaloMsgCreate)'
4118 :
4119 : !-----------------------------------------------------------------------
4120 : !
4121 : ! initialize
4122 : !
4123 : !-----------------------------------------------------------------------
4124 :
4125 0 : if (allocated(bufTripoleR8)) nxGlobal = size(bufTripoleR8,dim=1)
4126 :
4127 : !-----------------------------------------------------------------------
4128 : !
4129 : ! find source and destination block locations
4130 : !
4131 : !-----------------------------------------------------------------------
4132 :
4133 8 : if (srcBlock /= 0) then
4134 : call ice_DistributionGetBlockLoc(dist, abs(srcBlock), srcProc, &
4135 8 : srcLocalID)
4136 : else
4137 0 : srcProc = 0
4138 0 : srcLocalID = 0
4139 : endif
4140 :
4141 8 : if (dstBlock /= 0) then
4142 : call ice_DistributionGetBlockLoc(dist, abs(dstBlock), dstProc, &
4143 2 : dstLocalID)
4144 : else
4145 6 : dstProc = 0
4146 6 : dstLocalID = 0
4147 : endif
4148 :
4149 : !-----------------------------------------------------------------------
4150 : !
4151 : ! if destination all land or outside closed boundary (dstProc = 0),
4152 : ! then no send is necessary, so do the rest only for dstProc /= 0
4153 : !
4154 : !-----------------------------------------------------------------------
4155 :
4156 8 : if (dstProc == 0) return
4157 :
4158 : !-----------------------------------------------------------------------
4159 : !
4160 : ! get block information if either block is local
4161 : !
4162 : !-----------------------------------------------------------------------
4163 :
4164 2 : if (srcProc == my_task+1 .or. dstProc == my_task+1) then
4165 :
4166 2 : if (srcBlock >= 0 .and. dstBlock >= 0) then
4167 : call get_block_parameter(srcBlock, &
4168 : ilo=ibSrc, ihi=ieSrc, & ! LCOV_EXCL_LINE
4169 2 : jlo=jbSrc, jhi=jeSrc)
4170 : else ! tripole - need iGlobal info
4171 : call get_block_parameter(abs(srcBlock), &
4172 : ilo=ibSrc, ihi=ieSrc, & ! LCOV_EXCL_LINE
4173 : jlo=jbSrc, jhi=jeSrc, & ! LCOV_EXCL_LINE
4174 0 : i_glob=iGlobal)
4175 :
4176 : endif
4177 :
4178 2 : if (dstBlock /= 0) then
4179 : call get_block_parameter(abs(dstBlock), &
4180 : ilo=ibDst, ihi=ieDst, & ! LCOV_EXCL_LINE
4181 2 : jlo=jbDst, jhi=jeDst)
4182 : endif
4183 :
4184 : endif
4185 :
4186 : !-----------------------------------------------------------------------
4187 : !
4188 : ! if both blocks are local, create a local copy to fill halo
4189 : !
4190 : !-----------------------------------------------------------------------
4191 :
4192 2 : if (srcProc == my_task+1 .and. &
4193 : dstProc == my_task+1) then
4194 :
4195 : !*** compute addresses based on direction
4196 :
4197 1 : select case (direction)
4198 : case ('east')
4199 :
4200 : !*** copy easternmost physical domain of src
4201 : !*** into westernmost halo of dst
4202 :
4203 1 : msgIndx = halo%numLocalCopies
4204 :
4205 117 : do j=1,jeSrc-jbSrc+1
4206 233 : do i=1,nghost
4207 :
4208 116 : msgIndx = msgIndx + 1
4209 :
4210 116 : halo%srcLocalAddr(1,msgIndx) = ieSrc - nghost + i
4211 116 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
4212 116 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4213 :
4214 116 : halo%dstLocalAddr(1,msgIndx) = i
4215 116 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
4216 232 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4217 :
4218 : end do
4219 : end do
4220 :
4221 1 : halo%numLocalCopies = msgIndx
4222 :
4223 : case ('west')
4224 :
4225 : !*** copy westernmost physical domain of src
4226 : !*** into easternmost halo of dst
4227 :
4228 1 : msgIndx = halo%numLocalCopies
4229 :
4230 117 : do j=1,jeSrc-jbSrc+1
4231 233 : do i=1,nghost
4232 :
4233 116 : msgIndx = msgIndx + 1
4234 :
4235 116 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4236 116 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
4237 116 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4238 :
4239 116 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
4240 116 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
4241 232 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4242 :
4243 : end do
4244 : end do
4245 :
4246 1 : halo%numLocalCopies = msgIndx
4247 :
4248 : case ('north')
4249 :
4250 : !*** copy northern physical domain of src
4251 : !*** into southern halo of dst
4252 :
4253 0 : if (srcBlock > 0 .and. dstBlock > 0) then ! normal north boundary
4254 :
4255 0 : msgIndx = halo%numLocalCopies
4256 :
4257 0 : do j=1,nghost
4258 0 : do i=1,ieSrc-ibSrc+1
4259 :
4260 0 : msgIndx = msgIndx + 1
4261 :
4262 0 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4263 0 : halo%srcLocalAddr(2,msgIndx) = jeSrc - nghost + j
4264 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4265 :
4266 0 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
4267 0 : halo%dstLocalAddr(2,msgIndx) = j
4268 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4269 :
4270 : end do
4271 : end do
4272 :
4273 0 : halo%numLocalCopies = msgIndx
4274 :
4275 0 : else if (srcBlock > 0 .and. dstBlock < 0) then
4276 :
4277 : !*** tripole grid - copy info into tripole buffer
4278 : !*** copy physical domain of top halo+1 rows
4279 : !*** into global buffer at src location
4280 :
4281 : !*** perform an error check to make sure the
4282 : !*** block has enough points to perform a tripole
4283 : !*** update
4284 :
4285 0 : if (jeSrc - jbSrc + 1 < halo%tripoleRows) then
4286 0 : call abort_ice(subname//'ERROR: not enough points in block for tripole')
4287 0 : return
4288 : endif
4289 :
4290 0 : msgIndx = halo%numLocalCopies
4291 :
4292 0 : do j=1,halo%tripoleRows
4293 0 : do i=1,ieSrc-ibSrc+1
4294 :
4295 0 : msgIndx = msgIndx + 1
4296 :
4297 0 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4298 0 : halo%srcLocalAddr(2,msgIndx) = jeSrc-halo%tripoleRows+j
4299 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4300 :
4301 0 : halo%dstLocalAddr(1,msgIndx) = iGlobal(ibSrc + i - 1)
4302 0 : halo%dstLocalAddr(2,msgIndx) = j
4303 0 : halo%dstLocalAddr(3,msgIndx) = -dstLocalID
4304 :
4305 : end do
4306 : end do
4307 :
4308 0 : halo%numLocalCopies = msgIndx
4309 :
4310 0 : else if (srcBlock < 0 .and. dstBlock > 0) then
4311 :
4312 : !*** tripole grid - set up for copying out of
4313 : !*** tripole buffer into ghost cell domains
4314 : !*** include e-w ghost cells
4315 :
4316 0 : msgIndx = halo%numLocalCopies
4317 :
4318 0 : do j=1,halo%tripoleRows
4319 0 : do i=1,ieSrc+nghost
4320 :
4321 0 : msgIndx = msgIndx + 1
4322 :
4323 0 : halo%srcLocalAddr(1,msgIndx) = nxGlobal - iGlobal(i) + 1
4324 0 : halo%srcLocalAddr(2,msgIndx) = nghost + 3 - j
4325 0 : halo%srcLocalAddr(3,msgIndx) = -srcLocalID
4326 :
4327 0 : halo%dstLocalAddr(1,msgIndx) = i
4328 0 : if (j.gt.nghost+1) then
4329 0 : halo%dstLocalAddr(2,msgIndx) = -1 ! never used
4330 : else
4331 0 : halo%dstLocalAddr(2,msgIndx) = jeSrc + j - 1
4332 : endif
4333 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4334 :
4335 : end do
4336 : end do
4337 :
4338 0 : halo%numLocalCopies = msgIndx
4339 :
4340 : endif
4341 :
4342 : case ('south')
4343 :
4344 : !*** copy southern physical domain of src
4345 : !*** into northern halo of dst
4346 :
4347 0 : msgIndx = halo%numLocalCopies
4348 :
4349 0 : do j=1,nghost
4350 0 : do i=1,ieSrc-ibSrc+1
4351 :
4352 0 : msgIndx = msgIndx + 1
4353 :
4354 0 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4355 0 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
4356 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4357 :
4358 0 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
4359 0 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
4360 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4361 :
4362 : end do
4363 : end do
4364 :
4365 0 : halo%numLocalCopies = msgIndx
4366 :
4367 : case ('northeast')
4368 :
4369 : !*** normal northeast boundary - just copy NE corner
4370 : !*** of physical domain into SW halo of NE nbr block
4371 :
4372 0 : if (dstBlock > 0) then
4373 :
4374 0 : msgIndx = halo%numLocalCopies
4375 :
4376 0 : do j=1,nghost
4377 0 : do i=1,nghost
4378 :
4379 0 : msgIndx = msgIndx + 1
4380 :
4381 0 : halo%srcLocalAddr(1,msgIndx) = ieSrc - nghost + i
4382 0 : halo%srcLocalAddr(2,msgIndx) = jeSrc - nghost + j
4383 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4384 :
4385 0 : halo%dstLocalAddr(1,msgIndx) = i
4386 0 : halo%dstLocalAddr(2,msgIndx) = j
4387 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4388 :
4389 : end do
4390 : end do
4391 :
4392 0 : halo%numLocalCopies = msgIndx
4393 :
4394 : ! tcx,tcraig, 3/2023, this is not needed
4395 : ! else
4396 : !
4397 : ! !*** tripole grid - copy entire top halo+1
4398 : ! !*** rows into global buffer at src location
4399 : !
4400 : ! msgIndx = halo%numLocalCopies
4401 : !
4402 : ! do j=1,nghost+1
4403 : ! do i=1,ieSrc-ibSrc+1
4404 : !
4405 : ! msgIndx = msgIndx + 1
4406 : !
4407 : ! halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4408 : ! halo%srcLocalAddr(2,msgIndx) = jeSrc-1-nghost+j
4409 : ! halo%srcLocalAddr(3,msgIndx) = srcLocalID
4410 : !
4411 : ! halo%dstLocalAddr(1,msgIndx) = iGlobal(ibSrc + i - 1)
4412 : ! halo%dstLocalAddr(2,msgIndx) = j
4413 : ! halo%dstLocalAddr(3,msgIndx) = -dstLocalID
4414 : !
4415 : ! end do
4416 : ! end do
4417 : !
4418 : ! halo%numLocalCopies = msgIndx
4419 :
4420 : endif
4421 :
4422 : case ('northwest')
4423 :
4424 : !*** normal northwest boundary - just copy NW corner
4425 : !*** of physical domain into SE halo of NW nbr block
4426 :
4427 0 : if (dstBlock > 0) then
4428 :
4429 0 : msgIndx = halo%numLocalCopies
4430 :
4431 0 : do j=1,nghost
4432 0 : do i=1,nghost
4433 :
4434 0 : msgIndx = msgIndx + 1
4435 :
4436 0 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4437 0 : halo%srcLocalAddr(2,msgIndx) = jeSrc - nghost + j
4438 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4439 :
4440 0 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
4441 0 : halo%dstLocalAddr(2,msgIndx) = j
4442 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4443 :
4444 : end do
4445 : end do
4446 :
4447 0 : halo%numLocalCopies = msgIndx
4448 :
4449 : ! tcx,tcraig, 3/2023, this is not needed
4450 : ! else
4451 : !
4452 : ! !*** tripole grid - copy entire top halo+1
4453 : ! !*** rows into global buffer at src location
4454 : !
4455 : ! msgIndx = halo%numLocalCopies
4456 : !
4457 : ! do j=1,nghost+1
4458 : ! do i=1,ieSrc-ibSrc+1
4459 : !
4460 : ! msgIndx = msgIndx + 1
4461 : !
4462 : ! halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4463 : ! halo%srcLocalAddr(2,msgIndx) = jeSrc-1-nghost+j
4464 : ! halo%srcLocalAddr(3,msgIndx) = srcLocalID
4465 : !
4466 : ! halo%dstLocalAddr(1,msgIndx) = iGlobal(ibSrc + i - 1)
4467 : ! halo%dstLocalAddr(2,msgIndx) = j
4468 : ! halo%dstLocalAddr(3,msgIndx) = -dstLocalID
4469 : !
4470 : ! end do
4471 : ! end do
4472 : !
4473 : ! halo%numLocalCopies = msgIndx
4474 :
4475 : endif
4476 :
4477 : case ('southeast')
4478 :
4479 : !*** copy southeastern corner of src physical domain
4480 : !*** into northwestern halo of dst
4481 :
4482 0 : msgIndx = halo%numLocalCopies
4483 :
4484 0 : do j=1,nghost
4485 0 : do i=1,nghost
4486 :
4487 0 : msgIndx = msgIndx + 1
4488 :
4489 0 : halo%srcLocalAddr(1,msgIndx) = ieSrc - nghost + i
4490 0 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
4491 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4492 :
4493 0 : halo%dstLocalAddr(1,msgIndx) = i
4494 0 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
4495 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4496 :
4497 : end do
4498 : end do
4499 :
4500 0 : halo%numLocalCopies = msgIndx
4501 :
4502 : case ('southwest')
4503 :
4504 : !*** copy southwestern corner of src physical domain
4505 : !*** into northeastern halo of dst
4506 :
4507 0 : msgIndx = halo%numLocalCopies
4508 :
4509 0 : do j=1,nghost
4510 0 : do i=1,nghost
4511 :
4512 0 : msgIndx = msgIndx + 1
4513 :
4514 0 : halo%srcLocalAddr(1,msgIndx) = ibSrc + i - 1
4515 0 : halo%srcLocalAddr(2,msgIndx) = jbSrc + j - 1
4516 0 : halo%srcLocalAddr(3,msgIndx) = srcLocalID
4517 :
4518 0 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
4519 0 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
4520 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4521 :
4522 : end do
4523 : end do
4524 :
4525 0 : halo%numLocalCopies = msgIndx
4526 :
4527 : case default
4528 :
4529 0 : call abort_ice(subname//'ERROR: unknown direction local copy')
4530 2 : return
4531 :
4532 : end select
4533 :
4534 : !-----------------------------------------------------------------------
4535 : !
4536 : ! if dest block is local and source block does not exist, create a
4537 : ! local copy to fill halo with a fill value
4538 : !
4539 : !-----------------------------------------------------------------------
4540 :
4541 0 : else if (srcProc == 0 .and. dstProc == my_task+1) then
4542 :
4543 : !*** compute addresses based on direction
4544 :
4545 0 : select case (direction)
4546 : case ('east')
4547 :
4548 : !*** copy easternmost physical domain of src
4549 : !*** into westernmost halo of dst
4550 :
4551 0 : msgIndx = halo%numLocalCopies
4552 :
4553 0 : do j=1,jeSrc-jbSrc+1
4554 0 : do i=1,nghost
4555 :
4556 0 : msgIndx = msgIndx + 1
4557 :
4558 0 : halo%srcLocalAddr(1,msgIndx) = 0
4559 0 : halo%srcLocalAddr(2,msgIndx) = 0
4560 0 : halo%srcLocalAddr(3,msgIndx) = 0
4561 :
4562 0 : halo%dstLocalAddr(1,msgIndx) = i
4563 0 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
4564 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4565 :
4566 : end do
4567 : end do
4568 :
4569 0 : halo%numLocalCopies = msgIndx
4570 :
4571 : case ('west')
4572 :
4573 : !*** copy westernmost physical domain of src
4574 : !*** into easternmost halo of dst
4575 :
4576 0 : msgIndx = halo%numLocalCopies
4577 :
4578 0 : do j=1,jeSrc-jbSrc+1
4579 0 : do i=1,nghost
4580 :
4581 0 : msgIndx = msgIndx + 1
4582 :
4583 0 : halo%srcLocalAddr(1,msgIndx) = 0
4584 0 : halo%srcLocalAddr(2,msgIndx) = 0
4585 0 : halo%srcLocalAddr(3,msgIndx) = 0
4586 :
4587 0 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
4588 0 : halo%dstLocalAddr(2,msgIndx) = jbDst + j - 1
4589 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4590 :
4591 : end do
4592 : end do
4593 :
4594 0 : halo%numLocalCopies = msgIndx
4595 :
4596 : case ('north')
4597 :
4598 : !*** copy northern physical domain of src
4599 : !*** into southern halo of dst
4600 :
4601 0 : if (dstBlock > 0) then ! normal north boundary
4602 :
4603 0 : msgIndx = halo%numLocalCopies
4604 :
4605 0 : do j=1,nghost
4606 0 : do i=1,ieSrc-ibSrc+1
4607 :
4608 0 : msgIndx = msgIndx + 1
4609 :
4610 0 : halo%srcLocalAddr(1,msgIndx) = 0
4611 0 : halo%srcLocalAddr(2,msgIndx) = 0
4612 0 : halo%srcLocalAddr(3,msgIndx) = 0
4613 :
4614 0 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
4615 0 : halo%dstLocalAddr(2,msgIndx) = j
4616 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4617 :
4618 : end do
4619 : end do
4620 :
4621 0 : halo%numLocalCopies = msgIndx
4622 :
4623 : endif
4624 :
4625 : case ('south')
4626 :
4627 : !*** copy southern physical domain of src
4628 : !*** into northern halo of dst
4629 :
4630 0 : msgIndx = halo%numLocalCopies
4631 :
4632 0 : do j=1,nghost
4633 0 : do i=1,ieSrc-ibSrc+1
4634 :
4635 0 : msgIndx = msgIndx + 1
4636 :
4637 0 : halo%srcLocalAddr(1,msgIndx) = 0
4638 0 : halo%srcLocalAddr(2,msgIndx) = 0
4639 0 : halo%srcLocalAddr(3,msgIndx) = 0
4640 :
4641 0 : halo%dstLocalAddr(1,msgIndx) = ibDst + i - 1
4642 0 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
4643 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4644 :
4645 : end do
4646 : end do
4647 :
4648 0 : halo%numLocalCopies = msgIndx
4649 :
4650 : case ('northeast')
4651 :
4652 : !*** normal northeast boundary - just copy NE corner
4653 : !*** of physical domain into SW halo of NE nbr block
4654 :
4655 0 : if (dstBlock > 0) then
4656 :
4657 0 : msgIndx = halo%numLocalCopies
4658 :
4659 0 : do j=1,nghost
4660 0 : do i=1,nghost
4661 :
4662 0 : msgIndx = msgIndx + 1
4663 :
4664 0 : halo%srcLocalAddr(1,msgIndx) = 0
4665 0 : halo%srcLocalAddr(2,msgIndx) = 0
4666 0 : halo%srcLocalAddr(3,msgIndx) = 0
4667 :
4668 0 : halo%dstLocalAddr(1,msgIndx) = i
4669 0 : halo%dstLocalAddr(2,msgIndx) = j
4670 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4671 :
4672 : end do
4673 : end do
4674 :
4675 0 : halo%numLocalCopies = msgIndx
4676 :
4677 : endif
4678 :
4679 : case ('northwest')
4680 :
4681 : !*** normal northwest boundary - just copy NW corner
4682 : !*** of physical domain into SE halo of NW nbr block
4683 :
4684 0 : if (dstBlock > 0) then
4685 :
4686 0 : msgIndx = halo%numLocalCopies
4687 :
4688 0 : do j=1,nghost
4689 0 : do i=1,nghost
4690 :
4691 0 : msgIndx = msgIndx + 1
4692 :
4693 0 : halo%srcLocalAddr(1,msgIndx) = 0
4694 0 : halo%srcLocalAddr(2,msgIndx) = 0
4695 0 : halo%srcLocalAddr(3,msgIndx) = 0
4696 :
4697 0 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
4698 0 : halo%dstLocalAddr(2,msgIndx) = j
4699 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4700 :
4701 : end do
4702 : end do
4703 :
4704 0 : halo%numLocalCopies = msgIndx
4705 :
4706 : endif
4707 :
4708 : case ('southeast')
4709 :
4710 : !*** copy southeastern corner of src physical domain
4711 : !*** into northwestern halo of dst
4712 :
4713 0 : msgIndx = halo%numLocalCopies
4714 :
4715 0 : do j=1,nghost
4716 0 : do i=1,nghost
4717 :
4718 0 : msgIndx = msgIndx + 1
4719 :
4720 0 : halo%srcLocalAddr(1,msgIndx) = 0
4721 0 : halo%srcLocalAddr(2,msgIndx) = 0
4722 0 : halo%srcLocalAddr(3,msgIndx) = 0
4723 :
4724 0 : halo%dstLocalAddr(1,msgIndx) = i
4725 0 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
4726 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4727 :
4728 : end do
4729 : end do
4730 :
4731 0 : halo%numLocalCopies = msgIndx
4732 :
4733 : case ('southwest')
4734 :
4735 : !*** copy southwestern corner of src physical domain
4736 : !*** into northeastern halo of dst
4737 :
4738 0 : msgIndx = halo%numLocalCopies
4739 :
4740 0 : do j=1,nghost
4741 0 : do i=1,nghost
4742 :
4743 0 : msgIndx = msgIndx + 1
4744 :
4745 0 : halo%srcLocalAddr(1,msgIndx) = 0
4746 0 : halo%srcLocalAddr(2,msgIndx) = 0
4747 0 : halo%srcLocalAddr(3,msgIndx) = 0
4748 :
4749 0 : halo%dstLocalAddr(1,msgIndx) = ieDst + i
4750 0 : halo%dstLocalAddr(2,msgIndx) = jeDst + j
4751 0 : halo%dstLocalAddr(3,msgIndx) = dstLocalID
4752 :
4753 : end do
4754 : end do
4755 :
4756 0 : halo%numLocalCopies = msgIndx
4757 :
4758 : case default
4759 :
4760 0 : call abort_ice(subname//'ERROR: unknown direction local copy')
4761 0 : return
4762 :
4763 : end select
4764 :
4765 : !-----------------------------------------------------------------------
4766 : !
4767 : ! if none of the cases above, no message info required for this
4768 : ! block pair
4769 : !
4770 : !-----------------------------------------------------------------------
4771 :
4772 : endif
4773 :
4774 : !-----------------------------------------------------------------------
4775 :
4776 8 : end subroutine ice_HaloMsgCreate
4777 :
4778 : !***********************************************************************
4779 :
4780 8 : subroutine ice_HaloExtrapolate2DR8(ARRAY,dist,ew_bndy_type,ns_bndy_type)
4781 :
4782 : ! This subroutine extrapolates ARRAY values into the first row or column
4783 : ! of ghost cells, and is intended for grid variables whose ghost cells
4784 : ! would otherwise be set using the default boundary conditions (Dirichlet
4785 : ! or Neumann).
4786 : ! Note: This routine will need to be modified for nghost > 1.
4787 : ! We assume padding occurs only on east and north edges.
4788 : !
4789 : ! This is the specific interface for double precision arrays
4790 : ! corresponding to the generic interface ice_HaloExtrapolate
4791 :
4792 : use ice_blocks, only: block, nblocks_x, nblocks_y, get_block
4793 : use ice_constants, only: c2
4794 : use ice_distribution, only: ice_distributionGetBlockID
4795 :
4796 : character (char_len) :: &
4797 : ew_bndy_type, &! type of domain bndy in each logical ! LCOV_EXCL_LINE
4798 : ns_bndy_type ! direction (ew is i, ns is j)
4799 :
4800 : type (distrb), intent(in) :: &
4801 : dist ! block distribution for array X
4802 :
4803 : real (dbl_kind), dimension(:,:,:), intent(inout) :: &
4804 : ARRAY ! array containing distributed field
4805 :
4806 : !-----------------------------------------------------------------------
4807 : !
4808 : ! local variables
4809 : !
4810 : !-----------------------------------------------------------------------
4811 :
4812 : integer (int_kind) :: &
4813 : i,j,iblk, &! dummy loop indices ! LCOV_EXCL_LINE
4814 : numBlocks, &! number of local blocks ! LCOV_EXCL_LINE
4815 : blockID, &! block location ! LCOV_EXCL_LINE
4816 : ibc ! ghost cell column or row
4817 :
4818 : type (block) :: &
4819 : this_block ! block info for current block
4820 :
4821 : character(len=*), parameter :: subname = '(ice_HaloExtrapolate2DR8)'
4822 :
4823 : !-----------------------------------------------------------------------
4824 : !
4825 : ! Linear extrapolation
4826 : !
4827 : !-----------------------------------------------------------------------
4828 :
4829 : call ice_distributionGet(dist, &
4830 8 : numLocalBlocks = numBlocks)
4831 :
4832 16 : do iblk = 1, numBlocks
4833 8 : call ice_distributionGetBlockID(dist, iblk, blockID)
4834 8 : this_block = get_block(blockID, blockID)
4835 :
4836 8 : if (this_block%iblock == 1) then ! west edge
4837 8 : if (trim(ew_bndy_type) /= 'cyclic') then
4838 0 : do j = 1, ny_block
4839 0 : ARRAY(1,j,iblk) = c2*ARRAY(2,j,iblk) - ARRAY(3,j,iblk)
4840 : enddo
4841 : endif
4842 : endif
4843 :
4844 8 : if (this_block%iblock == nblocks_x) then ! east edge
4845 8 : if (trim(ew_bndy_type) /= 'cyclic') then
4846 : ! locate ghost cell column (avoid padding)
4847 0 : ibc = nx_block
4848 0 : do i = nx_block, nghost + 1, -1
4849 0 : if (this_block%i_glob(i) == 0) ibc = ibc - 1
4850 : enddo
4851 0 : do j = 1, ny_block
4852 0 : ARRAY(ibc,j,iblk) = c2*ARRAY(ibc-1,j,iblk) - ARRAY(ibc-2,j,iblk)
4853 : enddo
4854 : endif
4855 : endif
4856 :
4857 8 : if (this_block%jblock == 1) then ! south edge
4858 8 : if (trim(ns_bndy_type) /= 'cyclic') then
4859 824 : do i = 1, nx_block
4860 824 : ARRAY(i,1,iblk) = c2*ARRAY(i,2,iblk) - ARRAY(i,3,iblk)
4861 : enddo
4862 : endif
4863 : endif
4864 :
4865 24 : if (this_block%jblock == nblocks_y) then ! north edge
4866 : if (trim(ns_bndy_type) /= 'cyclic' .and. &
4867 : trim(ns_bndy_type) /= 'tripole' .and. & ! LCOV_EXCL_LINE
4868 : trim(ns_bndy_type) /= 'tripoleT' ) then
4869 : ! locate ghost cell column (avoid padding)
4870 8 : ibc = ny_block
4871 944 : do j = ny_block, nghost + 1, -1
4872 944 : if (this_block%j_glob(j) == 0) ibc = ibc - 1
4873 : enddo
4874 824 : do i = 1, nx_block
4875 824 : ARRAY(i,ibc,iblk) = c2*ARRAY(i,ibc-1,iblk) - ARRAY(i,ibc-2,iblk)
4876 : enddo
4877 : endif
4878 : endif
4879 :
4880 : enddo ! iblk
4881 :
4882 : !-----------------------------------------------------------------------
4883 :
4884 8 : end subroutine ice_HaloExtrapolate2DR8
4885 :
4886 : !***********************************************************************
4887 :
4888 0 : subroutine ice_HaloDestroy(halo)
4889 :
4890 : ! This routine creates a halo type with info necessary for
4891 : ! performing a halo (ghost cell) update. This info is computed
4892 : ! based on the input block distribution.
4893 :
4894 : type (ice_halo) :: &
4895 : halo ! a new halo type with info for halo updates
4896 :
4897 : integer (int_kind) :: &
4898 : istat ! error or status flag for MPI,alloc
4899 :
4900 : character(len=*), parameter :: subname = '(ice_HaloDestroy)'
4901 :
4902 : !-----------------------------------------------------------------------
4903 :
4904 : deallocate(halo%srcLocalAddr, &
4905 : halo%dstLocalAddr, & ! LCOV_EXCL_LINE
4906 0 : halo%blockGlobalID, stat=istat)
4907 :
4908 0 : if (istat > 0) then
4909 0 : call abort_ice(subname,' ERROR: deallocating')
4910 0 : return
4911 : endif
4912 :
4913 : end subroutine ice_HaloDestroy
4914 :
4915 : !***********************************************************************
4916 :
4917 0 : subroutine primary_grid_lengths_global_ext( &
4918 0 : ARRAY_O, ARRAY_I, ew_boundary_type, ns_boundary_type)
4919 :
4920 : ! This subroutine adds ghost cells to global primary grid lengths array
4921 : ! ARRAY_I and outputs result to array ARRAY_O
4922 :
4923 : use ice_constants, only: c0
4924 : use ice_domain_size, only: nx_global, ny_global
4925 :
4926 : real (kind=dbl_kind), dimension(:,:), intent(in) :: &
4927 : ARRAY_I
4928 :
4929 : character (*), intent(in) :: &
4930 : ew_boundary_type, ns_boundary_type
4931 :
4932 : real (kind=dbl_kind), dimension(:,:), intent(out) :: &
4933 : ARRAY_O
4934 :
4935 : !-----------------------------------------------------------------------
4936 : !
4937 : ! local variables
4938 : !
4939 : !-----------------------------------------------------------------------
4940 :
4941 : integer (kind=int_kind) :: &
4942 : ii, io, ji, jo
4943 :
4944 : character(len=*), parameter :: &
4945 : subname = '(primary_grid_lengths_global_ext)'
4946 :
4947 : !-----------------------------------------------------------------------
4948 : !
4949 : ! add ghost cells to global primary grid lengths array
4950 : !
4951 : !-----------------------------------------------------------------------
4952 :
4953 0 : if (trim(ns_boundary_type) == 'tripole' .or. &
4954 : trim(ns_boundary_type) == 'tripoleT') then
4955 : call abort_ice(subname//' ERROR: '//ns_boundary_type &
4956 0 : //' boundary type not implemented for configuration')
4957 : endif
4958 :
4959 0 : do jo = 1,ny_global+2*nghost
4960 0 : ji = -nghost + jo
4961 :
4962 : !*** Southern ghost cells
4963 :
4964 0 : if (ji < 1) then
4965 0 : select case (trim(ns_boundary_type))
4966 : case ('cyclic')
4967 0 : ji = ji + ny_global
4968 : case ('open')
4969 0 : ji = nghost - jo + 1
4970 : case ('closed')
4971 0 : ji = 0
4972 : case default
4973 : call abort_ice( &
4974 0 : subname//' ERROR: unknown north-south boundary type')
4975 : end select
4976 : endif
4977 :
4978 : !*** Northern ghost cells
4979 :
4980 0 : if (ji > ny_global) then
4981 0 : select case (trim(ns_boundary_type))
4982 : case ('cyclic')
4983 0 : ji = ji - ny_global
4984 : case ('open')
4985 0 : ji = 2 * ny_global - ji + 1
4986 : case ('closed')
4987 0 : ji = 0
4988 : case default
4989 : call abort_ice( &
4990 0 : subname//' ERROR: unknown north-south boundary type')
4991 : end select
4992 : endif
4993 :
4994 0 : do io = 1,nx_global+2*nghost
4995 0 : ii = -nghost + io
4996 :
4997 : !*** Western ghost cells
4998 :
4999 0 : if (ii < 1) then
5000 0 : select case (trim(ew_boundary_type))
5001 : case ('cyclic')
5002 0 : ii = ii + nx_global
5003 : case ('open')
5004 0 : ii = nghost - io + 1
5005 : case ('closed')
5006 0 : ii = 0
5007 : case default
5008 : call abort_ice( &
5009 0 : subname//' ERROR: unknown east-west boundary type')
5010 : end select
5011 : endif
5012 :
5013 : !*** Eastern ghost cells
5014 :
5015 0 : if (ii > nx_global) then
5016 0 : select case (trim(ew_boundary_type))
5017 : case ('cyclic')
5018 0 : ii = ii - nx_global
5019 : case ('open')
5020 0 : ii = 2 * nx_global - ii + 1
5021 : case ('closed')
5022 0 : ii = 0
5023 : case default
5024 : call abort_ice( &
5025 0 : subname//' ERROR: unknown east-west boundary type')
5026 : end select
5027 : endif
5028 :
5029 0 : if (ii == 0 .or. ji == 0) then
5030 0 : ARRAY_O(io, jo) = c0
5031 : else
5032 0 : ARRAY_O(io, jo) = ARRAY_I(ii, ji)
5033 : endif
5034 :
5035 : enddo
5036 : enddo
5037 :
5038 : !-----------------------------------------------------------------------
5039 :
5040 0 : end subroutine primary_grid_lengths_global_ext
5041 :
5042 : !***********************************************************************
5043 :
5044 0 : end module ice_boundary
5045 :
5046 : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|