Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
HPCAPPs
OpenFOAM-GPU-v2.0
Commits
55e5a777
Commit
55e5a777
authored
Oct 17, 2024
by
shunbo
Browse files
initial commit
parents
Changes
677
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
3542 additions
and
0 deletions
+3542
-0
OpenFOAM-v2112/applications/test/SphericalTensor/Make/files
OpenFOAM-v2112/applications/test/SphericalTensor/Make/files
+3
-0
OpenFOAM-v2112/applications/test/SphericalTensor/Make/options
...FOAM-v2112/applications/test/SphericalTensor/Make/options
+2
-0
OpenFOAM-v2112/applications/test/SphericalTensor/Test-SphericalTensor.C
.../applications/test/SphericalTensor/Test-SphericalTensor.C
+347
-0
OpenFOAM-v2112/applications/test/SphericalTensor2D/Make/files
...FOAM-v2112/applications/test/SphericalTensor2D/Make/files
+3
-0
OpenFOAM-v2112/applications/test/SphericalTensor2D/Make/options
...AM-v2112/applications/test/SphericalTensor2D/Make/options
+2
-0
OpenFOAM-v2112/applications/test/SphericalTensor2D/Test-SphericalTensor2D.C
...lications/test/SphericalTensor2D/Test-SphericalTensor2D.C
+330
-0
OpenFOAM-v2112/applications/test/SubField/Make/files
OpenFOAM-v2112/applications/test/SubField/Make/files
+3
-0
OpenFOAM-v2112/applications/test/SubField/Make/options
OpenFOAM-v2112/applications/test/SubField/Make/options
+2
-0
OpenFOAM-v2112/applications/test/SubField/Test-SubField.C
OpenFOAM-v2112/applications/test/SubField/Test-SubField.C
+96
-0
OpenFOAM-v2112/applications/test/SymmTensor/Make/files
OpenFOAM-v2112/applications/test/SymmTensor/Make/files
+3
-0
OpenFOAM-v2112/applications/test/SymmTensor/Make/options
OpenFOAM-v2112/applications/test/SymmTensor/Make/options
+2
-0
OpenFOAM-v2112/applications/test/SymmTensor/Test-SymmTensor.C
...FOAM-v2112/applications/test/SymmTensor/Test-SymmTensor.C
+868
-0
OpenFOAM-v2112/applications/test/SymmTensor2D/Make/files
OpenFOAM-v2112/applications/test/SymmTensor2D/Make/files
+3
-0
OpenFOAM-v2112/applications/test/SymmTensor2D/Make/options
OpenFOAM-v2112/applications/test/SymmTensor2D/Make/options
+2
-0
OpenFOAM-v2112/applications/test/SymmTensor2D/Test-SymmTensor2D.C
...-v2112/applications/test/SymmTensor2D/Test-SymmTensor2D.C
+680
-0
OpenFOAM-v2112/applications/test/Tensor/Make/files
OpenFOAM-v2112/applications/test/Tensor/Make/files
+3
-0
OpenFOAM-v2112/applications/test/Tensor/Make/options
OpenFOAM-v2112/applications/test/Tensor/Make/options
+2
-0
OpenFOAM-v2112/applications/test/Tensor/Test-Tensor.C
OpenFOAM-v2112/applications/test/Tensor/Test-Tensor.C
+1186
-0
OpenFOAM-v2112/applications/test/Tensor2D/Make/files
OpenFOAM-v2112/applications/test/Tensor2D/Make/files
+3
-0
OpenFOAM-v2112/applications/test/Tensor2D/Make/options
OpenFOAM-v2112/applications/test/Tensor2D/Make/options
+2
-0
No files found.
Too many changes to show.
To preserve performance only
677 of 677+
files are displayed.
Plain diff
Email patch
OpenFOAM-v2112/applications/test/SphericalTensor/Make/files
0 → 100644
View file @
55e5a777
Test-SphericalTensor.C
EXE = $(FOAM_USER_APPBIN)/Test-SphericalTensor
OpenFOAM-v2112/applications/test/SphericalTensor/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/SphericalTensor/Test-SphericalTensor.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-SphericalTensor
Description
Tests for \c SphericalTensor constructors, member functions and operators
using \c floatScalar, \c doubleScalar, and \c complex base types.
Cross-checks were obtained from 'NumPy 1.15.1' and 'SciPy 1.1.0' if no
theoretical cross-check exists (like eigendecomposition relations), and
were hard-coded for elementwise comparisons.
For \c complex base type, the cross-checks do only involve zero imag part.
\*---------------------------------------------------------------------------*/
#include "Tensor.H"
#include "SymmTensor.H"
#include "SphericalTensor.H"
#include "DiagTensor.H"
#include "scalar.H"
#include "complex.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Total number of unit tests
unsigned
nTest_
=
0
;
// Total number of failed unit tests
unsigned
nFail_
=
0
;
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template
<
class
Type
>
typename
std
::
enable_if
<
std
::
is_same
<
floatScalar
,
Type
>::
value
||
std
::
is_same
<
doubleScalar
,
Type
>::
value
||
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
relTol
=
1e-8
,
//<! are values the same within 8 decimals
const
scalar
absTol
=
0
//<! useful for cmps near zero
)
{
Info
<<
msg
<<
x
<<
endl
;
unsigned
nFail
=
0
;
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
),
mag
(
y
)))
<
mag
(
x
-
y
))
{
++
nFail
;
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template
<
class
Type
>
typename
std
::
enable_if
<
!
std
::
is_same
<
floatScalar
,
Type
>::
value
&&
!
std
::
is_same
<
doubleScalar
,
Type
>::
value
&&
!
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
relTol
=
1e-8
,
const
scalar
absTol
=
0
)
{
Info
<<
msg
<<
x
<<
endl
;
unsigned
nFail
=
0
;
for
(
label
i
=
0
;
i
<
pTraits
<
Type
>::
nComponents
;
++
i
)
{
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
[
i
]),
mag
(
y
[
i
])))
<
mag
(
x
[
i
]
-
y
[
i
]))
{
++
nFail
;
}
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Create each constructor of SphericalTensor<Type>, and print output
template
<
class
Type
>
void
test_constructors
(
Type
)
{
{
Info
<<
"# Construct initialized to zero:"
<<
nl
;
const
SphericalTensor
<
Type
>
spT
(
Zero
);
Info
<<
spT
<<
endl
;
}
{
Info
<<
"# Construct given VectorSpace of the same rank:"
<<
nl
;
const
VectorSpace
<
SphericalTensor
<
Type
>
,
Type
,
1
>
V
(
Zero
);
const
SphericalTensor
<
Type
>
spT
(
V
);
Info
<<
spT
<<
endl
;
}
{
Info
<<
"# Construct given the component:"
<<
nl
;
const
SphericalTensor
<
Type
>
spT
(
Type
(
1
));
Info
<<
spT
<<
endl
;
}
{
Info
<<
"# Copy construct:"
<<
nl
;
const
SphericalTensor
<
Type
>
spT
(
Zero
);
const
SphericalTensor
<
Type
>
copyspT
(
spT
);
Info
<<
spT
<<
tab
<<
copyspT
<<
endl
;
}
}
// Execute each member function of SphericalTensor<Type>, and print output
template
<
class
Type
>
void
test_member_funcs
(
Type
)
{
SphericalTensor
<
Type
>
spT
(
Type
(
1
));
const
SphericalTensor
<
Type
>
cspT
(
Type
(
-
9
));
Info
<<
"# Operand: "
<<
nl
<<
" SphericalTensor = "
<<
spT
<<
endl
;
{
Info
<<
"# Component access:"
<<
nl
;
SphericalTensor
<
Type
>
cpspT
(
spT
.
ii
());
cmp
(
" 'SphericalTensor' access:"
,
spT
,
cpspT
);
const
SphericalTensor
<
Type
>
cpcspT
(
cspT
.
ii
());
cmp
(
" 'const SphericalTensor' access:"
,
cspT
,
cpcspT
);
}
{
Info
<<
"# SphericalTensor operations:"
<<
nl
;
Info
<<
" Transpose:"
<<
nl
;
cmp
(
" 'SphericalTensor'.T():"
,
spT
.
T
(),
spT
);
}
}
// Execute each global function of SphericalTensor<Type>, and print output
template
<
class
Type
>
void
test_global_funcs
(
Type
)
{
const
SphericalTensor
<
Type
>
spT
(
Type
(
5
));
Info
<<
"# Operand: "
<<
nl
<<
" SphericalTensor = "
<<
spT
<<
endl
;
cmp
(
" Trace = "
,
tr
(
spT
),
Type
(
15
));
cmp
(
" Spherical part = "
,
sph
(
spT
),
spT
);
cmp
(
" Determinant = "
,
det
(
spT
),
Type
(
124
.
99999999999994
));
cmp
(
" Inverse = "
,
inv
(
spT
),
SphericalTensor
<
Type
>
(
Type
(
0
.
2
))
);
cmp
(
" Square of Frobenius norm = "
,
magSqr
(
spT
),
Type
(
75
));
cmp
(
" Max component = "
,
cmptMax
(
spT
),
Type
(
5
));
cmp
(
" Min component = "
,
cmptMax
(
spT
),
Type
(
5
));
cmp
(
" Sum of components = "
,
cmptSum
(
spT
),
Type
(
15
));
cmp
(
" Arithmetic average of components = "
,
cmptAv
(
spT
),
Type
(
5
));
}
// Execute each global operator of SphericalTensor<Type>, and print output
template
<
class
Type
>
void
test_global_opers
(
Type
)
{
const
Tensor
<
Type
>
T
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
);
const
SymmTensor
<
Type
>
sT
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
const
DiagTensor
<
Type
>
dT
(
Type
(
1
),
Type
(
5
),
Type
(
-
9
));
const
SphericalTensor
<
Type
>
spT
(
Type
(
-
2
));
const
Vector
<
Type
>
v
(
Type
(
3
),
Type
(
2
),
Type
(
1
));
const
Type
x
(
4
);
Info
<<
"# Operands:"
<<
nl
<<
" Tensor = "
<<
T
<<
nl
<<
" SymmTensor = "
<<
sT
<<
nl
<<
" DiagTensor = "
<<
dT
<<
nl
<<
" SphericalTensor = "
<<
spT
<<
nl
<<
" Vector = "
<<
v
<<
nl
<<
" Type = "
<<
x
<<
endl
;
cmp
(
" Division of Type by SpTensor = "
,
(
x
/
spT
),
SphericalTensor
<
Type
>
(
Type
(
-
2
))
);
cmp
(
" Division of SpTensor by Type = "
,
(
spT
/
x
),
SphericalTensor
<
Type
>
(
Type
(
-
0
.
5
))
);
cmp
(
" Inner-product of SpTensor-SpTensor = "
,
(
spT
&
spT
),
SphericalTensor
<
Type
>
(
Type
(
4
))
);
cmp
(
" Inner-product of SpTensor-Vector = "
,
(
spT
&
v
),
Vector
<
Type
>
(
Type
(
-
6
),
Type
(
-
4
),
Type
(
-
2
))
// Column-vector
);
cmp
(
" Inner-product of Vector-SpTensor = "
,
(
v
&
spT
),
Vector
<
Type
>
(
Type
(
-
6
),
Type
(
-
4
),
Type
(
-
2
))
// Row-vector
);
cmp
(
" D-inner-product of SpTensor-SpTensor = "
,
(
spT
&&
spT
),
Type
(
12
));
}
// Do compile-time recursion over the given types
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
==
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
){}
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
<
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
)
{
Info
<<
nl
<<
" ## Test constructors: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_constructors
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test member functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_member_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global operators: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_opers
(
std
::
get
<
I
>
(
types
));
run_tests
<
I
+
1
,
Tp
...
>
(
types
,
typeID
);
}
// * * * * * * * * * * * * * * * Main Program * * * * * * * * * * * * * * * //
int
main
()
{
const
std
::
tuple
<
floatScalar
,
doubleScalar
,
complex
>
types
(
std
::
make_tuple
(
Zero
,
Zero
,
Zero
)
);
const
List
<
word
>
typeID
({
"SphericalTensor<floatScalar>"
,
"SphericalTensor<doubleScalar>"
,
"SphericalTensor<complex>"
});
run_tests
(
types
,
typeID
);
if
(
nFail_
)
{
Info
<<
nl
<<
" #### "
<<
"Failed in "
<<
nFail_
<<
" tests "
<<
"out of total "
<<
nTest_
<<
" tests "
<<
"####
\n
"
<<
endl
;
return
1
;
}
Info
<<
nl
<<
" #### Passed all "
<<
nTest_
<<
" tests ####
\n
"
<<
endl
;
return
0
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
OpenFOAM-v2112/applications/test/SphericalTensor2D/Make/files
0 → 100644
View file @
55e5a777
Test-SphericalTensor2D.C
EXE = $(FOAM_USER_APPBIN)/Test-SphericalTensor2D
OpenFOAM-v2112/applications/test/SphericalTensor2D/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/SphericalTensor2D/Test-SphericalTensor2D.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-SphericalTensor2D
Description
Tests for \c SphericalTensor2D constructors, member functions and operators
using \c floatScalar, \c doubleScalar, and \c complex base types.
Cross-checks were obtained from 'NumPy 1.15.1' and 'SciPy 1.1.0' if no
theoretical cross-check exists (like eigendecomposition relations), and
were hard-coded for elementwise comparisons.
For \c complex base type, the cross-checks do only involve zero imag part.
\*---------------------------------------------------------------------------*/
#include "Tensor2D.H"
#include "SymmTensor2D.H"
#include "SphericalTensor2D.H"
#include "scalar.H"
#include "complex.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Total number of unit tests
unsigned
nTest_
=
0
;
// Total number of failed unit tests
unsigned
nFail_
=
0
;
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template
<
class
Type
>
typename
std
::
enable_if
<
std
::
is_same
<
floatScalar
,
Type
>::
value
||
std
::
is_same
<
doubleScalar
,
Type
>::
value
||
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
relTol
=
1e-8
,
//<! are values the same within 8 decimals
const
scalar
absTol
=
0
//<! useful for cmps near zero
)
{
Info
<<
msg
<<
x
<<
endl
;
unsigned
nFail
=
0
;
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
),
mag
(
y
)))
<
mag
(
x
-
y
))
{
++
nFail
;
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template
<
class
Type
>
typename
std
::
enable_if
<
!
std
::
is_same
<
floatScalar
,
Type
>::
value
&&
!
std
::
is_same
<
doubleScalar
,
Type
>::
value
&&
!
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
relTol
=
1e-8
,
const
scalar
absTol
=
0
)
{
Info
<<
msg
<<
x
<<
endl
;
unsigned
nFail
=
0
;
for
(
label
i
=
0
;
i
<
pTraits
<
Type
>::
nComponents
;
++
i
)
{
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
[
i
]),
mag
(
y
[
i
])))
<
mag
(
x
[
i
]
-
y
[
i
]))
{
++
nFail
;
}
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Create each constructor of SphericalTensor2D<Type>, and print output
template
<
class
Type
>
void
test_constructors
(
Type
)
{
{
Info
<<
"# Construct initialized to zero:"
<<
nl
;
const
SphericalTensor2D
<
Type
>
spT
(
Zero
);
Info
<<
spT
<<
endl
;
}
{
Info
<<
"# Construct given VectorSpace of the same rank:"
<<
nl
;
const
VectorSpace
<
SphericalTensor2D
<
Type
>
,
Type
,
1
>
V
(
Zero
);
const
SphericalTensor2D
<
Type
>
spT
(
V
);
Info
<<
spT
<<
endl
;
}
{
Info
<<
"# Construct given the component:"
<<
nl
;
const
SphericalTensor2D
<
Type
>
spT
(
Type
(
1
));
Info
<<
spT
<<
endl
;
}
{
Info
<<
"# Copy construct:"
<<
nl
;
const
SphericalTensor2D
<
Type
>
spT
(
Zero
);
const
SphericalTensor2D
<
Type
>
copyspT
(
spT
);
Info
<<
spT
<<
tab
<<
copyspT
<<
endl
;
}
}
// Execute each member function of SphericalTensor2D<Type>, and print output
template
<
class
Type
>
void
test_member_funcs
(
Type
)
{
SphericalTensor2D
<
Type
>
spT
(
Type
(
1
));
const
SphericalTensor2D
<
Type
>
cspT
(
Type
(
-
9
));
Info
<<
"# Operand: "
<<
nl
<<
" SphericalTensor2D = "
<<
spT
<<
endl
;
{
Info
<<
"# Component access:"
<<
nl
;
SphericalTensor2D
<
Type
>
cpspT
(
spT
.
ii
());
cmp
(
" 'SphericalTensor2D' access:"
,
spT
,
cpspT
);
const
SphericalTensor2D
<
Type
>
cpcspT
(
cspT
.
ii
());
cmp
(
" 'const SphericalTensor2D' access:"
,
cspT
,
cpcspT
);
}
}
// Execute each global function of SphericalTensor2D<Type>, and print output
template
<
class
Type
>
void
test_global_funcs
(
Type
)
{
const
SphericalTensor2D
<
Type
>
spT
(
Type
(
5
));
Info
<<
"# Operand: "
<<
nl
<<
" SphericalTensor2D = "
<<
spT
<<
endl
;
cmp
(
" Trace = "
,
tr
(
spT
),
Type
(
10
));
cmp
(
" Spherical part = "
,
sph
(
spT
),
spT
);
cmp
(
" Determinant = "
,
det
(
spT
),
Type
(
24
.
99999999999994
));
cmp
(
" Inverse = "
,
inv
(
spT
),
SphericalTensor2D
<
Type
>
(
Type
(
0
.
2
))
);
}
// Execute each global operator of SphericalTensor2D<Type>, and print output
template
<
class
Type
>
void
test_global_opers
(
Type
)
{
const
Tensor2D
<
Type
>
T
(
Type
(
-
1
),
Type
(
2
),
Type
(
4
),
Type
(
5
)
);
const
SymmTensor2D
<
Type
>
sT
(
Type
(
-
1
),
Type
(
2
),
Type
(
5
)
);
const
SphericalTensor2D
<
Type
>
spT
(
Type
(
-
2
));
const
Vector2D
<
Type
>
v
(
Type
(
3
),
Type
(
2
));
const
Type
x
(
4
);
Info
<<
"# Operands:"
<<
nl
<<
" Tensor2D = "
<<
T
<<
nl
<<
" SymmTensor2D = "
<<
sT
<<
nl
<<
" SphericalTensor2D = "
<<
spT
<<
nl
<<
" Vector2D = "
<<
v
<<
nl
<<
" Type = "
<<
x
<<
endl
;
cmp
(
" Division of Type by SpTensor2D = "
,
(
x
/
spT
),
SphericalTensor2D
<
Type
>
(
Type
(
-
2
))
);
cmp
(
" Division of SpTensor2D by Type = "
,
(
spT
/
x
),
SphericalTensor2D
<
Type
>
(
Type
(
-
0
.
5
))
);
cmp
(
" Inner-product of SpTensor2D-SpTensor2D = "
,
(
spT
&
spT
),
SphericalTensor2D
<
Type
>
(
Type
(
4
))
);
cmp
(
" Inner-product of SpTensor2D-Vector2D = "
,
(
spT
&
v
),
Vector2D
<
Type
>
(
Type
(
-
6
),
Type
(
-
4
))
// Column-vector
);
cmp
(
" Inner-product of Vector2D-SpTensor2D = "
,
(
v
&
spT
),
Vector2D
<
Type
>
(
Type
(
-
6
),
Type
(
-
4
))
// Row-vector
);
}
// Do compile-time recursion over the given types
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
==
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
){}
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
<
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
)
{
Info
<<
nl
<<
" ## Test constructors: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_constructors
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test member functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_member_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global operators: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_opers
(
std
::
get
<
I
>
(
types
));
run_tests
<
I
+
1
,
Tp
...
>
(
types
,
typeID
);
}
// * * * * * * * * * * * * * * * Main Program * * * * * * * * * * * * * * * //
int
main
()
{
const
std
::
tuple
<
floatScalar
,
doubleScalar
,
complex
>
types
(
std
::
make_tuple
(
Zero
,
Zero
,
Zero
)
);
const
List
<
word
>
typeID
({
"SphericalTensor2D<floatScalar>"
,
"SphericalTensor2D<doubleScalar>"
,
"SphericalTensor2D<complex>"
});
run_tests
(
types
,
typeID
);
if
(
nFail_
)
{
Info
<<
nl
<<
" #### "
<<
"Failed in "
<<
nFail_
<<
" tests "
<<
"out of total "
<<
nTest_
<<
" tests "
<<
"####
\n
"
<<
endl
;
return
1
;
}
Info
<<
nl
<<
" #### Passed all "
<<
nTest_
<<
" tests ####
\n
"
<<
endl
;
return
0
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
OpenFOAM-v2112/applications/test/SubField/Make/files
0 → 100644
View file @
55e5a777
Test-SubField.C
EXE = $(FOAM_USER_APPBIN)/Test-SubField
OpenFOAM-v2112/applications/test/SubField/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/SubField/Test-SubField.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-SubField
Description
Simple tests on SubList, SubField
\*---------------------------------------------------------------------------*/
#include "OSspecific.H"
#include "argList.H"
#include "scalarField.H"
#include "SubField.H"
#include "labelRange.H"
#include <numeric>
using
namespace
Foam
;
template
<
class
T
>
void
print
(
const
UList
<
T
>&
list
)
{
Info
<<
flatOutput
(
list
)
<<
nl
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
argList
::
noParallel
();
argList
::
noFunctionObjects
();
{
List
<
scalar
>
ident
(
25
);
std
::
iota
(
ident
.
begin
(),
ident
.
end
(),
0
);
print
(
ident
);
SubList
<
scalar
>
(
ident
,
10
)
=
-
10
;
print
(
ident
);
SubField
<
scalar
>
(
ident
,
10
)
=
10
;
print
(
ident
);
SubField
<
scalar
>
(
ident
,
10
)
+=
10
;
print
(
ident
);
SubField
<
scalar
>
{
ident
,
10
,
10
}
*=
5
;
print
(
ident
);
// NOTE: Need {} instead of ()
// SubList<scalar>(ident) = 100;
// GCC
// error: conflicting declaration 'Foam::SubList<double> ident'
// CLANG
// warning: parentheses were disambiguated as redundant parentheses
// around declaration of variable named 'ident' [-Wvexing-parse]
SubList
<
scalar
>
{
ident
}
=
100
;
print
(
ident
);
}
Info
<<
"
\n
End
\n
"
;
return
0
;
}
// ************************************************************************* //
OpenFOAM-v2112/applications/test/SymmTensor/Make/files
0 → 100644
View file @
55e5a777
Test-SymmTensor.C
EXE = $(FOAM_USER_APPBIN)/Test-SymmTensor
OpenFOAM-v2112/applications/test/SymmTensor/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/SymmTensor/Test-SymmTensor.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-SymmTensor
Description
Tests for \c SymmTensor constructors, member functions and operators
using \c floatScalar, \c doubleScalar, and \c complex base types.
Eigen decomposition tests for \c symmTensor, i.e. SymmTensor<scalar>.
Cross-checks were obtained from 'NumPy 1.15.1' and 'SciPy 1.1.0' if no
theoretical cross-check exists (like eigendecomposition relations), and
were hard-coded for elementwise comparisons.
For \c complex base type, the cross-checks do only involve zero imag part.
\*---------------------------------------------------------------------------*/
#include "symmTensor.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Total number of unit tests
unsigned
nTest_
=
0
;
// Total number of failed unit tests
unsigned
nFail_
=
0
;
// Create a random symmTensor
symmTensor
makeRandomContainer
(
Random
&
rnd
)
{
symmTensor
T
(
Zero
);
std
::
generate
(
T
.
begin
(),
T
.
end
(),
[
&
]{
return
rnd
.
GaussNormal
<
scalar
>
();
});
return
T
;
}
// Create a symmTensor based on a given value
template
<
class
Type
>
typename
std
::
enable_if
<
std
::
is_same
<
floatScalar
,
Type
>::
value
||
std
::
is_same
<
doubleScalar
,
Type
>::
value
,
symmTensor
>::
type
makeContainer
(
const
Type
val
)
{
symmTensor
T
(
Zero
);
std
::
fill
(
T
.
begin
(),
T
.
end
(),
val
);
return
T
;
}
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template
<
class
Type
>
typename
std
::
enable_if
<
std
::
is_same
<
floatScalar
,
Type
>::
value
||
std
::
is_same
<
doubleScalar
,
Type
>::
value
||
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
absTol
=
0
,
//<! useful for cmps near zero
const
scalar
relTol
=
1e-8
//<! are values the same within 8 decimals
)
{
Info
<<
msg
<<
x
<<
"?="
<<
y
<<
endl
;
unsigned
nFail
=
0
;
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
),
mag
(
y
)))
<
mag
(
x
-
y
))
{
++
nFail
;
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template
<
class
Type
>
typename
std
::
enable_if
<
!
std
::
is_same
<
floatScalar
,
Type
>::
value
&&
!
std
::
is_same
<
doubleScalar
,
Type
>::
value
&&
!
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
absTol
=
0
,
const
scalar
relTol
=
1e-8
)
{
Info
<<
msg
<<
x
<<
"?="
<<
y
<<
endl
;
unsigned
nFail
=
0
;
for
(
label
i
=
0
;
i
<
pTraits
<
Type
>::
nComponents
;
++
i
)
{
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
[
i
]),
mag
(
y
[
i
])))
<
mag
(
x
[
i
]
-
y
[
i
]))
{
++
nFail
;
}
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Create each constructor of SymmTensor<Type>, and print output
template
<
class
Type
>
void
test_constructors
(
Type
)
{
{
Info
<<
"# Construct initialized to zero:"
<<
nl
;
const
SymmTensor
<
Type
>
sT
(
Zero
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Construct given VectorSpace of the same rank:"
<<
nl
;
const
VectorSpace
<
SymmTensor
<
Type
>
,
Type
,
6
>
M
(
Zero
);
const
SymmTensor
<
Type
>
sT
(
M
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Construct given SphericalTensor:"
<<
nl
;
const
SphericalTensor
<
Type
>
Sp
(
Type
(
5
));
const
SymmTensor
<
Type
>
sT
(
Sp
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Construct given the six components:"
<<
nl
;
const
SymmTensor
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Copy construct:"
<<
nl
;
const
SymmTensor
<
Type
>
sT
(
Zero
);
const
SymmTensor
<
Type
>
copysT
(
sT
);
Info
<<
sT
<<
tab
<<
copysT
<<
endl
;
}
}
// Execute each member function of SymmTensor<Type>, and print output
template
<
class
Type
>
void
test_member_funcs
(
Type
)
{
SymmTensor
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
const
SymmTensor
<
Type
>
csT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
Info
<<
"# Operand: "
<<
nl
<<
" SymmTensor = "
<<
sT
<<
endl
;
{
Info
<<
"# Component access:"
<<
nl
;
SymmTensor
<
Type
>
cpsT
(
sT
.
xx
(),
sT
.
xy
(),
sT
.
xz
(),
sT
.
yy
(),
sT
.
yz
(),
sT
.
zz
()
);
cmp
(
" 'SymmTensor' access:"
,
sT
,
cpsT
);
cmp
(
" xy()=yx():"
,
sT
.
xy
(),
sT
.
yx
());
cmp
(
" xz()=zx():"
,
sT
.
xz
(),
sT
.
zx
());
cmp
(
" yz()=zy():"
,
sT
.
yz
(),
sT
.
zy
());
const
SymmTensor
<
Type
>
cpcsT
(
csT
.
xx
(),
csT
.
xy
(),
csT
.
xz
(),
csT
.
yy
(),
csT
.
yz
(),
csT
.
zz
()
);
cmp
(
" 'const SymmTensor' access:"
,
csT
,
cpcsT
);
cmp
(
" xy()=yx():"
,
sT
.
xy
(),
sT
.
yx
());
cmp
(
" xz()=zx():"
,
sT
.
xz
(),
sT
.
zx
());
cmp
(
" yz()=zy():"
,
sT
.
yz
(),
sT
.
zy
());
}
{
Info
<<
"# Diagonal access:"
<<
nl
;
cmp
(
" 'SymmTensor'.diag():"
,
sT
.
diag
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
5
),
Type
(
-
9
))
);
cmp
(
" 'const SymmTensor'.diag():"
,
csT
.
diag
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
5
),
Type
(
-
9
))
);
Info
<<
"# Diagonal manipulation:"
<<
nl
;
sT
.
diag
(
Vector
<
Type
>
(
Type
(
-
10
),
Type
(
-
15
),
Type
(
-
20
)));
cmp
(
" 'SymmTensor'.diag('Vector'):"
,
sT
.
diag
(),
Vector
<
Type
>
(
Type
(
-
10
),
Type
(
-
15
),
Type
(
-
20
))
);
}
{
Info
<<
"# Tensor operations:"
<<
nl
;
Info
<<
" Transpose:"
<<
nl
;
cmp
(
" 'SymmTensor'.T():"
,
sT
.
T
(),
sT
);
}
{
Info
<<
"# Member operators:"
<<
nl
;
sT
=
SphericalTensor
<
Type
>
(
Type
(
5
));
cmp
(
" Assign to a SphericalTensor:"
,
sT
,
SymmTensor
<
Type
>
(
Type
(
5
),
Zero
,
Zero
,
Type
(
5
),
Zero
,
Type
(
5
)
)
);
}
}
// Execute each global function of SymmTensor<Type>, and print output
template
<
class
Type
>
void
test_global_funcs
(
Type
)
{
const
SymmTensor
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
Info
<<
"# Operand: "
<<
nl
<<
" SymmTensor = "
<<
sT
<<
nl
<<
endl
;
cmp
(
" Trace = "
,
tr
(
sT
),
Type
(
-
3
));
cmp
(
" Spherical part = "
,
sph
(
sT
),
SphericalTensor
<
Type
>
(
tr
(
sT
)
/
Type
(
3
)));
cmp
(
" Symmetric part = "
,
symm
(
sT
),
sT
);
cmp
(
" Twice the symmetric part = "
,
twoSymm
(
sT
),
2
*
sT
);
cmp
(
" Deviatoric part = "
,
dev
(
sT
),
SymmTensor
<
Type
>
(
Type
(
2
),
Type
(
2
),
Type
(
-
3
),
Type
(
6
),
Type
(
-
6
),
Type
(
-
8
)
)
);
cmp
(
" Two-third deviatoric part = "
,
dev2
(
sT
),
sT
-
2
*
sph
(
sT
));
cmp
(
" Determinant = "
,
det
(
sT
),
Type
(
-
17
.
999999999999996
));
cmp
(
" Cofactor tensor = "
,
cof
(
sT
),
SymmTensor
<
Type
>
(
Type
(
-
81
),
Type
(
36
),
Type
(
3
),
Type
(
-
18
),
Type
(
0
),
Type
(
1
)
)
);
cmp
(
" Inverse = "
,
inv
(
sT
,
det
(
sT
)),
SymmTensor
<
Type
>
(
Type
(
4
.
5
),
Type
(
-
2
),
Type
(
-
0
.
16666667
),
Type
(
1
),
Type
(
0
),
Type
(
-
0
.
05555556
)
),
1e-8
);
cmp
(
" Inverse (another) = "
,
inv
(
sT
),
SymmTensor
<
Type
>
(
Type
(
4
.
5
),
Type
(
-
2
),
Type
(
-
0
.
16666667
),
Type
(
1
),
Type
(
0
),
Type
(
-
0
.
05555556
)
),
1e-8
);
cmp
(
" First invariant = "
,
invariantI
(
sT
),
Type
(
-
3
));
cmp
(
" Second invariant = "
,
invariantII
(
sT
),
Type
(
-
98
));
cmp
(
" Third invariant = "
,
invariantIII
(
sT
),
Type
(
-
17
.
999999999999996
));
cmp
(
" Inner-product with self = "
,
innerSqr
(
sT
),
SymmTensor
<
Type
>
(
Type
(
14
),
Type
(
30
),
Type
(
12
),
Type
(
65
),
Type
(
18
),
Type
(
126
)
)
);
cmp
(
" Square of Frobenius norm = "
,
magSqr
(
sT
),
Type
(
205
));
}
// Execute each global operator of SymmTensor<Type>, and print output
template
<
class
Type
>
void
test_global_opers
(
Type
)
{
const
Tensor
<
Type
>
T
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
);
const
SymmTensor
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
const
SphericalTensor
<
Type
>
spT
(
Type
(
1
));
const
Vector
<
Type
>
v
(
Type
(
3
),
Type
(
2
),
Type
(
1
));
const
Type
x
(
4
);
Info
<<
"# Operands:"
<<
nl
<<
" Tensor = "
<<
T
<<
nl
<<
" SymmTensor = "
<<
sT
<<
nl
<<
" SphericalTensor = "
<<
spT
<<
nl
<<
" Vector = "
<<
v
<<
nl
<<
" Type = "
<<
x
<<
endl
;
cmp
(
" Sum of SpTensor-SymmTensor = "
,
(
spT
+
sT
),
SymmTensor
<
Type
>
(
Type
(
2
),
Type
(
2
),
Type
(
-
3
),
Type
(
6
),
Type
(
-
6
),
Type
(
-
8
)
)
);
cmp
(
" Sum of SymmTensor-SpTensor = "
,
(
sT
+
spT
),
SymmTensor
<
Type
>
(
Type
(
2
),
Type
(
2
),
Type
(
-
3
),
Type
(
6
),
Type
(
-
6
),
Type
(
-
8
)
)
);
cmp
(
" Subtract SymmTensor from SpTensor = "
,
(
spT
-
sT
),
SymmTensor
<
Type
>
(
Type
(
0
),
Type
(
-
2
),
Type
(
3
),
Type
(
-
4
),
Type
(
6
),
Type
(
10
)
)
);
cmp
(
" Subtract SpTensor from SymmTensor = "
,
(
sT
-
spT
),
SymmTensor
<
Type
>
(
Type
(
0
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
-
6
),
Type
(
-
10
)
)
);
cmp
(
" Hodge dual of a SymmTensor"
,
*
sT
,
Vector
<
Type
>
(
Type
(
-
6
),
Type
(
3
),
Type
(
2
))
);
cmp
(
" Division of a SymmTensor by a Type"
,
sT
/
x
,
SymmTensor
<
Type
>
(
Type
(
0
.
25
),
Type
(
0
.
5
),
Type
(
-
0
.
75
),
Type
(
1
.
25
),
Type
(
-
1
.
5
),
Type
(
-
2
.
25
)
)
);
cmp
(
" Inner-product of SymmTensor-SymmTensor = "
,
(
sT
&
sT
),
Tensor
<
Type
>
(
Type
(
14
),
Type
(
30
),
Type
(
12
),
Type
(
30
),
Type
(
65
),
Type
(
18
),
Type
(
12
),
Type
(
18
),
Type
(
126
)
)
);
cmp
(
" Inner-product of SpTensor-SymmTensor = "
,
(
spT
&
sT
),
SymmTensor
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
)
);
cmp
(
" Inner-product of SymmTensor-SpTensor = "
,
(
sT
&
spT
),
SymmTensor
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
)
);
cmp
(
" Inner-product of SymmTensor-Vector = "
,
(
sT
&
v
),
Vector
<
Type
>
(
Type
(
4
),
Type
(
10
),
Type
(
-
30
))
// Column-vector
);
cmp
(
" Inner-product of Vector-SymmTensor = "
,
(
v
&
sT
),
Vector
<
Type
>
(
Type
(
4
),
Type
(
10
),
Type
(
-
30
))
// Row-vector
);
cmp
(
" D-inner-product of SymmTensor-SymmTensor = "
,
(
sT
&&
sT
),
Type
(
205
));
cmp
(
" D-inner-product of SymmTensor-SpTensor = "
,
(
sT
&&
spT
),
Type
(
-
3
));
cmp
(
" D-inner-product of SpTensor-SymmTensor = "
,
(
spT
&&
sT
),
Type
(
-
3
));
}
// Return false if given eigenvalues fail to satisy eigenvalue relations
// Relations: (Beauregard & Fraleigh (1973), ISBN 0-395-14017-X, p. 307)
void
test_eigenvalues
(
const
symmTensor
&
T
,
const
vector
&
EVals
)
{
{
const
scalar
determinant
=
det
(
T
);
const
scalar
EValsProd
=
EVals
.
x
()
*
EVals
.
y
()
*
EVals
.
z
();
cmp
(
"# Product of eigenvalues = det(T):"
,
EValsProd
,
determinant
,
1e-6
);
}
{
const
scalar
trace
=
tr
(
T
);
scalar
EValsSum
=
0
.
0
;
for
(
const
auto
&
val
:
EVals
)
{
EValsSum
+=
val
;
}
cmp
(
"# Sum of eigenvalues = trace(T):"
,
EValsSum
,
trace
);
}
}
// Return false if a given eigenvalue-eigenvector pair
// fails to satisfy the characteristic equation
void
test_characteristic_equation
(
const
symmTensor
&
T
,
const
vector
&
EVals
,
const
tensor
&
EVecs
)
{
Info
<<
"# Characteristic equation:"
<<
nl
;
for
(
direction
dir
=
0
;
dir
<
pTraits
<
vector
>::
nComponents
;
++
dir
)
{
Info
<<
"EVal = "
<<
EVals
[
dir
]
<<
nl
<<
"EVec = "
<<
EVecs
.
row
(
dir
)
<<
endl
;
const
vector
leftSide
(
T
&
EVecs
.
row
(
dir
));
const
vector
rightSide
(
EVals
[
dir
]
*
EVecs
.
row
(
dir
));
const
vector
X
(
leftSide
-
rightSide
);
for
(
const
auto
x
:
X
)
{
cmp
(
" (T & EVec - EVal*EVec) = 0:"
,
x
,
0
.
0
,
1e-5
);
}
}
}
// Return false if the eigen functions fail to satisfy relations
void
test_eigen_funcs
(
const
symmTensor
&
T
)
{
Info
<<
"# Operand:"
<<
nl
<<
" symmTensor = "
<<
T
<<
nl
;
Info
<<
"# Return eigenvalues of a given symmTensor:"
<<
nl
;
const
vector
EVals
(
eigenValues
(
T
));
Info
<<
EVals
<<
endl
;
test_eigenvalues
(
T
,
EVals
);
Info
<<
"# Return eigenvectors of a given symmTensor corresponding to"
<<
" given eigenvalues:"
<<
nl
;
const
tensor
EVecs0
(
eigenVectors
(
T
,
EVals
));
Info
<<
EVecs0
<<
endl
;
test_characteristic_equation
(
T
,
EVals
,
EVecs0
);
Info
<<
"# Return eigenvectors of a given symmTensor by computing"
<<
" the eigenvalues of the symmTensor in the background:"
<<
nl
;
const
tensor
EVecs1
(
eigenVectors
(
T
));
Info
<<
EVecs1
<<
endl
;
}
// Do compile-time recursion over the given types
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
==
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
){}
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
<
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
)
{
Info
<<
nl
<<
" ## Test constructors: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_constructors
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test member functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_member_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global operators: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_opers
(
std
::
get
<
I
>
(
types
));
run_tests
<
I
+
1
,
Tp
...
>
(
types
,
typeID
);
}
// * * * * * * * * * * * * * * * Main Program * * * * * * * * * * * * * * * //
int
main
()
{
const
std
::
tuple
<
floatScalar
,
doubleScalar
,
complex
>
types
(
std
::
make_tuple
(
Zero
,
Zero
,
Zero
)
);
const
List
<
word
>
typeID
({
"SymmTensor<floatScalar>"
,
"SymmTensor<doubleScalar>"
,
"SymmTensor<complex>"
});
run_tests
(
types
,
typeID
);
Info
<<
nl
<<
" ## Test symmTensor eigen functions: ##"
<<
nl
;
const
label
numberOfTests
=
10000
;
Random
rndGen
(
1234
);
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
const
symmTensor
T
(
makeRandomContainer
(
rndGen
));
test_eigen_funcs
(
T
);
}
{
Info
<<
nl
<<
" ## A zero symmTensor: ##"
<<
nl
;
const
symmTensor
zeroT
(
Zero
);
test_eigen_funcs
(
zeroT
);
}
{
Info
<<
nl
<<
" ## A symmTensor with 2 repeated eigenvalues: ##"
<<
nl
;
const
symmTensor
T
(
1
.
0
,
0
.
0
,
Foam
::
sqrt
(
2
.
0
),
2
.
0
,
0
.
0
,
0
.
0
);
test_eigen_funcs
(
T
);
}
{
Info
<<
nl
<<
" ## A symmTensor with 3 repeated eigenvalues: ##"
<<
nl
;
const
symmTensor
T
(
0
.
023215
,
-
5.0739e-09
,
-
7.0012e-09
,
0
.
023215
,
-
8.148e-10
,
0
.
023215
);
test_eigen_funcs
(
T
);
}
{
Info
<<
nl
<<
" ## A stiff symmTensor: ##"
<<
nl
;
const
symmTensor
stiff
(
pow
(
10
.
0
,
10
),
pow
(
10
.
0
,
8
),
pow
(
10
.
0
,
-
8
),
pow
(
10
.
0
,
-
8
),
pow
(
10
.
0
,
8
),
pow
(
10
.
0
,
7
)
);
test_eigen_funcs
(
stiff
);
}
{
Info
<<
nl
<<
" ## Random symmTensors with tiny off-diag elements: ##"
<<
nl
;
const
List
<
scalar
>
epsilons
({
0
,
SMALL
,
Foam
::
sqrt
(
SMALL
),
sqr
(
SMALL
),
Foam
::
cbrt
(
SMALL
),
-
SMALL
,
-
Foam
::
sqrt
(
SMALL
),
-
sqr
(
SMALL
),
-
Foam
::
cbrt
(
SMALL
)
});
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
for
(
const
auto
&
eps
:
epsilons
)
{
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
;
T
.
xz
()
=
eps
;
T
.
yz
()
=
eps
;
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
;
T
.
xz
()
=
eps
;
T
.
yz
()
=
eps
;
T
.
zz
()
=
eps
;
test_eigen_funcs
(
T
);
}
{
symmTensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
0
;
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
0
;
test_eigen_funcs
(
T
);
}
}
}
}
#if 0
// Numerical diagonalisation of 2x2 or 3x3 matrices with analytic methods
// are, like the methods currently being used in OpenFOAM, inherently error
// prone. Despite its speed, the analytic methods may becomes inaccurate or
// may even fail completely if the matrix entries differ greatly in
// magnitude, particularly with large off-diagonal elements.
// The remedy is to use iterative or hybrid analytic/iterative methods
// such as published here (for 3x3/2x2 matrices):
// (Kopp, 2008) arXiv.org: physics/0610206
// mpi-hd.mpg.de/personalhomes/globes/3x3/index.html
{
Info<< nl << " ## symmTensors consisting machine epsilons: ##" << nl;
Info<< " # floatScalar" << nl;
const List<floatScalar> floatEpsilons
({
floatScalarGREAT, floatScalarVGREAT, floatScalarROOTVGREAT,
floatScalarSMALL, floatScalarVSMALL, floatScalarROOTVSMALL,
Foam::sqrt(floatScalarSMALL), 0
});
for (const auto& eps : floatEpsilons)
{
const symmTensor T(makeContainer(eps));
test_eigen_funcs(T);
}
Info<< " # doubleScalar" << nl;
const List<doubleScalar> doubleEpsilons
({
doubleScalarGREAT, doubleScalarROOTVGREAT, // doubleVGREAT fails
doubleScalarSMALL, doubleScalarVSMALL, doubleScalarROOTVSMALL,
Foam::sqrt(doubleScalarSMALL), 0
});
for (const auto& eps : doubleEpsilons)
{
const symmTensor T(makeContainer(eps));
test_eigen_funcs(T);
}
}
{
Info<< nl
<< " ## Random symmTensors with machine eps off-diag elmes: ##"
<< nl;
const List<floatScalar> floatEpsilons
({
floatScalarGREAT, floatScalarVGREAT, floatScalarROOTVGREAT,
floatScalarSMALL, floatScalarVSMALL, floatScalarROOTVSMALL
});
const List<doubleScalar> doubleEpsilons
({
doubleScalarGREAT, doubleScalarVGREAT, doubleScalarROOTVGREAT,
doubleScalarSMALL, doubleScalarVSMALL, doubleScalarROOTVSMALL
});
for (label i = 0; i < numberOfTests; ++i)
{
symmTensor T(makeRandomContainer(rndGen));
for (const auto& eps : floatEpsilons)
{
T.xy() = eps;
T.xz() = eps;
T.yz() = eps;
test_eigen_funcs(T);
}
for (const auto& eps : doubleEpsilons)
{
T.xy() = eps;
T.xz() = eps;
T.yz() = eps;
test_eigen_funcs(T);
}
}
}
#endif
if
(
nFail_
)
{
Info
<<
nl
<<
" #### "
<<
"Failed in "
<<
nFail_
<<
" tests "
<<
"out of total "
<<
nTest_
<<
" tests "
<<
"####
\n
"
<<
endl
;
return
1
;
}
Info
<<
nl
<<
" #### Passed all "
<<
nTest_
<<
" tests ####
\n
"
<<
endl
;
return
0
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
OpenFOAM-v2112/applications/test/SymmTensor2D/Make/files
0 → 100644
View file @
55e5a777
Test-SymmTensor2D.C
EXE = $(FOAM_USER_APPBIN)/Test-SymmTensor2D
OpenFOAM-v2112/applications/test/SymmTensor2D/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/SymmTensor2D/Test-SymmTensor2D.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-SymmTensor2D
Description
Tests for \c SymmTensor2D constructors, member functions and operators
using \c floatScalar, \c doubleScalar, and \c complex base types.
Eigen decomposition tests for \c symmTensor2D, i.e. SymmTensor2D<scalar>.
Cross-checks were obtained from 'NumPy 1.15.1' and 'SciPy 1.1.0' if no
theoretical cross-check exists (like eigendecomposition relations), and
were hard-coded for elementwise comparisons.
For \c complex base type, the cross-checks do only involve zero imag part.
\*---------------------------------------------------------------------------*/
#include "symmTensor2D.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Total number of unit tests
unsigned
nTest_
=
0
;
// Total number of failed unit tests
unsigned
nFail_
=
0
;
// Create a random symmTensor2D
symmTensor2D
makeRandomContainer
(
Random
&
rnd
)
{
symmTensor2D
A
(
Zero
);
std
::
generate
(
A
.
begin
(),
A
.
end
(),
[
&
]{
return
rnd
.
GaussNormal
<
scalar
>
();
});
return
A
;
}
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template
<
class
Type
>
typename
std
::
enable_if
<
std
::
is_same
<
floatScalar
,
Type
>::
value
||
std
::
is_same
<
doubleScalar
,
Type
>::
value
||
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
absTol
=
0
,
//<! useful for cmps near zero
const
scalar
relTol
=
1e-8
//<! are values the same within 8 decimals
)
{
Info
<<
msg
<<
x
<<
"?="
<<
y
<<
endl
;
unsigned
nFail
=
0
;
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
),
mag
(
y
)))
<
mag
(
x
-
y
))
{
++
nFail
;
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template
<
class
Type
>
typename
std
::
enable_if
<
!
std
::
is_same
<
floatScalar
,
Type
>::
value
&&
!
std
::
is_same
<
doubleScalar
,
Type
>::
value
&&
!
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
absTol
=
0
,
const
scalar
relTol
=
1e-8
)
{
Info
<<
msg
<<
x
<<
"?="
<<
y
<<
endl
;
unsigned
nFail
=
0
;
for
(
label
i
=
0
;
i
<
pTraits
<
Type
>::
nComponents
;
++
i
)
{
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
[
i
]),
mag
(
y
[
i
])))
<
mag
(
x
[
i
]
-
y
[
i
]))
{
++
nFail
;
}
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Create each constructor of SymmTensor2D<Type>, and print output
template
<
class
Type
>
void
test_constructors
(
Type
)
{
{
Info
<<
"# Construct initialized to zero:"
<<
nl
;
const
SymmTensor2D
<
Type
>
sT
(
Zero
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Construct given VectorSpace:"
<<
nl
;
const
VectorSpace
<
SymmTensor2D
<
Type
>
,
Type
,
3
>
V
(
Zero
);
const
SymmTensor2D
<
Type
>
sT
(
V
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Construct given SphericalTensor2D:"
<<
nl
;
const
SphericalTensor2D
<
Type
>
Sp
(
Type
(
5
));
const
SymmTensor2D
<
Type
>
sT
(
Sp
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Construct given the three components:"
<<
nl
;
const
SymmTensor2D
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
4
)
);
Info
<<
sT
<<
endl
;
}
{
Info
<<
"# Copy construct:"
<<
nl
;
const
SymmTensor2D
<
Type
>
S
(
Type
(
1
),
Type
(
2
),
Type
(
3
));
const
SymmTensor2D
<
Type
>
sT
(
S
);
Info
<<
sT
<<
endl
;
}
}
// Execute each member function of SymmTensor2D<Type>, and print output
template
<
class
Type
>
void
test_member_funcs
(
Type
)
{
SymmTensor2D
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
));
const
SymmTensor2D
<
Type
>
csT
(
Type
(
-
3
),
Type
(
2
),
Type
(
1
));
{
Info
<<
"# Component access:"
<<
nl
;
SymmTensor2D
<
Type
>
cpsT
(
sT
.
xx
(),
sT
.
xy
(),
sT
.
yy
()
);
cmp
(
" 'SymmTensor2D' access:"
,
sT
,
cpsT
);
cmp
(
" xy()=yx():"
,
sT
.
xy
(),
sT
.
yx
());
const
SymmTensor2D
<
Type
>
cpcsT
(
csT
.
xx
(),
csT
.
xy
(),
csT
.
yy
()
);
cmp
(
" 'const SymmTensor2D' access:"
,
csT
,
cpcsT
);
cmp
(
" xy()=yx():"
,
sT
.
xy
(),
sT
.
yx
());
}
{
Info
<<
"# Diagonal access:"
<<
nl
;
cmp
(
" 'SymmTensor2D'.diag():"
,
sT
.
diag
(),
Vector2D
<
Type
>
(
Type
(
1
),
Type
(
-
3
))
);
cmp
(
" 'const SymmTensor2D'.diag():"
,
csT
.
diag
(),
Vector2D
<
Type
>
(
Type
(
-
3
),
Type
(
1
))
);
Info
<<
"# Diagonal manipulation:"
<<
nl
;
sT
.
diag
(
Vector2D
<
Type
>
(
Type
(
-
10
),
Type
(
-
15
)));
cmp
(
" 'SymmTensor2D'.diag('Vector2D'):"
,
sT
.
diag
(),
Vector2D
<
Type
>
(
Type
(
-
10
),
Type
(
-
15
))
);
}
{
Info
<<
"# Tensor operations:"
<<
nl
;
Info
<<
" Transpose:"
<<
nl
;
cmp
(
" 'SymmTensor2D'.T():"
,
sT
.
T
(),
sT
);
}
{
Info
<<
"# Member operators:"
<<
nl
;
sT
=
SphericalTensor2D
<
Type
>
(
Type
(
5
));
cmp
(
" Assign to a SphericalTensor2D:"
,
sT
,
SymmTensor2D
<
Type
>
(
Type
(
5
),
Zero
,
Type
(
5
)
)
);
}
}
// Execute each global function of SymmTensor2D<Type>, and print output
template
<
class
Type
>
void
test_global_funcs
(
Type
)
{
const
SymmTensor2D
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
));
const
Vector2D
<
Type
>
v
(
Type
(
-
3
),
Type
(
2
));
Info
<<
"# Operands: "
<<
nl
<<
" SymmTensor2D<Type> = "
<<
sT
<<
nl
<<
" Vector2D<Type> = "
<<
v
<<
endl
;
cmp
(
" Trace = "
,
tr
(
sT
),
Type
(
-
2
));
cmp
(
" Spherical part = "
,
sph
(
sT
),
SphericalTensor2D
<
Type
>
(
tr
(
sT
)
/
Type
(
2
)));
cmp
(
" Symmetric part = "
,
symm
(
sT
),
sT
);
cmp
(
" Twice the symmetric part = "
,
twoSymm
(
sT
),
2
*
sT
);
cmp
(
" Deviatoric part = "
,
dev
(
sT
),
SymmTensor2D
<
Type
>
(
Type
(
2
),
Type
(
2
),
Type
(
-
2
)
)
);
cmp
(
" Two-third deviatoric part = "
,
dev2
(
sT
),
sT
-
2
*
sph
(
sT
));
cmp
(
" Determinant = "
,
det
(
sT
),
Type
(
-
7
.
000000000000001
));
cmp
(
" Cofactor tensor = "
,
cof
(
sT
),
SymmTensor2D
<
Type
>
(
Type
(
-
3
),
Type
(
-
2
),
Type
(
1
)
)
);
cmp
(
" Inverse = "
,
inv
(
sT
,
det
(
sT
)),
SymmTensor2D
<
Type
>
(
Type
(
0
.
42857143
),
Type
(
0
.
28571429
),
Type
(
-
0
.
14285714
)
),
1e-7
);
cmp
(
" Inverse (another) = "
,
inv
(
sT
),
SymmTensor2D
<
Type
>
(
Type
(
0
.
42857143
),
Type
(
0
.
28571429
),
Type
(
-
0
.
14285714
)
),
1e-7
);
cmp
(
" First invariant = "
,
invariantI
(
sT
),
Type
(
-
2
));
cmp
(
" Second invariant = "
,
invariantII
(
sT
),
Type
(
-
7
));
cmp
(
" Inner-product with self = "
,
innerSqr
(
sT
),
SymmTensor2D
<
Type
>
(
Type
(
5
),
Type
(
-
4
),
Type
(
13
)
)
);
cmp
(
" Square of Frobenius norm = "
,
magSqr
(
sT
),
Type
(
17
.
999999999999996
));
cmp
(
" Outer-product of a Vector2D with itself = "
,
sqr
(
v
),
SymmTensor2D
<
Type
>
(
Type
(
9
),
Type
(
-
6
),
Type
(
4
)
)
);
}
// Execute each global operator of SymmTensor2D<Type>, and print output
template
<
class
Type
>
void
test_global_opers
(
Type
)
{
const
Tensor2D
<
Type
>
T
(
Type
(
1
),
Type
(
-
2
),
Type
(
3
),
Type
(
-
4
)
);
const
SymmTensor2D
<
Type
>
sT
(
Type
(
1
),
Type
(
2
),
Type
(
-
4
)
);
const
SphericalTensor2D
<
Type
>
spT
(
Type
(
-
1
));
const
Vector2D
<
Type
>
v
(
Type
(
3
),
Type
(
-
2
));
const
Type
x
(
-
4
);
Info
<<
"# Operands:"
<<
nl
<<
" Tensor2D = "
<<
T
<<
nl
<<
" SymmTensor2D = "
<<
sT
<<
nl
<<
" SphericalTensor2D = "
<<
spT
<<
nl
<<
" Vector2D = "
<<
v
<<
nl
<<
" Type = "
<<
x
<<
endl
;
cmp
(
" Sum of SpTensor2D-SymmTensor2D = "
,
(
spT
+
sT
),
SymmTensor2D
<
Type
>
(
Type
(
0
),
Type
(
2
),
Type
(
-
5
)
)
);
cmp
(
" Sum of SymmTensor2D-SpTensor2D = "
,
(
sT
+
spT
),
SymmTensor2D
<
Type
>
(
Type
(
0
),
Type
(
2
),
Type
(
-
5
)
)
);
cmp
(
" Subtract SymmTensor2D from SpTensor2D = "
,
(
spT
-
sT
),
SymmTensor2D
<
Type
>
(
Type
(
-
2
),
Type
(
-
2
),
Type
(
3
)
)
);
cmp
(
" Subtract SpTensor2D from SymmTensor2D = "
,
(
sT
-
spT
),
SymmTensor2D
<
Type
>
(
Type
(
2
),
Type
(
2
),
Type
(
-
3
)
)
);
cmp
(
" Division of a SymmTensor2D by a Type"
,
sT
/
x
,
SymmTensor2D
<
Type
>
(
Type
(
-
0
.
25
),
Type
(
-
0
.
5
),
Type
(
1
)
)
);
cmp
(
" Inner-product of SymmTensor2D-SymmTensor2D = "
,
(
sT
&
sT
),
Tensor2D
<
Type
>
(
Type
(
5
),
Type
(
-
6
),
Type
(
-
6
),
Type
(
20
)
)
);
cmp
(
" Inner-product of SpTensor2D-SymmTensor2D = "
,
(
spT
&
sT
),
SymmTensor2D
<
Type
>
(
Type
(
-
1
),
Type
(
-
2
),
Type
(
4
)
)
);
cmp
(
" Inner-product of SymmTensor2D-SpTensor2D = "
,
(
sT
&
spT
),
SymmTensor2D
<
Type
>
(
Type
(
-
1
),
Type
(
-
2
),
Type
(
4
)
)
);
cmp
(
" Inner-product of SymmTensor2D-Vector2D = "
,
(
sT
&
v
),
Vector2D
<
Type
>
(
Type
(
-
1
),
Type
(
14
))
// Column-vector
);
cmp
(
" Inner-product of Vector2D-SymmTensor2D = "
,
(
v
&
sT
),
Vector2D
<
Type
>
(
Type
(
-
1
),
Type
(
14
))
// Row-vector
);
cmp
(
" D-inner-prod of SymmTensor2D-SymmTensor2D = "
,
(
sT
&&
sT
),
Type
(
25
));
cmp
(
" D-inner-prod of SymmTensor2D-SpTensor2D = "
,
(
sT
&&
spT
),
Type
(
3
));
cmp
(
" D-inner-prod of SpTensor2D-SymmTensor2D = "
,
(
spT
&&
sT
),
Type
(
3
));
}
// Return false if given eigenvalues fail to satisy eigenvalue relations
// Relations: (Beauregard & Fraleigh (1973), ISBN 0-395-14017-X, p. 307)
void
test_eigenvalues
(
const
symmTensor2D
&
T
,
const
vector2D
&
EVals
)
{
{
const
scalar
determinant
=
det
(
T
);
const
scalar
EValsProd
=
EVals
.
x
()
*
EVals
.
y
();
cmp
(
"# Product of eigenvalues = det(T):"
,
EValsProd
,
determinant
,
1e-8
);
}
{
const
scalar
trace
=
tr
(
T
);
scalar
EValsSum
=
0
.
0
;
for
(
const
auto
&
val
:
EVals
)
{
EValsSum
+=
val
;
}
cmp
(
"# Sum of eigenvalues = trace(T):"
,
EValsSum
,
trace
);
}
}
// Return false if a given eigenvalue-eigenvector pair
// fails to satisfy the characteristic equation
void
test_characteristic_equation
(
const
symmTensor2D
&
T
,
const
vector2D
&
EVals
,
const
tensor2D
&
EVecs
)
{
Info
<<
"# Characteristic equation:"
<<
nl
;
for
(
direction
dir
=
0
;
dir
<
pTraits
<
vector2D
>::
nComponents
;
++
dir
)
{
Info
<<
"EVal = "
<<
EVals
[
dir
]
<<
nl
<<
"EVec = "
<<
EVecs
.
row
(
dir
)
<<
nl
;
const
vector2D
leftSide
(
T
&
EVecs
.
row
(
dir
));
const
vector2D
rightSide
(
EVals
[
dir
]
*
EVecs
.
row
(
dir
));
const
vector2D
X
(
leftSide
-
rightSide
);
for
(
const
auto
x
:
X
)
{
cmp
(
" (sT & EVec - EVal*EVec) = 0:"
,
x
,
0
.
0
,
1e-5
);
}
}
}
// Return false if the eigen functions fail to satisfy relations
void
test_eigen_funcs
(
const
symmTensor2D
&
T
)
{
Info
<<
"# Operand:"
<<
nl
<<
" symmTensor2D = "
<<
T
<<
nl
;
Info
<<
"# Return eigenvalues of a given symmTensor2D:"
<<
nl
;
const
vector2D
EVals
(
eigenValues
(
T
));
Info
<<
EVals
<<
endl
;
test_eigenvalues
(
T
,
EVals
);
Info
<<
"# Return eigenvectors of a given symmTensor2D corresponding to"
<<
" given eigenvalues:"
<<
nl
;
const
tensor2D
EVecs0
(
eigenVectors
(
T
,
EVals
));
Info
<<
EVecs0
<<
endl
;
test_characteristic_equation
(
T
,
EVals
,
EVecs0
);
Info
<<
"# Return eigenvectors of a given symmTensor2D by computing"
<<
" the eigenvalues of the symmTensor2D in the background:"
<<
nl
;
const
tensor2D
EVecs1
(
eigenVectors
(
T
));
Info
<<
EVecs1
<<
endl
;
}
// Do compile-time recursion over the given types
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
==
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
){}
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
<
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
)
{
Info
<<
nl
<<
" ## Test constructors: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_constructors
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test member functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_member_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global operators: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_opers
(
std
::
get
<
I
>
(
types
));
run_tests
<
I
+
1
,
Tp
...
>
(
types
,
typeID
);
}
// * * * * * * * * * * * * * * * Main Program * * * * * * * * * * * * * * * //
int
main
(
int
argc
,
char
*
argv
[])
{
const
std
::
tuple
<
floatScalar
,
doubleScalar
,
complex
>
types
(
std
::
make_tuple
(
Zero
,
Zero
,
Zero
)
);
const
List
<
word
>
typeID
({
"SymmTensor2D<floatScalar>"
,
"SymmTensor2D<doubleScalar>"
,
"SymmTensor2D<complex>"
});
run_tests
(
types
,
typeID
);
Info
<<
nl
<<
" ## Test symmTensor2D eigen functions: ##"
<<
nl
;
const
label
numberOfTests
=
10000
;
Random
rndGen
(
1234
);
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
const
symmTensor2D
T
(
makeRandomContainer
(
rndGen
));
test_eigen_funcs
(
T
);
}
{
Info
<<
nl
<<
" ## A symmTensor2D with T.xy = VSMALL"
<<
nl
;
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
symmTensor2D
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
VSMALL
;
test_eigen_funcs
(
T
);
}
}
{
Info
<<
nl
<<
" ## A symmTensor2D with T.xx = T.yy: ##"
<<
nl
;
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
symmTensor2D
T
(
makeRandomContainer
(
rndGen
));
T
.
xx
()
=
T
.
yy
();
test_eigen_funcs
(
T
);
}
}
{
Info
<<
nl
<<
" ## A zero symmTensor2D: ##"
<<
nl
;
const
symmTensor2D
zeroT
(
Zero
);
test_eigen_funcs
(
zeroT
);
}
{
Info
<<
nl
<<
" ## A stiff symmTensor2D: ##"
<<
nl
;
const
symmTensor2D
stiff
(
pow
(
10
.
0
,
10
),
pow
(
10
.
0
,
-
8
),
pow
(
10
.
0
,
9
)
);
test_eigen_funcs
(
stiff
);
}
{
Info
<<
nl
<<
" ## Random symmTensor2D with tiny off-diag elements: ##"
<<
nl
;
const
List
<
scalar
>
epsilons
({
0
,
SMALL
,
Foam
::
sqrt
(
SMALL
),
sqr
(
SMALL
),
Foam
::
cbrt
(
SMALL
),
-
SMALL
,
-
Foam
::
sqrt
(
SMALL
),
-
sqr
(
SMALL
),
-
Foam
::
cbrt
(
SMALL
)
});
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
for
(
const
auto
&
eps
:
epsilons
)
{
{
symmTensor2D
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
symmTensor2D
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
;
test_eigen_funcs
(
T
);
}
}
}
}
if
(
nFail_
)
{
Info
<<
nl
<<
" #### "
<<
"Failed in "
<<
nFail_
<<
" tests "
<<
"out of total "
<<
nTest_
<<
" tests "
<<
"####
\n
"
<<
endl
;
return
1
;
}
Info
<<
nl
<<
" #### Passed all "
<<
nTest_
<<
" tests ####
\n
"
<<
endl
;
return
0
;
}
// ************************************************************************* //
OpenFOAM-v2112/applications/test/Tensor/Make/files
0 → 100644
View file @
55e5a777
Test-Tensor.C
EXE = $(FOAM_USER_APPBIN)/Test-Tensor
OpenFOAM-v2112/applications/test/Tensor/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/Tensor/Test-Tensor.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-Tensor
Description
Tests for \c Tensor constructors, member functions and operators
using \c floatScalar, \c doubleScalar, and \c complex base types.
Eigen decomposition tests for \c tensor, i.e. Tensor<scalar>.
Cross-checks were obtained from 'NumPy 1.15.1' and 'SciPy 1.1.0' if no
theoretical cross-check exists (like eigendecomposition relations), and
were hard-coded for elementwise comparisons.
For \c complex base type, the cross-checks do only involve zero imag part.
\*---------------------------------------------------------------------------*/
#include "tensor.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Total number of unit tests
unsigned
nTest_
=
0
;
// Total number of failed unit tests
unsigned
nFail_
=
0
;
// Create a random tensor
tensor
makeRandomContainer
(
Random
&
rnd
)
{
tensor
A
(
Zero
);
std
::
generate
(
A
.
begin
(),
A
.
end
(),
[
&
]{
return
rnd
.
GaussNormal
<
scalar
>
();
});
return
A
;
}
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template
<
class
Type
>
typename
std
::
enable_if
<
std
::
is_same
<
floatScalar
,
Type
>::
value
||
std
::
is_same
<
doubleScalar
,
Type
>::
value
||
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
absTol
=
0
,
//<! useful for cmps near zero
const
scalar
relTol
=
1e-8
//<! are values the same within 8 decimals
)
{
Info
<<
msg
<<
x
<<
"?="
<<
y
<<
endl
;
unsigned
nFail
=
0
;
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
),
mag
(
y
)))
<
mag
(
x
-
y
))
{
++
nFail
;
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template
<
class
Type
>
typename
std
::
enable_if
<
!
std
::
is_same
<
floatScalar
,
Type
>::
value
&&
!
std
::
is_same
<
doubleScalar
,
Type
>::
value
&&
!
std
::
is_same
<
complex
,
Type
>::
value
,
void
>::
type
cmp
(
const
word
&
msg
,
const
Type
&
x
,
const
Type
&
y
,
const
scalar
absTol
=
0
,
const
scalar
relTol
=
1e-8
)
{
Info
<<
msg
<<
x
<<
"?="
<<
y
<<
endl
;
unsigned
nFail
=
0
;
for
(
label
i
=
0
;
i
<
pTraits
<
Type
>::
nComponents
;
++
i
)
{
if
(
max
(
absTol
,
relTol
*
max
(
mag
(
x
[
i
]),
mag
(
y
[
i
])))
<
mag
(
x
[
i
]
-
y
[
i
]))
{
++
nFail
;
}
}
if
(
nFail
)
{
Info
<<
nl
<<
" #### Fail in "
<<
nFail
<<
" comps ####"
<<
nl
<<
endl
;
++
nFail_
;
}
++
nTest_
;
}
// Create each constructor of Tensor<Type>, and print output
template
<
class
Type
>
void
test_constructors
(
Type
)
{
{
Info
<<
"# Construct initialized to zero:"
<<
nl
;
const
Tensor
<
Type
>
T
(
Zero
);
Info
<<
T
<<
endl
;
}
{
Info
<<
"# Construct given MatrixSpace of the same rank:"
<<
nl
;
const
MatrixSpace
<
Tensor
<
Type
>
,
Type
,
3
,
3
>
M
(
Zero
);
const
Tensor
<
Type
>
T
(
M
);
Info
<<
T
<<
endl
;
}
{
Info
<<
"# Construct given VectorSpace of the same rank:"
<<
nl
;
const
VectorSpace
<
Tensor
<
Type
>
,
Type
,
9
>
V
(
Zero
);
const
Tensor
<
Type
>
T
(
V
);
Info
<<
T
<<
endl
;
}
{
Info
<<
"# Construct given SphericalTensor<Type>:"
<<
nl
;
const
SphericalTensor
<
Type
>
Sp
(
Type
(
5
));
const
Tensor
<
Type
>
T
(
Sp
);
Info
<<
T
<<
endl
;
}
{
Info
<<
"# Construct given SymmTensor<Type>:"
<<
nl
;
const
SymmTensor
<
Type
>
S
(
Type
(
1
),
Type
(
2
),
Type
(
3
),
Type
(
5
),
Type
(
6
),
Type
(
9
)
);
const
Tensor
<
Type
>
T
(
S
);
Info
<<
T
<<
endl
;
}
{
Info
<<
"# Construct given triad of row vectors,"
<<
" optionally treated as transposed (ie, column vectors)"
<<
nl
;
const
Vector
<
Vector
<
Type
>>
vecs
(
Vector
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
3
)),
Vector
<
Type
>
(
Type
(
4
),
Type
(
5
),
Type
(
6
)),
Vector
<
Type
>
(
Type
(
7
),
Type
(
8
),
Type
(
9
))
);
const
Tensor
<
Type
>
T
(
vecs
);
Info
<<
T
<<
nl
;
const
Tensor
<
Type
>
transposedT
(
vecs
,
true
);
Info
<<
transposedT
<<
endl
;
}
{
Info
<<
"# Construct given the three row vectors,"
<<
" optionally treated as transposed (ie, column vectors)"
<<
nl
;
const
Vector
<
Type
>
a
(
Type
(
1
),
Type
(
2
),
Type
(
3
));
const
Vector
<
Type
>
b
(
Type
(
4
),
Type
(
5
),
Type
(
6
));
const
Vector
<
Type
>
c
(
Type
(
7
),
Type
(
8
),
Type
(
9
));
const
Tensor
<
Type
>
T
(
a
,
b
,
c
);
Info
<<
T
<<
nl
;
const
Tensor
<
Type
>
transposedT
(
a
,
b
,
c
,
true
);
Info
<<
transposedT
<<
endl
;
}
{
Info
<<
"# Construct given the nine components:"
<<
nl
;
const
Tensor
<
Type
>
T
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
);
Info
<<
T
<<
endl
;
}
{
Info
<<
"# Copy construct:"
<<
nl
;
const
Tensor
<
Type
>
T
(
Zero
);
const
Tensor
<
Type
>
copyT
(
T
);
Info
<<
T
<<
tab
<<
copyT
<<
endl
;
}
}
// Execute each member function of Tensor<Type>, and print output
template
<
class
Type
>
void
test_member_funcs
(
Type
)
{
Tensor
<
Type
>
T
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
);
Tensor
<
Type
>
Tbak
=
T
;
const
Tensor
<
Type
>
cT
(
Type
(
-
9
),
Type
(
8
),
Type
(
7
),
Type
(
-
6
),
Type
(
5
),
Type
(
4
),
Type
(
-
3
),
Type
(
2
),
Type
(
1
)
);
Info
<<
"# Operand: "
<<
nl
<<
" Tensor = "
<<
T
<<
endl
;
{
Info
<<
"# Component access:"
<<
nl
;
Tensor
<
Type
>
cpT
(
T
.
xx
(),
T
.
xy
(),
T
.
xz
(),
T
.
yx
(),
T
.
yy
(),
T
.
yz
(),
T
.
zx
(),
T
.
zy
(),
T
.
zz
()
);
cmp
(
" 'Tensor' access:"
,
T
,
cpT
);
const
Tensor
<
Type
>
cpcT
(
cT
.
xx
(),
cT
.
xy
(),
cT
.
xz
(),
cT
.
yx
(),
cT
.
yy
(),
cT
.
yz
(),
cT
.
zx
(),
cT
.
zy
(),
cT
.
zz
()
);
cmp
(
" 'const Tensor' access:"
,
cT
,
cpcT
);
}
{
Info
<<
"# Column-vector access:"
<<
nl
;
cmp
(
" cx():"
,
T
.
cx
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
4
),
Type
(
7
)));
cmp
(
" cy():"
,
T
.
cy
(),
Vector
<
Type
>
(
Type
(
2
),
Type
(
5
),
Type
(
8
)));
cmp
(
" cz():"
,
T
.
cz
(),
Vector
<
Type
>
(
Type
(
-
3
),
Type
(
-
6
),
Type
(
-
9
)));
cmp
(
" col(0):"
,
T
.
col
(
0
),
Vector
<
Type
>
(
Type
(
1
),
Type
(
4
),
Type
(
7
)));
cmp
(
" col(1):"
,
T
.
col
(
1
),
Vector
<
Type
>
(
Type
(
2
),
Type
(
5
),
Type
(
8
)));
cmp
(
" col(2):"
,
T
.
col
(
2
),
Vector
<
Type
>
(
Type
(
-
3
),
Type
(
-
6
),
Type
(
-
9
)));
cmp
(
" col<0>:"
,
T
.
template
col
<
0
>
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
4
),
Type
(
7
))
);
cmp
(
" col<1>:"
,
T
.
template
col
<
1
>
(),
Vector
<
Type
>
(
Type
(
2
),
Type
(
5
),
Type
(
8
))
);
cmp
(
" col<2>:"
,
T
.
template
col
<
2
>
(),
Vector
<
Type
>
(
Type
(
-
3
),
Type
(
-
6
),
Type
(
-
9
))
);
// Compilation error: Info << " col<3> = " << T.col<3>() << nl;
Info
<<
"# Column-vector manipulation:"
<<
nl
;
T
.
col
(
1
,
Vector
<
Type
>
(
Type
(
0
),
Type
(
1
),
Type
(
99
)));
cmp
(
" col(1, Vector):"
,
T
.
col
(
1
),
Vector
<
Type
>
(
Type
(
0
),
Type
(
1
),
Type
(
99
))
);
T
.
cols
(
Vector
<
Type
>
(
Type
(
1
),
Type
(
1
),
Type
(
1
)),
Vector
<
Type
>
(
Type
(
-
1
),
Type
(
1
),
Type
(
2
)),
Vector
<
Type
>
(
Type
(
1
),
Type
(
1
),
Type
(
3
))
);
cmp
(
" cols(Vectors):"
,
T
,
Tensor
<
Type
>
(
Type
(
1
),
Type
(
-
1
),
Type
(
1
),
Type
(
1
),
Type
(
1
),
Type
(
1
),
Type
(
1
),
Type
(
2
),
Type
(
3
)
)
);
}
{
Info
<<
"# Row-vector access:"
<<
nl
;
T
=
Tbak
;
cmp
(
" x():"
,
T
.
x
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
)));
cmp
(
" y():"
,
T
.
y
(),
Vector
<
Type
>
(
Type
(
4
),
Type
(
5
),
Type
(
-
6
)));
cmp
(
" z():"
,
T
.
z
(),
Vector
<
Type
>
(
Type
(
7
),
Type
(
8
),
Type
(
-
9
)));
cmp
(
" row(0):"
,
T
.
row
(
0
),
Vector
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
)));
cmp
(
" row(1):"
,
T
.
row
(
1
),
Vector
<
Type
>
(
Type
(
4
),
Type
(
5
),
Type
(
-
6
)));
cmp
(
" row(2):"
,
T
.
row
(
2
),
Vector
<
Type
>
(
Type
(
7
),
Type
(
8
),
Type
(
-
9
)));
cmp
(
" row<0>:"
,
T
.
template
row
<
0
>
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
))
);
cmp
(
" row<1>:"
,
T
.
template
row
<
1
>
(),
Vector
<
Type
>
(
Type
(
4
),
Type
(
5
),
Type
(
-
6
))
);
cmp
(
" row<2>:"
,
T
.
template
row
<
2
>
(),
Vector
<
Type
>
(
Type
(
7
),
Type
(
8
),
Type
(
-
9
))
);
// Compilation error: Info << " row<3> = " << T.row<3>() << nl;
Info
<<
"# Row-vector manipulation:"
<<
nl
;
T
.
row
(
1
,
Vector
<
Type
>
(
Type
(
0
),
Type
(
1
),
Type
(
99
)));
cmp
(
" row(1, Vector):"
,
T
.
row
(
1
),
Vector
<
Type
>
(
Type
(
0
),
Type
(
1
),
Type
(
99
))
);
T
.
rows
(
Vector
<
Type
>
(
Type
(
1
),
Type
(
1
),
Type
(
1
)),
Vector
<
Type
>
(
Type
(
-
1
),
Type
(
1
),
Type
(
2
)),
Vector
<
Type
>
(
Type
(
1
),
Type
(
1
),
Type
(
3
))
);
cmp
(
" rows(Vectors):"
,
T
,
Tensor
<
Type
>
(
Type
(
1
),
Type
(
1
),
Type
(
1
),
Type
(
-
1
),
Type
(
1
),
Type
(
2
),
Type
(
1
),
Type
(
1
),
Type
(
3
)
)
);
}
{
Info
<<
"# Diagonal access:"
<<
nl
;
T
=
Tbak
;
cmp
(
" 'Tensor'.diag():"
,
T
.
diag
(),
Vector
<
Type
>
(
Type
(
1
),
Type
(
5
),
Type
(
-
9
))
);
cmp
(
" 'const Tensor'.diag():"
,
cT
.
diag
(),
Vector
<
Type
>
(
Type
(
-
9
),
Type
(
5
),
Type
(
1
))
);
Info
<<
"# Diagonal manipulation:"
<<
nl
;
T
.
diag
(
Vector
<
Type
>
(
Type
(
-
10
),
Type
(
-
15
),
Type
(
-
20
)));
cmp
(
" 'Tensor'.diag('Vector'):"
,
T
.
diag
(),
Vector
<
Type
>
(
Type
(
-
10
),
Type
(
-
15
),
Type
(
-
20
))
);
}
{
Info
<<
"# Tensor operations:"
<<
nl
;
T
=
Tbak
;
cmp
(
" Transpose:"
,
T
,
(
T
.
T
()).
T
());
cmp
// Singular matrix
(
" Inverse:"
,
T
.
inv
(),
Tensor
<
Type
>
(
Type
(
-
4.50359963e+15
),
Type
(
9.00719925e+15
),
Type
(
-
4.50359963e+15
),
Type
(
9.00719925e+15
),
Type
(
-
1.80143985e+16
),
Type
(
9.00719925e+15
),
Type
(
4.50359963e+15
),
Type
(
-
9.00719925e+15
),
Type
(
4.50359963e+15
)
)
);
cmp
(
" Inner-product:"
,
T
.
inner
(
T
),
Tensor
<
Type
>
(
Type
(
-
12
),
Type
(
-
12
),
Type
(
12
),
Type
(
-
18
),
Type
(
-
15
),
Type
(
12
),
Type
(
-
24
),
Type
(
-
18
),
Type
(
12
)
)
);
cmp
(
" Schur-product:"
,
T
.
schur
(
T
),
Tensor
<
Type
>
(
Type
(
1
),
Type
(
4
),
Type
(
9
),
Type
(
16
),
Type
(
25
),
Type
(
36
),
Type
(
49
),
Type
(
64
),
Type
(
81
)
)
);
}
{
Info
<<
"# Member operators:"
<<
nl
;
T
=
Tbak
;
T
&=
T
;
cmp
(
" Assign inner-product of this with another Tensor:"
,
T
,
(
Tbak
&
Tbak
)
);
T
=
VectorSpace
<
Tensor
<
Type
>
,
Type
,
9
>
(
Zero
);
cmp
(
" Assign to an equivalent vector space:"
,
T
,
Tensor
<
Type
>
(
Zero
)
);
T
=
SphericalTensor
<
Type
>
(
Type
(
5
));
cmp
(
" Assign to a SphericalTensor:"
,
T
,
Tensor
<
Type
>
(
Type
(
5
),
Zero
,
Zero
,
Zero
,
Type
(
5
),
Zero
,
Zero
,
Zero
,
Type
(
5
)
)
);
T
=
SymmTensor
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
cmp
(
" Assign to a SymmTensor:"
,
T
,
Tensor
<
Type
>
(
Type
(
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
2
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
3
),
Type
(
-
6
),
Type
(
-
9
)
)
);
T
=
Vector
<
Vector
<
Type
>>
(
Vector
<
Type
>
(
Type
(
-
1
),
Type
(
2
),
Type
(
3
)),
Vector
<
Type
>
(
Type
(
-
4
),
Type
(
5
),
Type
(
6
)),
Vector
<
Type
>
(
Type
(
4
),
Type
(
-
5
),
Type
(
6
))
);
cmp
(
" Assign to a triad of row vectors:"
,
T
,
Tensor
<
Type
>
(
Type
(
-
1
),
Type
(
2
),
Type
(
3
),
Type
(
-
4
),
Type
(
5
),
Type
(
6
),
Type
(
4
),
Type
(
-
5
),
Type
(
6
)
)
);
}
}
// Execute each global function of Tensor<Type>, and print output
template
<
class
Type
>
void
test_global_funcs
(
Type
)
{
const
Tensor
<
Type
>
T
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
);
const
SymmTensor
<
Type
>
sT
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
Info
<<
"# Operands: "
<<
nl
<<
" Tensor = "
<<
T
<<
nl
<<
" SymmTensor = "
<<
sT
<<
endl
;
cmp
(
" Trace = "
,
tr
(
T
),
Type
(
-
5
));
cmp
(
" Spherical part = "
,
sph
(
T
),
SphericalTensor
<
Type
>
(
tr
(
T
)
/
Type
(
3
)));
cmp
(
" Symmetric part = "
,
symm
(
T
),
SymmTensor
<
Type
>
(
Type
(
-
1
),
Type
(
3
),
Type
(
2
),
Type
(
5
),
Type
(
1
),
Type
(
-
9
)
)
);
cmp
(
" Twice the symmetric part = "
,
twoSymm
(
T
),
SymmTensor
<
Type
>
(
Type
(
-
2
),
Type
(
6
),
Type
(
4
),
Type
(
10
),
Type
(
2
),
Type
(
-
18
)
)
);
cmp
(
" Skew-symmetric part = "
,
skew
(
T
),
Tensor
<
Type
>
(
Type
(
0
),
Type
(
-
1
),
Type
(
-
5
),
Type
(
1
),
Type
(
0
),
Type
(
-
7
),
Type
(
5
),
Type
(
7
),
Type
(
0
)
)
);
/*
// Complex-type is not supported for this function.
cmp
(
" Skew-symmetric part of a SymmTensor = ",
skew(sT),
Tensor<Type>(Zero)
);
*/
cmp
(
" Deviatoric part = "
,
dev
(
T
),
Tensor
<
Type
>
(
Type
(
0
.
66666667
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
6
.
66666667
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
7
.
33333333
)
),
1e-7
);
cmp
(
" Two-third deviatoric part = "
,
dev2
(
T
),
T
-
2
*
sph
(
T
));
cmp
(
" Determinant = "
,
det
(
T
),
Type
(
-
6
.
000000000000005
));
cmp
(
" Cofactor tensor = "
,
cof
(
T
),
Tensor
<
Type
>
(
Type
(
3
),
Type
(
-
6
),
Type
(
-
3
),
Type
(
-
6
),
Type
(
30
),
Type
(
22
),
Type
(
3
),
Type
(
-
18
),
Type
(
-
13
)
)
);
cmp
(
" Inverse = "
,
inv
(
T
,
det
(
T
)),
Tensor
<
Type
>
(
Type
(
-
0
.
5
),
Type
(
1
),
Type
(
-
0
.
5
),
Type
(
1
),
Type
(
-
5
),
Type
(
3
),
Type
(
0
.
5
),
Type
(
-
3
.
66666667
),
Type
(
2
.
16666667
)
),
1e-8
);
cmp
(
" Inverse (another) = "
,
inv
(
T
),
Tensor
<
Type
>
(
Type
(
-
0
.
5
),
Type
(
1
),
Type
(
-
0
.
5
),
Type
(
1
),
Type
(
-
5
),
Type
(
3
),
Type
(
0
.
5
),
Type
(
-
3
.
66666667
),
Type
(
2
.
16666667
)
),
1e-8
);
cmp
(
" Inverse (another) = "
,
T
.
inv
(),
Tensor
<
Type
>
(
Type
(
-
0
.
5
),
Type
(
1
),
Type
(
-
0
.
5
),
Type
(
1
),
Type
(
-
5
),
Type
(
3
),
Type
(
0
.
5
),
Type
(
-
3
.
66666667
),
Type
(
2
.
16666667
)
),
1e-8
);
cmp
(
" First invariant = "
,
invariantI
(
T
),
Type
(
-
5
));
cmp
(
" Second invariant = "
,
invariantII
(
T
),
Type
(
20
));
cmp
(
" Third invariant = "
,
invariantIII
(
T
),
Type
(
-
6
.
000000000000005
));
}
// Execute each global operator of Tensor<Type>, and print output
template
<
class
Type
>
void
test_global_opers
(
Type
)
{
const
Tensor
<
Type
>
T
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
);
const
SymmTensor
<
Type
>
sT
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
5
),
Type
(
-
6
),
Type
(
-
9
)
);
const
SphericalTensor
<
Type
>
spT
(
Type
(
1
));
const
Vector
<
Type
>
v
(
Type
(
3
),
Type
(
2
),
Type
(
1
));
const
Type
x
(
4
);
Info
<<
"# Operands:"
<<
nl
<<
" Tensor = "
<<
T
<<
nl
<<
" SymmTensor = "
<<
sT
<<
nl
<<
" SphericalTensor = "
<<
spT
<<
nl
<<
" Vector = "
<<
v
<<
nl
<<
" Type = "
<<
x
<<
endl
;
cmp
(
" Sum of SpTensor-Tensor = "
,
(
spT
+
T
),
Tensor
<
Type
>
(
Type
(
0
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
6
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
8
)
)
);
cmp
(
" Sum of Tensor-SpTensor = "
,
(
T
+
spT
),
Tensor
<
Type
>
(
Type
(
0
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
6
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
8
)
)
);
cmp
(
" Sum of SymmTensor-Tensor = "
,
(
sT
+
T
),
Tensor
<
Type
>
(
Type
(
-
2
),
Type
(
4
),
Type
(
-
6
),
Type
(
6
),
Type
(
10
),
Type
(
-
12
),
Type
(
4
),
Type
(
2
),
Type
(
-
18
)
)
);
cmp
(
" Sum of Tensor-SymmTensor = "
,
(
T
+
sT
),
Tensor
<
Type
>
(
Type
(
-
2
),
Type
(
4
),
Type
(
-
6
),
Type
(
6
),
Type
(
10
),
Type
(
-
12
),
Type
(
4
),
Type
(
2
),
Type
(
-
18
)
)
);
cmp
(
" Subtract Tensor from SpTensor = "
,
(
spT
-
T
),
Tensor
<
Type
>
(
Type
(
2
),
Type
(
-
2
),
Type
(
3
),
Type
(
-
4
),
Type
(
-
4
),
Type
(
6
),
Type
(
-
7
),
Type
(
-
8
),
Type
(
10
)
)
);
cmp
(
" Subtract SpTensor from Tensor = "
,
(
T
-
spT
),
Tensor
<
Type
>
(
Type
(
-
2
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
4
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
10
)
)
);
cmp
(
" Subtract Tensor from SymmTensor = "
,
(
sT
-
T
),
Tensor
<
Type
>
(
Type
(
0
),
Type
(
0
),
Type
(
0
),
Type
(
-
2
),
Type
(
0
),
Type
(
0
),
Type
(
-
10
),
Type
(
-
14
),
Type
(
0
)
)
);
cmp
(
" Subtract SymmTensor from Tensor = "
,
(
T
-
sT
),
Tensor
<
Type
>
(
Type
(
0
),
Type
(
0
),
Type
(
0
),
Type
(
2
),
Type
(
0
),
Type
(
0
),
Type
(
10
),
Type
(
14
),
Type
(
0
)
)
);
cmp
(
" Hodge dual of a Tensor = "
,
*
T
,
Vector
<
Type
>
(
T
.
yz
(),
-
T
.
xz
(),
T
.
xy
())
);
cmp
(
" Hodge dual of a Vector = "
,
*
v
,
Tensor
<
Type
>
(
Zero
,
-
v
.
z
(),
v
.
y
(),
v
.
z
(),
Zero
,
-
v
.
x
(),
-
v
.
y
(),
v
.
x
(),
Zero
)
);
/*cmp
(
" Division of Vector by Tensor = ",
(v/T),
Tensor<Type>
(
Type(-3), Type(1), Type(-0.33333333),
Type(0.75), Type(0.4), Type(-0.16666667),
Type(0.42857143), Type(0.25), Type(-0.11111111)
)
);*/
cmp
(
" Division of Tensor by Type = "
,
(
T
/
x
),
Tensor
<
Type
>
(
Type
(
-
0
.
25
),
Type
(
0
.
5
),
Type
(
-
0
.
75
),
Type
(
1
),
Type
(
1
.
25
),
Type
(
-
1
.
5
),
Type
(
1
.
75
),
Type
(
2
),
Type
(
-
2
.
25
)
)
);
cmp
(
" Inner-product of Tensor-Tensor = "
,
(
T
&
T
),
Tensor
<
Type
>
(
Type
(
-
12
),
Type
(
-
16
),
Type
(
18
),
Type
(
-
26
),
Type
(
-
15
),
Type
(
12
),
Type
(
-
38
),
Type
(
-
18
),
Type
(
12
)
)
);
cmp
(
" Inner-product of SpTensor-Tensor = "
,
(
spT
&
T
),
Tensor
<
Type
>
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
)
);
cmp
(
" Inner-product of Tensor-SpTensor = "
,
(
T
&
spT
),
Tensor
<
Type
>
(
Type
(
-
1
),
Type
(
2
),
Type
(
-
3
),
Type
(
4
),
Type
(
5
),
Type
(
-
6
),
Type
(
7
),
Type
(
8
),
Type
(
-
9
)
)
);
cmp
(
" Inner-product of SymmTensor-Tensor = "
,
(
sT
&
T
),
Tensor
<
Type
>
(
Type
(
-
12
),
Type
(
-
16
),
Type
(
18
),
Type
(
-
24
),
Type
(
-
19
),
Type
(
18
),
Type
(
-
84
),
Type
(
-
108
),
Type
(
126
)
)
);
cmp
(
" Inner-product of Tensor-SymmTensor = "
,
(
T
&
sT
),
Tensor
<
Type
>
(
Type
(
14
),
Type
(
26
),
Type
(
18
),
Type
(
24
),
Type
(
69
),
Type
(
12
),
Type
(
36
),
Type
(
108
),
Type
(
12
)
)
);
cmp
(
" Inner-product of Tensor-Vector = "
,
(
T
&
v
),
Vector
<
Type
>
(
Type
(
-
2
),
Type
(
16
),
Type
(
28
))
// Column-vector
);
cmp
(
" Inner-product of Vector-Tensor = "
,
(
v
&
T
),
Vector
<
Type
>
(
Type
(
12
),
Type
(
24
),
Type
(
-
30
))
// Row-vector
);
cmp
(
" D-inner-product of SpTensor-Tensor = "
,
(
spT
&&
T
),
Type
(
-
5
));
cmp
(
" D-inner-product of Tensor-SpTensor = "
,
(
T
&&
spT
),
Type
(
-
5
));
cmp
(
" D-inner-product of SymmTensor-Tensor = "
,
(
sT
&&
T
),
Type
(
95
));
cmp
(
" D-inner-product of Tensor-SymmTensor = "
,
(
T
&&
sT
),
Type
(
95
));
cmp
(
" Outer-product of Vector-Vector = "
,
(
v
*
v
),
Tensor
<
Type
>
(
Type
(
9
),
Type
(
6
),
Type
(
3
),
Type
(
6
),
Type
(
4
),
Type
(
2
),
Type
(
3
),
Type
(
2
),
Type
(
1
)
)
);
}
// Return false if given eigenvalues fail to satisy eigenvalue relations
// Relations: (Beauregard & Fraleigh (1973), ISBN 0-395-14017-X, p. 307)
void
test_eigenvalues
(
const
tensor
&
T
,
const
Vector
<
complex
>&
EVals
,
const
bool
prod
=
true
)
{
if
(
prod
)
{
const
scalar
determinant
=
det
(
T
);
// In case of complex EVals, the production is effectively scalar
// due to the (complex*complex conjugate) results in zero imag part
const
scalar
EValsProd
=
((
EVals
.
x
()
*
EVals
.
y
()
*
EVals
.
z
()).
real
());
cmp
(
"# Product of eigenvalues = det(T):"
,
EValsProd
,
determinant
,
1e-8
);
}
{
const
scalar
trace
=
tr
(
T
);
scalar
EValsSum
=
0
.
0
;
// In case of complex EVals, the summation is effectively scalar
// due to the (complex+complex conjugate) results in zero imag part
for
(
const
auto
&
val
:
EVals
)
{
EValsSum
+=
val
.
real
();
}
cmp
(
"# Sum of eigenvalues = trace(T):"
,
EValsSum
,
trace
);
}
}
// Return false if a given eigenvalue-eigenvector pair
// fails to satisfy the characteristic equation
void
test_characteristic_equation
(
const
tensor
&
T
,
const
Vector
<
complex
>&
EVals
,
const
Tensor
<
complex
>&
EVecs
)
{
Info
<<
"# Characteristic equation:"
<<
nl
;
Tensor
<
complex
>
Tc
(
Zero
);
forAll
(
T
,
i
)
{
Tc
[
i
]
=
complex
(
T
[
i
],
0
);
}
for
(
direction
dir
=
0
;
dir
<
pTraits
<
vector
>::
nComponents
;
++
dir
)
{
const
Vector
<
complex
>
leftSide
(
Tc
&
EVecs
.
row
(
dir
));
const
Vector
<
complex
>
rightSide
(
EVals
[
dir
]
*
EVecs
.
row
(
dir
));
const
Vector
<
complex
>
X
(
leftSide
-
rightSide
);
for
(
const
auto
x
:
X
)
{
cmp
(
" (sT & EVec - EVal*EVec) = 0:"
,
mag
(
x
),
0
.
0
,
1e-5
);
}
}
}
// Return false if the eigen functions fail to satisfy relations
void
test_eigen_funcs
(
const
tensor
&
T
,
const
bool
prod
=
true
)
{
Info
<<
"# Operand:"
<<
nl
<<
" tensor = "
<<
T
<<
nl
;
Info
<<
"# Return eigenvalues of a given tensor:"
<<
nl
;
const
Vector
<
complex
>
EVals
(
eigenValues
(
T
));
Info
<<
EVals
<<
endl
;
test_eigenvalues
(
T
,
EVals
,
prod
);
Info
<<
"# Return an eigenvector of a given tensor in a given direction"
<<
" corresponding to a given eigenvalue:"
<<
nl
;
const
Vector
<
complex
>
standardBasis1
(
Zero
,
pTraits
<
complex
>::
one
,
Zero
);
const
Vector
<
complex
>
standardBasis2
(
Zero
,
Zero
,
pTraits
<
complex
>::
one
);
const
Vector
<
complex
>
EVec
(
eigenVector
(
T
,
EVals
.
x
(),
standardBasis1
,
standardBasis2
)
);
Info
<<
EVec
<<
endl
;
Info
<<
"# Return eigenvectors of a given tensor corresponding to"
<<
" given eigenvalues:"
<<
nl
;
const
Tensor
<
complex
>
EVecs0
(
eigenVectors
(
T
,
EVals
));
Info
<<
EVecs0
<<
endl
;
test_characteristic_equation
(
T
,
EVals
,
EVecs0
);
Info
<<
"# Return eigenvectors of a given tensor by computing"
<<
" the eigenvalues of the tensor in the background:"
<<
nl
;
const
Tensor
<
complex
>
EVecs1
(
eigenVectors
(
T
));
Info
<<
EVecs1
<<
endl
;
}
// Do compile-time recursion over the given types
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
==
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
){}
template
<
std
::
size_t
I
=
0
,
typename
...
Tp
>
inline
typename
std
::
enable_if
<
I
<
sizeof
...(
Tp
),
void
>::
type
run_tests
(
const
std
::
tuple
<
Tp
...
>&
types
,
const
List
<
word
>&
typeID
)
{
Info
<<
nl
<<
" ## Test constructors: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_constructors
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test member functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_member_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global functions: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_funcs
(
std
::
get
<
I
>
(
types
));
Info
<<
nl
<<
" ## Test global operators: "
<<
typeID
[
I
]
<<
" ##"
<<
nl
;
test_global_opers
(
std
::
get
<
I
>
(
types
));
run_tests
<
I
+
1
,
Tp
...
>
(
types
,
typeID
);
}
// * * * * * * * * * * * * * * * Main Program * * * * * * * * * * * * * * * //
int
main
()
{
const
std
::
tuple
<
floatScalar
,
doubleScalar
,
complex
>
types
(
std
::
make_tuple
(
Zero
,
Zero
,
Zero
)
);
const
List
<
word
>
typeID
({
"Tensor<floatScalar>"
,
"Tensor<doubleScalar>"
,
"Tensor<complex>"
});
run_tests
(
types
,
typeID
);
Info
<<
nl
<<
" ## Test tensor eigen functions: ##"
<<
nl
;
const
label
numberOfTests
=
10000
;
Random
rndGen
(
1234
);
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
const
tensor
T
(
makeRandomContainer
(
rndGen
));
test_eigen_funcs
(
T
);
}
{
Info
<<
nl
<<
" ## A zero tensor: ##"
<<
nl
;
const
tensor
zeroT
(
Zero
);
test_eigen_funcs
(
zeroT
);
}
{
Info
<<
nl
<<
" ## A skew-symmetric tensor with no-real eigenvalues: ##"
<<
nl
;
const
tensor
T
(
0
,
1
,
1
,
-
1
,
0
,
1
,
-
1
,
-
1
,
0
);
test_eigen_funcs
(
T
);
}
{
Info
<<
nl
<<
" ## A stiff tensor: ##"
<<
nl
;
const
tensor
stiff
(
pow
(
10
.
0
,
10
),
pow
(
10
.
0
,
8
),
pow
(
10
.
0
,
7
),
pow
(
10
.
0
,
-
8
),
pow
(
10
.
0
,
9
),
pow
(
10
.
0
,
-
8
),
pow
(
10
.
0
,
10
),
pow
(
10
.
0
,
8
),
pow
(
10
.
0
,
7
)
);
// Although eigendecomposition is successful for the stiff tensors,
// cross-check between prod(eigenvalues) ?= det(stiff) is inherently
// problematic; therefore, eigenvalues of the stiff tensors are
// cross-checked by only sum(eigenvalues) ?= trace(stiff)
const
bool
testProd
=
false
;
test_eigen_funcs
(
stiff
,
testProd
);
}
{
Info
<<
nl
<<
" ## Random tensor with tiny off-diag elements: ##"
<<
nl
;
const
List
<
scalar
>
epsilons
({
0
,
SMALL
,
Foam
::
sqrt
(
SMALL
),
sqr
(
SMALL
),
Foam
::
cbrt
(
SMALL
),
-
SMALL
,
-
Foam
::
sqrt
(
SMALL
),
-
sqr
(
SMALL
),
-
Foam
::
cbrt
(
SMALL
)
});
for
(
label
i
=
0
;
i
<
numberOfTests
;
++
i
)
{
for
(
const
auto
&
eps
:
epsilons
)
{
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
zx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
zx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
zy
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
0
;
T
.
xz
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
yz
()
=
0
;
T
.
yx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
zx
()
=
eps
*
rndGen
.
GaussNormal
<
scalar
>
();
T
.
zy
()
=
0
;
test_eigen_funcs
(
T
);
}
{
tensor
T
(
makeRandomContainer
(
rndGen
));
T
.
xy
()
=
eps
;
T
.
xz
()
=
eps
;
T
.
yz
()
=
eps
;
T
.
yx
()
=
eps
;
T
.
zx
()
=
eps
;
T
.
zy
()
=
eps
;
test_eigen_funcs
(
T
);
}
}
}
}
if
(
nFail_
)
{
Info
<<
nl
<<
" #### "
<<
"Failed in "
<<
nFail_
<<
" tests "
<<
"out of total "
<<
nTest_
<<
" tests "
<<
"####
\n
"
<<
endl
;
return
1
;
}
Info
<<
nl
<<
" #### Passed all "
<<
nTest_
<<
" tests ####
\n
"
<<
endl
;
return
0
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
OpenFOAM-v2112/applications/test/Tensor2D/Make/files
0 → 100644
View file @
55e5a777
Test-Tensor2D.C
EXE = $(FOAM_USER_APPBIN)/Test-Tensor2D
OpenFOAM-v2112/applications/test/Tensor2D/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
Prev
1
…
13
14
15
16
17
18
19
20
21
…
34
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment