Alamo
Laminate.H
Go to the documentation of this file.
1//
2// Create a single laminate with specified orientation, thickness, and offset.
3//
4
5#ifndef IC_LAMINATE_H_
6#define IC_LAMINATE_H_
7
8#include "IC/IC.H"
9#include "Util/Util.H"
10#include "IO/ParmParse.H"
11
12namespace IC
13{
14/// Initialize Laminates in a matrix
15class Laminate: public IC<Set::Scalar>
16{
17public:
18 static constexpr const char* name = "laminate";
20
21 Laminate(amrex::Vector<amrex::Geometry>& _geom): IC(_geom) {}
22 Laminate(amrex::Vector<amrex::Geometry>& _geom, IO::ParmParse& pp, std::string name): IC(_geom)
23 {
24 pp_queryclass(name, *this);
25 }
26
27 void Add(const int& lev, Set::Field<Set::Scalar>& a_field, Set::Scalar)
28 {
29 for (amrex::MFIter mfi(*a_field[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
30 {
31 amrex::Box bx = mfi.tilebox();
32 bx.grow(a_field[lev]->nGrow());
33 amrex::IndexType type = a_field[lev]->ixType();
34
35 amrex::Array4<Set::Scalar> const& field = a_field[lev]->array(mfi);
36 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
37
38 Set::Vector x = Set::Position(i, j, k, geom[lev], type);
39
40 // The base matrix is always field(i,j,k,0)
41 // Inclusions start with field(i,j,k,1)
42
43 if (!singlefab)
44 {
45 Set::Scalar value = 0.0;
46 for (int m = 0; m < number_of_inclusions; m++)
47 {
48 Set::Scalar t = std::abs((x - center[m]).transpose() * orientation[m]) - (thickness[m] / 2.0);
49 field(i, j, k, m + 1) = 0.5 - 0.5 * std::erf(t / eps[m]);
50 if (field(i, j, k, m + 1) < 0.) field(i, j, k, m + 1) = 0.;
51 if (field(i, j, k, m + 1) > 1.) field(i, j, k, m + 1) = 1.;
52 value += field(i, j, k, m + 1);
53 }
54 field(i, j, k, 0) = 1.0 - value;
55 if (field(i, j, k, 0) < 0.) field(i, j, k, 0) = 0.;
56 if (field(i, j, k, 0) > 1.) field(i, j, k, 0) = 1.;
57 }
58 else
59 {
60 Set::Scalar t = std::abs((x - center[0]).transpose() * orientation[0]) - (thickness[0] / 2.0);
61 field(i, j, k, 0) = 0.5 - 0.5 * std::erf(t / eps[0]);
62 if (invert) field(i, j, k, 0) = 1.0 - field(i, j, k, 0);
63 }
64 });
65 }
66 a_field[lev]->FillBoundary();
67 };
68
69private:
71 amrex::Vector<Set::Vector> center;
72 amrex::Vector<Set::Vector> orientation;
73 amrex::Vector<Set::Vector> normal;
74 amrex::Vector<Set::Scalar> eps;
75 amrex::Vector<Set::Scalar> thickness;
77 bool singlefab = false;
78 bool invert = false;
79
80public:
81 static void Parse(Laminate& value, IO::ParmParse& pp)
82 {
83 // How many laminates (MUST be greater than or equal to 1).
84 pp_query_default("number_of_inclusions", value.number_of_inclusions, 1);
85
86 amrex::Vector<Set::Scalar> a_center;
87 // (x,y,[z]) values for the center point of the laminate
88 pp.queryarr("center", a_center, Unit::Length());
89
90 amrex::Vector<Set::Scalar> a_thickness;
91 // thickness of the laminate
92 pp.queryarr("thickness", a_thickness,Unit::Length());
93
94 amrex::Vector<Set::Scalar> a_orientation;
95 // Vector normal to the interface of the laminate
96 pp_queryarr("orientation", a_orientation);
97
98 amrex::Vector<Set::Scalar> a_eps;
99 // Diffuse thickness
100 pp.queryarr("eps", a_eps, Unit::Length());
101
102 std::string mollifier;
103 // Type of mollifer to use (options: dirac, [gaussian])
104 pp.query_switch("mollifier", {
105 {"dirac", [&]() {value.moll = Mollifier::Dirac; }},
106 {"gaussian", [&]() {value.moll = Mollifier::Gaussian; }}
107 });
108
109 // Switch to mode where only one component is used.
110 pp.query_default("singlefab", value.singlefab,false);
111
112 // Take the complement of the laminate
113 pp.query_default("invert", value.invert,false);
114
115 if (IO::ParmParse::InTraversalMode()) return;
116
117 if (value.number_of_inclusions < 1)
118 Util::Abort(INFO, "Number of inclusions must be at least 1. Aborting.");
119
120 if (a_center.size() != value.number_of_inclusions * AMREX_SPACEDIM) value.center.push_back(Set::Vector::Zero());
121 else
122 {
123 for (int i = 0; i < a_center.size(); i += AMREX_SPACEDIM)
124 value.center.push_back(Set::Vector(AMREX_D_DECL(a_center[i], a_center[i + 1], a_center[i + 2])));
125 }
126
127
128 if (a_thickness.size() != value.number_of_inclusions && a_thickness.size() != 1)
129 Util::Abort(INFO, "Thickness of each inclusion must be specified");
130
131 if (a_thickness.size() == 1)
132 {
133 if (a_thickness[0] <= 0.0) Util::Abort(INFO, "Invalid value of inclusion thickness");
134 for (int i = 0; i < value.number_of_inclusions; i++) value.thickness.push_back(a_thickness[0]);
135 }
136
137 else
138 {
139 for (int i = 0; i < value.number_of_inclusions; i++)
140 {
141 if (a_thickness[i] <= 0.0) Util::Abort(INFO, "Invalid value of inclusion ", i + 1, " thickness");
142 value.thickness.push_back(a_thickness[i]);
143 }
144 }
145
146
147 if (a_orientation.size() != value.number_of_inclusions * AMREX_SPACEDIM && a_orientation.size() != AMREX_SPACEDIM)
148 Util::Abort(INFO, "Orientation of each inclusion must be specified");
149
150 if (a_orientation.size() == AMREX_SPACEDIM)
151 for (int i = 0; i < value.number_of_inclusions; i++)
152 value.orientation.push_back(Set::Vector(AMREX_D_DECL(a_orientation[0], a_orientation[1], a_orientation[2])));
153
154 else
155 for (int i = 0; i < a_orientation.size(); i += AMREX_SPACEDIM)
156 value.orientation.push_back(Set::Vector(AMREX_D_DECL(a_orientation[i], a_orientation[i + 1], a_orientation[i + 2])));
157
158 for (int i = 0; i < value.orientation.size(); i++)
159 if (value.orientation[i].lpNorm<2>() <= 0.) value.orientation[i] = Set::Vector::Random();
160
161 for (int i = 0; i < value.orientation.size(); i++)
162 value.orientation[i] = value.orientation[i] / value.orientation[i].lpNorm<2>();
163
164 value.normal.resize(value.number_of_inclusions);
165 for (int i = 0; i < value.orientation.size(); i++)
166 {
167 value.normal[i] = Set::Vector::Zero();
168 if (value.orientation[i](0) != 0.)
169 {
170 AMREX_D_TERM(value.normal[i](0) = 1.;, value.normal[i](1) = 1.;, value.normal[i](2) = 1.;);
171 value.normal[i](0) = -(AMREX_D_TERM(0., +value.orientation[i](1), +value.orientation[i](2))) / value.orientation[i](0);
172 value.normal[i] = value.normal[i] / value.normal[i].lpNorm<2>();
173 }
174 else if (value.orientation[i](1) != 0.)
175 {
176 AMREX_D_TERM(value.normal[i](0) = 1.;, value.normal[i](1) = 1.;, value.normal[i](2) = 1.;);
177 value.normal[i](1) = -(AMREX_D_TERM(value.orientation[i](0), +0.0, +value.orientation[i](2))) / value.orientation[i](1);
178 value.normal[i] = value.normal[i] / value.normal[i].lpNorm<2>();
179 }
180 }
181
182
183 if (a_eps.size() < 1)
184 for (int i = 0; i < value.number_of_inclusions; i++)
185 value.eps.push_back(1.e-5);
186 if (a_eps.size() == 1)
187 {
188 if (a_eps[0] < 0.0)
189 {
190 Util::Warning(INFO, "Invalid value of laminate.eps. Resetting to 1e-5");
191 a_eps[0] = 1.e-5;
192 }
193 for (int i = 0; i < value.number_of_inclusions; i++)
194 value.eps.push_back(a_eps[0]);
195 }
196 else
197 {
198 for (int i = 0; i < value.number_of_inclusions; i++)
199 value.eps.push_back(a_eps[i]);
200 }
201
202 }
203};
204}
205#endif
std::time_t t
#define pp_queryarr(...)
Definition ParmParse.H:126
#define pp_query_default(...)
Definition ParmParse.H:120
#define pp_queryclass(...)
Definition ParmParse.H:130
#define INFO
Definition Util.H:24
amrex::Vector< amrex::Geometry > & geom
Definition IC.H:61
Initialize Laminates in a matrix.
Definition Laminate.H:16
void Add(const int &lev, Set::Field< Set::Scalar > &a_field, Set::Scalar)
Definition Laminate.H:27
amrex::Vector< Set::Vector > orientation
Definition Laminate.H:72
Mollifier moll
Definition Laminate.H:76
amrex::Vector< Set::Vector > center
Definition Laminate.H:71
amrex::Vector< Set::Vector > normal
Definition Laminate.H:73
amrex::Vector< Set::Scalar > thickness
Definition Laminate.H:75
Laminate(amrex::Vector< amrex::Geometry > &_geom)
Definition Laminate.H:21
amrex::Vector< Set::Scalar > eps
Definition Laminate.H:74
bool invert
Definition Laminate.H:78
static constexpr const char * name
Definition Laminate.H:18
bool singlefab
Definition Laminate.H:77
int number_of_inclusions
Definition Laminate.H:70
Laminate(amrex::Vector< amrex::Geometry > &_geom, IO::ParmParse &pp, std::string name)
Definition Laminate.H:22
static void Parse(Laminate &value, IO::ParmParse &pp)
Definition Laminate.H:81
int queryarr(std::string name, std::vector< T > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1024
int query_default(std::string name, T &value, T defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:492
int query_switch(std::string name, std::initializer_list< std::pair< std::string, std::function< void()> > > cases, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:714
static bool InTraversalMode()
Definition ParmParse.cpp:14
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
AMREX_FORCE_INLINE Vector Position(const int &i, const int &j, const int &k, const amrex::Geometry &geom, const amrex::IndexType &ixType)
Definition Base.H:122
void Warning(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:213
AMREX_GPU_HOST_DEVICE void Abort(const char *msg)
Definition Util.cpp:406
static Unit Length()
Definition Unit.H:198