@@ -591,29 +591,41 @@ subroutine floodFill_tropo(mesh, diag, pvuVal)
591591 ! (2) flood fill troposphere (<2pvu) from troposphere seeds near surface.
592592 !Somewhat paradoxically, the bottom of the stratosphere is lower than the top of the troposphere.
593593
594+ !Originally, it was assumed that each (MPI) domain would have >0 cells with "right" DT found by flood filling.
595+ !However, for "small" domains over the Arctic say during winter, the entire surface can be capped by high PV.
596+ !So, we need to communicate between domains during the flood fill or else we find the DT at the surface.
597+ !The extreme limiting case is if we had every cell as its own domain; then, it' s clear that there has to be communication.
598+
594599 !The " output" is iLev_DT, which is the vertical index for the level >= pvuVal. If >nVertLevels, pvuVal above column. If <2 , pvuVal below column.
595600 !Communication between blocks during the flood fill may be needed to treat some edge cases appropriately.
596601
597- use mpas_pool_routines, only : mpas_pool_get_dimension, mpas_pool_get_array
602+ use mpas_pool_routines, only : mpas_pool_get_dimension, mpas_pool_get_array, mpas_pool_get_field
603+ use mpas_dmpar, only : mpas_dmpar_max_int,mpas_dmpar_exch_halo_field
604+ use mpas_derived_types, only : dm_info, field2DInteger
598605
599606 implicit none
600607
601608 type (mpas_pool_type), intent (in ) :: mesh
602609 type (mpas_pool_type), intent (inout ) :: diag
603610 real (kind= RKIND), intent (in ) :: pvuVal
604-
605- integer :: iCell, k, nChanged, iNbr, iCellNbr, levInd
606- integer, pointer :: nCells, nVertLevels
611+
612+ integer :: iCell, k, nChanged, iNbr, iCellNbr, levInd, haloChanged, global_haloChanged
613+ integer , pointer :: nCells, nVertLevels, nCellsSolve
607614 integer , dimension (:), pointer :: nEdgesOnCell, iLev_DT
608- integer, dimension(:,:), pointer :: cellsOnCell
609-
615+ integer , dimension (:,:), pointer :: cellsOnCell, inTropo
616+
617+ type (field2DInteger), pointer :: inTropo_f
618+
610619 real (kind= RKIND) :: sgnHemi, sgn
611620 real (kind= RKIND),dimension (:),pointer:: latCell
612621 real (kind= RKIND), dimension (:,:), pointer :: ertel_pv
613622
614- integer, dimension(:,:), allocatable :: candInTropo, inTropo !whether in troposphere
623+ type (dm_info), pointer :: dminfo
624+
625+ integer , dimension (:,:), allocatable :: candInTropo !whether in troposphere
615626
616627 call mpas_pool_get_dimension(mesh, ' nCells' , nCells)
628+ call mpas_pool_get_dimension(mesh, ' nCellsSolve' , nCellsSolve)
617629 call mpas_pool_get_dimension(mesh, ' nVertLevels' , nVertLevels)
618630 call mpas_pool_get_array(mesh, ' nEdgesOnCell' , nEdgesOnCell)
619631 call mpas_pool_get_array(mesh, ' cellsOnCell' , cellsOnCell)
@@ -622,9 +634,9 @@ subroutine floodFill_tropo(mesh, diag, pvuVal)
622634 call mpas_pool_get_array(diag, ' ertel_pv' , ertel_pv)
623635 !call mpas_pool_get_array(diag, ' iLev_DT_trop' , iLev_DT)
624636 call mpas_pool_get_array(diag, ' iLev_DT' , iLev_DT)
637+ call mpas_pool_get_array(diag, ' inTropo' , inTropo)
625638
626639 allocate(candInTropo(nVertLevels, nCells+1 ))
627- allocate(inTropo(nVertLevels, nCells+1))
628640 candInTropo(:,:) = 0
629641 inTropo(:,:) = 0
630642 !store whether each level above DT to avoid repeating logic. we' ll use cand as a isVisited marker further below.
@@ -645,56 +657,71 @@ subroutine floodFill_tropo(mesh, diag, pvuVal)
645657 do k= 1 ,levInd
646658 if (candInTropo(k,iCell) .GT. 0 ) then
647659 inTropo(k,iCell) = 1
648- candInTropo(k,iCell) = 0
660+ ! candInTropo(k,iCell) = 0
649661 nChanged = nChanged+1
650662 end if
651663 end do
652664 end do
653665
654666 !flood fill from the given seeds. since I don' t know enough fortran,
655667 !we' ll just brute force a continuing loop rather than queue.
656- do while(nChanged .GT. 0)
657- nChanged = 0
658- do iCell=1,nCells
659- do k=1,nVertLevels
660- !update if candidate and neighbor in troposphere
661- if (candInTropo(k,iCell) .GT. 0) then
662- !nbr below
663- if (k .GT. 1) then
664- if (inTropo(k-1,iCell) .GT. 0) then
665- inTropo(k,iCell) = 1
666- candInTropo(k,iCell) = 0
667- nChanged = nChanged+1
668- cycle
668+ call mpas_pool_get_field(diag, ' inTropo' , inTropo_f)
669+ dminfo = > inTropo_f % block % domain % dminfo
670+ global_haloChanged = 1
671+ do while (global_haloChanged .GT. 0 ) !any cell in a halo has changed, to propagate to other domains
672+ global_haloChanged = 0 !aggregate the number of changed cells w/ in the loop below
673+ do while (nChanged .GT. 0 )
674+ nChanged = 0
675+ do iCell= 1 ,nCells !should we look for neighbors of hallo cells?
676+ !do iCell= 1 ,nCellsSolve !should we look for neighbors of hallo cells?
677+ do k= 1 ,nVertLevels
678+ !update if candidate and neighbor in troposphere
679+ if ((candInTropo(k,iCell) .GT. 0 ) .AND. (inTropo(k,iCell).LT. 1 ) ) then
680+ !nbr below
681+ if (k .GT. 1 ) then
682+ if (inTropo(k-1 ,iCell) .GT. 0 ) then
683+ inTropo(k,iCell) = 1
684+ !candInTropo(k,iCell) = 0
685+ nChanged = nChanged+1
686+ cycle
687+ end if
669688 end if
670- end if
671-
672- !side nbrs
673- do iNbr = 1, nEdgesOnCell( iCell)
674- iCellNbr = cellsOnCell(iNbr,iCell)
675- if ( inTropo(k,iCellNbr) .GT. 0) then
676- inTropo (k,iCell) = 1
677- candInTropo(k,iCell) = 0
678- nChanged = nChanged+1
679- cycle
680- end if
681- end do
682-
683- !nbr above
684- if (k .LT. nVertLevels ) then
685- if ( inTropo(k+1 ,iCell) .GT. 0) then
686- inTropo (k,iCell) = 1
687- candInTropo(k,iCell) = 0
688- nChanged = nChanged+1
689- cycle
689+
690+ !side nbrs
691+ do iNbr = 1 , nEdgesOnCell(iCell)
692+ iCellNbr = cellsOnCell(iNbr, iCell)
693+ if (inTropo(k,iCellNbr) .GT. 0 ) then
694+ inTropo(k,iCell) = 1
695+ !candInTropo (k,iCell) = 0
696+ nChanged = nChanged +1
697+ exit
698+ end if
699+ end do
700+
701+ !nbr above
702+ if (k .LT. nVertLevels) then
703+ if (inTropo(k +1 ,iCell) .GT. 0 ) then
704+ inTropo(k,iCell) = 1
705+ !candInTropo (k,iCell) = 0
706+ nChanged = nChanged +1
707+ cycle
708+ end if
690709 end if
691- end if
692-
693- end if !candIn
694- end do !levels
695- end do !cells
696- !here' s where a communication would be needed for edge cases !!!
697- end do !while
710+
711+ end if !candIn
712+ end do !levels
713+ end do !cells
714+ global_haloChanged = global_haloChanged+ nChanged
715+ end do !while w/ in domain
716+ !communicate to other domains for edge case where a chunk of a block hasn' t gotten to fill
717+ nChanged = global_haloChanged
718+ call mpas_dmpar_max_int(dminfo, nChanged, global_haloChanged)
719+ if (global_haloChanged .GT. 0) then !communicate inTropo everywhere
720+ call mpas_dmpar_exch_halo_field(inTropo_f)
721+ end if
722+ nChanged = global_haloChanged !so each block will iterate again if anything changed
723+ end do !while haloChanged
724+ deallocate(candInTropo)
698725
699726 !Fill iLev_DT with the lowest level above the tropopause (If DT above column, iLev>nVertLevels. If DT below column, iLev=0.
700727 do iCell=1,nCells
0 commit comments