ENH: define transform(symmTensor, int/float) as no-op

- avoids implicit promotion of label to scalar for no-op,
  or alternatively promotion of symmTensor to tensor for no-op
  (ie, ambiguous).

- fix incorrect transform(.., symmTensor, ...) declarations.
This commit is contained in:
Mark Olesen
2023-01-13 18:15:13 +01:00
parent 0fa129e83c
commit a50d32b587
11 changed files with 271 additions and 175 deletions

View File

@ -36,8 +36,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef transformFieldField_H #ifndef Foam_transformFieldField_H
#define transformFieldField_H #define Foam_transformFieldField_H
#include "transform.H" #include "transform.H"
#include "tensorFieldField.H" #include "tensorFieldField.H"

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -28,132 +29,130 @@ License
#include "symmTransformField.H" #include "symmTransformField.H"
#include "FieldM.H" #include "FieldM.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
template<class Type> template<class Type>
void transform void Foam::transform
( (
Field<Type>& rtf, Field<Type>& result,
const symmTensorField& trf, const symmTensor& rot,
const Field<Type>& tf const Field<Type>& fld
) )
{ {
if (trf.size() == 1) TFOR_ALL_F_OP_FUNC_S_F
(
Type, result, =, transform, symmTensor, rot, Type, fld
);
}
template<class Type>
void Foam::transform
(
Field<Type>& result,
const symmTensorField& rot,
const Field<Type>& fld
)
{
if (rot.size() == 1)
{ {
return transform(rtf, trf[0], tf); return transform(result, rot.front(), fld);
}
else
{
TFOR_ALL_F_OP_FUNC_F_F
(
Type, rtf, =, transform, symmTensor, trf, Type, tf
)
} }
TFOR_ALL_F_OP_FUNC_F_F
(
Type, result, =, transform, symmTensor, rot, Type, fld
);
} }
template<class Type> template<class Type>
tmp<Field<Type>> transform Foam::tmp<Foam::Field<Type>>
Foam::transform
( (
const symmTensorField& trf, const symmTensorField& rot,
const Field<Type>& tf const Field<Type>& fld
) )
{ {
auto tresult = tmp<Field<Type>>::New(tf.size()); auto tresult = tmp<Field<Type>>::New(fld.size());
transform(tresult.ref(), trf, tf); transform(tresult.ref(), rot, fld);
return tresult; return tresult;
} }
template<class Type> template<class Type>
tmp<Field<Type>> transform Foam::tmp<Foam::Field<Type>>
Foam::transform
( (
const symmTensorField& trf, const symmTensorField& rot,
const tmp<Field<Type>>& ttf const tmp<Field<Type>>& tfld
) )
{ {
tmp<Field<Type>> tresult = New(ttf); tmp<Field<Type>> tresult = New(tfld);
transform(tresult.ref(), trf, ttf()); transform(tresult.ref(), rot, tfld());
ttf.clear(); tfld.clear();
return tresult; return tresult;
} }
template<class Type> template<class Type>
tmp<Field<Type>> transform Foam::tmp<Foam::Field<Type>>
Foam::transform
( (
const tmp<symmTensorField>& ttrf, const tmp<symmTensorField>& trot,
const Field<Type>& tf const Field<Type>& fld
) )
{ {
auto tresult = tmp<Field<Type>>::New(tf.size()); auto tresult = tmp<Field<Type>>::New(fld.size());
transform(tresult.ref(), ttrf(), tf); transform(tresult.ref(), trot(), fld);
ttrf.clear(); trot.clear();
return tresult; return tresult;
} }
template<class Type> template<class Type>
tmp<Field<Type>> transform Foam::tmp<Foam::Field<Type>>
Foam::transform
( (
const tmp<symmTensorField>& ttrf, const tmp<symmTensorField>& trot,
const tmp<Field<Type>>& ttf const tmp<Field<Type>>& tfld
) )
{ {
tmp<Field<Type>> tresult = New(ttf); tmp<Field<Type>> tresult = New(tfld);
transform(tresult.ref(), ttrf(), ttf()); transform(tresult.ref(), trot(), tfld());
ttf.clear(); trot.clear();
ttrf.clear(); tfld.clear();
return tresult; return tresult;
} }
template<class Type> template<class Type>
void transform Foam::tmp<Foam::Field<Type>>
Foam::transform
( (
Field<Type>& rtf, const symmTensor& rot,
const symmTensor& t, const Field<Type>& fld
const Field<Type>& tf
) )
{ {
TFOR_ALL_F_OP_FUNC_S_F(Type, rtf, =, transform, tensor, t, Type, tf) auto tresult = tmp<Field<Type>>::New(fld.size());
} transform(tresult.ref(), rot, fld);
template<class Type>
tmp<Field<Type>> transform
(
const symmTensor& t,
const Field<Type>& tf
)
{
auto tresult = tmp<Field<Type>>::New(tf.size());
transform(tresult.ref(), t, tf);
return tresult; return tresult;
} }
template<class Type> template<class Type>
tmp<Field<Type>> transform Foam::tmp<Foam::Field<Type>>
Foam::transform
( (
const symmTensor& t, const symmTensor& rot,
const tmp<Field<Type>>& ttf const tmp<Field<Type>>& tfld
) )
{ {
tmp<Field<Type>> tresult = New(ttf); tmp<Field<Type>> tresult = New(tfld);
transform(tresult.ref(), t, ttf()); transform(tresult.ref(), rot, tfld());
ttf.clear(); tfld.clear();
return tresult; return tresult;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,8 +35,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef symmTransformField_H #ifndef Foam_symmTransformField_H
#define symmTransformField_H #define Foam_symmTransformField_H
#include "symmTransform.H" #include "symmTransform.H"
#include "symmTensorField.H" #include "symmTensorField.H"
@ -48,73 +49,96 @@ namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> // transform()
void transform(Field<Type>&, const symmTensorField&, const Field<Type>&);
template<class Type> template<class Type>
tmp<Field<Type>> transform(const symmTensorField&, const Field<Type>&); void transform
(
Field<Type>& result,
const symmTensor& rot,
const Field<Type>& fld
);
template<class Type> template<class Type>
tmp<Field<Type>> transform(const symmTensorField&, const tmp<Field<Type>>&); void transform
(
Field<Type>& result,
const symmTensorField& rot,
const Field<Type>& fld
);
template<class Type>
tmp<Field<Type>> transform(const tmp<symmTensorField>&, const Field<Type>&);
template<class Type> template<class Type>
tmp<Field<Type>> transform tmp<Field<Type>> transform
( (
const tmp<symmTensorField>&, const symmTensorField& rot,
const tmp<Field<Type>>& const Field<Type>& fld
);
template<class Type>
tmp<Field<Type>> transform
(
const symmTensorField& rot,
const tmp<Field<Type>>& tfld
);
template<class Type>
tmp<Field<Type>> transform
(
const tmp<symmTensorField>& trot,
const Field<Type>& tfld
);
template<class Type>
tmp<Field<Type>> transform
(
const tmp<symmTensorField>& trot,
const tmp<Field<Type>>& tfld
); );
template<class Type> template<class Type>
void transform(Field<Type>&, const tensor&, const Field<Type>&); tmp<Field<Type>> transform
(
const symmTensor& rot,
const Field<Type>& fld
);
template<class Type> template<class Type>
tmp<Field<Type>> transform(const tensor&, const Field<Type>&); tmp<Field<Type>> transform
template<class Type>
tmp<Field<Type>> transform(const tensor&, const tmp<Field<Type>>&);
template<>
tmp<Field<sphericalTensor>> transformFieldMask<sphericalTensor>
( (
const symmTensorField& const symmTensor& rot,
); const tmp<Field<Type>>& tfld
template<>
tmp<Field<sphericalTensor>> transformFieldMask<sphericalTensor>
(
const tmp<symmTensorField>&
); );
template<> // Specializations
tmp<Field<symmTensor>> transformFieldMask<symmTensor>
(
const symmTensorField&
);
template<> template<>
tmp<Field<symmTensor>> transformFieldMask<symmTensor> tmp<Field<sphericalTensor>>
( transformFieldMask<sphericalTensor>(const symmTensorField&);
const tmp<symmTensorField>&
); template<>
tmp<Field<sphericalTensor>>
transformFieldMask<sphericalTensor>(const tmp<symmTensorField>&);
template<> template<>
tmp<Field<tensor>> transformFieldMask<tensor> tmp<Field<symmTensor>>
( transformFieldMask<symmTensor>(const symmTensorField&);
const symmTensorField&
);
template<> template<>
tmp<Field<tensor>> transformFieldMask<tensor> tmp<Field<symmTensor>>
( transformFieldMask<symmTensor>(const tmp<symmTensorField>&);
const tmp<symmTensorField>&
);
template<>
tmp<Field<tensor>>
transformFieldMask<tensor>(const symmTensorField&);
template<>
tmp<Field<tensor>>
transformFieldMask<tensor>(const tmp<symmTensorField>&);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -35,8 +35,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef transformField_H #ifndef Foam_transformField_H
#define transformField_H #define Foam_transformField_H
#include "transform.H" #include "transform.H"
#include "quaternion.H" #include "quaternion.H"
@ -177,6 +177,7 @@ tmp<Field<Type>> invTransform
); );
// transformFieldMask()
template<class Type1, class Type2> template<class Type1, class Type2>
tmp<Field<Type1>> transformFieldMask(const Field<Type2>& fld); tmp<Field<Type1>> transformFieldMask(const Field<Type2>& fld);

View File

@ -56,7 +56,7 @@ void Foam::transform
{ {
if (rot.size() == 1) if (rot.size() == 1)
{ {
return transform(result, rot.first(), fld); return transform(result, rot.front(), fld);
} }
TFOR_ALL_F_OP_FUNC_F_F TFOR_ALL_F_OP_FUNC_F_F
@ -180,7 +180,7 @@ void Foam::invTransform
{ {
if (rot.size() == 1) if (rot.size() == 1)
{ {
return invTransform(result, rot.first(), fld); return invTransform(result, rot.front(), fld);
} }
TFOR_ALL_F_OP_FUNC_F_F TFOR_ALL_F_OP_FUNC_F_F

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd. Copyright (C) 2018-2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -37,9 +37,12 @@ Foam::List<T> Foam::transform
const UList<T>& field const UList<T>& field
) )
{ {
List<T> result(field.size()); const label loopLen = field.size();
forAll(field, i) List<T> result(loopLen);
/* pragmas... */
for (label i = 0; i < loopLen; ++i)
{ {
result[i] = transform(rotTensor, field[i]); result[i] = transform(rotTensor, field[i]);
} }
@ -51,7 +54,10 @@ Foam::List<T> Foam::transform
template<class T> template<class T>
void Foam::transformList(const tensor& rotTensor, UList<T>& field) void Foam::transformList(const tensor& rotTensor, UList<T>& field)
{ {
forAll(field, i) const label loopLen = field.size();
/* pragmas... */
for (label i = 0; i < loopLen; ++i)
{ {
field[i] = transform(rotTensor, field[i]); field[i] = transform(rotTensor, field[i]);
} }
@ -63,11 +69,14 @@ void Foam::transformList(const tensorField& rotTensor, UList<T>& field)
{ {
if (rotTensor.size() == 1) if (rotTensor.size() == 1)
{ {
transformList(rotTensor[0], field); transformList(rotTensor.front(), field);
} }
else if (rotTensor.size() == field.size()) else if (rotTensor.size() == field.size())
{ {
forAll(field, i) const label loopLen = field.size();
/* pragmas... */
for (label i = 0; i < loopLen; ++i)
{ {
field[i] = transform(rotTensor[i], field[i]); field[i] = transform(rotTensor[i], field[i]);
} }
@ -98,7 +107,7 @@ void Foam::transformList(const tensorField& rotTensor, Map<T>& field)
{ {
if (rotTensor.size() == 1) if (rotTensor.size() == 1)
{ {
transformList(rotTensor[0], field); transformList(rotTensor.front(), field);
} }
else else
{ {
@ -126,7 +135,7 @@ void Foam::transformList(const tensorField& rotTensor, EdgeMap<T>& field)
{ {
if (rotTensor.size() == 1) if (rotTensor.size() == 1)
{ {
transformList(rotTensor[0], field); transformList(rotTensor.front(), field);
} }
else else
{ {

View File

@ -35,8 +35,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef transformList_H #ifndef Foam_transformList_H
#define transformList_H #define Foam_transformList_H
#include "transform.H" #include "transform.H"
#include "List.H" #include "List.H"
@ -67,7 +67,7 @@ void transformList(const tensorField& rotTensor, UList<T>& field);
template<class T> template<class T>
void transformList(const tensor& rotTensor, Map<T>& field); void transformList(const tensor& rotTensor, Map<T>& field);
//- Inplace transform a Map of elements using one tensor per element. //- Inplace transform a Map of elements.
// Using multiple tensors is ill-defined (Fatal). // Using multiple tensors is ill-defined (Fatal).
template<class T> template<class T>
void transformList(const tensorField& rotTensor, Map<T>& field); void transformList(const tensorField& rotTensor, Map<T>& field);
@ -77,7 +77,7 @@ void transformList(const tensorField& rotTensor, Map<T>& field);
template<class T> template<class T>
void transformList(const tensor& rotTensor, EdgeMap<T>& field); void transformList(const tensor& rotTensor, EdgeMap<T>& field);
//- Inplace transform a Map of elements using one tensor per element. //- Inplace transform a Map of elements.
// Using multiple tensors is ill-defined (Fatal). // Using multiple tensors is ill-defined (Fatal).
template<class T> template<class T>
void transformList(const tensorField& rotTensor, EdgeMap<T>& field); void transformList(const tensorField& rotTensor, EdgeMap<T>& field);

View File

@ -35,8 +35,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef transformGeometricField_H #ifndef Foam_transformGeometricField_H
#define transformGeometricField_H #define Foam_transformGeometricField_H
#include "transform.H" #include "transform.H"
#include "GeometricField.H" #include "GeometricField.H"

View File

@ -274,6 +274,7 @@ inline const complex& sum(const complex& c)
template<class Cmpt> class Tensor; template<class Cmpt> class Tensor;
//- No-op rotational transform for complex
inline complex transform(const Tensor<scalar>&, const complex c) inline complex transform(const Tensor<scalar>&, const complex c)
{ {
return c; return c;

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,8 +32,8 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef symmTransform_H #ifndef Foam_symmTransform_H
#define symmTransform_H #define Foam_symmTransform_H
#include "transform.H" #include "transform.H"
@ -43,57 +44,84 @@ namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
inline scalar transform(const symmTensor&, const scalar s) //- No-op rotational transform for base types
template<class T>
constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
transform(const symmTensor&, const T val)
{ {
return s; return val;
} }
//- No-op rotational transform for spherical tensor
template<class Cmpt> template<class Cmpt>
inline Vector<Cmpt> transform(const symmTensor& stt, const Vector<Cmpt>& v) inline SphericalTensor<Cmpt> transform
(
const symmTensor&,
const SphericalTensor<Cmpt>& val
)
{ {
return stt & v; return val;
} }
//- Use rotational tensor to transform a vector
// Same as (rot & v)
template<class Cmpt>
inline Vector<Cmpt> transform(const symmTensor& tt, const Vector<Cmpt>& v)
{
return tt & v;
}
//- Use rotational tensor to transform a tensor.
// Same as (rot & input & rot.T())
template<class Cmpt> template<class Cmpt>
inline Tensor<Cmpt> transform(const symmTensor& stt, const Tensor<Cmpt>& t) inline Tensor<Cmpt> transform(const symmTensor& stt, const Tensor<Cmpt>& t)
{ {
//return stt & t & stt.T();
return Tensor<Cmpt> return Tensor<Cmpt>
( (
// xx:
(stt.xx()*t.xx() + stt.xy()*t.yx() + stt.xz()*t.zx())*stt.xx() (stt.xx()*t.xx() + stt.xy()*t.yx() + stt.xz()*t.zx())*stt.xx()
+ (stt.xx()*t.xy() + stt.xy()*t.yy() + stt.xz()*t.zy())*stt.xy() + (stt.xx()*t.xy() + stt.xy()*t.yy() + stt.xz()*t.zy())*stt.xy()
+ (stt.xx()*t.xz() + stt.xy()*t.yz() + stt.xz()*t.zz())*stt.xz(), + (stt.xx()*t.xz() + stt.xy()*t.yz() + stt.xz()*t.zz())*stt.xz(),
// xy:
(stt.xx()*t.xx() + stt.xy()*t.yx() + stt.xz()*t.zx())*stt.xy() (stt.xx()*t.xx() + stt.xy()*t.yx() + stt.xz()*t.zx())*stt.xy()
+ (stt.xx()*t.xy() + stt.xy()*t.yy() + stt.xz()*t.zy())*stt.yy() + (stt.xx()*t.xy() + stt.xy()*t.yy() + stt.xz()*t.zy())*stt.yy()
+ (stt.xx()*t.xz() + stt.xy()*t.yz() + stt.xz()*t.zz())*stt.yz(), + (stt.xx()*t.xz() + stt.xy()*t.yz() + stt.xz()*t.zz())*stt.yz(),
// xz:
(stt.xx()*t.xx() + stt.xy()*t.yx() + stt.xz()*t.zx())*stt.xz() (stt.xx()*t.xx() + stt.xy()*t.yx() + stt.xz()*t.zx())*stt.xz()
+ (stt.xx()*t.xy() + stt.xy()*t.yy() + stt.xz()*t.zy())*stt.yz() + (stt.xx()*t.xy() + stt.xy()*t.yy() + stt.xz()*t.zy())*stt.yz()
+ (stt.xx()*t.xz() + stt.xy()*t.yz() + stt.xz()*t.zz())*stt.zz(), + (stt.xx()*t.xz() + stt.xy()*t.yz() + stt.xz()*t.zz())*stt.zz(),
// yx:
(stt.xy()*t.xx() + stt.yy()*t.yx() + stt.yz()*t.zx())*stt.xx() (stt.xy()*t.xx() + stt.yy()*t.yx() + stt.yz()*t.zx())*stt.xx()
+ (stt.xy()*t.xy() + stt.yy()*t.yy() + stt.yz()*t.zy())*stt.xy() + (stt.xy()*t.xy() + stt.yy()*t.yy() + stt.yz()*t.zy())*stt.xy()
+ (stt.xy()*t.xz() + stt.yy()*t.yz() + stt.yz()*t.zz())*stt.xz(), + (stt.xy()*t.xz() + stt.yy()*t.yz() + stt.yz()*t.zz())*stt.xz(),
// yy:
(stt.xy()*t.xx() + stt.yy()*t.yx() + stt.yz()*t.zx())*stt.xy() (stt.xy()*t.xx() + stt.yy()*t.yx() + stt.yz()*t.zx())*stt.xy()
+ (stt.xy()*t.xy() + stt.yy()*t.yy() + stt.yz()*t.zy())*stt.yy() + (stt.xy()*t.xy() + stt.yy()*t.yy() + stt.yz()*t.zy())*stt.yy()
+ (stt.xy()*t.xz() + stt.yy()*t.yz() + stt.yz()*t.zz())*stt.yz(), + (stt.xy()*t.xz() + stt.yy()*t.yz() + stt.yz()*t.zz())*stt.yz(),
// yz:
(stt.xy()*t.xx() + stt.yy()*t.yx() + stt.yz()*t.zx())*stt.xz() (stt.xy()*t.xx() + stt.yy()*t.yx() + stt.yz()*t.zx())*stt.xz()
+ (stt.xy()*t.xy() + stt.yy()*t.yy() + stt.yz()*t.zy())*stt.yz() + (stt.xy()*t.xy() + stt.yy()*t.yy() + stt.yz()*t.zy())*stt.yz()
+ (stt.xy()*t.xz() + stt.yy()*t.yz() + stt.yz()*t.zz())*stt.zz(), + (stt.xy()*t.xz() + stt.yy()*t.yz() + stt.yz()*t.zz())*stt.zz(),
// zx:
(stt.xz()*t.xx() + stt.yz()*t.yx() + stt.zz()*t.zx())*stt.xx() (stt.xz()*t.xx() + stt.yz()*t.yx() + stt.zz()*t.zx())*stt.xx()
+ (stt.xz()*t.xy() + stt.yz()*t.yy() + stt.zz()*t.zy())*stt.xy() + (stt.xz()*t.xy() + stt.yz()*t.yy() + stt.zz()*t.zy())*stt.xy()
+ (stt.xz()*t.xz() + stt.yz()*t.yz() + stt.zz()*t.zz())*stt.xz(), + (stt.xz()*t.xz() + stt.yz()*t.yz() + stt.zz()*t.zz())*stt.xz(),
// zy:
(stt.xz()*t.xx() + stt.yz()*t.yx() + stt.zz()*t.zx())*stt.xy() (stt.xz()*t.xx() + stt.yz()*t.yx() + stt.zz()*t.zx())*stt.xy()
+ (stt.xz()*t.xy() + stt.yz()*t.yy() + stt.zz()*t.zy())*stt.yy() + (stt.xz()*t.xy() + stt.yz()*t.yy() + stt.zz()*t.zy())*stt.yy()
+ (stt.xz()*t.xz() + stt.yz()*t.yz() + stt.zz()*t.zz())*stt.yz(), + (stt.xz()*t.xz() + stt.yz()*t.yz() + stt.zz()*t.zz())*stt.yz(),
// zz:
(stt.xz()*t.xx() + stt.yz()*t.yx() + stt.zz()*t.zx())*stt.xz() (stt.xz()*t.xx() + stt.yz()*t.yx() + stt.zz()*t.zx())*stt.xz()
+ (stt.xz()*t.xy() + stt.yz()*t.yy() + stt.zz()*t.zy())*stt.yz() + (stt.xz()*t.xy() + stt.yz()*t.yy() + stt.zz()*t.zy())*stt.yz()
+ (stt.xz()*t.xz() + stt.yz()*t.yz() + stt.zz()*t.zz())*stt.zz() + (stt.xz()*t.xz() + stt.yz()*t.yz() + stt.zz()*t.zz())*stt.zz()
@ -101,17 +129,8 @@ inline Tensor<Cmpt> transform(const symmTensor& stt, const Tensor<Cmpt>& t)
} }
template<class Cmpt> //- Use rotational tensor to transform a symmTensor
inline SphericalTensor<Cmpt> transform // Same as (rot & input & rot.T())
(
const symmTensor& stt,
const SphericalTensor<Cmpt>& st
)
{
return st;
}
template<class Cmpt> template<class Cmpt>
inline SymmTensor<Cmpt> transform inline SymmTensor<Cmpt> transform
( (
@ -121,26 +140,32 @@ inline SymmTensor<Cmpt> transform
{ {
return SymmTensor<Cmpt> return SymmTensor<Cmpt>
( (
// xx:
(stt.xx()*st.xx() + stt.xy()*st.xy() + stt.xz()*st.xz())*stt.xx() (stt.xx()*st.xx() + stt.xy()*st.xy() + stt.xz()*st.xz())*stt.xx()
+ (stt.xx()*st.xy() + stt.xy()*st.yy() + stt.xz()*st.yz())*stt.xy() + (stt.xx()*st.xy() + stt.xy()*st.yy() + stt.xz()*st.yz())*stt.xy()
+ (stt.xx()*st.xz() + stt.xy()*st.yz() + stt.xz()*st.zz())*stt.xz(), + (stt.xx()*st.xz() + stt.xy()*st.yz() + stt.xz()*st.zz())*stt.xz(),
// xy:
(stt.xx()*st.xx() + stt.xy()*st.xy() + stt.xz()*st.xz())*stt.xy() (stt.xx()*st.xx() + stt.xy()*st.xy() + stt.xz()*st.xz())*stt.xy()
+ (stt.xx()*st.xy() + stt.xy()*st.yy() + stt.xz()*st.yz())*stt.yy() + (stt.xx()*st.xy() + stt.xy()*st.yy() + stt.xz()*st.yz())*stt.yy()
+ (stt.xx()*st.xz() + stt.xy()*st.yz() + stt.xz()*st.zz())*stt.yz(), + (stt.xx()*st.xz() + stt.xy()*st.yz() + stt.xz()*st.zz())*stt.yz(),
// xz:
(stt.xx()*st.xx() + stt.xy()*st.xy() + stt.xz()*st.xz())*stt.xz() (stt.xx()*st.xx() + stt.xy()*st.xy() + stt.xz()*st.xz())*stt.xz()
+ (stt.xx()*st.xy() + stt.xy()*st.yy() + stt.xz()*st.yz())*stt.yz() + (stt.xx()*st.xy() + stt.xy()*st.yy() + stt.xz()*st.yz())*stt.yz()
+ (stt.xx()*st.xz() + stt.xy()*st.yz() + stt.xz()*st.zz())*stt.zz(), + (stt.xx()*st.xz() + stt.xy()*st.yz() + stt.xz()*st.zz())*stt.zz(),
// yy:
(stt.xy()*st.xx() + stt.yy()*st.xy() + stt.yz()*st.xz())*stt.xy() (stt.xy()*st.xx() + stt.yy()*st.xy() + stt.yz()*st.xz())*stt.xy()
+ (stt.xy()*st.xy() + stt.yy()*st.yy() + stt.yz()*st.yz())*stt.yy() + (stt.xy()*st.xy() + stt.yy()*st.yy() + stt.yz()*st.yz())*stt.yy()
+ (stt.xy()*st.xz() + stt.yy()*st.yz() + stt.yz()*st.zz())*stt.yz(), + (stt.xy()*st.xz() + stt.yy()*st.yz() + stt.yz()*st.zz())*stt.yz(),
// yz:
(stt.xy()*st.xx() + stt.yy()*st.xy() + stt.yz()*st.xz())*stt.xz() (stt.xy()*st.xx() + stt.yy()*st.xy() + stt.yz()*st.xz())*stt.xz()
+ (stt.xy()*st.xy() + stt.yy()*st.yy() + stt.yz()*st.yz())*stt.yz() + (stt.xy()*st.xy() + stt.yy()*st.yy() + stt.yz()*st.yz())*stt.yz()
+ (stt.xy()*st.xz() + stt.yy()*st.yz() + stt.yz()*st.zz())*stt.zz(), + (stt.xy()*st.xz() + stt.yy()*st.yz() + stt.yz()*st.zz())*stt.zz(),
// zz:
(stt.xz()*st.xx() + stt.yz()*st.xy() + stt.zz()*st.xz())*stt.xz() (stt.xz()*st.xx() + stt.yz()*st.xy() + stt.zz()*st.xz())*stt.xz()
+ (stt.xz()*st.xy() + stt.yz()*st.yy() + stt.zz()*st.yz())*stt.yz() + (stt.xz()*st.xy() + stt.yz()*st.yy() + stt.zz()*st.yz())*stt.yz()
+ (stt.xz()*st.xz() + stt.yz()*st.yz() + stt.zz()*st.zz())*stt.zz() + (stt.xz()*st.xz() + stt.yz()*st.yz() + stt.zz()*st.zz())*stt.zz()
@ -148,6 +173,8 @@ inline SymmTensor<Cmpt> transform
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<> template<>
inline sphericalTensor transformMask<sphericalTensor>(const symmTensor& st) inline sphericalTensor transformMask<sphericalTensor>(const symmTensor& st)
{ {

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -146,6 +146,8 @@ inline tensor Ra(const vector& a, const scalar omega)
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- No-op rotational transform for base types //- No-op rotational transform for base types
template<class T> template<class T>
constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
@ -154,6 +156,19 @@ transform(const tensor&, const T val)
return val; return val;
} }
//- No-op rotational transform for spherical tensor
template<class Cmpt>
inline SphericalTensor<Cmpt> transform
(
const tensor&,
const SphericalTensor<Cmpt>& val
)
{
return val;
}
//- No-op inverse rotational transform for base types //- No-op inverse rotational transform for base types
template<class T> template<class T>
constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
@ -163,6 +178,18 @@ invTransform(const tensor&, const T val)
} }
//- No-op inverse rotational transform for spherical tensor
template<class Cmpt>
inline SphericalTensor<Cmpt> invTransform
(
const tensor&,
const SphericalTensor<Cmpt>& val
)
{
return val;
}
//- Use rotational tensor to transform a vector. //- Use rotational tensor to transform a vector.
// Same as (rot & v) // Same as (rot & v)
template<class Cmpt> template<class Cmpt>
@ -188,38 +215,47 @@ inline Tensor<Cmpt> transform(const tensor& tt, const Tensor<Cmpt>& t)
{ {
return Tensor<Cmpt> return Tensor<Cmpt>
( (
// xx:
(tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.xx() (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.xx()
+ (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.xy() + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.xy()
+ (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.xz(), + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.xz(),
// xy:
(tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.yx() (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.yx()
+ (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.yy() + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.yy()
+ (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.yz(), + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.yz(),
// xz:
(tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.zx() (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.zx()
+ (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.zy() + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.zy()
+ (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.zz(), + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.zz(),
// yx:
(tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.xx() (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.xx()
+ (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.xy() + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.xy()
+ (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.xz(), + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.xz(),
// yy:
(tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.yx() (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.yx()
+ (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.yy() + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.yy()
+ (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.yz(), + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.yz(),
// yz:
(tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.zx() (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.zx()
+ (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.zy() + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.zy()
+ (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.zz(), + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.zz(),
// zx:
(tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.xx() (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.xx()
+ (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.xy() + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.xy()
+ (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.xz(), + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.xz(),
// zy:
(tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.yx() (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.yx()
+ (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.yy() + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.yy()
+ (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.yz(), + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.yz(),
// zz:
(tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.zx() (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.zx()
+ (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.zy() + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.zy()
+ (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.zz() + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.zz()
@ -234,38 +270,47 @@ inline Tensor<Cmpt> invTransform(const tensor& tt, const Tensor<Cmpt>& t)
{ {
return Tensor<Cmpt> return Tensor<Cmpt>
( (
// xx:
(tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xx() (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xx()
+ (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yx() + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yx()
+ (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zx(), + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zx(),
// xy:
(tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xy() (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xy()
+ (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yy() + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yy()
+ (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zy(), + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zy(),
// xz:
(tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xz() (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xz()
+ (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yz() + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yz()
+ (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zz(), + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zz(),
// yx:
(tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xx() (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xx()
+ (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yx() + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yx()
+ (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zx(), + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zx(),
// yy:
(tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xy() (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xy()
+ (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yy() + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yy()
+ (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zy(), + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zy(),
// yz:
(tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xz() (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xz()
+ (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yz() + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yz()
+ (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zz(), + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zz(),
// zx:
(tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xx() (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xx()
+ (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yx() + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yx()
+ (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zx(), + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zx(),
// zy:
(tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xy() (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xy()
+ (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yy() + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yy()
+ (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zy(), + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zy(),
// zz:
(tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xz() (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xz()
+ (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yz() + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yz()
+ (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zz() + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zz()
@ -273,30 +318,6 @@ inline Tensor<Cmpt> invTransform(const tensor& tt, const Tensor<Cmpt>& t)
} }
//- Use rotational tensor to transform a spherical tensor (no-op).
template<class Cmpt>
inline SphericalTensor<Cmpt> transform
(
const tensor& tt,
const SphericalTensor<Cmpt>& st
)
{
return st;
}
//- Use rotational tensor to inverse transform a spherical tensor (no-op).
template<class Cmpt>
inline SphericalTensor<Cmpt> invTransform
(
const tensor& tt,
const SphericalTensor<Cmpt>& st
)
{
return st;
}
//- Use rotational tensor to transform a symmetrical tensor. //- Use rotational tensor to transform a symmetrical tensor.
// Same as (rot & input & rot.T()) // Same as (rot & input & rot.T())
template<class Cmpt> template<class Cmpt>
@ -304,26 +325,32 @@ inline SymmTensor<Cmpt> transform(const tensor& tt, const SymmTensor<Cmpt>& st)
{ {
return SymmTensor<Cmpt> return SymmTensor<Cmpt>
( (
// xx:
(tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.xx() (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.xx()
+ (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.xy() + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.xy()
+ (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.xz(), + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.xz(),
// xy:
(tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.yx() (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.yx()
+ (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.yy() + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.yy()
+ (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.yz(), + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.yz(),
// xz:
(tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.zx() (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.zx()
+ (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.zy() + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.zy()
+ (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.zz(), + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.zz(),
// yy:
(tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.yx() (tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.yx()
+ (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.yy() + (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.yy()
+ (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.yz(), + (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.yz(),
// yz:
(tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.zx() (tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.zx()
+ (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.zy() + (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.zy()
+ (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.zz(), + (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.zz(),
// zz:
(tt.zx()*st.xx() + tt.zy()*st.xy() + tt.zz()*st.xz())*tt.zx() (tt.zx()*st.xx() + tt.zy()*st.xy() + tt.zz()*st.xz())*tt.zx()
+ (tt.zx()*st.xy() + tt.zy()*st.yy() + tt.zz()*st.yz())*tt.zy() + (tt.zx()*st.xy() + tt.zy()*st.yy() + tt.zz()*st.yz())*tt.zy()
+ (tt.zx()*st.xz() + tt.zy()*st.yz() + tt.zz()*st.zz())*tt.zz() + (tt.zx()*st.xz() + tt.zy()*st.yz() + tt.zz()*st.zz())*tt.zz()
@ -339,26 +366,32 @@ invTransform(const tensor& tt, const SymmTensor<Cmpt>& st)
{ {
return SymmTensor<Cmpt> return SymmTensor<Cmpt>
( (
// xx:
(tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xx() (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xx()
+ (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yx() + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yx()
+ (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zx(), + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zx(),
// xy:
(tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xy() (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xy()
+ (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yy() + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yy()
+ (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zy(), + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zy(),
// xz:
(tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xz() (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xz()
+ (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yz() + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yz()
+ (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zz(), + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zz(),
// yy:
(tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xy() (tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xy()
+ (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yy() + (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yy()
+ (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zy(), + (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zy(),
// yz:
(tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xz() (tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xz()
+ (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yz() + (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yz()
+ (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zz(), + (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zz(),
// zz:
(tt.xz()*st.xx() + tt.yz()*st.xy() + tt.zz()*st.xz())*tt.xz() (tt.xz()*st.xx() + tt.yz()*st.xy() + tt.zz()*st.xz())*tt.xz()
+ (tt.xz()*st.xy() + tt.yz()*st.yy() + tt.zz()*st.yz())*tt.yz() + (tt.xz()*st.xy() + tt.yz()*st.yy() + tt.zz()*st.yz())*tt.yz()
+ (tt.xz()*st.xz() + tt.yz()*st.yz() + tt.zz()*st.zz())*tt.zz() + (tt.xz()*st.xz() + tt.yz()*st.yz() + tt.zz()*st.zz())*tt.zz()
@ -366,6 +399,8 @@ invTransform(const tensor& tt, const SymmTensor<Cmpt>& st)
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type1, class Type2> template<class Type1, class Type2>
inline Type1 transformMask(const Type2& t) inline Type1 transformMask(const Type2& t)
{ {