read_forest Subroutine

public subroutine read_forest(file_handle)

Uses

  • proc~~read_forest~~UsesGraph proc~read_forest read_forest mod_amr_solution_node mod_amr_solution_node proc~read_forest->mod_amr_solution_node module~mod_amr_neighbors mod_amr_neighbors proc~read_forest->module~mod_amr_neighbors module~mod_forest mod_forest proc~read_forest->module~mod_forest module~mod_functions_connectivity mod_functions_connectivity proc~read_forest->module~mod_functions_connectivity module~mod_global_parameters mod_global_parameters proc~read_forest->module~mod_global_parameters module~mod_space_filling_curve mod_space_filling_curve proc~read_forest->module~mod_space_filling_curve module~mod_basic_types mod_basic_types module~mod_global_parameters->module~mod_basic_types module~mod_connectivity mod_connectivity module~mod_global_parameters->module~mod_connectivity module~mod_constants mod_constants module~mod_global_parameters->module~mod_constants module~mod_physicaldata mod_physicaldata module~mod_global_parameters->module~mod_physicaldata module~mod_variables mod_variables module~mod_global_parameters->module~mod_variables mpi mpi module~mod_global_parameters->mpi module~mod_variables->module~mod_basic_types

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: file_handle

Calls

proc~~read_forest~~CallsGraph proc~read_forest read_forest getnode getnode proc~read_forest->getnode mpi_bcast mpi_bcast proc~read_forest->mpi_bcast mpi_file_seek mpi_file_seek proc~read_forest->mpi_file_seek mpi_get_count mpi_get_count proc~read_forest->mpi_get_count proc~add_to_linked_list add_to_linked_list proc~read_forest->proc~add_to_linked_list proc~amr_morton_order amr_Morton_order proc~read_forest->proc~amr_morton_order proc~asign_tree_neighbor asign_tree_neighbor proc~read_forest->proc~asign_tree_neighbor proc~build_connectivity build_connectivity proc~read_forest->proc~build_connectivity proc~get_level_range get_level_range proc~read_forest->proc~get_level_range proc~get_morton_range get_Morton_range proc~read_forest->proc~get_morton_range proc~getigrids getigrids proc~read_forest->proc~getigrids proc~level1_morton_order level1_Morton_order proc~read_forest->proc~level1_morton_order proc~mpi_file_read_wrapper mpi_file_read_wrapper proc~read_forest->proc~mpi_file_read_wrapper proc~mpistop mpistop proc~amr_morton_order->proc~mpistop proc~find_neighbor find_neighbor proc~asign_tree_neighbor->proc~find_neighbor proc~add_to_c nbprocs_info_t%add_to_c proc~build_connectivity->proc~add_to_c proc~add_to_f nbprocs_info_t%add_to_f proc~build_connectivity->proc~add_to_f proc~add_to_srl nbprocs_info_t%add_to_srl proc~build_connectivity->proc~add_to_srl proc~alloc_buffers_c nbprocs_info_t%alloc_buffers_c proc~build_connectivity->proc~alloc_buffers_c proc~alloc_buffers_f nbprocs_info_t%alloc_buffers_f proc~build_connectivity->proc~alloc_buffers_f proc~alloc_buffers_srl nbprocs_info_t%alloc_buffers_srl proc~build_connectivity->proc~alloc_buffers_srl proc~build_connectivity->proc~find_neighbor proc~identifyphysbound_connectivity identifyphysbound_connectivity proc~build_connectivity->proc~identifyphysbound_connectivity proc~reset nbprocs_info_t%reset proc~build_connectivity->proc~reset proc~mortonencode mortonEncode proc~level1_morton_order->proc~mortonencode mpi_file_read mpi_file_read proc~mpi_file_read_wrapper->mpi_file_read proc~add_igrid_to_c nbprocs_info_t%add_igrid_to_c proc~add_to_c->proc~add_igrid_to_c proc~add_igrid_to_f nbprocs_info_t%add_igrid_to_f proc~add_to_f->proc~add_igrid_to_f proc~add_igrid_to_srl nbprocs_info_t%add_igrid_to_srl proc~add_to_srl->proc~add_igrid_to_srl proc~idecode nbprocs_info_t%idecode proc~alloc_buffers_srl->proc~idecode proc~find_root_neighbor find_root_neighbor proc~find_neighbor->proc~find_root_neighbor mpi_abort mpi_abort proc~mpistop->mpi_abort proc~init_cf_info nbinfo_cf_t%init_cf_info proc~add_igrid_to_c->proc~init_cf_info proc~add_igrid_to_f->proc~init_cf_info proc~iencode nbprocs_info_t%iencode proc~add_igrid_to_srl->proc~iencode proc~init_srl_info init_srl_info proc~add_igrid_to_srl->proc~init_srl_info

Called by

proc~~read_forest~~CalledByGraph proc~read_forest read_forest proc~read_snapshot read_snapshot proc~read_snapshot->proc~read_forest proc~read_snapshot_old read_snapshot_old proc~read_snapshot->proc~read_snapshot_old proc~read_snapshot_old->proc~read_forest proc~main main proc~main->proc~read_snapshot program~agile agile program~agile->proc~main

Source Code

  subroutine read_forest(file_handle)
    use mod_forest
    use mod_global_parameters
    use mod_space_filling_curve
    use mod_amr_solution_node, only: getnode
    use mod_functions_connectivity, only: get_level_range,build_connectivity,&
       getigrids
    use mod_amr_neighbors, only: asign_tree_neighbor

    integer, intent(in) :: file_handle

    integer, dimension(MPI_STATUS_SIZE) :: status
    !integer :: ig^D, level, size_logical, Morton_no, igrid, ipe
    integer :: ig1,ig2,ig3, level, Morton_no, igrid, ipe, isfc
    logical :: leafbuf(nleafbuf)
    integer :: ibuf, nvalid, nread

    Morton_no=0
    ipe=0
    level=1
    nleafs_level(1:nlevelshi) = 0
    nparents = 0
    ! force a fill on the first node
    ibuf   = 0
    nvalid = 0
    nread  = 0

    call get_Morton_range
    call level1_Morton_order
    do isfc=1,nglev1
       ig1=sfc_iglevel1(1,isfc)
       ig2=sfc_iglevel1(2,isfc)
       ig3=sfc_iglevel1(3,isfc)
       allocate(tree_root(ig1,ig2,ig3)%node)
       nullify(tree_root(ig1,ig2,ig3)%node%parent%node)
       call read_node(tree_root(ig1,ig2,ig3),ig1,ig2,ig3,level)
    end do

    ! Hand back the read-ahead: leave rank 0's file pointer exactly where the
    ! last consumed node ends, which is where it sat when this routine read one
    ! node at a time.  read_snapshot_old relies on the sequential position.
    if (mype==0 .and. nread>ibuf) then
       call MPI_FILE_SEEK(file_handle, -int(nread-ibuf,kind=MPI_OFFSET_KIND)* &
          int(size_logical,kind=MPI_OFFSET_KIND), MPI_SEEK_CUR, ierrmpi)
    end if

    call get_level_range

    ! Rebuild tree connectivity
    call getigrids
    call build_connectivity

    ! This call is here to ensure the sfc array is initialized
    call amr_Morton_order()

    contains

      recursive subroutine read_node(tree,ig1,ig2,ig3,level)
        implicit none

        type(tree_node_ptr) :: tree
        integer, intent(in) :: ig1,ig2,ig3, level

        logical :: leaf
        integer :: ic1,ic2,ic3, child_ig1,child_ig2,child_ig3, child_level

        if (ibuf == nvalid) call refill_leafbuf
        ibuf = ibuf + 1
        leaf = leafbuf(ibuf)

        tree%node%leaf=leaf
        tree%node%ig1=ig1;tree%node%ig2=ig2;tree%node%ig3=ig3;
        tree%node%level=level
        tree%node%active=.true. .and. leaf

        do ic3=1,2
        do ic2=1,2
        do ic1=1,2
           nullify(tree%node%child(ic1,ic2,ic3)%node)
        end do
        end do
        end do
        nullify(tree%node%neighbor(1,1)%node,tree%node%neighbor(1,2)%node,&
           tree%node%neighbor(1,3)%node,tree%node%neighbor(2,1)%node,&
           tree%node%neighbor(2,2)%node,tree%node%neighbor(2,3)%node)
        nullify(tree%node%next%node,tree%node%prev%node)

        call asign_tree_neighbor(tree)

        if (leaf) then
           call add_to_linked_list(level,tree)
           nleafs_level(level) = nleafs_level(level) + 1

           Morton_no=Morton_no+1
           if (Morton_no>Morton_stop(ipe)) ipe=ipe+1
           igrid=getnode(ipe)
           tree%node%igrid=igrid
           tree%node%ipe=ipe
           igrid_to_node(igrid,ipe)%node => tree%node
           if (ipe==mype) sfc_to_igrid(Morton_no)=igrid
         else
           nparents = nparents + 1
           tree%node%igrid=0
           tree%node%ipe=-1
           child_level=level+1
           do ic3=1,2
           do ic2=1,2
           do ic1=1,2
              child_ig1=2*(ig1-1)+ic1;child_ig2=2*(ig2-1)+ic2
              child_ig3=2*(ig3-1)+ic3;
              allocate(tree%node%child(ic1,ic2,ic3)%node)
              tree%node%child(ic1,ic2,ic3)%node%parent%node => tree%node
              call read_node(tree%node%child(ic1,ic2,ic3),child_ig1,child_ig2,&
                 child_ig3,child_level)
           end do
           end do
           end do
        end if

      end subroutine read_node

      !> Pull the next chunk of leaf flags in, one read and one broadcast for
      !> up to nleafbuf nodes instead of one of each per node.  Every rank walks
      !> the tree in lockstep - the recursion is driven only by flags they all
      !> hold - so they run out of buffer at the same node and this stays
      !> collective without any agreement beyond that.
      subroutine refill_leafbuf
        implicit none

        if (mype==0) then
          call mpi_file_read_wrapper(file_handle,leafbuf,nleafbuf,MPI_LOGICAL,&
             status,ierrmpi)
          call MPI_GET_COUNT(status,MPI_LOGICAL,nread,ierrmpi)
        end if
        if (npe>1) call MPI_BCAST(leafbuf,nleafbuf,MPI_LOGICAL,0,icomm,ierrmpi)

        ! A short read at end of file is fine: the walk stops when the tree is
        ! complete and never looks past the last node the file holds, so the
        ! tail of the buffer is not consumed.  nvalid therefore counts the whole
        ! buffer, and only rank 0 tracks what it actually read, for the rewind.
        ibuf   = 0
        nvalid = nleafbuf

      end subroutine refill_leafbuf

  end subroutine read_forest