Loading...
Searching...
No Matches
transform.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) 2020-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
27InNamespace
28 Foam
29
30Description
31 3D tensor transformation operations.
32
33\*---------------------------------------------------------------------------*/
34
35#ifndef Foam_transform_H
36#define Foam_transform_H
37
38#include "tensor.H"
40#include <type_traits>
41
42// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43
44namespace Foam
45{
47// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48
49//- Rotational transformation tensor from vector n1 to n2
51(
52 const vector& n1,
53 const vector& n2
54)
55{
56 const scalar s = n1 & n2;
57 const vector n3 = n1 ^ n2;
58 const scalar magSqrN3 = magSqr(n3);
59
60 // n1 and n2 define a plane n3
61 if (magSqrN3 > SMALL)
62 {
63 // Return rotational transformation tensor in the n3-plane
64 return
65 s*I
66 + (1 - s)*sqr(n3)/magSqrN3
67 + (n2*n1 - n1*n2);
68 }
69 // n1 and n2 are contradirectional
70 else if (s < 0)
71 {
72 // Return mirror transformation tensor
73 return I + 2*n1*n2;
74 }
75 // n1 and n2 are codirectional
76 else
77 {
78 // Return null transformation tensor
79 return I;
80 }
81}
82
84//- Rotational transformation tensor about the x-axis by omega radians
85inline tensor Rx(const scalar omega)
86{
87 const scalar s = sin(omega);
88 const scalar c = cos(omega);
89 return tensor
90 (
91 1, 0, 0,
92 0, c, s,
93 0, -s, c
94 );
95}
96
97
98//- Rotational transformation tensor about the y-axis by omega radians
99inline tensor Ry(const scalar omega)
100{
101 const scalar s = sin(omega);
102 const scalar c = cos(omega);
103 return tensor
104 (
105 c, 0, -s,
106 0, 1, 0,
107 s, 0, c
108 );
109}
110
111
112//- Rotational transformation tensor about the z-axis by omega radians
113inline tensor Rz(const scalar omega)
114{
115 const scalar s = sin(omega);
116 const scalar c = cos(omega);
117 return tensor
118 (
119 c, s, 0,
120 -s, c, 0,
121 0, 0, 1
122 );
123}
124
125
126//- Rotational transformation tensor about axis a by omega radians
127inline tensor Ra(const vector& a, const scalar omega)
128{
129 const scalar s = sin(omega);
130 const scalar c = cos(omega);
132 return tensor
133 (
134 sqr(a.x())*(1 - c) + c,
135 a.y()*a.x()*(1 - c) + a.z()*s,
136 a.x()*a.z()*(1 - c) - a.y()*s,
137
138 a.x()*a.y()*(1 - c) - a.z()*s,
139 sqr(a.y())*(1 - c) + c,
140 a.y()*a.z()*(1 - c) + a.x()*s,
141
142 a.x()*a.z()*(1 - c) + a.y()*s,
143 a.y()*a.z()*(1 - c) - a.x()*s,
144 sqr(a.z())*(1 - c) + c
145 );
146}
147
148
149// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
150
151//- No-op rotational transform for base types
152template<class T>
153constexpr std::enable_if_t<std::is_arithmetic_v<T>, T>
154transform(const tensor&, const T val)
155{
156 return val;
157}
158
159
160//- No-op rotational transform for spherical tensor
161template<class Cmpt>
163(
164 const tensor&,
165 const SphericalTensor<Cmpt>& val
166)
167{
168 return val;
169}
171
172//- No-op inverse rotational transform for base types
173template<class T>
174constexpr std::enable_if_t<std::is_arithmetic_v<T>, T>
175invTransform(const tensor&, const T val)
176{
177 return val;
178}
179
180
181//- No-op inverse rotational transform for spherical tensor
182template<class Cmpt>
183inline SphericalTensor<Cmpt> invTransform
184(
185 const tensor&,
186 const SphericalTensor<Cmpt>& val
187)
188{
189 return val;
190}
191
192
193//- Use rotational tensor to transform a vector.
194// Same as (rot & v)
195template<class Cmpt>
196inline Vector<Cmpt> transform(const tensor& tt, const Vector<Cmpt>& v)
197{
198 return (tt & v);
199}
200
201
202//- Use rotational tensor to inverse transform a vector.
203// Same as (v & rot)
204template<class Cmpt>
205inline Vector<Cmpt> invTransform(const tensor& tt, const Vector<Cmpt>& v)
206{
207 return (v & tt);
208}
209
210
211//- Use rotational tensor to transform a tensor.
212// Same as (rot & input & rot.T())
213template<class Cmpt>
214inline Tensor<Cmpt> transform(const tensor& tt, const Tensor<Cmpt>& t)
215{
216 return Tensor<Cmpt>
217 (
218 // xx:
219 (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.xx()
220 + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.xy()
221 + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.xz(),
222
223 // xy:
224 (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.yx()
225 + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.yy()
226 + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.yz(),
227
228 // xz:
229 (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.zx()
230 + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.zy()
231 + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.zz(),
232
233 // yx:
234 (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.xx()
235 + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.xy()
236 + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.xz(),
237
238 // yy:
239 (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.yx()
240 + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.yy()
241 + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.yz(),
242
243 // yz:
244 (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.zx()
245 + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.zy()
246 + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.zz(),
247
248 // zx:
249 (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.xx()
250 + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.xy()
251 + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.xz(),
252
253 // zy:
254 (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.yx()
255 + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.yy()
256 + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.yz(),
257
258 // zz:
259 (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.zx()
260 + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.zy()
261 + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.zz()
262 );
263}
264
265
266//- Use rotational tensor to inverse transform a tensor.
267// Same as (rot.T() & input & rot)
268template<class Cmpt>
269inline Tensor<Cmpt> invTransform(const tensor& tt, const Tensor<Cmpt>& t)
270{
271 return Tensor<Cmpt>
272 (
273 // xx:
274 (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xx()
275 + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yx()
276 + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zx(),
277
278 // xy:
279 (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xy()
280 + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yy()
281 + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zy(),
282
283 // xz:
284 (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xz()
285 + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yz()
286 + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zz(),
287
288 // yx:
289 (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xx()
290 + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yx()
291 + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zx(),
292
293 // yy:
294 (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xy()
295 + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yy()
296 + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zy(),
297
298 // yz:
299 (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xz()
300 + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yz()
301 + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zz(),
302
303 // zx:
304 (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xx()
305 + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yx()
306 + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zx(),
307
308 // zy:
309 (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xy()
310 + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yy()
311 + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zy(),
312
313 // zz:
314 (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xz()
315 + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yz()
316 + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zz()
317 );
318}
319
320
321//- Use rotational tensor to transform a symmetrical tensor.
322// Same as (rot & input & rot.T())
323template<class Cmpt>
324inline SymmTensor<Cmpt> transform(const tensor& tt, const SymmTensor<Cmpt>& st)
325{
326 return SymmTensor<Cmpt>
327 (
328 // xx:
329 (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.xx()
330 + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.xy()
331 + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.xz(),
332
333 // xy:
334 (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.yx()
335 + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.yy()
336 + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.yz(),
337
338 // xz:
339 (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.zx()
340 + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.zy()
341 + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.zz(),
342
343 // yy:
344 (tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.yx()
345 + (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.yy()
346 + (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.yz(),
347
348 // yz:
349 (tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.zx()
350 + (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.zy()
351 + (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.zz(),
352
353 // zz:
354 (tt.zx()*st.xx() + tt.zy()*st.xy() + tt.zz()*st.xz())*tt.zx()
355 + (tt.zx()*st.xy() + tt.zy()*st.yy() + tt.zz()*st.yz())*tt.zy()
356 + (tt.zx()*st.xz() + tt.zy()*st.yz() + tt.zz()*st.zz())*tt.zz()
357 );
358}
359
360
361//- Use rotational tensor to inverse transform a symmetrical tensor.
362// Same as (rot.T() & input & rot)
363template<class Cmpt>
364inline SymmTensor<Cmpt>
365invTransform(const tensor& tt, const SymmTensor<Cmpt>& st)
366{
367 return SymmTensor<Cmpt>
368 (
369 // xx:
370 (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xx()
371 + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yx()
372 + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zx(),
373
374 // xy:
375 (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xy()
376 + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yy()
377 + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zy(),
378
379 // xz:
380 (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xz()
381 + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yz()
382 + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zz(),
383
384 // yy:
385 (tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xy()
386 + (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yy()
387 + (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zy(),
388
389 // yz:
390 (tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xz()
391 + (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yz()
392 + (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zz(),
393
394 // zz:
395 (tt.xz()*st.xx() + tt.yz()*st.xy() + tt.zz()*st.xz())*tt.xz()
396 + (tt.xz()*st.xy() + tt.yz()*st.yy() + tt.zz()*st.yz())*tt.yz()
397 + (tt.xz()*st.xz() + tt.yz()*st.yz() + tt.zz()*st.zz())*tt.zz()
398 );
399}
400
401
402// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
403
404template<class Type1, class Type2>
405inline Type1 transformMask(const Type2& t)
406{
407 return t;
408}
409
410
411template<>
413{
414 return sph(t);
415}
416
417
418template<>
420{
421 return symm(t);
422}
423
424
425//- Estimate angle of vec in coordinate system (e0, e1, e0^e1).
426// Is guaranteed to return increasing number but is not correct
427// angle. Used for sorting angles. All input vectors need to be normalized.
428//
429// Calculates scalar which increases with angle going from e0 to vec in
430// the coordinate system e0, e1, e0^e1
431//
432// Jumps from 2*pi -> 0 at -SMALL so hopefully parallel vectors with small
433// rounding errors should still get the same quadrant.
434//
435inline scalar pseudoAngle
436(
437 const vector& e0,
438 const vector& e1,
439 const vector& vec
440)
441{
442 const scalar cos_angle = vec & e0;
443 const scalar sin_angle = vec & e1;
444
445 if (sin_angle < -SMALL)
446 {
447 return (3.0 + cos_angle)*constant::mathematical::piByTwo;
448 }
449 else
450 {
451 return (1.0 - cos_angle)*constant::mathematical::piByTwo;
452 }
453}
454
455
456// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
457
458} // End namespace Foam
459
460// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
461
462#endif
463
464// ************************************************************************* //
A templated (3 x 3) diagonal tensor of objects of <T>, effectively containing 1 element,...
A templated (3 x 3) symmetric tensor of objects of <T>, effectively containing 6 elements,...
Definition SymmTensor.H:53
const Cmpt & yy() const noexcept
Definition SymmTensor.H:154
const Cmpt & xx() const noexcept
Definition SymmTensor.H:150
const Cmpt & yz() const noexcept
Definition SymmTensor.H:155
const Cmpt & zz() const noexcept
Definition SymmTensor.H:158
const Cmpt & xy() const noexcept
Definition SymmTensor.H:151
const Cmpt & xz() const noexcept
Definition SymmTensor.H:152
A templated (3 x 3) tensor of objects of <T> derived from MatrixSpace.
Definition Tensor.H:60
const Cmpt & yy() const noexcept
Definition Tensor.H:197
const Cmpt & zy() const noexcept
Definition Tensor.H:200
const Cmpt & yx() const noexcept
Definition Tensor.H:196
const Cmpt & xx() const noexcept
Definition Tensor.H:193
const Cmpt & yz() const noexcept
Definition Tensor.H:198
const Cmpt & zz() const noexcept
Definition Tensor.H:201
const Cmpt & xy() const noexcept
Definition Tensor.H:194
const Cmpt & xz() const noexcept
Definition Tensor.H:195
const Cmpt & zx() const noexcept
Definition Tensor.H:199
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition Vector.H:61
const Cmpt & x() const noexcept
Access to the vector x component.
Definition Vector.H:135
const Cmpt & z() const noexcept
Access to the vector z component.
Definition Vector.H:145
const Cmpt & y() const noexcept
Access to the vector y component.
Definition Vector.H:140
Tensor of scalars, i.e. Tensor<scalar>.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const volScalarField & T
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))
constexpr scalar piByTwo(0.5 *M_PI)
Namespace for OpenFOAM.
dimensionSet invTransform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
scalar pseudoAngle(const vector &e0, const vector &e1, const vector &vec)
Estimate angle of vec in coordinate system (e0, e1, e0^e1).
Definition transform.H:469
tensor Rx(const scalar omega)
Rotational transformation tensor about the x-axis by omega radians.
Definition transform.H:83
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
tensor Ra(const vector &a, const scalar omega)
Rotational transformation tensor about axis a by omega radians.
Definition transform.H:131
dimensionedSymmTensor sqr(const dimensionedVector &dv)
sphericalTensor transformMask< sphericalTensor >(const symmTensor &st)
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from vector n1 to n2.
Definition transform.H:47
tensor Ry(const scalar omega)
Rotational transformation tensor about the y-axis by omega radians.
Definition transform.H:99
dimensionedScalar sin(const dimensionedScalar &ds)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
static const Identity< scalar > I
Definition Identity.H:100
Tensor< scalar > tensor
Definition symmTensor.H:57
Type1 transformMask(const Type2 &t)
Definition transform.H:435
tensor Rz(const scalar omega)
Rotational transformation tensor about the z-axis by omega radians.
Definition transform.H:115
SphericalTensor< Cmpt > sph(const DiagTensor< Cmpt > &dt)
Return the spherical part of a DiagTensor as a SphericalTensor.
symmTensor transformMask< symmTensor >(const symmTensor &st)
Vector< scalar > vector
Definition vector.H:57
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars, i.e. SphericalTensor<scalar>.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
dimensionedScalar cos(const dimensionedScalar &ds)
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition symmTensor.H:55