libMesh
Loading...
Searching...
No Matches
parallel_eigen.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#ifndef LIBMESH_PARALLEL_EIGEN_H
19#define LIBMESH_PARALLEL_EIGEN_H
20
21// libMesh includes
22#include "libmesh/libmesh_config.h"
23#include "libmesh/libmesh_common.h"
24#include "libmesh/int_range.h"
25
26// TIMPI includes
27#include "timpi/packing.h"
28
29#ifdef LIBMESH_HAVE_EIGEN
30
31// libEigen includes, avoiding warnings triggered by some versions
32#include "libmesh/ignore_warnings.h"
33#include <Eigen/Core>
34#include "libmesh/restore_warnings.h"
35
36namespace libMesh
37{
38
39 namespace Parallel
40 {
41 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
42 class Packing<Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
43 {
44 public:
45 typedef unsigned int buffer_type;
46
47 template <typename Context>
48 static unsigned int packable_size(const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &object,
49 const Context *context);
50
51 template <typename BufferIter>
52 static unsigned int packed_size(BufferIter iter);
53
54 template <typename OutputIter, typename Context>
55 static void pack(const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &object,
56 OutputIter data_out,
57 const Context *context);
58
59 template <typename BufferIter, typename Context>
60 static Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> unpack(BufferIter in, Context *context);
61
62 private:
63 template <typename T2>
64 static inline constexpr bool IsFixed = TIMPI::StandardType<T2>::is_fixed_type;
65 static std::size_t BufferCount(std::size_t n) { return (sizeof(Scalar) * n + sizeof(buffer_type) - 1) / sizeof(buffer_type); }
66 };
67
68
69
70 template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
71 template <typename Context>
72 unsigned int
73 Packing<Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>::packable_size(const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &mtx,
74 const Context * context)
75 {
76 const auto rows = mtx.rows();
77 const auto cols = mtx.cols();
78
79 // compute packable size of the underlying data
80 std::size_t ints_per_data;
81 if constexpr (IsFixed<Scalar>)
82 {
83 libmesh_ignore(context);
84 ints_per_data = BufferCount(rows * cols);
85 }
86 else
87 {
88 ints_per_data = 0;
89 for (const auto i : make_range(rows * cols))
90 ints_per_data += Packing<Scalar>::packable_size(mtx.data()[i], context);
91 }
92
93 constexpr std::size_t header_size = (Rows == Eigen::Dynamic) + (Cols == Eigen::Dynamic);
94 return header_size + ints_per_data;
95 }
96
97 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
98 template <typename BufferIter>
99 unsigned int
101 {
102 constexpr std::size_t header_size = (Rows == Eigen::Dynamic) + (Cols == Eigen::Dynamic);
103 const std::size_t rows = Rows == Eigen::Dynamic ? *in++ : Rows;
104 const std::size_t cols = Cols == Eigen::Dynamic ? *in++ : Cols;
105
106 // compute packable size of the underlying data
107 std::size_t ints_per_data;
108 if constexpr (IsFixed<Scalar>)
109 ints_per_data = BufferCount(rows * cols);
110 else
111 {
112 ints_per_data = 0;
113 for (const auto i : make_range(rows * cols))
114 {
115 ints_per_data += Packing<Scalar>::packed_size(in + ints_per_data);
117 }
118 }
119
120 return header_size + ints_per_data;
121 }
122
123 template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
124 template <typename OutputIter, typename Context>
125 void
126 Packing<Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>::pack(const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &mtx,
127 OutputIter data_out,
128 const Context *context)
129 {
130 const auto rows = mtx.rows();
131 const auto cols = mtx.cols();
132
133 // store dynamic dimensions
134 if constexpr (Rows == Eigen::Dynamic)
135 *data_out++ = rows;
136 if constexpr (Cols == Eigen::Dynamic)
137 *data_out++ = cols;
138
139 // pack underlying data
140 if constexpr (IsFixed<Scalar>)
141 {
142 libmesh_ignore(context);
143 const auto *raw_data = reinterpret_cast<const buffer_type *>(mtx.data());
144 for (const auto i : make_range(BufferCount(rows * cols)))
145 *data_out++ = (raw_data[i]);
146 }
147 else
148 for (const auto i : make_range(rows * cols))
149 Packing<Scalar>::pack(mtx.data()[i], data_out, context);
150 }
151
152 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
153 template <typename BufferIter, typename Context>
154 Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>
156 {
157 const std::size_t rows = Rows == Eigen::Dynamic ? *in++ : Rows;
158 const std::size_t cols = Cols == Eigen::Dynamic ? *in++ : Cols;
159 auto mtx = Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>(rows, cols);
160
161 // unpack underlying data
162 if constexpr (IsFixed<Scalar>)
163 {
164 libmesh_ignore(context);
165 auto *raw_data = reinterpret_cast<buffer_type *>(mtx.data());
166 for (const auto i : make_range(BufferCount(rows * cols)))
167 raw_data[i] = *in++;
168 }
169 else
170 for (const auto i : make_range(rows * cols))
171 {
172 // unpack matrix entry and advance iterator
173 mtx.data()[i] = Packing<Scalar>::unpack(in, context);
175 }
176
177 return mtx;
178 }
179
180 } // namespace Parallel
181} // namespace libMesh
182
183#endif // LIBMESH_HAVE_EIGEN
184
185#endif // LIBMESH_PARALLEL_EIGEN_H
std::pair< T1, T2 > unpack(BufferIter in, Context *ctx)
static unsigned int packed_size(BufferIter iter)
unsigned int packable_size(const std::pair< T1, T2 > &pr, const Context *ctx)
void pack(const std::pair< T1, T2 > &pr, OutputIter data_out, const Context *ctx)
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)
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