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