initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / OpenFOAM / primitives / Tensor / TensorI.H
blob71e7c0c76732a91728311840f2a0233d811bf80a
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
29 namespace Foam
32 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
34 //- Construct null
35 template <class Cmpt>
36 inline Tensor<Cmpt>::Tensor()
40 //- Construct given VectorSpace
41 template <class Cmpt>
42 inline Tensor<Cmpt>::Tensor(const VectorSpace<Tensor<Cmpt>, Cmpt, 9>& vs)
44     VectorSpace<Tensor<Cmpt>, Cmpt, 9>(vs)
48 //- Construct given SphericalTensor
49 template <class Cmpt>
50 inline Tensor<Cmpt>::Tensor(const SphericalTensor<Cmpt>& st)
52     this->v_[XX] = st.ii(); this->v_[XY] = 0; this->v_[XZ] = 0;
53     this->v_[YX] = 0; this->v_[YY] = st.ii(); this->v_[YZ] = 0;
54     this->v_[ZX] = 0; this->v_[ZY] = 0; this->v_[ZZ] = st.ii();
58 //- Construct given SymmTensor
59 template <class Cmpt>
60 inline Tensor<Cmpt>::Tensor(const SymmTensor<Cmpt>& st)
62     this->v_[XX] = st.xx(); this->v_[XY] = st.xy(); this->v_[XZ] = st.xz();
63     this->v_[YX] = st.xy(); this->v_[YY] = st.yy(); this->v_[YZ] = st.yz();
64     this->v_[ZX] = st.xz(); this->v_[ZY] = st.yz(); this->v_[ZZ] = st.zz();
68 //- Construct from components
69 template <class Cmpt>
70 inline Tensor<Cmpt>::Tensor
72     const Cmpt txx, const Cmpt txy, const Cmpt txz,
73     const Cmpt tyx, const Cmpt tyy, const Cmpt tyz,
74     const Cmpt tzx, const Cmpt tzy, const Cmpt tzz
77     this->v_[XX] = txx; this->v_[XY] = txy; this->v_[XZ] = txz;
78     this->v_[YX] = tyx; this->v_[YY] = tyy; this->v_[YZ] = tyz;
79     this->v_[ZX] = tzx; this->v_[ZY] = tzy; this->v_[ZZ] = tzz;
83 //- Construct from Istream
84 template <class Cmpt>
85 inline Tensor<Cmpt>::Tensor(Istream& is)
87     VectorSpace<Tensor<Cmpt>, Cmpt, 9>(is)
91 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
93 template <class Cmpt>
94 inline const Vector<Cmpt>&  Tensor<Cmpt>::x() const
96     return reinterpret_cast<const Vector<Cmpt>&>(this->v_[XX]);
99 template <class Cmpt>
100 inline const Vector<Cmpt>&  Tensor<Cmpt>::y() const
102     return reinterpret_cast<const Vector<Cmpt>&>(this->v_[YX]);
105 template <class Cmpt>
106 inline const Vector<Cmpt>&  Tensor<Cmpt>::z() const
108     return reinterpret_cast<const Vector<Cmpt>&>(this->v_[ZX]);
112 template <class Cmpt>
113 inline Vector<Cmpt>&  Tensor<Cmpt>::x()
115     return reinterpret_cast<Vector<Cmpt>&>(this->v_[XX]);
118 template <class Cmpt>
119 inline Vector<Cmpt>&  Tensor<Cmpt>::y()
121     return reinterpret_cast<Vector<Cmpt>&>(this->v_[YX]);
124 template <class Cmpt>
125 inline Vector<Cmpt>&  Tensor<Cmpt>::z()
127     return reinterpret_cast<Vector<Cmpt>&>(this->v_[ZX]);
131 template <class Cmpt>
132 inline const Cmpt&  Tensor<Cmpt>::xx() const
134     return this->v_[XX];
137 template <class Cmpt>
138 inline const Cmpt&  Tensor<Cmpt>::xy() const
140     return this->v_[XY];
143 template <class Cmpt>
144 inline const Cmpt&  Tensor<Cmpt>::xz() const
146     return this->v_[XZ];
150 template <class Cmpt>
151 inline const Cmpt&  Tensor<Cmpt>::yx() const
153     return this->v_[YX];
156 template <class Cmpt>
157 inline const Cmpt&  Tensor<Cmpt>::yy() const
159     return this->v_[YY];
162 template <class Cmpt>
163 inline const Cmpt&  Tensor<Cmpt>::yz() const
165     return this->v_[YZ];
169 template <class Cmpt>
170 inline const Cmpt&  Tensor<Cmpt>::zx() const
172     return this->v_[ZX];
175 template <class Cmpt>
176 inline const Cmpt&  Tensor<Cmpt>::zy() const
178     return this->v_[ZY];
181 template <class Cmpt>
182 inline const Cmpt&  Tensor<Cmpt>::zz() const
184     return this->v_[ZZ];
188 template <class Cmpt>
189 inline Cmpt& Tensor<Cmpt>::xx()
191     return this->v_[XX];
194 template <class Cmpt>
195 inline Cmpt& Tensor<Cmpt>::xy()
197     return this->v_[XY];
200 template <class Cmpt>
201 inline Cmpt& Tensor<Cmpt>::xz()
203     return this->v_[XZ];
207 template <class Cmpt>
208 inline Cmpt& Tensor<Cmpt>::yx()
210     return this->v_[YX];
213 template <class Cmpt>
214 inline Cmpt& Tensor<Cmpt>::yy()
216     return this->v_[YY];
219 template <class Cmpt>
220 inline Cmpt& Tensor<Cmpt>::yz()
222     return this->v_[YZ];
226 template <class Cmpt>
227 inline Cmpt& Tensor<Cmpt>::zx()
229     return this->v_[ZX];
232 template <class Cmpt>
233 inline Cmpt& Tensor<Cmpt>::zy()
235     return this->v_[ZY];
238 template <class Cmpt>
239 inline Cmpt& Tensor<Cmpt>::zz()
241     return this->v_[ZZ];
245 //- Return tensor transpose
246 template <class Cmpt>
247 inline Tensor<Cmpt> Tensor<Cmpt>::T() const
249     return Tensor<Cmpt>
250     (
251         xx(), yx(), zx(),
252         xy(), yy(), zy(),
253         xz(), yz(), zz()
254     );
258 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
260 template <class Cmpt>
261 inline void Tensor<Cmpt>::operator=(const SphericalTensor<Cmpt>& st)
263     this->v_[XX] = st.ii(); this->v_[XY] = 0; this->v_[XZ] = 0;
264     this->v_[YX] = 0; this->v_[YY] = st.ii(); this->v_[YZ] = 0;
265     this->v_[ZX] = 0; this->v_[ZY] = 0; this->v_[ZZ] = st.ii();
269 template <class Cmpt>
270 inline void Tensor<Cmpt>::operator=(const SymmTensor<Cmpt>& st)
272     this->v_[XX] = st.xx(); this->v_[XY] = st.xy(); this->v_[XZ] = st.xz();
273     this->v_[YX] = st.xy(); this->v_[YY] = st.yy(); this->v_[YZ] = st.yz();
274     this->v_[ZX] = st.xz(); this->v_[ZY] = st.yz(); this->v_[ZZ] = st.zz();
278 // * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
280 //- Hodge Dual operator (tensor -> vector)
281 template <class Cmpt>
282 inline Vector<Cmpt> operator*(const Tensor<Cmpt>& t)
284     return Vector<Cmpt>(t.yz(), -t.xz(), t.xy());
288 //- Hodge Dual operator (vector -> tensor)
289 template <class Cmpt>
290 inline Tensor<Cmpt> operator*(const Vector<Cmpt>& v)
292     return Tensor<Cmpt>
293     (
294              0, -v.z(),   v.y(),
295          v.z(),      0,  -v.x(),
296         -v.y(),  v.x(),       0
297     );
301 //- Inner-product between two tensors
302 template <class Cmpt>
303 inline typename innerProduct<Tensor<Cmpt>, Tensor<Cmpt> >::type
304 operator&(const Tensor<Cmpt>& t1, const Tensor<Cmpt>& t2)
306     return Tensor<Cmpt>
307     (
308         t1.xx()*t2.xx() + t1.xy()*t2.yx() + t1.xz()*t2.zx(),
309         t1.xx()*t2.xy() + t1.xy()*t2.yy() + t1.xz()*t2.zy(),
310         t1.xx()*t2.xz() + t1.xy()*t2.yz() + t1.xz()*t2.zz(),
312         t1.yx()*t2.xx() + t1.yy()*t2.yx() + t1.yz()*t2.zx(),
313         t1.yx()*t2.xy() + t1.yy()*t2.yy() + t1.yz()*t2.zy(),
314         t1.yx()*t2.xz() + t1.yy()*t2.yz() + t1.yz()*t2.zz(),
316         t1.zx()*t2.xx() + t1.zy()*t2.yx() + t1.zz()*t2.zx(),
317         t1.zx()*t2.xy() + t1.zy()*t2.yy() + t1.zz()*t2.zy(),
318         t1.zx()*t2.xz() + t1.zy()*t2.yz() + t1.zz()*t2.zz()
319     );
323 //- Inner-product between a tensor and a vector
324 template <class Cmpt>
325 inline typename innerProduct<Tensor<Cmpt>, Vector<Cmpt> >::type
326 operator&(const Tensor<Cmpt>& t, const Vector<Cmpt>& v)
328     return Vector<Cmpt>
329     (
330         t.xx()*v.x() + t.xy()*v.y() + t.xz()*v.z(),
331         t.yx()*v.x() + t.yy()*v.y() + t.yz()*v.z(),
332         t.zx()*v.x() + t.zy()*v.y() + t.zz()*v.z()
333     );
337 //- Inner-product between a vector and a tensor
338 template <class Cmpt>
339 inline typename innerProduct<Vector<Cmpt>, Tensor<Cmpt> >::type
340 operator&(const Vector<Cmpt>& v, const Tensor<Cmpt>& t)
342     return Vector<Cmpt>
343     (
344         v.x()*t.xx() + v.y()*t.yx() + v.z()*t.zx(),
345         v.x()*t.xy() + v.y()*t.yy() + v.z()*t.zy(),
346         v.x()*t.xz() + v.y()*t.yz() + v.z()*t.zz()
347     );
351 //- Outer-product between two vectors
352 template <class Cmpt>
353 inline typename outerProduct<Vector<Cmpt>, Vector<Cmpt> >::type
354 operator*(const Vector<Cmpt>& v1, const Vector<Cmpt>& v2)
356     return Tensor<Cmpt>
357     (
358         v1.x()*v2.x(), v1.x()*v2.y(), v1.x()*v2.z(),
359         v1.y()*v2.x(), v1.y()*v2.y(), v1.y()*v2.z(),
360         v1.z()*v2.x(), v1.z()*v2.y(), v1.z()*v2.z()
361     );
365 //- Division of a vector by a tensor, i.e. dot-product with the tensor inverse
366 template <class Cmpt>
367 inline typename innerProduct<Vector<Cmpt>, Tensor<Cmpt> >::type
368 operator/(const Vector<Cmpt>& v, const Tensor<Cmpt>& t)
370     return inv(t) & v;
374 // * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
376 //- Return the trace of a tensor
377 template <class Cmpt>
378 inline Cmpt tr(const Tensor<Cmpt>& t)
380     return t.xx() + t.yy() + t.zz();
384 //- Return the spherical part of a tensor
385 template <class Cmpt>
386 inline SphericalTensor<Cmpt> sph(const Tensor<Cmpt>& t)
388     return (1.0/3.0)*tr(t);
392 //- Return the symmetric part of a tensor
393 template <class Cmpt>
394 inline SymmTensor<Cmpt> symm(const Tensor<Cmpt>& t)
396     return SymmTensor<Cmpt>
397     (
398         t.xx(), 0.5*(t.xy() + t.yx()), 0.5*(t.xz() + t.zx()),
399                 t.yy(),                0.5*(t.yz() + t.zy()),
400                                        t.zz()
401     );
405 //- Return twice the symmetric part of a tensor
406 template <class Cmpt>
407 inline SymmTensor<Cmpt> twoSymm(const Tensor<Cmpt>& t)
409     return SymmTensor<Cmpt>
410     (
411         2*t.xx(), (t.xy() + t.yx()), (t.xz() + t.zx()),
412                   2*t.yy(),          (t.yz() + t.zy()),
413                                      2*t.zz()
414     );
418 //- Return the skew-symmetric part of a tensor
419 template <class Cmpt>
420 inline Tensor<Cmpt> skew(const Tensor<Cmpt>& t)
422     return Tensor<Cmpt>
423     (
424         0.0, 0.5*(t.xy() - t.yx()), 0.5*(t.xz() - t.zx()),
425         0.5*(t.yx() - t.xy()), 0.0, 0.5*(t.yz() - t.zy()),
426         0.5*(t.zx() - t.xz()), 0.5*(t.zy() - t.yz()), 0.0
427     );
431 //- Return the skew-symmetric part of a symmetric tensor
432 template <class Cmpt>
433 inline const Tensor<Cmpt>& skew(const SymmTensor<Cmpt>& st)
435     return Tensor<Cmpt>::zero;
439 //- Return the deviatoric part of a tensor
440 template <class Cmpt>
441 inline Tensor<Cmpt> dev(const Tensor<Cmpt>& t)
443     return t - SphericalTensor<Cmpt>::oneThirdI*tr(t);
447 //- Return the deviatoric part of a tensor
448 template <class Cmpt>
449 inline Tensor<Cmpt> dev2(const Tensor<Cmpt>& t)
451     return t - SphericalTensor<Cmpt>::twoThirdsI*tr(t);
455 //- Return the determinant of a tensor
456 template <class Cmpt>
457 inline Cmpt det(const Tensor<Cmpt>& t)
459     return
460     (
461         t.xx()*t.yy()*t.zz() + t.xy()*t.yz()*t.zx()
462       + t.xz()*t.yx()*t.zy() - t.xx()*t.yz()*t.zy()
463       - t.xy()*t.yx()*t.zz() - t.xz()*t.yy()*t.zx()
464     );
468 //- Return the cofactor tensor of a tensor
469 template <class Cmpt>
470 inline Tensor<Cmpt> cof(const Tensor<Cmpt>& t)
472     return Tensor<Cmpt>
473     (
474         t.yy()*t.zz() - t.zy()*t.yz(),
475         t.zx()*t.yz() - t.yx()*t.zz(),
476         t.yx()*t.zy() - t.yy()*t.zx(),
478         t.xz()*t.zy() - t.xy()*t.zz(),
479         t.xx()*t.zz() - t.xz()*t.zx(),
480         t.xy()*t.zx() - t.xx()*t.zy(),
482         t.xy()*t.yz() - t.xz()*t.yy(),
483         t.yx()*t.xz() - t.xx()*t.yz(),
484         t.xx()*t.yy() - t.yx()*t.xy()
485     );
489 //- Return the inverse of a tensor give the determinant
490 template <class Cmpt>
491 inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t, const Cmpt dett)
493     return Tensor<Cmpt>
494     (
495         t.yy()*t.zz() - t.zy()*t.yz(),
496         t.xz()*t.zy() - t.xy()*t.zz(),
497         t.xy()*t.yz() - t.xz()*t.yy(),
499         t.zx()*t.yz() - t.yx()*t.zz(),
500         t.xx()*t.zz() - t.xz()*t.zx(),
501         t.yx()*t.xz() - t.xx()*t.yz(),
503         t.yx()*t.zy() - t.yy()*t.zx(),
504         t.xy()*t.zx() - t.xx()*t.zy(),
505         t.xx()*t.yy() - t.yx()*t.xy()
506     )/dett;
510 //- Return the inverse of a tensor
511 template <class Cmpt>
512 inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t)
514     return inv(t, det(t));
518 //- Return the 1st invariant of a tensor
519 template <class Cmpt>
520 inline Cmpt invariantI(const Tensor<Cmpt>& t)
522     return tr(t);
526 //- Return the 2nd invariant of a tensor
527 template <class Cmpt>
528 inline Cmpt invariantII(const Tensor<Cmpt>& t)
530     return
531     (
532         0.5*sqr(tr(t))
533       - 0.5*
534         (
535            t.xx()*t.xx() + t.xy()*t.xy() + t.xz()*t.xz()
536          + t.yx()*t.yx() + t.yy()*t.yy() + t.yz()*t.yz()
537          + t.zx()*t.zx() + t.zy()*t.zy() + t.zz()*t.zz()
538         )
539     );
543 //- Return the 3rd invariant of a tensor
544 template <class Cmpt>
545 inline Cmpt invariantIII(const Tensor<Cmpt>& t)
547     return det(t);
551 // * * * * * * * * * Mixed Tensor SphericalTensor Operators  * * * * * * * * //
553 template <class Cmpt>
554 inline Tensor<Cmpt>
555 operator+(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
557     return Tensor<Cmpt>
558     (
559         st1.ii() + t2.xx(), t2.xy(),            t2.xz(),
560         t2.yx(),            st1.ii() + t2.yy(), t2.yz(),
561         t2.zx(),            t2.zy(),            st1.ii() + t2.zz()
562     );
566 template <class Cmpt>
567 inline Tensor<Cmpt>
568 operator+(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
570     return Tensor<Cmpt>
571     (
572         t1.xx() + st2.ii(), t1.xy(),            t1.xz(),
573         t1.yx(),            t1.yy() + st2.ii(), t1.yz(),
574         t1.zx(),            t1.zy(),            t1.zz() + st2.ii()
575     );
579 template <class Cmpt>
580 inline Tensor<Cmpt>
581 operator-(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
583     return Tensor<Cmpt>
584     (
585         st1.ii() - t2.xx(), -t2.xy(),            -t2.xz(),
586        -t2.yx(),             st1.ii() - t2.yy(), -t2.yz(),
587        -t2.zx(),            -t2.zy(),             st1.ii() - t2.zz()
588     );
592 template <class Cmpt>
593 inline Tensor<Cmpt>
594 operator-(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
596     return Tensor<Cmpt>
597     (
598         t1.xx() - st2.ii(), t1.xy(),            t1.xz(),
599         t1.yx(),            t1.yy() - st2.ii(), t1.yz(),
600         t1.zx(),            t1.zy(),            t1.zz() - st2.ii()
601     );
605 //- Inner-product between a spherical tensor and a tensor
606 template <class Cmpt>
607 inline Tensor<Cmpt>
608 operator&(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
610     return Tensor<Cmpt>
611     (
612         st1.ii()*t2.xx(), st1.ii()*t2.xy(), st1.ii()*t2.xz(),
613         st1.ii()*t2.yx(), st1.ii()*t2.yy(), st1.ii()*t2.yz(),
614         st1.ii()*t2.zx(), st1.ii()*t2.zy(), st1.ii()*t2.zz()
615     );
619 //- Inner-product between a tensor and a spherical tensor
620 template <class Cmpt>
621 inline Tensor<Cmpt>
622 operator&(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
624     return Tensor<Cmpt>
625     (
626         t1.xx()*st2.ii(), t1.xy()*st2.ii(), t1.xz()*st2.ii(),
627         t1.yx()*st2.ii(), t1.yy()*st2.ii(), t1.yz()*st2.ii(),
628         t1.zx()*st2.ii(), t1.zy()*st2.ii(), t1.zz()*st2.ii()
629     );
633 //- Double-dot-product between a spherical tensor and a tensor
634 template <class Cmpt>
635 inline Cmpt
636 operator&&(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
638     return(st1.ii()*t2.xx() + st1.ii()*t2.yy() + st1.ii()*t2.zz());
642 //- Double-dot-product between a tensor and a spherical tensor
643 template <class Cmpt>
644 inline Cmpt
645 operator&&(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
647     return(t1.xx()*st2.ii() + t1.yy()*st2.ii() + t1.zz()*st2.ii());
650 template<class Cmpt>
651 class typeOfSum<SphericalTensor<Cmpt>, Tensor<Cmpt> >
653 public:
655     typedef Tensor<Cmpt> type;
658 template<class Cmpt>
659 class typeOfSum<Tensor<Cmpt>, SphericalTensor<Cmpt> >
661 public:
663     typedef Tensor<Cmpt> type;
666 template<class Cmpt>
667 class innerProduct<SphericalTensor<Cmpt>, Tensor<Cmpt> >
669 public:
671     typedef Tensor<Cmpt> type;
674 template<class Cmpt>
675 class innerProduct<Tensor<Cmpt>, SphericalTensor<Cmpt> >
677 public:
679     typedef Tensor<Cmpt> type;
683 // * * * * * * * * * * Mixed Tensor SymmTensor Operators * * * * * * * * * * //
685 template <class Cmpt>
686 inline Tensor<Cmpt>
687 operator+(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
689     return Tensor<Cmpt>
690     (
691         st1.xx() + t2.xx(), st1.xy() + t2.xy(), st1.xz() + t2.xz(),
692         st1.xy() + t2.yx(), st1.yy() + t2.yy(), st1.yz() + t2.yz(),
693         st1.xz() + t2.zx(), st1.yz() + t2.zy(), st1.zz() + t2.zz()
694     );
698 template <class Cmpt>
699 inline Tensor<Cmpt>
700 operator+(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
702     return Tensor<Cmpt>
703     (
704         t1.xx() + st2.xx(), t1.xy() + st2.xy(), t1.xz() + st2.xz(),
705         t1.yx() + st2.xy(), t1.yy() + st2.yy(), t1.yz() + st2.yz(),
706         t1.zx() + st2.xz(), t1.zy() + st2.yz(), t1.zz() + st2.zz()
707     );
711 template <class Cmpt>
712 inline Tensor<Cmpt>
713 operator-(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
715     return Tensor<Cmpt>
716     (
717         st1.xx() - t2.xx(), st1.xy() - t2.xy(), st1.xz() - t2.xz(),
718         st1.xy() - t2.yx(), st1.yy() - t2.yy(), st1.yz() - t2.yz(),
719         st1.xz() - t2.zx(), st1.yz() - t2.zy(), st1.zz() - t2.zz()
720     );
724 template <class Cmpt>
725 inline Tensor<Cmpt>
726 operator-(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
728     return Tensor<Cmpt>
729     (
730         t1.xx() - st2.xx(), t1.xy() - st2.xy(), t1.xz() - st2.xz(),
731         t1.yx() - st2.xy(), t1.yy() - st2.yy(), t1.yz() - st2.yz(),
732         t1.zx() - st2.xz(), t1.zy() - st2.yz(), t1.zz() - st2.zz()
733     );
737 //- Inner-product between a spherical tensor and a tensor
738 template <class Cmpt>
739 inline Tensor<Cmpt>
740 operator&(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
742     return Tensor<Cmpt>
743     (
744         st1.xx()*t2.xx() + st1.xy()*t2.yx() + st1.xz()*t2.zx(),
745         st1.xx()*t2.xy() + st1.xy()*t2.yy() + st1.xz()*t2.zy(),
746         st1.xx()*t2.xz() + st1.xy()*t2.yz() + st1.xz()*t2.zz(),
748         st1.xy()*t2.xx() + st1.yy()*t2.yx() + st1.yz()*t2.zx(),
749         st1.xy()*t2.xy() + st1.yy()*t2.yy() + st1.yz()*t2.zy(),
750         st1.xy()*t2.xz() + st1.yy()*t2.yz() + st1.yz()*t2.zz(),
752         st1.xz()*t2.xx() + st1.yz()*t2.yx() + st1.zz()*t2.zx(),
753         st1.xz()*t2.xy() + st1.yz()*t2.yy() + st1.zz()*t2.zy(),
754         st1.xz()*t2.xz() + st1.yz()*t2.yz() + st1.zz()*t2.zz()
755     );
759 //- Inner-product between a tensor and a spherical tensor
760 template <class Cmpt>
761 inline Tensor<Cmpt>
762 operator&(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
764     return Tensor<Cmpt>
765     (
766         t1.xx()*st2.xx() + t1.xy()*st2.xy() + t1.xz()*st2.xz(),
767         t1.xx()*st2.xy() + t1.xy()*st2.yy() + t1.xz()*st2.yz(),
768         t1.xx()*st2.xz() + t1.xy()*st2.yz() + t1.xz()*st2.zz(),
770         t1.yx()*st2.xx() + t1.yy()*st2.xy() + t1.yz()*st2.xz(),
771         t1.yx()*st2.xy() + t1.yy()*st2.yy() + t1.yz()*st2.yz(),
772         t1.yx()*st2.xz() + t1.yy()*st2.yz() + t1.yz()*st2.zz(),
774         t1.zx()*st2.xx() + t1.zy()*st2.xy() + t1.zz()*st2.xz(),
775         t1.zx()*st2.xy() + t1.zy()*st2.yy() + t1.zz()*st2.yz(),
776         t1.zx()*st2.xz() + t1.zy()*st2.yz() + t1.zz()*st2.zz()
777     );
781 //- Double-dot-product between a spherical tensor and a tensor
782 template <class Cmpt>
783 inline Cmpt
784 operator&&(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
786     return
787     (
788         st1.xx()*t2.xx() + st1.xy()*t2.xy() + st1.xz()*t2.xz() +
789         st1.xy()*t2.yx() + st1.yy()*t2.yy() + st1.yz()*t2.yz() +
790         st1.xz()*t2.zx() + st1.yz()*t2.zy() + st1.zz()*t2.zz()
791     );
795 //- Double-dot-product between a tensor and a spherical tensor
796 template <class Cmpt>
797 inline Cmpt
798 operator&&(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
800     return
801     (
802         t1.xx()*st2.xx() + t1.xy()*st2.xy() + t1.xz()*st2.xz() +
803         t1.yx()*st2.xy() + t1.yy()*st2.yy() + t1.yz()*st2.yz() +
804         t1.zx()*st2.xz() + t1.zy()*st2.yz() + t1.zz()*st2.zz()
805     );
808 template<class Cmpt>
809 class typeOfSum<SymmTensor<Cmpt>, Tensor<Cmpt> >
811 public:
813     typedef Tensor<Cmpt> type;
816 template<class Cmpt>
817 class typeOfSum<Tensor<Cmpt>, SymmTensor<Cmpt> >
819 public:
821     typedef Tensor<Cmpt> type;
825 template<class Cmpt>
826 class innerProduct<SymmTensor<Cmpt>, Tensor<Cmpt> >
828 public:
830     typedef Tensor<Cmpt> type;
833 template<class Cmpt>
834 class innerProduct<Tensor<Cmpt>, SymmTensor<Cmpt> >
836 public:
838     typedef Tensor<Cmpt> type;
842 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
844 } // End namespace Foam
846 // ************************************************************************* //