mod_slice.f90 Source File


This file depends on

sourcefile~~mod_slice.f90~~EfferentGraph sourcefile~mod_slice.f90 mod_slice.f90 sourcefile~mod_basic_types.f90 mod_basic_types.f90 sourcefile~mod_slice.f90->sourcefile~mod_basic_types.f90 sourcefile~mod_calculate_xw.f90 mod_calculate_xw.f90 sourcefile~mod_slice.f90->sourcefile~mod_calculate_xw.f90 sourcefile~mod_comm_lib.f90 mod_comm_lib.f90 sourcefile~mod_slice.f90->sourcefile~mod_comm_lib.f90 sourcefile~mod_forest.f90 mod_forest.f90 sourcefile~mod_slice.f90->sourcefile~mod_forest.f90 sourcefile~mod_geometry.f90 mod_geometry.f90 sourcefile~mod_slice.f90->sourcefile~mod_geometry.f90 sourcefile~mod_global_parameters.f90 mod_global_parameters.f90 sourcefile~mod_slice.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_input_output_helper.f90 mod_input_output_helper.f90 sourcefile~mod_slice.f90->sourcefile~mod_input_output_helper.f90 sourcefile~mod_mpi_wrapper.f90 mod_mpi_wrapper.f90 sourcefile~mod_slice.f90->sourcefile~mod_mpi_wrapper.f90 sourcefile~mod_calculate_xw.f90->sourcefile~mod_comm_lib.f90 sourcefile~mod_calculate_xw.f90->sourcefile~mod_geometry.f90 sourcefile~mod_calculate_xw.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_limiter.f90 mod_limiter.f90 sourcefile~mod_calculate_xw.f90->sourcefile~mod_limiter.f90 sourcefile~mod_usr_methods.f90 mod_usr_methods.f90 sourcefile~mod_calculate_xw.f90->sourcefile~mod_usr_methods.f90 sourcefile~mod_comm_lib.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_geometry.f90->sourcefile~mod_comm_lib.f90 sourcefile~mod_geometry.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_geometry.f90->sourcefile~mod_limiter.f90 sourcefile~mod_global_parameters.f90->sourcefile~mod_basic_types.f90 sourcefile~mod_connectivity.f90 mod_connectivity.f90 sourcefile~mod_global_parameters.f90->sourcefile~mod_connectivity.f90 sourcefile~mod_constants.f90 mod_constants.f90 sourcefile~mod_global_parameters.f90->sourcefile~mod_constants.f90 sourcefile~mod_physicaldata.f90 mod_physicaldata.f90 sourcefile~mod_global_parameters.f90->sourcefile~mod_physicaldata.f90 sourcefile~mod_variables.f90 mod_variables.f90 sourcefile~mod_global_parameters.f90->sourcefile~mod_variables.f90 sourcefile~mod_input_output_helper.f90->sourcefile~mod_comm_lib.f90 sourcefile~mod_input_output_helper.f90->sourcefile~mod_forest.f90 sourcefile~mod_input_output_helper.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_limiter.f90->sourcefile~mod_comm_lib.f90 sourcefile~mod_limiter.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_usr_methods.f90->sourcefile~mod_global_parameters.f90 sourcefile~mod_variables.f90->sourcefile~mod_basic_types.f90

Files dependent on this one

sourcefile~~mod_slice.f90~~AfferentGraph sourcefile~mod_slice.f90 mod_slice.f90 sourcefile~mod_collapse.f90 mod_collapse.f90 sourcefile~mod_collapse.f90->sourcefile~mod_slice.f90 sourcefile~mod_input_output.f90 mod_input_output.f90 sourcefile~mod_input_output.f90->sourcefile~mod_slice.f90 sourcefile~mod_input_output.f90->sourcefile~mod_collapse.f90 sourcefile~mod_particles.f90 mod_particles.f90 sourcefile~mod_input_output.f90->sourcefile~mod_particles.f90 sourcefile~mod_particle_base.f90 mod_particle_base.f90 sourcefile~mod_particle_base.f90->sourcefile~mod_slice.f90 sourcefile~agile.f90 agile.f90 sourcefile~agile.f90->sourcefile~mod_input_output.f90 sourcefile~mod_initialize.f90 mod_initialize.f90 sourcefile~agile.f90->sourcefile~mod_initialize.f90 sourcefile~agile.f90->sourcefile~mod_particles.f90 sourcefile~mod_advance.f90 mod_advance.f90 sourcefile~agile.f90->sourcefile~mod_advance.f90 sourcefile~mod_amr_grid.f90 mod_amr_grid.f90 sourcefile~agile.f90->sourcefile~mod_amr_grid.f90 sourcefile~mod_initialize.f90->sourcefile~mod_input_output.f90 sourcefile~mod_particle_advect.f90 mod_particle_advect.f90 sourcefile~mod_particle_advect.f90->sourcefile~mod_particle_base.f90 sourcefile~mod_particle_gca.f90 mod_particle_gca.f90 sourcefile~mod_particle_gca.f90->sourcefile~mod_particle_base.f90 sourcefile~mod_particle_lorentz.f90 mod_particle_lorentz.f90 sourcefile~mod_particle_lorentz.f90->sourcefile~mod_particle_base.f90 sourcefile~mod_particle_sample.f90 mod_particle_sample.f90 sourcefile~mod_particle_sample.f90->sourcefile~mod_particle_base.f90 sourcefile~mod_particles.f90->sourcefile~mod_particle_base.f90 sourcefile~mod_particles.f90->sourcefile~mod_particle_advect.f90 sourcefile~mod_particles.f90->sourcefile~mod_particle_gca.f90 sourcefile~mod_particles.f90->sourcefile~mod_particle_lorentz.f90 sourcefile~mod_particles.f90->sourcefile~mod_particle_sample.f90 sourcefile~mod_point_searching.f90 mod_point_searching.f90 sourcefile~mod_point_searching.f90->sourcefile~mod_particle_base.f90 sourcefile~mod_advance.f90->sourcefile~mod_particles.f90 sourcefile~mod_amr_grid.f90->sourcefile~mod_particles.f90

Source Code

!> Writes D-1 slice, can do so in various formats, depending on slice_type
module mod_slice
#ifdef USE_MPIWRAPPERS
  use mod_mpi_wrapper
#else
#define mpi_recv_wrapper MPI_RECV
#define mpi_send_wrapper MPI_SEND
#endif
  use mod_basic_types
  use mod_comm_lib, only: mpistop
  implicit none

  !> Maximum number of slices
  integer, parameter :: nslicemax=1000

  !> Slice coordinates, see @ref slices.md
  double precision :: slicecoord(nslicemax)

  !> Number of slices to output
  integer :: nslices

  !> The slice direction for each slice
  integer :: slicedir(nslicemax)

  !> choose data type of slice: vtu, vtuCC, dat, or csv
  character(len=std_len) :: slice_type

  !> tag for MPI message
  integer, private :: itag

  !> igrid and ipe of blocks on the slice. Row 0 stores leaf/parent counts.
  integer, allocatable :: sfc_sub(:,:)

contains

  subroutine write_slice
    use mod_global_parameters
    ! Writes a D-1 slice
    ! by Oliver Porth
    ! 22.Nov 2011
    integer :: islice

    do islice=1,nslices
       call put_slice(slicedir(islice),slicecoord(islice))
    end do

    slicenext=slicenext+1
  end subroutine write_slice

  subroutine put_slice(dir,xslice)
    use mod_forest, only: Morton_sub_start, Morton_sub_stop
    use mod_global_parameters
    use mod_geometry, only: s_of_r
    ! Writes a D-1 slice
    ! For ONED simulations, output will be appended to one csv-file per slice
    ! slices are sensitive to the saveprim switch and
    ! can contain auxiliary io variables (nwauxio)
    ! Thus csv or vtu(CC)-files with primitive variables are obtained.
    ! when slice_type='dat', we save a D-1 dat file for potential restarts
    ! by Oliver Porth
    ! 22.Nov 2011
    integer, intent(in) :: dir
    double precision, intent(in) :: xslice
    ! .. local ..
    integer :: Njgrid, jgrid
    integer, dimension(ndim-1) :: ixsubGlo, ixsubGhi
    integer, dimension(ndim-1) :: ixsubMlo, ixsubMhi
    integer :: size_subblock_io, nx1,nx2,nx3, slice_fh, nwexpand
    integer :: type_subblock_io, type_subblockC_io, type_subblock_x_io,&
        type_subblockC_x_io
    integer, dimension(ndim) :: sizes, subsizes, start
    double precision,dimension(0:nw+nwauxio)          :: normconv
    double precision, dimension(ndim-1) :: xprobminsub, xprobmaxsub
    integer, dimension(ndim-1) :: block_nx_sub, domain_nx_sub
    logical, dimension(ndim-1) :: periodBsub

    ! Preamble:
    nx1=ixMhi1-ixMlo1+1;nx2=ixMhi2-ixMlo2+1;nx3=ixMhi3-ixMlo3+1;
    slice_fh=unitslice

    if (ndim==1) then
       nwexpand = nwauxio
    else
       if(slice_type/='dat')then
          nwexpand = nwauxio
       else
          nwexpand = 0
       endif
    end if

    ! Do a last consistency check. xslice is a physical coordinate, so under
    ! LOG_RADIUS the radial one has to be compared in the logical coordinate
    ! that xprobmin1/xprobmax1 are stored in.
    select case(dir)
       case(1)
       if(xslice<xprobmin1.or.xslice>xprobmax1) call &
          mpistop("slice out of bounds")

       case(2)
       if(xslice<xprobmin2.or.xslice>xprobmax2) call &
          mpistop("slice out of bounds")

       case(3)
       if(xslice<xprobmin3.or.xslice>xprobmax3) call &
          mpistop("slice out of bounds")

    end select

    ! Traverse the forest and fill nodes:
    call select_slice(dir,xslice,.false.,slice_fh,normconv)

    ! Create the MPI-datatype and select indices:

    select case(dir)
    case (1)
       sizes(1) = ixGhi2; sizes(2) = ixGhi3;
       ixsubGlo(1) = ixGlo2; ixsubGlo(2) = ixGlo3;
       ixsubGhi(1) = ixGhi2; ixsubGhi(2) = ixGhi3;
       subsizes(1)=nx2;subsizes(2)=nx3;
       start(1)=ixMlo2-1;start(2)=ixMlo3-1;
       size_subblock_io=nx2*nx3*(nw+nwexpand)*size_double
       xprobminsub(1)=xprobmin2; xprobmaxsub(1)=xprobmax2;
       xprobminsub(2)=xprobmin3; xprobmaxsub(2)=xprobmax3;
       domain_nx_sub(1)=domain_nx2; domain_nx_sub(2)=domain_nx3;
       block_nx_sub(1)=block_nx2; block_nx_sub(2)=block_nx3;
       periodBsub(1)=periodB(2); periodBsub(2)=periodB(3);
    case (2)
       sizes(1) = ixGhi1; sizes(2) = ixGhi3;
       ixsubGlo(1) = ixGlo1; ixsubGlo(2) = ixGlo3;
       ixsubGhi(1) = ixGhi1; ixsubGhi(2) = ixGhi3;
       subsizes(1)=nx1;subsizes(2)=nx3;
       start(1)=ixMlo1-1;start(2)=ixMlo3-1;
       size_subblock_io=nx1*nx3*(nw+nwexpand)*size_double
       xprobminsub(1)=xprobmin1; xprobmaxsub(1)=xprobmax1;
       xprobminsub(2)=xprobmin3; xprobmaxsub(2)=xprobmax3;
       domain_nx_sub(1)=domain_nx1; domain_nx_sub(2)=domain_nx3;
       block_nx_sub(1)=block_nx1; block_nx_sub(2)=block_nx3;
       periodBsub(1)=periodB(1); periodBsub(2)=periodB(3);
    case (3)
       ixsubGlo(1) = ixGlo1; ixsubGlo(2) = ixGlo2;
       ixsubGhi(1) = ixGhi1; ixsubGhi(2) = ixGhi2;
       sizes(1) = ixGhi1; sizes(2) = ixGhi2;
       subsizes(1)=nx1;subsizes(2)=nx2;
       start(1)=ixMlo1-1;start(2)=ixMlo2-1;
       size_subblock_io=nx1*nx2*(nw+nwexpand)*size_double
       xprobminsub(1)=xprobmin1; xprobmaxsub(1)=xprobmax1;
       xprobminsub(2)=xprobmin2; xprobmaxsub(2)=xprobmax2;
       domain_nx_sub(1)=domain_nx1; domain_nx_sub(2)=domain_nx2;
       block_nx_sub(1)=block_nx1; block_nx_sub(2)=block_nx2;
       periodBsub(1)=periodB(1); periodBsub(2)=periodB(2);
    case default
       call mpistop("slice direction not clear in put_slice")
    end select





    ixsubMlo(2-1) = ixsubGlo(2-1)+nghostcells
    ixsubMlo(3-1) = ixsubGlo(3-1)+nghostcells;
    ixsubMhi(2-1) = ixsubGhi(2-1)-nghostcells
    ixsubMhi(3-1) = ixsubGhi(3-1)-nghostcells;


    sizes(ndim)=nw+nwexpand
    subsizes(ndim)=nw+nwexpand
    start(ndim)=0

    ! Types for center variables:
    call MPI_TYPE_CREATE_SUBARRAY(ndim,sizes,subsizes,start, MPI_ORDER_FORTRAN,&
       MPI_DOUBLE_PRECISION, type_subblock_io,ierrmpi)
    call MPI_TYPE_COMMIT(type_subblock_io,ierrmpi)

    sizes(ndim)=3
    subsizes(ndim)=3
    start(ndim)=0
    call MPI_TYPE_CREATE_SUBARRAY(ndim,sizes,subsizes,start, MPI_ORDER_FORTRAN,&
       MPI_DOUBLE_PRECISION, type_subblock_x_io,ierrmpi)
    call MPI_TYPE_COMMIT(type_subblock_x_io,ierrmpi)


    ! Types for corner variables:
    subsizes(1:ndim-1) = subsizes(1:ndim-1) + 1
    start(1:ndim-1)    = start(1:ndim-1) - 1
    sizes(ndim)=nw+nwexpand
    subsizes(ndim)=nw+nwexpand
    start(ndim)=0

    call MPI_TYPE_CREATE_SUBARRAY(ndim,sizes,subsizes,start, MPI_ORDER_FORTRAN,&
       MPI_DOUBLE_PRECISION, type_subblockC_io,ierrmpi)
    call MPI_TYPE_COMMIT(type_subblockC_io,ierrmpi)

    sizes(ndim)=3
    subsizes(ndim)=3
    start(ndim)=0
    call MPI_TYPE_CREATE_SUBARRAY(ndim,sizes,subsizes,start, MPI_ORDER_FORTRAN,&
       MPI_DOUBLE_PRECISION, type_subblockC_x_io,ierrmpi)
    call MPI_TYPE_COMMIT(type_subblockC_x_io,ierrmpi)


    ! local number of sub-grids:
    Njgrid=Morton_sub_stop(mype)-Morton_sub_start(mype)+1

    ! Now output using various schemes:
    if (ndim==1) then
       call put_slice_zerod
    else
       select case(slice_type)
       case ('csv')
          call put_slice_csv
       case ('dat')
          call put_slice_dat
       case ('vtu', 'vtuCC')
          call put_slice_vtu
       end select
    end if

    do jgrid=1,Njgrid
       call dealloc_subnode(jgrid)
    end do

    call MPI_TYPE_FREE(type_subblock_io,ierrmpi)
    call MPI_TYPE_FREE(type_subblock_x_io,ierrmpi)
    call MPI_TYPE_FREE(type_subblockC_io,ierrmpi)
    call MPI_TYPE_FREE(type_subblockC_x_io,ierrmpi)

    if (allocated(sfc_sub)) deallocate(sfc_sub)

  contains

    subroutine put_slice_vtu

      use mod_calculate_xw
      character(len=1024) :: filename, xlabel
      character(len=79)   :: xxlabel
      logical             :: fileopen
      character(len=name_len) :: wnamei(1:nw+nwauxio),&
         xandwnamei(1:ndim+nw+nwauxio)
      character(len=1024) :: outfilehead
      integer :: status(MPI_STATUS_SIZE), ipe

      if (mype==0) then

         inquire(slice_fh,opened=fileopen)
         if(.not.fileopen)then
            ! generate filename:
            write(xlabel,"(D9.2)")xslice
            xxlabel=trim(xlabel)
            if(xslice>=zero)then
               write(xxlabel(1:1),"(a)") "+"
            endif
            write(filename,"(a,i1.1,a,i4.4,a)") TRIM(base_filename)//'_d',dir,&
               '_x'//trim(xxlabel)//'_n',slicenext,'.vtu'
            open(slice_fh,file=filename,status='unknown',form='formatted')
         end if
         ! get and write the header:
         call getheadernames(wnamei,xandwnamei,outfilehead)
         ! generate xml header
         write(slice_fh,'(a)')'<?xml version="1.0"?>'
         write(slice_fh,'(a)',advance='no') '<VTKFile type="UnstructuredGrid"'
         if(type_endian==1)then
            write(slice_fh,'(a)')' version="0.1" byte_order="LittleEndian">'
         else
            write(slice_fh,'(a)')' version="0.1" byte_order="BigEndian">'
         endif
         write(slice_fh,'(a)')'  <UnstructuredGrid>'
         write(slice_fh,'(a)')'<FieldData>'
         write(slice_fh,'(2a)')'<DataArray type="Float32" Name="TIME" ',&
            'NumberOfTuples="1" format="ascii">'
         write(slice_fh,*) real(global_time*time_convert_factor)
         write(slice_fh,'(a)')'</DataArray>'
         write(slice_fh,'(a)')'</FieldData>'

         ! write to file:
         do jgrid=1, Njgrid
            call write_slice_vtk(jgrid,slice_fh,wnamei)
         end do

         ! create a recv buffer using allocate, will be deallocated at the end of the routine:
         call alloc_subnode(Njgrid+1,dir,nwauxio)

      end if

      ! Also communicate the normconv array since processor zero might not have it yet:
      if (npe>1) then
         do ipe=1,npe-1
            do jgrid=1,Morton_sub_stop(ipe)-Morton_sub_start(ipe)+1
               itag=Morton_sub_start(ipe)+jgrid-1
               itag=itag*5
               if (ipe == mype ) then
                  call mpi_send_wrapper(ps_sub(jgrid)%x,1,type_subblock_x_io,0,itag,&
                     icomm,ierrmpi)
                  call mpi_send_wrapper(ps_sub(jgrid)%w,1,type_subblock_io,0,itag+1,&
                     icomm,ierrmpi)
                  call mpi_send_wrapper(ps_sub(jgrid)%xC,1,type_subblockC_x_io,0,&
                     itag+2,icomm,ierrmpi)
                  call mpi_send_wrapper(ps_sub(jgrid)%wC,1,type_subblockC_io,0,itag+3,&
                     icomm,ierrmpi)
                  call mpi_send_wrapper(normconv,nw+nwauxio+1,MPI_DOUBLE_PRECISION,0,&
                     itag+4,icomm,ierrmpi)
               end if
               if (mype == 0) then
                  call mpi_recv_wrapper(ps_sub(Njgrid+1)%x,1,type_subblock_x_io,ipe,&
                     itag,icomm,status,ierrmpi)
                  call mpi_recv_wrapper(ps_sub(Njgrid+1)%w,1,type_subblock_io,ipe,&
                     itag+1,icomm,status,ierrmpi)
                  call mpi_recv_wrapper(ps_sub(Njgrid+1)%xC,1,type_subblockC_x_io,ipe,&
                     itag+2,icomm,status,ierrmpi)
                  call mpi_recv_wrapper(ps_sub(Njgrid+1)%wC,1,type_subblockC_io,ipe,&
                     itag+3,icomm,status,ierrmpi)
                  call mpi_recv_wrapper(normconv,nw+nwauxio+1,MPI_DOUBLE_PRECISION,ipe,&
                     itag+4,icomm,status,ierrmpi)
                  call write_slice_vtk(Njgrid+1,slice_fh,wnamei)
               end if
            end do
         end do
      endif

      if (mype==0) then

         write(slice_fh,'(a)')'</UnstructuredGrid>'
         write(slice_fh,'(a)')'</VTKFile>'
         close(slice_fh)
         call dealloc_subnode(Njgrid+1)

      end if

    end subroutine put_slice_vtu

    subroutine write_slice_vtk(jgrid,slice_fh,wnamei)

      ! this only works for 2D and 3D, 1D reduction (line to point) not allowed
      integer, intent(in)           :: jgrid, slice_fh
      character(len=name_len), intent(in) :: wnamei(1:nw+nwauxio)
      ! This remainder part only for more than 1D, but nesting with NOONED gives problems

      ! .. local ..
      integer                       :: ixCmin1,ixCmin2,ixCmin3,ixCmax1,ixCmax2,&
         ixCmax3, ixCCmin1,ixCCmin2,ixCCmin3,ixCCmax1,ixCCmax2,ixCCmax3, nc,&
          np, iw
      integer                       :: nx1,nx2, nxC1,nxC2, icell, ix1,ix2
      double precision              :: x_VTK(1:3)
      integer                       :: VTK_type
      double precision, parameter   :: minvalue = 1.0d-99, maxvalue = 1.0d+99

      ixCCmin1 = ixsubMlo(1);ixCCmin2 = ixsubMlo(2);
      ixCCmax1 = ixsubMhi(1);ixCCmax2 = ixsubMhi(2);
      ixCmin1  = ixsubMlo(1)-1;ixCmin2  = ixsubMlo(2)-1;
      ixCmax1  = ixsubMhi(1);ixCmax2  = ixsubMhi(2);

      nx1=ixCCmax1-ixCCmin1+1;nx2=ixCCmax2-ixCCmin2+1;
      nxC1=nx1+1;nxC2=nx2+1;
      nc=nx1*nx2      ! Number of cells per subgrid
      np=nxC1*nxC2     ! Number of corner points per subgrid

      ! we write out every grid as one VTK PIECE
      write(slice_fh,'(a,i7,a,i7,a)') '<Piece NumberOfPoints="',np,&
         '" NumberOfCells="',nc,'">'

      !==============================
      ! celldata or pointdata?
      !==============================
      select case(slice_type)

      case('vtuCC') ! celldata
         write(slice_fh,'(a)')'<CellData>'
         do iw=1,nw+nwauxio
            if(iw<=nw) then
               if(.not.w_write(iw)) cycle
            endif
            write(slice_fh,'(a,a,a)')'<DataArray type="Float64" Name="',&
               TRIM(wnamei(iw)),'" format="ascii">'
            write(slice_fh,'(200(1pe14.6))') &
               ((roundoff_minmax(ps_sub(jgrid)%w(ix1,ix2,iw)*normconv(iw),&
               minvalue,maxvalue),ix1=ixCCmin1,ixCCmax1),ix2=ixCCmin2,&
               ixCCmax2)
            write(slice_fh,'(a)')'</DataArray>'
         enddo
         write(slice_fh,'(a)')'</CellData>'


      case('vtu') ! pointdata
         write(slice_fh,'(a)')'<PointData>'
         do iw=1,nw+nwauxio
            if(iw<=nw) then
               if(.not.w_write(iw)) cycle
            endif
            write(slice_fh,'(a,a,a)')'<DataArray type="Float64" Name="',&
               TRIM(wnamei(iw)),'" format="ascii">'
            write(slice_fh,'(200(1pe14.6))') &
               ((roundoff_minmax(ps_sub(jgrid)%wC(ix1,ix2,iw)*normconv(iw),&
               minvalue,maxvalue),ix1=ixCmin1,ixCmax1),ix2=ixCmin2,ixCmax2)
            write(slice_fh,'(a)')'</DataArray>'
         enddo
         write(slice_fh,'(a)')'</PointData>'


      end select
      !==============================
      ! Done: celldata or pointdata?
      !==============================

      !==============================
      ! output Cornerpoints
      !==============================
      write(slice_fh,'(a)')'<Points>'
      write(slice_fh,'(a)'&
         )'<DataArray type="Float32" NumberOfComponents="3" format="ascii">'
 !write cell corner coordinates in a backward dimensional loop, always 3D output
      do ix2=ixCmin2,ixCmax2
      do ix1=ixCmin1,ixCmax1
            x_VTK(1:3)=zero;
            x_VTK(1:ndim)=ps_sub(jgrid)%xC(ix1,ix2,1:ndim)*normconv(0);
            write(slice_fh,'(3(1pe14.6))') x_VTK
      end do
      end do
      write(slice_fh,'(a)')'</DataArray>'
      write(slice_fh,'(a)')'</Points>'
      !==============================
      ! Done: output Cornerpoints
      !==============================

      !==============================
      ! cell Metainformation
      !==============================
      write(slice_fh,'(a)')'<Cells>'

      ! connectivity part
      write(slice_fh,'(a)'&
         )'<DataArray type="Int32" Name="connectivity" format="ascii">'

       do ix2=1,nx2
       do ix1=1,nx1

      write(slice_fh,'(4(i7,1x))')(ix2-1)*nxC1+ix1-1, (ix2-1)*nxC1+ix1,&
         ix2*nxC1+ix1-1,ix2*nxC1+ix1
      end do
       end do

      write(slice_fh,'(a)')'</DataArray>'

      ! offsets data array
      write(slice_fh,'(a)'&
         )'<DataArray type="Int32" Name="offsets" format="ascii">'
      do icell=1,nc
         write(slice_fh,'(i7)') icell*(2**(3-1))
      end do
      write(slice_fh,'(a)')'</DataArray>'

      ! VTK cell type data array
      write(slice_fh,'(a)'&
         )'<DataArray type="Int32" Name="types" format="ascii">'
      ! VTK_LINE=3; VTK_PIXEL=8; VTK_VOXEL=11 -> vtk-syntax

       VTK_type=8
      do icell=1,nc
         write(slice_fh,'(i2)') VTK_type
      enddo
      write(slice_fh,'(a)')'</DataArray>'

      write(slice_fh,'(a)')'</Cells>'
      !==============================
      ! Done: cell Metainformation
      !==============================
      write(slice_fh,'(a)')'</Piece>'


    end subroutine write_slice_vtk

    subroutine put_slice_csv

      use mod_calculate_xw
      character(len=1024)           :: filename, xlabel
      character(len=79)             :: xxlabel
      logical                       :: fileopen
      character(len=name_len)       :: wnamei(1:nw+nwauxio),&
         xandwnamei(1:ndim+nw+nwauxio)
      character(len=1024)           :: outfilehead
      integer                       :: iw, ipe, itag
      character(len=1024)           :: line
      integer                       :: status(MPI_STATUS_SIZE)

      if (mype==0) then
         inquire(slice_fh,opened=fileopen)
         if(.not.fileopen)then
            ! generate filename:
            write(xlabel,"(D9.2)")xslice
            xxlabel=trim(xlabel)
            if(xslice>=zero)then
               write(xxlabel(1:1),"(a)") "+"
            endif
            write(filename,"(a,i1.1,a,i4.4,a)") TRIM(base_filename)//'_d',dir,&
               '_x'//trim(xxlabel)//'_n',slicenext,'.csv'
            open(slice_fh,file=filename,status='unknown',form='formatted')
         end if
         ! get and write the header:
         call getheadernames(wnamei,xandwnamei,outfilehead)
         line=''
         do iw=1,ndim+nw+nwauxio-1
            line = trim(line)//trim(xandwnamei(iw))//', '
         end do
         line = trim(line)//trim(xandwnamei(ndim+nw+nwauxio))
         write(slice_fh,'(a)')trim(line)
         ! create a recv buffer using allocate, will be deallocated at the end of the routine:
         call alloc_subnode(Njgrid+1,dir,nwauxio)

         ! write to file:
         do jgrid=1, Njgrid
            call put_slice_line(jgrid,slice_fh)
         end do
      end if

      ! Also communicate the normconv array since processor zero might not have it yet:
      if (npe>1) then
         do ipe=1,npe-1
            do jgrid=1,Morton_sub_stop(ipe)-Morton_sub_start(ipe)+1
               itag=Morton_sub_start(ipe)+jgrid-1
               if (ipe == mype ) then
                  call mpi_send_wrapper(ps_sub(jgrid)%x,1,type_subblock_x_io,0,itag,&
                     icomm,ierrmpi)
                  call mpi_send_wrapper(ps_sub(jgrid)%w,1,type_subblock_io,0,itag,&
                     icomm,ierrmpi)
                  call mpi_send_wrapper(normconv,nw+nwauxio+1,MPI_DOUBLE_PRECISION,0,&
                     itag,icomm,ierrmpi)
               end if
               if (mype == 0) then
                  call mpi_recv_wrapper(ps_sub(Njgrid+1)%x,1,type_subblock_x_io,ipe,&
                     itag,icomm,status,ierrmpi)
                  call mpi_recv_wrapper(ps_sub(Njgrid+1)%w,1,type_subblock_io,ipe,itag,&
                     icomm,status,ierrmpi)
                  call mpi_recv_wrapper(normconv,nw+nwauxio+1,MPI_DOUBLE_PRECISION,ipe,&
                     itag,icomm,status,ierrmpi)
                  call put_slice_line(Njgrid+1,slice_fh)
               end if
            end do
         end do
      endif

      if (mype==0) then
         close(slice_fh)
         call dealloc_subnode(Njgrid+1)
      end if

    end subroutine put_slice_csv

    subroutine put_slice_line(jout,file_handle)
      integer, intent(in) :: jout, file_handle
      ! .. local ..
      character(len=1024) ::line, data
      integer :: ix1,ix2,ix3,idir,iw
      double precision, parameter :: minvalue = 1.0d-99, maxvalue = 1.0d+99


      do ix2=ixsubMlo(2),ixsubMhi(2)
         do ix1=ixsubMlo(1),ixsubMhi(1)


               ! Format the line:
               line = ''
               do idir=1,ndim

                  write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%x(ix1,ix2,&
                     idir),minvalue,maxvalue)




                  line = trim(line)//trim(data)//', '
               end do
               do iw = 1,nw+nwauxio-1

                  write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(ix1,ix2,&
                     iw)*normconv(iw),minvalue,maxvalue)



                  line = trim(line)//trim(data)//', '
               end do

               write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(ix1,ix2,&
                  nw+nwauxio)*normconv(nw+nwauxio),minvalue,maxvalue)


               line = trim(line)//trim(data)
               write(file_handle,'(a)')trim(line)


         end do
      end do


    end subroutine put_slice_line

    subroutine put_slice_dat
      use mod_forest, only: tree_node, igrid_to_node
      use mod_input_output_helper, only: version_number, save_now
      use mod_physics, only: physics_type, phys_write_info

      integer, dimension(max_blocks*2) :: iorequest
      integer, dimension(MPI_STATUS_SIZE,max_blocks*2) :: iostatus
      integer(kind=MPI_OFFSET_KIND) :: offset, offset1
      integer :: nsubleafs
      character(len=1024) :: filename, xlabel
      character(len=79)   :: xxlabel
      integer :: amode, status(MPI_STATUS_SIZE), iwrite
      character(len=name_len) :: dname

      integer :: nsubparents, iw, ileaf, inode
      integer :: n_ghost_sub(2*(ndim-1))
      integer(kind=MPI_OFFSET_KIND) :: block_offset, tree_offset
      integer, allocatable :: block_ig_sub(:,:)
      integer, allocatable :: block_lvl_sub(:)
      integer(kind=MPI_OFFSET_KIND), allocatable :: block_offset_sub(:)
      logical, allocatable :: isleaf_sub(:)
      type(tree_node), pointer :: pnode

      nsubleafs=Morton_sub_stop(npe-1)

      if (mype==0) then

         if (nsubleafs /= sfc_sub(0,1)) error stop "nsubleafs /= sfc_sub(0,1)"
         nsubparents = sfc_sub(0,2)
         allocate(block_ig_sub(ndim-1,nsubleafs))
         allocate(block_lvl_sub(nsubleafs))
         allocate(block_offset_sub(nsubleafs))
         allocate(isleaf_sub(nsubleafs+nsubparents))

         block_offset = int(0,kind=MPI_OFFSET_KIND)
         ileaf = 0
         do inode=1,nsubleafs+nsubparents
            if (sfc_sub(inode,1) == 0) then
               isleaf_sub(inode) = .false.
            else
               isleaf_sub(inode) = .true.
               pnode => igrid_to_node(sfc_sub(inode,1),sfc_sub(inode,2))%node
               ileaf = ileaf + 1
               select case (dir)
               case (1)
                  block_ig_sub(:,ileaf) = [ pnode%ig2, pnode%ig3 ]
               case (2)
                  block_ig_sub(:,ileaf) = [ pnode%ig1, pnode%ig3 ]
               case (3)
                  block_ig_sub(:,ileaf) = [ pnode%ig1, pnode%ig2 ]
               end select
               block_lvl_sub(ileaf) = pnode%level
               block_offset_sub(ileaf) = block_offset
               block_offset = block_offset + int(2*(ndim-1)*size_int,kind=MPI_OFFSET_KIND)
               block_offset = block_offset + int(product(block_nx_sub)*nw*size_double,&
                  kind=MPI_OFFSET_KIND)
            end if
         end do
      end if

      ! generate filename
      write(xlabel,"(D9.2)")xslice
      xxlabel=trim(xlabel)
      if(xslice>=zero)then
         write(xxlabel(1:1),"(a)") "+"
      endif
      write(filename,"(a,i1.1,a,i4.4,a)") TRIM(base_filename)//'_d',dir,&
         '_x'//trim(xxlabel)//'_n',slicenext,'.dat'

      if(mype==0) then
         open(unit=slice_fh,file=filename,status='replace')
         close(unit=slice_fh)
      end if

      if (mype==0) then
         amode=ior(MPI_MODE_APPEND,MPI_MODE_WRONLY)
         call MPI_FILE_OPEN(MPI_COMM_SELF,filename,amode,MPI_INFO_NULL,&
            slice_fh,ierrmpi)

         call MPI_FILE_WRITE(slice_fh, version_number, 1, MPI_INTEGER, status,&
            ierrmpi)
         call MPI_FILE_WRITE(slice_fh, 0, 1, MPI_INTEGER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, 0, 1, MPI_INTEGER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, nw, 1, MPI_INTEGER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, ndir, 1, MPI_INTEGER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, ndim-1, 1, MPI_INTEGER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, levmax_sub, 1, MPI_INTEGER, status,&
            ierrmpi)
         call MPI_FILE_WRITE(slice_fh, nsubleafs, 1, MPI_INTEGER, status,&
            ierrmpi)
         call MPI_FILE_WRITE(slice_fh, nsubparents, 1, MPI_INTEGER, status,&
            ierrmpi)
         call MPI_FILE_WRITE(slice_fh, it, 1, MPI_INTEGER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, global_time, 1, MPI_DOUBLE_PRECISION,&
            status,ierrmpi)

         call MPI_FILE_WRITE(slice_fh, xprobminsub, ndim-1,&
            MPI_DOUBLE_PRECISION, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, xprobmaxsub, ndim-1,&
            MPI_DOUBLE_PRECISION, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, domain_nx_sub, ndim-1, MPI_INTEGER,&
            status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, block_nx_sub, ndim-1, MPI_INTEGER,&
            status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, periodBsub, ndim-1, MPI_LOGICAL,&
            status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, geometry_name(1:name_len), name_len,&
            MPI_CHARACTER, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, stagger_grid, 1, MPI_LOGICAL, status,&
            ierrmpi)

         do iw = 1, nw
            dname = trim(adjustl(cons_wnames(iw)))
            call MPI_FILE_WRITE(slice_fh, dname, name_len, MPI_CHARACTER,&
               status, ierrmpi)
         end do

         call MPI_FILE_WRITE(slice_fh, physics_type, name_len, MPI_CHARACTER,&
            status, ierrmpi)
         call phys_write_info(slice_fh)

         if(pass_wall_time.or.save_now) then
            call MPI_FILE_WRITE(slice_fh, snapshotnext, 1, MPI_INTEGER, status,&
               ierrmpi)
         else
            call MPI_FILE_WRITE(slice_fh, snapshotnext+1, 1, MPI_INTEGER,&
               status, ierrmpi)
         end if
         call MPI_FILE_WRITE(slice_fh, slicenext, 1, MPI_INTEGER, status,&
            ierrmpi)
         call MPI_FILE_WRITE(slice_fh, collapsenext, 1, MPI_INTEGER, status,&
            ierrmpi)

         call MPI_FILE_GET_POSITION(slice_fh, tree_offset, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, isleaf_sub, nsubleafs+nsubparents,&
            MPI_LOGICAL, status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, block_lvl_sub, nsubleafs, MPI_INTEGER,&
            status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, block_ig_sub, size(block_ig_sub),&
            MPI_INTEGER, status, ierrmpi)

         call MPI_FILE_GET_POSITION(slice_fh, block_offset, ierrmpi)
         block_offset_sub(:) = block_offset_sub(:) + block_offset + &
            int(nsubleafs*2*size_int, kind=MPI_OFFSET_KIND)

         call MPI_FILE_WRITE(slice_fh, block_offset_sub, nsubleafs, MPI_OFFSET,&
            status, ierrmpi)

         call MPI_FILE_GET_POSITION(slice_fh, block_offset, ierrmpi)
         if (block_offset - tree_offset /= &
            (nsubleafs + nsubparents) * size_logical + &
            nsubleafs * ((ndim-1+1) * size_int + 2 * size_int)) then
            print *, "Warning: MPI_OFFSET type /= 8 bytes"
            print *, "This *could* cause problems when reading .dat files"
         end if

         call MPI_FILE_SEEK(slice_fh, int(size_int,kind=MPI_OFFSET_KIND),&
            MPI_SEEK_SET, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, int(tree_offset), 1, MPI_INTEGER,&
            status, ierrmpi)
         call MPI_FILE_WRITE(slice_fh, int(block_offset), 1, MPI_INTEGER,&
            status, ierrmpi)

         call MPI_FILE_CLOSE(slice_fh,ierrmpi)
      end if

      call MPI_BCAST(nsubleafs, 1, MPI_INTEGER, 0, icomm, ierrmpi)
      call MPI_BCAST(nsubparents, 1, MPI_INTEGER, 0, icomm, ierrmpi)

      if (mype /= 0) then
         allocate(block_offset_sub(nsubleafs))
      end if

      call MPI_BCAST(block_offset_sub, nsubleafs, MPI_OFFSET, 0, icomm,&
         ierrmpi)

      amode=ior(MPI_MODE_CREATE,MPI_MODE_WRONLY)
      call MPI_FILE_OPEN(icomm,filename,amode,MPI_INFO_NULL,slice_fh,ierrmpi)
      iorequest=MPI_REQUEST_NULL
      iwrite=0
      n_ghost_sub = 0

      do jgrid=1,Njgrid
         iwrite=iwrite+1
         offset=block_offset_sub(int(Morton_sub_start(mype)+jgrid-1))
         call MPI_FILE_IWRITE_AT(slice_fh,offset,n_ghost_sub,2*(ndim-1),&
            MPI_INTEGER, iorequest(iwrite),ierrmpi)
         iwrite=iwrite+1
         offset1=offset+int(2*(ndim-1)*size_int,kind=MPI_OFFSET_KIND)
         call MPI_FILE_IWRITE_AT(slice_fh,offset1,ps_sub(jgrid)%w,1,&
            type_subblock_io, iorequest(iwrite),ierrmpi)
      end do

      if (iwrite>0) call MPI_WAITALL(iwrite,iorequest,iostatus,ierrmpi)
      call MPI_BARRIER(icomm, ierrmpi)
      call MPI_FILE_CLOSE(slice_fh,ierrmpi)

      deallocate(block_offset_sub)
      if (mype==0) then
         deallocate(block_ig_sub)
         deallocate(block_lvl_sub)
         deallocate(isleaf_sub)
      end if

    end subroutine put_slice_dat

    subroutine put_slice_zerod

      use mod_calculate_xw
      integer::  iw
      character(len=name_len) :: wnamei(1:nw+nwauxio),&
         xandwnamei(1:ndim+nw+nwauxio)
      character(len=1024) :: outfilehead
      logical, save :: opened=.false.
      character(len=1024) ::line, data
      character(len=1024) :: filename, xlabel
      character(len=79)   :: xxlabel
      integer :: amode, iwrite, status(MPI_STATUS_SIZE)


    end subroutine put_slice_zerod

  end subroutine put_slice

  subroutine select_slice(dir,xslice,writeonly,file_handle,normconv)
    use mod_forest, only: iglevel1_sfc, sfc_iglevel1, tree_node_ptr,&
        tree_root, Morton_sub_start, Morton_sub_stop
    use mod_global_parameters
    integer, intent(in) :: dir
    double precision, intent(in) :: xslice
    integer, intent(in) :: file_handle
    logical, intent(in) :: writeonly
    double precision,dimension(0:nw+nwauxio),intent(out)       :: normconv
    ! .. local ..
    integer :: ig1,ig2,ig3, jgrid, slice_fh, ipe, mylevmax
    integer, dimension(nlevelshi) :: igslice
    integer, allocatable :: iglevel1_sub_sfc(:)
    integer :: igmin1, igmin2, igmin3, igmax1, igmax2, igmax3, ngsub1,&
       jglevel1, igsorted, kgrid, ngmax

    kgrid = 0
    jgrid = 0
    mylevmax = 0
    jglevel1 = 0

    ! Find the global slice index for every level:
    call get_igslice(dir,xslice,igslice)
    igmin1=1; igmin2=1; igmin3=1;
    igmax1=ng1(1); igmax2=ng2(1); igmax3=ng3(1);

    ! Traverse forest to find grids indicating slice:

    select case(dir)
    case (1)
       igmin1=igslice(1); igmax1=igslice(1);
    case (2)
       igmin2=igslice(1); igmax2=igslice(1);
    case (3)
       igmin3=igslice(1); igmax3=igslice(1);
    case default
       call mpistop("slice direction not clear in select_slice")
    end select

    ngsub1=((igmax1-igmin1+1)*(igmax2-igmin2+1)*(igmax3-igmin3+1))
    allocate(iglevel1_sub_sfc(ngsub1))
    if (.not. allocated(sfc_sub)) then
       ngmax = ngsub1*(4**refine_max_level-1)
       allocate(sfc_sub(0:ngmax,1:3))
       sfc_sub = 0
    end if

    do ig3=igmin3,igmax3
       do ig2=igmin2,igmax2
          do ig1=igmin1,igmax1
             jglevel1=jglevel1+1
             iglevel1_sub_sfc(jglevel1)=iglevel1_sfc(ig1,ig2,ig3)
          end do
       end do
    end do

    call quicksort_integer(iglevel1_sub_sfc, 1, ngsub1)

    do igsorted=1,ngsub1
       ig1 = sfc_iglevel1(1,iglevel1_sub_sfc(igsorted))
       ig2 = sfc_iglevel1(2,iglevel1_sub_sfc(igsorted))
       ig3 = sfc_iglevel1(3,iglevel1_sub_sfc(igsorted))
       call traverse_slice(tree_root(ig1,ig2,ig3))
    end do
    deallocate(iglevel1_sub_sfc)




    if (.not.writeonly) then
       ! Synchronize the levmax_sub for output (only rank 0 needs it):
       levmax_sub = mylevmax
       call MPI_ALLREDUCE(MPI_IN_PLACE,levmax_sub,1,MPI_INTEGER,MPI_MAX,icomm,&
          ierrmpi)

       ! Communicate the subgrid indices according to new Morton sub-sfc:
       Morton_sub_start(:) = 1
       do ipe=0,npe-1
          call MPI_GATHER(jgrid,1,MPI_INTEGER,Morton_sub_stop,1,MPI_INTEGER,&
             ipe,icomm,ierrmpi)
       end do

       do ipe = 0, npe-2
          Morton_sub_start(ipe+1) = Morton_sub_stop(ipe)+Morton_sub_start(ipe+&
             1)
          Morton_sub_stop(ipe+1)  = Morton_sub_stop(ipe)+Morton_sub_stop(ipe+&
             1)
       end do
    end if

  contains

    recursive subroutine traverse_slice(tree)
      implicit none
      type(tree_node_ptr) :: tree
      integer :: ic1,ic2,ic3

      if (mype==0) then
         kgrid = kgrid + 1
         sfc_sub(kgrid,1) = tree%node%igrid
         sfc_sub(kgrid,2) = tree%node%ipe
         if (tree%node%leaf) then
            sfc_sub(0,1) = sfc_sub(0,1) + 1
            sfc_sub(kgrid,3) = 1
         else
            sfc_sub(0,2) = sfc_sub(0,2) + 1
            sfc_sub(kgrid,3) = 0
         end if
      end if

      if (tree%node%leaf) then
         if (tree%node%ipe == mype.and..not.writeonly) then
            mylevmax = max(mylevmax,tree%node%level)
            call fill_subnode(tree%node%igrid,tree%node%active,jgrid,dir,&
               xslice,normconv)
         end if
         return
      end if
      ! We are out for leaves now, continue for branches

      ! Get the correct child:
      select case (dir)
         case (1)
         ic1 = igslice(tree%node%level+1) - 2 * tree%node%ig1 + 2

         case (2)
         ic2 = igslice(tree%node%level+1) - 2 * tree%node%ig2 + 2

         case (3)
         ic3 = igslice(tree%node%level+1) - 2 * tree%node%ig3 + 2

      case default
         call mpistop("slice direction not clear in traverse_slice")
      end select

      ! Recursively descend into the correct child branch:

      select case(dir)
      case (1)
         do ic3=1,2
            do ic2=1,2
               call traverse_slice(tree%node%child(ic1,ic2,ic3))
            end do
         end do
      case (2)
         do ic3=1,2
            do ic1=1,2
               call traverse_slice(tree%node%child(ic1,ic2,ic3))
            end do
         end do
      case (3)
         do ic2=1,2
            do ic1=1,2
               call traverse_slice(tree%node%child(ic1,ic2,ic3))
            end do
         end do
      case default
         call mpistop("slice direction not clear in traverse_slice")
      end select




    end subroutine traverse_slice

  end subroutine select_slice

  subroutine fill_subnode(igrid,active,jgrid,dir,xslice,normconv)
    use mod_global_parameters
    use mod_calculate_xw
    integer, intent(in)                                       :: igrid, dir
    integer, intent(inout)                                    :: jgrid
    logical, intent(in)                                       :: active
    double precision, intent(in)                              :: xslice
    double precision,dimension(0:nw+nwauxio),intent(out)      :: normconv
    ! .. local ..
    double precision, dimension(ixMlo1-1:ixMhi1,ixMlo2-1:ixMhi2,&
       ixMlo3-1:ixMhi3,ndim)       :: xC_TMP, xC
    double precision, dimension(ixMlo1:ixMhi1,ixMlo2:ixMhi2,ixMlo3:ixMhi3,&
       ndim)         :: xCC_TMP, xCC
    double precision, dimension(ixMlo1-1:ixMhi1,ixMlo2-1:ixMhi2,&
       ixMlo3-1:ixMhi3,nw+nwauxio) :: wC_TMP
    double precision, dimension(ixMlo1:ixMhi1,ixMlo2:ixMhi2,ixMlo3:ixMhi3,&
       nw+nwauxio)   :: wCC_TMP
    double precision, dimension(ixGlo1:ixGhi1,ixGlo2:ixGhi2,&
       ixGlo3:ixGhi3)                        :: x_save
    integer                :: ixslice, nwexpand, ixCmin1,ixCmin2,ixCmin3,&
       ixCmax1,ixCmax2,ixCmax3, ixCCmin1,ixCCmin2,ixCCmin3,ixCCmax1,ixCCmax2,&
       ixCCmax3
    logical                :: mask(ixGlo1:ixGhi1,ixGlo2:ixGhi2,ixGlo3:ixGhi3)

    mask=.false.
    ! increase grid-count:
    jgrid=jgrid+1
    ! Allocate subdim solution array:
    if (ndim==1) then
       nwexpand = nwauxio
    else
       if(slice_type/='dat')then
          nwexpand = nwauxio
       else
          nwexpand = 0
       endif
    end if
    call alloc_subnode(jgrid,dir,nwexpand)
    call fill_subnode_info(igrid,jgrid,dir)

    mask(ixMlo1:ixMhi1,ixMlo2:ixMhi2,ixMlo3:ixMhi3)=.true.

    ! Now hunt for the index closest to the slice:



    select case (dir)
    case (1)
       ixslice = minloc(dabs(xslice-ps(igrid)%x(:,ixMlo2,ixMlo3,dir)),1,mask(:,&
          ixMlo2,ixMlo3))
    case (2)
       ixslice = minloc(dabs(xslice-ps(igrid)%x(ixMlo1,:,ixMlo3,dir)),1,&
          mask(ixMlo1,:,ixMlo3))
    case (3)
       ixslice = minloc(dabs(xslice-ps(igrid)%x(ixMlo1,ixMlo2,:,dir)),1,&
          mask(ixMlo1,ixMlo2,:))
    case default
       call mpistop("slice direction not clear in fill_subnode")
    end select


    call calc_x(igrid,xC,xCC)
    ! Set the coordinate to be exactly on the slice:
    xC(:,:,:,dir)  = xslice
    xCC(:,:,:,dir) = xslice
    call calc_grid(unitslice,igrid,xC,xCC,xC_TMP,xCC_TMP,wC_TMP,wCC_TMP,&
       normconv,ixCmin1,ixCmin2,ixCmin3,ixCmax1,ixCmax2,ixCmax3,ixCCmin1,&
       ixCCmin2,ixCCmin3,ixCCmax1,ixCCmax2,ixCCmax3,.true.)
    ! CC stands for CellCenter
    ! C  stands for Corner

    ! Fill the subdimensional solution and position array:



    select case (dir)
    case (1)
       ps_sub(jgrid)%w(ixCCmin2:ixCCmax2,ixCCmin3:ixCCmax3,&
          1:nw+nwexpand) = wCC_TMP(ixslice,ixCCmin2:ixCCmax2,ixCCmin3:ixCCmax3,&
          1:nw+nwexpand)
       ps_sub(jgrid)%x(ixCCmin2:ixCCmax2,ixCCmin3:ixCCmax3,&
          1:ndim) = xCC_TMP(ixslice,ixCCmin2:ixCCmax2,ixCCmin3:ixCCmax3,&
          1:ndim)
       ps_sub(jgrid)%wC(ixCmin2:ixCmax2,ixCmin3:ixCmax3,&
          1:nw+nwexpand) = wC_TMP(ixslice,ixCmin2:ixCmax2,ixCmin3:ixCmax3,&
          1:nw+nwexpand)
       ps_sub(jgrid)%xC(ixCmin2:ixCmax2,ixCmin3:ixCmax3,&
          1:ndim) = xC_TMP(ixslice,ixCmin2:ixCmax2,ixCmin3:ixCmax3,1:ndim)
    case (2)
       ps_sub(jgrid)%w(ixCCmin1:ixCCmax1,ixCCmin3:ixCCmax3,&
          1:nw+nwexpand) = wCC_TMP(ixCCmin1:ixCCmax1,ixslice,ixCCmin3:ixCCmax3,&
          1:nw+nwexpand)
       ps_sub(jgrid)%x(ixCCmin1:ixCCmax1,ixCCmin3:ixCCmax3,&
          1:ndim) = xCC_TMP(ixCCmin1:ixCCmax1,ixslice,ixCCmin3:ixCCmax3,&
          1:ndim)
       ps_sub(jgrid)%wC(ixCmin1:ixCmax1,ixCmin3:ixCmax3,&
          1:nw+nwexpand) = wC_TMP(ixCmin1:ixCmax1,ixslice,ixCmin3:ixCmax3,&
          1:nw+nwexpand)
       ps_sub(jgrid)%xC(ixCmin1:ixCmax1,ixCmin3:ixCmax3,&
          1:ndim) = xC_TMP(ixCmin1:ixCmax1,ixslice,ixCmin3:ixCmax3,1:ndim)
    case (3)
       ps_sub(jgrid)%w(ixCCmin1:ixCCmax1,ixCCmin2:ixCCmax2,&
          1:nw+nwexpand) = wCC_TMP(ixCCmin1:ixCCmax1,ixCCmin2:ixCCmax2,ixslice,&
          1:nw+nwexpand)
       ps_sub(jgrid)%x(ixCCmin1:ixCCmax1,ixCCmin2:ixCCmax2,&
          1:ndim) = xCC_TMP(ixCCmin1:ixCCmax1,ixCCmin2:ixCCmax2,ixslice,&
          1:ndim)
       ps_sub(jgrid)%wC(ixCmin1:ixCmax1,ixCmin2:ixCmax2,&
          1:nw+nwexpand) = wC_TMP(ixCmin1:ixCmax1,ixCmin2:ixCmax2,ixslice,&
          1:nw+nwexpand)
       ps_sub(jgrid)%xC(ixCmin1:ixCmax1,ixCmin2:ixCmax2,&
          1:ndim) = xC_TMP(ixCmin1:ixCmax1,ixCmin2:ixCmax2,ixslice,1:ndim)
    case default
       call mpistop("slice direction not clear in fill_subnode")
    end select


  end subroutine fill_subnode

  subroutine alloc_subnode(jgrid,dir,nwexpand)
    use mod_global_parameters
    integer, intent(in) :: jgrid, dir, nwexpand

    ! take care, what comes out is not necessarily a right handed system!



    select case (dir)
    case (1)
       allocate(ps_sub(jgrid)%w(ixGlo2:ixGhi2,ixGlo3:ixGhi3,1:nw+nwexpand),&
          ps_sub(jgrid)%x(ixGlo2:ixGhi2,ixGlo3:ixGhi3,1:ndim),&
           ps_sub(jgrid)%wC(ixGlo2:ixGhi2,ixGlo3:ixGhi3,1:nw+nwexpand),&
          ps_sub(jgrid)%xC(ixGlo2:ixGhi2,ixGlo3:ixGhi3,1:ndim))
    case (2)
       allocate(ps_sub(jgrid)%w(ixGlo1:ixGhi1,ixGlo3:ixGhi3,1:nw+nwexpand),&
          ps_sub(jgrid)%x(ixGlo1:ixGhi1,ixGlo3:ixGhi3,1:ndim),&
           ps_sub(jgrid)%wC(ixGlo1:ixGhi1,ixGlo3:ixGhi3,1:nw+nwexpand),&
          ps_sub(jgrid)%xC(ixGlo1:ixGhi1,ixGlo3:ixGhi3,1:ndim))
    case (3)
       allocate(ps_sub(jgrid)%w(ixGlo1:ixGhi1,ixGlo2:ixGhi2,1:nw+nwexpand),&
          ps_sub(jgrid)%x(ixGlo1:ixGhi1,ixGlo2:ixGhi2,1:ndim),&
           ps_sub(jgrid)%wC(ixGlo1:ixGhi1,ixGlo2:ixGhi2,1:nw+nwexpand),&
          ps_sub(jgrid)%xC(ixGlo1:ixGhi1,ixGlo2:ixGhi2,1:ndim))
    case default
       call mpistop("slice direction not clear in alloc_subnode")
    end select

  end subroutine alloc_subnode

  subroutine dealloc_subnode(jgrid)
    use mod_global_parameters
    integer, intent(in) :: jgrid

    if (jgrid==0) then
       call mpistop("trying to delete a non-existing grid in dealloc_subnode")
    end if

    deallocate(ps_sub(jgrid)%w,ps_sub(jgrid)%x,ps_sub(jgrid)%wC,&
       ps_sub(jgrid)%xC)

    ! reset the global node info:
    node_sub(:,jgrid)=0
    rnode_sub(:,jgrid)=zero

  end subroutine dealloc_subnode

  subroutine fill_subnode_info(igrid,jgrid,dir)
    use mod_global_parameters
    integer, intent(in) :: igrid,jgrid,dir

    node_sub(plevel_,jgrid)=node(plevel_,igrid)

    select case(dir)
    case (1)
       node_sub(pig1_,jgrid)=node(pig2_,igrid)
       node_sub(pig2_,jgrid)=node(pig3_,igrid)
       rnode_sub(rpdx1_,jgrid)=rnode(rpdx2_,igrid)
       rnode_sub(rpdx2_,jgrid)=rnode(rpdx3_,igrid)
       rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin2_,igrid)
       rnode_sub(rpxmin2_,jgrid)=rnode(rpxmin3_,igrid)
    case (2)
       node_sub(pig1_,jgrid)=node(pig1_,igrid)
       node_sub(pig2_,jgrid)=node(pig3_,igrid)
       rnode_sub(rpdx1_,jgrid)=rnode(rpdx1_,igrid)
       rnode_sub(rpdx2_,jgrid)=rnode(rpdx3_,igrid)
       rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin1_,igrid)
       rnode_sub(rpxmin2_,jgrid)=rnode(rpxmin3_,igrid)
    case (3)
       node_sub(pig1_,jgrid)=node(pig1_,igrid)
       node_sub(pig2_,jgrid)=node(pig2_,igrid)
       rnode_sub(rpdx1_,jgrid)=rnode(rpdx1_,igrid)
       rnode_sub(rpdx2_,jgrid)=rnode(rpdx2_,igrid)
       rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin1_,igrid)
       rnode_sub(rpxmin2_,jgrid)=rnode(rpxmin2_,igrid)
    case default
       call mpistop("slice direction not clear in fill_subnode_info")
    end select




  end subroutine fill_subnode_info

  !> Block indices, per level, of the blocks a slice passes through.
  !>
  !> The position comes in as a *physical* coordinate, because that is what the
  !> rest of the slice machinery uses - fill_subnode picks the cell within a
  !> block by comparing against ps(igrid)%x. Everything below, though, is
  !> block-index arithmetic in the *logical* coordinate, the one xprobmin, dg
  !> and ng are expressed in. Under LOG_RADIUS those differ, so the conversion
  !> is done here, once, and the body is unchanged.
  !>
  !> Getting this backwards is a silent trap: converting the slice position at
  !> read time instead would fix this routine and break fill_subnode, whose
  !> minloc would then match nothing, return 0, and emit a slice with all-zero
  !> coordinates without any error.
  subroutine get_igslice(dir,xphys,igslice)
    use mod_global_parameters
    use mod_geometry, only: s_of_r
    integer, intent(in) :: dir
    !> slice position, a physical coordinate
    double precision, intent(in) :: xphys
    integer, dimension(nlevelshi), intent(out) :: igslice
    ! .. local ..
    integer :: level
    double precision :: distance
    !> the same position in the logical coordinate used below
    double precision :: x
    !double precision :: xsgrid(ndim,nlevelshi),qs(ndim),xmgrid(ndim,3),xnew,xlgrid(ndim,3)
    !integer :: nbefore

    if (xphys.ne.xphys) call mpistop("get_igslice: your slice position is NaN!")

    x = xphys

    select case (dir)
    case (1)
      select case (stretch_type(1))
      case (stretch_none) ! This dimension is unstretched
        if (x<=xprobmin1) then
          igslice=1
        else if (x>=xprobmax1) then
          do level=1,refine_max_level
            igslice(level)=ng1(level)
          end do
        else
          distance=x-xprobmin1
          do level = 1, refine_max_level
            igslice(level) = ceiling(distance/dg1(level))
          end do
        end if

      case (stretch_uni) ! Uniform stretching

        if (x<=xprobmin1) then
          igslice=1
        else if (x>=xprobmax1) then
          do level=1,refine_max_level
            igslice(level)=ng1(level)
          end do
        else
          distance=x-xprobmin1
          do level=1,refine_max_level
            igslice(level)= ceiling(dlog(distance/dxfirst(level,&
               1)*(qstretch(level,1)-1.d0)+1.d0)/dlog(qstretch(level,&
               1))/dble(block_nx1))
          end do
        end if

      case (stretch_symm) ! Symmetric stretching
        ! symmetric stretch about 0.5*(xprobmin+xprobmax)
        if (x<=xprobmin1) then
          igslice=1
        else if (x>=xprobmax1) then
          do level=1,refine_max_level
            igslice(level)=ng1(level)
          end do
        else if(x<xprobmin1+xstretch1) then
          distance=xprobmin1+xstretch1-x
          ! stretch to left from xprobmin+xstretch
          do level=1,refine_max_level
            igslice(level) = nstretchedblocks(level,&
               1)/2-int(dlog(distance*(qstretch(level,1)-one)/dxfirst(level,&
               1)+one)/dlog(qstretch(level,1))/dble(block_nx1))
          end do
        else if(x>xprobmax1-xstretch1) then
          distance=x-xprobmax1+xstretch1
          ! stretch to right from xprobmax-xstretch
          do level=1,refine_max_level
            igslice(level) = ceiling(dlog(distance*(qstretch(level,&
               1)-one)/dxfirst(level,1)+one)/dlog(qstretch(level,&
               1))/dble(block_nx1))+ng1(level)-nstretchedblocks(level,1)/2
          end do
        else
          ! possible non-stretched central part
          distance=x-xprobmin1-xstretch1
          do level=1,refine_max_level
            igslice(level)=nstretchedblocks(level,&
               1)/2+ceiling(distance/dg1(level))
          end do
        end if
 !xsgrid(1,1)=half*(xprobmax1-xprobmin1)!        /(half*domain_nx1-half*nstretchedblocks_baselevel(1)*block_nx1 !        +(one-qstretch_baselevel(1)**(half*nstretchedblocks_baselevel(1)*block_nx1)) !        /(one-qstretch_baselevel(1)))
 !xmgrid(1,1)=xsgrid(1,1)*(domain_nx1-nstretchedblocks_baselevel(1)*block_nx1)
        !xlgrid(1,1)=xsgrid(1,1)

        !if (x .ge. xmgrid(1,1)*half) then
        !  xnew=x-xmgrid(1,1)*half
        !  do level=1,refine_max_level
        !    qs(1)=qstretch_baselevel(1)**(one/2.d0**(level-1))
        !    if (level .gt. 1) xsgrid(1,level)=xsgrid(1,level-1)/(one+qs(1))
 !nbefore=(domain_nx1/block_nx1-nstretchedblocks_baselevel(1)/2)*2**(level-1)
 !igslice(level)=floor((dlog(one-xnew/xsgrid(1,level)*(one-qs(1)))/dlog(qs(1))-1.e-16)/block_nx1)+1+nbefore
        !    if (x>=xprobmax1) igslice(level)=domain_nx1*2**(level-1)
        !  end do
        !else if(x .ge. -xmgrid(1,1)*half) then
        !  xnew=x+xmgrid(1,1)*half
        !  do level=1,refine_max_level
        !    nbefore=nstretchedblocks_baselevel(1)/2*2**(level-1)
        !    if (level .gt. 1) xlgrid(1,level)=xlgrid(1,level-1)/2.d0
 !igslice(level)=floor(((xnew-1.e-16)/xlgrid(1,level))/block_nx1)+1+nbefore
        !  end do
        !else
        !  xnew=xmgrid(1,1)*half-x
        !  do level=1,refine_max_level
        !    qs(1)=qstretch_baselevel(1)**(one/2.d0**(level-1))
        !    if (level .gt. 1) xsgrid(1,level)=xsgrid(1,level-1)/(one+qs(1))
 !igslice(level)=nstretchedblocks_baselevel(1)/2*2**(level-1) !      -floor((dlog(one-xnew/xsgrid(1,level)*(one-qs(1)))/dlog(qs(1)))/block_nx1)
        !    if (x<=xprobmin1) igslice(level)=1
        !  end do
        !end if

      case default
        call mpistop("stretch type not supported by get_igslice")
      end select

    case (2)
      select case (stretch_type(2))
      case (stretch_none) ! This dimension is unstretched
        if (x<=xprobmin2) then
          igslice=1
        else if (x>=xprobmax2) then
          do level=1,refine_max_level
            igslice(level)=ng2(level)
          end do
        else
          distance=x-xprobmin2
          do level = 1, refine_max_level
            igslice(level) = ceiling(distance/dg2(level))
          end do
        end if

      case (stretch_uni) ! Uniform stretching

        if (x<=xprobmin2) then
          igslice=1
        else if (x>=xprobmax2) then
          do level=1,refine_max_level
            igslice(level)=ng2(level)
          end do
        else
          distance=x-xprobmin2
          do level=1,refine_max_level
            igslice(level)= ceiling(dlog(distance/dxfirst(level,&
               2)*(qstretch(level,2)-1.d0)+1.d0)/dlog(qstretch(level,&
               2))/dble(block_nx2))
          end do
        end if

      case (stretch_symm) ! Symmetric stretching
        ! symmetric stretch about 0.5*(xprobmin+xprobmax)
        if (x<=xprobmin2) then
          igslice=1
        else if (x>=xprobmax2) then
          do level=1,refine_max_level
            igslice(level)=ng2(level)
          end do
        else if(x<xprobmin2+xstretch2) then
          distance=xprobmin2+xstretch2-x
          ! stretch to left from xprobmin+xstretch
          do level=1,refine_max_level
            igslice(level) = nstretchedblocks(level,&
               2)/2-int(dlog(distance*(qstretch(level,2)-one)/dxfirst(level,&
               2)+one)/dlog(qstretch(level,2))/dble(block_nx2))
          end do
        else if(x>xprobmax2-xstretch2) then
          distance=x-xprobmax2+xstretch2
          ! stretch to right from xprobmax-xstretch
          do level=1,refine_max_level
            igslice(level) = ceiling(dlog(distance*(qstretch(level,&
               2)-one)/dxfirst(level,2)+one)/dlog(qstretch(level,&
               2))/dble(block_nx2))+ng2(level)-nstretchedblocks(level,2)/2
          end do
        else
          ! possible non-stretched central part
          distance=x-xprobmin2-xstretch2
          do level=1,refine_max_level
            igslice(level)=nstretchedblocks(level,&
               2)/2+ceiling(distance/dg2(level))
          end do
        end if
 !xsgrid(2,1)=half*(xprobmax2-xprobmin2)!        /(half*domain_nx2-half*nstretchedblocks_baselevel(2)*block_nx2 !        +(one-qstretch_baselevel(2)**(half*nstretchedblocks_baselevel(2)*block_nx2)) !        /(one-qstretch_baselevel(2)))
 !xmgrid(2,1)=xsgrid(2,1)*(domain_nx2-nstretchedblocks_baselevel(2)*block_nx2)
        !xlgrid(2,1)=xsgrid(2,1)

        !if (x .ge. xmgrid(2,1)*half) then
        !  xnew=x-xmgrid(2,1)*half
        !  do level=1,refine_max_level
        !    qs(2)=qstretch_baselevel(2)**(one/2.d0**(level-1))
        !    if (level .gt. 1) xsgrid(2,level)=xsgrid(2,level-1)/(one+qs(2))
 !nbefore=(domain_nx2/block_nx2-nstretchedblocks_baselevel(2)/2)*2**(level-1)
 !igslice(level)=floor((dlog(one-xnew/xsgrid(2,level)*(one-qs(2)))/dlog(qs(2))-1.e-16)/block_nx2)+1+nbefore
        !    if (x>=xprobmax2) igslice(level)=domain_nx2*2**(level-1)
        !  end do
        !else if(x .ge. -xmgrid(2,1)*half) then
        !  xnew=x+xmgrid(2,1)*half
        !  do level=1,refine_max_level
        !    nbefore=nstretchedblocks_baselevel(2)/2*2**(level-1)
        !    if (level .gt. 1) xlgrid(2,level)=xlgrid(2,level-1)/2.d0
 !igslice(level)=floor(((xnew-1.e-16)/xlgrid(2,level))/block_nx2)+1+nbefore
        !  end do
        !else
        !  xnew=xmgrid(2,1)*half-x
        !  do level=1,refine_max_level
        !    qs(2)=qstretch_baselevel(2)**(one/2.d0**(level-1))
        !    if (level .gt. 1) xsgrid(2,level)=xsgrid(2,level-1)/(one+qs(2))
 !igslice(level)=nstretchedblocks_baselevel(2)/2*2**(level-1) !      -floor((dlog(one-xnew/xsgrid(2,level)*(one-qs(2)))/dlog(qs(2)))/block_nx2)
        !    if (x<=xprobmin2) igslice(level)=1
        !  end do
        !end if

      case default
        call mpistop("stretch type not supported by get_igslice")
      end select

    case (3)
      select case (stretch_type(3))
      case (stretch_none) ! This dimension is unstretched
        if (x<=xprobmin3) then
          igslice=1
        else if (x>=xprobmax3) then
          do level=1,refine_max_level
            igslice(level)=ng3(level)
          end do
        else
          distance=x-xprobmin3
          do level = 1, refine_max_level
            igslice(level) = ceiling(distance/dg3(level))
          end do
        end if

      case (stretch_uni) ! Uniform stretching

        if (x<=xprobmin3) then
          igslice=1
        else if (x>=xprobmax3) then
          do level=1,refine_max_level
            igslice(level)=ng3(level)
          end do
        else
          distance=x-xprobmin3
          do level=1,refine_max_level
            igslice(level)= ceiling(dlog(distance/dxfirst(level,&
               3)*(qstretch(level,3)-1.d0)+1.d0)/dlog(qstretch(level,&
               3))/dble(block_nx3))
          end do
        end if

      case (stretch_symm) ! Symmetric stretching
        ! symmetric stretch about 0.5*(xprobmin+xprobmax)
        if (x<=xprobmin3) then
          igslice=1
        else if (x>=xprobmax3) then
          do level=1,refine_max_level
            igslice(level)=ng3(level)
          end do
        else if(x<xprobmin3+xstretch3) then
          distance=xprobmin3+xstretch3-x
          ! stretch to left from xprobmin+xstretch
          do level=1,refine_max_level
            igslice(level) = nstretchedblocks(level,&
               3)/2-int(dlog(distance*(qstretch(level,3)-one)/dxfirst(level,&
               3)+one)/dlog(qstretch(level,3))/dble(block_nx3))
          end do
        else if(x>xprobmax3-xstretch3) then
          distance=x-xprobmax3+xstretch3
          ! stretch to right from xprobmax-xstretch
          do level=1,refine_max_level
            igslice(level) = ceiling(dlog(distance*(qstretch(level,&
               3)-one)/dxfirst(level,3)+one)/dlog(qstretch(level,&
               3))/dble(block_nx3))+ng3(level)-nstretchedblocks(level,3)/2
          end do
        else
          ! possible non-stretched central part
          distance=x-xprobmin3-xstretch3
          do level=1,refine_max_level
            igslice(level)=nstretchedblocks(level,&
               3)/2+ceiling(distance/dg3(level))
          end do
        end if
 !xsgrid(3,1)=half*(xprobmax3-xprobmin3)!        /(half*domain_nx3-half*nstretchedblocks_baselevel(3)*block_nx3 !        +(one-qstretch_baselevel(3)**(half*nstretchedblocks_baselevel(3)*block_nx3)) !        /(one-qstretch_baselevel(3)))
 !xmgrid(3,1)=xsgrid(3,1)*(domain_nx3-nstretchedblocks_baselevel(3)*block_nx3)
        !xlgrid(3,1)=xsgrid(3,1)

        !if (x .ge. xmgrid(3,1)*half) then
        !  xnew=x-xmgrid(3,1)*half
        !  do level=1,refine_max_level
        !    qs(3)=qstretch_baselevel(3)**(one/2.d0**(level-1))
        !    if (level .gt. 1) xsgrid(3,level)=xsgrid(3,level-1)/(one+qs(3))
 !nbefore=(domain_nx3/block_nx3-nstretchedblocks_baselevel(3)/2)*2**(level-1)
 !igslice(level)=floor((dlog(one-xnew/xsgrid(3,level)*(one-qs(3)))/dlog(qs(3))-1.e-16)/block_nx3)+1+nbefore
        !    if (x>=xprobmax3) igslice(level)=domain_nx3*2**(level-1)
        !  end do
        !else if(x .ge. -xmgrid(3,1)*half) then
        !  xnew=x+xmgrid(3,1)*half
        !  do level=1,refine_max_level
        !    nbefore=nstretchedblocks_baselevel(3)/2*2**(level-1)
        !    if (level .gt. 1) xlgrid(3,level)=xlgrid(3,level-1)/2.d0
 !igslice(level)=floor(((xnew-1.e-16)/xlgrid(3,level))/block_nx3)+1+nbefore
        !  end do
        !else
        !  xnew=xmgrid(3,1)*half-x
        !  do level=1,refine_max_level
        !    qs(3)=qstretch_baselevel(3)**(one/2.d0**(level-1))
        !    if (level .gt. 1) xsgrid(3,level)=xsgrid(3,level-1)/(one+qs(3))
 !igslice(level)=nstretchedblocks_baselevel(3)/2*2**(level-1) !      -floor((dlog(one-xnew/xsgrid(3,level)*(one-qs(3)))/dlog(qs(3)))/block_nx3)
        !    if (x<=xprobmin3) igslice(level)=1
        !  end do
        !end if

      case default
        call mpistop("stretch type not supported by get_igslice")
      end select

    case default
      call mpistop("slice direction not clear in get_igslice")
    end select

  end subroutine get_igslice

  double precision function roundoff_minmax(val,minval,maxval)
    implicit none
    double precision,intent(in)         :: val, minval, maxval

    roundoff_minmax = val

    if (abs(roundoff_minmax) .le. minval) then
       roundoff_minmax = 0.0d0
    end if

    if (roundoff_minmax .gt. maxval) then
       roundoff_minmax = maxval
    else if (roundoff_minmax .lt. -maxval) then
       roundoff_minmax = -maxval
    end if

    ! Replace NaN with maxval (e.g. Paraview chokes on ASCII NaN):
    if (roundoff_minmax /= roundoff_minmax) roundoff_minmax = maxval

  end function roundoff_minmax

  recursive subroutine quicksort_integer(arr, left, right)
    integer, intent(inout) :: arr(:)
    integer, intent(in) :: left, right
    integer :: i, j, pivot, temp

    if (left < right) then
       pivot = arr((left + right) / 2)
       i = left
       j = right

       do
          do while (arr(i) < pivot)
             i = i + 1
          end do
          do while (arr(j) > pivot)
             j = j - 1
          end do

          if (i >= j) exit

          temp = arr(i)
          arr(i) = arr(j)
          arr(j) = temp
          i = i + 1
          j = j - 1
       end do

       call quicksort_integer(arr, left, j)
       call quicksort_integer(arr, j + 1, right)
    end if

  end subroutine quicksort_integer

end module mod_slice