convert_dat_generic Subroutine

public subroutine convert_dat_generic(nwc, dataset_names, file_suffix, convert_vars)

Uses

  • proc~~convert_dat_generic~~UsesGraph proc~convert_dat_generic convert_dat_generic module~mod_forest mod_forest proc~convert_dat_generic->module~mod_forest module~mod_functions_forest mod_functions_forest proc~convert_dat_generic->module~mod_functions_forest module~mod_global_parameters mod_global_parameters proc~convert_dat_generic->module~mod_global_parameters module~mod_input_output_helper mod_input_output_helper proc~convert_dat_generic->module~mod_input_output_helper module~mod_mpi_wrapper mod_mpi_wrapper module~mod_functions_forest->module~mod_mpi_wrapper 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_mpi_wrapper->mpi module~mod_variables->module~mod_basic_types

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nwc
character(len=*), intent(in) :: dataset_names(:)
character(len=*), intent(in) :: file_suffix
public function convert_vars(ixImin1, ixImin2, ixImin3, ixImax1, ixImax2, ixImax3, ixOmin1, ixOmin2, ixOmin3, ixOmax1, ixOmax2, ixOmax3, w, x, nwc) result(wres)
Arguments
Type IntentOptional Attributes Name
integer, intent(in) :: ixImin1
integer, intent(in) :: ixImin2
integer, intent(in) :: ixImin3
integer, intent(in) :: ixImax1
integer, intent(in) :: ixImax2
integer, intent(in) :: ixImax3
integer, intent(in) :: ixOmin1
integer, intent(in) :: ixOmin2
integer, intent(in) :: ixOmin3
integer, intent(in) :: ixOmax1
integer, intent(in) :: ixOmax2
integer, intent(in) :: ixOmax3
double precision, intent(in) :: w(ixImin1:ixImax1,ixImin2:ixImax2,ixImin3:ixImax3,1:nw)
double precision, intent(in) :: x(ixImin1:ixImax1,ixImin2:ixImax2,ixImin3:ixImax3,1:ndim)
integer, intent(in) :: nwc
Return Value double precision, (ixOmin1:ixOmax1,ixOmin2:ixOmax2,ixOmin3:ixOmax3,1:nwc)

Calls

proc~~convert_dat_generic~~CallsGraph proc~convert_dat_generic convert_dat_generic mpi_barrier mpi_barrier proc~convert_dat_generic->mpi_barrier mpi_file_close mpi_file_close proc~convert_dat_generic->mpi_file_close mpi_file_get_position mpi_file_get_position proc~convert_dat_generic->mpi_file_get_position mpi_file_seek mpi_file_seek proc~convert_dat_generic->mpi_file_seek mpi_file_write mpi_file_write proc~convert_dat_generic->mpi_file_write proc~count_ix count_ix proc~convert_dat_generic->proc~count_ix proc~create_output_file create_output_file proc~convert_dat_generic->proc~create_output_file proc~mpi_recv_wrapper mpi_recv_wrapper proc~convert_dat_generic->proc~mpi_recv_wrapper proc~mpi_send_wrapper mpi_send_wrapper proc~convert_dat_generic->proc~mpi_send_wrapper proc~snapshot_write_header1 snapshot_write_header1 proc~convert_dat_generic->proc~snapshot_write_header1 proc~write_forest write_forest proc~convert_dat_generic->proc~write_forest mpi_file_open mpi_file_open proc~create_output_file->mpi_file_open proc~mpistop mpistop proc~create_output_file->proc~mpistop mpi_recv mpi_recv proc~mpi_recv_wrapper->mpi_recv mpi_send mpi_send proc~mpi_send_wrapper->mpi_send proc~snapshot_write_header1->mpi_file_write phys_write_info phys_write_info proc~snapshot_write_header1->phys_write_info proc~write_forest->mpi_file_write mpi_abort mpi_abort proc~mpistop->mpi_abort

Called by

proc~~convert_dat_generic~~CalledByGraph proc~convert_dat_generic convert_dat_generic proc~convert_all convert_all proc~convert_all->proc~convert_dat_generic

Source Code

  subroutine convert_dat_generic(nwc, dataset_names, file_suffix,&
      convert_vars)

    use mod_forest
    use mod_global_parameters
    use mod_input_output_helper, only: count_ix, create_output_file,&
        snapshot_write_header1, block_shape_io
    use mod_functions_forest, only: write_forest

    integer                       :: file_handle, igrid, Morton_no, iwrite
    integer                       :: ipe, ix_buffer(2*ndim+1), n_values
    integer                       :: ixImin1,ixImin2,ixImin3,ixImax1,ixImax2,&
       ixImax3, ixOmin1,ixOmin2,ixOmin3,ixOmax1,ixOmax2,ixOmax3,&
        n_ghost(2*ndim)
    integer                       :: ixOsmin1,ixOsmin2,ixOsmin3,ixOsmax1,&
       ixOsmax2,ixOsmax3,n_values_stagger
    integer                       :: iorecvstatus(MPI_STATUS_SIZE)
    integer                       :: ioastatus(MPI_STATUS_SIZE)
    integer                       :: igrecvstatus(MPI_STATUS_SIZE)
    integer                       :: istatus(MPI_STATUS_SIZE)
    type(tree_node), pointer      :: pnode
    integer(kind=MPI_OFFSET_KIND) :: offset_tree_info
    integer(kind=MPI_OFFSET_KIND) :: offset_block_data
    integer(kind=MPI_OFFSET_KIND) :: offset_offsets
    double precision, allocatable :: w_buffer(:)
    double precision, allocatable:: converted_vars(:,:,:,:)

    integer :: idim, itag
    integer, allocatable                       :: block_ig(:, :)
    integer, allocatable                       :: block_lvl(:)
    integer(kind=MPI_OFFSET_KIND), allocatable :: block_offset(:)

    integer, intent(in) :: nwc
    character(len=*), intent(in) :: dataset_names(:)
    character(len=*), intent(in) :: file_suffix
    interface

      function convert_vars(ixImin1,ixImin2,ixImin3,ixImax1,ixImax2,ixImax3,&
          ixOmin1,ixOmin2,ixOmin3,ixOmax1,ixOmax2,ixOmax3,w,x,&
         nwc) result(wres)
        use mod_global_parameters
        integer, intent(in) :: ixImin1,ixImin2,ixImin3,ixImax1,ixImax2,ixImax3,&
            ixOmin1,ixOmin2,ixOmin3,ixOmax1,ixOmax2,ixOmax3, nwc
        double precision, intent(in) ::  x(ixImin1:ixImax1,ixImin2:ixImax2,&
           ixImin3:ixImax3,1:ndim)
        double precision, intent(in) :: w(ixImin1:ixImax1,ixImin2:ixImax2,&
           ixImin3:ixImax3,1:nw)
        double precision  :: wres(ixOmin1:ixOmax1,ixOmin2:ixOmax2,&
           ixOmin3:ixOmax3,1:nwc)
      end function convert_vars

    end interface


    call MPI_BARRIER(icomm, ierrmpi)

    ! Allocate send/receive buffer
    n_values = count_ix(ixGlo1,ixGlo2,ixGlo3,ixGhi1,ixGhi2,ixGhi3) * nw
    allocate(w_buffer(n_values))

    ! Allocate arrays with information about grid blocks
    allocate(block_ig(ndim, nleafs))
    allocate(block_lvl(nleafs))
    allocate(block_offset(nleafs+1))

    ! master processor
    if (mype==0) then
      call create_output_file(file_handle, snapshotnext, ".dat", file_suffix)

      ! Don't know offsets yet, we will write header again later
      offset_tree_info = -1
      offset_block_data = -1
      call snapshot_write_header1(file_handle, offset_tree_info,&
          offset_block_data, dataset_names, nwc)

      call MPI_File_get_position(file_handle, offset_tree_info, ierrmpi)

      call write_forest(file_handle)

      ! Collect information about the spatial index (ig^D) and refinement level
      ! of leaves
      do Morton_no = Morton_start(0), Morton_stop(npe-1)
         igrid = sfc(1, Morton_no)
         ipe = sfc(2, Morton_no)
         pnode => igrid_to_node(igrid, ipe)%node

         block_ig(:, Morton_no) = [ pnode%ig1,pnode%ig2,pnode%ig3 ]
         block_lvl(Morton_no) = pnode%level
         block_offset(Morton_no) = 0 ! Will be determined later
      end do

      call MPI_FILE_WRITE(file_handle, block_lvl, size(block_lvl), MPI_INTEGER,&
          istatus, ierrmpi)

      call MPI_FILE_WRITE(file_handle, block_ig, size(block_ig), MPI_INTEGER,&
          istatus, ierrmpi)

      ! Block offsets are currently unknown, but will be overwritten later
      call MPI_File_get_position(file_handle, offset_offsets, ierrmpi)
      call MPI_FILE_WRITE(file_handle, block_offset(1:nleafs), nleafs,&
          MPI_OFFSET, istatus, ierrmpi)

      call MPI_File_get_position(file_handle, offset_block_data, ierrmpi)

      ! Check whether data was written as expected
      if (offset_block_data - offset_tree_info /= (nleafs + nparents) * &
         size_logical + nleafs * ((1+ndim) * size_int + 2 * size_int)) then
        if (mype == 0) then
          print *, "Warning: MPI_OFFSET type /= 8 bytes"
          print *, "This *could* cause problems when reading .dat files"
        end if
      end if

      block_offset(1) = offset_block_data
      iwrite = 0
    end if

    do Morton_no=Morton_start(mype), Morton_stop(mype)
      igrid  = sfc_to_igrid(Morton_no)
      itag   = Morton_no
      block=>ps(igrid)
      ! this might be used in convert function,
      ! it was not used when the output is already computed vars  (write_snapshot)
      dxlevel(1)=rnode(rpdx1_,igrid);dxlevel(2)=rnode(rpdx2_,igrid)
      dxlevel(3)=rnode(rpdx3_,igrid);

      ! start copied from block_shape_io,
      ! because nwc is needed  as parameter
      ! TODO check if this will be used elsewehere and put it in separate subroutine
      n_ghost(:) = 0

      if(save_physical_boundary) then
        do idim=1,ndim
          ! Include ghost cells on lower boundary
          if(ps(igrid)%is_physical_boundary(2*idim-1)) &
             n_ghost(idim)=nghostcells
          ! Include ghost cells on upper boundary
          if(ps(igrid)%is_physical_boundary(2*idim)) &
             n_ghost(ndim+idim)=nghostcells
        end do
      end if

      ixOmin1 = ixMlo1 - n_ghost(1)
      ixOmin2 = ixMlo2 - n_ghost(2)
      ixOmin3 = ixMlo3 - n_ghost(3)
      ixOmax1 = ixMhi1 + n_ghost(ndim+1)
      ixOmax2 = ixMhi2 + n_ghost(ndim+2)
      ixOmax3 = ixMhi3 + n_ghost(ndim+3)

      n_values = count_ix(ixOmin1,ixOmin2,ixOmin3,ixOmax1,ixOmax2,&
         ixOmax3) * nwc
      ! end copied from block_shape_io

      ixImin1 = ixGlo1
      ixImin2 = ixGlo2
      ixImin3 = ixGlo3
      ixImax1 = ixGhi1
      ixImax2 = ixGhi2
      ixImax3 = ixGhi3

      w_buffer(1:n_values) = pack(convert_vars(ixImin1,ixImin2,ixImin3,ixImax1,&
         ixImax2,ixImax3, ixOmin1,ixOmin2,ixOmin3,ixOmax1,ixOmax2,ixOmax3,&
         ps(igrid)%w(ixImin1:ixImax1,ixImin2:ixImax2,ixImin3:ixImax3, 1:nw),&
          ps(igrid)%x(ixImin1:ixImax1,ixImin2:ixImax2,ixImin3:ixImax3, 1:ndim),&
         nwc), .true.)

      ix_buffer(1) = n_values
      ix_buffer(2:) = n_ghost

      if (mype /= 0) then
        call mpi_send_wrapper(ix_buffer, 2*ndim+1, MPI_INTEGER, 0, itag, icomm,&
            ierrmpi)
        call mpi_send_wrapper(w_buffer, n_values, MPI_DOUBLE_PRECISION, 0, itag, icomm,&
            ierrmpi)
      else
        iwrite = iwrite+1
        call MPI_FILE_WRITE(file_handle, ix_buffer(2:), 2*ndim, MPI_INTEGER,&
            istatus, ierrmpi)
        call MPI_FILE_WRITE(file_handle, w_buffer, n_values,&
            MPI_DOUBLE_PRECISION, istatus, ierrmpi)

        ! Set offset of next block
        block_offset(iwrite+1) = block_offset(iwrite) + int(n_values,&
            MPI_OFFSET_KIND) * size_double + 2 * ndim * size_int
      end if
    end do

    ! Write data communicated from other processors
    if (mype == 0) then
      do ipe = 1, npe-1
        do Morton_no=Morton_start(ipe), Morton_stop(ipe)
          iwrite=iwrite+1
          itag=Morton_no

          call mpi_recv_wrapper(ix_buffer, 2*ndim+1, MPI_INTEGER, ipe, itag, icomm,&
             igrecvstatus, ierrmpi)
          n_values = ix_buffer(1)

          call mpi_recv_wrapper(w_buffer, n_values, MPI_DOUBLE_PRECISION,ipe, itag,&
              icomm, iorecvstatus, ierrmpi)

          call MPI_FILE_WRITE(file_handle, ix_buffer(2:), 2*ndim, MPI_INTEGER,&
              istatus, ierrmpi)
          call MPI_FILE_WRITE(file_handle, w_buffer, n_values,&
              MPI_DOUBLE_PRECISION, istatus, ierrmpi)

          ! Set offset of next block
          block_offset(iwrite+1) = block_offset(iwrite) + int(n_values,&
              MPI_OFFSET_KIND) * size_double + 2 * ndim * size_int
        end do
      end do

      ! Write block offsets (now we know them)
      call MPI_FILE_SEEK(file_handle, offset_offsets, MPI_SEEK_SET, ierrmpi)
      call MPI_FILE_WRITE(file_handle, block_offset(1:nleafs), nleafs,&
          MPI_OFFSET, istatus, ierrmpi)

      ! Write header again, now with correct offsets
      call MPI_FILE_SEEK(file_handle, 0_MPI_OFFSET_KIND, MPI_SEEK_SET,&
          ierrmpi)
      call snapshot_write_header1(file_handle, offset_tree_info,&
          offset_block_data, dataset_names, nwc)

      call MPI_FILE_CLOSE(file_handle, ierrmpi)
    end if

    call MPI_BARRIER(icomm, ierrmpi)

  end subroutine convert_dat_generic