https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComputeGBMisorientationType.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 "SolutionUserObject.h"
12
14
17{
19 params.addClassDescription("Calculate types of grain boundaries in a polycrystalline sample");
20 params.addRequiredParam<UserObjectName>("grain_tracker",
21 "The GrainTracker UserObject to get values from.");
22 params.addRequiredParam<UserObjectName>("ebsd_reader", "The EBSDReader GeneralUserObject");
24 "v", "var_name_base", "op_num", "Array of coupled variables");
25 params.addParam<Real>("angle_threshold", 15, "Max LAGB Misorientation angle");
26 return params;
27}
28
30 : Material(parameters),
31 _grain_tracker(getUserObject<GrainTracker>("grain_tracker")),
32 _ebsd_reader(getUserObject<EBSDReader>("ebsd_reader")),
33 _op_num(coupledComponents("v")),
34 _vals(coupledValues("v")),
35 _angle_threshold(getParam<Real>("angle_threshold")),
36 _gb_type(declareADProperty<Real>("gb_type"))
37{
39}
40
41void
43{
44 // Find out the number of boundary unique_id and save them
45 _gb_pairs.clear();
46 _gb_op_pairs.clear();
47
48 const auto & op_to_grains = _grain_tracker.getVarToFeatureVector(_current_elem->id());
49 for (auto i : index_range(op_to_grains))
50 {
51 if (op_to_grains[i] == FeatureFloodCount::invalid_id)
52 continue;
53
54 _gb_pairs.push_back(_ebsd_reader.getFeatureID(op_to_grains[i]));
55 _gb_op_pairs.push_back((*_vals[i])[_qp]);
56 }
57
58 // Compute GB type by the number of id
59 _gb_type[_qp] = 0;
60 switch (_gb_pairs.size())
61 {
62 case 0:
63 break;
64 case 1:
65 break;
66 case 2:
67 // get type by Misorientation angle
68 _gb_type[_qp] =
70 : 2);
71 break;
72 default:
73 // get continuous type at triple junction
75 }
76}
77
78// Function to output total line number of Misorientation angle file
79unsigned int
84
85// Function to output specific line number in Misorientation angle file
86unsigned int
87ComputeGBMisorientationType::getLineNum(unsigned int grain_i, unsigned int grain_j)
88{
89 if (grain_i > grain_j)
90 return grain_j + (grain_i - 1) * grain_i / 2;
91 else
92 return grain_i + (grain_j - 1) * grain_j / 2;
93}
94
95// Function to calculate the GB type in Triple junction
96Real
98{
99 unsigned int lagb_num = 0;
100 unsigned int hagb_num = 0;
101 Real ratio_base = 0.0;
102 Real ratio_lagb = 0.0;
103 for (unsigned int i = 1; i < _gb_pairs.size(); ++i)
104 {
105 for (unsigned int j = 0; j < i; ++j)
106 {
107 ratio_base += (_gb_op_pairs[i] * _gb_op_pairs[i] * _gb_op_pairs[j] * _gb_op_pairs[j]);
109 {
110 lagb_num += 1;
111 ratio_lagb += (_gb_op_pairs[i] * _gb_op_pairs[i] * _gb_op_pairs[j] * _gb_op_pairs[j]);
112 }
113 else
114 hagb_num += 1;
115 }
116 }
117 if (lagb_num == 0)
118 return 2;
119 else if (hagb_num == 0)
120 return 1;
121 else
122 return 2 - ratio_lagb / ratio_base;
123}
124
125// Function to convert symmetry matrix to quaternion form
126void
128 Eigen::Quaternion<Real> & q)
129{
130 double q4 = 0;
131 if ((1 + O[0][0] + O[1][1] + O[2][2]) > 0)
132 {
133 q4 = sqrt(1 + O[0][0] + O[1][1] + O[2][2]) / 2;
134 q.w() = q4;
135 q.x() = (O[2][1] - O[1][2]) / (4 * q4);
136 q.y() = (O[0][2] - O[2][0]) / (4 * q4);
137 q.z() = (O[1][0] - O[0][1]) / (4 * q4);
138 }
139 else if ((1 + O[0][0] - O[1][1] - O[2][2]) > 0)
140 {
141 q4 = sqrt(1 + O[0][0] - O[1][1] - O[2][2]) / 2;
142 q.w() = (O[2][1] - O[1][2]) / (4 * q4);
143 q.x() = q4;
144 q.y() = (O[1][0] + O[0][1]) / (4 * q4);
145 q.z() = (O[0][2] + O[2][0]) / (4 * q4);
146 }
147 else if ((1 - O[0][0] + O[1][1] - O[2][2]) > 0)
148 {
149 q4 = sqrt(1 - O[0][0] + O[1][1] - O[2][2]) / 2;
150 q.w() = (O[0][2] - O[2][0]) / (4 * q4);
151 q.x() = (O[1][0] + O[0][1]) / (4 * q4);
152 q.y() = q4;
153 q.z() = (O[2][1] + O[1][2]) / (4 * q4);
154 }
155 else if ((1 - O[0][0] - O[1][1] + O[2][2]) > 0)
156 {
157 q4 = sqrt(1 - O[0][0] - O[1][1] + O[2][2]) / 2;
158 q.w() = (O[1][0] - O[0][1]) / (4 * q4);
159 q.x() = (O[0][2] + O[2][0]) / (4 * q4);
160 q.y() = (O[2][1] + O[1][2]) / (4 * q4);
161 q.z() = q4;
162 }
163}
164
165// Function to define the symmetry operator
166void
168{
169 // grow by number of symmetric operators
170 _sym_quat.resize(_o_sym);
171
172 // cubic symmetry
173 double sym_rotation[24][3][3] = {
174 {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, {{1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
175 {{1, 0, 0}, {0, 0, -1}, {0, 1, 0}}, {{1, 0, 0}, {0, 0, 1}, {0, -1, 0}},
176 {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}, {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}},
177 {{-1, 0, 0}, {0, 0, -1}, {0, -1, 0}}, {{-1, 0, 0}, {0, 0, 1}, {0, 1, 0}},
178 {{0, 1, 0}, {-1, 0, 0}, {0, 0, 1}}, {{0, 1, 0}, {0, 0, -1}, {-1, 0, 0}},
179 {{0, 1, 0}, {1, 0, 0}, {0, 0, -1}}, {{0, 1, 0}, {0, 0, 1}, {1, 0, 0}},
180 {{0, -1, 0}, {1, 0, 0}, {0, 0, 1}}, {{0, -1, 0}, {0, 0, -1}, {1, 0, 0}},
181 {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}, {{0, -1, 0}, {0, 0, 1}, {-1, 0, 0}},
182 {{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}}, {{0, 0, 1}, {1, 0, 0}, {0, 1, 0}},
183 {{0, 0, 1}, {0, -1, 0}, {1, 0, 0}}, {{0, 0, 1}, {-1, 0, 0}, {0, -1, 0}},
184 {{0, 0, -1}, {0, 1, 0}, {1, 0, 0}}, {{0, 0, -1}, {-1, 0, 0}, {0, 1, 0}},
185 {{0, 0, -1}, {0, -1, 0}, {-1, 0, 0}}, {{0, 0, -1}, {1, 0, 0}, {0, -1, 0}}};
186
187 // initialize global operator
188 for (int o = 0; o < _o_sym; o++)
189 rotationSymmetryToQuaternion(sym_rotation[o], _sym_quat[o]);
190}
191
192// Function to return the misorientation of two quaternions
193double
195 const Eigen::Quaternion<Real> qj)
196{
197 Real miso0, misom = 2.0 * libMesh::pi;
198 Eigen::Quaternion<Real> q, qib, qjb, qmin;
199 qmin.w() = 0;
200 qmin.x() = 0;
201 qmin.y() = 0;
202 qmin.z() = 0;
203
204 for (int o1 = 0; o1 < _o_sym; o1++)
205 {
206 for (int o2 = 0; o2 < _o_sym; o2++)
207 {
208 qib = _sym_quat[o1] * qi;
209 qjb = _sym_quat[o2] * qj;
210
211 // j-grain conjugate quaternion
212 qjb.x() = -qjb.x();
213 qjb.y() = -qjb.y();
214 qjb.z() = -qjb.z();
215 q = qib * qjb;
216 miso0 = round(2 * std::acos(q.w()) * 1e5) / 1e5;
217
218 if (miso0 > libMesh::pi)
219 miso0 = miso0 - 2 * libMesh::pi;
220 if (std::abs(miso0) < misom)
221 {
222 misom = std::abs(miso0);
223 qmin = q;
224 }
225 }
226 }
227
228 miso0 = 2 * std::acos(qmin.w());
229 if (miso0 > libMesh::pi)
230 miso0 = miso0 - 2 * libMesh::pi;
231
232 return std::abs(miso0);
233}
234
235// Get the Misorientation angle
236void
238{
239 // Initialize symmetry operator as quaternion vectors
241 // Initialize parameters to calculate misorientation
242 const auto grain_num = _ebsd_reader.getGrainNum();
243 _euler_angle.resize(grain_num);
244 _quat_angle.resize(grain_num);
245
246 // Get Euler Angle of Orientation
247 for (const auto i : make_range(grain_num))
248 {
249 auto grain_id = _ebsd_reader.getFeatureID(i);
250 mooseAssert(grain_id < grain_num, "Feature ids cannot exceed max grain number");
252 _quat_angle[grain_id] = _euler_angle[grain_id].toQuaternion();
253 }
254
255 for (const auto j : make_range(std::make_unsigned_t<int>(1), grain_num))
256 {
257 for (const auto i : make_range(j))
258 {
260 _misorientation_angles.push_back(theta / libMesh::pi * 180);
261 }
262 }
263}
registerMooseObject("PhaseFieldApp", ComputeGBMisorientationType)
Visualize the location of grain boundaries in a polycrystalline simulation.
virtual unsigned int getTotalLineNum() const
Function to obtain the total line number in misorientation angle file.
const std::vector< const VariableValue * > _vals
void defineSymmetryOperator()
Function to define the symmetry operator.
const Real _angle_threshold
the max value of LAGB
void getMisorientationAngles()
Get the Misorientation angle.
std::vector< Eigen::Quaternion< Real > > _sym_quat
The parameters to calculate the misorientation.
virtual Real getTripleJunctionType()
Function to get the GB type for triple junctions.
double getMisorientationFromQuaternion(const Eigen::Quaternion< Real > qi, const Eigen::Quaternion< Real > qj)
Function to return the misorientation of two quaternions.
ComputeGBMisorientationType(const InputParameters &parameters)
virtual void computeQpProperties() override
Necessary override. This is where the property values are set.
const GrainTracker & _grain_tracker
Grain tracker object.
ADMaterialProperty< Real > & _gb_type
precalculated element value
void rotationSymmetryToQuaternion(const double O[3][3], Eigen::Quaternion< Real > &q)
Function to convert symmetry matrix to quaternion form.
std::vector< EulerAngles > _euler_angle
std::vector< unsigned int > _gb_pairs
parameters to store the EBSD id and corresponding value on GB
virtual unsigned int getLineNum(unsigned int grain_i, unsigned int grain_j)
Function to obtain line number for a given grain pair.
const EBSDReader & _ebsd_reader
EBSD reader user object.
std::vector< double > _misorientation_angles
Parameters to calculate the Misorientation angle file.
std::vector< Eigen::Quaternion< Real > > _quat_angle
A GeneralUserObject that reads an EBSD file and stores the centroid data in a data structure which in...
Definition EBSDReader.h:32
unsigned int getFeatureID(unsigned int phase, unsigned int local_id) const
Return the EBSD feature id for a given phase and phase (local) grain number.
Definition EBSDReader.h:81
virtual const EulerAngles & getEulerAngles(unsigned int) const
EulerAngleProvider interface implementation to fetch a triplet of Euler angles.
Definition EBSDReader.C:362
virtual unsigned int getGrainNum() const
Return the total number of grains.
Definition EBSDReader.C:374
Eigen::Quaternion< Real > toQuaternion()
Definition EulerAngles.C:55
static const unsigned int invalid_id
virtual const std::vector< unsigned int > & getVarToFeatureVector(dof_id_type elem_id) const override
Returns a list of active unique feature ids for a particular element.
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 addRequiredCoupledVarWithAutoBuild(const std::string &name, const std::string &base_name, const std::string &num_name, const std::string &doc_string)
unsigned int _qp
static InputParameters validParams()
const Elem *const & _current_elem
const Real pi