ryujin 2.1.1 revision 46bf70e400e423a8ffffe8300887eeb35b8dfb2c
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 <compile_time_options.h>
9
10#include "simd.h"
11
12#include <deal.II/base/mpi.h>
13#include <deal.II/base/partitioner.h>
14#include <deal.II/base/vectorization.h>
15#include <deal.II/lac/la_parallel_vector.h>
16
17namespace ryujin
18{
19 namespace Vectors
20 {
40 std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
42 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
43 &scalar_partitioner,
44 const unsigned int n_components);
45
46
57 template <typename Number,
58 int n_comp,
59 int simd_length = dealii::VectorizedArray<Number>::size()>
61 : public dealii::LinearAlgebra::distributed::Vector<Number>
62 {
63 public:
69 using VectorizedArray = dealii::VectorizedArray<Number, simd_length>;
70
76 using ScalarVector = dealii::LinearAlgebra::distributed::Vector<Number>;
77
82 using ScalarVector::operator=;
83
91 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
92 &scalar_partitioner);
93
108 void extract_component(ScalarVector &scalar_vector,
109 unsigned int component) const;
110
124 void insert_component(const ScalarVector &scalar_vector,
125 unsigned int component);
126
136 template <typename Number2 = Number,
137 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
138 Tensor get_tensor(const unsigned int i) const;
139
148 template <typename Number2 = Number,
149 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
150 Tensor get_tensor(const unsigned int *js) const;
151
165 template <typename Number2 = Number,
166 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
167 void write_tensor(const Tensor &tensor, const unsigned int i);
168
182 template <typename Number2 = Number,
183 typename Tensor = dealii::Tensor<1, n_comp, Number2>>
184 void add_tensor(const Tensor &tensor, const unsigned int i);
185 };
186
187
188#ifndef DOXYGEN
189 /* Template definitions: */
190
191 template <typename Number, int n_comp, int simd_length>
194 const std::shared_ptr<const dealii::Utilities::MPI::Partitioner>
195 &scalar_partitioner)
196 {
197 /* Special case of a zero component vector */
198 if (n_comp == 0)
199 return;
200
201 auto vector_partitioner =
202 create_vector_partitioner(scalar_partitioner, n_comp);
203
204 dealii::LinearAlgebra::distributed::Vector<Number>::reinit(
205 vector_partitioner);
206 }
207
208
209 template <typename Number, int n_comp, int simd_length>
211 ScalarVector &scalar_vector, unsigned int component) const
212 {
213 Assert(n_comp > 0,
214 dealii::ExcMessage(
215 "Cannot extract from a vector with zero components."));
216
217 Assert(n_comp * scalar_vector.get_partitioner()->locally_owned_size() ==
218 this->get_partitioner()->locally_owned_size(),
219 dealii::ExcMessage("Called with a scalar_vector argument that has "
220 "incompatible local range."));
221 const auto local_size =
222 scalar_vector.get_partitioner()->locally_owned_size();
223 for (unsigned int i = 0; i < local_size; ++i)
224 scalar_vector.local_element(i) =
225 this->local_element(i * n_comp + component);
226 scalar_vector.update_ghost_values();
227 }
228
229
230 template <typename Number, int n_comp, int simd_length>
232 const ScalarVector &scalar_vector, unsigned int component)
233 {
234 Assert(n_comp > 0,
235 dealii::ExcMessage(
236 "Cannot insert into a vector with zero components."));
237
238 Assert(n_comp * scalar_vector.get_partitioner()->locally_owned_size() ==
239 this->get_partitioner()->locally_owned_size(),
240 dealii::ExcMessage("Called with a scalar_vector argument that has "
241 "incompatible local range."));
242 const auto local_size =
243 scalar_vector.get_partitioner()->locally_owned_size();
244 for (unsigned int i = 0; i < local_size; ++i)
245 this->local_element(i * n_comp + component) =
246 scalar_vector.local_element(i);
247 }
248
249 /* Inline function definitions: */
250
251 template <typename Number, int n_comp, int simd_length>
252 template <typename Number2, typename Tensor>
253 DEAL_II_ALWAYS_INLINE inline Tensor
255 const unsigned int i) const
256 {
257 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
258 "dummy type mismatch");
259 Tensor tensor;
260
261 /* Special case of a zero component vector */
262 if constexpr (n_comp == 0)
263 return tensor;
264
265 if constexpr (std::is_same<Number, Number2>::value) {
266 /* Non-vectorized sequential access. */
267
268 for (unsigned int d = 0; d < n_comp; ++d)
269 tensor[d] = this->local_element(i * n_comp + d);
270
271 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
272
273 /* Vectorized fast access. index must be divisible by simd_length */
274 std::array<unsigned int, VectorizedArray::size()> indices;
275 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
276 indices[k] = k * n_comp;
277
278 dealii::vectorized_load_and_transpose(
279 n_comp, this->begin() + i * n_comp, indices.data(), &tensor[0]);
280
281 } else {
282 /* not implemented */
283 __builtin_trap();
284 }
285
286 return tensor;
287 }
288
289
290 template <typename Number, int n_comp, int simd_length>
291 template <typename Number2, typename Tensor>
292 DEAL_II_ALWAYS_INLINE inline Tensor
294 const unsigned int *js) const
295 {
296 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
297 "dummy type mismatch");
298 Tensor tensor;
299
300 /* Special case of a zero component vector */
301 if constexpr (n_comp == 0)
302 return tensor;
303
304 if constexpr (std::is_same<Number, Number2>::value) {
305 /* Non-vectorized sequential access. */
306
307 for (unsigned int d = 0; d < n_comp; ++d)
308 tensor[d] = this->local_element(js[0] * n_comp + d);
309
310 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
311 /* Vectorized fast access. index must be divisible by simd_length */
312
313 std::array<unsigned int, VectorizedArray::size()> indices;
314 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
315 indices[k] = js[k] * n_comp;
316
317 dealii::vectorized_load_and_transpose(
318 n_comp, this->begin(), indices.data(), &tensor[0]);
319
320 } else {
321 /* not implemented */
322 __builtin_trap();
323 }
324
325 return tensor;
326 }
327
328
329 template <typename Number, int n_comp, int simd_length>
330 template <typename Number2, typename Tensor>
331 DEAL_II_ALWAYS_INLINE inline void
333 const Tensor &tensor, const unsigned int i)
334 {
335 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
336 "dummy type mismatch");
337
338 /* Special case of a zero component vector */
339 if constexpr (n_comp == 0)
340 return;
341
342 if constexpr (std::is_same<Number, Number2>::value) {
343 /* Non-vectorized sequential access. */
344
345 for (unsigned int d = 0; d < n_comp; ++d)
346 this->local_element(i * n_comp + d) = tensor[d];
347
348 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
349 /* Vectorized fast access. index must be divisible by simd_length */
350
351 std::array<unsigned int, VectorizedArray::size()> indices;
352 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
353 indices[k] = k * n_comp;
354
355 dealii::vectorized_transpose_and_store(/*add into*/ false,
356 n_comp,
357 &tensor[0],
358 indices.data(),
359 this->begin() + i * n_comp);
360
361 } else {
362 /* not implemented */
363 __builtin_trap();
364 }
365 }
366
367
368 template <typename Number, int n_comp, int simd_length>
369 template <typename Number2, typename Tensor>
370 DEAL_II_ALWAYS_INLINE inline void
372 const Tensor &tensor, const unsigned int i)
373 {
374 static_assert(std::is_same<Number2, typename Tensor::value_type>::value,
375 "dummy type mismatch");
376
377 /* Special case of a zero component vector */
378 if constexpr (n_comp == 0)
379 return;
380
381 if constexpr (std::is_same<Number, Number2>::value) {
382 /* Non-vectorized sequential access. */
383
384 for (unsigned int d = 0; d < n_comp; ++d)
385 this->local_element(i * n_comp + d) += tensor[d];
386
387 } else if constexpr (std::is_same<VectorizedArray, Number2>::value) {
388 /* Vectorized fast access. index must be divisible by simd_length */
389
390 std::array<unsigned int, VectorizedArray::size()> indices;
391 for (unsigned int k = 0; k < VectorizedArray::size(); ++k)
392 indices[k] = k * n_comp;
393
394 dealii::vectorized_transpose_and_store(/*add into*/ true,
395 n_comp,
396 &tensor[0],
397 indices.data(),
398 this->begin() + i * n_comp);
399
400 } else {
401 /* not implemented */
402 __builtin_trap();
403 }
404 }
405#endif
406 } // namespace Vectors
407} // 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:33