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