libMesh
Loading...
Searching...
No Matches
eigen_sparse_vector.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// C++ includes
21#include <algorithm> // for std::min
22#include <limits>
23
24// Local Includes
25#include "libmesh/dense_subvector.h"
26#include "libmesh/dense_vector.h"
27#include "libmesh/eigen_sparse_vector.h"
28#include "libmesh/eigen_sparse_matrix.h"
29#include "libmesh/int_range.h"
30
31#ifdef LIBMESH_HAVE_EIGEN
32
33namespace libMesh
34{
35
36template <typename T>
38{
39 libmesh_assert (this->closed());
41
42 return _vec.sum();
43}
44
45
46
47template <typename T>
49{
50 libmesh_assert (this->closed());
52
53 return _vec.lpNorm<1>();
54}
55
56
57
58template <typename T>
60{
61 libmesh_assert (this->closed());
63
64 return _vec.lpNorm<2>();
65}
66
67
68
69template <typename T>
71{
72 libmesh_assert (this->closed());
74
75 return _vec.lpNorm<Eigen::Infinity>();
76}
77
78
79
80template <typename T>
82{
83 libmesh_assert (this->closed());
84
85 const EigenSparseVector<T> & v = cast_ref<const EigenSparseVector<T> &>(v_in);
86
87 _vec += v._vec;
88
89 return *this;
90}
91
92
93
94
95template <typename T>
97{
98 libmesh_assert (this->closed());
99
100 const EigenSparseVector<T> & v = cast_ref<const EigenSparseVector<T> &>(v_in);
101
102 _vec -= v._vec;
103
104 return *this;
105}
106
107
108
109template <typename T>
111{
112 libmesh_assert (this->closed());
113 libmesh_assert_equal_to(size(), v_in.size());
114
115 const EigenSparseVector<T> & v = cast_ref<const EigenSparseVector<T> &>(v_in);
116
117 _vec = _vec.cwiseProduct(v._vec);
118
119 return *this;
120}
121
122
123
124template <typename T>
126{
127 libmesh_assert (this->closed());
128 libmesh_assert_equal_to(size(), v_in.size());
129
130 const EigenSparseVector<T> & v = cast_ref<const EigenSparseVector<T> &>(v_in);
131
132 _vec = _vec.cwiseQuotient(v._vec);
133
134 return *this;
135}
136
137
138
139
140template <typename T>
142{
143#ifndef NDEBUG
144 const numeric_index_type n = this->size();
145
146 for (numeric_index_type i=0; i<n; i++)
147 // Don't divide by zero!
148 libmesh_assert_not_equal_to ((*this)(i), T(0));
149#endif
150
151 _vec = _vec.cwiseInverse();
152}
153
154
155
156template <typename T>
158{
159 _vec = _vec.conjugate();
160}
161
162
163
164template <typename T>
166{
167 _vec += EigenSV::Constant(this->size(), v);
168}
169
170
171
172
173template <typename T>
175{
176 libmesh_assert (this->initialized());
177
178 const EigenSparseVector<T> & v = cast_ref<const EigenSparseVector<T> &>(v_in);
179
180 _vec += v._vec;
181}
182
183
184
185template <typename T>
186void EigenSparseVector<T>::add (const T a, const NumericVector<T> & v_in)
187{
188 libmesh_assert (this->initialized());
189
190 const EigenSparseVector<T> & v = cast_ref<const EigenSparseVector<T> &>(v_in);
191
192 _vec += v._vec*a;
193}
194
195
196
197template <typename T>
199 const SparseMatrix<T> & mat_in)
200{
201 // Make sure the data passed in are really in Eigen types
202 const EigenSparseVector<T> * e_vec = cast_ptr<const EigenSparseVector<T> *>(&vec_in);
203 const EigenSparseMatrix<T> * mat = cast_ptr<const EigenSparseMatrix<T> *>(&mat_in);
204
205 libmesh_assert(e_vec);
206 libmesh_assert(mat);
207
208 _vec += mat->_mat*e_vec->_vec;
209}
210
211
212
213template <typename T>
215 const SparseMatrix<T> & mat_in)
216{
217 // Make sure the data passed in are really in Eigen types
218 const EigenSparseVector<T> * e_vec = cast_ptr<const EigenSparseVector<T> *>(&vec_in);
219 const EigenSparseMatrix<T> * mat = cast_ptr<const EigenSparseMatrix<T> *>(&mat_in);
220
221 libmesh_assert(e_vec);
222 libmesh_assert(mat);
223
224 _vec += mat->_mat.transpose()*e_vec->_vec;
225}
226
227
228
229template <typename T>
230void EigenSparseVector<T>::scale (const T factor)
231{
232 libmesh_assert (this->initialized());
233
234 _vec *= factor;
235}
236
237
238
239template <typename T>
241{
242 libmesh_assert (this->initialized());
243
244 const numeric_index_type n = this->size();
245
246 for (numeric_index_type i=0; i!=n; ++i)
247 this->set(i,std::abs((*this)(i)));
248}
249
250
251
252template <typename T>
254{
255 libmesh_assert (this->initialized());
256
257 // Make sure the NumericVector passed in is really a EigenSparseVector
258 const EigenSparseVector<T> * v = cast_ptr<const EigenSparseVector<T> *>(&v_in);
260
261 return _vec.dot(v->_vec);
262}
263
264
265
266template <typename T>
269{
270 libmesh_assert (this->initialized());
271 libmesh_assert (this->closed());
272
273 _vec.fill(s);
274
275 return *this;
276}
277
278
279
280template <typename T>
283{
284 // Make sure the NumericVector passed in is really a EigenSparseVector
285 const EigenSparseVector<T> * v =
286 cast_ptr<const EigenSparseVector<T> *>(&v_in);
287
289
290 *this = *v;
291
292 return *this;
293}
294
295
296
297template <typename T>
300{
301 libmesh_assert (this->initialized());
303 libmesh_assert_equal_to (this->size(), v.size());
304
305 _vec = v._vec;
306
307 this->_is_closed = true;
308
309 return *this;
310}
311
312
313
314template <typename T>
316EigenSparseVector<T>::operator = (const std::vector<T> & v)
317{
322 if (this->size() == v.size())
323 for (auto i : index_range(v))
324 this->set (i, v[i]);
325
326 else
327 libmesh_error_msg("this->size() = " << this->size() << " must be equal to v.size() = " << v.size());
328
329 return *this;
330}
331
332
333template <typename T>
335{
336 // Make sure the NumericVector passed in is really a EigenSparseVector
337 EigenSparseVector<T> * v_local =
338 cast_ptr<EigenSparseVector<T> *>(&v_local_in);
339
340 libmesh_assert(v_local);
341
342 *v_local = *this;
343}
344
345
346
347template <typename T>
349 const std::vector<numeric_index_type> & libmesh_dbg_var(send_list)) const
350{
351 // Make sure the NumericVector passed in is really a EigenSparseVector
352 EigenSparseVector<T> * v_local =
353 cast_ptr<EigenSparseVector<T> *>(&v_local_in);
354
355 libmesh_assert(v_local);
356 libmesh_assert_less_equal (send_list.size(), v_local->size());
357
358 *v_local = *this;
359}
360
361
362
363template <typename T>
364void EigenSparseVector<T>::localize (std::vector<T> & v_local,
365 const std::vector<numeric_index_type> & indices) const
366{
367 // EigenSparseVectors are serial, so we can just copy values
368 v_local.resize(indices.size());
369
370 for (auto i : index_range(v_local))
371 v_local[i] = (*this)(indices[i]);
372}
373
374
375
376template <typename T>
377void EigenSparseVector<T>::localize (const numeric_index_type libmesh_dbg_var(first_local_idx),
378 const numeric_index_type libmesh_dbg_var(last_local_idx),
379 const std::vector<numeric_index_type> & libmesh_dbg_var(send_list))
380{
381 libmesh_assert_equal_to (first_local_idx, 0);
382 libmesh_assert_equal_to (last_local_idx+1, this->size());
383
384 libmesh_assert_less_equal (send_list.size(), this->size());
385
386 this->_is_closed = true;
387}
388
389
390
391template <typename T>
392void EigenSparseVector<T>::localize (std::vector<T> & v_local) const
393
394{
395 v_local.resize(this->size());
396
397 for (auto i : index_range(v_local))
398 v_local[i] = (*this)(i);
399}
400
401
402
403template <typename T>
404void EigenSparseVector<T>::localize_to_one (std::vector<T> & v_local,
405 const processor_id_type libmesh_dbg_var(pid)) const
406{
407 libmesh_assert_equal_to (pid, 0);
408
409 this->localize (v_local);
410}
411
412
413
414template <typename T>
416 const NumericVector<T> & /*vec2*/)
417{
418 libmesh_not_implemented();
419}
420
421template <typename T>
423 const NumericVector<T> & /*vec2*/)
424{
425 libmesh_not_implemented();
426}
427
428
429
430template <typename T>
432 const std::vector<numeric_index_type> & rows,
433 const bool /* supplying_global_rows */) const
434{
435 // Make sure the passed in subvector is really an EigenSparseVector
436 EigenSparseVector<T> * eigen_subvector = cast_ptr<EigenSparseVector<T> *>(&subvector);
437
438 // If the eigen_subvector is already initialized, we assume that the
439 // user has already allocated the *correct* amount of space for it.
440 // If not, we do so.
441 if (!eigen_subvector->initialized())
442 eigen_subvector->init(rows.size());
443
444 eigen_subvector->vec() = this->vec()(rows);
445
446 eigen_subvector->_is_closed = true;
447}
448
449
450
451template <typename T>
452std::unique_ptr<NumericVector<T>>
453EigenSparseVector<T>::get_subvector(const std::vector<numeric_index_type> & rows)
454{
455 auto returnval = std::make_unique<EigenSparseVector<T>>(this->comm(), rows.size());
456
457 // We're just going to make a copy here, since we'll be calling a
458 // restore later anyway. Someone with more familiarity with Eigen
459 // can see if there's a way to improve this later.
460 this->create_subvector(*returnval, rows);
461
462 this->_is_closed = false;
463
464 return returnval;
465}
466
467template <typename T>
468void
470 const std::vector<numeric_index_type> & rows)
471{
472 auto * const eigen_subvector = cast_ptr<EigenSparseVector<T> *>(subvector.get());
473
474 this->vec()(rows) = eigen_subvector->vec();
475 this->_is_closed = true;
476}
477
478
479
480template <typename T>
482{
483 libmesh_assert (this->initialized());
484 if (!this->size())
485 return -std::numeric_limits<Real>::max();
486
487#ifdef LIBMESH_USE_COMPLEX_NUMBERS
488 Real the_max = libmesh_real((*this)(0));
489
490 const numeric_index_type n = this->size();
491
492 for (numeric_index_type i=1; i<n; i++)
493 the_max = std::max (the_max, libmesh_real((*this)(i)));
494
495 return the_max;
496#else
497 return libmesh_real(_vec.maxCoeff());
498#endif
499}
500
501
502
503template <typename T>
505{
506 libmesh_assert (this->initialized());
507 if (!this->size())
508 return std::numeric_limits<Real>::max();
509
510#ifdef LIBMESH_USE_COMPLEX_NUMBERS
511 Real the_min = libmesh_real((*this)(0));
512
513 const numeric_index_type n = this->size();
514
515 for (numeric_index_type i=1; i<n; i++)
516 the_min = std::min (the_min, libmesh_real((*this)(i)));
517
518 return the_min;
519#else
520 return libmesh_real(_vec.minCoeff());
521#endif
522}
523
524
525//------------------------------------------------------------------
526// Explicit instantiations
527template class LIBMESH_EXPORT EigenSparseVector<Number>;
528
529} // namespace libMesh
530
531
532#endif // #ifdef LIBMESH_HAVE_EIGEN
The EigenSparseMatrix class wraps a sparse matrix object from the Eigen library.
This class provides a nice interface to the Eigen C++-based data structures for serial vectors.
virtual NumericVector< T > & operator+=(const NumericVector< T > &v) override
Adds v to *this, .
virtual void add_vector(const NumericVector< T > &v, const SparseMatrix< T > &A) override
Computes , i.e.
virtual T sum() const override
virtual void restore_subvector(std::unique_ptr< NumericVector< T > > subvector, const std::vector< numeric_index_type > &rows) override
Restores a view into this vector using the indices in rows.
virtual Real max() const override
virtual NumericVector< T > & operator-=(const NumericVector< T > &v) override
Subtracts v from *this, .
virtual T dot(const NumericVector< T > &v) const override
virtual void localize_to_one(std::vector< T > &v_local, const processor_id_type proc_id=0) const override
Creates a local copy of the global vector in v_local only on processor proc_id.
DataType _vec
Actual Eigen::SparseVector<> we are wrapping.
virtual Real l2_norm() const override
virtual void add(const numeric_index_type i, const T value) override
Adds value to the vector entry specified by i.
virtual void conjugate() override
Negates the imaginary component of each entry in the vector.
virtual void add_vector_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A) override
Computes , i.e.
virtual Real min() const override
virtual void pointwise_divide(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
virtual std::unique_ptr< NumericVector< T > > get_subvector(const std::vector< numeric_index_type > &rows) override
Creates a view into this vector using the indices in rows.
virtual numeric_index_type size() const override
virtual NumericVector< T > & operator/=(const NumericVector< T > &v_in) override
Computes the component-wise division of this vector's entries by another's, .
virtual Real linfty_norm() const override
virtual void pointwise_mult(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
virtual void init(const numeric_index_type N, const numeric_index_type n_local, const bool fast=false, const ParallelType ptype=AUTOMATIC) override
Change the dimension of the vector to n.
virtual Real l1_norm() const override
virtual NumericVector< T > & operator*=(const NumericVector< T > &v_in) override
Computes the component-wise multiplication of this vector's entries by another's, .
virtual void reciprocal() override
Computes the component-wise reciprocal, .
DataType & vec()
References to the underlying Eigen data types.
virtual void scale(const T factor) override
Scale each element of the vector by the given factor.
virtual void abs() override
Sets for each entry in the vector.
EigenSparseVector< T > & operator=(const EigenSparseVector< T > &v)
Copy assignment operator.
virtual void create_subvector(NumericVector< T > &subvector, const std::vector< numeric_index_type > &rows, bool supplying_global_rows=true) const override
Fills in subvector from this vector using the indices in rows.
virtual void localize(std::vector< T > &v_local) const override
Creates a copy of the global vector in the local vector v_local.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual bool initialized() const
virtual numeric_index_type size() const =0
bool _is_closed
Flag which tracks whether the vector's values are consistent on all processors after insertion or add...
virtual bool closed() const
Generic sparse matrix.
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
bool closed()
Checks that the library has been closed.
Definition libmesh.C:331
T libmesh_real(T a)
libmesh_assert(ctx)
dof_id_type numeric_index_type
Definition id_types.h:99
bool initialized()
Checks that library initialization has been done.
Definition libmesh.C:324
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104