https://mooseframework.inl.gov
TricrystalTripleJunctionIC.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 
11 #include "MooseRandom.h"
12 #include "MooseMesh.h"
13 #include "MathUtils.h"
14 #include "FEProblemBase.h"
15 
17 
20 {
22  params.addClassDescription("Tricrystal with a triple junction");
23  params.addRequiredParam<unsigned int>("op_num", "Number of grain order parameters");
24  params.addRequiredParam<unsigned int>("op_index", "Index for the current grain order parameter");
25  params.addParam<Real>("theta1", 135.0, "Angle of first grain at triple junction in degrees");
26  params.addParam<Real>("theta2", 135.0, "Angle of second grain at triple junction in degrees");
27  params.addParam<Point>(
28  "junction",
29  "The point where the triple junction is located. Default is the center of the mesh");
30  return params;
31 }
32 
34  : InitialCondition(parameters),
35  _mesh(_fe_problem.mesh()),
36  _op_num(getParam<unsigned int>("op_num")),
37  _op_index(getParam<unsigned int>("op_index")),
38  _theta1(getParam<Real>("theta1")),
39  _theta2(getParam<Real>("theta2"))
40 {
41  if (_op_num != 3)
42  paramError("op_num", "Tricrystal ICs must have op_num = 3");
43 
44  if (_theta1 + _theta2 >= 360.0)
45  paramError("theta1", "Sum of the angles theta1 and theta2 must total less than 360 degrees");
46 
47  // Default junction point is the center
48  if (!parameters.isParamValid("junction"))
49  {
50  for (const auto i : make_range(Moose::dim))
52  }
53  else
54  _junction = getParam<Point>("junction");
55 
56  // Make sure that _junction is in the domain
57  for (const auto i : make_range(Moose::dim))
58  {
60  paramError("junction", "Triple junction out of bounds");
61  }
62 
63  // Convert the angles to radians
64  _theta1 = _theta1 * libMesh::pi / 180.0;
65  _theta2 = _theta2 * libMesh::pi / 180.0;
66 
67  // Change the first angle to be measured from the +x axis
68  _theta1 = 3.0 * libMesh::pi / 2.0 - _theta1;
69 
70  // Change the third angle to be measured from the +x axis
71  _theta2 = _theta2 - libMesh::pi / 2.0;
72 
73  // Only compute the tangent once for computational efficiency
74  _tan_theta1 = std::tan(_theta1);
75  _tan_theta2 = std::tan(_theta2);
76 }
77 
78 Real
80 {
81  /*
82  * This does all the work to create a triple junction that looks like the letter Y
83  */
84  Real dist_left; // The distance from the point to the line specified by _theta1
85  Real dist_right; // The distance from the point to the line specified by _theta2
86 
87  // Check if the point is above or below the left-most line
88  // Function to use is y = _junction(1) + (x - _junction(0)) * std::tan(libMesh::pi/2.0 - _theta1)
89  if (_theta1 == 0) // Handle tan(0) case
90  dist_left = p(1) - _junction(1);
91  else
92  dist_left = p(1) - (_junction(1) + (p(0) - _junction(0)) * _tan_theta1);
93 
94  // Check if the point is above or below the right-most line
95  // Function to use is y = _junction(1) + (x - _junction(0))*std::tan(-(libMesh::pi/2.0 - _theta2))
96  if (_theta2 == 0) // Handle tan(0) classes
97  dist_right = p(1) - _junction(1);
98  else
99  dist_right = p(1) - (_junction(1) + (p(0) - _junction(0)) * _tan_theta2);
100 
101  // Check if the point is to the left or right of the middle line
102  Real dist_center = p(0) - _junction(0); // Negative value if the point is to the left
103 
104  if (_tan_theta1 > 0 && _theta1 <= libMesh::pi / 2.0) // Case for large left grain
105  {
106  /*
107  * There's a lot going on here. The first statement tells MOOSE to check and
108  * see if the current point is above the line defined by the first angle, only
109  * if it is past the center line. All other points to the left of the center
110  * line are going to be part of the 1st grain (_op_index == 1)
111  * The second statement defines the second grain by the line defined by _theta2
112  * and marks everything below that line, and to the right of the center line.
113  * The third statement takes care of everything in between.
114  */
115  if ((((dist_left >= 0 && dist_center >= 0) || (dist_center < 0)) && _op_index == 1) ||
116  (dist_right <= 0 && dist_center > 0 && _op_index == 2) ||
117  (dist_left < 0 && dist_center > 0 && dist_right > 0 && _op_index == 3))
118  return 1.0;
119  else
120  return 0.0;
121  }
122 
123  // This does a similar thing as the above case, but switches it for the right and left grains
124  else if (_tan_theta2 < 0 && _theta2 >= libMesh::pi / 2.0) // Case for large right grain
125  {
126  if ((dist_left <= 0 && dist_center <= 0 && _op_index == 1) ||
127  (((dist_right >= 0 && dist_center <= 0) || (dist_center > 0)) && _op_index == 2) ||
128  (dist_left > 0 && dist_right < 0 && dist_center < 0 && _op_index == 3))
129  return 1.0;
130  else
131  return 0.0;
132  }
133 
134  else // all other cases
135  {
136  if ((dist_left <= 0 && dist_center <= 0 && _op_index == 1) || // First grain
137  (dist_right <= 0 && dist_center > 0 && _op_index == 2) || // Second grain
138  (((dist_left > 0 && dist_center < 0) || (dist_right > 0 && dist_center >= 0)) &&
139  _op_index == 3)) // Third grain
140  return 1.0;
141  else
142  return 0.0;
143  }
144 }
virtual Real getMaxInDimension(unsigned int component) const
virtual Real getMinInDimension(unsigned int component) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const unsigned int _op_num
Number of order parameters.
virtual Real value(const Point &p)
TricrystalTripleJunctionIC creates a 3-grain structure with a triple junction centered at _junction a...
MeshBase & mesh
static constexpr std::size_t dim
static InputParameters validParams()
void addRequiredParam(const std::string &name, const std::string &doc_string)
static InputParameters validParams()
Real _theta2
Angle of third grain at triple junction in radians.
Real _tan_theta1
tangent of the first angle after a shift of pi/2
Real _theta1
Angle of first grain at triple junction in radians.
void paramError(const std::string &param, Args... args) const
Real _tan_theta2
tangent of the second angle after a shift of pi/2
registerMooseObject("PhaseFieldApp", TricrystalTripleJunctionIC)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
void addClassDescription(const std::string &doc_string)
const InputParameters & parameters() const
Point _junction
Point where the triple junction occurs.
void ErrorVector unsigned int
TricrystalTripleJunctionIC(const InputParameters &parameters)
const Real pi
bool isParamValid(const std::string &name) const