LCOV - code coverage report
Current view: top level - src/Test/Numeric - Stencil.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 51 63 81.0 %
Date: 2025-02-18 04:54:05 Functions: 53 54 98.1 %

          Line data    Source code
       1             : #ifndef TEST_NUMERIC_STENCIL
       2             : #define TEST_NUMERIC_STENCIL
       3             : 
       4             : #include <AMReX.H>
       5             : 
       6             : #include "Set/Set.H"
       7             : #include "IC/Trig2.H"
       8             : #include "Numeric/Stencil.H"
       9             : 
      10             : namespace Test
      11             : {
      12             : /// Tests for the Numeric namespace classes
      13             : namespace Numeric
      14             : {
      15             : class Stencil
      16             : {
      17             : 
      18             : public:
      19           8 :     Stencil() {};
      20           2 :     ~Stencil() {};
      21             : 
      22           2 :     void Define(amrex::IntVect _ncells)
      23             :     {
      24           2 :         ncells = _ncells;
      25           2 :         amrex::RealBox rb({AMREX_D_DECL(0.,0.,0.)}, {AMREX_D_DECL(L,L,L)});
      26           2 :         amrex::Geometry::Setup(&rb, 0);
      27             :         
      28           4 :         amrex::Box domain(amrex::IntVect{AMREX_D_DECL(0,0,0)}, ncells,
      29           2 :                 amrex::IntVect::TheCellVector());
      30           2 :         geom.resize(1);
      31           2 :         grids.resize(1);
      32           2 :         dmap.resize(1);
      33           2 :         phi.resize(1);
      34           2 :         DphiNumeric.resize(1);
      35           2 :         DphiExact.resize(1);
      36             : 
      37           2 :         geom[0].define(domain);
      38           2 :         grids[0].define(domain);
      39           4 :         grids[0].maxSize(ncells[0]/2);
      40           2 :         dmap[0].define(grids[0]);
      41             : 
      42           2 :         phi        .Define(0,grids[0],dmap[0],1,nghost);
      43           2 :         DphiNumeric.Define(0,grids[0],dmap[0],1,nghost);
      44           2 :         DphiExact  .Define(0,grids[0],dmap[0],1,nghost);
      45             : 
      46           2 :         phi[0]->setVal(0.0);
      47             :         // Initial function is
      48             :         //   cos(2*pi*x/L) * cos(2*pi*y/L) * cos(2*pi*z / L)
      49           2 :         IC::Trig2 ic(geom,1.0,AMREX_D_DECL(0.0,0.0,0.0),AMREX_D_DECL(1,1,1));
      50           2 :         ic.Add(0,phi,0.0);
      51           2 :     }
      52           2 :     void Define(int _ncells)
      53             :     {
      54           2 :         Define(amrex::IntVect{AMREX_D_DECL(_ncells,_ncells,_ncells)});
      55           2 :     }
      56             : 
      57             :     template<int i,int j,int k>
      58          36 :     bool Derivative(int verbose,std::string plotfile = "")
      59             :     {
      60          36 :         const Set::Scalar tolerance = 1E-2;
      61             :         
      62          36 :         DphiExact[0]->setVal(0.0);
      63          36 :         DphiNumeric[0]->setVal(0.0);
      64             : 
      65             :         //
      66             :         // Compute exact derivative
      67             :         //
      68          36 :         Set::Scalar AMREX_D_DECL(theta1 = 0.0, theta2 = 0.0, theta3 = 0.0);
      69          36 :         Set::Scalar fac = 1.0;
      70         143 :         AMREX_D_TERM( for (int p = 0; p < i; p++) theta1 += 0.5*Set::Constant::Pi;,
      71             :                 for (int q = 0; q < j; q++) theta2 += 0.5*Set::Constant::Pi;,
      72             :                 for (int r = 0; r < k; r++) theta3 += 0.5*Set::Constant::Pi; );
      73             :                   
      74         143 :         AMREX_D_TERM( for (int p = 0; p < i; p++) fac *= 1.0*Set::Constant::Pi / L;,
      75             :                 for (int q = 0; q < j; q++) fac *= 1.0*Set::Constant::Pi / L;,
      76             :                 for (int r = 0; r < k; r++) fac *= 1.0*Set::Constant::Pi / L;);
      77          72 :         IC::Trig2 ic(geom,fac,AMREX_D_DECL(theta1,theta2,theta3),AMREX_D_DECL(1,1,1));
      78          36 :         ic.Add(0,DphiExact,0.0);
      79             : 
      80             : 
      81             :         //
      82             :         // Compute numeric derivative
      83             :         //
      84          36 :         const amrex::Real* DX = geom[0].CellSize();
      85         810 :         for ( amrex::MFIter mfi(*phi[0],amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
      86             :         {
      87         774 :             const amrex::Box& bx = mfi.tilebox();
      88         774 :             amrex::Array4<const amrex::Real> const& Phi = phi[0]->array(mfi);
      89         774 :             amrex::Array4<amrex::Real> const& DPhi    = DphiNumeric[0]->array(mfi);
      90     1821582 :             amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int p, int q, int r){ DPhi(p,q,r) = ::Numeric::Stencil<Set::Scalar,i,j,k>::D(Phi,p,q,r,0,DX); });
      91             :         }
      92             : 
      93         108 :         amrex::MultiFab diff(grids[0],dmap[0],ncomp,nghost);
      94          36 :         amrex::MultiFab::Copy    (diff,*DphiExact[0]  ,0,0,ncomp,nghost);
      95          36 :         amrex::MultiFab::Subtract(diff,*DphiNumeric[0],0,0,ncomp,nghost);
      96             : 
      97          36 :         Set::Scalar error = diff.norm0(0,0,false) / DphiExact[0]->norm0(0,0,false);
      98             : 
      99          36 :         if (verbose) Util::Message(INFO,"Infinity norm of error = ", 100*error,"%");
     100             : 
     101          36 :         if (plotfile != "")
     102           0 :             WritePlotFile(plotfile);
     103             : 
     104          36 :         if (error < tolerance) return 0;
     105           0 :         else return 1;
     106             :     }
     107             : 
     108             : 
     109           0 :     void WritePlotFile(std::string plotfile)
     110             :     {
     111           0 :         amrex::Vector<amrex::MultiFab> plotmf(1);
     112           0 :         plotmf[0].define(grids[0], dmap[0], 3, 0);
     113           0 :         for (amrex::MFIter mfi(plotmf[0],false); mfi.isValid(); ++mfi)
     114             :         {
     115           0 :             amrex::Box bx = mfi.validbox();
     116           0 :             plotmf[0][mfi].copy((*phi[0])[mfi]        ,bx, 0, bx, 0, 1); 
     117           0 :             plotmf[0][mfi].copy((*DphiExact[0])[mfi]  ,bx, 0, bx, 1, 1); 
     118           0 :             plotmf[0][mfi].copy((*DphiNumeric[0])[mfi],bx, 0, bx, 2, 1); 
     119             :         }
     120           0 :         amrex::WriteSingleLevelPlotfile(plotfile,plotmf[0],varnames,geom[0],0.0,1);
     121           0 :     }        
     122             : 
     123             : 
     124             : private:
     125             :     amrex::IntVect ncells;
     126             :     const Set::Scalar L = 1.0;
     127             :     const int ncomp = 1, nghost = 2;
     128             :     amrex::Vector<amrex::Geometry> geom;
     129             :     amrex::Vector<amrex::BoxArray> grids;
     130             :     amrex::Vector<amrex::DistributionMapping> dmap;
     131             :     
     132             :     Set::Field<Set::Scalar> phi;
     133             :     Set::Field<Set::Scalar> DphiExact;
     134             :     Set::Field<Set::Scalar> DphiNumeric;
     135             :     amrex::Vector<std::string> varnames = {"phi","dphi_exact","dphi_numeric"};
     136             : };
     137             : }
     138             : }
     139             : 
     140             : 
     141             : 
     142             : #endif

Generated by: LCOV version 1.14