https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MultiSmoothSuperellipsoidIC.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10// Creates multiple superellipsoids that are positioned randomly throughout the domain
11// each semiaxis can be varied by a uniform or normal distribution
12
14
15// MOOSE includes
16#include "MooseMesh.h"
17#include "MooseUtils.h"
18#include "MooseVariable.h"
19
21
24{
26 params.addClassDescription("Random distribution of smooth ellipse with given minimum spacing");
27 params.addRequiredParam<std::vector<unsigned int>>("numbub",
28 "Vector of the number of bubbles to place");
29 params.addRequiredParam<std::vector<Real>>(
30 "bubspac",
31 "Vector of the minimum spacing of bubbles of one type, measured from center to center");
32 params.addParam<unsigned int>("max_num_tries", 1000, "The number of tries");
33 params.addRequiredParam<std::vector<Real>>(
34 "semiaxis_a", "Vector of mean semiaxis values in the x direction for the ellipse");
35 params.addRequiredParam<std::vector<Real>>(
36 "semiaxis_b", "Vector of mean semiaxis values in the y direction for the ellipse");
37 params.addRequiredParam<std::vector<Real>>("semiaxis_c",
38 "Vector of mean semiaxis values in the z direction "
39 "for the ellipse, must be greater than 0 even if 2D.");
40 params.addParam<std::vector<Real>>(
41 "exponent",
42 std::vector<Real>(),
43 "Vector of exponents for each superellipsoid, n=2 is a normal ellipse");
44 params.addParam<std::vector<Real>>("semiaxis_a_variation",
45 std::vector<Real>(),
46 "Vector of plus or minus fractions of random variation in the "
47 "bubble semiaxis in the x direction for uniform, standard "
48 "deviation for normal");
49 params.addParam<std::vector<Real>>("semiaxis_b_variation",
50 std::vector<Real>(),
51 "Vector of plus or minus fractions of random variation in the "
52 "bubble semiaxis in the y direction for uniform, standard "
53 "deviation for normal");
54 params.addParam<std::vector<Real>>("semiaxis_c_variation",
55 std::vector<Real>(),
56 "Vector of plus or minus fractions of random variation in the "
57 "bubble semiaxis in the z direction for uniform, standard "
58 "deviation for normal. Must be set to 0 if 2D.");
59 params.addParam<bool>("check_extremes",
60 false,
61 "Check all Superellipsoid extremes (center +- "
62 "each semiaxis) for overlap, must have "
63 "prevent_overlap set to True.");
64 params.addParam<bool>("prevent_overlap",
65 false,
66 "Check all Superellipsoid centers for overlap with other superellipsoids.");
67 params.addParam<bool>("vary_axes_independently",
68 true,
69 "If true the length of each semiaxis is randomly chosen "
70 "within the provided parameters, if false then one random "
71 "number is generated and applied to all semiaxes.");
72 MooseEnum rand_options("uniform normal none", "none");
73 params.addParam<MooseEnum>(
74 "semiaxis_variation_type",
75 rand_options,
76 "Type of distribution that random superellipsoid semiaxes will follow");
77 return params;
78}
79
81 : SmoothSuperellipsoidBaseIC(parameters),
82 _max_num_tries(getParam<unsigned int>("max_num_tries")),
83 _semiaxis_variation_type(getParam<MooseEnum>("semiaxis_variation_type")),
84 _prevent_overlap(getParam<bool>("prevent_overlap")),
85 _check_extremes(getParam<bool>("check_extremes")),
86 _vary_axes_independently(getParam<bool>("vary_axes_independently")),
87 _numbub(parameters.get<std::vector<unsigned int>>("numbub")),
88 _bubspac(parameters.get<std::vector<Real>>("bubspac")),
89 _exponent(parameters.get<std::vector<Real>>("exponent")),
90 _semiaxis_a(parameters.get<std::vector<Real>>("semiaxis_a")),
91 _semiaxis_b(parameters.get<std::vector<Real>>("semiaxis_b")),
92 _semiaxis_c(parameters.get<std::vector<Real>>("semiaxis_c")),
93 _semiaxis_a_variation(parameters.get<std::vector<Real>>("semiaxis_a_variation")),
94 _semiaxis_b_variation(parameters.get<std::vector<Real>>("semiaxis_b_variation")),
95 _semiaxis_c_variation(parameters.get<std::vector<Real>>("semiaxis_c_variation"))
96{
97}
98
99void
101{
102 unsigned int nv = _numbub.size();
103
104 if (nv != _bubspac.size() || nv != _exponent.size() || nv != _semiaxis_a.size() ||
105 nv != _semiaxis_b.size() || nv != _semiaxis_c.size())
106 mooseError("Vectors for numbub, bubspac, exponent, semiaxis_a, semiaxis_b, and semiaxis_c must "
107 "be the same size.");
108
109 if (_semiaxis_variation_type != 2 &&
110 (nv != _semiaxis_a_variation.size() || nv != _semiaxis_b_variation.size() ||
111 nv != _semiaxis_c_variation.size()))
112 mooseError("Vectors for numbub, semiaxis_a_variation, semiaxis_b_variation, and "
113 "semiaxis_c_variation must be the same size.");
114
115 if (_semiaxis_variation_type == 2 &&
116 (_semiaxis_a_variation.size() > 0 || _semiaxis_b_variation.size() > 0 ||
117 _semiaxis_c_variation.size() > 0))
119 "Values were provided for semiaxis_a/b/c_variation but semiaxis_variation_type is set "
120 "to 'none' in 'MultiSmoothSuperellipsoidIC'.");
121
122 for (_gk = 0; _gk < nv; ++_gk)
123 {
124 // Set up domain bounds with mesh tools
125 for (const auto i : make_range(Moose::dim))
126 {
129 }
131
133 }
134}
135
136void
138{
139 Real randnum;
140 unsigned int start = _as.size();
141 _as.resize(start + _numbub[_gk]);
142 _bs.resize(start + _numbub[_gk]);
143 _cs.resize(start + _numbub[_gk]);
144
145 for (unsigned int i = start; i < _as.size(); i++)
146 {
148 {
149 case 0: // Uniform distrubtion
150 randnum = _random.rand(_tid);
151 _as[i] = _semiaxis_a[_gk] * (1.0 + (1.0 - 2.0 * randnum) * _semiaxis_a_variation[_gk]);
152 _bs[i] = _semiaxis_b[_gk] *
153 (1.0 + (1.0 - 2.0 * (_vary_axes_independently ? _random.rand(_tid) : randnum)) *
155 _cs[i] = _semiaxis_c[_gk] *
156 (1.0 + (1.0 - 2.0 * (_vary_axes_independently ? _random.rand(_tid) : randnum)) *
158 break;
159
160 case 1: // Normal distribution
161 randnum = _random.randNormal(_tid, 0, 1);
162 _as[i] = _semiaxis_a[_gk] + (randnum * _semiaxis_a_variation[_gk]);
163 _bs[i] = _semiaxis_b[_gk] +
164 ((_vary_axes_independently ? _random.randNormal(_tid, 0, 1) : randnum) *
166 _cs[i] = _semiaxis_c[_gk] +
167 ((_vary_axes_independently ? _random.randNormal(_tid, 0, 1) : randnum) *
169 break;
170
171 case 2: // No variation
172 _as[i] = _semiaxis_a[_gk];
173 _bs[i] = _semiaxis_b[_gk];
174 _cs[i] = _semiaxis_c[_gk];
175 }
176
177 _as[i] = _as[i] < 0.0 ? 0.0 : _as[i];
178 _bs[i] = _bs[i] < 0.0 ? 0.0 : _bs[i];
179 _cs[i] = _cs[i] < 0.0 ? 0.0 : _cs[i];
180 }
181}
182
183void
185{
186 unsigned int start = _centers.size();
187 _centers.resize(start + _numbub[_gk]);
188
189 for (unsigned int i = start; i < _centers.size(); i++)
190 {
191 // Vary circle center positions
192 unsigned int num_tries = 0;
193 while (num_tries < _max_num_tries)
194 {
195 num_tries++;
196
197 RealTensorValue ran;
198 ran(0, 0) = _random.rand(_tid);
199 ran(1, 1) = _random.rand(_tid);
200 ran(2, 2) = _random.rand(_tid);
201
202 _centers[i] = _bottom_left + ran * _range;
203
204 for (unsigned int j = 0; j < i; ++j)
206 ellipsoidsOverlap(i, j))
207 goto fail;
208
209 // accept the position of the new center
210 goto accept;
211
212 // retry a new position until tries are exhausted
213 fail:
214 continue;
215 }
216
217 if (num_tries == _max_num_tries)
218 mooseError("max_num_tries reached in 'MultiSmoothSuperellipsoidIC'.");
219
220 accept:
221 continue;
222 }
223}
224
225void
227{
228 unsigned int start = _ns.size();
229 _ns.resize(start + _numbub[_gk]);
230
231 for (unsigned int i = start; i < _ns.size(); ++i)
232 _ns[i] = _exponent[_gk];
233}
234
235bool
237{
238 // Check for overlap between centers
239 const Point dist_vec = _mesh.minPeriodicVector(_var, _centers[i], _centers[j]);
240 const Real dist = dist_vec.norm();
241
242 // Handle this case independently because we cannot calculate polar angles at this point
243 if (MooseUtils::absoluteFuzzyEqual(dist, 0.0))
244 return true;
245
246 // Compute the distance r from the center of the superellipsoid to its outside edge
247 // along the vector from the center to the current point
248 // This uses the equation for a superellipse in polar coordinates and substitutes
249 // distances for sin, cos functions
250 Real rmn;
251
252 // calculate rmn = r^(-n), replacing sin, cos functions with distances
253 rmn = (std::pow(std::abs(dist_vec(0) / dist / _as[i]), _ns[i]) +
254 std::pow(std::abs(dist_vec(1) / dist / _bs[i]), _ns[i]) +
255 std::pow(std::abs(dist_vec(2) / dist / _cs[i]), _ns[i]));
256 // calculate r2 from rmn
257 const Real r1 = std::pow(rmn, (-1.0 / _ns[i]));
258
259 // calculate rmn = r^(-n), replacing sin, cos functions with distances
260 rmn = (std::pow(std::abs(dist_vec(0) / dist / _as[j]), _ns[j]) +
261 std::pow(std::abs(dist_vec(1) / dist / _bs[j]), _ns[j]) +
262 std::pow(std::abs(dist_vec(2) / dist / _cs[j]), _ns[j]));
263 const Real r2 = std::pow(rmn, (-1.0 / _ns[j]));
264
265 if (dist < r1 + r2)
266 return true;
267
268 // Check for overlap between extremes of new ellipsoid candidate and the center
269 // of accepted ellisoids if _check_extremes enabled
270 if (_check_extremes)
271 return checkExtremes(i, j) || checkExtremes(j, i);
272
273 // otherwise no overlap has been detected
274 return false;
275}
276
277bool
278MultiSmoothSuperellipsoidIC::checkExtremes(unsigned int i, unsigned int j)
279{
280 Point tmp_p;
281 for (unsigned int pc = 0; pc < 6; pc++)
282 {
283 tmp_p = _centers[j];
284 // Find extremes along semiaxis of candidate ellipsoids
285 if (pc == 0)
286 tmp_p(0) -= _as[j];
287 else if (pc == 1)
288 tmp_p(0) += _as[j];
289 else if (pc == 2)
290 tmp_p(1) -= _bs[j];
291 else if (pc == 3)
292 tmp_p(1) += _bs[j];
293 else if (pc == 4)
294 tmp_p(2) -= _cs[j];
295 else
296 tmp_p(2) += _cs[j];
297
298 const Point dist_vec = _mesh.minPeriodicVector(_var, _centers[i], tmp_p);
299 const Real dist = dist_vec.norm();
300
301 // Handle this case independently because we cannot calculate polar angles at this point
302 if (MooseUtils::absoluteFuzzyEqual(dist, 0.0))
303 return true;
304
305 // calculate rmn = r^(-n), replacing sin, cos functions with distances
306 Real rmn = (std::pow(std::abs(dist_vec(0) / dist / _as[i]), _ns[i]) +
307 std::pow(std::abs(dist_vec(1) / dist / _bs[i]), _ns[i]) +
308 std::pow(std::abs(dist_vec(2) / dist / _cs[i]), _ns[i]));
309 Real r = std::pow(rmn, (-1.0 / _ns[i]));
310
311 if (dist < r)
312 return true;
313 }
314
315 return false;
316}
registerMooseObject("PhaseFieldApp", MultiSmoothSuperellipsoidIC)
void ErrorVector unsigned int
MooseVariableField< T > & _var
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
RealVectorValue minPeriodicVector(const unsigned int sys_num, const unsigned int var_num, Point p, Point q) const
Real minPeriodicDistance(const unsigned int sys_num, const unsigned int var_num, const Point &p, const Point &q) const
virtual Real getMaxInDimension(unsigned int component) const
virtual Real getMinInDimension(unsigned int component) const
Real rand(std::size_t i)
Real randNormal(std::size_t i, Real mean, Real sigma)
MultismoothSuperellipsoidIC creates multiple SmoothSuperellipsoid (number = numbub) that are randomly...
virtual bool checkExtremes(unsigned int i, unsigned int j)
virtual bool ellipsoidsOverlap(unsigned int i, unsigned int j)
MultiSmoothSuperellipsoidIC(const InputParameters &parameters)
std::vector< unsigned int > _numbub
SmoothSuperellipsoidBaseIC is the base class for all initial conditions that create superellipsoids.
static InputParameters validParams()
static constexpr std::size_t dim