www.mooseframework.org
PolycrystalHex.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 #include "PolycrystalHex.h"
11 #include "MooseRandom.h"
12 #include "MooseMesh.h"
13 #include "MathUtils.h"
14 
15 registerMooseObject("PhaseFieldApp", PolycrystalHex);
16 
19 {
21  params.addClassDescription("Perturbed hexagonal polycrystal");
22  params.addParam<Real>("x_offset", 0.5, "Specifies offset of hexagon grid in x-direction");
23  params.addRangeCheckedParam<Real>(
24  "perturbation_percent",
25  0.0,
26  "perturbation_percent >= 0.0 & perturbation_percent <= 1.0",
27  "The percent to randomly perturb centers of grains relative to the size of the grain");
28  return params;
29 }
30 
32  : PolycrystalVoronoi(parameters),
33  _x_offset(getParam<Real>("x_offset")),
34  _perturbation_percent(getParam<Real>("perturbation_percent"))
35 {
36  if (_columnar_3D == false && _dim == 3)
37  mooseError(
38  "PolycrystalHex is supported on 2D domains or 3D domains with the columnar_3D option");
39  if (_grain_num % 2 != 0)
40  mooseError("PolycrystalHex requires an even square number for 2D or columnar 3D");
41 
42  _random.seed(_tid, getParam<unsigned int>("rand_seed"));
43 }
44 
45 void
47 {
48  unsigned int d = _dim;
49 
50  if (_columnar_3D && _dim == 3)
51  d -= 1;
52 
53  // check if periodic boundary condition is set
54  for (unsigned int j = 0; j < d; ++j)
55  {
56  for (unsigned int i = 0; i < _vars.size(); ++i)
57  if (!_mesh.isTranslatedPeriodic(_vars[i]->number(), j))
58  mooseError("PolycrystalHex works only with periodic BCs");
59  }
60 
61  const unsigned int root = MathUtils::round(std::pow(_grain_num, 1.0 / d));
62 
63  // integer power the rounded root and check if we recover the grain number
64  unsigned int grain_pow = root;
65  for (unsigned int i = 1; i < d; ++i)
66  grain_pow *= root;
67 
68  if (_grain_num != grain_pow)
69  mooseError(
70  "PolycrystalHex requires a square number for 2D or columnar 3D and a cubic number for 3D");
71 
72  // Set up domain bounds with mesh tools
73  for (const auto i : make_range(Moose::dim))
74  {
77  }
79 
80  _centerpoints.resize(_grain_num);
81 
82  std::vector<Real> distances(_grain_num);
83  std::vector<Point> holder(_grain_num);
84 
85  const Real ndist = 1.0 / root;
86 
87  // Assign the relative center points positions, defining the grains according to a hexagonal
88  // pattern
89  unsigned int count = 0;
90 
91  for (unsigned int k = 0; k < (d == 3 ? root : 1); ++k)
92  for (unsigned int j = 0; j < (d >= 2 ? root : 1); ++j)
93  for (unsigned int i = 0; i < root; ++i)
94  {
95  // set x-coordinate
96  holder[count](0) = i * ndist + (0.5 * ndist * (j % 2)) + _x_offset * ndist;
97 
98  // set y-coordinate
99  holder[count](1) = j * ndist + (0.5 * ndist * (k % 2));
100 
101  // set z-coordinate
102  holder[count](2) = k * ndist;
103 
104  // increment counter
105  count++;
106  }
107 
108  // Assign center point values
109  for (unsigned int grain = 0; grain < _grain_num; ++grain)
110  for (const auto i : make_range(Moose::dim))
111  {
112  if (_range(i) == 0)
113  continue;
114 
115  Real perturbation_dist = (_range(i) / root * (_random.rand(_tid) * 2 - 1.0)) *
116  _perturbation_percent; // Perturb -100 to 100%
117  _centerpoints[grain](i) = _bottom_left(i) + _range(i) * holder[grain](i) + perturbation_dist;
118 
119  if (_centerpoints[grain](i) > _top_right(i))
120  _centerpoints[grain](i) = _top_right(i);
121  if (_centerpoints[grain](i) < _bottom_left(i))
122  _centerpoints[grain](i) = _bottom_left(i);
123 
124  if (_columnar_3D && _dim == 3)
125  _centerpoints[grain](2) = _bottom_left(2) + _range(2) * 0.5;
126  }
127 
128  buildSearchTree();
129 }
virtual Real getMaxInDimension(unsigned int component) const
virtual Real getMinInDimension(unsigned int component) const
MooseRandom _random
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static InputParameters validParams()
void seed(std::size_t i, unsigned int seed)
bool isTranslatedPeriodic(unsigned int nonlinear_var_num, unsigned int component) const
static constexpr std::size_t dim
std::vector< Point > _centerpoints
const Real _perturbation_percent
virtual void precomputeGrainStructure()
This callback is triggered after the object is initialized and may be optionally overridden to do pre...
PolycrystalHex(const InputParameters &parameters)
const unsigned int _dim
mesh dimension
std::vector< MooseVariable * > _vars
The vector of coupled in variables cast to MooseVariable.
T round(T x)
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent&#39;s method.
Definition: BrentsMethod.C:61
PolycrystalHex creates a hexagonal polycrystal initial condition.
static InputParameters validParams()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
registerMooseObject("PhaseFieldApp", PolycrystalHex)
const THREAD_ID _tid
IntRange< T > make_range(T beg, T end)
const Real _x_offset
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Real rand(std::size_t i)
MooseMesh & _mesh
A reference to the mesh.
MooseUnits pow(const MooseUnits &, int)
static const std::string k
Definition: NS.h:124
unsigned int _grain_num
The number of grains to create.