TensorI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include <type_traits>
30 
31 #include "SymmTensor.H"
32 
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 
35 template<class Cmpt>
37 :
39 {}
40 
41 
42 template<class Cmpt>
43 template<class Cmpt2>
45 (
46  const MatrixSpace<Tensor<Cmpt2>, Cmpt2, 3, 3>& vs
47 )
48 :
50 {}
51 
52 
53 template<class Cmpt>
54 template<class Cmpt2>
56 (
57  const VectorSpace<Tensor<Cmpt2>, Cmpt2, 9>& vs
58 )
59 :
60  Tensor::msType(vs)
61 {}
62 
63 
64 template<class Cmpt>
66 {
67  this->v_[XX] = st.ii(); this->v_[XY] = Zero; this->v_[XZ] = Zero;
68  this->v_[YX] = Zero; this->v_[YY] = st.ii(); this->v_[YZ] = Zero;
69  this->v_[ZX] = Zero; this->v_[ZY] = Zero; this->v_[ZZ] = st.ii();
70 }
71 
72 
73 template<class Cmpt>
75 {
76  this->v_[XX] = st.xx(); this->v_[XY] = st.xy(); this->v_[XZ] = st.xz();
77  this->v_[YX] = st.xy(); this->v_[YY] = st.yy(); this->v_[YZ] = st.yz();
78  this->v_[ZX] = st.xz(); this->v_[ZY] = st.yz(); this->v_[ZZ] = st.zz();
79 }
80 
81 
82 template<class Cmpt>
84 (
85  const Vector<Vector<Cmpt>>& vecs,
86  const bool transposed
87 )
88 :
89  Tensor<Cmpt>(vecs.x(), vecs.y(), vecs.z(), transposed)
90 {}
91 
92 
93 template<class Cmpt>
95 (
96  const Vector<Cmpt>& x,
97  const Vector<Cmpt>& y,
98  const Vector<Cmpt>& z,
99  const bool transposed
100 )
101 {
102  if (transposed)
103  {
104  this->cols(x, y, z);
105  }
106  else
107  {
108  this->rows(x, y, z);
109  }
110 }
111 
112 
113 template<class Cmpt>
115 (
116  const Cmpt txx, const Cmpt txy, const Cmpt txz,
117  const Cmpt tyx, const Cmpt tyy, const Cmpt tyz,
118  const Cmpt tzx, const Cmpt tzy, const Cmpt tzz
119 )
120 {
121  this->v_[XX] = txx; this->v_[XY] = txy; this->v_[XZ] = txz;
122  this->v_[YX] = tyx; this->v_[YY] = tyy; this->v_[YZ] = tyz;
123  this->v_[ZX] = tzx; this->v_[ZY] = tzy; this->v_[ZZ] = tzz;
124 }
125 
126 
127 template<class Cmpt>
128 template
129 <
130  template<class, Foam::direction, Foam::direction> class Block2,
131  Foam::direction BRowStart,
132  Foam::direction BColStart
133 >
135 (
136  const Block2<Tensor<Cmpt>, BRowStart, BColStart>& block
137 )
138 :
140 {}
141 
142 
143 template<class Cmpt>
145 :
147 {}
148 
149 
150 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
151 
152 template<class Cmpt>
154 {
155  return Vector<Cmpt>(this->v_[XX], this->v_[XY], this->v_[XZ]);
156 }
157 
158 
159 template<class Cmpt>
161 {
162  return Vector<Cmpt>(this->v_[YX], this->v_[YY], this->v_[YZ]);
163 }
164 
165 
166 template<class Cmpt>
168 {
169  return Vector<Cmpt>(this->v_[ZX], this->v_[ZY], this->v_[ZZ]);
170 }
171 
172 
173 template<class Cmpt>
175 {
176  return Vector<Cmpt>(this->v_[XX], this->v_[YX], this->v_[ZX]);
177 }
178 
179 
180 template<class Cmpt>
182 {
183  return Vector<Cmpt>(this->v_[XY], this->v_[YY], this->v_[ZY]);
184 }
185 
186 
187 template<class Cmpt>
189 {
190  return Vector<Cmpt>(this->v_[XZ], this->v_[YZ], this->v_[ZZ]);
191 }
192 
193 
194 template<class Cmpt>
195 template<Foam::direction Idx>
197 {
198  if (Idx == 0) return cx();
199  else if (Idx == 1) return cy();
200  else if (Idx == 2) return cz();
202  static_assert(Idx < 3, "Invalid column access");
203  return Zero;
204 }
205 
206 
207 template<class Cmpt>
209 {
210  switch (c)
211  {
212  case 0: return cx(); break;
213  case 1: return cy(); break;
214  case 2: return cz(); break;
215  default:
217  << "Invalid column access " << c << abort(FatalError);
218  }
220  return Zero;
221 }
222 
223 
224 template<class Cmpt>
225 template<Foam::direction Idx>
227 {
228  if (Idx == 0) return x();
229  else if (Idx == 1) return y();
230  else if (Idx == 2) return z();
232  static_assert(Idx < 3, "Invalid row access");
233  return Zero;
234 }
235 
236 
237 template<class Cmpt>
239 {
240  switch (r)
241  {
242  case 0: return x(); break;
243  case 1: return y(); break;
244  case 2: return z(); break;
245  default:
247  << "Invalid row access " << r << abort(FatalError);
248  }
250  return Zero;
251 }
252 
253 
254 template<class Cmpt>
255 template<Foam::direction Idx>
256 inline void Foam::Tensor<Cmpt>::col(const Vector<Cmpt>& v)
257 {
258  if (Idx == 0)
259  {
260  this->v_[XX] = v.x();
261  this->v_[YX] = v.y();
262  this->v_[ZX] = v.z();
263  }
264  else if (Idx == 1)
265  {
266  this->v_[XY] = v.x();
267  this->v_[YY] = v.y();
268  this->v_[ZY] = v.z();
269  }
270  else if (Idx == 2)
271  {
272  this->v_[XZ] = v.x();
273  this->v_[YZ] = v.y();
274  this->v_[ZZ] = v.z();
275  }
277  static_assert(Idx < 3, "Invalid column access");
278 }
279 
280 
281 template<class Cmpt>
282 template<Foam::direction Idx>
283 inline void Foam::Tensor<Cmpt>::row(const Vector<Cmpt>& v)
284 {
285  if (Idx == 0)
286  {
287  this->v_[XX] = v.x(); this->v_[XY] = v.y(); this->v_[XZ] = v.z();
288  }
289  else if (Idx == 1)
290  {
291  this->v_[YX] = v.x(); this->v_[YY] = v.y(); this->v_[YZ] = v.z();
292  }
293  else if (Idx == 2)
294  {
295  this->v_[ZX] = v.x(); this->v_[ZY] = v.y(); this->v_[ZZ] = v.z();
296  }
298  static_assert(Idx < 3, "Invalid row access");
299 }
300 
301 
302 template<class Cmpt>
303 inline void Foam::Tensor<Cmpt>::cols
304 (
305  const Vector<Cmpt>& x,
306  const Vector<Cmpt>& y,
307  const Vector<Cmpt>& z
308 )
309 {
310  this->v_[XX] = x.x(); this->v_[XY] = y.x(); this->v_[XZ] = z.x();
311  this->v_[YX] = x.y(); this->v_[YY] = y.y(); this->v_[YZ] = z.y();
312  this->v_[ZX] = x.z(); this->v_[ZY] = y.z(); this->v_[ZZ] = z.z();
313 }
314 
315 
316 template<class Cmpt>
317 inline void Foam::Tensor<Cmpt>::rows
318 (
319  const Vector<Cmpt>& x,
320  const Vector<Cmpt>& y,
321  const Vector<Cmpt>& z
322 )
323 {
324  this->v_[XX] = x.x(); this->v_[XY] = x.y(); this->v_[XZ] = x.z();
325  this->v_[YX] = y.x(); this->v_[YY] = y.y(); this->v_[YZ] = y.z();
326  this->v_[ZX] = z.x(); this->v_[ZY] = z.y(); this->v_[ZZ] = z.z();
327 }
328 
329 
330 template<class Cmpt>
331 inline void Foam::Tensor<Cmpt>::col
332 (
333  const direction c,
334  const Vector<Cmpt>& v
335 )
336 {
337  switch (c)
338  {
339  case 0: col<0>(v); break;
340  case 1: col<1>(v); break;
341  case 2: col<2>(v); break;
342  default:
344  << "Invalid column access " << c << abort(FatalError);
345  }
346 }
347 
348 
349 template<class Cmpt>
350 inline void Foam::Tensor<Cmpt>::row
351 (
352  const direction r,
353  const Vector<Cmpt>& v
354 )
355 {
356  switch (r)
357  {
358  case 0: row<0>(v); break;
359  case 1: row<1>(v); break;
360  case 2: row<2>(v); break;
361  default:
363  << "Invalid row access " << r << abort(FatalError);
364  }
365 }
366 
367 
368 template<class Cmpt>
370 {
371  return Vector<Cmpt>(this->v_[XX], this->v_[YY], this->v_[ZZ]);
372 }
373 
374 
375 template<class Cmpt>
377 {
378  this->v_[XX] = v.x(); this->v_[YY] = v.y(); this->v_[ZZ] = v.z();
379 }
380 
381 
382 template<class Cmpt>
383 inline bool Foam::Tensor<Cmpt>::is_identity(const scalar tol) const
384 {
385  return
386  (
387  mag(xx() - pTraits<Cmpt>::one) < tol
388  && mag(yy() - pTraits<Cmpt>::one) < tol
389  && mag(zz() - pTraits<Cmpt>::one) < tol
390  && mag(xy()) < tol && mag(xz()) < tol
391  && mag(yx()) < tol && mag(yz()) < tol
392  && mag(zx()) < tol && mag(zy()) < tol
393  );
394 }
395 
396 
397 // * * * * * * * * * * * * * * * Member Operations * * * * * * * * * * * * * //
398 
399 template<class Cmpt>
401 {
402  return Tensor<Cmpt>
403  (
404  xx(), yx(), zx(),
405  xy(), yy(), zy(),
406  xz(), yz(), zz()
407  );
408 }
409 
410 
411 template<class Cmpt>
412 inline Foam::Tensor<Cmpt>
414 {
415  const Tensor<Cmpt>& t1 = *this;
416 
417  return Tensor<Cmpt>
418  (
419  t1.xx()*t2.xx() + t1.xy()*t2.yx() + t1.xz()*t2.zx(),
420  t1.xx()*t2.xy() + t1.xy()*t2.yy() + t1.xz()*t2.zy(),
421  t1.xx()*t2.xz() + t1.xy()*t2.yz() + t1.xz()*t2.zz(),
422 
423  t1.yx()*t2.xx() + t1.yy()*t2.yx() + t1.yz()*t2.zx(),
424  t1.yx()*t2.xy() + t1.yy()*t2.yy() + t1.yz()*t2.zy(),
425  t1.yx()*t2.xz() + t1.yy()*t2.yz() + t1.yz()*t2.zz(),
426 
427  t1.zx()*t2.xx() + t1.zy()*t2.yx() + t1.zz()*t2.zx(),
428  t1.zx()*t2.xy() + t1.zy()*t2.yy() + t1.zz()*t2.zy(),
429  t1.zx()*t2.xz() + t1.zy()*t2.yz() + t1.zz()*t2.zz()
430  );
431 }
432 
433 
434 template<class Cmpt>
435 inline Foam::Tensor<Cmpt>
437 {
438  const Tensor<Cmpt>& t1 = *this;
439 
440  return Tensor<Cmpt>
441  (
442  t1.xx()*t2.xx(), t1.xy()*t2.xy(), t1.xz()*t2.xz(),
443  t1.yx()*t2.yx(), t1.yy()*t2.yy(), t1.yz()*t2.yz(),
444  t1.zx()*t2.zx(), t1.zy()*t2.zy(), t1.zz()*t2.zz()
445  );
446 }
447 
448 
449 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
450 
451 template<class Cmpt>
452 inline void Foam::Tensor<Cmpt>::operator&=(const Tensor<Cmpt>& t)
453 {
454  *this = this->inner(t);
455 }
456 
457 
458 template<class Cmpt>
459 template<class Cmpt2>
460 inline void Foam::Tensor<Cmpt>::operator=
461 (
462  const VectorSpace<Tensor<Cmpt2>, Cmpt2, 9>& vs
463 )
464 {
465  VectorSpace<Tensor<Cmpt>, Cmpt, 9>::operator=(vs);
466 }
467 
468 
469 template<class Cmpt>
471 {
472  this->v_[XX] = st.ii(); this->v_[XY] = Zero; this->v_[XZ] = Zero;
473  this->v_[YX] = Zero; this->v_[YY] = st.ii(); this->v_[YZ] = Zero;
474  this->v_[ZX] = Zero; this->v_[ZY] = Zero; this->v_[ZZ] = st.ii();
475 }
476 
477 
478 template<class Cmpt>
479 inline void Foam::Tensor<Cmpt>::operator=(const SymmTensor<Cmpt>& st)
480 {
481  this->v_[XX] = st.xx(); this->v_[XY] = st.xy(); this->v_[XZ] = st.xz();
482  this->v_[YX] = st.xy(); this->v_[YY] = st.yy(); this->v_[YZ] = st.yz();
483  this->v_[ZX] = st.xz(); this->v_[ZY] = st.yz(); this->v_[ZZ] = st.zz();
484 }
485 
486 
487 template<class Cmpt>
489 {
490  this->v_[XX] = tr.x().x();
491  this->v_[XY] = tr.x().y();
492  this->v_[XZ] = tr.x().z();
493 
494  this->v_[YX] = tr.y().x();
495  this->v_[YY] = tr.y().y();
496  this->v_[YZ] = tr.y().z();
497 
498  this->v_[ZX] = tr.z().x();
499  this->v_[ZY] = tr.z().y();
500  this->v_[ZZ] = tr.z().z();
501 }
502 
503 
504 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
505 
506 namespace Foam
507 {
509 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
510 
511 //- Return the trace of a Tensor
512 template<class Cmpt>
513 inline Cmpt tr(const Tensor<Cmpt>& t)
514 {
515  return t.xx() + t.yy() + t.zz();
516 }
517 
519 //- Return the spherical part of a Tensor
520 template<class Cmpt>
521 inline SphericalTensor<Cmpt> sph(const Tensor<Cmpt>& t)
522 {
523  return SphericalTensor<Cmpt>
524  (
525  (1.0/3.0)*tr(t)
526  );
527 }
528 
529 
530 //- Return the symmetric part of a Tensor
531 template<class Cmpt>
532 inline SymmTensor<Cmpt> symm(const Tensor<Cmpt>& t)
533 {
534  return SymmTensor<Cmpt>
535  (
536  t.xx(), 0.5*(t.xy() + t.yx()), 0.5*(t.xz() + t.zx()),
537  t.yy(), 0.5*(t.yz() + t.zy()),
538  t.zz()
539  );
540 }
541 
542 
543 //- Return twice the symmetric part of a Tensor
544 template<class Cmpt>
545 inline SymmTensor<Cmpt> twoSymm(const Tensor<Cmpt>& t)
546 {
547  return SymmTensor<Cmpt>
548  (
549  2*t.xx(), (t.xy() + t.yx()), (t.xz() + t.zx()),
550  2*t.yy(), (t.yz() + t.zy()),
551  2*t.zz()
552  );
553 }
554 
555 
556 //- Return the skew-symmetric part of a Tensor
557 template<class Cmpt>
558 inline Tensor<Cmpt> skew(const Tensor<Cmpt>& t)
559 {
560  return Tensor<Cmpt>
561  (
562  Zero, 0.5*(t.xy() - t.yx()), 0.5*(t.xz() - t.zx()),
563  0.5*(t.yx() - t.xy()), Zero, 0.5*(t.yz() - t.zy()),
564  0.5*(t.zx() - t.xz()), 0.5*(t.zy() - t.yz()), Zero
565  );
566 }
567 
568 
569 //- Return the skew-symmetric part of a SymmTensor as a Tensor
570 template<class Cmpt>
571 inline const Tensor<Cmpt>& skew(const SymmTensor<Cmpt>& st)
572 {
573  return Tensor<Cmpt>::zero;
574 }
575 
577 //- Return the deviatoric part of a Tensor
578 template<class Cmpt>
579 inline Tensor<Cmpt> dev(const Tensor<Cmpt>& t)
580 {
581  return t - sph(t);
582 }
583 
584 
585 //- Return the two-third deviatoric part of a Tensor
586 template<class Cmpt>
587 inline Tensor<Cmpt> dev2(const Tensor<Cmpt>& t)
588 {
589  return t - 2*sph(t);
590 }
591 
592 
593 //- Return the determinant of a Tensor
594 template<class Cmpt>
595 inline Cmpt det(const Tensor<Cmpt>& t)
596 {
597  return
598  (
599  t.xx()*t.yy()*t.zz() + t.xy()*t.yz()*t.zx()
600  + t.xz()*t.yx()*t.zy() - t.xx()*t.yz()*t.zy()
601  - t.xy()*t.yx()*t.zz() - t.xz()*t.yy()*t.zx()
602  );
603 }
604 
605 
606 //- Return the cofactor Tensor of a Tensor
607 template<class Cmpt>
608 inline Tensor<Cmpt> cof(const Tensor<Cmpt>& t)
609 {
610  return Tensor<Cmpt>
611  (
612  t.yy()*t.zz() - t.zy()*t.yz(),
613  t.zx()*t.yz() - t.yx()*t.zz(),
614  t.yx()*t.zy() - t.yy()*t.zx(),
615 
616  t.xz()*t.zy() - t.xy()*t.zz(),
617  t.xx()*t.zz() - t.xz()*t.zx(),
618  t.xy()*t.zx() - t.xx()*t.zy(),
619 
620  t.xy()*t.yz() - t.xz()*t.yy(),
621  t.yx()*t.xz() - t.xx()*t.yz(),
622  t.xx()*t.yy() - t.yx()*t.xy()
623  );
624 }
625 
626 
627 //- Return the inverse of a Tensor by using the given determinant
628 template<class Cmpt>
629 inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t, const Cmpt dett)
630 {
631  #ifdef FULLDEBUG
632  if (mag(dett) < VSMALL)
633  {
635  << "Tensor is not invertible due to the (almost) zero determinant:"
636  << " Tensor = " << t << nl
637  << " det(Tensor) = " << dett
638  << abort(FatalError);
639  }
640  #endif
641 
642  return cof(t).T()/dett;
643 }
645 
646 //- Return the inverse of a Tensor
647 template<class Cmpt>
648 inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t)
649 {
650  return inv(t, det(t));
651 }
652 
653 
654 //- Return the inverse of this Tensor
655 template<class Cmpt>
656 inline Tensor<Cmpt> Tensor<Cmpt>::inv() const
657 {
658  return Foam::inv(*this);
659 }
660 
661 
662 //- Return the 1st invariant of a Tensor
663 template<class Cmpt>
664 inline Cmpt invariantI(const Tensor<Cmpt>& t)
665 {
666  return tr(t);
667 }
668 
669 
670 //- Return the 2nd invariant of a Tensor
671 template<class Cmpt>
672 inline Cmpt invariantII(const Tensor<Cmpt>& t)
673 {
674  return
675  (
676  t.xx()*t.yy() + t.yy()*t.zz() + t.xx()*t.zz()
677  - t.xy()*t.yx() - t.yz()*t.zy() - t.xz()*t.zx()
678  );
679 }
680 
681 
682 //- Return the 3rd invariant of a Tensor
683 template<class Cmpt>
684 inline Cmpt invariantIII(const Tensor<Cmpt>& t)
685 {
686  return det(t);
687 }
688 
689 
690 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
691 
692 //- Sum of a SphericalTensor and a Tensor
693 template<class Cmpt>
694 inline Tensor<Cmpt>
696 {
697  return Tensor<Cmpt>
698  (
699  st1.ii() + t2.xx(), t2.xy(), t2.xz(),
700  t2.yx(), st1.ii() + t2.yy(), t2.yz(),
701  t2.zx(), t2.zy(), st1.ii() + t2.zz()
702  );
703 }
704 
705 
706 //- Sum of a Tensor and a SphericalTensor
707 template<class Cmpt>
708 inline Tensor<Cmpt>
710 {
711  return Tensor<Cmpt>
712  (
713  t1.xx() + st2.ii(), t1.xy(), t1.xz(),
714  t1.yx(), t1.yy() + st2.ii(), t1.yz(),
715  t1.zx(), t1.zy(), t1.zz() + st2.ii()
716  );
717 }
718 
719 
720 //- Sum of a SymmTensor and a Tensor
721 template<class Cmpt>
723 operator+(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
724 {
725  return Tensor<Cmpt>
726  (
727  st1.xx() + t2.xx(), st1.xy() + t2.xy(), st1.xz() + t2.xz(),
728  st1.xy() + t2.yx(), st1.yy() + t2.yy(), st1.yz() + t2.yz(),
729  st1.xz() + t2.zx(), st1.yz() + t2.zy(), st1.zz() + t2.zz()
730  );
731 }
732 
733 
734 //- Sum of a Tensor and a SymmTensor
735 template<class Cmpt>
736 inline Tensor<Cmpt>
737 operator+(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
738 {
739  return Tensor<Cmpt>
740  (
741  t1.xx() + st2.xx(), t1.xy() + st2.xy(), t1.xz() + st2.xz(),
742  t1.yx() + st2.xy(), t1.yy() + st2.yy(), t1.yz() + st2.yz(),
743  t1.zx() + st2.xz(), t1.zy() + st2.yz(), t1.zz() + st2.zz()
744  );
745 }
746 
747 
748 //- Subtract a Tensor from a SphericalTensor
749 template<class Cmpt>
750 inline Tensor<Cmpt>
751 operator-(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
752 {
753  return Tensor<Cmpt>
754  (
755  st1.ii() - t2.xx(), -t2.xy(), -t2.xz(),
756  -t2.yx(), st1.ii() - t2.yy(), -t2.yz(),
757  -t2.zx(), -t2.zy(), st1.ii() - t2.zz()
758  );
759 }
760 
761 
762 //- Subtract a SphericalTensor from a Tensor
763 template<class Cmpt>
764 inline Tensor<Cmpt>
765 operator-(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
766 {
767  return Tensor<Cmpt>
768  (
769  t1.xx() - st2.ii(), t1.xy(), t1.xz(),
770  t1.yx(), t1.yy() - st2.ii(), t1.yz(),
771  t1.zx(), t1.zy(), t1.zz() - st2.ii()
772  );
773 }
774 
775 
776 //- Subtract a Tensor from a SymmTensor
777 template<class Cmpt>
778 inline Tensor<Cmpt>
779 operator-(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
780 {
781  return Tensor<Cmpt>
782  (
783  st1.xx() - t2.xx(), st1.xy() - t2.xy(), st1.xz() - t2.xz(),
784  st1.xy() - t2.yx(), st1.yy() - t2.yy(), st1.yz() - t2.yz(),
785  st1.xz() - t2.zx(), st1.yz() - t2.zy(), st1.zz() - t2.zz()
786  );
787 }
788 
789 
790 //- Subtract a SymmTensor from a Tensor
791 template<class Cmpt>
792 inline Tensor<Cmpt>
793 operator-(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
794 {
795  return Tensor<Cmpt>
796  (
797  t1.xx() - st2.xx(), t1.xy() - st2.xy(), t1.xz() - st2.xz(),
798  t1.yx() - st2.xy(), t1.yy() - st2.yy(), t1.yz() - st2.yz(),
799  t1.zx() - st2.xz(), t1.zy() - st2.yz(), t1.zz() - st2.zz()
800  );
801 }
803 
804 //- Return the Hodge dual of a Tensor as a Vector
805 template<class Cmpt>
806 inline Vector<Cmpt> operator*(const Tensor<Cmpt>& t)
807 {
808  return Vector<Cmpt>(t.yz(), -t.xz(), t.xy());
809 }
810 
811 
812 //- Return the Hodge dual of a Vector as a Tensor
813 template<class Cmpt>
814 inline Tensor<Cmpt> operator*(const Vector<Cmpt>& v)
815 {
816  return Tensor<Cmpt>
817  (
818  Zero, -v.z(), v.y(),
819  v.z(), Zero, -v.x(),
820  -v.y(), v.x(), Zero
821  );
822 }
823 
824 
825 //- Division of a Vector by a Tensor
826 template<class Cmpt>
827 inline typename innerProduct<Vector<Cmpt>, Tensor<Cmpt>>::type
828 operator/(const Vector<Cmpt>& v, const Tensor<Cmpt>& t)
829 {
830  return inv(t) & v;
831 }
832 
833 
834 //- Division of a Tensor by a Cmpt
835 template<class Cmpt>
836 inline Tensor<Cmpt>
837 operator/(const Tensor<Cmpt>& t, const Cmpt s)
838 {
839  #ifdef FULLDEBUG
840  if (mag(s) < VSMALL)
841  {
843  << "Tensor = " << t
844  << " is not divisible due to a zero value in Cmpt:"
845  << "Cmpt = " << s
846  << abort(FatalError);
847  }
848  #endif
850  return Tensor<Cmpt>
851  (
852  t.xx()/s, t.xy()/s, t.xz()/s,
853  t.yx()/s, t.yy()/s, t.yz()/s,
854  t.zx()/s, t.zy()/s, t.zz()/s
855  );
856 }
857 
858 
859 //- Inner-product of a Tensor and a Tensor
860 template<class Cmpt>
862 operator&(const Tensor<Cmpt>& t1, const Tensor<Cmpt>& t2)
863 {
864  return t1.inner(t2);
865 }
866 
867 
868 //- Inner-product of a SphericalTensor and a Tensor
869 template<class Cmpt>
870 inline Tensor<Cmpt>
871 operator&(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
872 {
873  return Tensor<Cmpt>
874  (
875  st1.ii()*t2.xx(), st1.ii()*t2.xy(), st1.ii()*t2.xz(),
876  st1.ii()*t2.yx(), st1.ii()*t2.yy(), st1.ii()*t2.yz(),
877  st1.ii()*t2.zx(), st1.ii()*t2.zy(), st1.ii()*t2.zz()
878  );
879 }
880 
881 
882 //- Inner-product of a Tensor and a SphericalTensor
883 template<class Cmpt>
884 inline Tensor<Cmpt>
885 operator&(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
886 {
887  return Tensor<Cmpt>
888  (
889  t1.xx()*st2.ii(), t1.xy()*st2.ii(), t1.xz()*st2.ii(),
890  t1.yx()*st2.ii(), t1.yy()*st2.ii(), t1.yz()*st2.ii(),
891  t1.zx()*st2.ii(), t1.zy()*st2.ii(), t1.zz()*st2.ii()
892  );
893 }
894 
895 
896 //- Inner-product of a SymmTensor and a Tensor
897 template<class Cmpt>
898 inline Tensor<Cmpt>
899 operator&(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
900 {
901  return Tensor<Cmpt>
902  (
903  st1.xx()*t2.xx() + st1.xy()*t2.yx() + st1.xz()*t2.zx(),
904  st1.xx()*t2.xy() + st1.xy()*t2.yy() + st1.xz()*t2.zy(),
905  st1.xx()*t2.xz() + st1.xy()*t2.yz() + st1.xz()*t2.zz(),
906 
907  st1.xy()*t2.xx() + st1.yy()*t2.yx() + st1.yz()*t2.zx(),
908  st1.xy()*t2.xy() + st1.yy()*t2.yy() + st1.yz()*t2.zy(),
909  st1.xy()*t2.xz() + st1.yy()*t2.yz() + st1.yz()*t2.zz(),
910 
911  st1.xz()*t2.xx() + st1.yz()*t2.yx() + st1.zz()*t2.zx(),
912  st1.xz()*t2.xy() + st1.yz()*t2.yy() + st1.zz()*t2.zy(),
913  st1.xz()*t2.xz() + st1.yz()*t2.yz() + st1.zz()*t2.zz()
914  );
915 }
916 
917 
918 //- Inner-product of a Tensor and a SymmTensor
919 template<class Cmpt>
920 inline Tensor<Cmpt>
921 operator&(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
922 {
923  return Tensor<Cmpt>
924  (
925  t1.xx()*st2.xx() + t1.xy()*st2.xy() + t1.xz()*st2.xz(),
926  t1.xx()*st2.xy() + t1.xy()*st2.yy() + t1.xz()*st2.yz(),
927  t1.xx()*st2.xz() + t1.xy()*st2.yz() + t1.xz()*st2.zz(),
928 
929  t1.yx()*st2.xx() + t1.yy()*st2.xy() + t1.yz()*st2.xz(),
930  t1.yx()*st2.xy() + t1.yy()*st2.yy() + t1.yz()*st2.yz(),
931  t1.yx()*st2.xz() + t1.yy()*st2.yz() + t1.yz()*st2.zz(),
932 
933  t1.zx()*st2.xx() + t1.zy()*st2.xy() + t1.zz()*st2.xz(),
934  t1.zx()*st2.xy() + t1.zy()*st2.yy() + t1.zz()*st2.yz(),
935  t1.zx()*st2.xz() + t1.zy()*st2.yz() + t1.zz()*st2.zz()
936  );
937 }
938 
939 
940 //- Inner-product of a Tensor and a Vector
941 template<class Cmpt>
942 #if defined(__GNUC__) && !defined(__clang__)
943 // Workaround for gcc (11+) that fails to handle tensor dot vector
944 __attribute__((optimize("no-tree-vectorize")))
945 #endif
946 inline Vector<Cmpt>
947 operator&(const Tensor<Cmpt>& t, const Vector<Cmpt>& v)
948 {
949  return Vector<Cmpt>
950  (
951  t.xx()*v.x() + t.xy()*v.y() + t.xz()*v.z(),
952  t.yx()*v.x() + t.yy()*v.y() + t.yz()*v.z(),
953  t.zx()*v.x() + t.zy()*v.y() + t.zz()*v.z()
954  );
955 }
957 
958 //- Inner-product of a Vector and a Tensor
959 template<class Cmpt>
960 inline Vector<Cmpt>
961 operator&(const Vector<Cmpt>& v, const Tensor<Cmpt>& t)
962 {
963  return Vector<Cmpt>
964  (
965  v.x()*t.xx() + v.y()*t.yx() + v.z()*t.zx(),
966  v.x()*t.xy() + v.y()*t.yy() + v.z()*t.zy(),
967  v.x()*t.xz() + v.y()*t.yz() + v.z()*t.zz()
968  );
969 }
970 
971 
972 //- Double-inner-product of a SphericalTensor and a Tensor
973 template<class Cmpt>
974 inline Cmpt
975 operator&&(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
976 {
977  return (st1.ii()*t2.xx() + st1.ii()*t2.yy() + st1.ii()*t2.zz());
978 }
979 
981 //- Double-inner-product of a Tensor and a SphericalTensor
982 template<class Cmpt>
983 inline Cmpt
984 operator&&(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
985 {
986  return (t1.xx()*st2.ii() + t1.yy()*st2.ii() + t1.zz()*st2.ii());
987 }
988 
989 
990 //- Double-inner-product of a SymmTensor and a Tensor
991 template<class Cmpt>
992 inline Cmpt
993 operator&&(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
994 {
995  return
996  (
997  st1.xx()*t2.xx() + st1.xy()*t2.xy() + st1.xz()*t2.xz() +
998  st1.xy()*t2.yx() + st1.yy()*t2.yy() + st1.yz()*t2.yz() +
999  st1.xz()*t2.zx() + st1.yz()*t2.zy() + st1.zz()*t2.zz()
1000  );
1001 }
1002 
1003 
1004 //- Double-inner-product of a Tensor and a SymmTensor
1005 template<class Cmpt>
1006 inline Cmpt
1007 operator&&(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
1009  return
1010  (
1011  t1.xx()*st2.xx() + t1.xy()*st2.xy() + t1.xz()*st2.xz() +
1012  t1.yx()*st2.xy() + t1.yy()*st2.yy() + t1.yz()*st2.yz() +
1013  t1.zx()*st2.xz() + t1.zy()*st2.yz() + t1.zz()*st2.zz()
1014  );
1015 }
1016 
1017 
1018 //- Outer-product of a Vector and a Vector
1019 template<class Cmpt>
1020 inline typename outerProduct<Vector<Cmpt>, Vector<Cmpt>>::type
1021 operator*(const Vector<Cmpt>& v1, const Vector<Cmpt>& v2)
1022 {
1023  return Tensor<Cmpt>
1024  (
1025  v1.x()*v2.x(), v1.x()*v2.y(), v1.x()*v2.z(),
1026  v1.y()*v2.x(), v1.y()*v2.y(), v1.y()*v2.z(),
1027  v1.z()*v2.x(), v1.z()*v2.y(), v1.z()*v2.z()
1028  );
1029 }
1030 
1031 
1032 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1033 
1034 template<class Cmpt>
1035 class typeOfSum<SphericalTensor<Cmpt>, Tensor<Cmpt>>
1036 {
1037 public:
1038 
1039  typedef Tensor<Cmpt> type;
1040 };
1041 
1042 
1043 template<class Cmpt>
1044 class typeOfSum<Tensor<Cmpt>, SphericalTensor<Cmpt>>
1045 {
1046 public:
1047 
1048  typedef Tensor<Cmpt> type;
1049 };
1050 
1052 template<class Cmpt>
1053 class innerProduct<SphericalTensor<Cmpt>, Tensor<Cmpt>>
1054 {
1055 public:
1056 
1057  typedef Tensor<Cmpt> type;
1058 };
1059 
1060 
1061 template<class Cmpt>
1063 {
1064 public:
1065 
1066  typedef Tensor<Cmpt> type;
1067 };
1068 
1069 
1070 template<class Cmpt>
1071 class typeOfSum<SymmTensor<Cmpt>, Tensor<Cmpt>>
1072 {
1073 public:
1074 
1075  typedef Tensor<Cmpt> type;
1076 };
1077 
1079 template<class Cmpt>
1080 class typeOfSum<Tensor<Cmpt>, SymmTensor<Cmpt>>
1081 {
1082 public:
1083 
1084  typedef Tensor<Cmpt> type;
1085 };
1086 
1087 
1088 template<class Cmpt>
1089 class innerProduct<SymmTensor<Cmpt>, Tensor<Cmpt>>
1090 {
1091 public:
1092 
1093  typedef Tensor<Cmpt> type;
1094 };
1095 
1096 
1097 template<class Cmpt>
1098 class innerProduct<Tensor<Cmpt>, SymmTensor<Cmpt>>
1099 {
1100 public:
1101 
1102  typedef Tensor<Cmpt> type;
1103 };
1104 
1105 
1106 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1107 
1108 } // End namespace Foam
1109 
1110 // ************************************************************************* //
Cmpt invariantII(const SymmTensor< Cmpt > &st)
Return the 2nd invariant of a SymmTensor.
Definition: SymmTensorI.H:375
Cmpt tr(const Tensor< Cmpt > &t)
Return the trace of a Tensor.
Definition: TensorI.H:508
const Cmpt & xz() const noexcept
Definition: SymmTensor.H:152
uint8_t direction
Definition: direction.H:46
Vector< Cmpt > cx() const
Extract vector for column 0.
Definition: TensorI.H:167
A templated (3 x 3) symmetric tensor of objects of <T>, effectively containing 6 elements, derived from VectorSpace.
Definition: SymmTensor.H:50
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
const Cmpt & yx() const noexcept
Definition: Tensor.H:196
dimensionedTensor skew(const dimensionedTensor &dt)
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Vector< Cmpt > cz() const
Extract vector for column 2.
Definition: TensorI.H:181
Tensor< Cmpt > T() const
Return non-Hermitian transpose.
Definition: TensorI.H:393
Vector< Cmpt > x() const
Extract vector for row 0.
Definition: TensorI.H:146
A traits class, which is primarily used for primitives.
Definition: pTraits.H:50
const Cmpt & xy() const noexcept
Definition: Tensor.H:194
Templated vector space.
Definition: VectorSpace.H:52
dimensionSet operator &&(const dimensionSet &ds1, const dimensionSet &ds2)
dimensionedScalar operator/(const scalar s1, const dimensionedScalar &ds2)
Vector< Cmpt > y() const
Extract vector for row 1.
Definition: TensorI.H:153
const Cmpt & y() const noexcept
Access to the vector y component.
Definition: Vector.H:140
dimensionedScalar det(const dimensionedSphericalTensor &dt)
SphericalTensor< Cmpt > sph(const DiagTensor< Cmpt > &dt)
Return the spherical part of a DiagTensor as a SphericalTensor.
Definition: DiagTensorI.H:87
Templated matrix space.
Definition: MatrixSpace.H:54
tmp< faMatrix< Type > > operator+(const faMatrix< Type > &, const faMatrix< Type > &)
Tensor()=default
Default construct.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
const Cmpt & zz() const noexcept
Definition: SymmTensor.H:158
A templated (3 x 3) diagonal tensor of objects of <T>, effectively containing 1 element, derived from VectorSpace.
Vector< Cmpt > z() const
Extract vector for row 2.
Definition: TensorI.H:160
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:752
scalar y
const Cmpt & yz() const noexcept
Definition: Tensor.H:198
const Cmpt & xx() const noexcept
Definition: Tensor.H:193
const Cmpt & yy() const noexcept
Definition: Tensor.H:197
void cols(const Vector< Cmpt > &x, const Vector< Cmpt > &y, const Vector< Cmpt > &z)
Set column values.
Definition: TensorI.H:297
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)
Vector< Cmpt > col() const
Extract vector for given column: compile-time check of index.
tmp< faMatrix< Type > > operator*(const areaScalarField::Internal &, const faMatrix< Type > &)
bool is_identity(const scalar tol=ROOTVSMALL) const
Is identity tensor?
Definition: TensorI.H:376
Cmpt invariantIII(const SymmTensor< Cmpt > &st)
Return the 3rd invariant of a SymmTensor.
Definition: SymmTensorI.H:389
const Cmpt & zx() const noexcept
Definition: Tensor.H:199
const Cmpt & ii() const noexcept
const Cmpt & xx() const noexcept
Definition: SymmTensor.H:150
void rows(const Vector< Cmpt > &x, const Vector< Cmpt > &y, const Vector< Cmpt > &z)
Set row values.
Definition: TensorI.H:311
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
errorManip< error > abort(error &err)
Definition: errorManip.H:139
tmp< faMatrix< Type > > operator-(const faMatrix< Type > &)
Unary negation.
Creates a single block of cells from point coordinates, numbers of cells in each direction and an exp...
Definition: block.H:54
Templated 3D Vector derived from VectorSpace adding construction from 3 components, element access using x(), y() and z() member functions and the inner-product (dot-product) and cross-product operators.
Definition: Vector.H:58
const Cmpt & x() const noexcept
Access to the vector x component.
Definition: Vector.H:135
dimensioned< Type > T() const
Return transpose.
const Cmpt & zy() const noexcept
Definition: Tensor.H:200
Tensor< Cmpt > schur(const Tensor< Cmpt > &t2) const
Schur-product of this with another Tensor.
Definition: TensorI.H:429
Tensor & operator=(const Tensor &)=default
Copy assignment.
const Cmpt & z() const noexcept
Access to the vector z component.
Definition: Vector.H:145
Tensor< Cmpt > inv() const
Return inverse.
Definition: TensorI.H:675
dimensionedSymmTensor dev2(const dimensionedSymmTensor &dt)
Vector< Cmpt > diag() const
Extract the diagonal as a vector.
Definition: TensorI.H:362
const Cmpt & yy() const noexcept
Definition: SymmTensor.H:154
const Cmpt & zz() const noexcept
Definition: Tensor.H:201
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
tmp< GeometricField< Type, faPatchField, areaMesh > > operator &(const faMatrix< Type > &, const DimensionedField< Type, areaMesh > &)
const dimensionedScalar c
Speed of light in a vacuum.
Cmpt invariantI(const SymmTensor< Cmpt > &st)
Return the 1st invariant of a SymmTensor.
Definition: SymmTensorI.H:365
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:58
void operator &=(const Tensor< Cmpt > &t)
Assign inner-product of this with another Tensor.
A templated (3 x 3) tensor of objects of <T> derived from MatrixSpace.
Definition: complexI.H:268
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const Cmpt & xz() const noexcept
Definition: Tensor.H:195
Tensor< Cmpt > inner(const Tensor< Cmpt > &t2) const
Inner-product of this with another Tensor.
Definition: TensorI.H:406
typeOfRank< typename pTraits< arg1 >::cmptType, direction(pTraits< arg1 >::rank)+direction(pTraits< arg2 >::rank) - 2 >::type type
Definition: products.H:155
dimensionedSymmTensor cof(const dimensionedSymmTensor &dt)
Vector< Cmpt > cy() const
Extract vector for column 1.
Definition: TensorI.H:174
const Cmpt & xy() const noexcept
Definition: SymmTensor.H:151
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157
Vector< Cmpt > row() const
Extract vector for given row: compile-time check of index.
const Cmpt & yz() const noexcept
Definition: SymmTensor.H:155