!-----------------------------------------------------------------
!
!  This file is (or was) part of SPLASH, a visualisation tool
!  for Smoothed Particle Hydrodynamics written by Daniel Price:
!
!  http://users.monash.edu.au/~dprice/splash
!
!  SPLASH comes with ABSOLUTELY NO WARRANTY.
!  This is free software; and you are welcome to redistribute
!  it under the terms of the GNU General Public License
!  (see LICENSE file for details) and the provision that
!  this notice remains intact. If you modify this file, please
!  note section 2a) of the GPLv2 states that:
!
!  a) You must cause the modified files to carry prominent notices
!     stating that you changed the files and the date of any change.
!
!  Copyright (C) 2005-2012 Daniel Price. All rights reserved.
!  Contact: daniel.price@monash.edu
!
!-----------------------------------------------------------------

!-------------------------------------------------------------------------
! this subroutine reads from the data file(s)
! change this to change the format of data input
!
! THIS VERSION IS FOR READING UNFORMATTED OUTPUT FROM STEPHAN ROSSWOG'S CODE
! (ie. STRAIGHT FROM THE DATA DUMP)
!
! *** CONVERTS TO SINGLE PRECISION ***
!
! SOME CHOICES FOR THIS FORMAT CAN BE SET USING THE FOLLOWING
!  ENVIRONMENT VARIABLES:
!
! RSPLASH_FORMAT can be 'MHD' or 'HYDRO'
! RSPLASH_RESET_COM if 'YES' then centre of mass is reset for n2=0 (ie single objects)
! RSPLASH_COROTATING if 'YES' then velocities are transformed to corotating frame
! RSPLASH_HFACT can be changed to give correct hfact value for particle masses
!  on minidumps: e.g. setenv RSPLASH_HFACT=1.2
!
! the data is stored in the global array dat
!
! >> this subroutine must return values for the following: <<
!
! ncolumns    : number of data columns
! ndim, ndimV : number of spatial, velocity dimensions
! nstepsread  : number of steps read from this file
!
! maxplot,maxpart,maxstep      : dimensions of main data array
! dat(maxplot,maxpart,maxstep) : main data array
!
! npartoftype(1:6,maxstep) : number of particles of each type in each timestep
!
! time(maxstep)       : time at each step
! gamma(maxstep)      : gamma at each step
!
! most of these values are stored in global arrays
! in the module 'particle_data'
!-------------------------------------------------------------------------

subroutine read_data(rootname,indexstart,ipos,nstepsread)
 use particle_data, only:dat,time,npartoftype,gamma,maxpart,maxcol,maxstep
 use params
 use settings_data, only:ndim,ndimV,ncolumns,iformat
 use mem_allocation, only:alloc
 use system_utils, only:lenvironment
 use system_commands, only:get_environment
 implicit none
 integer, intent(in) :: indexstart,ipos
 integer, intent(out) :: nstepsread
 character(len=*), intent(in) :: rootname
 integer, parameter :: max_spec = 7 ! number of species in abundance file
 real :: hfact, dhfact3,hfacttemp
 integer :: i,j,k,ierr,ierr1
 integer :: nprint,nptmass,npart_max,nstep_max
 integer :: n1,n2,idump,ncol
 logical :: iexist,magfield,minidump,doubleprec,iabunfileopen
 character(len=len(rootname)) :: dumpfile
 character(len=13) :: abunfile
 character(len=10) :: string
 real :: timei,tkin,tgrav,tterm,escap,rstar,mstar,Etot_burn_cgs
 real(doub_prec) :: timedb,tkindb,tgravdb,ttermdb
 real(doub_prec) :: escapdb,rstardb,mstardb,Etot_burn_cgsdb
 real(doub_prec), dimension(:,:), allocatable :: datdb

 nstepsread = 0
 nstep_max = 0
 npart_max = maxpart
 iabunfileopen = .false.
 hfact = 1.5
 dhfact3 = 1./hfact**3

 dumpfile = trim(rootname)
 !
 !--check if first data file exists
 !
 inquire(file=dumpfile,exist=iexist)
 if (.not.iexist) then
    print "(a)",' *** error: '//trim(dumpfile)//': file not found ***'
    return
 endif
 !
 !--use minidump format if minidump
 !
 minidump = .false.
 if (index(dumpfile,'minidump') /= 0) minidump = .true.
 !
 !--get hfact for minidumps
 !
 if (minidump) then
    call get_environment('RSPLASH_HFACT',string)
    read(string,*,iostat=ierr) hfacttemp
    if (hfacttemp > 0.5 .and. hfacttemp  < 10.0 .and. ierr==0) then
       hfact = hfacttemp
       print *,'setting hfact =',hfact,' from RSPLASH_HFACT environment variable'
    else
       print "(1x,a)",'error reading hfact from RSPLASH_HFACT environment variable'
    endif
 endif
 !
 !--try to guess full dump format from file names
 !
 magfield = .true.
!  if (.not.minidump) then
!     if (index(dumpfile,'SMBH') > 0) magfield = .false.
!     if (index(dumpfile,'nsbh') > 0) magfield = .false.
!     if (index(dumpfile,'NSBH') > 0) magfield = .false.
!     if (index(dumpfile,'WD') > 0) magfield = .false.
!  endif
 !
 !--override this with environment variable
 !
 call get_environment('RSPLASH_FORMAT',string)
 select case(trim(adjustl(string)))
 case('MHD','mhd','ns','NS')
    magfield = .true.
 case('WD','hydro','HYDRO','ns_bh_v2')
    magfield = .false.
 end select

 if (magfield) then
    print "(1x,a)",'reading MAGMA code format (set RSPLASH_FORMAT=hydro for hydro format)'
 else
    print "(1x,a)",'reading Stephan Rosswog (hydro) code format (set RSPLASH_FORMAT=MHD for MAGMA)'
 endif

 !
 !--fix number of spatial dimensions
 !
 ndim = 3
 ndimV = 3
 if (magfield) then
    if (minidump) then
       ncol = 11
       iformat = 1
    else
       ncol = 27
       iformat = 2
    endif
 else
    if (minidump) then
       ncol = 7  ! number of columns in file
       iformat = 3
    else
       ncol = 16
       iformat = 4
    endif
 endif
 n1 = 0
 n2 = 0
 !
 !--allocate memory initially
 !
 nstep_max = max(nstep_max,indexstart,1)

 j = indexstart
 nstepsread = 0

 write(*,"(26('>'),1x,a,1x,26('<'))") trim(dumpfile)
 !
 !--open the (unformatted) binary file and read the number of particles
 !
 open(unit=15,iostat=ierr,file=dumpfile,status='old',form='unformatted')
 if (ierr /= 0) then
    print "(a)",'*** ERROR OPENING '//trim(dumpfile)//' ***'
    return
 else
    !
    !--read the number of particles in the first step,
    !  allocate memory and rewind
    !
    doubleprec = .true.
    if (minidump) then
       !--try double precision first
       read(15,end=55,iostat=ierr) timedb,nprint,nptmass
       !--change to single precision if stupid answers
       if (nprint <= 0.or.nprint > 1e10 &
            .or.nptmass < 0.or.nptmass > 1e6) then
          doubleprec = .false.
          rewind(15)
          read(15,end=55,iostat=ierr) timei,nprint,nptmass
          if (magfield) then
             print "(a)",' single precision MHD minidump'
          else
             print "(a)",' single precision hydro minidump'
          endif
       else
          if (magfield) then
             print "(a)",' double precision MHD minidump'
          else
             print "(a)",' double precision hydro minidump'
          endif
          timei = real(timedb)
       endif
    else
       !--try double precision first
       read(15,end=55,iostat=ierr) nprint,rstardb,mstardb,n1,n2, &
                nptmass,timedb
       !--change to single precision if stupid answers
       if (n1 < 0.or.n1 > 1e10.or.n2 < 0.or.n2 > 1e10 &
           .or.nptmass < 0.or.nptmass > 1.e6) then
          doubleprec = .false.
          rewind(15)
          read(15,end=55,iostat=ierr) nprint,rstar,mstar,n1,n2, &
                nptmass,timei
          if (magfield) then
             print "(a)",' single precision full MHD dump'
          else
             print "(a)",' single precision full hydro dump'
          endif
       else
          if (magfield) then
             print "(a)",' double precision full MHD dump'
          else
             print "(a)",' double precision full hydro dump'
          endif
          timei = real(timedb)
       endif
    endif
    print "(a,f10.2,a,i9,a,i6)",' time: ',timei,' npart: ',nprint,' nptmass: ',nptmass
    !--barf if stupid answers in single and double precision
    if (nptmass < 0.or.nptmass > 1.e6 .or. nprint < 0 &
         .or. nprint > 1e10 .or. (nprint==0 .and. nptmass==0)) then
       print "(a)",' *** ERRORS IN TIMESTEP HEADER: NO DATA READ ***'
       close(15)
       return
    endif

    ncolumns = ncol
    !
    !--check if abundance files are present and read from them
    !
    if (.not.magfield) then
       !--extract dump number from filename (last 5 characters)
       read(dumpfile(len_trim(dumpfile)-4:len_trim(dumpfile)),*,iostat=ierr1) idump
       if (ierr1 /= 0) then
          print "(a)",' error extracting dump number from filename'
       else
          write(abunfile,"(a,'.',i5.5)") 'abun_a7',idump
          inquire(file=abunfile,exist=iexist)
          if (.not.iexist) then
             print "(a)",' abundance file '//trim(abunfile)//' NOT FOUND'
          else
             open(unit=41,file=abunfile,status='old',form='unformatted',iostat=ierr1)
             if (ierr1 /= 0) then
                print "(a)",'*** ERROR OPENING '//trim(abunfile)
             else
                ncolumns = ncol + max_spec + 2
                iabunfileopen = .true.
             endif
          endif
       endif
    endif

    if (.not.allocated(dat) .or. (nprint+nptmass) > npart_max) then
       npart_max = max(npart_max,INT(1.1*(nprint+nptmass)))
       call alloc(npart_max,nstep_max,ncolumns)
    endif
    rewind(15)
 endif
 if (ierr /= 0) then
    print "(a)",'*** ERROR READING TIMESTEP HEADER ***'
 else
!
!--loop over the timesteps in this file
!
    npart_max = max(npart_max,nprint)
!
!--allocate/reallocate memory if j > maxstep
!
    if (j > maxstep) then
       call alloc(maxpart,j+1,maxcol)
    endif
!
!--now read the timestep data in the dumpfile
!
    if (magfield) then
       if (minidump) then
          dat(:,:,j) = 0.

          if (doubleprec) then
             allocate(datdb(maxpart,ncol),stat=ierr)
             if (ierr /= 0) then
                print*,"(a)",'*** error allocating memory for double conversion ***'
                return
             else
                datdb = 0.
             endif
             read(15,end=55,iostat=ierr) timedb,nprint,nptmass, &
                ((datdb(i,k),i=1,nprint),k=1,6),  &
                ((datdb(i,k),i=1,nprint),k=8,ncol), &
                (datdb(i,7), i=nprint+1, nprint+nptmass), &
                ((datdb(i,k), i=nprint+1, nprint+nptmass),k=1,3)

             if (ierr /= 0) print "(a)",'*** WARNING: ERRORS DURING READ ***'
             dat(:,1:ncol,j) = real(datdb(:,1:ncol))
             time(j) = real(timedb)

          else
             read(15,end=55,iostat=ierr) time(j),nprint,nptmass, &
                ((dat(i,k,j),i=1,nprint),k=1,6), &
                ((dat(i,k,j),i=1,nprint),k=8,ncol), &
                (dat(i,7,j), i=nprint+1, nprint+nptmass), &
                ((dat(i,k,j), i=nprint+1, nprint+nptmass),k=1,3)
          endif
          !
          !--because masses are not dumped, we need to reconstruct them
          !  from density and h (only strictly true for grad h code)
          !
          dat(1:nprint,7,j) = dat(1:nprint,4,j)**3*dat(1:nprint,5,j)*dhfact3
          print "(a,f5.2,a)", &
            ' WARNING: setting particle masses assuming h = ',hfact,'*(m/rho)^(1/3)'
       else

          dat(:,:,j) = 0. ! because ptmasses don't have all quantities
          !
          !--read full dump
          !
          if (doubleprec) then
             allocate(datdb(maxpart,27),stat=ierr)
             if (ierr /= 0) then
                print*,"(a)",'*** error allocating memory for double conversion ***'
                return
             else
                datdb = 0.
             endif
             read(15,iostat=ierr) nprint,rstardb,mstardb,n1,n2, &
                nptmass,timedb,(datdb(i,7),i=1,nprint), &
                escapdb,tkindb,tgravdb,ttermdb, &
                ((datdb(i,k),i=1,nprint),k=1,6), &
                ((datdb(i,k),i=1,nprint),k=8,ncol), &
                (datdb(i,9), i=nprint+1, nprint+nptmass), &
                ((datdb(i,k), i=nprint+1, nprint+nptmass),k=1,6), &
                ((datdb(i,k), i=nprint+1, nprint+nptmass),k=21,23)

             if (ierr < 0) print "(a)",'*** WARNING: END OF FILE DURING READ ***'
             if (ierr > 0) print "(a)",'*** WARNING: ERRORS DURING READ ***'
             dat(:,1:ncol,j) = real(datdb(:,1:ncol))
             time(j) = real(timedb)

          else
             read(15,iostat=ierr) nprint,rstar,mstar,n1,n2, &
                nptmass,time(j),(dat(i,7,j),i=1,nprint), &
                escap,tkin,tgrav,tterm, &
                ((dat(i,k,j),i=1,nprint),k=1,6), &
                ((dat(i,k,j),i=1,nprint),k=8,ncol), &
                (dat(i,9,j), i=nprint+1, nprint+nptmass), &
                ((dat(i,k,j), i=nprint+1, nprint+nptmass),k=1,6), &
                ((dat(i,k,j), i=nprint+1, nprint+nptmass),k=21,23)

             if (ierr < 0) print "(a)",'*** WARNING: END OF FILE DURING READ ***'
             if (ierr > 0) print "(a)",'*** WARNING: ERRORS DURING READ ***'

          endif
       endif
    else
       !
       !--hydro minidumps
       !
       if (minidump) then
          if (doubleprec) then
             allocate(datdb(maxpart,7),stat=ierr)
             if (ierr /= 0) then
                print*,"(a)",'*** error allocating memory for double conversion ***'
                return
             else
                datdb = 0.
             endif
             read(15,end=55,iostat=ierr) timedb,nprint,nptmass, &
              ((datdb(i,k), i=1, nprint),k=1,6), &
              (datdb(i,7), i=nprint+1, nprint+nptmass), &
              ((datdb(i,k), i=nprint+1, nprint+nptmass),k=1,3)

             if (ierr < 0) print "(a)",'*** WARNING: END OF FILE DURING READ ***'
             if (ierr > 0) print "(a)",'*** WARNING: ERRORS DURING READ ***'
             dat(:,1:ncol,j) = real(datdb(:,1:ncol))
             time(j) = real(timedb)
          else
             read(15,end=55,iostat=ierr) time(j),nprint,nptmass, &
              ((dat(i,k,j), i=1, nprint),k=1,6), &
              (dat(i,7,j), i=nprint+1, nprint+nptmass), &
              ((dat(i,k,j), i=nprint+1, nprint+nptmass),k=1,3)
          endif
          !
          !--because masses are not dumped, we need to reconstruct them
          !  from density and h (only strictly true for grad h code)
          !
          dat(1:nprint,7,j) = dat(1:nprint,4,j)**3*dat(1:nprint,5,j)*dhfact3
          print "(a,f5.2,a)", &
            ' WARNING: setting particle masses assuming h = ',hfact,'*(m/rho)^(1/3)'
       else
          !
          !--hydro full dumps
          !
          dat(:,:,j) = 0. ! because ptmasses don't have all quantities

          if (doubleprec) then
             allocate(datdb(maxpart,ncol),stat=ierr)
             if (ierr /= 0) then
                print*,"(a)",'*** error allocating memory for double conversion ***'
                return
             else
                datdb = 0.
             endif
             read(15,iostat=ierr) nprint,rstardb,mstardb,n1,n2, &
                nptmass,timedb,(datdb(i,7),i=1,nprint), &
                escapdb,tkindb,tgravdb,ttermdb, &
                ((datdb(i,k),i=1,nprint),k=1,6), &
                ((datdb(i,k),i=1,nprint),k=8,ncol), &
                (datdb(i,9), i=nprint+1, nprint+nptmass), &
                ((datdb(i,k), i=nprint+1, nprint+nptmass),k=1,6), &
                ((datdb(i,k), i=nprint+1, nprint+nptmass),k=13,15)

             if (ierr < 0) print "(a)",'*** WARNING: END OF FILE DURING READ ***'
             if (ierr > 0) print "(a)",'*** WARNING: ERRORS DURING READ ***'
             dat(:,1:ncol,j) = real(datdb(:,1:ncol))
             time(j) = real(timedb)

          else
             read(15,iostat=ierr) nprint,rstar,mstar,n1,n2, &
                nptmass,time(j),(dat(i,7,j),i=1,nprint), &
                escap,tkin,tgrav,tterm, &
                ((dat(i,k,j),i=1,nprint),k=1,6), &
                ((dat(i,k,j),i=1,nprint),k=8,ncol), &
                (dat(i,9,j), i=nprint+1, nprint+nptmass), &
                ((dat(i,k,j), i=nprint+1, nprint+nptmass),k=1,6), &
                ((dat(i,k,j), i=nprint+1, nprint+nptmass),k=13,15)

             if (ierr < 0) print "(a)",'*** WARNING: END OF FILE DURING READ ***'
             if (ierr > 0) print "(a)",'*** WARNING: ERRORS DURING READ ***'

          endif
       endif
    endif

    if (ierr /= 0 ) then
       print "(a)",'|*** ERROR READING TIMESTEP ***'
!           return
!        else
!           nstepsread = nstepsread + 1
    endif
    nstepsread = nstepsread + 1

    npartoftype(1,j) = nprint
    npartoftype(2,j) = nptmass
!!        print*,j,' time = ',time(j)
    gamma(j) = 1.666666666667
!
!--read abundances from abundance file
!
    if (iabunfileopen) then
       print "(a)",' ... reading abundances from '//trim(abunfile)//' ...'
       read(41,iostat=ierr1) nprint
       if (ierr1 /= 0) then
          print "(a)",' *** ERROR READING ABUNDANCE FILE ***'
       elseif (nprint /= npartoftype(1,j)) then
          print "(a)",' *** ERROR: npart in abundance file differs from full dump ***'
       else
          rewind(41)
          if (doubleprec) then
             read(41,iostat=ierr1) nprint,((datdb(i,k),k=1,max_spec+2),i=1,nprint),Etot_burn_cgsdb
             dat(:,ncol+1:ncolumns,j) = real(datdb(:,1:max_spec+2))
             print*,' Etot_burn (cgs) = ',Etot_burn_cgsdb
          else
             read(41,iostat=ierr1) nprint,((dat(i,k,j),k=1,max_spec+2),i=1,nprint),Etot_burn_cgs
             print*,' Etot_burn (cgs) = ',Etot_burn_cgs
          endif
          if (ierr1 < 0) then
             print "(a)",' *** END OF FILE REACHED IN ABUNDANCE FILE ***'
          elseif (ierr1 > 0) then
             print "(a)",' *** ERRORS DURING ABUNDANCE FILE READ ***'
          elseif (nprint /= npartoftype(1,j)) then
             print "(a)",' *** ERROR: npart in abundance file differs from full dump ***'
          endif
       endif
       close(unit=41)
    endif

    j = j + 1

    if (allocated(datdb)) deallocate(datdb)

 endif

55 continue
 !
 !--reached end of file
 !
 close(15)

 !
 !--reset centre of mass to zero
 !
 if (allocated(dat) .and. n2==0 .and. lenvironment('RSPLASH_RESET_CM')) then
    if (minidump) then
       call reset_centre_of_mass(dat(1:nprint,1:3,j-1),dat(1:nprint,7,j-1),nprint)
    else ! full dumps ipmass = 9
       call reset_centre_of_mass(dat(1:nprint,1:3,j-1),dat(1:nprint,9,j-1),nprint)
    endif
 endif

 !
 !--transform velocities to corotating frame
 !
 if (.not.minidump .and. allocated(dat) .and. lenvironment('RSPLASH_COROTATING')) then
    print*,'TRANSFORMING VELOCITIES TO CORORATING FRAME'
    call set_corotating_vels(dat(1:nprint,9,j-1),dat(1:nprint,4:5,j-1),n1,nprint)
 endif

 if (allocated(npartoftype)) then
    print*,'>> end of dump file: nsteps =',j-1,'ntot = ', &
        sum(npartoftype(:,j-1)),'nptmass=',npartoftype(2,j-1)
 endif
 return

contains

!
!--reset centre of mass to zero
!
subroutine reset_centre_of_mass(xyz,pmass,npart)
 implicit none
 integer, intent(in) :: npart
 real, dimension(npart,3), intent(inout) :: xyz
 real, dimension(npart) :: pmass
 real :: masstot,xcm,ycm,zcm

 !
 !--get centre of mass
 !
 masstot = SUM(pmass(1:npart))
 xcm = SUM(pmass(1:npart)*xyz(1:npart,1))/masstot
 ycm = SUM(pmass(1:npart)*xyz(1:npart,2))/masstot
 zcm = SUM(pmass(1:npart)*xyz(1:npart,3))/masstot

 print*,' centre of mass is at ',xcm,ycm,zcm
 print*,' resetting to zero...'
 xyz(1:npart,1) = xyz(1:npart,1) - xcm
 xyz(1:npart,2) = xyz(1:npart,2) - ycm
 xyz(1:npart,3) = xyz(1:npart,3) - zcm

 return
end subroutine reset_centre_of_mass

!
!--adjust velocities to corotating frame
!
subroutine set_corotating_vels(pmass,vxy,n1,npart)
 implicit none
 integer, intent(in) :: n1,npart
 real, dimension(npart,2), intent(inout) :: vxy !, xy
 real, dimension(npart) :: pmass
 real :: mass1,mass2 !,xcm1,ycm1,xcm2,ycm2
 real :: vxcm1,vycm1,vxcm2,vycm2

 !
 !--get centre of mass of star 1 and star 2
 !
 mass1 = SUM(pmass(1:n1))
!  xcm1 = SUM(pmass(1:n1)*xy(1:n1,1))/mass1
!  ycm1 = SUM(pmass(1:n1)*xy(1:n1,2))/mass1

 mass2 = SUM(pmass(n1+1:npart))
!  xcm2 = SUM(pmass(n1+1:npart)*xy(n1+1:npart,1))/mass2
!  ycm2 = SUM(pmass(n1+1:npart)*xy(n1+1:npart,2))/mass2
 !
 !--work out centre of mass velocities for each star
 !
 vxcm1 = SUM(pmass(1:n1)*vxy(1:n1,1))/mass1
 vycm1 = SUM(pmass(1:n1)*vxy(1:n1,2))/mass1

 vxcm2 = SUM(pmass(n1+1:npart)*vxy(n1+1:npart,1))/mass2
 vycm2 = SUM(pmass(n1+1:npart)*vxy(n1+1:npart,2))/mass2

 !
 !--subtract centre of mass velocities appropriately
 !
 vxy(1:n1,1) = vxy(1:n1,1) - vxcm1
 vxy(1:n1,2) = vxy(1:n1,2) - vycm1
 vxy(n1+1:npart,1) = vxy(n1+1:npart,1) - vxcm2
 vxy(n1+1:npart,2) = vxy(n1+1:npart,2) - vycm2

end subroutine set_corotating_vels

end subroutine read_data

!!------------------------------------------------------------
!! set labels for each column of data
!!------------------------------------------------------------

subroutine set_labels
 use filenames, only:rootname
 use labels, only:label,unitslabel,labelvec,labeltype,iamvec,&
              ix,ivx,ih,irho,iutherm,ipmass,iBfirst,idivB,make_vector_label
 use settings_data, only:ndim,ndimV,ncolumns,ntypes,UseTypeInRenderings,iformat
 use geometry, only:labelcoord
 use settings_units, only:units
 implicit none
 integer :: i
 logical :: minidump
 real :: udistcm,udistkm,utime,umass,uvelkms

 minidump = .false.
 if (index(rootname(1),'minidump') /= 0) minidump = .true.

 if (ndim <= 0 .or. ndim > 3) then
    print*,'*** ERROR: ndim = ',ndim,' in set_labels ***'
    return
 endif
 if (ndimV <= 0 .or. ndimV > 3) then
    print*,'*** ERROR: ndimV = ',ndimV,' in set_labels ***'
    return
 endif

 do i=1,ndim
    ix(i) = i
 enddo
 if (minidump) then
    ivx = 0
    ih = 4        !  smoothing length
    irho = 5     ! location of rho in data array
    iutherm = 0  !  thermal energy
    ipmass = 7  !  particle mass
    label(6) = 'T'
    if (ncolumns > 7) then
       iBfirst = 8
       idivB = 11
    endif
    if (ncolumns > 11) then
       label(12) = 'grad h'
       label(13) = 'grad soft'
       label(14) = 'dsoft'
    endif
!
!--set transformation factors between code units/real units
!
    udistkm = 1.5  ! km
    udistcm = 1.5e5
    utime = 5.0415e-6
    umass = 1.99e33
    units(1:3) = udistkm
    unitslabel(1:3) = ' [km]'
    units(ih) = udistkm
    unitslabel(ih) = ' [km]'
    units(ipmass) = umass
    unitslabel(ipmass) = ' [g]'
    units(irho) = umass/udistcm**3
    unitslabel(irho) = ' [g/cm^3]'
    if (iBfirst > 0) then
       units(iBfirst:iBfirst+ndimV-1) = 8.0988e14
       unitslabel(iBfirst:iBfirst+ndimV-1) = ' [G]'
       units(idivB) = units(iBfirst)/udistcm
       unitslabel(idivB) = ' [G/cm]'
    endif

 else !--full dump
    ivx = ndim+1
    ih = 7
    iutherm = 8
    ipmass = 9
    irho = 10
    label(11) = 'temperature [ MeV ]'
    label(12) = 'electron fraction (y_{e})'

    if (iformat==2) then ! MHD full dump
       iBfirst = 13
       label(16) = 'psi'
       idivB = 17
       call make_vector_label('force',18,ndimV,iamvec,labelvec,label,labelcoord(:,1))

       label(21) = 'Euler alpha'
       label(22) = 'Euler beta'
       label(23) = 'Bevol\dz'
       label(24) = 'grad h'
       label(25) = 'grad soft'
       label(26) = 'av  '
       label(27) = 'avB'
!
!--set transformation factors between code units/real units
!
       udistkm = 1.5  ! km
       udistcm = 1.5e5
       utime = 5.0415e-6
       umass = 1.99e33

       units(iBfirst:iBfirst+ndimV-1) = 8.0988e14
       unitslabel(iBfirst:iBfirst+ndimV-1) = ' [G]'
       units(idivB) = units(iBfirst)/udistcm
       unitslabel(idivB) = ' [G/cm]'

       units(1:3) = udistkm
       unitslabel(1:3) = ' [km]'
       units(4:6) = 1.0
       unitslabel(4:6) = '/c'
       units(7) = udistkm
       unitslabel(7) = ' [km]'
       units(8) = (udistcm/utime)**2
       unitslabel(8) = ' [erg/g]'
       units(9) = umass
       unitslabel(9) = ' [g]'
       units(10) = umass/udistcm**3
       unitslabel(10) = ' [g/cm^3]'

    else
       call make_vector_label('force',13,ndimV,iamvec,labelvec,label,labelcoord(:,1))
       label(16) = 'dgrav'
       if (ncolumns > 16) then
          label(11) = 'temperature [ 10^6 K ]'
          do i=17,ncolumns
             write(label(i),"('species ',i2)") i-16
          enddo
          if (ncolumns >= 25) then
             label(17) = 'He'
             label(18) = 'C'
             label(19) = 'O'
             label(20) = 'Ne'
             label(21) = 'Mg'
             label(22) = 'Si'
             label(23) = 'Fe'
             label(24) = 'mean A'
             label(25) = 'mean Z'
          endif
       endif

       udistcm = 1.0e9
       utime = 2.7443
       umass = 1.99e33
       uvelkms = (udistcm/utime)/1e5

       units(1:3) = 1.0 !!udistcm
       unitslabel(1:3) = ' [10^9 cm]'
       units(4:6) = uvelkms
       unitslabel(4:6) = ' [km/s]'
       units(ih) = units(1)
       unitslabel(ih) = unitslabel(1)
       units(8) = (udistcm/utime)**2
       unitslabel(8) = ' [erg/g]'
       units(9) = umass
       unitslabel(9) = ' [g]'
       units(10) = umass/udistcm**3
       unitslabel(10) = ' [g/cm^3]'
    endif

 endif

 units(0) = utime*1000.
 unitslabel(0) = ' ms'

 call make_vector_label('v',ivx,ndimV,iamvec,labelvec,label,labelcoord(:,1))
 call make_vector_label('B',iBfirst,ndimV,iamvec,labelvec,label,labelcoord(:,1))
 if (iBfirst /= 0) label(idivB) = 'div B'

 label(ix(1:ndim)) = labelcoord(1:ndim,1)
 label(irho) = '\gr'
 if (iutherm > 0) label(iutherm) = 'u'
 label(ih) = 'h       '
 label(ipmass) = 'particle mass'
 !
 !--set labels for each particle type
 !
 ntypes = 2 !!maxparttypes
 labeltype(1) = 'gas'
 labeltype(2) = 'point mass'
 UseTypeInRenderings(1) = .true.
 UseTypeInRenderings(2) = .false.

end subroutine set_labels
