libMesh
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 
28 namespace libMesh
29 {
30 
31 
32 
33 
34 // ------------------------------------------------------------
35 // TypeTensor<T> class member functions
36 
37 
38 template <typename T>
39 void 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 
66 template <typename T>
67 bool 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 
123 template <>
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 
139 template <>
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
156 template <>
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 
176 template <>
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
202 template class LIBMESH_EXPORT TypeTensor<Real>;
203 
204 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
205 template class LIBMESH_EXPORT TypeTensor<Complex>;
206 #endif
207 
208 } // namespace libMesh
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
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
T libmesh_conj(T a)
bool operator<(const TypeTensor< T > &rhs) const
The libMesh namespace provides an interface to certain functionality in the library.
This class defines a tensor in LIBMESH_DIM dimensional space of type T.
Definition: tensor_tools.h:36
libmesh_assert(ctx)
void write_unformatted(std::ostream &out_stream, const bool newline=true) const
Unformatted print to the stream out.
Definition: type_tensor.C:39
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm(const T &a)
Definition: tensor_tools.h:74
boost::multiprecision::float128 imag(const boost::multiprecision::float128)
bool operator>(const TypeTensor< T > &rhs) const