libMesh
Loading...
Searching...
No Matches
type_tensor.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19
20
21// C++ includes
22#include <iostream>
23#include <iomanip> // for std::setw, std::setiosflags
24
25// Local includes
26#include "libmesh/type_tensor.h"
27
28namespace libMesh
29{
30
31
32
33
34// ------------------------------------------------------------
35// TypeTensor<T> class member functions
36
37
38template <typename T>
39void TypeTensor<T>::write_unformatted (std::ostream & out_stream,
40 const bool newline) const
41{
42 libmesh_assert (out_stream);
43
44 out_stream << std::setiosflags(std::ios::showpoint)
45 << (*this)(0,0) << " "
46 << (*this)(0,1) << " "
47 << (*this)(0,2) << " ";
48 if (newline)
49 out_stream << '\n';
50
51 out_stream << std::setiosflags(std::ios::showpoint)
52 << (*this)(1,0) << " "
53 << (*this)(1,1) << " "
54 << (*this)(1,2) << " ";
55 if (newline)
56 out_stream << '\n';
57
58 out_stream << std::setiosflags(std::ios::showpoint)
59 << (*this)(2,0) << " "
60 << (*this)(2,1) << " "
61 << (*this)(2,2) << " ";
62 if (newline)
63 out_stream << '\n';
64}
65
66template <typename T>
67bool TypeTensor<T>::is_hpd(Real rel_tol) const
68{
69 // Convenient reference to this object, to be used for matrix
70 // operations.
71 const auto & A = *this;
72
73 // The norm of this matrix, needed for relative tolerance checks.
74 auto A_norm = A.norm();
75
76 // The zero matrix is only positive semi-definite
77 if (A_norm == 0)
78 return false;
79
80 // An absolute tolerance (based on the user's provided relative
81 // tolerance) to be used in the floating point comparisons below.
82 auto abs_tol = rel_tol * A_norm;
83
84 // Form the complex conjugate transpose of A
85 TypeTensor<T> A_conjugate_transpose;
86 for (unsigned int i=0; i<LIBMESH_DIM; i++)
87 for (unsigned int j=0; j<LIBMESH_DIM; j++)
88 A_conjugate_transpose(i,j) = libmesh_conj(A(j,i));
89
90 // Check if Hermitian
91 if ((A - A_conjugate_transpose).norm() > abs_tol)
92 return false;
93
94 // If we made it here, then we are Hermitian, so now we just need to
95 // check if we are positive-definite by checking that all principal
96 // minors are positive. Note: the determinant of a Hermitian matrix
97 // and all principal minors are real-valued. Since we already
98 // checked that the matrix is Hermitian above, we don't bother to
99 // check the complex parts are also zero now.
100
101 // For 3x3 and 2x2, check the 1x1 determinant
102#if LIBMESH_DIM > 1
103 if (std::real(A(0,0)) < -abs_tol)
104 return false;
105#endif
106
107 // For 3x3, check the upper 2x2 determinant
108#if LIBMESH_DIM > 2
109 if (std::real(A(0,0)*A(1,1) - A(0,1)*A(1,0)) < -abs_tol)
110 return false;
111#endif
112
113 // Finally, check the full determinant
114 if (std::real(A.det()) < -abs_tol)
115 return false;
116
117 // If we made it here, then the matrix is Hermitian
118 // positive-definite.
119 return true;
120}
121
122
123template <>
125{
126 for (unsigned int i=0; i<LIBMESH_DIM; i++)
127 for (unsigned int j=0; j<LIBMESH_DIM; j++)
128 {
129 if ((*this)(i,j) < rhs(i,j))
130 return true;
131 if ((*this)(i,j) > rhs(i,j))
132 return false;
133 }
134 return false;
135}
136
137
138
139template <>
141{
142 for (unsigned int i=0; i<LIBMESH_DIM; i++)
143 for (unsigned int j=0; j<LIBMESH_DIM; j++)
144 {
145 if ((*this)(i,j) > rhs(i,j))
146 return true;
147 if ((*this)(i,j) < rhs(i,j))
148 return false;
149 }
150 return false;
151}
152
153
154
155#ifdef LIBMESH_USE_COMPLEX_NUMBERS
156template <>
158{
159 for (unsigned int i=0; i<LIBMESH_DIM; i++)
160 for (unsigned int j=0; j<LIBMESH_DIM; j++)
161 {
162 if ((*this)(i,j).real() < rhs(i,j).real())
163 return true;
164 if ((*this)(i,j).real() > rhs(i,j).real())
165 return false;
166 if ((*this)(i,j).imag() < rhs(i,j).imag())
167 return true;
168 if ((*this)(i,j).imag() > rhs(i,j).imag())
169 return false;
170 }
171 return false;
172}
173
174
175
176template <>
178{
179 for (unsigned int i=0; i<LIBMESH_DIM; i++)
180 for (unsigned int j=0; j<LIBMESH_DIM; j++)
181 {
182 if ((*this)(i,j).real() > rhs(i,j).real())
183 return true;
184 if ((*this)(i,j).real() < rhs(i,j).real())
185 return false;
186 if ((*this)(i,j).imag() > rhs(i,j).imag())
187 return true;
188 if ((*this)(i,j).imag() < rhs(i,j).imag())
189 return false;
190 }
191 return false;
192}
193
194
195
196#endif
197
198
199
200// ------------------------------------------------------------
201// Explicit instantiations
202template class LIBMESH_EXPORT TypeTensor<Real>;
203
204#ifdef LIBMESH_USE_COMPLEX_NUMBERS
205template class LIBMESH_EXPORT TypeTensor<Complex>;
206#endif
207
208} // namespace libMesh
This class defines a tensor in LIBMESH_DIM dimensional space of type T.
Definition type_tensor.h:53
bool operator>(const TypeTensor< T > &rhs) const
bool operator<(const TypeTensor< T > &rhs) const
void write_unformatted(std::ostream &out_stream, const bool newline=true) const
Unformatted print to the stream out.
Definition type_tensor.C:39
bool is_hpd(Real rel_tol=TOLERANCE *TOLERANCE) const
Returns true if the TypeTensor is Hermitian (or symmetric, when T==Real) and positive-definite to wit...
Definition type_tensor.C:67
The libMesh namespace provides an interface to certain functionality in the library.
libmesh_assert(ctx)
T libmesh_conj(T a)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)