Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 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_SUBVECTOR_H
21 : #define LIBMESH_DENSE_SUBVECTOR_H
22 :
23 : // Local Includes
24 : #include "libmesh/libmesh_common.h"
25 : #include "libmesh/dense_vector.h"
26 : #include "libmesh/int_range.h"
27 :
28 : // C++ includes
29 :
30 : namespace libMesh
31 : {
32 :
33 : /**
34 : * Defines a dense subvector for use in finite element computations.
35 : * Useful for storing element load vectors before summation into a
36 : * global vector, particularly when you have systems of equations.
37 : * All overridden virtual functions are documented in dense_vector_base.h.
38 : *
39 : * \author Benjamin S. Kirk
40 : * \date 2003
41 : */
42 : template<typename T>
43 : class DenseSubVector : public DenseVectorBase<T>
44 : {
45 : public:
46 : /**
47 : * Constructor. Creates a dense subvector of the vector
48 : * \p parent. The subvector has dimensions \f$(m \times n)\f$,
49 : * and the \f$(0,0)\f$ entry of the subvector is located
50 : * at the \f$(ioff,joff)\f$ location in the parent vector.
51 : */
52 : DenseSubVector(DenseVector<T> & new_parent,
53 : const unsigned int ioff=0,
54 : const unsigned int n=0);
55 :
56 : /**
57 : * The 5 special functions can be defaulted for this class, as it
58 : * does not manage any memory itself.
59 : */
60 0 : DenseSubVector (DenseSubVector &&) = default;
61 : DenseSubVector (const DenseSubVector &) = default;
62 : DenseSubVector & operator= (const DenseSubVector &) = default;
63 : DenseSubVector & operator= (DenseSubVector &&) = default;
64 6063141 : virtual ~DenseSubVector() = default;
65 :
66 : /**
67 : * \returns A reference to the parent vector.
68 : */
69 0 : DenseVector<T> & parent () { return _parent_vector; }
70 :
71 : virtual void zero() override final;
72 :
73 : /**
74 : * \returns The \p (i,j) element of the subvector as a const
75 : * reference.
76 : */
77 : const T & operator() (const unsigned int i) const;
78 :
79 : /**
80 : * \returns The \p (i,j) element of the subvector as a writable reference.
81 : */
82 : T & operator() (const unsigned int i);
83 :
84 0 : virtual T el(const unsigned int i) const override final
85 0 : { return (*this)(i); }
86 :
87 0 : virtual T & el(const unsigned int i) override final
88 0 : { return (*this)(i); }
89 :
90 4951354 : virtual unsigned int size() const override final
91 4951354 : { return _n; }
92 :
93 0 : virtual bool empty() const override final
94 1728 : { return (_n == 0); }
95 :
96 : /**
97 : * \returns The row offset into the parent vector.
98 : */
99 502233484 : unsigned int i_off() const { return _i_off; }
100 :
101 : /**
102 : * Changes the location of the subvector in the parent vector.
103 : */
104 : void reposition(const unsigned int ioff,
105 : const unsigned int n);
106 :
107 : /**
108 : * \returns The minimum element in the vector, or the minimum real
109 : * part in the case of complex numbers.
110 : */
111 : Real min () const;
112 :
113 : /**
114 : * \returns The maximum element in the vector, or the maximum real
115 : * part in the case of complex numbers.
116 : */
117 : Real max () const;
118 :
119 : /**
120 : * \returns The \f$l_1\f$-norm of the vector, i.e. the sum of the
121 : * absolute values of the entries.
122 : */
123 : Real l1_norm () const;
124 :
125 : /**
126 : * \returns The \f$l_2\f$-norm of the vector, i.e. the square root
127 : * of the sum of the squares of the entries.
128 : */
129 : Real l2_norm () const;
130 :
131 : /**
132 : * \returns The \f$l_\infty\f$-norm of the vector, i.e. the maximum
133 : * absolute value of the entries.
134 : */
135 : Real linfty_norm () const;
136 :
137 : private:
138 :
139 :
140 : /**
141 : * The parent vector that contains this subvector.
142 : */
143 : DenseVector<T> & _parent_vector;
144 :
145 : /**
146 : * The length of this subvector.
147 : */
148 : unsigned int _n;
149 :
150 : /**
151 : * The offset into the parent vector.
152 : */
153 : unsigned int _i_off;
154 : };
155 :
156 :
157 :
158 : // ------------------------------------------------------------
159 : // Dense Vector member functions
160 : template<typename T>
161 : inline
162 6062977 : DenseSubVector<T>::DenseSubVector(DenseVector<T> & new_parent,
163 : const unsigned int ioff,
164 : const unsigned int n) :
165 6062977 : _parent_vector(new_parent)
166 : {
167 258656 : reposition (ioff, n);
168 258656 : }
169 :
170 :
171 :
172 : template<typename T>
173 : inline
174 19841552 : void DenseSubVector<T>::reposition(const unsigned int ioff,
175 : const unsigned int n)
176 : {
177 224222262 : _i_off = ioff;
178 199526933 : _n = n;
179 :
180 : // Make sure we still fit in the parent vector.
181 19841552 : libmesh_assert_less_equal ((this->i_off() + this->size()), _parent_vector.size());
182 23230288 : }
183 :
184 :
185 :
186 : template<typename T>
187 : inline
188 0 : void DenseSubVector<T>::zero()
189 : {
190 0 : for (auto i : index_range(*this))
191 0 : _parent_vector (i + this->i_off()) = 0.;
192 0 : }
193 :
194 :
195 :
196 : template<typename T>
197 : inline
198 371624571 : const T & DenseSubVector<T>::operator () (const unsigned int i) const
199 : {
200 371624571 : libmesh_assert_less (i, this->size());
201 371624571 : libmesh_assert_less (i + this->i_off(), _parent_vector.size());
202 :
203 4315189252 : return _parent_vector (i + this->i_off());
204 : }
205 :
206 :
207 : template<typename T>
208 : inline
209 0 : T & DenseSubVector<T>::operator () (const unsigned int i)
210 : {
211 0 : libmesh_assert_less (i, this->size());
212 0 : libmesh_assert_less (i + this->i_off(), _parent_vector.size());
213 :
214 529744012 : return _parent_vector (i + this->i_off());
215 : }
216 :
217 : template<typename T>
218 : inline
219 0 : Real DenseSubVector<T>::min () const
220 : {
221 0 : libmesh_assert (this->size());
222 0 : Real my_min = libmesh_real(_parent_vector (this->i_off()));
223 :
224 0 : for (auto i : make_range(1u, this->size()))
225 : {
226 0 : Real current = libmesh_real(_parent_vector (i + this->i_off()));
227 0 : my_min = (my_min < current? my_min : current);
228 : }
229 0 : return my_min;
230 : }
231 :
232 :
233 :
234 : template<typename T>
235 : inline
236 0 : Real DenseSubVector<T>::max () const
237 : {
238 0 : libmesh_assert (this->size());
239 0 : Real my_max = libmesh_real(_parent_vector (this->i_off()));
240 :
241 0 : for (auto i : make_range(1u, this->size()))
242 : {
243 0 : Real current = libmesh_real(_parent_vector (i + this->i_off()));
244 0 : my_max = (my_max > current? my_max : current);
245 : }
246 0 : return my_max;
247 : }
248 :
249 :
250 :
251 : template<typename T>
252 : inline
253 0 : Real DenseSubVector<T>::l1_norm () const
254 : {
255 0 : Real my_norm = 0.;
256 0 : for (auto i : index_range(*this))
257 : {
258 0 : my_norm += std::abs(_parent_vector (i + this->i_off()));
259 : }
260 0 : return my_norm;
261 : }
262 :
263 :
264 :
265 : template<typename T>
266 : inline
267 0 : Real DenseSubVector<T>::l2_norm () const
268 : {
269 0 : Real my_norm = 0.;
270 0 : for (auto i : index_range(*this))
271 : {
272 0 : my_norm += TensorTools::norm_sq(_parent_vector (i + this->i_off()));
273 : }
274 0 : return sqrt(my_norm);
275 : }
276 :
277 :
278 :
279 : template<typename T>
280 : inline
281 0 : Real DenseSubVector<T>::linfty_norm () const
282 : {
283 0 : if (!this->size())
284 0 : return 0.;
285 0 : Real my_norm = TensorTools::norm_sq(_parent_vector (this->i_off()));
286 :
287 0 : for (auto i : make_range(1u, this->size()))
288 : {
289 0 : Real current = TensorTools::norm_sq(_parent_vector (i + this->i_off()));
290 0 : my_norm = (my_norm > current? my_norm : current);
291 : }
292 0 : return sqrt(my_norm);
293 : }
294 :
295 : } // namespace libMesh
296 :
297 :
298 : #endif // LIBMESH_DENSE_SUBVECTOR_H
|