MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
multivector.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_MULTIVECTOR_HPP
13#define MFEM_MULTIVECTOR_HPP
14
15#include "../general/array.hpp"
16#include "vector.hpp"
17#include <vector>
18#include <array>
19#include <variant>
20
21namespace mfem
22{
23
24/// Class representing an array of Vectors with generally different sizes.
25/** This class is similar to BlockVector with the following two main
26 differences:
27 - the data for the individual Vector blocks does not need to be part of one
28 big contiguous memory allocation;
29 - this class does not inherit from class Vector (as a consequence of the
30 first bullet).
31
32 Internally, each Vector block is represented as one of the following
33 three options:
34 - (default) a Vector object constructed and owned by this class; this
35 object, in turn, as any Vector object, can own its Memory allocation or
36 refer to a sub-Memory of another Memory object; or
37 - a pointer to an externally allocated Vector or classes derived from
38 Vector.
39 - a pointer to an externally allocated const Vector or classes derived from
40 Vector. This option is helpful for wrapping const Vector objects as a
41 MultiVector that will be then used as a const MultiVector. */
43{
44private:
45 std::vector<std::variant<Vector,Vector*,const Vector*>> blocks;
46
47public:
48 /// Create an empty MultiVector with zero blocks.
49 MultiVector() = default;
50
51 /** @brief Create a MultiVector with @a num_blocks blocks. The individual
52 Vector blocks are default initialized, i.e. they all have size zero. */
53 MultiVector(int num_blocks)
54 : blocks(num_blocks) { }
55
56 /** @brief Construct a MultiVector with number of blocks and individual block
57 Vector sizes given by @a vector_sizes.
58
59 @note The memory of the individual Vector blocks is NOT initialized. */
60 MultiVector(const Array<int> &vector_sizes);
61
62 /** @brief Construct a MultiVector with number of blocks and individual block
63 Vector sizes given by @a vector_sizes. All Vector blocks use the
64 MemoryType @a mt.
65
66 @note The memory of the individual Vector blocks is NOT initialized. */
67 MultiVector(const Array<int> &vector_sizes, MemoryType mt);
68
69 /** @brief Construct a MultiVector referencing data within a given monolithic
70 Vector @a base.
71
72 With this constructor, the Memory flags of @a base and of the individual
73 Vector blocks may need to be explicitly synchronized when data is moved
74 between host and device. */
75 MultiVector(Vector &base, const Array<int> &vector_sizes);
76
77 /** @brief Construct a MultiVector referencing multiple Vectors given as
78 arguments.
79
80 The VectorTypes reference arguments are expected to be static_cast-able
81 to (Vector &) which is the case if the types are derived from Vector,
82 e.g. HypreParVector, GridFunction, etc.
83
84 With this constructor, operations on individual Vector blocks are
85 performed directly on the objects @a vs. In particular, there is no need
86 to synchronize the Memory flags of @a vs and the ones of the individual
87 Vector blocks when data is moved between host and device. */
88 template <typename... VectorTypes,
89 std::enable_if_t<
90 std::conjunction_v<
91 std::is_convertible<VectorTypes&,Vector&>...>, bool> = true>
92 MultiVector(VectorTypes &...vs) { MakeRef(vs...); }
93
94 /** @brief Construct a MultiVector referencing multiple const Vectors given
95 as arguments. Individual blocks are read-only; non-const operator[]
96 will generate an error. */
97 template <typename... VectorTypes,
98 std::enable_if_t<
99 std::conjunction_v<
100 std::is_convertible<const VectorTypes&,const Vector&>...>,
101 bool> = true>
102 MultiVector(const VectorTypes &...vs) { MakeRef(vs...); }
103
104 /// Return the number of Vectors in the MultiVector.
105 int NumBlocks() const { return blocks.size(); }
106
107 /** @brief Set the number of Vectors in the MultiVector. Existing Vector
108 blocks will remain unmodified. New Vector blocks will be default
109 initialized, i.e. they all have size zero. */
110 void SetNumBlocks(int num_blocks) { blocks.resize(num_blocks); }
111
112 /** @brief Read-write access to the i-th Vector. Generates an error if the
113 i-th block is read-only, i.e. it is a pointer to a const Vector. */
114 inline Vector &operator[](int i);
115
116 /// Read-only access to the i-th Vector.
117 inline const Vector &operator[](int i) const;
118
119 /** @brief Update the MultiVector according to the given @a vector_sizes.
120
121 This method can be used to add or remove blocks. The individual Vector
122 sizes are updated using the method Vector::SetSize(int). */
123 void SetSizes(const Array<int> &vector_sizes);
124
125 /** @brief Update the MultiVector according to the given @a vector_sizes and
126 MemoryType @a mt.
127
128 This method can be used to add or remove blocks. The individual Vector
129 sizes and MemoryType are updated using the method
130 Vector::SetSize(int, MemoryType). */
131 void SetSizes(const Array<int> &vector_sizes, MemoryType mt);
132
133 /** @brief Update the MultiVector to reference data within a given monolithic
134 Vector @a base.
135
136 After calling this method, the Memory flags of @a base and of the
137 individual Vector blocks may need to be explicitly synchronized when data
138 is moved between host and device.*/
139 void MakeRef(Vector &base, const Array<int> &vector_sizes);
140
141 /** @brief Update the @a i-th MultiVector block to reference data within the
142 given monolithic Vector @a base at the given @a offset and with the given
143 @a size.
144
145 After calling this method, the Memory flags of @a base and of the @a i-th
146 Vector block may need to be explicitly synchronized when data is moved
147 between host and device.*/
148 inline void MakeRef(int i, Vector &base, int offset, int size)
149 {
150 blocks[i].emplace<0>(base, offset, size);
151 }
152
153 /** @brief Update the MultiVector to reference multiple Vectors given as
154 arguments.
155
156 The VectorTypes reference arguments are expected to be static_cast-able
157 to (Vector &) which is the case if the types are derived from Vector,
158 e.g. HypreParVector, GridFunction, etc.
159
160 After calling this method, operations on individual Vector blocks are
161 performed directly on the objects @a vs. In particular, there is no need
162 to synchronize the Memory flags of @a vs and the ones of the individual
163 Vector blocks when data is moved between host and device. */
164 template <typename... VectorTypes,
165 std::enable_if_t<
166 std::conjunction_v<
167 std::is_convertible<VectorTypes&,Vector&>...>, bool> = true>
168 inline void MakeRef(VectorTypes &...vs);
169
170 /** @brief Update the MultiVector to reference multiple const Vectors given
171 as arguments. Individual blocks are read-only; non-const operator[]
172 will generate an error. */
173 template <typename... VectorTypes,
174 std::enable_if_t<
175 std::conjunction_v<
176 std::is_convertible<const VectorTypes&,const Vector&>...>,
177 bool> = true>
178 inline void MakeRef(const VectorTypes &...vs);
179
180 /** @brief Update the @a i-th MultiVector block to reference the given
181 Vector @a v.
182
183 After calling this method, operations on the @a i-th Vector block are
184 performed directly on the Vector @a v. In particular, there is no need
185 to synchronize the Memory flags of @a v and the ones of the @a i-th
186 Vector blocks when data is moved between host and device. */
187 inline void MakeRef(int i, Vector &v) { blocks[i] = &v; }
188
189 /** @brief Update the @a i-th MultiVector block to reference the given
190 const Vector @a v. The block becomes read-only. */
191 inline void MakeRef(int i, const Vector &v) { blocks[i] = &v; }
192};
193
194// Inline and template methods
195
197{
198 auto &bi = blocks[i];
199 const auto idx = bi.index();
200 if (idx == 0) { return std::get<0>(bi); }
201 if (idx == 1) { return *std::get<1>(bi); }
202 MFEM_ABORT("Non-const access to a const Vector block!");
203}
204
205inline const Vector &MultiVector::operator[](int i) const
206{
207 auto &bi = blocks[i];
208 const auto idx = bi.index();
209 return (idx == 0) ? std::get<0>(bi) :
210 (idx == 1) ? *std::get<1>(bi) :
211 /**/ *std::get<2>(bi);
212}
213
214template <typename... VectorTypes,
215 std::enable_if_t<
216 std::conjunction_v<
217 std::is_convertible<VectorTypes&,Vector&>...>, bool>>
218inline void MultiVector::MakeRef(VectorTypes &...vs)
219{
220 blocks.resize(sizeof...(vs));
221 if constexpr (sizeof...(vs) > 0)
222 {
223 const std::array vs_p{&static_cast<Vector&>(vs)...};
224 for (std::size_t i = 0; i < sizeof...(vs); i++)
225 {
226 blocks[i] = vs_p[i];
227 }
228 }
229}
230
231template <typename... VectorTypes,
232 std::enable_if_t<
233 std::conjunction_v<
234 std::is_convertible<const VectorTypes&,const Vector&>...>,
235 bool>>
236inline void MultiVector::MakeRef(const VectorTypes &...vs)
237{
238 blocks.resize(sizeof...(vs));
239 if constexpr (sizeof...(vs) > 0)
240 {
241 const std::array vs_p{&static_cast<const Vector&>(vs)...};
242 for (std::size_t i = 0; i < sizeof...(vs); i++)
243 {
244 blocks[i] = vs_p[i];
245 }
246 }
247}
248
249} // namespace mfem
250
251#endif // MFEM_MULTIVECTOR_HPP
Class representing an array of Vectors with generally different sizes.
void MakeRef(int i, Vector &base, int offset, int size)
Update the i-th MultiVector block to reference data within the given monolithic Vector base at the gi...
void MakeRef(int i, const Vector &v)
Update the i-th MultiVector block to reference the given const Vector v. The block becomes read-only.
void SetNumBlocks(int num_blocks)
Set the number of Vectors in the MultiVector. Existing Vector blocks will remain unmodified....
int NumBlocks() const
Return the number of Vectors in the MultiVector.
void MakeRef(int i, Vector &v)
Update the i-th MultiVector block to reference the given Vector v.
MultiVector(VectorTypes &...vs)
Construct a MultiVector referencing multiple Vectors given as arguments.
MultiVector()=default
Create an empty MultiVector with zero blocks.
void MakeRef(Vector &base, const Array< int > &vector_sizes)
Update the MultiVector to reference data within a given monolithic Vector base.
MultiVector(int num_blocks)
Create a MultiVector with num_blocks blocks. The individual Vector blocks are default initialized,...
MultiVector(const VectorTypes &...vs)
Construct a MultiVector referencing multiple const Vectors given as arguments. Individual blocks are ...
Vector & operator[](int i)
Read-write access to the i-th Vector. Generates an error if the i-th block is read-only,...
void SetSizes(const Array< int > &vector_sizes)
Update the MultiVector according to the given vector_sizes.
Vector data type.
Definition vector.hpp:82
MemoryType
Memory types supported by MFEM.