module testmix2mhd
  use testHelper
  use voltapp
  use gamapp
  use uservoltic
  use mix2mhd_interface
  use ioH5

  implicit none

contains

  @before
  subroutine firstSerial()
  end subroutine firstSerial

  @after
  subroutine lastSerial()
  end subroutine lastSerial

  @test
  subroutine corotationTest()
    ! testing that a corotation potential from remix results in a corotation field in gamera
    type(voltApp_T) :: voltronApp
    type(gamApp_T) :: gameraApp

    character(len=strLen) :: caseInput = 'cmiD.xml'
    real(rp), dimension(NDIM) :: rHatP,eHat,xyz,Exyz,ccEijk
    real(rp) :: deltaSum,lambda,rval,xc,yc,zc
    real(rp) :: Psi0,RIn,errorThresh
    integer :: h,ip,it,k,j,jp,kp,n,np,i,ig

    !type(IOVAR_T), dimension(MAXMIXIOVAR) :: debugHDF

    write(*,*) 'Running corotationTest ...'
    !Setting some values for inner shell
    RIn  = 1.0
    Psi0 = 10.0

    call initGamera(gameraApp, initUser, caseInput)

    call initVoltron(voltronApp, gameraApp, caseInput)

    associate(rApp=>voltronApp%remixApp)
    do h=1,2
        do ip=1,rApp%ion(h)%g%Np
            do it=1,rApp%ion(h)%g%Nt
                rval = rApp%ion(h)%g%r(ip,it)
                lambda = (PI/2.0_rp) - rApp%ion(h)%g%t(ip,it)
                !write(*,*) 'h / ip / it, r/lam = ',h,ip,it,rval,lambda
                rApp%ion(h)%st%vars(ip,it,POT) = Psi0*cos(lambda)*cos(lambda)/RIn
            enddo
        enddo
    enddo
    end associate

    !Can add a test of the interpolation to Gamera shells here?
    call mapRemixToGamera(voltronApp%mix2mhd, voltronApp%remixApp)

    call convertRemixToGamera(voltronApp%mix2mhd, voltronApp%remixApp, gameraApp, .false.) !Don't add corotation potential

    ! find the remix BC to verify the resulting Gamera data
    SELECT type(iiBC=>gameraApp%Grid%externalBCs(INI)%p)
        TYPE IS (IonInnerBC_T)

            ! verify that the gamera field (iiBC%inEijk, iiBC%inExyz, or both) have the expected values here
            ! inExyz should be pointed exactly radially at all locations
            deltaSum = 0.0_rp
            !Only loop over active cells
            do k=gameraApp%Grid%ks,gameraApp%Grid%ke
                do j=gameraApp%Grid%js,gameraApp%Grid%je

                    !Map to active ip,jp,kp (i=Grid%is => ip=Grid%is)
                    call lfmIJKcc(gameraApp%Model,gameraApp%Grid,gameraApp%Grid%is,j,k,ip,jp,kp)

                    do n=1,gameraApp%Model%Ng
                        ig = gameraApp%Grid%is-n
                        np = gameraApp%Model%nG-n+1

                        call cellCenter(gameraApp%Grid, ig,j,k,xc,yc,zc)
                        rHatP = normVec([xc,yc,zc])

                        eHat = normVec(iiBC%inExyz(np,jp,kp,:))
                        !write(*,*) 'ig,j,k,np = ',ig,j,k,np
                        !write(*,*) 'eIJK / eXYZ = ', iiBC%inEijk(np,jp,kp,:), iiBC%inExyz(np,jp,kp,:)

                        deltaSum = deltaSum + abs(norm2(rHatP-eHat))
                    end do
                end do
            end do

            ! remix doesn't go below a certain lat, causing discontinuity. high error
            errorThresh = 2*(1+gameraApp%Grid%ke-gameraApp%Grid%ks)*(1+gameraApp%Grid%je-gameraApp%Grid%js)*gameraApp%Model%Ng
            @assertLessThanOrEqual(deltaSum, errorThresh, 'Magnetic field from remix was not pointing radially')

             !Now test Eijk fields
            deltaSum = 0.0
            !Only loop over active cells
            do k=gameraApp%Grid%ks,gameraApp%Grid%ke
                do j=gameraApp%Grid%js,gameraApp%Grid%je
                    !Map to active ip,jp,kp (i=Grid%is => ip=Grid%is)
                    call lfmIJKcc(gameraApp%Model,gameraApp%Grid,gameraApp%Grid%is,j,k,ip,jp,kp)
                    do n=1,gameraApp%Model%Ng
                        ig = gameraApp%Grid%is-n
                        np = gameraApp%Model%nG-n+1
                        !Convert Eijk (edges) to cc-Eijk
                        ccEijk(IDIR) = 0.25*(iiBC%inEijk(np,j,k,IDIR)+iiBC%inEijk(np,j,k+1,IDIR)+iiBC%inEijk(np,j+1,k,IDIR)+iiBC%inEijk(np,j+1,k+1,IDIR))
                        ccEijk(JDIR) = 0.25*(iiBC%inEijk(np,j,k,JDIR)+iiBC%inEijk(np,j,k+1,JDIR)+iiBC%inEijk(np+1,j,k,JDIR)+iiBC%inEijk(np+1,j,k+1,JDIR))
                        ccEijk(KDIR) = 0.25*(iiBC%inEijk(np,j,k,KDIR)+iiBC%inEijk(np+1,j,k,KDIR)+iiBC%inEijk(np,j+1,k,KDIR)+iiBC%inEijk(np+1,j+1,k,KDIR))
                        !Now convert cc-Eijk to Exyz
                        Exyz = ccEijk2Exyz(gameraApp%Model,gameraApp%Grid,ccEijk,ig,j,k)
                        !Exyz above is approximation to inExyz, ie testing whether or not Eijk and Exyz are consistent
                        deltaSum = deltaSum + norm2(Exyz-iiBC%inExyz(np,jp,kp,:))
                    enddo
                enddo
          enddo

          ! remix doesn't go below a certain lat, causing discontinuity. high error
          errorThresh = 2e-2*(1+gameraApp%Grid%ke-gameraApp%Grid%ks)*(1+gameraApp%Grid%je-gameraApp%Grid%js)*gameraApp%Model%Ng
          @assertLessThanOrEqual(deltaSum, errorThresh, 'inEijk values did not match inExyz values')

        CLASS DEFAULT
            @assertTrue(.false., 'Could not find Ion Inner BC in remix IC')
    END SELECT

  end subroutine corotationTest

end module testmix2mhd

