This function rotates a set of three Bunge Euler angles into the standard Stereographic triangle, interpolates the RGB color value based on a user selected reference sample direction, and outputs an integer value representing the RGB tuplet usable for plotting inverse pole figure colored grain maps.
The program can accommodate any of the seven crystal systems.
Inputs: 1) Reference sample direction (sd) input as an integer between 1 and 3. Options are [100], [010], and [001] with [001] being the most common choice found in the literature. Input "1" to select [100], "2" to select [010], and "3" to select the [001] sample direction. 2) Set of three Euler angles (phi1, PHI, phi2) in the Bunge notation (must be in radians) 3) Phase number "phase" used to assign black color values to voids (phase = 0) 4) Integer value of crystal class as defined by OIM Software: "43" for cubic "62" for hexagonal "42" for tetragonal "32" for trigonal "22" for orthorhombic "2" for monoclinic "1" for triclinic "0" for unindexed points (bad data point)
50 const Real pi_x2 = 2.0 *
pi;
54 unsigned int index = 0;
55 unsigned int nsym = 1;
69 unsigned int ref_dir[3] = {0, 0, 0};
70 Real g[3][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
71 Real hkl[3] = {0.0, 0.0, 0.0};
72 Real S[3][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
73 const Real(*SymOps)[3][3];
100 const Real SymOpsCubic[24][3][3] = {
101 {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, {{0, 0, 1}, {1, 0, 0}, {0, 1, 0}},
102 {{0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, {{0, -1, 0}, {0, 0, 1}, {-1, 0, 0}},
103 {{0, -1, 0}, {0, 0, -1}, {1, 0, 0}}, {{0, 1, 0}, {0, 0, -1}, {-1, 0, 0}},
104 {{0, 0, -1}, {1, 0, 0}, {0, -1, 0}}, {{0, 0, -1}, {-1, 0, 0}, {0, 1, 0}},
105 {{0, 0, 1}, {-1, 0, 0}, {0, -1, 0}}, {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}},
106 {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}}, {{1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
107 {{0, 0, -1}, {0, -1, 0}, {-1, 0, 0}}, {{0, 0, 1}, {0, -1, 0}, {1, 0, 0}},
108 {{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}}, {{0, 0, -1}, {0, 1, 0}, {1, 0, 0}},
109 {{-1, 0, 0}, {0, 0, -1}, {0, -1, 0}}, {{1, 0, 0}, {0, 0, -1}, {0, 1, 0}},
110 {{1, 0, 0}, {0, 0, 1}, {0, -1, 0}}, {{-1, 0, 0}, {0, 0, 1}, {0, 1, 0}},
111 {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}, {{0, 1, 0}, {-1, 0, 0}, {0, 0, -1}},
112 {{0, 1, 0}, {1, 0, 0}, {0, 0, -1}}, {{0, -1, 0}, {1, 0, 0}, {0, 0, 1}}};
114 const Real SymOpsHexagonal[12][3][3] = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
115 {{-0.5,
a, 0}, {-
a, -0.5, 0}, {0, 0, 1}},
116 {{-0.5, -
a, 0}, {
a, -0.5, 0}, {0, 0, 1}},
117 {{0.5,
a, 0}, {-
a, 0.5, 0}, {0, 0, 1}},
118 {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}},
119 {{0.5, -
a, 0}, {
a, 0.5, 0}, {0, 0, 1}},
120 {{-0.5, -
a, 0}, {-
a, 0.5, 0}, {0, 0, -1}},
121 {{1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
122 {{-0.5,
a, 0}, {
a, 0.5, 0}, {0, 0, -1}},
123 {{0.5,
a, 0}, {
a, -0.5, 0}, {0, 0, -1}},
124 {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}},
125 {{0.5, -
a, 0}, {-
a, -0.5, 0}, {0, 0, -1}}};
127 const Real SymOpsTetragonal[8][3][3] = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
128 {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}},
129 {{1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
130 {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}},
131 {{0, 1, 0}, {-1, 0, 0}, {0, 0, 1}},
132 {{0, -1, 0}, {1, 0, 0}, {0, 0, 1}},
133 {{0, 1, 0}, {1, 0, 0}, {0, 0, -1}},
134 {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}};
136 const Real SymOpsTrigonal[6][3][3] = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
137 {{-0.5,
a, 0}, {-
a, -0.5, 0}, {0, 0, 1}},
138 {{-0.5, -
a, 0}, {
a, -0.5, 0}, {0, 0, 1}},
139 {{0.5,
a, 0}, {
a, -0.5, 0}, {0, 0, -1}},
140 {{-1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
141 {{0.5, -
a, 0}, {-
a, -0.5, 0}, {0, 0, -1}}};
143 const Real SymOpsOrthorhombic[4][3][3] = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
144 {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}},
145 {{1, 0, 0}, {0, -1, 0}, {0, 0, 1}},
146 {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}}};
148 const Real SymOpsMonoclinic[2][3][3] = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
149 {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}};
151 const Real SymOpsTriclinic[1][3][3] = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
158 SymOps = SymOpsCubic;
159 eta_min = 0 * (
pi / 180);
160 eta_max = 45 * (
pi / 180);
161 chi_min = 0 * (
pi / 180);
162 chi_max = std::acos(
std::sqrt(1.0 / (2.0 + (Utility::pow<2>(std::tan(eta_max))))));
169 SymOps = SymOpsHexagonal;
170 eta_min = 0 * (
pi / 180);
171 eta_max = 30 * (
pi / 180);
172 chi_min = 0 * (
pi / 180);
180 SymOps = SymOpsTetragonal;
181 eta_min = 0 * (
pi / 180);
182 eta_max = 45 * (
pi / 180);
183 chi_min = 0 * (
pi / 180);
191 SymOps = SymOpsTrigonal;
192 eta_min = 0 * (
pi / 180);
193 eta_max = 60 * (
pi / 180);
194 chi_min = 0 * (
pi / 180);
202 SymOps = SymOpsOrthorhombic;
203 eta_min = 0 * (
pi / 180);
204 eta_max = 90 * (
pi / 180);
205 chi_min = 0 * (
pi / 180);
213 SymOps = SymOpsMonoclinic;
214 eta_min = 0 * (
pi / 180);
215 eta_max = 180 * (
pi / 180);
216 chi_min = 0 * (
pi / 180);
224 SymOps = SymOpsTriclinic;
225 eta_min = 0 * (
pi / 180);
226 eta_max = 360 * (
pi / 180);
227 chi_min = 0 * (
pi / 180);
239 if (nsym == 0 || phase == 0)
243 else if (phi1 > pi_x2 || PHI > pi || phi2 > pi_x2)
250 g[0][0] = std::cos(phi1) * std::cos(phi2) - std::sin(phi1) * std::cos(PHI) * std::sin(phi2);
251 g[0][1] = std::sin(phi1) * std::cos(phi2) + std::cos(phi1) * std::cos(PHI) * std::sin(phi2);
252 g[0][2] = std::sin(phi2) * std::sin(PHI);
253 g[1][0] = -std::cos(phi1) * std::sin(phi2) - std::sin(phi1) * std::cos(PHI) * std::cos(phi2);
254 g[1][1] = -std::sin(phi1) * std::sin(phi2) + std::cos(phi1) * std::cos(PHI) * std::cos(phi2);
255 g[1][2] = std::cos(phi2) * std::sin(PHI);
256 g[2][0] = std::sin(phi1) * std::sin(PHI);
257 g[2][1] = -std::cos(phi1) * std::sin(PHI);
258 g[2][2] = std::cos(PHI);
265 for (
unsigned int i = 0; i < 3; ++i)
266 for (
unsigned int j = 0;
j < 3; ++
j)
269 for (
unsigned int k = 0;
k < 3; ++
k)
270 S[i][
j] += SymOps[index][i][
k] * g[
k][
j];
274 for (
unsigned int i = 0; i < 3; ++i)
277 for (
unsigned int j = 0;
j < 3; ++
j)
278 hkl[i] +=
S[i][
j] * ref_dir[
j];
282 eta =
std::abs(std::atan2(hkl[1], hkl[0]));
286 if (eta >= eta_min && eta < eta_max && chi >= chi_min && chi < chi_max)
294 mooseAssert(index != nsym,
"Euler2RGB failed to map the supplied Euler angle into the SST!");
299 chi_max2 = std::acos(
std::sqrt(1.0 / (2.0 + (Utility::pow<2>(std::tan(eta))))));
304 red =
std::abs(1.0 - (chi / chi_max2));
305 blue =
std::abs((eta - eta_min) / (eta_max - eta_min));
308 blue = blue * (chi / chi_max2);
309 green = green * (chi / chi_max2);
312 mooseAssert(red >= 0 || green >= 0 || blue >= 0,
"RGB component values must be positive!");
319 maxRGB = std::max({RGB(0), RGB(1), RGB(2)});
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
static const std::string S
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k