https://github.com/jadexter/grtrans
Raw File
Tip revision: c76cb11fa1396516f38ba6f972c68fbb5b5ae984 authored by Jason Dexter on 08 March 2021, 22:06:47 UTC
testing new intel compiler fix
Tip revision: c76cb11
fluid_model_harm3d.f90
   module fluid_model_harm3d

      use class_four_vector
      use interpolate, only: interp
      use kerr, only: kerr_metric, lnrf_frame, uks2ubl, bl2ks
      use phys_constants, only: pi
      use math, only: zbrent
      implicit none

      namelist /harm/  dfile, hfile, nt, indf, gfile

      character(len=100) :: dfile, hfile, gfile
      integer :: nx1, nx2, nx3, n, ndumps, nt, indf, dlen, nhead
      integer :: ndim=3
      integer, dimension(:), allocatable :: dumps
      real :: tstep=20., h, asim, dx1, dx2, dx3, gam, startx1, startx2, startx3, toffset=0.
      real, dimension(:), allocatable :: t
      real, dimension(:), allocatable :: x1_arr, x2_arr, x3_arr, r_arr, th_arr, ph_arr
      real, dimension(:), allocatable :: rho_arr, p_arr, u0_arr, vrl_arr, &
        vpl_arr, vtl_arr, temp_arr
      real, dimension(:), allocatable :: b0_arr, br_arr, bth_arr, bph_arr

      interface init_harm3d_data
        module procedure init_harm3d_data
      end interface

      interface del_harm3d_data
        module procedure del_harm3d_data
      end interface

      interface initialize_harm3d_model
        module procedure initialize_harm3d_model
      end interface

      interface transformbl2mksh
         module procedure transformbl2mksh
      end interface

      interface umksh2uks
         module procedure umksh2uks
      end interface

      interface harm3d_vals
        module procedure harm3d_vals
      end interface

      contains

        function findx2harm(x2,args) result(diff)
        real(kind=8), intent(in) :: x2
        real(kind=8), intent(in), dimension(:) :: args
        real(kind=8) :: h, theta, diff
        h=args(2); theta=args(1)
        diff=theta-pi*x2
        end function findx2harm

        subroutine transformbl2mksh(r,th,phi,x1,x2,x3,h)
        ! to 3D on 19/11/15 JD
        ! transform Boyer-Lindquist coordinates to modified Kerr-Schild coordinates used by HARM
        real, intent(in), dimension(:) :: r,th,phi
        real, intent(out), dimension(size(r)) :: x1,x2,x3
        real, intent(in) :: h
        real :: hval
        real, dimension(2) :: args
        integer :: i
        x1=log(r)
        x3=phi
        x2=th/pi
!        hval=1d0
!        args=(/th(1),hval/)
!        do i=1,size(r)
!           args(1)=th(i)
!           x2(i)=zbrent(findx2harm,0d0,1d0,dble(args),1d-6)
!        enddo
        end subroutine transformbl2mksh

        function umksh2uks(fum,r,x2,hin) result(uks)
          ! Converts a Kerr-Schild spherical 4-velocity to a Boyer-Lindquist one.
          ! JAD 11/10/2008
          ! Do simple transformation first:
          ! to 3D on 19/11/15 JD
          real, dimension(:), intent(in) :: r, x2
          type (four_vector), dimension(:), intent(in) :: fum
          type (four_vector), dimension(size(r)) :: uks
          real, intent(in), optional :: hin
          real :: hval
          real(kind=8), dimension(size(r)) :: ur, uth, uph
          real, dimension(size(r)) :: dthdx2
          write(6,*) 'read harm umksh2uks present h'
          if (present(hin)) then
             hval=hin
          else
             hval=0.3
          endif
          write(6,*) 'hval: ',present(hin), hval
          ur=dble(r)*fum%data(2)
          ! Compute partial derivatives:
          dthdx2=pi
          uth=fum%data(3)*dble(dthdx2)
          uph=fum%data(4)
          uks=fum
          uks%data(2)=ur
          uks%data(3)=uth
          uks%data(4)=uph
        end function umksh2uks

        subroutine harm3d_vals(x0,a,rho,p,b,u,bmag)
        type (four_Vector), intent(in), dimension(:) :: x0
        real, intent(in) :: a
        real(kind=8), dimension(size(x0)) :: done,pfac,nfac,bfac
        real, dimension(size(x0)) :: x3,x2,x1,zm,theta,fone, &
         vpl0,vrl0,vtl0,rd,td, pd,rttd,zr,dzero, &
         vr0,vth0,vph0,bth,dummy,tt,ttd,zt,zphi,zpp
        real, dimension(nx1) :: uniqx1,uniqr
        real, dimension(nx2) :: uniqx2,uniqth
        real, dimension(nx3) :: uniqx3,uniqph
        real, dimension(size(x0),2**(ndim+1)) :: ppi,rhoi,vrli,vtli, &
         vpli,bri,bthi,bphi,b0i,u0i,ri,thi,phii
!        integer, dimension(size(x0)*(2**ndim)) :: sindx
        real, dimension(size(x0)) :: dth, minph
        integer, dimension(size(x0)*2*(2**ndim)) :: indx
        integer, dimension(size(x0)) :: lx1,lx2, lx3, ux1,ux2,ux3,x1l,x1u,x2l,x2u,x3l,x3u, &
         umax,one,tindx
        integer :: npts,i,maxtindx
        real, dimension(size(x0)), intent(out) :: rho,p,bmag
        type (four_Vector), intent(out), dimension(size(x0)) :: u,b
        ! Interpolates HARM data to input coordinates
        ! JAD 3/20/2009, fortran 11/12/2012
!        write(6,*) 'harm: ',size(x0)
        !nx1=floor(sqrt(real(size(x1_arr)))); nx2=nx1
!        write(6,*) 'harm3d vals: ',nx1,nx2,nx3,size(x1_arr),size(x2_arr),size(x3_arr)
!        write(6,*) 'harm3d vals'
        umax=nx2-1; one=1
        dzero=0d0; done=1d0; fone=1.
        uniqx3=x3_arr(1:nx3)
        uniqx2=x2_arr(1:nx3*(nx2-1)+1:nx3)
!       write(6,*) 'between'
        uniqx1=x1_arr(1:nx3*(nx2-1)*nx1+1:nx3*nx2)
        uniqr=exp(uniqx1)
        uniqth=pi*uniqx2
        uniqph=uniqx3
!        write(6,*) 'uniqx1: ',minval(uniqx1),maxval(uniqx1)
!        write(6,*) 'uniqr: ',minval(uniqr), maxval(uniqr)
!        write(6,*) 'uniqth: ',minval(uniqth), maxval(uniqth)
!        write(6,*) 'uniqph: ',minval(uniqph), maxval(uniqph)
        npts=size(x0)
        theta=x0%data(3)
        zr=x0%data(2)
        zt=x0%data(1)
        tt=bl2ks(dble(zr),dble(zt),dble(a),1)-bl2ks(dble(zr(1)),0d0,dble(a),1)
        tt=-tt
!        write(6,*) 'tt: ',minval(x0%data(1)),maxval(x0%data(1)),minval(tt),maxval(tt)
!        ztt=-ztt
!        tt=ztt-min(ztt)+tabs0
        zpp=x0%data(4)
        zphi=bl2ks(dble(zr),dble(zpp),dble(a))
        zphi=mod(zphi,(2.*pi))
        where(zphi.lt.0.)
            zphi=zphi+2.*pi
        endwhere
!        write(6,*) 'harm3d vals transform'
        call transformbl2mksh(zr,theta,zphi,x1,x2,x3,h)

!        write(6,*) 'transform r: ',maxval(zr), minval(zr), maxval(x1), minval(x1)
!        write(6,*) 'transform th: ',maxval(theta), minval(theta), minval(x2), maxval(x2)
!        write(6,*) 'transform phi: ',maxval(zphi), minval(zphi), minval(x3), maxval(x3)
!        write(6,*) 'dif x3: ',(uniqx3(nx3)-uniqx3(1)),x3,uniqx3
        lx1=floor((x1-uniqx1(1))/(uniqx1(nx1)-uniqx1(1))*(nx1-1))+1
        ux1=lx1+1
        lx2=floor((x2-uniqx2(1))/(uniqx2(nx2)-uniqx2(1))*(nx2-1))+1
        ux2=lx2+1
        lx3=floor((x3-uniqx3(1))/(uniqx3(nx3)-uniqx3(1))*(nx3-1))+1
        ux3=lx3+1
        lx2=merge(merge(lx2,one,lx2.ge.1),umax,lx2.le.(nx2-1))
        lx1=merge(lx1,one,lx1.ge.1)
        ux1=lx1+1
        lx2=merge(lx2,one,lx2.ge.1)
        lx2=merge(lx2,nx2,lx2.le.nx2)
        ux2=merge(ux2,one,ux2.ge.1)
        ux2=merge(ux2,nx2,ux2.le.nx2)
!        write(6,*) 'nx1 nx2 nx3: ',nx1,nx2,nx3,minval(zphi),maxval(zphi),minval(zr),maxval(zr),minval(theta), &
!             maxval(theta)
!       write(6,*) 'ux lx: ',minval(lx1),maxval(ux1),minval(lx2),maxval(ux2), minval(lx3), maxval(ux3)
! Deal with poles
!        write(6,*) 'poles'
        where(ux2.ne.lx2)
           dth=uniqth(ux2)-uniqth(lx2)
        elsewhere
            dth=uniqth(1)*2
        endwhere
! periodic in phi
        minph=uniqph(lx3)
        where(ux3.gt.nx3)
            ux3=1
        endwhere
        where(lx3.lt.1)
            lx3=nx3
            minph=uniqph(lx3)-2.*pi
        endwhere
!        write(6,*) 'uniform phi'
! uniform in phi
        pd=(zphi-minph)/(uniqph(2)-uniqph(1))
        td=abs(theta-uniqth(lx2))/dth
        rd=(zr-uniqr(lx1))/(uniqr(ux1)-uniqr(lx1))
! When the geodesic is inside the innermost zone center located outside the horizon, use nearest neighbor rather than interpolate
        where(uniqr(lx1).le.max(uniqr(1),(1.+sqrt(1.-a**2.))))
           rd=1.
           pfac=1d-6
           nfac=1d-6
           bfac=1d-6
        elsewhere
           pfac=1d0
           nfac=1d0
           bfac=1d0
        endwhere
!        write(6,*) 'coords: ',
!        write(6,*) 'rd td pd: ',minval(rd),maxval(rd),minval(td),maxval(td),minval(pd),maxval(pd)
!        write(6,*) 'ux lx: ',minval(lx1),maxval(ux1),minval(lx2),maxval(ux2),minval(lx3),maxval(ux3)
        ! th is fastest changing index
        x3l=lx3-1; x3u=ux3-1
        x2l=(lx2-1)*nx3 ; x2u=(ux2-1)*nx3
        x1l=(lx1-1)*nx2*nx3; x1u=(ux1-1)*nx2*nx3
! Indices for nearest neighbors in 2D
!        write(6,*) 'sindx', size(sindx)
!        sindx=(/(/x1l+x2l+1/),(/x1l+x2u+1/),(/x1u+x2l+1/),(/x1u+x2u+1/)/)
!        write(6,*) 'sindx', maxval(sindx), sindx(npts+1), x1l(1)+x2u(1)+1, size(sindx)
! Now find timestep indices:
        maxtindx=nt-2
        where(floor(tt/tstep).le.maxtindx)
           tindx(:)=floor(tt/tstep)
           ttd=(tt-tindx*tstep)/tstep
        elsewhere
           tindx=maxtindx+1
           ttd=0.
        endwhere
!        write(6,*) 'tindx: ',minval(tindx),maxval(tindx)
! Create index array across times and 2D nearest neighbors (first half at first time, second half at second time):
! Need to make sure there aren't integer problems when these indices get very large
!        write(6,*) 'indx', size(indx), 2**ndim, maxval(tindx), minval(tindx), tstep
        indx=(/(/x1l+x2l+x3l+1+n*tindx/),(/x1l+x2u+x3l+1+n*tindx/),(/x1u+x2l+x3l+1+n*tindx/), &
            (/x1u+x2u+x3l+1+n*tindx/),(/x1l+x2l+x3u+1+n*tindx/), &
            (/x1l+x2u+x3u+1+n*tindx/),(/x1u+x2l+x3u+1+n*tindx/),(/x1u+x2u+x3u+1+n*tindx/), &
            (/x1l+x2l+x3l+1+n*(tindx+1)/),(/x1l+x2u+x3l+1+n*(tindx+1)/),(/x1u+x2l+x3l+1+n*(tindx+1)/), &
            (/x1u+x2u+x3l+1+n*(tindx+1)/),(/x1l+x2l+x3u+1+n*(tindx+1)/),(/x1l+x2u+x3u+1+n*(tindx+1)/), &
            (/x1u+x2l+x3u+1+n*(tindx+1)/),(/x1u+x2u+x3u+1+n*(tindx+1)/)/)
! keep indx from going out of bounds when loading one time slice
        where(indx.gt.size(rho_arr))
           indx=indx-n
        endwhere
!        do i=1,2**ndim
!           indx((i-1)*npts+1:i*npts)=sindx((i-1)*npts+1)+npts*tindx
!           indx((2**ndim+i-1)*npts+1:(i+2**ndim)*npts)=sindx((i-1)*npts+1)+npts*(tindx+1)
!        end do
!        write(6,*) 'after indx', maxval(indx), maxval(sindx), indx(npts+1), n*maxval(tindx+1),size(rho_arr),maxloc(indx)!size(rho_arr(indx))
        rhoi=reshape(rho_arr(indx),(/npts,2**(ndim+1)/))
        vrli=reshape(vrl_arr(indx),(/npts,2**(ndim+1)/))
        vtli=reshape(vtl_arr(indx),(/npts,2**(ndim+1)/))
        vpli=reshape(vpl_arr(indx),(/npts,2**(ndim+1)/))
        ppi=reshape(p_arr(indx),(/npts,2**(ndim+1)/))
        b0i=reshape(b0_arr(indx),(/npts,2**(ndim+1)/))
        bri=reshape(br_arr(indx),(/npts,2**(ndim+1)/))
        bthi=reshape(bth_arr(indx),(/npts,2**(ndim+1)/))
        bphi=reshape(bph_arr(indx),(/npts,2**(ndim+1)/))
        u0i=reshape(u0_arr(indx),(/npts,2**(ndim+1)/))
! coordinates for debugging
        ri=reshape(r_arr(indx),(/npts,2**(ndim+1)/))
        thi=reshape(th_arr(indx),(/npts,2**(ndim+1)/))
        phii=reshape(ph_arr(indx),(/npts,2**(ndim+1)/))
                                                                                               !        write(6,*) 'after reshape', minval(ttd), maxval(ttd)
!        rttd=ttd
        rttd=0.
        rho=interp(rhoi,rttd,pd,rd,td)*nfac
        p=interp(ppi,rttd,pd,rd,td)*pfac
!        rho=merge(interp(rhoi,rttd,pd,rd,td),dzero,x1.gt.uniqx1(1))*nfac
!        p=merge(interp(ppi,rttd,pd,rd,td),fone,x1.gt.uniqx1(1))*pfac
!        write(6,*) 'rho: ', rho, p
        vrl0=merge(interp(vrli,rttd,pd,rd,td),dzero,x1.gt.uniqx1(1))
        vtl0=merge(interp(vtli,rttd,pd,rd,td),dzero,x1.gt.uniqx1(1))
!        write(6,*) 'v'
        b%data(1)=merge(interp(b0i,rttd,pd,rd,td),fone,x1.gt.uniqx1(1))
        b%data(2)=merge(interp(bri,rttd,pd,rd,td),fone,x1.gt.uniqx1(1))
!        write(6,*) 'b'
        b%data(3)=merge(interp(bthi,rttd,pd,rd,td),fone,x1.gt.uniqx1(1))
        b%data(4)=merge(interp(bphi,rttd,pd,rd,td),fone,x1.gt.uniqx1(1))
 !       write(6,*) 'u'
        u%data(1)=merge(dble(interp(u0i,rttd,pd,rd,td)),done,x1.gt.uniqx1(1))
        vpl0=merge(interp(vpli,rttd,pd,rd,td),dzero,x1.gt.uniqx1(1))
!        write(6,*) 'after assign'
        ! Protect azimuthal velocities at poles
        ! Compute magnitude of interpolated b-field and force b^2 > 0 (need to look into numerical issues here):
        call assign_metric(b,transpose(kerr_metric(zr, &
         real(x0%data(3)),a)))
        bmag=b*b; bmag=merge(bmag,dzero,bmag.ge.0d0)
        bmag=sqrt(bmag)*bfac
        ! Get four-velocity:
        call lnrf_frame(vrl0,vtl0,vpl0,zr,a,real(x0%data(3)) &
         ,vr0,vth0,vph0,1)
        u%data(2)=u%data(1)*dble(vr0)
        u%data(3)=u%data(1)*dble(vth0)
        u%data(4)=u%data(1)*dble(vph0)
        call assign_metric(u,transpose(kerr_metric(zr,real(x0%data(3)) &
        ,a)))
 !       write(6,*) 'min vals u', minval(u%data(1)), maxval(abs(u*u+1))
 !       write(6,*) 'minmax vals: ',minval(rho),maxval(rho),minval(bmag),minval(p)
!        write(6,*) 'harm vals r: ',zr
!        write(6,*) 'harm vals rho: ',rho
!        write(6,*) 'harm vals rd: ',rd
!        write(6,*) 'harm vals ux: ',nx1,ux1
!        write(6,*) 'harm vals udotu: ',(abs(u*u+1))

!        write(6,*) 'harm vals minloc: ',minloc(zr),rd(minloc(zr)), &
!             td(minloc(zr)),x0(minloc(zr))%data(3),uniqth(lx2(minloc(zr))), &
!             lx2(minloc(zr)),pd(minloc(zr)),lx1(minloc(zr)),ux1(minloc(zr)), &
!             uniqx1(1),x1(minloc(zr))
!        write(6,*) 'harm vals minloc u0 vrl: ',u(minloc(zr))%data(1),vrl0(minloc(zr))
!        write(6,*) 'harm vals minloc u0i vrli: ',u0i(minloc(zr),:),vrli(minloc(zr),:)
!        write(6,*) 'harm vals minloc b0i: ',b0i(minloc(zr),:)
!        write(6,*) 'harm vals minloc bri: ',bri(minloc(zr),:)
!        write(6,*) 'harm vals minloc bthi: ',bthi(minloc(zr),:)
!        write(6,*) 'harm vals minloc bphi: ',bphi(minloc(zr),:)
!        write(6,*) 'harm vals interp bi: ',b(minloc(zr))%data(1),b(minloc(zr))%data(2), &
!             b(minloc(zr))%data(3),b(minloc(zr))%data(4)
!        write(6,*) 'harm vals minloc x0: ', ri(minloc(zr),:),thi(minloc(zr),:),&
!             phii(minloc(zr),:)
!        write(6,*) 'harm coords: ',zr(minloc(p)),theta(minloc(p)),zphi(minloc(p))
!        write(6,*) 'harm vals rhoi: ',rhoi(minloc(p),:)
        end subroutine harm3d_vals

        subroutine read_harm3d_inputs(ifile)
        character(len=20), intent(in) :: ifile
        open(unit=8,file=ifile,form='formatted',status='old')
        read(8,nml=harm)
        write(6,*) 'read: ',nt
        close(unit=8)
        end subroutine read_harm3d_inputs

        subroutine read_harm3d_data_header(nhead)
        integer, intent(in) :: nhead
        real(8), dimension(nhead) :: header
        real(8) :: tcur
        ! Read HARM header file
        ! JAD 11/24/2012 based on previous IDL codes
        ! header format from HARM dump.c
        write(6,*) 'read harm header: ',nhead
        open(unit=8,file=hfile,form='formatted',status='old')
        read(8,*) header
        nx1=header(2)
        nx2=header(3)
        nx3=header(4)
        startx1=header(5)
        startx2=header(6)
        startx3=header(7)
        dx1=header(8)
        dx2=header(9)
        dx3=header(10)
        if(nhead.eq.15) then
           asim=header(11)
           gam=header(12)
        else
           asim=header(13)
           gam=header(14)
        endif
        h=header(nhead-1)
        tcur=header(1)
! is this true for HARM?
!        defcoord=header(19)
        close(unit=8)
        end subroutine read_harm3d_data_header

        subroutine read_harm3d_data_file(data_file,tcur,rho,p,u,b,mdot)
        character(len=100), intent(in) :: data_file
        character(len=100) :: data_file_app
        integer :: nhead,dlen
        integer :: rhopos,ppos,vpos,bpos,gdetpos
        integer, intent(in), optional :: mdot
        real(8), intent(out) :: tcur
        real(8), dimension(:), allocatable, intent(out) :: p,rho
        real(8), dimension(:), allocatable :: gdet, header, udotu, bdotu,bdotb, pmin
        type (four_vector), dimension(:), allocatable, intent(out) :: u,b
        type (four_vector), dimension(:), allocatable :: uks,bks
        real(8), dimension(:,:), allocatable :: grid, data, tmetric
        integer :: i,j, nelem, nelem2
        integer :: BINARY=1
! option to write an ASCII file read here back out as a binary
          ! Read HARM data from a file of given line length, 
          ! positions of desired variables
          ! JAD 11/24/2012 based on previous IDL codes
          ! Set grid parameters so we can generalize later:
!          nhead=21 ; dlen=72
! MONIKA FILE NUMBERS
!          dlen=31; nhead=29
! CHRIS WHITE FILE NUMBERS
          dlen=35; nhead=15
          allocate(header(nhead))
!          rhopos=6; ppos=7; vpos=14; bpos=22; gdetpos=30
          rhopos=9; ppos=rhopos+1; vpos=19; bpos=vpos+8
          allocate(grid(nx1*nx2*nx3,6)); allocate(p(nx1*nx2*nx3)); allocate(rho(nx1*nx2*nx3)); allocate(pmin(nx1*nx2*nx3))
          allocate(u(nx1*nx2*nx3)); allocate(b(nx1*nx2*nx3)); allocate(gdet(nx1*nx2*nx3))
          allocate(uks(nx1*nx2*nx3)); allocate(bks(nx1*nx2*nx3))
          pmin=1e-18
          write(6,*) 'data file: ',data_file
          if(BINARY.ne.1) then
             open(unit=8,file=data_file,form='formatted',status='old',action='read')
             allocate(data(dlen,nx3)); nelem=nx3
             write(6,*) 'read harm sizes', dlen, nx2, size(data)
             read(8,*) header
             tcur=header(1)
             deallocate(header)
             write(6,*) 'read harm past header: ',nx1,nx2,nx3,nelem,dlen
             do i=0,(nx1*nx2*nx3)/(nelem)-1
!                write(6,*) 'i: ',i
                read(8,*) data
!                write(6,*) 'harm data: ', data(:,1)
!             write(6,*) 'data loop: ',i,size(rho),size(p),size(b)
!             write(6,*) 'data vals: ',data(:,1),data(:,gdetpos+1)
                rho(1+i*nelem:(1+i)*nelem)=data(rhopos+1,:)
!                write(6,*) 'sizes rho: ',size(rho),size(data(rhopos+1,:))
                p(1+i*nelem:(1+i)*nelem)=data(ppos+1,:)
                b(1+i*nelem:(1+i)*nelem)%data(1)=(data(bpos+1,:))
                b(1+i*nelem:(1+i)*nelem)%data(2)=(data(bpos+2,:))
                b(1+i*nelem:(1+i)*nelem)%data(3)=(data(bpos+3,:))
                b(1+i*nelem:(1+i)*nelem)%data(4)=(data(bpos+4,:))
!                write(6,*) 'sizes b: ',size(b%data(4)),size(data(bpos+4,:))
                u(1+i*nelem:(1+i)*nelem)%data(1)=(data(vpos+1,:))
                u(1+i*nelem:(1+i)*nelem)%data(2)=(data(vpos+2,:))
                u(1+i*nelem:(1+i)*nelem)%data(3)=(data(vpos+3,:))
                u(1+i*nelem:(1+i)*nelem)%data(4)=(data(vpos+4,:))
!                write(6,*) 'sizes u: ',size(u%data(4)),size(data(vpos+4,:))
!               write(6,*) 'sizes: ',size(grid(1+i*nelem:(i+1)*nelem,:)),size(data(1:4,:))
 !               write(6,*) 'grid '
                grid(1+i*nelem:(1+i)*nelem,:)=transpose(data(1:6,:))
!                write(6,*) 'sizes grid: ',size(grid(1+i*nelem+j*nelem2:(1+i)*nelem+j*nelem2:(1+i)*nelem+(1+j)*nelem2,:)),size(data(1:6,:))
!            write(6,*) 'sizes: ',size(gdet),size(data(gdetpos+1,:))
                gdet(1+i*nelem:(1+i)*nelem)=(data(gdetpos+1,:))
                !             write(6,*) 'data loop'
             end do
!          write(6,*) 'after read loop'
             close(unit=8)
             deallocate(data)
             x1_arr=grid(:,1); x2_arr=grid(:,2); x3_arr=grid(:,3); r_arr=grid(:,4); th_arr=grid(:,5); ph_arr=grid(:,6)
          else
! CHANGING FOR CHRIS WHITE VERSION
             data_file_app = trim(data_file) // '.bin'
             call read_harm3d_data(data_file_app,rho,p,u%data(1),u%data(2),u%data(3),u%data(4),b%data(1), &
                  b%data(2),b%data(3),b%data(4),grid)
             x1_arr=real(grid(:,1)); x2_arr=real(grid(:,2)); x3_arr=real(grid(:,3))
!             call read_harm3d_grid_file()
             r_arr=exp(x1_arr); th_arr=x2_arr*pi; ph_arr=x3_arr
          endif
          p=merge(p,pmin,p.gt.pmin)
          write(6,*) "min vals p", minval(rho),minval(p)
          write(6,*) "min vals u", minval(u%data(1)), minval(u%data(2)), minval(u%data(3)), minval(u%data(4))
          write(6,*) "max vals u", maxval(u%data(1)), maxval(u%data(2)), maxval(u%data(3)), maxval(u%data(4))
          write(6,*) 'read harm grid sizes', size(x1_arr), size(x2_arr), size(x3_arr), size(r_arr), size(th_arr), size(ph_arr)
          write(6,*) 'read harm assign grid'
          deallocate(grid)
!          if (present(mdot)) then
             ! Calculate accretion rate in code units:
             !  nx1=n_elements(uniqx1) ; nx2=n_elements(uniqx2) ; nz=n_elements(uniqx3) 
!             dx2=uniqx2(2)-uniqx2(1) ; dx3=uniqx3(2)-uniqx3(1)
!             mdotarr=-1.*sum(sum(reform(gdet*rho*v(:,1),nx1,nx2,nz),3),2)*dx2*dx3
!          endif
          ! Transform velocities, magnetic fields from MKS to KS and then BL:
          write(6,*) 'read harm transform coords r ', minval(r_arr), maxval(r_arr), asim
          write(6,*) 'read harm transform coords th ',minval(x2_arr), maxval(x2_arr), h
          write(6,*) 'read harm transform coords phi',minval(x3_arr), maxval(x3_arr)
          write(6,*) 'read harm transform coords u ',minval(u%data(1)),minval(u%data(2))
!          write(6,*) 'read harm transform coords u ',u%data(1)
!          write(6,*) 'read harm transform coords u ',u%data(2)
!          write(6,*) 'read harm transform coords u ',u%data(3)
!          write(6,*) 'read harm transform coords u ',u%data(4)
          write(6,*) 'read harm transform coords u size ',size(u),h
          uks = umksh2uks(u,r_arr,x2_arr,h)
          write(6,*) 'after uks ',minval(uks%data(1))
          u = uks2ubl(uks,dble(r_arr),dble(asim))
          write(6,*) 'read harm transform coords b', minval(u%data(3)),maxval(u%data(2)),&
               minval(b%data(1)),maxval(b%data(4))
          write(6,*) "min vals u", minval(u%data(1)), minval(u%data(2)), minval(u%data(3)), minval(u%data(4))
          write(6,*) "max vals u", maxval(u%data(1)), maxval(u%data(2)), maxval(u%data(3)), maxval(u%data(4))
          bks = umksh2uks(b,r_arr,x2_arr,h)
          b   = uks2ubl(bks,dble(r_arr),dble(asim))
! test code...
          allocate(bdotu(n)); allocate(udotu(n)); allocate(bdotb(n))
          call assign_metric(u,transpose(kerr_metric(r_arr,th_arr,real(asim))))
          call assign_metric(b,transpose(kerr_metric(r_arr,th_arr,real(asim))))
          where(r_arr.gt.(1.+sqrt(1.-asim**2.)))
             udotu=abs(u*u+1.)
             bdotu=abs(u*b)
             bdotb=abs(b*b)
          elsewhere
             udotu=0.
             bdotu=0.
             bdotb=0.
          endwhere
          write(6,*) 'after transform', rho(1:4), p(1:4)
          write(6,*) 'after transform',p(5*nx1+23), rho(7*nx1+131), &
               maxval(abs(udotu)), maxval(abs(bdotu)),minval(bdotb)
          deallocate(udotu); deallocate(bdotu); deallocate(bdotb)
        end subroutine read_harm3d_data_file

        subroutine read_harm3d_grid_file()
!        integer, intent(in) :: nt
!        integer :: n
        open(unit=8,file=gfile,form='unformatted',status='old')
!        read(8) nx1,nx2,nx3
!        n=nx1*nx2*nx3
        ! allocate data
        !          call init_harm3d_data(n,n*nt)
        write(6,*) 'read grid: ',size(x1_arr),size(x2_arr),size(x3_arr)
        read(8) x1_arr
        read(8) x2_arr
        read(8) x3_arr
        close(unit=8)
        end subroutine read_harm3d_grid_file

        subroutine read_harm3d_data(dfile,rho,p,u0,vr,vth,vph,b0,br,bth,bph,grid)
        integer :: nx, status, dlen, nheader_bytes,rhopos,ppos,vpos,bpos
        real, dimension(:,:), allocatable :: data
        real(8), intent(inout), dimension(:) :: rho,p,u0,vr,vth,vph,b0,br,bth,bph
        real(8), intent(inout), dimension(:,:) :: grid
        real, dimension(size(rho),10) :: metric
        real, dimension(size(rho)) :: ui2
        character(len=100), intent(in) :: dfile
        character :: header_byte
        !open(unit=8,file=dfile,form='unformatted',status='old')
!        read(8) nx
!        if(nx.ne.10*nx1*nx2*nx3) then
!           write(6,*) 'ERROR: INCORRECT DATA SIZE IN READ_HARM3D_DATA: ',nx,nx1,nx2,nx3
!           return
!        endif
!        allocate(data(nx))
!        read(8) data
!        close(8)

! CHRIS NUMBERS
        dlen=35
        rhopos=10; ppos=rhopos+1; vpos=19; bpos=vpos+8
        allocate(data(dlen,nx1*nx2*nx3))

        open(unit=8,file=dfile,form='unformatted',access='stream',status='old',action='read')
        nheader_bytes=1
        read(8) header_byte
        do while(header_byte.ne.char(10))
           read(8) header_byte
           nheader_bytes=nheader_bytes+1
        end do
        write(6,*) 'read header: ',nheader_bytes,dlen
        read(8) data
        close(8)

        write(6,*) 'data first entry: ',data(:,1)
        write(6,*) 'data last entry: ',data(:,nx1*nx2*nx3)

        grid=transpose(data(4:9,:))
!        write(6,*) 'grid: ',maxval(grid(
        rho=data(rhopos,:)
        p=data(ppos,:)
        u0=data(vpos,:)
        vr=data(vpos+1,:)
        vth=data(vpos+2,:)
        vph=data(vpos+3,:)
        b0=data(bpos,:)
        br=data(bpos+1,:)
        bth=data(bpos+2,:)
        bph=data(bpos+3,:)
        

!        rho=data(1:nx1*nx2*nx3)
!        p=data(nx1*nx2*nx3+1:2*nx1*nx2*nx3)
!        u0=data(2*nx1*nx2*nx3+1:3*nx1*nx2*nx3)
!        vr=data(3*nx1*nx2*nx3+1:4*nx1*nx2*nx3)
!        vth=data(4*nx1*nx2*nx3+1:5*nx1*nx2*nx3)
!        vph=data(5*nx1*nx2*nx3+1:6*nx1*nx2*nx3)
!        b0=data(6*nx1*nx2*nx3+1:7*nx1*nx2*nx3)
!        br=data(7*nx1*nx2*nx3+1:8*nx1*nx2*nx3)
!        bth=data(8*nx1*nx2*nx3+1:9*nx1*nx2*nx3)
!        bph=data(9*nx1*nx2*nx3+1:10*nx1*nx2*nx3)

        deallocate(data)
! calculate u0 from others (from IDL grtrans):
!        metric=kerr_metric(r_arr,th_arr,asim)
!        ui2=metric(:,1)+2.*metric(:,4)*vph+vr**2*metric(:,5)+metric(:,8)*vth**2+metric(:,10)*vph**2
!        u0=1./sqrt(-ui2)
        end subroutine read_harm3d_data

        subroutine initialize_harm3d_model(a,ifile,df,hf,gf,ntt,indft)
        real(kind=8), intent(in) :: a
        integer :: nx, status, nhead
        character(len=20), intent(in), optional :: ifile
        character(len=20) :: default_ifile='harm.in'
        character(len=100), intent(in), optional :: df,hf,gf
        integer, intent(in), optional :: ntt,indft
! MONIKA FILE NUMBER
!        nhead=29
! CHRIS FILE NUMBER
        nhead=15
! if all inputs are given, assign variables rather than reading from file
        if (present(df)) then
           dfile = df
           hfile = hf
           gfile = gf
           nt = ntt
           indf = indft
        else
           if (present(ifile)) then
              call read_harm3d_inputs(ifile)
           else
              call read_harm3d_inputs(default_ifile)
           endif
        endif
!        dfile='m87bl09rfp10xi5a998fluidvars.bin'
!        write(6,*) 'init harm'
        call read_harm3d_data_header(nhead)
        if (abs(asim-a).gt.1e-4) then 
           write(6,*) 'ERROR -- Different simulation and grtrans spin values!',a,asim
           return
        endif
!        write(6,*) 'read header', nx1, nx2
        n=nx1*nx2*nx3
        call init_harm3d_data(n,n*nt)
        write(6,*) 'init data', nt, indf, hfile, dfile
        call load_harm3d_data(nt)
        end subroutine initialize_harm3d_model

        subroutine load_harm3d_data(nt)
        real(8), dimension(:), allocatable :: rho,p
        real, dimension(:), allocatable :: vrl, vtl, vpl
        type (four_vector), dimension(:), allocatable :: u, b
        integer, intent(in) :: nt
        character(len=20) :: append
        character(len=100) :: data_file
        integer :: k
        real(8) :: tcur, tstep_test
        allocate(rho(n)); allocate(p(n))
        allocate(vrl(n)); allocate(vtl(n)); allocate(vpl(n))
        allocate(u(n)); allocate(b(n))
        do k=1,nt
           write(append, fmt='(I3.3)') indf-(k-1)
           data_file = trim(dfile) // append
!           write(6,*) 'data_file: ',indf-(k-1),append,data_file
           call read_harm3d_data_file(data_file,tcur,rho,p,u,b)
           t(k)=tcur
           ! transform velocities to LNRF frame
!           write(6,*) 'lnrf sizes: ',size(u%data(2)), size(r_arr), size(th_arr), size(vrl), size(vtl)
           call lnrf_frame(real(u%data(2)/u%data(1)),real(u%data(3)/u%data(1)), & 
                real(u%data(4)/u%data(1)),r_arr,asim,th_arr,vrl,vtl,vpl)
!           write(6,*) 'lnrf transform', size(b0_arr), size(b%data(1)), size(b0_arr((k-1)*n+1:k*n))
!           write(6,*) 'lnrf transform', size(vrl), size(vtl), size(vpl), size(u0_arr)
           ! now assign to data arrays
           rho_arr((k-1)*n+1:k*n)=rho
! conversion between internal energy and pressure
           p_arr((k-1)*n+1:k*n)=p*(gam-1.)
           b0_arr((k-1)*n+1:k*n)=b%data(1)
           br_arr((k-1)*n+1:k*n)=b%data(2)
           bth_arr((k-1)*n+1:k*n)=b%data(3)
           bph_arr((k-1)*n+1:k*n)=b%data(4)
!           write(6,*) 'v assign'
           u0_arr((k-1)*n+1:k*n)=u%data(1)
!           write(6,*) 'vrl assign'
           vrl_arr((k-1)*n+1:k*n)=real(vrl)
!           write(6,*) 'after assign', size(vtl_arr((k-1)*n+1:k*n)), size(vtl)
           vpl_arr((k-1)*n+1:k*n)=real(vpl)
!           write(6,*) 'after vpl', vtl(1), vtl(n), vtl
           vtl_arr((k-1)*n+1:k*n)=real(vtl)
!           write(6,*) 'after vtl'
!           write(6,*) 'assign'
        end do
!        tstep=10.
! Need to be able to do light curves even when nload (nt) = 1... Maybe read headers for first two files.
        if (nt.gt.1) then
! use default sim time step unless told otherwise
           tstep=t(1)-t(2)
           tstep_test=t(nt-1)-t(nt)
           if (abs((tstep-tstep_test)/tstep).gt.0.1) then 
              write(6,*) 'WARNING -- Time step changes over dumps!'
           endif
        endif
!        write(6,*) 'after loop', maxval(abs(u*u+1.))
        deallocate(rho); deallocate(p)
        deallocate(vrl); deallocate(vtl); deallocate(vpl)
        deallocate(u); deallocate(b)
!        write(6,*) 'read data file', a
        write(6,*) maxval(vrl_arr**2.+vtl_arr**2.+vpl_arr**2.)
!        write(6,*) 'maxmin temp: ',minval(p_arr/rho_arr*1.67e-24*9e20/1.38e-16), &
!             maxval(p_arr/rho_arr*1.67e-24*9e20/1.38e-16)
        end subroutine  load_harm3d_data

        subroutine advance_harm3d_timestep(dtobs)
        real(8), intent(in) :: dtobs
        integer :: nupdate
        nupdate = floor(dtobs / tstep)
        toffset = toffset+dtobs-tstep*nupdate
! after a couple stpes might be accumulating offset
        nupdate=nupdate+floor(toffset/tstep)
        toffset=toffset-floor(toffset/tstep)*tstep
        indf=indf+nupdate
        write(6,*) 'advance harm timestep: ',dtobs,tstep,toffset,indf,nupdate
        call update_harm3d_data(nupdate)
        end subroutine advance_harm3d_timestep

        subroutine update_harm3d_data(nupdate)
        integer, intent(in) :: nupdate
        integer :: nshift
        if(nupdate.gt.nt) then
! this is case where we just load all new data
           call load_harm3d_data(nt)
        else
! this is case where we shift existing data back and then load more
           nshift=n*nupdate+1
!           rho_arr=rho_arr(nshift:nshift-1:1)
!           allocate(temp_arr(n))
           rho_arr(nshift:n*nt)=rho_arr(1:n*nt-nshift)
           p_arr(nshift:n*nt)=p_arr(1:n*nt-nshift)
           br_arr(nshift:n*nt)=br_arr(1:n*nt-nshift)
           bth_arr(nshift:n*nt)=bth_arr(1:n*nt-nshift)
           bph_arr(nshift:n*nt)=bph_arr(1:n*nt-nshift)
           b0_arr(nshift:n*nt)=b0_arr(1:n*nt-nshift)
           vrl_arr(nshift:n*nt)=vrl_arr(1:n*nt-nshift)
           vtl_arr(nshift:n*nt)=vtl_arr(1:n*nt-nshift)
           vpl_arr(nshift:n*nt)=vpl_arr(1:n*nt-nshift)
           call load_harm3d_data(nupdate)
        end if
        end subroutine update_harm3d_data

        subroutine init_harm3d_data(nx,n)
        integer, intent(in) :: n,nx
!        integer, intent(in), optional :: aux,td,auxn
        allocate(rho_arr(n)); allocate(p_arr(n)); allocate(u0_arr(n))
        allocate(vrl_arr(n)); allocate(vtl_arr(n)); allocate(vpl_arr(n))
        allocate(b0_arr(n)); allocate(br_arr(n)); allocate(bth_arr(n))
        allocate(bph_arr(n))
        allocate(x1_arr(nx)); allocate(x2_arr(nx)); allocate(r_arr(nx))
        allocate(th_arr(nx)); allocate(t(nt)); allocate(x3_arr(nx))
        allocate(ph_arr(nx))
        end subroutine init_harm3d_data

        subroutine del_harm3d_data()
        deallocate(rho_arr); deallocate(p_arr); deallocate(u0_arr)
        deallocate(vrl_arr); deallocate(vtl_arr); deallocate(vpl_arr)
        deallocate(b0_arr); deallocate(br_arr); deallocate(bth_arr)
        deallocate(bph_arr); deallocate(x1_arr); deallocate(x2_arr)
        deallocate(r_arr); deallocate(th_arr); deallocate(t)
        deallocate(x3_arr)
        deallocate(ph_arr)
        end subroutine del_harm3d_data

      end module fluid_model_harm3d
back to top