Alamo
Ellipse.H
Go to the documentation of this file.
1 // If :code:`number_of_inclusions` is specified, then multiple ellipses are specified.
2 // In this case, each parameter must have number_of_inclusion*M values, where M is the
3 // number of values specified for the single ellipse case.
4 //
5 // .. WARNING::
6 //
7 // This class is redundant with :ref:`IC::Ellipsoid` and :ref:`IC::Expression` and will
8 // probably be consolidated.
9 //
10 
11 
12 #ifndef IC_ELLIPSE_H_
13 #define IC_ELLIPSE_H_
14 
15 #include "Set/Set.H"
16 #include "IC/IC.H"
17 #include "IO/ParmParse.H"
18 
19 namespace IC
20 {
21 class Ellipse : public IC
22 {
23 public:
25 
26  Ellipse (amrex::Vector<amrex::Geometry> &_geom) : IC(_geom) {}
27  Ellipse (amrex::Vector<amrex::Geometry> &_geom, IO::ParmParse &pp, std::string name) : Ellipse(_geom)
28  {pp_queryclass(name,*this);}
29 
30  void Add(const int &lev, Set::Field<Set::Scalar> &a_field, Set::Scalar)
31  {
32  Set::Vector DX(geom[lev].CellSize());
33  amrex::IndexType type = a_field[lev]->ixType();
34  int ncomp = a_field[lev]->nComp();
35 
36  for (amrex::MFIter mfi(*a_field[lev],amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
37  {
38  amrex::Box bx;
39  if (type == amrex::IndexType::TheNodeType()) bx = mfi.grownnodaltilebox();
40  if (type == amrex::IndexType::TheCellType()) bx = mfi.growntilebox();
41 
42  amrex::Array4<Set::Scalar> const& field = a_field[lev]->array(mfi);
43  amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
44 
45  Set::Vector x;
46  // NODE
47  if (type == amrex::IndexType::TheNodeType())
48  {
49  AMREX_D_TERM(x(0) = geom[lev].ProbLo()[0] + ((amrex::Real)(i)) * geom[lev].CellSize()[0];,
50  x(1) = geom[lev].ProbLo()[1] + ((amrex::Real)(j)) * geom[lev].CellSize()[1];,
51  x(2) = geom[lev].ProbLo()[2] + ((amrex::Real)(k)) * geom[lev].CellSize()[2];);
52  }
53  else if (type == amrex::IndexType::TheCellType())
54  {
55  AMREX_D_TERM(x(0) = geom[lev].ProbLo()[0] + ((amrex::Real)(i) + 0.5) * geom[lev].CellSize()[0];,
56  x(1) = geom[lev].ProbLo()[1] + ((amrex::Real)(j) + 0.5) * geom[lev].CellSize()[1];,
57  x(2) = geom[lev].ProbLo()[2] + ((amrex::Real)(k) + 0.5) * geom[lev].CellSize()[2];);
58  }
59 
60  if(number_of_inclusions == 0)
61  {
62  Set::Scalar norm = (A[0]*(x-center[0])).lpNorm<2>();
63  field(i,j,k,0) = 0.5 - 0.5*std::erf(((x-center[0]).transpose() * A[0] * (x-center[0]) - 1.0) / eps[0] / norm);
64  if (invert) field(i,j,k,0) = 1.0 - field(i,j,k,0);
65  if (ncomp > 1) field(i,j,k,1) = 1.0 - field(i,j,k,0);
66  }
67  else
68  {
69  // Base matrix is 0, rest of the inclusions are numbered from 1.
70  Set::Scalar value = 0.0;
71  for (int m = 0; m < number_of_inclusions; m++)
72  {
73  Set::Scalar norm = (A[m]*(x-center[m])).lpNorm<2>();
74  value += 0.5 - 0.5*std::erf(((x-center[m]).transpose() * A[m] * (x-center[m]) - 1.0) / eps[m] / norm);
75  // if (field(i,j,k,m+1) < 0.) field(i,j,k,m+1) = 0.;
76  // if (field(i,j,k,m+1) > 1.) field(i,j,k,m+1) = 1.;
77  // value += field(i,j,k,m+1);
78  }
79  field (i,j,k,invert) = 1.0 - value;
80  field (i,j,k,1-invert) = value;
81  if (field(i,j,k,invert) < 0.) field(i,j,k,invert) = 0.;
82  if (field(i,j,k,invert) > 1.) field(i,j,k,invert) = 1.;
83  if (field(i,j,k,1-invert) < 0.) field(i,j,k,1-invert) = 0.;
84  if (field(i,j,k,1-invert) > 1.) field(i,j,k,1-invert) = 1.;
85  }
86 
87  });
88  }
89  a_field[lev]->FillBoundary();
90  }
91 
92 private:
94  amrex::Vector<Set::Vector> center;
95  amrex::Vector<Set::Matrix> A;
96  amrex::Vector<Set::Scalar> eps;
97  int invert = 0;
98 
99 public:
100  static void Parse(Ellipse & value, IO::ParmParse & pp)
101  {
102  amrex::Vector<Set::Scalar> x0;
103  if(!(pp.contains("number_of_inclusions")))
104  {
105  value.center.resize(0);
106  value.A.resize(0);
107  value.eps.resize(0);
108 
109  value.number_of_inclusions = 0;
110  pp_queryarr("x0",x0); // Coorinates of ellipse center
111  value.center.push_back(Set::Vector(AMREX_D_DECL(x0[0],x0[1],x0[2])));
112 
113  Set::Scalar _eps;
114  pp_query_default("eps",_eps,0.0); // Diffuse boundary thickness
115  value.eps.push_back(_eps);
116 
117  Set::Matrix _A = Set::Matrix::Zero();
118  if (pp.contains("A"))
119  {
120  pp_queryarr("A",_A); // DxD square matrix defining an ellipse.
121  value.A.push_back(_A);
122  }
123  else if (pp.contains("a"))
124  {
125  Set::Matrix _A = Set::Matrix::Zero();
126  Set::Vector a = Set::Vector::Ones();
127  pp_queryarr("a",a); // If :code:`A` is not defined, then assume a sphere with radius :code:`a`
128  for (int d = 0; d < AMREX_SPACEDIM; d++) _A(d,d) = 1./a(d)/a(d);
129  value.A.push_back(_A);
130  }
131  }
132  else
133  {
134  pp_query("number_of_inclusions",value.number_of_inclusions); // Number of ellipses
135  if(value.number_of_inclusions < 1) Util::Abort(INFO, "number of inclusions have to be at least 1");
136 
137  value.center.resize(0);
138  value.A.resize(0);
139  value.eps.resize(0);
140 
141  if (pp.contains("center") && pp.contains("x0")) Util::Abort(INFO,"Cannot specify both center (depricated) and x0");
142  pp_queryarr("center", x0); // center of the ellipse
143  pp_queryarr("x0", x0); // center of the ellipse
144 
145  if(x0.size() != value.number_of_inclusions*AMREX_SPACEDIM){
146  Util::Message(INFO, value.number_of_inclusions*AMREX_SPACEDIM);
147  Util::Message(INFO, x0.size());
148  Util::Abort(INFO, "Need centers for all the inclusions");}
149  for (int i = 0; i < x0.size(); i+= AMREX_SPACEDIM)
150  value.center.push_back(Set::Vector(AMREX_D_DECL(x0[i],x0[i+1],x0[i+2])));
151 
152  if (pp.contains("A"))
153  {
154  amrex::Vector<Set::Scalar> _A;
155  pp_queryarr("A", _A); // either a vector containing ellipse radii, or a matrix defining the ellipse
156  if(_A.size() != value.number_of_inclusions*AMREX_SPACEDIM*AMREX_SPACEDIM && _A.size() != AMREX_SPACEDIM*AMREX_SPACEDIM)
157  Util::Abort(INFO, "Invalid value of A for ellipse initialization");
158  if(_A.size() == AMREX_SPACEDIM*AMREX_SPACEDIM)
159  {
160  Set::Matrix _A1 = Set::Matrix::Zero();
161  pp_queryarr("A",_A1); // Same
162  for (int i = 0; i < value.number_of_inclusions; i++)
163  value.A.push_back(_A1);
164  }
165  else
166  {
167  Set::Matrix _A1 = Set::Matrix::Zero();
168  for (int i = 0; i < value.number_of_inclusions; i+= AMREX_SPACEDIM*AMREX_SPACEDIM)
169  {
170  AMREX_D_PICK( _A1(0,0) = _A[i];
171  ,
172  _A1(0,0) = _A[i]; _A1(0,1) = _A[i+1];
173  _A1(1,0) = _A[i+2]; _A1(1,1) = _A[i+3];
174  ,
175  _A1(0,0) = _A[i+0]; _A1(0,1) = _A[i+1]; _A1(0,2) = _A[i+2];
176  _A1(1,0) = _A[i+3]; _A1(1,1) = _A[i+4]; _A1(1,2) = _A[i+5];
177  _A1(2,0) = _A[i+6]; _A1(2,1) = _A[i+7]; _A1(2,2) = _A[i+8];
178  );
179  value.A.push_back(_A1);
180  }
181  }
182  }
183  else if (pp.contains("radius"))
184  {
185  amrex::Vector<Set::Scalar> _r;
186  pp_queryarr("radius", _r); // Array of radii [depricated]
187 
188  if(_r.size() != value.number_of_inclusions*AMREX_SPACEDIM && _r.size() != AMREX_SPACEDIM)
189  Util::Abort(INFO, "Invalid value of radius for ellipse initialization");
190  if(_r.size() == AMREX_SPACEDIM)
191  {
192  Set::Matrix _A1 = Set::Matrix::Zero();
193  for (int i = 0; i< AMREX_SPACEDIM; i++) _A1(i,i) = 1.0/(_r[i]*_r[i]);
194  for (int i = 0; i < value.number_of_inclusions; i++)
195  value.A.push_back(_A1);
196  }
197  else
198  {
199  for (int i = 0; i < value.number_of_inclusions; i++)
200  {
201  Set::Matrix _A1 = Set::Matrix::Zero();
202  for (int d = 0; d < AMREX_SPACEDIM; d++) _A1(d,d) = 1.0/_r[i+d]/_r[i+d];
203  value.A.push_back(_A1);
204  }
205  }
206  }
207 
208  amrex::Vector<Set::Scalar> _eps;
209  pp_queryarr("eps",_eps); // Regularization for smooth boundary
210  if(_eps.size() != 1 && _eps.size() != value.number_of_inclusions)
211  Util::Abort(INFO, "Incorrect eps. Check the number of values specified");
212 
213  if (_eps.size() == 1)
214  for (int i = 0; i < value.number_of_inclusions; i++) value.eps.push_back(_eps[0]);
215 
216  else
217  for (int i = 0; i < value.number_of_inclusions; i++) value.eps.push_back(_eps[i]);
218  }
219  // Flip the inside and the outside
220  pp_query("invert",value.invert);
221  }
222 };
223 }
224 #endif
IC::IC::geom
amrex::Vector< amrex::Geometry > & geom
Definition: IC.H:45
IC::Ellipse::number_of_inclusions
int number_of_inclusions
Definition: Ellipse.H:93
BC::AMREX_D_DECL
@ AMREX_D_DECL
Definition: BC.H:34
IC::Ellipse
Definition: Ellipse.H:21
Set::Field< Set::Scalar >
Definition: Set.H:236
IC::Ellipse::Add
void Add(const int &lev, Set::Field< Set::Scalar > &a_field, Set::Scalar)
Definition: Ellipse.H:30
Set::Vector
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition: Base.H:20
ParmParse.H
pp_query
#define pp_query(...)
Definition: ParmParse.H:104
Set::Scalar
amrex::Real Scalar
Definition: Base.H:19
pp_queryclass
#define pp_queryclass(...)
Definition: ParmParse.H:105
Set::Matrix
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition: Base.H:23
IC::Ellipse::Parse
static void Parse(Ellipse &value, IO::ParmParse &pp)
Definition: Ellipse.H:100
IC::Ellipse::eps
amrex::Vector< Set::Scalar > eps
Definition: Ellipse.H:96
IC::Ellipse::Dirac
@ Dirac
Definition: Ellipse.H:24
IO::ParmParse::contains
bool contains(std::string name)
Definition: ParmParse.H:151
pp_query_default
#define pp_query_default(...)
Definition: ParmParse.H:100
IC::Ellipse::Mollifier
Mollifier
Definition: Ellipse.H:24
Util::Abort
void Abort(const char *msg)
Definition: Util.cpp:165
IC::Ellipse::Gaussian
@ Gaussian
Definition: Ellipse.H:24
IC::Ellipse::center
amrex::Vector< Set::Vector > center
Definition: Ellipse.H:94
Set.H
IC
Definition: Affine.H:18
IO::ParmParse
Definition: ParmParse.H:110
IC::Ellipse::Ellipse
Ellipse(amrex::Vector< amrex::Geometry > &_geom, IO::ParmParse &pp, std::string name)
Definition: Ellipse.H:27
IC::Ellipse::Ellipse
Ellipse(amrex::Vector< amrex::Geometry > &_geom)
Definition: Ellipse.H:26
INFO
#define INFO
Definition: Util.H:20
IC.H
IC::Ellipse::A
amrex::Vector< Set::Matrix > A
Definition: Ellipse.H:95
Util::Message
void Message(std::string file, std::string func, int line, Args const &... args)
Definition: Util.H:133
IC::Ellipse::invert
int invert
Definition: Ellipse.H:97
pp_queryarr
#define pp_queryarr(...)
Definition: ParmParse.H:103