ryujin 2.1.1 revision 0348cbb53a3e4b1da2a4c037e81f88f2d21ce219
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
180 template <typename Number2 = Number,
181 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
182 void add_tensor(const Tensor &tensor, const unsigned int i);
183 };
184
185
186#ifndef DOXYGEN
187 /* Template definitions: */
188
189 template <typename Number, int n_comp, int simd_length>
192 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
193 &scalar_partitioner)
194 {
195 /* Special case of a zero component vector */
196 if (n_comp == 0)
197 return;
198
199 auto vector_partitioner =
200 create_vector_partitioner(scalar_partitioner, n_comp);
201
202 dealii::LinearAlgebra::distributed::Vector<Number>::reinit(
203 vector_partitioner);
204 }
205
206
207 template <typename Number, int n_comp, int simd_length>
209 ScalarVector &scalar_vector, unsigned int component) const
210 {
211 Assert(n_comp > 0,
212 dealii::ExcMessage(
213 "Cannot extract from a vector with zero components."));
214
215 Assert(n_comp * scalar_vector.get_partitioner()->locally_owned_size() ==
216 this->get_partitioner()->locally_owned_size(),
217 dealii::ExcMessage("Called with a scalar_vector argument that has "
218 "incompatible local range."));
219 const auto local_size =
220 scalar_vector.get_partitioner()->locally_owned_size();
221 for (unsigned int i = 0; i < local_size; ++i)
222 scalar_vector.local_element(i) =
223 this->local_element(i * n_comp + component);
224 scalar_vector.update_ghost_values();
225 }
226
227
228 template <typename Number, int n_comp, int simd_length>
230 const ScalarVector &scalar_vector, unsigned int component)
231 {
232 Assert(n_comp > 0,
233 dealii::ExcMessage(
234 "Cannot insert into a vector with zero components."));
235
236 Assert(n_comp * scalar_vector.get_partitioner()->locally_owned_size() ==
237 this->get_partitioner()->locally_owned_size(),
238 dealii::ExcMessage("Called with a scalar_vector argument that has "
239 "incompatible local range."));
240 const auto local_size =
241 scalar_vector.get_partitioner()->locally_owned_size();
242 for (unsigned int i = 0; i < local_size; ++i)
243 this->local_element(i * n_comp + component) =
244 scalar_vector.local_element(i);
245 }
246
247 /* Inline function definitions: */
248
249 template <typename Number, int n_comp, int simd_length>
250 template <typename Number2, typename Tensor>
251 DEAL_II_ALWAYS_INLINE inline Tensor
253 const unsigned int i) const
254 {
255 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
256 "dummy type mismatch");
257 Tensor tensor;
258
259 /* Special case of a zero component vector */
260 if constexpr (n_comp == 0)
261 return tensor;
262
263 if constexpr (std::is_same<Number, Number2>::value) {
264 /* Non-vectorized sequential access. */
265
266 for (unsigned int d = 0; d < n_comp; ++d)
267 tensor[d] = this->local_element(i * n_comp + d);
268
269 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
270
271 /* Vectorized fast access. index must be divisible by simd_length */
272 std::array<unsigned int, VectorizedArray::size()> indices;
273 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
274 indices[k] = k * n_comp;
275
276 dealii::vectorized_load_and_transpose(
277 n_comp, this->begin() + i * n_comp, indices.data(), &tensor[0]);
278
279 } else {
280 /* not implemented */
281 __builtin_trap();
282 }
283
284 return tensor;
285 }
286
287
288 template <typename Number, int n_comp, int simd_length>
289 template <typename Number2, typename Tensor>
290 DEAL_II_ALWAYS_INLINE inline Tensor
292 const unsigned int *js) const
293 {
294 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
295 "dummy type mismatch");
296 Tensor tensor;
297
298 /* Special case of a zero component vector */
299 if constexpr (n_comp == 0)
300 return tensor;
301
302 if constexpr (std::is_same<Number, Number2>::value) {
303 /* Non-vectorized sequential access. */
304
305 for (unsigned int d = 0; d < n_comp; ++d)
306 tensor[d] = this->local_element(js[0] * n_comp + d);
307
308 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
309 /* Vectorized fast access. index must be divisible by simd_length */
310
311 std::array<unsigned int, VectorizedArray::size()> indices;
312 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
313 indices[k] = js[k] * n_comp;
314
315 dealii::vectorized_load_and_transpose(
316 n_comp, this->begin(), indices.data(), &tensor[0]);
317
318 } else {
319 /* not implemented */
320 __builtin_trap();
321 }
322
323 return tensor;
324 }
325
326
327 template <typename Number, int n_comp, int simd_length>
328 template <typename Number2, typename Tensor>
329 DEAL_II_ALWAYS_INLINE inline void
331 const Tensor &tensor, const unsigned int i)
332 {
333 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
334 "dummy type mismatch");
335
336 /* Special case of a zero component vector */
337 if constexpr (n_comp == 0)
338 return;
339
340 if constexpr (std::is_same<Number, Number2>::value) {
341 /* Non-vectorized sequential access. */
342
343 for (unsigned int d = 0; d < n_comp; ++d)
344 this->local_element(i * n_comp + d) = tensor[d];
345
346 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
347 /* Vectorized fast access. index must be divisible by simd_length */
348
349 std::array<unsigned int, VectorizedArray::size()> indices;
350 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
351 indices[k] = k * n_comp;
352
353 dealii::vectorized_transpose_and_store(/*add into*/ false,
354 n_comp,
355 &tensor[0],
356 indices.data(),
357 this->begin() + i * n_comp);
358
359 } else {
360 /* not implemented */
361 __builtin_trap();
362 }
363 }
364
365
366 template <typename Number, int n_comp, int simd_length>
367 template <typename Number2, typename Tensor>
368 DEAL_II_ALWAYS_INLINE inline void
370 const Tensor &tensor, const unsigned int i)
371 {
372 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
373 "dummy type mismatch");
374
375 /* Special case of a zero component vector */
376 if constexpr (n_comp == 0)
377 return;
378
379 if constexpr (std::is_same<Number, Number2>::value) {
380 /* Non-vectorized sequential access. */
381
382 for (unsigned int d = 0; d < n_comp; ++d)
383 this->local_element(i * n_comp + d) += tensor[d];
384
385 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
386 /* Vectorized fast access. index must be divisible by simd_length */
387
388 std::array<unsigned int, VectorizedArray::size()> indices;
389 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
390 indices[k] = k * n_comp;
391
392 dealii::vectorized_transpose_and_store(/*add into*/ true,
393 n_comp,
394 &tensor[0],
395 indices.data(),
396 this->begin() + i * n_comp);
397
398 } else {
399 /* not implemented */
400 __builtin_trap();
401 }
402 }
403#endif
404 } // namespace Vectors
405} // namespace ryujin
void write_tensor(const Tensor &tensor, const unsigned int i)
void extract_component(ScalarVector &scalar_vector, unsigned int component) const
void add_tensor(const Tensor &tensor, const unsigned int i)
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