https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
78Real
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}
const Real p
registerMooseObject("PhaseFieldApp", TricrystalTripleJunctionIC)
void ErrorVector unsigned int
static InputParameters validParams()
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)
bool isParamValid(const std::string &name) const
const InputParameters & parameters() const
void paramError(const std::string &param, Args... args) const
virtual Real getMaxInDimension(unsigned int component) const
virtual Real getMinInDimension(unsigned int component) const
TricrystalTripleJunctionIC creates a 3-grain structure with a triple junction centered at _junction a...
virtual Real value(const Point &p)
const unsigned int _op_num
Number of order parameters.
static InputParameters validParams()
Real _theta1
Angle of first grain at triple junction in radians.
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
Point _junction
Point where the triple junction occurs.
TricrystalTripleJunctionIC(const InputParameters &parameters)
Real _tan_theta2
tangent of the second angle after a shift of pi/2
MeshBase & mesh
static constexpr std::size_t dim
const Real pi