ryujin 2.1.1 revision 9391072059490dd712e0ea92785f21acd6605f00
multicomponent_vector.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2023 by the ryujin authors
4//
5
6#pragma once
7
8#include "simd.h"
9
10#include <deal.II/base/mpi.h>
11#include <deal.II/base/partitioner.h>
12#include <deal.II/base/vectorization.h>
13#include <deal.II/lac/la_parallel_vector.h>
14
15namespace ryujin
16{
17 namespace Vectors
18 {
38 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
40 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
41 &scalar_partitioner,
42 const unsigned int n_components);
43
44
55 template <typename Number,
56 int n_comp,
57 int simd_length = dealii::VectorizedArray<Number>::size()>
59 : public dealii::LinearAlgebra::distributed::Vector<Number>
60 {
61 public:
67 using VectorizedArray = dealii::VectorizedArray<Number, simd_length>;
68
74 using ScalarVector = dealii::LinearAlgebra::distributed::Vector<Number>;
75
80 using ScalarVector::operator=;
81
89 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
90 &scalar_partitioner);
91
106 void extract_component(ScalarVector &scalar_vector,
107 unsigned int component) const;
108
122 void insert_component(const ScalarVector &scalar_vector,
123 unsigned int component);
124
134 template <typename Number2 = Number,
135 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
136 Tensor get_tensor(const unsigned int i) const;
137
146 template <typename Number2 = Number,
147 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
148 Tensor get_tensor(const unsigned int *js) const;
149
163 template <typename Number2 = Number,
164 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
165 void write_tensor(const Tensor &tensor, const unsigned int i);
166 };
167
168
169#ifndef DOXYGEN
170 /* Template definitions: */
171
172 template <typename Number, int n_comp, int simd_length>
175 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
176 &scalar_partitioner)
177 {
178 /* Special case of a zero component vector */
179 if (n_comp == 0)
180 return;
181
182 auto vector_partitioner =
183 create_vector_partitioner(scalar_partitioner, n_comp);
184
185 dealii::LinearAlgebra::distributed::Vector<Number>::reinit(
186 vector_partitioner);
187 }
188
189
190 template <typename Number, int n_comp, int simd_length>
192 ScalarVector &scalar_vector, unsigned int component) const
193 {
194 Assert(n_comp > 0,
195 dealii::ExcMessage(
196 "Cannot extract from a vector with zero components."));
197
198 Assert(n_comp * scalar_vector.get_partitioner()->locally_owned_size() ==
199 this->get_partitioner()->locally_owned_size(),
200 dealii::ExcMessage("Called with a scalar_vector argument that has "
201 "incompatible local range."));
202 const auto local_size =
203 scalar_vector.get_partitioner()->locally_owned_size();
204 for (unsigned int i = 0; i < local_size; ++i)
205 scalar_vector.local_element(i) =
206 this->local_element(i * n_comp + component);
207 scalar_vector.update_ghost_values();
208 }
209
210
211 template <typename Number, int n_comp, int simd_length>
213 const ScalarVector &scalar_vector, unsigned int component)
214 {
215 Assert(n_comp > 0,
216 dealii::ExcMessage(
217 "Cannot insert into a vector with zero components."));
218
219 Assert(n_comp * scalar_vector.get_partitioner()->locally_owned_size() ==
220 this->get_partitioner()->locally_owned_size(),
221 dealii::ExcMessage("Called with a scalar_vector argument that has "
222 "incompatible local range."));
223 const auto local_size =
224 scalar_vector.get_partitioner()->locally_owned_size();
225 for (unsigned int i = 0; i < local_size; ++i)
226 this->local_element(i * n_comp + component) =
227 scalar_vector.local_element(i);
228 }
229
230 /* Inline function definitions: */
231
232 template <typename Number, int n_comp, int simd_length>
233 template <typename Number2, typename Tensor>
234 DEAL_II_ALWAYS_INLINE inline Tensor
236 const unsigned int i) const
237 {
238 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
239 "dummy type mismatch");
240 Tensor tensor;
241
242 /* Special case of a zero component vector */
243 if constexpr (n_comp == 0)
244 return tensor;
245
246 if constexpr (std::is_same<Number, Number2>::value) {
247 /* Non-vectorized sequential access. */
248
249 for (unsigned int d = 0; d < n_comp; ++d)
250 tensor[d] = this->local_element(i * n_comp + d);
251
252 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
253
254 /* Vectorized fast access. index must be divisible by simd_length */
255 std::array<unsigned int, VectorizedArray::size()> indices;
256 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
257 indices[k] = k * n_comp;
258
259 dealii::vectorized_load_and_transpose(
260 n_comp, this->begin() + i * n_comp, indices.data(), &tensor[0]);
261
262 } else {
263 /* not implemented */
264 __builtin_trap();
265 }
266
267 return tensor;
268 }
269
270
271 template <typename Number, int n_comp, int simd_length>
272 template <typename Number2, typename Tensor>
273 DEAL_II_ALWAYS_INLINE inline Tensor
275 const unsigned int *js) const
276 {
277 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
278 "dummy type mismatch");
279 Tensor tensor;
280
281 /* Special case of a zero component vector */
282 if constexpr (n_comp == 0)
283 return tensor;
284
285 if constexpr (std::is_same<Number, Number2>::value) {
286 /* Non-vectorized sequential access. */
287
288 for (unsigned int d = 0; d < n_comp; ++d)
289 tensor[d] = this->local_element(js[0] * n_comp + d);
290
291 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
292 /* Vectorized fast access. index must be divisible by simd_length */
293
294 std::array<unsigned int, VectorizedArray::size()> indices;
295 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
296 indices[k] = js[k] * n_comp;
297
298 dealii::vectorized_load_and_transpose(
299 n_comp, this->begin(), indices.data(), &tensor[0]);
300
301 } else {
302 /* not implemented */
303 __builtin_trap();
304 }
305
306 return tensor;
307 }
308
309
310 template <typename Number, int n_comp, int simd_length>
311 template <typename Number2, typename Tensor>
312 DEAL_II_ALWAYS_INLINE inline void
314 const Tensor &tensor, const unsigned int i)
315 {
316 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
317 "dummy type mismatch");
318
319 /* Special case of a zero component vector */
320 if constexpr (n_comp == 0)
321 return;
322
323 if constexpr (std::is_same<Number, Number2>::value) {
324 /* Non-vectorized sequential access. */
325
326 for (unsigned int d = 0; d < n_comp; ++d)
327 this->local_element(i * n_comp + d) = tensor[d];
328
329 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
330 /* Vectorized fast access. index must be divisible by simd_length */
331
332 std::array<unsigned int, VectorizedArray::size()> indices;
333 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
334 indices[k] = k * n_comp;
335
336 dealii::vectorized_transpose_and_store(false,
337 n_comp,
338 &tensor[0],
339 indices.data(),
340 this->begin() + i * n_comp);
341
342 } else {
343 /* not implemented */
344 __builtin_trap();
345 }
346 }
347#endif
348 } // namespace Vectors
349} // namespace ryujin
void write_tensor(const Tensor &tensor, const unsigned int i)
void extract_component(ScalarVector &scalar_vector, unsigned int component) const
Tensor get_tensor(const unsigned int *js) const
void insert_component(const ScalarVector &scalar_vector, unsigned int component)
dealii::VectorizedArray< Number, simd_length > VectorizedArray
dealii::LinearAlgebra::distributed::Vector< Number > ScalarVector
void reinit_with_scalar_partitioner(const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &scalar_partitioner)
Tensor get_tensor(const unsigned int i) const
std::shared_ptr< const dealii::Utilities::MPI::Partitioner > create_vector_partitioner(const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &scalar_partitioner, const unsigned int n_components)
dealii::LinearAlgebra::distributed::Vector< Number > ScalarVector
Definition: state_vector.h:31