Line data Source code
1 : #ifndef SET_MATRIX4_MAJORMINOR_H
2 : #define SET_MATRIX4_MAJORMINOR_H
3 :
4 : #include "Set.H"
5 : #include "Base.H"
6 : #include <math.h>
7 : #include "Matrix3.H"
8 : #include "Matrix4.H"
9 :
10 : namespace Set
11 : {
12 : /// \brief Data structure for a 4th order 3D tensor with major and minor symmetry
13 : ///
14 : /// 2D version. See full explanation below.
15 : ///
16 : template<>
17 : class Matrix4<2,Sym::MajorMinor>
18 : {
19 : Scalar data[6] = {NAN,NAN,NAN,NAN,NAN,NAN};
20 :
21 : public:
22 1373 : AMREX_GPU_HOST_DEVICE Matrix4() {};
23 : //Matrix4(const Matrix4<2,Sym::MajorMinor> &in)
24 : //{
25 : // for (int i = 0; i < 6; i++) data[i] = in.data[i];
26 : //}
27 : AMREX_FORCE_INLINE
28 : const Scalar & operator () (const int i, const int j, const int k, const int l) const
29 : {
30 1600 : int uid = i + 2*j + 4*k + 8*l;
31 1600 : if (uid==0 ) return data[0]; // [0000]
32 1500 : else if (uid==8 || uid==4 || uid==2 || uid==1 ) return data[1]; // [0001] [0010] [0100] [1000]
33 1100 : else if (uid==12 || uid==3 ) return data[2]; // [0011] [1100]
34 900 : else if (uid==10 || uid==6 || uid==9 || uid==5 ) return data[3]; // [0101] [1001] [0110] [1010]
35 500 : else if (uid==14 || uid==13 || uid==11 || uid==7 ) return data[4]; // [0111] [1011] [1101] [1110]
36 100 : else if (uid==15 ) return data[5]; // [1111]
37 0 : else Util::Abort(INFO,"Index out of range");
38 0 : return Set::Garbage;
39 : }
40 : AMREX_FORCE_INLINE
41 : Scalar & operator () (const int i, const int j, const int k, const int l)
42 : {
43 1537696 : int uid = i + 2*j + 4*k + 8*l;
44 190723 : if (uid==0 ) return data[0]; // [0000]
45 1461390 : else if (uid==8 || uid==4 || uid==2 || uid==1 ) return data[1]; // [0001] [0010] [0100] [1000]
46 1071686 : else if (uid==12 || uid==3 ) return data[2]; // [0011] [1100]
47 876834 : else if (uid==10 || uid==6 || uid==9 || uid==5 ) return data[3]; // [0101] [1001] [0110] [1010]
48 487130 : else if (uid==14 || uid==13 || uid==11 || uid==7 ) return data[4]; // [0111] [1011] [1101] [1110]
49 97426 : else if (uid==15 ) return data[5]; // [1111]
50 0 : else Util::Abort(INFO,"Index out of range");
51 0 : return Set::Garbage;
52 : }
53 : void Print (std::ostream& os)
54 : {
55 : os.precision(4);
56 : for (int k = 0; k < 2; k++)
57 : {
58 : for (int i = -1; i < 3; i++)
59 : {
60 : for (int l = 0; l < 2; l++)
61 : {
62 : if (i==-1) os << "┌ ┐ ";
63 : else if (i == 2) os << "└ ┘ ";
64 : else
65 : {
66 : os << "│ ";
67 : for (int j = 0; j < 2; j++)
68 : {
69 : const Set::Scalar &val = (*this)(i,j,k,l);
70 : os << std::scientific << std::setw(11) << val ; //(fabs(val)>1E-10 ? val : 0);
71 : os << " ";
72 : }
73 : os << "│ ";
74 : }
75 : }
76 : os<<std::endl;
77 : }
78 : }
79 : }
80 :
81 : Set::Scalar Norm()
82 : {
83 : return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3] + data[4]*data[4] + data[5]*data[5]);
84 : }
85 : bool contains_nan() const
86 : {
87 : if (std::isnan(data[ 0])) return true;
88 : if (std::isnan(data[ 1])) return true;
89 : if (std::isnan(data[ 2])) return true;
90 : if (std::isnan(data[ 3])) return true;
91 : if (std::isnan(data[ 4])) return true;
92 : if (std::isnan(data[ 5])) return true;
93 : return false;
94 : }
95 :
96 0 : AMREX_GPU_HOST_DEVICE void operator += (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] += a.data[i];}
97 : AMREX_GPU_HOST_DEVICE void operator -= (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] -= a.data[i];}
98 : AMREX_GPU_HOST_DEVICE void operator *= (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] *= a.data[i];}
99 : AMREX_GPU_HOST_DEVICE void operator /= (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] /= a.data[i];}
100 : AMREX_GPU_HOST_DEVICE void operator *= (Set::Scalar alpha) {for (int i = 0; i < 6; i++) data[i] *= alpha;}
101 : AMREX_GPU_HOST_DEVICE void operator /= (Set::Scalar alpha) {for (int i = 0; i < 6; i++) data[i] /= alpha;}
102 :
103 : static Matrix4<2,Sym::MajorMinor> Increment()
104 : {
105 : Matrix4<2,Sym::MajorMinor> ret;
106 : for (int i = 0 ; i < 6; i++) ret.data[i] = (Set::Scalar)i;
107 : return ret;
108 : }
109 1 : void Randomize()
110 : {
111 7 : for (int i = 0 ; i < 6; i++) data[i] = (Util::Random());
112 1 : }
113 1 : static Matrix4<2,Sym::MajorMinor> Random()
114 : {
115 1 : Matrix4<2,Sym::MajorMinor> ret;
116 1 : ret.Randomize();
117 1 : return ret;
118 : }
119 94 : static Matrix4<2,Sym::MajorMinor> Zero()
120 : {
121 94 : Matrix4<2,Sym::MajorMinor> ret;
122 658 : for (int i = 0 ; i < 6; i++) ret.data[i] = 0.0;
123 94 : return ret;
124 : }
125 1104 : static Matrix4<2,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44,
126 : Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
127 : {
128 1104 : Set::Matrix4<2,Sym::MajorMinor> ret;
129 : Set::Scalar Ctmp[3][3][3][3];
130 :
131 4416 : for(int i = 0; i < 3; i++)
132 13248 : for(int j = 0; j < 3; j++)
133 39744 : for(int k = 0; k < 3; k++)
134 119232 : for(int l = 0; l < 3; l++)
135 : {
136 89424 : if(i == j && j == k && k == l) Ctmp[i][j][k][l] = C11;
137 86112 : else if (i==k && j==l) Ctmp[i][j][k][l] = C44;
138 79488 : else if (i==j && k==l) Ctmp[i][j][k][l] = C12;
139 72864 : else Ctmp[i][j][k][l] = 0.0;
140 : }
141 3312 : for(int p = 0; p < 2; p++)
142 6624 : for(int q = 0; q < 2; q++)
143 13248 : for(int s = 0; s < 2; s++)
144 26496 : for(int t = 0; t < 2; t++)
145 : {
146 17664 : ret(p,q,s,t) = 0.0;
147 70656 : for(int i = 0; i < 3; i++)
148 211968 : for(int j = 0; j < 3; j++)
149 635904 : for(int k = 0; k < 3; k++)
150 1907712 : for(int l = 0; l < 3; l++)
151 2861568 : ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
152 : }
153 2208 : return ret;
154 : }
155 44 : static Matrix4<2,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44,
156 : Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
157 : {
158 44 : Eigen::Matrix3d R;
159 44 : R = Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
160 88 : Eigen::AngleAxisd(Phi, Eigen::Vector3d::UnitZ()) *
161 88 : Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
162 44 : return Matrix4<2,Sym::MajorMinor>::Cubic(C11,C12,C44,R);
163 : }
164 1060 : static Matrix4<2,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44,
165 : Set::Quaternion q)
166 : {
167 1060 : Eigen::Matrix3d R = q.normalized().toRotationMatrix();
168 1060 : return Cubic(C11,C12,C44,R);
169 : }
170 :
171 :
172 22 : static Matrix4<2,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
173 : {
174 22 : Set::Matrix4<2,Sym::MajorMinor> ret;
175 22 : Set::Scalar Ctmp[3][3][3][3] = {{{{0.0}}}};
176 :
177 88 : for(int i = 0; i < 3; i++)
178 264 : for(int j = 0; j < 3; j++)
179 792 : for(int k = 0; k < 3; k++)
180 2376 : for(int l = 0; l < 3; l++)
181 : {
182 1782 : if(i==j && j==k && k==l)
183 : {
184 66 : if (i < 2) Ctmp[i][j][k][l] = C11;
185 22 : else Ctmp[i][j][k][l] = C33;
186 : }
187 1716 : else if(i==j && k==l)
188 : {
189 132 : if (i<2 && k<2 && i!=k) Ctmp[i][j][k][l] = C12;
190 88 : else if ((i<2 && k==2) || (i==2 && k<2)) Ctmp[i][j][k][l] = C13;
191 : }
192 1584 : else if((i==k && j==l) && (i!=j))
193 : {
194 132 : Ctmp[i][j][k][l] = C44;
195 : }
196 : else
197 : {
198 1452 : Ctmp[i][j][k][l] = 0.0;
199 : }
200 : }
201 :
202 : // C66 = 0.5*(C11 - C12)
203 22 : Ctmp[0][1][0][1] = 0.5 * (C11 - C12);
204 22 : Ctmp[1][0][1][0] = 0.5 * (C11 - C12);
205 :
206 66 : for(int p = 0; p < 2; p++)
207 132 : for(int q = 0; q < 2; q++)
208 264 : for(int s = 0; s < 2; s++)
209 528 : for(int t = 0; t < 2; t++)
210 : {
211 352 : ret(p,q,s,t) = 0.0;
212 1408 : for(int i = 0; i < 3; i++)
213 4224 : for(int j = 0; j < 3; j++)
214 12672 : for(int k = 0; k < 3; k++)
215 38016 : for(int l = 0; l < 3; l++)
216 57024 : ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
217 : }
218 44 : return ret;
219 : }
220 21 : static Matrix4<2,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
221 : {
222 : Eigen::Quaterniond q =
223 21 : Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
224 21 : Eigen::AngleAxisd(Phi, Eigen::Vector3d::UnitZ()) *
225 42 : Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
226 21 : Eigen::Matrix3d R = q.toRotationMatrix();
227 21 : return Matrix4<2,Sym::MajorMinor>::Transverse(C11,C12,C13,C33,C44,R);
228 : }
229 : static Matrix4<2,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Quaternion q)
230 : {
231 : Eigen::Matrix3d R = q.normalized().toRotationMatrix();
232 : return Transverse(C11,C12,C13,C33,C44,R);
233 : }
234 :
235 :
236 : friend Eigen::Matrix<Set::Scalar,2,2> operator * (Matrix4<2,Sym::MajorMinor> a, Eigen::Matrix<Set::Scalar,2,2> b);
237 : friend bool operator == (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b);
238 : friend Matrix4<2,Sym::MajorMinor> operator + (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b);
239 : friend Matrix4<2,Sym::MajorMinor> operator - (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b);
240 : friend Matrix4<2,Sym::MajorMinor> operator * (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b);
241 : friend Matrix4<2,Sym::MajorMinor> operator * (Set::Scalar b, Matrix4<2,Sym::MajorMinor> a);
242 : friend Matrix4<2,Sym::MajorMinor> operator / (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b);
243 : friend Set::Vector operator * (Matrix4<2,Sym::MajorMinor> a, Set::Matrix3 b);
244 : };
245 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
246 : bool operator == (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b)
247 : {
248 175 : for (int i = 0 ; i < 6 ; i++) if (a.data[i] != b.data[i]) return false;
249 25 : return true;
250 : }
251 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
252 : Matrix4<2,Sym::MajorMinor> operator + (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b)
253 : {
254 0 : Matrix4<2,Sym::MajorMinor> ret;
255 0 : for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] + b.data[i];
256 0 : return ret;
257 : }
258 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
259 : Matrix4<2,Sym::MajorMinor> operator - (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b)
260 : {
261 0 : Matrix4<2,Sym::MajorMinor> ret;
262 0 : for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] - b.data[i];
263 0 : return ret;
264 : }
265 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
266 : Matrix4<2,Sym::MajorMinor> operator * (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b)
267 : {
268 10 : Matrix4<2,Sym::MajorMinor> ret;
269 70 : for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] * b;
270 10 : return ret;
271 : }
272 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
273 : Matrix4<2,Sym::MajorMinor> operator * (Set::Scalar b,Matrix4<2,Sym::MajorMinor> a)
274 : {
275 0 : return a*b;
276 : }
277 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
278 : Matrix4<2,Sym::MajorMinor> operator / (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b)
279 : {
280 0 : Matrix4<2,Sym::MajorMinor> ret;
281 0 : for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] / b;
282 0 : return ret;
283 : }
284 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
285 : Eigen::Matrix<Set::Scalar,2,2> operator * (Matrix4<2,Sym::MajorMinor> a, Eigen::Matrix<Set::Scalar,2,2> b)
286 : {
287 2430 : Eigen::Matrix<Set::Scalar,2,2> ret = Eigen::Matrix<Set::Scalar,2,2>::Zero();
288 2430 : ret(0,0) = a.data[0]*b(0,0) + a.data[1]*(b(0,1) + b(1,0)) + a.data[2]*b(1,1);
289 2430 : ret(0,1) = a.data[1]*b(0,0) + a.data[3]*(b(0,1) + b(1,0)) + a.data[4]*b(1,1);
290 2430 : ret(1,1) = a.data[2]*b(0,0) + a.data[4]*(b(0,1) + b(1,0)) + a.data[5]*b(1,1);
291 2430 : ret(1,0) = ret(0,1);
292 2430 : return ret;
293 : }
294 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
295 : Eigen::Matrix<amrex::Real,2,1> operator * (Matrix4<2,Sym::MajorMinor> a, std::array<Eigen::Matrix<amrex::Real,2,2>,2> b);
296 :
297 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
298 : Set::Vector operator * (Matrix4<2,Sym::MajorMinor> a, Set::Matrix3 b)
299 : {
300 0 : Set::Vector ret = Set::Vector::Zero();
301 0 : ret(0) = a.data[0]*b(0,0,0) + a.data[1]*(b(0,1,0) + b(1,0,0) + b(0,0,1)) + a.data[2]*b(1,1,0) + a.data[3]*(b(0,1,1) + b(1,0,1)) + a.data[4]*b(1,1,1);
302 0 : ret(1) = a.data[1]*b(0,0,0) + a.data[2]*b(0,0,1) + a.data[3]*(b(0,1,0) + b(1,0,0)) + a.data[4]*(b(1,1,0) + b(0,1,1) + b(1,0,1)) + a.data[5]*b(1,1,1);
303 0 : return ret;
304 : }
305 :
306 : /// \brief Data structure for a 4th order 3D tensor with major and minor symmetry
307 : ///
308 : /// Let the tensor
309 : /// \f$\mathbb{C}\in\mathbb{R}^3\times\mathbb{R}^3\times\mathbb{R}^3\times\mathbb{R}^3\f$
310 : /// be have major symmetry (\f$\mathbb{C}_{ijkl}=\mathbb{C}_{klij}\f$)
311 : /// and minor symmetry (\f$\mathbb{C}_{ijkl}=\mathbb{C}_{jikl}=\mathbb{C}_{ijlk}\f$)
312 : /// Then there are only 21 unique elements (rather than 81).
313 : ///
314 : /// This object acts like a 4D array such that `C(i,j,k,l)` returns the corresponding
315 : /// element, but symmetry is always obeyed. This allows the user code to be much prettier,
316 : /// while maintaining a relatively small object size.
317 : ///
318 : template<>
319 : class Matrix4<3,Sym::MajorMinor>
320 : {
321 : Scalar data[21] = { NAN,NAN,NAN,NAN,NAN,NAN,NAN,
322 : NAN,NAN,NAN,NAN,NAN,NAN,NAN,
323 : NAN,NAN,NAN,NAN,NAN,NAN,NAN };
324 :
325 : public:
326 1425097 : AMREX_GPU_HOST_DEVICE Matrix4() {};
327 : AMREX_FORCE_INLINE
328 : const Scalar & operator () (const int i, const int j, const int k, const int l) const
329 : {
330 9475 : int uid = i + 3*j + 9*k + 27*l;
331 : // [0000]
332 9475 : if (uid==0 ) return data[0];
333 : // [0001] [0010] [0100] [1000]
334 8000 : else if (uid==27 || uid==9 || uid==3 || uid==1 ) return data[1];
335 : // [0002] [0020] [0200] [2000]
336 7600 : else if (uid==54 || uid==18 || uid==6 || uid==2 ) return data[2];
337 : // [0011] [1100]
338 7200 : else if (uid==36 || uid==4 ) return data[3];
339 : // [0012] [0021] [1200] [2100]
340 7000 : else if (uid==63 || uid==45 || uid==7 || uid==5 ) return data[4];
341 : // [0022] [2200]
342 6600 : else if (uid==72 || uid==8 ) return data[5];
343 : // [0101] [0110] [1001] [1010]
344 6400 : else if (uid==30 || uid==12 || uid==28 || uid==10 ) return data[6];
345 : // [0102] [0120] [1002] [1020] [0201] [2001] [0210] [2010]
346 6000 : else if (uid==57 || uid==21 || uid==33 || uid==15 || uid==55 || uid==19 || uid==29 || uid==11 ) return data[7];
347 : // [0111] [1011] [1101] [1110]
348 5200 : else if (uid==39 || uid==37 || uid==31 || uid==13 ) return data[8];
349 : // [0112] [1012] [0121] [1021] [1201] [1210] [2101] [2110]
350 4800 : else if (uid==66 || uid==48 || uid==64 || uid==46 || uid==34 || uid==16 || uid==32 || uid==14 ) return data[9];
351 : // [0122] [1022] [2201] [2210]
352 4000 : else if (uid==75 || uid==73 || uid==35 || uid==17 ) return data[10];
353 : // [0202] [2002] [0220] [2020]
354 3600 : else if (uid==60 || uid==24 || uid==56 || uid==20 ) return data[11];
355 : // [0211] [2011] [1102] [1120]
356 3200 : else if (uid==42 || uid==58 || uid==22 || uid==38 ) return data[12];
357 : // [0212] [2012] [0221] [2021] [1202] [1220] [2102] [2120]
358 2800 : else if (uid==69 || uid==51 || uid==61 || uid==25 || uid==65 || uid==47 || uid==59 || uid==23 ) return data[13];
359 : // [0222] [2022] [2202] [2220]
360 2000 : else if (uid==78 || uid==74 || uid==62 || uid==26 ) return data[14];
361 : // [1111]
362 1600 : else if (uid==40 ) return data[15];
363 : // [1112] [1121] [1211] [2111]
364 1500 : else if (uid==67 || uid==49 || uid==43 || uid==41 ) return data[16];
365 : // [1122] [2211]
366 1100 : else if (uid==76 || uid==44 ) return data[17];
367 : // [1212] [2112] [1221] [2121]
368 900 : else if (uid==70 || uid==52 || uid==68 || uid==50 ) return data[18];
369 : // [1222] [2122] [2212] [2221]
370 500 : else if (uid==79 || uid==77 || uid==71 || uid==53 ) return data[19];
371 : // [2222]
372 100 : else if (uid==80 ) return data[20];
373 0 : else Util::Abort(INFO,"Index out of range");
374 0 : return Set::Garbage;
375 : }
376 : AMREX_FORCE_INLINE
377 : Scalar & operator () (const int i, const int j, const int k, const int l)
378 : {
379 28034100 : int uid = i + 3*j + 9*k + 27*l;
380 : // [0000]
381 2593617 : if (uid==0 ) return data[0];
382 : // [0001] [0010] [0100] [1000]
383 27688000 : else if (uid==27 || uid==9 || uid==3 || uid==1 ) return data[1];
384 : // [0002] [0020] [0200] [2000]
385 26303600 : else if (uid==54 || uid==18 || uid==6 || uid==2 ) return data[2];
386 : // [0011] [1100]
387 24919200 : else if (uid==36 || uid==4 ) return data[3];
388 : // [0012] [0021] [1200] [2100]
389 24227000 : else if (uid==63 || uid==45 || uid==7 || uid==5 ) return data[4];
390 : // [0022] [2200]
391 22842600 : else if (uid==72 || uid==8 ) return data[5];
392 : // [0101] [0110] [1001] [1010]
393 22150400 : else if (uid==30 || uid==12 || uid==28 || uid==10 ) return data[6];
394 : // [0102] [0120] [1002] [1020] [0201] [2001] [0210] [2010]
395 20766000 : else if (uid==57 || uid==21 || uid==33 || uid==15 || uid==55 || uid==19 || uid==29 || uid==11 ) return data[7];
396 : // [0111] [1011] [1101] [1110]
397 17997200 : else if (uid==39 || uid==37 || uid==31 || uid==13 ) return data[8];
398 : // [0112] [1012] [0121] [1021] [1201] [1210] [2101] [2110]
399 16612800 : else if (uid==66 || uid==48 || uid==64 || uid==46 || uid==34 || uid==16 || uid==32 || uid==14 ) return data[9];
400 : // [0122] [1022] [2201] [2210]
401 13844000 : else if (uid==75 || uid==73 || uid==35 || uid==17 ) return data[10];
402 : // [0202] [2002] [0220] [2020]
403 12459600 : else if (uid==60 || uid==24 || uid==56 || uid==20 ) return data[11];
404 : // [0211] [2011] [1102] [1120]
405 11075200 : else if (uid==42 || uid==58 || uid==22 || uid==38 ) return data[12];
406 : // [0212] [2012] [0221] [2021] [1202] [1220] [2102] [2120]
407 9690800 : else if (uid==69 || uid==51 || uid==61 || uid==25 || uid==65 || uid==47 || uid==59 || uid==23 ) return data[13];
408 : // [0222] [2022] [2202] [2220]
409 6922000 : else if (uid==78 || uid==74 || uid==62 || uid==26 ) return data[14];
410 : // [1111]
411 5537600 : else if (uid==40 ) return data[15];
412 : // [1112] [1121] [1211] [2111]
413 5191500 : else if (uid==67 || uid==49 || uid==43 || uid==41 ) return data[16];
414 : // [1122] [2211]
415 3807100 : else if (uid==76 || uid==44 ) return data[17];
416 : // [1212] [2112] [1221] [2121]
417 3114900 : else if (uid==70 || uid==52 || uid==68 || uid==50 ) return data[18];
418 : // [1222] [2122] [2212] [2221]
419 1730500 : else if (uid==79 || uid==77 || uid==71 || uid==53 ) return data[19];
420 : // [2222]
421 346100 : else if (uid==80 ) return data[20];
422 0 : else Util::Abort(INFO,"Index out of range");
423 0 : return Set::Garbage;
424 : }
425 : void Print (std::ostream& os)
426 : {
427 : for (int i = 0; i < 21; i++)
428 : os << "i = " << i << " " << data[i] << std::endl;
429 :
430 : os.precision(4);
431 : for (int k = 0; k < 3; k++)
432 : {
433 : for (int i = -1; i < 4; i++)
434 : {
435 : for (int l = 0; l < 3; l++)
436 : {
437 : if (i==-1) os << "┌ ┐ ";
438 : else if (i == 3) os << "└ ┘ ";
439 : else
440 : {
441 : os << "│ ";
442 : for (int j = 0; j < 3; j++)
443 : {
444 : const Set::Scalar &val = (*this)(i,j,k,l);
445 : os << std::scientific << std::setw(11) << val ; //(fabs(val)>1E-10 ? val : 0);
446 : os << " ";
447 : }
448 : os << "│ ";
449 : }
450 : }
451 : os<<std::endl;
452 : }
453 : }
454 : }
455 :
456 : Set::Scalar Norm()
457 : {
458 : Set::Scalar retsq = 0;
459 : for (int i = 0; i < 21; i++) retsq += data[i];
460 : return std::sqrt(retsq);
461 : }
462 : bool contains_nan() const
463 : {
464 : if (std::isnan(data[ 0])) return true;
465 : if (std::isnan(data[ 1])) return true;
466 : if (std::isnan(data[ 2])) return true;
467 : if (std::isnan(data[ 3])) return true;
468 : if (std::isnan(data[ 4])) return true;
469 : if (std::isnan(data[ 5])) return true;
470 : if (std::isnan(data[ 6])) return true;
471 : if (std::isnan(data[ 7])) return true;
472 : if (std::isnan(data[ 8])) return true;
473 : if (std::isnan(data[ 9])) return true;
474 : if (std::isnan(data[10])) return true;
475 : if (std::isnan(data[11])) return true;
476 : if (std::isnan(data[12])) return true;
477 : if (std::isnan(data[13])) return true;
478 : if (std::isnan(data[14])) return true;
479 : if (std::isnan(data[15])) return true;
480 : if (std::isnan(data[16])) return true;
481 : if (std::isnan(data[17])) return true;
482 : if (std::isnan(data[18])) return true;
483 : if (std::isnan(data[19])) return true;
484 : if (std::isnan(data[20])) return true;
485 : return false;
486 : }
487 :
488 : //AMREX_GPU_HOST_DEVICE void operator = (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] = a.data[i];}
489 2750 : AMREX_GPU_HOST_DEVICE void operator += (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] += a.data[i];}
490 : AMREX_GPU_HOST_DEVICE void operator -= (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] -= a.data[i];}
491 : AMREX_GPU_HOST_DEVICE void operator *= (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] *= a.data[i];}
492 : AMREX_GPU_HOST_DEVICE void operator /= (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] /= a.data[i];}
493 : AMREX_GPU_HOST_DEVICE void operator *= (Set::Scalar alpha) {for (int i = 0; i < 21; i++) data[i] *= alpha;}
494 : AMREX_GPU_HOST_DEVICE void operator /= (Set::Scalar alpha) {for (int i = 0; i < 21; i++) data[i] /= alpha;}
495 :
496 : static Matrix4<3,Sym::MajorMinor> Increment()
497 : {
498 : Matrix4<3,Sym::MajorMinor> ret;
499 : for (int i = 0 ; i < 21; i++) ret.data[i] = (Set::Scalar)i;
500 : return ret;
501 : }
502 1 : void Randomize()
503 : {
504 22 : for (int i = 0 ; i < 21; i++) data[i] = (Util::Random());
505 1 : }
506 1 : static Matrix4<3,Sym::MajorMinor> Random()
507 : {
508 1 : Matrix4<3,Sym::MajorMinor> ret;
509 1 : ret.Randomize();
510 1 : return ret;
511 : }
512 321 : static Matrix4<3,Sym::MajorMinor> Zero()
513 : {
514 321 : Matrix4<3,Sym::MajorMinor> ret;
515 7062 : for (int i = 0 ; i < 21; i++) ret.data[i] = 0.0;
516 321 : return ret;
517 : }
518 3904 : static Matrix4<3,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44,
519 : Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
520 : {
521 3904 : Set::Matrix4<3,Sym::MajorMinor> ret;
522 : Set::Scalar Ctmp[3][3][3][3];
523 :
524 15616 : for(int i = 0; i < 3; i++)
525 46848 : for(int j = 0; j < 3; j++)
526 140544 : for(int k = 0; k < 3; k++)
527 421632 : for(int l = 0; l < 3; l++)
528 : {
529 316224 : if(i == j && j == k && k == l) Ctmp[i][j][k][l] = C11;
530 304512 : else if (i==k && j==l) Ctmp[i][j][k][l] = C44;
531 281088 : else if (i==j && k==l) Ctmp[i][j][k][l] = C12;
532 257664 : else Ctmp[i][j][k][l] = 0.0;
533 : }
534 15616 : for(int p = 0; p < 3; p++)
535 46848 : for(int q = 0; q < 3; q++)
536 140544 : for(int s = 0; s < 3; s++)
537 421632 : for(int t = 0; t < 3; t++)
538 : {
539 316224 : ret(p,q,s,t) = 0.0;
540 1264896 : for(int i = 0; i < 3; i++)
541 3794688 : for(int j = 0; j < 3; j++)
542 11384064 : for(int k = 0; k < 3; k++)
543 34152192 : for(int l = 0; l < 3; l++)
544 51228288 : ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
545 : }
546 7808 : return ret;
547 : }
548 44 : static Matrix4<3,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44,
549 : Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
550 : {
551 44 : Eigen::Matrix3d R;
552 44 : R = Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
553 88 : Eigen::AngleAxisd(Phi, Eigen::Vector3d::UnitZ()) *
554 88 : Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
555 44 : return Matrix4<3,Sym::MajorMinor>::Cubic(C11,C12,C44,R);
556 : }
557 3860 : static Matrix4<3,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44,
558 : Set::Quaternion q)
559 : {
560 3860 : Eigen::Matrix3d R = q.normalized().toRotationMatrix();
561 3860 : return Cubic(C11,C12,C44,R);
562 : }
563 :
564 22 : static Matrix4<3,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
565 : {
566 22 : Set::Matrix4<3,Sym::MajorMinor> ret;
567 22 : Set::Scalar Ctmp[3][3][3][3] = {{{{0.0}}}};
568 :
569 88 : for(int i = 0; i < 3; i++)
570 264 : for(int j = 0; j < 3; j++)
571 792 : for(int k = 0; k < 3; k++)
572 2376 : for(int l = 0; l < 3; l++)
573 : {
574 1782 : if(i==j && j==k && k==l)
575 : {
576 66 : if (i < 2) Ctmp[i][j][k][l] = C11;
577 22 : else Ctmp[i][j][k][l] = C33;
578 : }
579 1716 : else if(i==j && k==l)
580 : {
581 132 : if (i<2 && k<2 && i!=k) Ctmp[i][j][k][l] = C12;
582 88 : else if ((i<2 && k==2) || (i==2 && k<2)) Ctmp[i][j][k][l] = C13;
583 : }
584 1584 : else if((i==k && j==l) && (i!=j))
585 : {
586 132 : Ctmp[i][j][k][l] = C44;
587 : }
588 : else
589 : {
590 1452 : Ctmp[i][j][k][l] = 0.0;
591 : }
592 : }
593 :
594 : // C66 = 0.5*(C11 - C12)
595 22 : Ctmp[0][1][0][1] = 0.5 * (C11 - C12);
596 22 : Ctmp[1][0][1][0] = 0.5 * (C11 - C12);
597 :
598 88 : for(int p = 0; p < 3; p++)
599 264 : for(int q = 0; q < 3; q++)
600 792 : for(int s = 0; s < 3; s++)
601 2376 : for(int t = 0; t < 3; t++)
602 : {
603 1782 : ret(p,q,s,t) = 0.0;
604 7128 : for(int i = 0; i < 3; i++)
605 21384 : for(int j = 0; j < 3; j++)
606 64152 : for(int k = 0; k < 3; k++)
607 192456 : for(int l = 0; l < 3; l++)
608 288684 : ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
609 : }
610 44 : return ret;
611 : }
612 21 : static Matrix4<3,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
613 : {
614 : Eigen::Quaterniond q =
615 21 : Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
616 21 : Eigen::AngleAxisd(Phi, Eigen::Vector3d::UnitZ()) *
617 42 : Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
618 21 : Eigen::Matrix3d R = q.toRotationMatrix();
619 21 : return Matrix4<3,Sym::MajorMinor>::Transverse(C11,C12,C13,C33,C44,R);
620 : }
621 : static Matrix4<3,Sym::MajorMinor> Trans(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Quaternion q)
622 : {
623 : Eigen::Matrix3d R = q.normalized().toRotationMatrix();
624 : return Transverse(C11,C12,C13,C33,C44,R);
625 : }
626 :
627 : friend bool operator == (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b);
628 : friend Matrix4<3,Sym::MajorMinor> operator + (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b);
629 : friend Matrix4<3,Sym::MajorMinor> operator - (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b);
630 : friend Matrix4<3,Sym::MajorMinor> operator * (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b);
631 : friend Matrix4<3,Sym::MajorMinor> operator * (Set::Scalar b, Matrix4<3,Sym::MajorMinor> a);
632 : friend Matrix4<3,Sym::MajorMinor> operator / (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b);
633 : friend Set::Vector operator * (Matrix4<3,Sym::MajorMinor> a, Set::Matrix3 b);
634 : friend Eigen::Matrix<amrex::Real,3,3> operator * (Matrix4<3,Sym::MajorMinor> a, Eigen::Matrix<amrex::Real,3,3> b);
635 : };
636 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
637 : bool operator == (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b)
638 : {
639 550 : for (int i = 0 ; i < 21 ; i++) if (a.data[i] != b.data[i]) return false;
640 25 : return true;
641 : }
642 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
643 : Matrix4<3,Sym::MajorMinor> operator + (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b)
644 : {
645 9800 : Matrix4<3,Sym::MajorMinor> ret;
646 215600 : for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] + b.data[i];
647 9800 : return ret;
648 : }
649 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
650 : Matrix4<3,Sym::MajorMinor> operator - (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b)
651 : {
652 294597 : Matrix4<3,Sym::MajorMinor> ret;
653 6481134 : for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] - b.data[i];
654 294597 : return ret;
655 : }
656 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
657 : Matrix4<3,Sym::MajorMinor> operator * (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b)
658 : {
659 301332 : Matrix4<3,Sym::MajorMinor> ret;
660 6629304 : for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] * b;
661 301332 : return ret;
662 : }
663 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
664 : Matrix4<3,Sym::MajorMinor> operator * (Set::Scalar b,Matrix4<3,Sym::MajorMinor> a)
665 : {
666 0 : return a*b;
667 : }
668 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
669 : Matrix4<3,Sym::MajorMinor> operator / (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b)
670 : {
671 295597 : Matrix4<3,Sym::MajorMinor> ret;
672 6503134 : for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] / b;
673 295597 : return ret;
674 : }
675 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
676 : Eigen::Matrix<amrex::Real,3,3> operator * (Matrix4<3,Sym::MajorMinor> a, Eigen::Matrix<amrex::Real,3,3> b)
677 : {
678 1413576 : Eigen::Matrix<amrex::Real,3,3> ret = Eigen::Matrix<amrex::Real,3,3>::Zero();
679 1413576 : ret(0,0) += a.data[ 0]*b(0,0) + a.data[ 1]*(b(0,1) + b(1,0)) + a.data[ 2]*(b(0,2) + b(2,0)) + a.data[ 3]*b(1,1) + a.data[ 4]*(b(1,2) + b(2,1)) + a.data[ 5]*b(2,2);
680 1413576 : ret(1,1) += a.data[ 3]*b(0,0) + a.data[ 8]*(b(0,1) + b(1,0)) + a.data[ 12]*(b(0,2) + b(2,0)) + a.data[ 15]*b(1,1) + a.data[ 16]*(b(1,2) + b(2,1)) + a.data[ 17]*b(2,2);
681 1413576 : ret(2,2) += a.data[ 5]*b(0,0) + a.data[ 10]*(b(0,1) + b(1,0)) + a.data[ 14]*(b(0,2) + b(2,0)) + a.data[ 17]*b(1,1) + a.data[ 19]*(b(1,2) + b(2,1)) + a.data[ 20]*b(2,2);
682 1413576 : ret(1,2) += a.data[ 4]*b(0,0) + a.data[ 9]*(b(0,1) + b(1,0)) + a.data[ 13]*(b(0,2) + b(2,0)) + a.data[ 16]*b(1,1) + a.data[ 18]*(b(1,2) + b(2,1)) + a.data[ 19]*b(2,2);
683 1413576 : ret(2,0) += a.data[ 2]*b(0,0) + a.data[ 7]*(b(0,1) + b(1,0)) + a.data[ 11]*(b(0,2) + b(2,0)) + a.data[ 12]*b(1,1) + a.data[ 13]*(b(1,2) + b(2,1)) + a.data[ 14]*b(2,2);
684 1413576 : ret(0,1) += a.data[ 1]*b(0,0) + a.data[ 6]*(b(0,1) + b(1,0)) + a.data[ 7]*(b(0,2) + b(2,0)) + a.data[ 8]*b(1,1) + a.data[ 9]*(b(1,2) + b(2,1)) + a.data[ 10]*b(2,2);
685 :
686 1413576 : ret(2,1) = ret(1,2);
687 1413576 : ret(0,2) = ret(2,0);
688 1413576 : ret(1,0) = ret(0,1);
689 :
690 1413576 : return ret;
691 : }
692 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
693 : Eigen::Matrix<amrex::Real,2,2> operator * (Matrix4<3,Sym::MajorMinor> a, Eigen::Matrix<amrex::Real,2,2> b)
694 : {
695 : Eigen::Matrix<amrex::Real,2,2> ret = Eigen::Matrix<amrex::Real,2,2>::Zero();
696 : for (int i = 0; i < 2; i++)
697 : for (int j = 0; j < 2; j++)
698 : for (int k = 0; k < 2; k++)
699 : for (int l = 0; l < 2; l++)
700 : ret(i,j) += a(i,j,k,l)*b(k,l);
701 : return ret;
702 : }
703 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
704 : Eigen::Matrix<amrex::Real,3,1> operator * (Matrix4<3,Sym::MajorMinor> a, std::array<Eigen::Matrix<amrex::Real,3,3>,3> b);
705 :
706 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
707 : Eigen::Matrix<amrex::Real,2,1> operator * (Matrix4<3,Sym::MajorMinor> a, std::array<Eigen::Matrix<amrex::Real,2,2>,2> b);
708 :
709 : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
710 : Set::Vector operator * (Matrix4<3,Sym::MajorMinor> a, Set::Matrix3 b)
711 : {
712 : // TODO: improve efficiency of this method
713 106599 : Set::Vector ret = Set::Vector::Zero();
714 :
715 213198 : ret(0) +=
716 106599 : a.data[ 0]*b(0,0,0) +
717 319797 : a.data[ 1]*(b(0,1,0) + b(1,0,0) + b(0,0,1)) +
718 319797 : a.data[ 2]*(b(0,2,0) + b(2,0,0) + b(0,0,2)) +
719 106599 : a.data[ 3]*b(1,1,0) +
720 213198 : a.data[ 4]*(b(1,2,0) + b(2,1,0)) +
721 106599 : a.data[ 5]*b(2,2,0) +
722 213198 : a.data[ 6]*(b(0,1,1) + b(1,0,1)) +
723 426396 : a.data[ 7]*(b(0,2,1) + b(2,0,1) + b(0,1,2) + b(1,0,2)) +
724 106599 : a.data[ 8]*b(1,1,1) +
725 213198 : a.data[ 9]*(b(1,2,1) + b(2,1,1)) +
726 106599 : a.data[ 10]*b(2,2,1) +
727 213198 : a.data[ 11]*(b(0,2,2) + b(2,0,2)) +
728 106599 : a.data[ 12]*b(1,1,2) +
729 213198 : a.data[ 13]*(b(1,2,2) + b(2,1,2)) +
730 213198 : a.data[ 14]*b(2,2,2);
731 :
732 213198 : ret(1) +=
733 106599 : a.data[ 1]*b(0,0,0) +
734 106599 : a.data[ 4]*b(0,0,2) +
735 106599 : a.data[ 3]*b(0,0,1) +
736 213198 : a.data[ 6]*(b(0,1,0) + b(1,0,0)) +
737 213198 : a.data[ 7]*(b(0,2,0) + b(2,0,0)) +
738 319797 : a.data[ 8]*(b(1,1,0) + b(0,1,1) + b(1,0,1)) +
739 426396 : a.data[ 9]*(b(1,2,0) + b(2,1,0) + b(0,1,2) + b(1,0,2)) +
740 106599 : a.data[ 10]*b(2,2,0) +
741 213198 : a.data[ 12]*(b(0,2,1) + b(2,0,1)) +
742 213198 : a.data[ 13]*(b(0,2,2) + b(2,0,2)) +
743 106599 : a.data[ 15]*b(1,1,1) +
744 319797 : a.data[ 16]*(b(1,2,1) + b(2,1,1) + b(1,1,2)) +
745 106599 : a.data[ 17]*b(2,2,1) +
746 213198 : a.data[ 18]*(b(1,2,2) + b(2,1,2)) +
747 213198 : a.data[ 19]*b(2,2,2);
748 :
749 213198 : ret(2) +=
750 106599 : a.data[ 2]*b(0,0,0) +
751 106599 : a.data[ 4]*b(0,0,1) +
752 106599 : a.data[ 5]*b(0,0,2) +
753 213198 : a.data[ 7]*(b(0,1,0) + b(1,0,0)) +
754 213198 : a.data[ 9]*(b(0,1,1) + b(1,0,1)) +
755 213198 : a.data[ 10]*(b(0,1,2) + b(1,0,2)) +
756 213198 : a.data[ 11]*(b(0,2,0) + b(2,0,0)) +
757 106599 : a.data[ 12]*b(1,1,0) +
758 426396 : a.data[ 13]*(b(1,2,0) + b(2,1,0) + b(0,2,1) + b(2,0,1)) +
759 319797 : a.data[ 14]*(b(2,2,0) + b(0,2,2) + b(2,0,2)) +
760 106599 : a.data[ 16]*b(1,1,1) +
761 106599 : a.data[ 17]*b(1,1,2) +
762 213198 : a.data[ 18]*(b(1,2,1) + b(2,1,1)) +
763 319797 : a.data[ 19]*(b(2,2,1) + b(1,2,2) + b(2,1,2)) +
764 213198 : a.data[ 20]*b(2,2,2);
765 :
766 106599 : return ret;
767 : }
768 :
769 : }
770 : #endif
|