Create a subTree from a given inTree and an array of shapes.
All elements to the inTree%treeID are collected into the subTree%map2global array and a sub-communicator with participating processes is created. Additionally how many and which elements exist on my local process and are requested from the shapes is identified.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(treelmesh_type), | intent(in) | :: | inTree |
Global mesh from which the elements are identified and then stored to |
||
type(tem_subTree_type), | intent(out) | :: | subTree |
new mesh |
||
type(tem_shape_type), | intent(in) | :: | inShape(:) |
shape objects on which to work |
||
type(tem_levelDesc_type), | intent(in), | optional | :: | levelDesc(:) |
optional level descriptor needed for local shape |
|
type(tem_BC_prop_type), | intent(in), | optional | :: | bc_prop |
bc property which is used to identify elements belong to certain BCs |
|
logical, | intent(in), | optional | :: | storePnts |
To store space points in subTree |
|
type(tem_stencilHeader_type), | intent(in), | optional | :: | stencil |
stencil used to find bcID on certain links |
|
character(len=*), | intent(in), | optional | :: | prefix |
prefix for the subTree |
subroutine tem_create_subTree_of( inTree, subTree, inShape, levelDesc, & & bc_prop, storePnts, stencil, prefix ) ! --------------------------------------------------------------------------- !> Global mesh from which the elements are identified and then stored to type(treelmesh_type), intent(in) :: inTree !> new mesh type(tem_subTree_type), intent(out) :: subTree !> shape objects on which to work type(tem_shape_type),intent(in) :: inShape(:) !> optional level descriptor needed for local shape type(tem_levelDesc_type ), optional, intent(in) :: levelDesc(:) !> bc property which is used to identify elements belong to certain BCs type( tem_bc_prop_type ), optional, intent(in) :: bc_prop !> To store space points in subTree logical, optional, intent(in) :: storePnts !> stencil used to find bcID on certain links type( tem_stencilHeader_type ), optional, intent(in) :: stencil !> prefix for the subTree character(len=*), optional, intent(in) :: prefix ! --------------------------------------------------------------------------- ! local growing array for the map to the global tree type(dyn_intArray_type) :: local_map2global type(tem_grwPoints_type) :: local_grwPnts integer, allocatable :: map2globalTemp(:) integer(kind=long_k), allocatable :: tmp_treeID(:) integer :: iShape, iElem ! mpi variables for parallel writing of the log-wise trees integer :: color, iError ! if the local rank has part of the tracking object logical :: participateInMesh, globalParticipateInMesh ! if any element be found for this iShape integer :: local_countElems( globalMaxLevels ) integer :: local_countPnts logical :: local_storePnts ! -------------------------------------------------------------------------- if (present(storePnts)) then local_storePnts = storePnts else local_storePnts = .false. end if subTree%useGlobalMesh = any(inShape(:)%shapeID == tem_global_shape) subTree%useLocalMesh = any(inShape(:)%shapeID == tem_local_shape) subTree%created_new_comm = .false. if (subTree%useGlobalMesh) then write(logUnit(5),*) 'Subtree encompasses all fluid elements' else if (subTree%useLocalMesh) then if (present(levelDesc)) then write(logUnit(5),*) 'Subtree encompasses all elements of local domain' else write(logUnit(1),*) 'ERROR:levelDesc is not passed to ' & & // 'tem_create_subTree_of' write(logUnit(1),*) ' levelDesc is required to create ' & & // 'subTree for tem_local_shape!' call tem_abort() end if end if end if ! Prepare output structure ! init here the sub-tree mesh subTree%global = inTree%global ! initialize the number of elements on this partition with 0 subTree%nElems = 0 subTree%global%nElems = 0 if ( present(prefix) ) subTree%global%dirname = trim(prefix) check_shapes: if (.not. (subTree%useGlobalMesh .or. subTree%useLocalMesh) ) then local_countElems = 0 local_countPnts = 0 call init( local_map2global, length = 128) do iShape = 1, size( inShape ) call tem_shape2subTree(me = inShape(iShape), & & iShape = iShape, & & inTree = inTree, & & storePnts = local_storePnts, & & map2global = local_map2global, & & grwPnts = local_grwPnts, & & countElems = local_countElems, & & countPnts = local_countPnts, & & bcIDs = subTree%bc_ID, & & bc_prop = bc_prop, & & stencil = stencil ) end do ! iShape participateInMesh = ( sum(local_countElems) > 0 .or. local_countPnts > 0 ) ! abort if no elements are found for the given shape call MPI_ALLREDUCE( participateInMesh, globalParticipateInMesh, 1, & & MPI_LOGICAL, MPI_LOR, inTree%global%comm, iError ) if (.not. globalParticipateInMesh) then write(logUnit(1),*) 'Error: No elements found for ' & & // trim(subTree%global%dirname) // ' in the mesh' call tem_abort() end if else check_shapes ! For local or global shapes we always participate participateInMesh = .true. end if check_shapes if ( .not. subTree%useGlobalMesh ) then subTree%global%predefined = '' end if ! Exchange information about the mesh ! Now create a new communicator with ranks that own parts of the sub-mesh ! This is done with the color if (participateInMesh) then color = 1 else ! Not participating, set color to undefined color = MPI_UNDEFINED end if ! Input rank as a key to keep sorting as in global communicator ! reorder process ranks into tracking communicator if (subTree%useLocalMesh) then subTree%global%comm = MPI_COMM_SELF call tem_shape_initLocal(levelDesc, tmp_treeID) else call mpi_comm_split( inTree%global%comm, color, inTree%global%myPart, & & subTree%global%comm, iError ) if (iError .ne. mpi_success) then write(logUnit(1),*)' There was an error splitting the communicator' write(logUnit(1),*)' for the tracking subset. Aborting...' call tem_abort() end if subTree%created_new_comm = .true. end if if (participateInMesh) then call mpi_comm_size( subTree%global%comm, subTree%global%nParts, iError ) call mpi_comm_rank( subTree%global%comm, subTree%global%myPart, iError ) if (.not. subTree%useGlobalmesh) then if (subTree%useLocalMesh) then call tem_subTree_from( me = subTree, & & treeID = tmp_treeID ) ! update the property list of the newly defined tree according to the ! the local shape (simply copy the bits) call tem_copyPropertyBits( levelDesc = levelDesc, subTree = subTree ) else ! NOT useLocalMesh ! Copy the created dynamic local_tIDlist to a long integer array allocate( map2globalTemp(local_map2global%nVals) ) ! Assign list of links to the temporary list, first sorting do iElem = 1, local_map2global%nVals map2globalTemp(iElem) = local_map2global & & %val( local_map2global%sorted(iElem) ) end do call tem_subTree_from( me = subTree, & & map2global = map2globalTemp, & & grwPnts = local_grwPnts ) call destroy( me = local_grwPnts ) ! copy property bits from the global tree call tem_copyPropertyBits( inTree = inTree, subTree = subTree ) deallocate( map2globalTemp ) end if ! useLocalMesh with level desc ! Calculate the effective extents of the tracking sub-tree bounding box call tem_setEffBoundingBox( subTree, inTree ) else ! useGlobalMesh ! assign the global properties to the subTree subTree%nElems = inTree%nElems subTree%global%nElems = inTree%global%nElems end if ! not global mesh? else ! NOT participating in subtree subTree%nElems = 0 subTree%global%nElems = 0 allocate( subTree%map2global(0) ) subTree%nPoints = 0 subTree%glob_nPoints = 0_long_k allocate( subTree%points(0,0) ) end if ! Participate in subtree? write(logUnit(5),"(A,I0)") 'Found corresponding nElems: ', & & subTree%global%nElems call destroy( me = local_map2global ) call tem_horizontalSpacer( fUnit= logUnit(5) ) end subroutine tem_create_subTree_of