Program Listing for File evolveVectorPotential.cpp

Return to documentation for file (hydro/electromotiveforce/evolveVectorPotential.cpp)

// ***********************************************************************************
// Idefix MHD astrophysical code
// Copyright(C) 2020-2022 Geoffroy R. J. Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
// and other code contributors
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************

#include <string>

#include "idefix.hpp"
#include "hydro.hpp"
#include "dataBlock.hpp"

void ElectroMotiveForce::EvolveVectorPotential(real dt, IdefixArray4D<real> &Vein) {
  #ifdef EVOLVE_VECTOR_POTENTIAL
    idfx::pushRegion("ElectroMotiveForce::EvolveVectorPotential");
    IdefixArray4D<real> Ve = Vein;
        // Corned EMFs
    IdefixArray3D<real> Ex1 = this->ex;
    IdefixArray3D<real> Ex2 = this->ey;
    IdefixArray3D<real> Ex3 = this->ez;
    idefix_for("EvolvVectorPotential",
      data->beg[KDIR],data->end[KDIR]+KOFFSET,
      data->beg[JDIR],data->end[JDIR]+JOFFSET,
      data->beg[IDIR],data->end[IDIR]+IOFFSET,
      KOKKOS_LAMBDA (int k, int j, int i) {
        #if DIMENSIONS == 3
          Ve(AX1e,k,j,i) += - dt * Ex1(k,j,i);
          Ve(AX2e,k,j,i) += - dt * Ex2(k,j,i);
        #endif
        #if DIMENSIONS >= 2
          Ve(AX3e,k,j,i) += - dt * Ex3(k,j,i);
        #endif
      });

    idfx::popRegion();
  #endif
}



void ElectroMotiveForce::ComputeMagFieldFromA(IdefixArray4D<real> &Vein,
                                              IdefixArray4D<real> &Vsout) {
  #ifdef EVOLVE_VECTOR_POTENTIAL
    idfx::pushRegion("ElectroMotiveForce::ComputeMagFieldfromA");

    // Corned EMFs
    IdefixArray3D<real> Ex1 = this->ex;
    IdefixArray3D<real> Ex2 = this->ey;
    IdefixArray3D<real> Ex3 = this->ez;

    // Field
    IdefixArray4D<real> Vs = Vsout;
    IdefixArray4D<real> Ve = Vein;

    // Coordinates
    IdefixArray1D<real> x1=data->x[IDIR];
    IdefixArray1D<real> x2=data->x[JDIR];
    IdefixArray1D<real> x3=data->x[KDIR];

    IdefixArray1D<real> x1p=data->xr[IDIR];
    IdefixArray1D<real> x2p=data->xr[JDIR];
    IdefixArray1D<real> x3p=data->xr[KDIR];

    IdefixArray1D<real> x1m=data->xl[IDIR];
    IdefixArray1D<real> x2m=data->xl[JDIR];
    IdefixArray1D<real> x3m=data->xl[KDIR];

    IdefixArray1D<real> dx1=data->dx[IDIR];
    IdefixArray1D<real> dx2=data->dx[JDIR];
    IdefixArray1D<real> dx3=data->dx[KDIR];

    #if GEOMETRY == SPHERICAL
      IdefixArray1D<real> dmu=data->dmu;
      IdefixArray1D<real> sinx2m=data->sinx2m;
      #if DIMENSIONS >= 2
        bool haveAxis = hydro->haveAxis;
      #endif
    #endif



    idefix_for("ComputeMagFieldFromA",
              data->beg[KDIR],data->end[KDIR]+KOFFSET,
              data->beg[JDIR],data->end[JDIR]+JOFFSET,
              data->beg[IDIR],data->end[IDIR]+IOFFSET,
      KOKKOS_LAMBDA (int k, int j, int i) {
  #if GEOMETRY == CARTESIAN
    Vs(BX1s,k,j,i) = D_EXPAND( ZERO_F                                     ,
                    + 1/dx2(j) * (Ve(AX3e,k,j+1,i) - Ve(AX3e,k,j,i) )  ,
                    - 1/dx3(k) * (Ve(AX2e,k+1,j,i) - Ve(AX2e,k,j,i) )  );

    #if DIMENSIONS >= 2
      Vs(BX2s,k,j,i) =  D_EXPAND( - 1/dx1(i) * (Ve(AX3e,k,j,i+1) - Ve(AX3e,k,j,i) )  ,
                                                                  ,
                        + 1/dx3(k) * (Ve(AX1e,k+1,j,i) - Ve(AX1e,k,j,i) ) );
    #endif
    #if DIMENSIONS == 3
      Vs(BX3s,k,j,i) = + 1/dx1(i) * (Ve(AX2e,k,j,i+1) - Ve(AX2e,k,j,i) )
              - 1/dx2(j) * (Ve(AX1e,k,j+1,i) - Ve(AX1e,k,j,i) );
    #endif

  #elif GEOMETRY == CYLINDRICAL
    Vs(BX1s,k,j,i) = + 1/dx2(j) * (Ve(AX3e,k,j+1,i) - Ve(AX3e,k,j,i) );
    #if DIMENSIONS >= 2
      Vs(BX2s,k,j,i) =  -( FABS(x1p(i)) * Ve(AX3e,k,j,i+1)
                          - FABS(x1m(i)) * Ve(AX3e,k,j,i)) / FABS(x1(i)*dx1(i));
    #endif

  #elif GEOMETRY == POLAR
    Vs(BX1s,k,j,i) = D_EXPAND( ZERO_F                                                      ,
                    + 1/(FABS(x1m(i)) * dx2(j)) * (Ve(AX3e,k,j+1,i) - Ve(AX3e,k,j,i) )  ,
                    - 1/dx3(k) * (Ve(AX2e,k+1,j,i) - Ve(AX2e,k,j,i) )                   );

    #if DIMENSIONS >= 2
      Vs(BX2s,k,j,i) =  D_EXPAND( - 1/dx1(i) * (Ve(AX3e,k,j,i+1) - Ve(AX3e,k,j,i) )  ,
                                                                  ,
                        + 1/dx3(k) * (Ve(AX1e,k+1,j,i) - Ve(AX1e,k,j,i) ) );
    #endif
    #if DIMENSIONS == 3
      Vs(BX3s,k,j,i) = 1/(FABS(x1(i))) * (
                    (x1m(i+1)*Ve(AX2e,k,j,i+1) - x1m(i)*Ve(AX2e,k,j,i) ) / dx1(i)
                  -  (Ve(AX1e,k,j+1,i) - Ve(AX1e,k,j,i) ) / dx2(j) );
    #endif
  #elif GEOMETRY == SPHERICAL
    real dV2  = dmu(j);
    real Ax2p = FABS(sinx2m(j+1));
    real Ax2m = FABS(sinx2m(j));

    Vs(BX1s,k,j,i) = D_EXPAND( ZERO_F                                                        ,
                    + 1/(x1m(i)*dV2) * ( Ax2p*Ve(AX3e,k,j+1,i) - Ax2m*Ve(AX3e,k,j,i) )    ,
                    - dx2(j)/(x1m(i)*dV2*dx3(k)) * (Ve(AX2e,k+1,j,i) - Ve(AX2e,k,j,i) ) );

    #if DIMENSIONS >= 2
      // If we include the axis, we symmetrize Ex on the axis. However, Ax2=0 on the axis
      // so BX2s might become singular. We therefore enforce Ax2=1 on the axis, knowing
      // that the contribution to BX2s of this term will be zero because Ve(AX1e,k+1)-Ve(AX1e,k)=0
      if(haveAxis) {
        if(FABS(Ax2m)<1e-12) Ax2m = ONE_F;
      }
      Vs(BX2s,k,j,i) =  D_EXPAND( - 1/(x1(i)*dx1(i)) * (x1m(i+1)*Ve(AX3e,k,j,i+1)
                                                        - x1m(i)*Ve(AX3e,k,j,i) )  ,
                                                                                  ,
                        + 1/(x1(i)*Ax2m*dx3(k)) * (Ve(AX1e,k+1,j,i) - Ve(AX1e,k,j,i) )  );
    #endif
    #if DIMENSIONS == 3
      Vs(BX3s,k,j,i) = + 1/(x1(i)*dx1(i)) * (x1m(i+1)*Ve(AX2e,k,j,i+1) - x1m(i)*Ve(AX2e,k,j,i) )
              - 1/(x1(i)*dx2(j)) * (Ve(AX1e,k,j+1,i) - Ve(AX1e,k,j,i) );
    #endif
  #endif // GEOMETRY
  });

  if(data->haveGridCoarsening) {
    hydro->CoarsenMagField(Vsout);
  }

  idfx::popRegion();
  #endif
}