libMesh
Loading...
Searching...
No Matches
dense_submatrix.h
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#ifndef LIBMESH_DENSE_SUBMATRIX_H
21#define LIBMESH_DENSE_SUBMATRIX_H
22
23// Local Includes
24#include "libmesh/libmesh_common.h"
25#include "libmesh/dense_matrix.h"
26#include "libmesh/dense_subvector.h"
27#include "libmesh/int_range.h"
28
29// C++ includes
30
31namespace libMesh
32{
33
44template<typename T>
46{
47public:
48
55 DenseSubMatrix(DenseMatrix<T> & new_parent,
56 const unsigned int ioff=0,
57 const unsigned int joff=0,
58 const unsigned int m=0,
59 const unsigned int n=0);
60
66 DenseSubMatrix (const DenseSubMatrix &) = default;
69 virtual ~DenseSubMatrix() = default;
70
75
76 virtual void zero() override final;
77
81 T operator() (const unsigned int i,
82 const unsigned int j) const;
83
87 T & operator() (const unsigned int i,
88 const unsigned int j);
89
90 virtual T el(const unsigned int i,
91 const unsigned int j) const override final
92 { return (*this)(i,j); }
93
94 virtual T & el(const unsigned int i,
95 const unsigned int j) override final
96 { return (*this)(i,j); }
97
98 virtual void left_multiply (const DenseMatrixBase<T> & M2) override final;
99
100 virtual void right_multiply (const DenseMatrixBase<T> & M3) override final;
101
105 void reposition(const unsigned int ioff,
106 const unsigned int joff,
107 const unsigned int new_m,
108 const unsigned int new_n);
109
113 unsigned int i_off() const { return _i_off; }
114
118 unsigned int j_off() const { return _j_off; }
119
126 void condense(const unsigned int i,
127 const unsigned int j,
128 const T val,
129 DenseSubVector<T> & rhs)
130 {
131 this->parent().condense(this->i_off()+i,
132 this->j_off()+j,
133 val, rhs.parent());
134 }
135
136private:
137
142
146 unsigned int _i_off;
147
151 unsigned int _j_off;
152};
153
154
155// --------------------------------------------------
156// Constructor
157template<typename T>
158inline
160 const unsigned int ioff,
161 const unsigned int joff,
162 const unsigned int new_m,
163 const unsigned int new_n) :
164 DenseMatrixBase<T>(new_m,new_n),
165 _parent_matrix(new_parent)
166{
167 this->reposition (ioff, joff, new_m, new_n);
168}
169
170
171template<typename T>
172inline
173void DenseSubMatrix<T>::reposition(const unsigned int ioff,
174 const unsigned int joff,
175 const unsigned int new_m,
176 const unsigned int new_n)
177{
178 _i_off = ioff;
179 _j_off = joff;
180 this->_m = new_m;
181 this->_n = new_n;
182
183 // Make sure we still fit in the parent matrix.
184 libmesh_assert_less_equal ((this->i_off() + this->m()), _parent_matrix.m());
185 libmesh_assert_less_equal ((this->j_off() + this->n()), _parent_matrix.n());
186}
187
188
189
190template<typename T>
191inline
193{
194 for (auto i : make_range(this->m()))
195 for (auto j : make_range(this->n()))
196 _parent_matrix(i + this->i_off(),
197 j + this->j_off()) = 0.;
198}
199
200
201
202template<typename T>
203inline
204T DenseSubMatrix<T>::operator () (const unsigned int i,
205 const unsigned int j) const
206{
207 libmesh_assert_less (i, this->m());
208 libmesh_assert_less (j, this->n());
209 libmesh_assert_less (i + this->i_off(), _parent_matrix.m());
210 libmesh_assert_less (j + this->j_off(), _parent_matrix.n());
211
212 return _parent_matrix (i + this->i_off(),
213 j + this->j_off());
214}
215
216
217template<typename T>
218inline
219T & DenseSubMatrix<T>::operator () (const unsigned int i,
220 const unsigned int j)
221{
222 libmesh_assert_less (i, this->m());
223 libmesh_assert_less (j, this->n());
224 libmesh_assert_less (i + this->i_off(), _parent_matrix.m());
225 libmesh_assert_less (j + this->j_off(), _parent_matrix.n());
226
227 return _parent_matrix (i + this->i_off(),
228 j + this->j_off());
229}
230
231
232// A submatrix is finite iff every component is
233template <typename T>
234bool isfinite (const DenseSubMatrix<T> & var)
235{
236 using std::isfinite;
237 using libMesh::isfinite; // for T==complex
238 const auto m = var.m(), n = var.n();
239 for (auto i : make_range(m))
240 for (auto j : make_range(n))
241 if (!isfinite(var(i,j)))
242 return false;
243 return true;
244}
245
246
247// A submatrix is infinite iff some component is infinite but no
248// component is NaN.
249//
250// This is arguably inconsistent with our std::complex overload (and
251// the C99 Annex G recommendations for _Complex, and C++ std::complex
252// arithmetic), which treats mixed (inf,NaN) pairs as infinite, but
253// this is probably safer for users.
254template <typename T>
255bool isinf (const DenseSubMatrix<T> & var)
256{
257 using std::isinf;
258 using libMesh::isinf; // for T==complex
259 using std::isnan;
260 using libMesh::isnan;
261 const auto m = var.m(), n = var.n();
262 bool has_inf = false;
263 for (auto i : make_range(m))
264 for (auto j : make_range(n))
265 {
266 // NaN anywhere makes us NaN, not inf
267 if (isnan(var(i,j)))
268 return false;
269 has_inf = has_inf || isinf(var(i,j));
270 }
271 return has_inf;
272}
273
274
275
276// A submatrix is NaN iff some component is NaN
277//
278// This is arguably inconsistent with our std::complex overload (and
279// the C99 Annex G recommendations for _Complex, and C++ std::complex
280// arithmetic), which treats mixed (inf,NaN) pairs as infinite, but
281// this is probably safer for users.
282template <typename T>
283bool isnan (const DenseSubMatrix<T> & var)
284{
285 using std::isnan;
286 using libMesh::isnan; // for T==complex
287 const auto m = var.m(), n = var.n();
288 for (auto i : make_range(m))
289 for (auto j : make_range(n))
290 if (isnan(var(i,j)))
291 return true;
292 return false;
293}
294
295
296} // namespace libMesh
297
298
299#endif // LIBMESH_DENSE_SUBMATRIX_H
Defines an abstract dense matrix base class for use in Finite Element-type computations.
Defines a dense matrix for use in Finite Element-type computations.
Defines a dense submatrix for use in Finite Element-type computations.
virtual T el(const unsigned int i, const unsigned int j) const override final
void reposition(const unsigned int ioff, const unsigned int joff, const unsigned int new_m, const unsigned int new_n)
Changes the location of the submatrix in the parent matrix.
DenseSubMatrix(DenseMatrix< T > &new_parent, const unsigned int ioff=0, const unsigned int joff=0, const unsigned int m=0, const unsigned int n=0)
Constructor.
DenseSubMatrix & operator=(const DenseSubMatrix &)=default
virtual ~DenseSubMatrix()=default
unsigned int _j_off
The column offset into the parent matrix.
unsigned int _i_off
The row offset into the parent matrix.
T operator()(const unsigned int i, const unsigned int j) const
unsigned int i_off() const
void condense(const unsigned int i, const unsigned int j, const T val, DenseSubVector< T > &rhs)
Condense-out the (i,j) entry of the matrix, forcing it to take on the value val.
virtual void left_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- M2 * (*this)
virtual T & el(const unsigned int i, const unsigned int j) override final
DenseMatrix< T > & parent()
unsigned int j_off() const
DenseSubMatrix(DenseSubMatrix &&)=default
The 5 special functions can be defaulted for this class, as it does not manage any memory itself.
virtual void zero() override final
Set every element in the matrix to 0.
DenseMatrix< T > & _parent_matrix
The parent matrix that contains this submatrix.
DenseSubMatrix(const DenseSubMatrix &)=default
virtual void right_multiply(const DenseMatrixBase< T > &M3) override final
Performs the operation: (*this) <- (*this) * M3.
Defines a dense subvector for use in finite element computations.
DenseVector< T > & parent()
The libMesh namespace provides an interface to certain functionality in the library.
bool isfinite(std::complex< T > a)
bool isnan(std::complex< T > a)
bool isinf(std::complex< T > a)
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176