LCOV - code coverage report
Current view: top level - src/IC - Ellipsoid.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 0 62 0.0 %
Date: 2024-11-18 05:28:54 Functions: 0 4 0.0 %

          Line data    Source code
       1             : // This IC initializes a single-component fab using the formula
       2             : // 
       3             : // .. math::
       4             : //
       5             : //    \phi = \begin{cases} 
       6             : //                \alpha_{in}  & (\mathbf{x}-\mathbf{x}_0)^T\mathbf{A}(\mathbf{x}-\mathbf{x}_0) \le r  \\
       7             : //                \alpha_{out} & \text{else} 
       8             : //           \end{cases}
       9             : //
      10             : // The boundary can be mollified using an error function with parameter :math:`\varepsilon`
      11             : //
      12             : // .. WARNING::
      13             : //
      14             : //    This IC is redundant with :ref:`IC::Ellipse` and :ref:`IC::Expression` and will probably be consolidated
      15             : //
      16             : 
      17             : #ifndef IC_ELLIPSOID_H_
      18             : #define IC_ELLIPSOID_H_
      19             : 
      20             : #include "IC/IC.H"
      21             : #include "Util/Util.H"
      22             : #include "IO/ParmParse.H"
      23             : 
      24             : /// \class Ellipsoid
      25             : /// \brief Initialize an ellipsoidal inclusion
      26             : namespace IC
      27             : {
      28             : class Ellipsoid : public IC
      29             : {
      30             : public:
      31             :     enum Mollifier {Dirac, Gaussian};
      32             : 
      33           0 :     Ellipsoid (amrex::Vector<amrex::Geometry> &_geom) : IC(_geom) {}
      34             :   
      35           0 :     void Add(const int &lev,Set::Field<Set::Scalar> &a_field, Set::Scalar)
      36             :     {
      37           0 :         for (amrex::MFIter mfi(*a_field[lev],amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
      38             :         {
      39           0 :             amrex::Box bx = mfi.tilebox();
      40           0 :             bx.grow(a_field[lev]->nGrow());
      41           0 :             amrex::IndexType type = a_field[lev]->ixType();
      42             : 
      43           0 :             amrex::Array4<Set::Scalar> const& field = a_field[lev]->array(mfi);
      44           0 :             amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
      45             : 
      46           0 :                     Set::Vector x = Set::Position(i,j,k,geom[lev],type);
      47             : 
      48           0 :                     Set::Scalar min_value = field(i,j,k);
      49           0 :                     for (int i=0 ; i < center.size(); i++)
      50             :                     {
      51           0 :                         Set::Scalar value = 0.;
      52           0 :                         Set::Scalar norm = (A[i]*(x-center[i])).lpNorm<2>();
      53           0 :                         value = 0.5 + 0.5*std::erf(((x-center[i]).transpose() * A[i] * (x-center[i]) - 1.0) / eps[i] / norm);
      54           0 :                         value = in_value + value*(out_value - in_value);
      55           0 :                         min_value = value < min_value ? value : min_value;
      56             :                     }
      57           0 :                     field(i,j,k) = min_value;
      58           0 :                     if (field(i,j,k) < std::min(in_value,out_value)) field(i,j,k) = std::min(in_value,out_value);
      59           0 :                     if (field(i,j,k) > std::max(in_value,out_value)) field(i,j,k) = std::max(in_value,out_value);
      60           0 :                 });
      61             :         }
      62           0 :         a_field[lev]->FillBoundary();
      63           0 :     };
      64             :   
      65             : private:
      66             :     Set::Scalar in_value = 0.0, out_value = 1.0;
      67             :     amrex::Vector<Set::Vector> center; 
      68             :     amrex::Vector<Set::Scalar> eps;
      69             :     amrex::Vector<Set::Matrix> A;
      70             :     Mollifier moll = Mollifier::Dirac;
      71             : 
      72             : public:
      73           0 :     static void Parse(Ellipsoid & value, IO::ParmParse & pp)
      74             :     {
      75           0 :         amrex::Vector<Set::Scalar> center;
      76           0 :         if(pp.contains("center")) pp_queryarr("center",center); // Center of the ellipse :math:`\mathbf{x}_0`
      77             : 
      78           0 :         if(center.size() < AMREX_SPACEDIM) value.center.push_back(Set::Vector::Zero());
      79             :         else
      80             :         {
      81           0 :             for (int i = 0; i<center.size(); i+=AMREX_SPACEDIM)
      82           0 :                 value.center.push_back(Set::Vector(AMREX_D_DECL(center[i],center[i+1],center[i+2])));
      83             :         }
      84             :         
      85           0 :         amrex::Vector<Set::Scalar> A;
      86           0 :         if (pp.contains("A"))
      87             :         {
      88           0 :             pp_queryarr("A", A); // Matrix defining elipse radii and orientation  
      89           0 :             if(A.size() < AMREX_SPACEDIM*AMREX_SPACEDIM) value.A.push_back(Set::Matrix::Identity());
      90             :             else
      91             :             {
      92           0 :                 int i=0, j=0;
      93           0 :                 Set::Matrix temp = Set::Matrix::Zero();
      94           0 :                 for (i=0; i<A.size(); i+=AMREX_SPACEDIM)
      95             :                 {
      96           0 :                     for (j=0; j<AMREX_SPACEDIM; j++)
      97           0 :                         temp(i,j) = A[i+j];
      98             :                     
      99           0 :                     if((i+j) % (AMREX_SPACEDIM*AMREX_SPACEDIM) == 0) 
     100             :                     {
     101           0 :                         value.A.push_back(temp);
     102           0 :                         temp = Set::Matrix::Zero();
     103             :                     }
     104             :                 }
     105             :             }
     106             :         }
     107           0 :         if (pp.contains("radius"))
     108             :         { 
     109           0 :             amrex::Vector<Set::Scalar> a_radius; 
     110           0 :             pp_queryarr("radius",a_radius); // "Vector of radii (use instead of A)"
     111             : 
     112           0 :             if (a_radius.size() < AMREX_SPACEDIM) value.A.push_back(Set::Matrix::Identity());
     113             :             else
     114             :             {
     115           0 :                 for (int i = 0; i<a_radius.size(); i+=AMREX_SPACEDIM)
     116             :                 {
     117           0 :                     Set::Matrix temp = Set::Matrix::Zero();
     118           0 :                     AMREX_D_TERM( temp(0,0) = 1./(a_radius[i]*a_radius[i]) ;, temp(1,1) = 1./(a_radius[i+1]*a_radius[i+1]) ;, temp(2,2) = 1./(a_radius[i+2]*a_radius[i+2]) ; );
     119           0 :                     value.A.push_back(temp);
     120             :                 }
     121             :             }
     122             :         }
     123             : 
     124           0 :         amrex::Vector<Set::Scalar> eps;
     125           0 :         pp_queryarr("eps", eps); // Mollifying value for erf
     126             : 
     127           0 :         if(eps.size() < 1) value.eps.push_back(1.e-5);
     128           0 :         for (int i =0; i < value.A.size(); i++)
     129             :         {
     130           0 :             if (eps[i] <= 0.0) eps[i] = 1.e-5;
     131           0 :             value.eps.push_back(eps[i]);
     132             :         }
     133             :         //if(value.eps <= 0.) value.eps = 1.e-5;
     134             : 
     135           0 :         pp_query_default("in_value",  value.in_value,  0.0); // Value of field inside ellipse
     136           0 :         pp_query_default("out_value", value.out_value, 1.0); // Value of field outside ellipse
     137             : 
     138           0 :         std::string mollifier;
     139           0 :         pp_query("mollifier",mollifier); // Type of mollifier to use (options: dirac, [gaussian])
     140           0 :         if(mollifier == "Dirac" || mollifier == "dirac") 
     141           0 :             value.moll = Mollifier::Dirac;
     142             :         else 
     143           0 :             value.moll = Mollifier::Gaussian;
     144           0 :     }
     145             : };
     146             : }
     147             : #endif

Generated by: LCOV version 1.14