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