www.mooseframework.org
PolycrystalVoronoiVoidIC.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
3 /* */
4 /* All contents are licensed under LGPL V2.1 */
5 /* See LICENSE for full restrictions */
6 /****************************************************************/
8 
9 // MOOSE includes
10 #include "MooseMesh.h"
11 #include "MooseVariable.h"
12 
13 InputParameters
15 {
16  InputParameters params = validParams<MultiSmoothCircleIC>();
17 
18  params.addRequiredParam<unsigned int>("op_num", "Number of order parameters");
19  params.addRequiredParam<unsigned int>(
20  "grain_num", "Number of grains being represented by the order parameters");
21 
22  params.addParam<unsigned int>("rand_seed", 12444, "The random seed");
23 
24  params.addParam<bool>(
25  "columnar_3D", false, "3D microstructure will be columnar in the z-direction?");
26 
27  return params;
28 }
29 
30 template <>
31 InputParameters
33 {
34  InputParameters params = PolycrystalVoronoiVoidIC::actionParameters();
35  MooseEnum structure_options("grains voids");
36  params.addRequiredParam<MooseEnum>("structure_type",
37  structure_options,
38  "Which structure type is being initialized, grains or voids");
39  params.addParam<unsigned int>("op_index",
40  0,
41  "The index for the current "
42  "order parameter, not needed if "
43  "structure_type = voids");
44  return params;
45 }
46 
47 PolycrystalVoronoiVoidIC::PolycrystalVoronoiVoidIC(const InputParameters & parameters)
48  : MultiSmoothCircleIC(parameters),
49  _structure_type(getParam<MooseEnum>("structure_type")),
50  _op_num(getParam<unsigned int>("op_num")),
51  _grain_num(getParam<unsigned int>("grain_num")),
52  _op_index(getParam<unsigned int>("op_index")),
53  _rand_seed(getParam<unsigned int>("rand_seed")),
54  _columnar_3D(getParam<bool>("columnar_3D"))
55 {
56  if (_invalue < _outvalue)
57  mooseError("PolycrystalVoronoiVoidIC requires that the voids be "
58  "represented with invalue > outvalue");
59  if (_numbub == 0)
60  mooseError("PolycrystalVoronoiVoidIC requires numbub > 0. If you want no voids to "
61  "be "
62  "represented, use invalue = outvalue. In general, you should use "
63  "PolycrystalReducedIC to represent Voronoi grain structures without "
64  "voids.");
65 }
66 
67 void
69 {
70  if (_op_num <= _op_index)
71  mooseError("op_index is too large in CircleGrainVoidIC");
72 
73  MooseRandom::seed(getParam<unsigned int>("rand_seed"));
74  // Set up domain bounds with mesh tools
75  for (unsigned int i = 0; i < LIBMESH_DIM; i++)
76  {
77  _bottom_left(i) = _mesh.getMinInDimension(i);
78  _top_right(i) = _mesh.getMaxInDimension(i);
79  }
81 
82  // Create _centerpoints and _assigned_op vectors
84 
85  // Call initial setup from MultiSmoothCircleIC to create _centers and _radii
86  // for voids
88 }
89 
90 void
92 {
93  _centers.resize(_numbub);
94 
95  // This Code will place void center points on grain boundaries
96  for (unsigned int vp = 0; vp < _numbub; ++vp)
97  {
98  bool try_again;
99  unsigned int num_tries = 0;
100 
101  do
102  {
103  try_again = false;
104  num_tries++;
105 
106  if (num_tries > _max_num_tries)
107  mooseError("Too many tries of assigning void centers in "
108  "PolycrystalVoronoiVoidIC");
109 
110  Point rand_point;
111 
112  for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
113  rand_point(i) = _bottom_left(i) + _range(i) * MooseRandom::rand();
114 
115  // Allow the vectors to be sorted based on their distance from the
116  // rand_point
117  std::vector<PolycrystalVoronoiVoidIC::DistancePoint> diff(_grain_num);
118 
119  for (unsigned int gr = 0; gr < _grain_num; ++gr)
120  {
121  diff[gr].d = _mesh.minPeriodicDistance(_var.number(), rand_point, _centerpoints[gr]);
122  diff[gr].gr = gr;
123  }
124 
125  std::sort(diff.begin(), diff.end(), _customLess);
126 
127  Point closest_point = _centerpoints[diff[0].gr];
128  Point next_closest_point = _centerpoints[diff[1].gr];
129 
130  // Find Slope of Line in the plane orthogonal to the diff_centerpoint
131  // vector
132  Point diff_centerpoints =
133  _mesh.minPeriodicVector(_var.number(), closest_point, next_closest_point);
134  Point diff_rand_center = _mesh.minPeriodicVector(_var.number(), closest_point, rand_point);
135  Point normal_vector = diff_centerpoints.cross(diff_rand_center);
136  Point slope = normal_vector.cross(diff_centerpoints);
137 
138  // Midpoint position vector between two center points
139  Point midpoint = closest_point + (0.5 * diff_centerpoints);
140 
141  // Solve for the scalar multiplier solution on the line
142  Real lambda = 0;
143  Point mid_rand_vector = _mesh.minPeriodicVector(_var.number(), midpoint, rand_point);
144 
145  for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
146  lambda += (mid_rand_vector(i) * slope(i)) /
147  (slope(0) * slope(0) + slope(1) * slope(1) + slope(2) * slope(2));
148 
149  // Assigning points to vector
150  _centers[vp] = slope * lambda + midpoint;
151 
152  // Checking to see if points are in the domain ONLY WORKS FOR PERIODIC
153  for (unsigned int i = 0; i < LIBMESH_DIM; i++)
154  if ((_centers[vp](i) > _top_right(i)) || (_centers[vp](i) < _bottom_left(i)))
155  try_again = true;
156 
157  for (unsigned int i = 0; i < vp; ++i)
158  {
159  Real dist = _mesh.minPeriodicDistance(_var.number(), _centers[vp], _centers[i]);
160 
161  if (dist < _bubspac)
162  try_again = true;
163  }
164 
165  // Two algorithms are available for screening bubbles falling in grain
166  // interior. They produce
167  // nearly identical results.
168  // Here only one is listed. The other one is available upon request.
169 
170  // Use circle center for checking whether voids are at GBs
171  if (try_again == false)
172  {
173  Real min_rij_1, min_rij_2, rij, rij_diff_tol;
174 
175  min_rij_1 = _range.norm();
176  min_rij_2 = _range.norm();
177 
178  rij_diff_tol = 0.1 * _radius;
179 
180  for (unsigned int gr = 0; gr < _grain_num; ++gr)
181  {
182  rij = _mesh.minPeriodicDistance(_var.number(), _centers[vp], _centerpoints[gr]);
183 
184  if (rij < min_rij_1)
185  {
186  min_rij_2 = min_rij_1;
187  min_rij_1 = rij;
188  }
189  else if (rij < min_rij_2)
190  min_rij_2 = rij;
191  }
192 
193  if (std::abs(min_rij_1 - min_rij_2) > rij_diff_tol)
194  try_again = true;
195  }
196 
197  } while (try_again == true);
198  }
199 }
200 
201 Real
203 {
204  Real value = 0.0;
205 
206  // Determine value for voids
207  Real void_value = MultiSmoothCircleIC::value(p);
208 
209  // Determine value for grains
210  Real grain_value = grainValueCalc(p);
211 
212  switch (_structure_type)
213  {
214  case 0: // assigning values for grains (order parameters)
215  if (grain_value == 0) // Not in this grain
216  value = grain_value;
217  else // in this grain, but might be in a void
218  if (void_value == _outvalue) // Not in a void
219  value = grain_value;
220  else if (void_value > _outvalue && void_value < _invalue) // On void interface
221  value = 1.0 - (void_value - _outvalue) / (_invalue - _outvalue);
222  else if (void_value == _invalue) // In a void, so op = 0
223  value = 0.0;
224  break;
225 
226  case 1: // assigning values for voids (concentration)
227  value = void_value;
228  break;
229  }
230 
231  return value;
232 }
233 
234 RealGradient
236 {
237  RealGradient gradient;
238  RealGradient void_gradient = MultiSmoothCircleIC::gradient(p);
239 
240  // Order parameter assignment assumes zero gradient (sharp interface)
241  switch (_structure_type)
242  {
243  case 1: // assigning gradient for voids
244  gradient = void_gradient;
245  break;
246  }
247 
248  return gradient;
249 }
250 
251 Real
253 {
254  Real val = 0.0;
255 
256  unsigned int min_index =
258 
259  // If the current order parameter index (_op_index) is equal to the min_index,
260  // set the value to
261  // 1.0
262  if (_assigned_op[min_index] == _op_index)
263  val = 1.0;
264 
265  if (val > 1.0)
266  val = 1.0;
267 
268  if (val < 0.0)
269  val = 0.0;
270 
271  return val;
272 }
273 
274 void
276 {
277  if (_op_num > _grain_num)
278  mooseError("ERROR in PolycrystalVoronoiVoidIC: Number of order parameters "
279  "(op_num) can't be "
280  "larger than the number of grains (grain_num)");
281 
282  // Initialize vectors
283  _centerpoints.resize(_grain_num);
284  _assigned_op.resize(_grain_num);
285 
286  // Randomly generate the centers of the individual grains represented by the
287  // Voronoi tessellation
288  for (unsigned int grain = 0; grain < _grain_num; grain++)
289  {
290  for (unsigned int i = 0; i < LIBMESH_DIM; i++)
291  _centerpoints[grain](i) = _bottom_left(i) + _range(i) * MooseRandom::rand();
292 
293  if (_columnar_3D)
294  _centerpoints[grain](2) = _bottom_left(2) + _range(2) * 0.5;
295  }
296 
297  // Assign grains to specific order parameters in a way that maximizes the
298  // distance
300 }
struct PolycrystalVoronoiVoidIC::DistancePointComparator _customLess
std::vector< Point > _centers
const unsigned int _max_num_tries
virtual Real value(const Point &p)
std::vector< Point > _centerpoints
unsigned int assignPointToGrain(const Point &p, const std::vector< Point > &centerpoints, const MooseMesh &mesh, const MooseVariable &var, const Real maxsize)
virtual Real value(const Point &p) override
std::vector< unsigned int > assignPointsToVariables(const std::vector< Point > &centerpoints, const Real op_num, const MooseMesh &mesh, const MooseVariable &var)
InputParameters validParams< MultiSmoothCircleIC >()
const unsigned int _numbub
PolycrystalVoronoiVoidIC(const InputParameters &parameters)
virtual RealGradient gradient(const Point &p)
virtual void initialSetup()
virtual Real grainValueCalc(const Point &p)
virtual RealGradient gradient(const Point &p) override
InputParameters validParams< PolycrystalVoronoiVoidIC >()
static InputParameters actionParameters()
virtual void computeCircleCenters() override
MultismoothCircleIC creates multiple SmoothCircles (number = numbub) that are randomly positioned aro...
virtual void initialSetup() override
std::vector< unsigned int > _assigned_op