libMesh
Loading...
Searching...
No Matches
dense_vector.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_VECTOR_H
21#define LIBMESH_DENSE_VECTOR_H
22
23// Local Includes
24#include "libmesh/libmesh_common.h"
25#include "libmesh/dense_vector_base.h"
26#include "libmesh/compare_types.h"
27#include "libmesh/int_range.h"
28#include "libmesh/tensor_tools.h"
29
30#ifdef LIBMESH_HAVE_EIGEN
31#include "libmesh/ignore_warnings.h"
32#include <Eigen/Core>
33#include "libmesh/restore_warnings.h"
34#endif
35
36#ifdef LIBMESH_HAVE_METAPHYSICL
37#include "metaphysicl/raw_type.h"
38#endif
39
40// C++ includes
41#include <vector>
42#include <initializer_list>
43
44namespace libMesh
45{
46
57template<typename T>
59{
60public:
61
65 explicit
66 DenseVector(const unsigned int n=0);
67
72 explicit
73 DenseVector(const unsigned int n,
74 const T & val);
75
79 template <typename T2>
80 DenseVector (const DenseVector<T2> & other_vector);
81
85 template <typename T2>
86 DenseVector (const std::vector<T2> & other_vector);
87
91 template <typename T2>
92 DenseVector (std::initializer_list<T2> init_list);
93
98 DenseVector (DenseVector &&) = default;
99 DenseVector (const DenseVector &) = default;
100 DenseVector & operator= (const DenseVector &) = default;
102 virtual ~DenseVector() = default;
103
104 virtual unsigned int size() const override final
105 {
106 return cast_int<unsigned int>(_val.size());
107 }
108
109 virtual bool empty() const override final
110 { return _val.empty(); }
111
112 virtual void zero() override final;
113
117 const T & operator() (const unsigned int i) const;
118
122 T & operator() (const unsigned int i);
123
127 const T & operator[] (const unsigned int i) const { return (*this)(i); }
128
132 T & operator[] (const unsigned int i) { return (*this)(i); }
133
134 virtual T el(const unsigned int i) const override final
135 { return (*this)(i); }
136
137 virtual T & el(const unsigned int i) override final
138 { return (*this)(i); }
139
145 template <typename T2>
147
151 void swap(DenseVector<T> & other_vector);
152
156 void resize (const unsigned int n);
157
162 template <typename T2>
163 void append (const DenseVector<T2> & other_vector);
164
168 void scale (const T factor);
169
175 DenseVector<T> & operator*= (const T factor);
176
184 template <typename T2, typename T3>
185 typename std::enable_if<
186 ScalarTraits<T2>::value, void >::type
187 add (const T2 factor,
188 const DenseVector<T3> & vec);
189
195 template <typename T2>
197
204 template <typename T2>
206
210 template <typename T2>
211 bool operator== (const DenseVector<T2> & vec) const;
212
216 template <typename T2>
217 bool operator!= (const DenseVector<T2> & vec) const;
218
224 template <typename T2>
226
232 template <typename T2>
234
239 Real min () const;
240
245 Real max () const;
246
251 Real l1_norm () const;
252
257 Real l2_norm () const;
258
264
269 void get_principal_subvector (unsigned int sub_n, DenseVector<T> & dest) const;
270
278 std::vector<T> & get_values() { return _val; }
279
283 const std::vector<T> & get_values() const { return _val; }
284
288 typename std::vector<T>::const_iterator begin() const { return _val.begin(); }
289 typename std::vector<T>::iterator begin() { return _val.begin(); }
290
294 typename std::vector<T>::const_iterator end() const { return _val.end(); }
295 typename std::vector<T>::iterator end() { return _val.end(); }
296
297private:
298
302 std::vector<T> _val;
303};
304
305
306
307// ------------------------------------------------------------
308// DenseVector member functions
309template<typename T>
310inline
311DenseVector<T>::DenseVector(const unsigned int n) :
312 _val (n, T{})
313{
314}
315
316
317template<typename T>
318inline
319DenseVector<T>::DenseVector(const unsigned int n,
320 const T & val) :
321 _val (n, val)
322{
323}
324
325
326
327template<typename T>
328template<typename T2>
329inline
331 DenseVectorBase<T>()
332{
333 const std::vector<T2> & other_vals = other_vector.get_values();
334
335 _val.clear();
336
337 const int N = cast_int<int>(other_vals.size());
338 _val.reserve(N);
339
340 for (int i=0; i<N; i++)
341 _val.push_back(other_vals[i]);
342}
343
344
345
346template<typename T>
347template<typename T2>
348inline
349DenseVector<T>::DenseVector (const std::vector<T2> & other_vector) :
350 _val(other_vector)
351{
352}
353
354
355template<typename T>
356template <typename T2>
357inline
358DenseVector<T>::DenseVector (std::initializer_list<T2> init_list) :
359 _val(init_list.begin(), init_list.end())
360{
361}
362
363
364
365template<typename T>
366template<typename T2>
367inline
369{
370 const std::vector<T2> & other_vals = other_vector.get_values();
371
372 _val.clear();
373
374 const int N = cast_int<int>(other_vals.size());
375 _val.reserve(N);
376
377 for (int i=0; i<N; i++)
378 _val.push_back(other_vals[i]);
379
380 return *this;
381}
382
383
384
385template<typename T>
386inline
388{
389 _val.swap(other_vector._val);
390}
391
392
393
394template<typename T>
395inline
396void DenseVector<T>::resize(const unsigned int n)
397{
398 _val.resize(n);
399
400 zero();
401}
402
403
404
405template<typename T>
406template<typename T2>
407inline
408void DenseVector<T>::append (const DenseVector<T2> & other_vector)
409{
410 const std::vector<T2> & other_vals = other_vector.get_values();
411
412 _val.reserve(this->size() + other_vals.size());
413 _val.insert(_val.end(), other_vals.begin(), other_vals.end());
414}
415
416
417
418template<typename T>
419inline
421{
422 std::fill (_val.begin(),
423 _val.end(),
424 T{});
425}
426
427
428
429template<typename T>
430inline
431const T & DenseVector<T>::operator () (const unsigned int i) const
432{
433 libmesh_assert_less (i, _val.size());
434
435 return _val[i];
436}
437
438
439
440template<typename T>
441inline
442T & DenseVector<T>::operator () (const unsigned int i)
443{
444 libmesh_assert_less (i, _val.size());
445
446 return _val[i];
447}
448
449
450
451template<typename T>
452inline
453void DenseVector<T>::scale (const T factor)
454{
455 const int N = cast_int<int>(_val.size());
456 for (int i=0; i<N; i++)
457 _val[i] *= factor;
458}
459
460
461
462template<typename T>
463inline
465{
466 this->scale(factor);
467 return *this;
468}
469
470
471
472template<typename T>
473template<typename T2, typename T3>
474inline
475typename std::enable_if<
476 ScalarTraits<T2>::value, void >::type
477DenseVector<T>::add (const T2 factor,
478 const DenseVector<T3> & vec)
479{
480 libmesh_assert_equal_to (this->size(), vec.size());
481
482 const int N = cast_int<int>(_val.size());
483 for (int i=0; i<N; i++)
484 (*this)(i) += static_cast<T>(factor)*vec(i);
485}
486
487
488
489template<typename T>
490template<typename T2>
491inline
493{
494 if (!_val.size())
495 return 0.;
496
497 libmesh_assert_equal_to (this->size(), vec.size());
498
499#ifdef LIBMESH_HAVE_EIGEN
500 // We reverse the order of the arguments to dot() here since
501 // the convention in Eigen is to take the complex conjugate of the
502 // *first* argument, while ours is to take the complex conjugate of
503 // the second.
504 return Eigen::Map<const typename Eigen::Matrix<T2, Eigen::Dynamic, 1>>(vec.get_values().data(), vec.size())
505 .dot(Eigen::Map<const typename Eigen::Matrix<T, Eigen::Dynamic, 1>>(_val.data(), _val.size()));
506#else
507 typename CompareTypes<T, T2>::supertype val = 0.;
508
509 const int N = cast_int<int>(_val.size());
510 // The following pragma tells clang's vectorizer that it is safe to
511 // reorder floating point operations for this loop.
512#ifdef __clang__
513#pragma clang loop vectorize(enable)
514#endif
515 for (int i=0; i<N; i++)
516 val += (*this)(i)*libmesh_conj(vec(i));
517
518 return val;
519#endif
520}
521
522template<typename T>
523template<typename T2>
524inline
526{
527 libmesh_assert_equal_to (this->size(), vec.size());
528
529 typename CompareTypes<T, T2>::supertype val = 0.;
530
531 const int N = cast_int<int>(_val.size());
532 for (int i=0; i<N; i++)
533 val += (*this)(i)*(vec(i));
534
535 return val;
536}
537
538template<typename T>
539template<typename T2>
540inline
542{
543 libmesh_assert_equal_to (this->size(), vec.size());
544
545 const int N = cast_int<int>(_val.size());
546 for (int i=0; i<N; i++)
547 if ((*this)(i) != vec(i))
548 return false;
549
550 return true;
551}
552
553
554
555template<typename T>
556template<typename T2>
557inline
559{
560 libmesh_assert_equal_to (this->size(), vec.size());
561
562 const int N = cast_int<int>(_val.size());
563 for (int i=0; i<N; i++)
564 if ((*this)(i) != vec(i))
565 return true;
566
567 return false;
568}
569
570
571
572template<typename T>
573template<typename T2>
574inline
576{
577 libmesh_assert_equal_to (this->size(), vec.size());
578
579 const int N = cast_int<int>(_val.size());
580 for (int i=0; i<N; i++)
581 (*this)(i) += vec(i);
582
583 return *this;
584}
585
586
587
588template<typename T>
589template<typename T2>
590inline
592{
593 libmesh_assert_equal_to (this->size(), vec.size());
594
595 const int N = cast_int<int>(_val.size());
596 for (int i=0; i<N; i++)
597 (*this)(i) -= vec(i);
598
599 return *this;
600}
601
602
603
604template<typename T>
605inline
607{
608 libmesh_assert (this->size());
609 Real my_min = libmesh_real((*this)(0));
610
611 const int N = cast_int<int>(_val.size());
612 for (int i=1; i!=N; i++)
613 {
614 Real current = libmesh_real((*this)(i));
615 my_min = (my_min < current? my_min : current);
616 }
617 return my_min;
618}
619
620
621
622template<typename T>
623inline
625{
626 libmesh_assert (this->size());
627 Real my_max = libmesh_real((*this)(0));
628
629 const int N = cast_int<int>(_val.size());
630 for (int i=1; i!=N; i++)
631 {
632 Real current = libmesh_real((*this)(i));
633 my_max = (my_max > current? my_max : current);
634 }
635 return my_max;
636}
637
638
639
640template<typename T>
641inline
643{
644 if (!_val.size())
645 return 0.;
646
647#ifdef LIBMESH_HAVE_EIGEN
648 return Eigen::Map<const typename Eigen::Matrix<T, Eigen::Dynamic, 1>>(_val.data(), _val.size()).template lpNorm<1>();
649#else
650 Real my_norm = 0.;
651 const int N = cast_int<int>(_val.size());
652 for (int i=0; i!=N; i++)
653 my_norm += std::abs((*this)(i));
654
655 return my_norm;
656#endif
657}
658
659
660
661template<typename T>
662inline
664{
665 if (!_val.size())
666 return 0.;
667
668#ifdef LIBMESH_HAVE_EIGEN
669 return Eigen::Map<const typename Eigen::Matrix<T, Eigen::Dynamic, 1>>(_val.data(), _val.size()).norm();
670#else
671 Real my_norm = 0.;
672 const int N = cast_int<int>(_val.size());
673 // The following pragma tells clang's vectorizer that it is safe to
674 // reorder floating point operations for this loop.
675#ifdef __clang__
676#pragma clang loop vectorize(enable)
677#endif
678 for (int i=0; i!=N; i++)
679 my_norm += TensorTools::norm_sq((*this)(i));
680
681 return sqrt(my_norm);
682#endif
683}
684
685
686
687template<typename T>
688inline
690{
691 if (!_val.size())
692 return 0.;
693
694#ifdef LIBMESH_HAVE_EIGEN
695 return Eigen::Map<const typename Eigen::Matrix<T, Eigen::Dynamic, 1>>(_val.data(), _val.size()).template lpNorm<Eigen::Infinity>();
696#else
697 Real my_norm = TensorTools::norm_sq((*this)(0));
698
699 const int N = cast_int<int>(_val.size());
700 for (int i=1; i!=N; i++)
701 {
702 Real current = TensorTools::norm_sq((*this)(i));
703 my_norm = (my_norm > current? my_norm : current);
704 }
705 return sqrt(my_norm);
706#endif
707}
708
709
710
711template<typename T>
712inline
714 DenseVector<T> & dest) const
715{
716 libmesh_assert_less_equal ( sub_n, this->size() );
717
718 dest.resize(sub_n);
719 const int N = cast_int<int>(sub_n);
720 for (int i=0; i<N; i++)
721 dest(i) = _val[i];
722}
723
724
725// A vector is finite iff every component is
726template <typename T>
727bool isfinite (const DenseVector<T> & var)
728{
729 using std::isfinite;
730 using libMesh::isfinite; // for T==complex
731 for (auto i : index_range(var))
732 if (!isfinite(var(i)))
733 return false;
734 return true;
735}
736
737
738// A vector is infinite iff some component is infinite but no
739// component is NaN.
740//
741// This is arguably inconsistent with our std::complex overload (and
742// the C99 Annex G recommendations for _Complex, and C++ std::complex
743// arithmetic), which treats mixed (inf,NaN) pairs as infinite, but
744// this is probably safer for users.
745template <typename T>
746bool isinf (const DenseVector<T> & var)
747{
748 using std::isinf;
749 using libMesh::isinf; // for T==complex
750 using std::isnan;
751 using libMesh::isnan;
752 bool has_inf = false;
753 for (auto i : index_range(var))
754 {
755 // NaN anywhere makes us NaN, not inf
756 if (isnan(var(i)))
757 return false;
758 has_inf = has_inf || isinf(var(i));
759 }
760 return has_inf;
761}
762
763
764// A vector is NaN iff some component is NaN
765//
766// This is arguably inconsistent with our std::complex overload (and
767// the C99 Annex G recommendations for _Complex, and C++ std::complex
768// arithmetic), which treats mixed (inf,NaN) pairs as infinite, but
769// this is probably safer for users.
770template <typename T>
771bool isnan (const DenseVector<T> & var)
772{
773 using std::isnan;
774 using libMesh::isnan; // for T==complex
775 for (auto i : index_range(var))
776 if (isnan(var(i)))
777 return true;
778 return false;
779}
780
781
782} // namespace libMesh
783
784#ifdef LIBMESH_HAVE_METAPHYSICL
785namespace MetaPhysicL
786{
787template <typename T>
788struct RawType<libMesh::DenseVector<T>>
789{
791
793 {
794 const auto s = in.size();
795 value_type ret(s);
796 for (unsigned int i = 0; i < s; ++i)
797 ret(i) = raw_value(in(i));
798
799 return ret;
800 }
801};
802}
803#endif
804
805#endif // LIBMESH_DENSE_VECTOR_H
Defines an abstract dense vector base class for use in Finite Element-type computations.
Defines a dense vector for use in Finite Element-type computations.
DenseVector & operator=(const DenseVector &)=default
void resize(const unsigned int n)
Resize the vector.
std::vector< T >::const_iterator begin() const
Real linfty_norm() const
DenseVector(const DenseVector< T2 > &other_vector)
Copy-constructor.
std::vector< T >::iterator end()
virtual void zero() override final
Set every element in the vector to 0.
const std::vector< T > & get_values() const
const T & operator[](const unsigned int i) const
std::enable_if< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseVector< T3 > &vec)
Adds factor times vec to this vector.
bool operator==(const DenseVector< T2 > &vec) const
DenseVector< T > & operator-=(const DenseVector< T2 > &vec)
Subtracts vec from this vector.
std::vector< T > & get_values()
DenseVector< T > & operator*=(const T factor)
Multiplies every element in the vector by factor.
std::vector< T >::const_iterator end() const
DenseVector(std::initializer_list< T2 > init_list)
Initializer list constructor.
std::vector< T >::iterator begin()
CompareTypes< T, T2 >::supertype indefinite_dot(const DenseVector< T2 > &vec) const
DenseVector(const unsigned int n, const T &val)
Constructor.
std::vector< T > _val
The actual data values, stored as a 1D array.
const T & operator()(const unsigned int i) const
virtual bool empty() const override final
bool operator!=(const DenseVector< T2 > &vec) const
void append(const DenseVector< T2 > &other_vector)
Append additional entries to (resizing, but unchanging) the vector.
DenseVector(DenseVector &&)=default
The 5 special functions can be defaulted for this class, as it does not manage any memory itself.
DenseVector(const unsigned int n=0)
Constructor.
virtual ~DenseVector()=default
DenseVector< T > & operator+=(const DenseVector< T2 > &vec)
Adds vec to this vector.
DenseVector(const std::vector< T2 > &other_vector)
Copy-constructor, from a std::vector.
virtual T & el(const unsigned int i) override final
DenseVector(const DenseVector &)=default
void swap(DenseVector< T > &other_vector)
STL-like swap method.
void get_principal_subvector(unsigned int sub_n, DenseVector< T > &dest) const
Puts the principal subvector of size sub_n (i.e.
CompareTypes< T, T2 >::supertype dot(const DenseVector< T2 > &vec) const
virtual T el(const unsigned int i) const override final
void scale(const T factor)
Multiplies every element in the vector by factor.
virtual unsigned int size() const override final
auto norm_sq(const T &a)
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
T libmesh_real(T a)
libmesh_assert(ctx)
bool isfinite(std::complex< T > a)
bool isnan(std::complex< T > a)
const Number zero
.
Definition libmesh.h:297
bool isinf(std::complex< T > a)
T libmesh_conj(T a)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static value_type value(const libMesh::DenseVector< T > &in)
libMesh::DenseVector< typename RawType< T >::value_type > value_type