8#include <compile_time_options.h>
10#include <ryujin/interface/parabolic_system.h>
28 template <
typename Description,
32 class SelectedComponentsExtractorView;
78 template <
typename Description,
int dim,
typename Number>
103 2 * View::problem_dimension;
126 const Interface::ParabolicSystem ¶bolic_system,
128 const std::vector<std::string> &additional_names = {},
129 const std::vector<std::reference_wrapper<const ScalarVector<Number>>>
130 &additional_vectors = {});
140 void prepare(
const std::vector<std::string> &selected);
158 template <
typename MemorySpace = dealii::MemorySpace::Host>
185 template <
typename MemorySpace = dealii::MemorySpace::Host>
196 dealii::ObserverPointer<const OfflineData<dim, Number>> offline_data_;
197 dealii::ObserverPointer<const HyperbolicSystem> hyperbolic_system_;
198 dealii::ObserverPointer<const Interface::ParabolicSystem> parabolic_system_;
202 const std::vector<std::string> additional_names_;
203 const std::vector<std::reference_wrapper<const ScalarVector<Number>>>
209 const unsigned int additional_offset_;
215 std::vector<unsigned int> selection_;
222 bool read_conserved_ =
false;
223 bool read_primitive_ =
false;
224 bool read_precomputed_ =
false;
225 bool read_initial_ =
false;
227 template <
typename MemorySpace>
235 mutable std::variant<std::monostate,
256 template <
typename Description,
259 typename MemorySpace>
263 static_assert(std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
264 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
265 "Unexpected memory space");
280 dealii::LinearAlgebra::distributed::Vector<Number, MemorySpace>;
301 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int n_selected()
const
303 return static_cast<unsigned int>(entries_.extent(0));
324 template <
typename T = Number,
typename Writer>
325 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
335 using HyperbolicSystem =
typename Description::HyperbolicSystem;
336 using EquationView =
typename HyperbolicSystem::template View<dim, Number>;
338 template <
int n_comp>
371 bool read_conserved_ =
false;
372 bool read_primitive_ =
false;
373 bool read_precomputed_ =
false;
374 bool read_initial_ =
false;
378 HyperbolicVectorView U_view_;
379 PrecomputedVectorView precomputed_view_;
380 InitialPrecomputedVectorView initial_view_;
386 Kokkos::View<const Entry *, typename MemorySpace::kokkos_space> entries_;
402 template <
typename Description,
int dim,
typename Number>
407 const Interface::ParabolicSystem ¶bolic_system,
409 const std::vector<std::string> &additional_names,
412 : offline_data_(&offline_data)
413 , hyperbolic_system_(&hyperbolic_system)
414 , parabolic_system_(¶bolic_system)
415 , initial_precomputed_(initial_precomputed)
416 , additional_names_(additional_names)
417 , additional_vectors_(additional_vectors)
418 , additional_offset_(parabolic_offset +
419 parabolic_system.state_names(dim).size())
421 Assert(additional_names_.size() == additional_vectors_.size(),
422 dealii::ExcMessage(
"The number of additional component names does "
423 "not match the number of additional vectors."));
427 template <
typename Description,
int dim,
typename Number>
429 const std::vector<std::string> &selected)
431 std::vector<unsigned int> selection;
432 selection.reserve(selected.size());
434 for (
const auto &entry : selected) {
435 const auto search = [&](
const auto &names,
const unsigned int offset) {
436 const auto pos = std::find(std::begin(names), std::end(names), entry);
437 if (pos == std::end(names))
439 const unsigned int index = std::distance(std::begin(names), pos);
440 selection.push_back(offset + index);
445 search(hyperbolic_system_->state_names(dim), conserved_offset) ||
446 search(hyperbolic_system_->primitive_names(dim), primitive_offset) ||
447 search(hyperbolic_system_->precomputed_names(dim),
448 precomputed_offset) ||
449 search(hyperbolic_system_->initial_precomputed_names(dim),
451 search(parabolic_system_->state_names(dim), parabolic_offset) ||
452 search(additional_names_, additional_offset_);
456 "Invalid component name: \"" + entry +
457 "\" is not a valid conserved, primitive, precomputed, "
458 "initial, parabolic, or additional component name."));
466 const auto selects = [&](
const unsigned int begin,
const unsigned int end) {
468 selection.begin(), selection.end(), [&](
const auto offset) {
469 return begin <= offset && offset < end;
473 read_conserved_ = selects(conserved_offset, primitive_offset);
474 read_primitive_ = selects(primitive_offset, precomputed_offset);
475 read_precomputed_ = selects(precomputed_offset, initial_offset);
476 read_initial_ = selects(initial_offset, parabolic_offset);
478 selection_ = std::move(selection);
481 view_ = std::monostate{};
485 template <
typename Description,
int dim,
typename Number>
486 template <
typename MemorySpace>
489 const StateVector<Number> &state_vector)
const
491 ExtractorView<MemorySpace> view(*offline_data_, *hyperbolic_system_);
493 view.read_conserved_ = read_conserved_;
494 view.read_primitive_ = read_primitive_;
495 view.read_precomputed_ = read_precomputed_;
496 view.read_initial_ = read_initial_;
503 if (read_conserved_ || read_primitive_) {
504 copy_to_memory_space<MemorySpace>(state_vector,
507 state_vector.U.template view<View::problem_dimension, MemorySpace>();
510 if (read_precomputed_) {
511 copy_to_memory_space<MemorySpace>(state_vector,
513 view.precomputed_view_ =
514 state_vector.precomputed
515 .template view<View::n_precomputed_values, MemorySpace>();
519 copy_to_memory_space<MemorySpace>(initial_precomputed_);
522 .template view<View::n_initial_precomputed_values, MemorySpace>();
531 Kokkos::View<typename ExtractorView<MemorySpace>::Entry *,
533 entries(
"selected_components_entries", n_selected());
537 for (
unsigned int k = 0; k < n_selected(); ++k) {
538 const auto offset = selection_[k];
539 entries[k].offset = offset;
541 if (offset < parabolic_offset)
545 offset < additional_offset_
547 : additional_vectors_[offset - additional_offset_].get();
549 copy_to_memory_space<MemorySpace>(vector);
550 entries[k].scalar_view = vector.template view<1, MemorySpace>();
553 view.entries_ = Kokkos::create_mirror_view_and_copy(
554 typename MemorySpace::kokkos_space{}, entries);
557 view_.template emplace<ExtractorView<MemorySpace>>(std::move(view));
561 template <
typename Description,
int dim,
typename Number>
565 return static_cast<unsigned int>(selection_.size());
569 template <
typename Description,
int dim,
typename Number>
570 template <
typename MemorySpace>
571 SelectedComponentsExtractorView<Description, dim, Number, MemorySpace>
574 Assert(std::holds_alternative<ExtractorView<MemorySpace>>(view_),
576 "Invalid state: prepare_extraction() has to be called for the "
577 "selected memory space before a view can be created."));
579 return std::get<ExtractorView<MemorySpace>>(view_);
583 template <
typename Description,
586 typename MemorySpace>
587 SelectedComponentsExtractorView<Description, dim, Number, MemorySpace>::
588 SelectedComponentsExtractorView(
589 const OfflineData<dim, Number> &offline_data,
590 const HyperbolicSystem &hyperbolic_system)
591 : offline_data_(&offline_data)
592 , system_views_(hyperbolic_system)
597 template <
typename Description,
600 typename MemorySpace>
604 const auto &offline_data = *offline_data_;
611 std::vector<ScalarVector> extracted_components(n_selected());
617 Kokkos::View<Destination *, Kokkos::HostSpace> host_destinations(
618 "selected_components_destinations", n_selected());
620 for (
unsigned int k = 0; k < n_selected(); ++k) {
621 extracted_components[k].reinit(offline_data.scalar_partitioner());
622 host_destinations[k].data = extracted_components[k].begin();
625 const auto destinations = Kokkos::create_mirror_view_and_copy(
626 typename MemorySpace::kokkos_space{}, host_destinations);
632 const auto view = *
this;
634 const auto body = [=](
auto sentinel,
unsigned int i) {
635 using T =
decltype(sentinel);
637 view.template extract_element<T>(
638 i, [&](
const unsigned int k,
const T &value) {
639 if constexpr (std::is_same_v<T, dealii::VectorizedArray<Number>>)
640 value.store(destinations[k].data + i);
642 destinations[k].data[i] = value;
646 loop<MemorySpace, Number>(
"extract_selected_components",
649 offline_data.n_locally_internal(),
650 offline_data.n_locally_owned());
652 for (
auto &it : extracted_components)
653 it.update_ghost_values();
655 return extracted_components;
659 template <
typename Description,
662 typename MemorySpace>
663 template <
typename T,
typename Writer>
664 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
674 T staging[Extractor::parabolic_offset];
676 if (read_conserved_ || read_primitive_) {
677 const auto U_i = U_view_.template read_tensor<T>(i);
678 for (
unsigned int d = 0; d < EquationView::problem_dimension; ++d)
679 staging[Extractor::conserved_offset + d] = U_i[d];
681 if (read_primitive_) {
682 const auto primitive_i =
683 system_views_.template view<T>().to_primitive_state(U_i);
684 for (
unsigned int d = 0; d < EquationView::problem_dimension; ++d)
685 staging[Extractor::primitive_offset + d] = primitive_i[d];
689 if (read_precomputed_) {
690 const auto precomputed_i = precomputed_view_.template read_tensor<T>(i);
691 for (
unsigned int d = 0; d < EquationView::n_precomputed_values; ++d)
692 staging[Extractor::precomputed_offset + d] = precomputed_i[d];
696 const auto initial_i = initial_view_.template read_tensor<T>(i);
697 for (
unsigned int d = 0; d < EquationView::n_initial_precomputed_values;
699 staging[Extractor::initial_offset + d] = initial_i[d];
707 for (
unsigned int k = 0; k < n_selected(); ++k) {
708 const auto &entry = entries_[k];
710 if (entry.offset < Extractor::parabolic_offset)
711 write(k, staging[entry.offset]);
713 write(k, entry.scalar_view.template read_entry<T>(i));
MultiComponentVector< Number > ScalarVector