SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Interpolation/Actions - InterpolationTargetVarsFromElement.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 66.7 % 3 2
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <sstream>
       7              : #include <string>
       8              : #include <unordered_map>
       9              : #include <utility>
      10              : #include <vector>
      11              : 
      12              : #include "DataStructures/DataBox/DataBox.hpp"
      13              : #include "DataStructures/Variables.hpp"
      14              : #include "Domain/BlockLogicalCoordinates.hpp"
      15              : #include "ParallelAlgorithms/Actions/FunctionsOfTimeAreReady.hpp"
      16              : #include "ParallelAlgorithms/Interpolation/InterpolationTargetDetail.hpp"
      17              : #include "ParallelAlgorithms/Interpolation/Tags.hpp"
      18              : #include "Utilities/Gsl.hpp"
      19              : #include "Utilities/TMPL.hpp"
      20              : 
      21              : /// \cond
      22              : namespace domain::Tags {
      23              : struct FunctionsOfTime;
      24              : }  // namespace domain::Tags
      25              : namespace Parallel {
      26              : template <typename Metavariables>
      27              : class GlobalCache;
      28              : }  // namespace Parallel
      29              : /// \endcond
      30              : 
      31              : namespace intrp {
      32              : namespace Actions {
      33              : /// \ingroup ActionsGroup
      34              : /// \brief Receives interpolated variables from an `Element` on a subset
      35              : ///  of the target points.
      36              : ///
      37              : /// If interpolated variables for all target points have been received, then
      38              : /// - Checks if functions of time are ready (if there are any). If they are not
      39              : ///   ready, register a simple action callback with the GlobalCache to this
      40              : ///   action.
      41              : /// - Calls `InterpolationTargetTag::post_interpolation_callbacks`
      42              : /// - Removes the finished `temporal_id` from `Tags::TemporalIds<TemporalId>`
      43              : ///   and adds it to `Tags::CompletedTemporalIds<TemporalId>`
      44              : /// - Removes `Tags::InterpolatedVars<InterpolationTargetTag,TemporalId>`,
      45              : ///   `Tags::IndicesOfFilledInterpPoints`, and
      46              : ///   `Tags::IndicesOfInvalidInterpPoints` for the finished `temporal_id`.
      47              : ///
      48              : /// Uses:
      49              : /// - DataBox:
      50              : ///   - `Tags::TemporalIds<TemporalId>`
      51              : ///   - `Tags::IndicesOfFilledInterpPoints<TemporalId>`
      52              : ///   - `Tags::InterpolatedVars<InterpolationTargetTag,TemporalId>`
      53              : ///   - `Tags::InterpolatedVars<InterpolationTargetTag,TemporalId>`
      54              : ///   - `::Tags::Variables<typename
      55              : ///                   InterpolationTargetTag::vars_to_interpolate_to_target>`
      56              : ///
      57              : /// DataBox changes:
      58              : /// - Adds: nothing
      59              : /// - Removes: nothing
      60              : /// - Modifies:
      61              : ///   - `Tags::TemporalIds<TemporalId>`
      62              : ///   - `Tags::CompletedTemporalIds<TemporalId>`
      63              : ///   - `Tags::IndicesOfFilledInterpPoints<TemporalId>`
      64              : ///   - `Tags::InterpolatedVars<InterpolationTargetTag,TemporalId>`
      65              : ///   - `::Tags::Variables<typename
      66              : ///                   InterpolationTargetTag::vars_to_interpolate_to_target>`
      67              : ///
      68              : /// For requirements on InterpolationTargetTag, see InterpolationTarget
      69              : /// and intrp::protocols::InterpolationTargetTag
      70              : ///
      71              : /// \note This action can be used only with InterpolationTargets that are
      72              : /// non-sequential.
      73              : template <typename InterpolationTargetTag>
      74            1 : struct InterpolationTargetVarsFromElement {
      75              :   /// For requirements on Metavariables, see InterpolationTarget
      76              :   template <typename ParallelComponent, typename DbTags, typename Metavariables,
      77              :             typename ArrayIndex, typename TemporalId>
      78            1 :   static void apply(
      79              :       db::DataBox<DbTags>& box, Parallel::GlobalCache<Metavariables>& cache,
      80              :       const ArrayIndex& array_index,
      81              :       const std::vector<Variables<
      82              :           typename InterpolationTargetTag::vars_to_interpolate_to_target>>&
      83              :           vars_src,
      84              :       const std::vector<BlockLogicalCoords<Metavariables::volume_dim>>&
      85              :           block_logical_coords,
      86              :       const std::vector<std::vector<size_t>>& global_offsets,
      87              :       const TemporalId& temporal_id,
      88              :       const bool vars_have_already_been_received = false) {
      89              :     static_assert(
      90              :         not InterpolationTargetTag::compute_target_points::is_sequential::value,
      91              :         "Use InterpolationTargetGetVarsFromElement only with non-sequential"
      92              :         " compute_target_points");
      93              :     std::stringstream ss{};
      94              :     const ::Verbosity& verbosity = Parallel::get<intrp::Tags::Verbosity>(cache);
      95              :     const bool debug_print = verbosity >= ::Verbosity::Debug;
      96              :     const bool verbose_print = verbosity >= ::Verbosity::Verbose;
      97              :     if (verbose_print) {
      98              :       ss << InterpolationTarget_detail::target_output_prefix<
      99              :                 InterpolationTargetVarsFromElement, InterpolationTargetTag>(
     100              :                 temporal_id)
     101              :          << ", ";
     102              :     }
     103              :     // Check if we already have completed interpolation at this
     104              :     // temporal_id.
     105              :     const auto& completed_ids =
     106              :         db::get<Tags::CompletedTemporalIds<TemporalId>>(box);
     107              :     // (Search from the end because temporal_id is more likely to be
     108              :     // at the end of the list then at the beginning.)
     109              :     if (UNLIKELY(std::find(completed_ids.rbegin(), completed_ids.rend(),
     110              :                            temporal_id) != completed_ids.rend())) {
     111              :       // The code will get into this 'if' statement in the following
     112              :       // scenario:
     113              :       // - There is at least one interpolation point exactly on the
     114              :       //   boundary of two or more Elements, so that
     115              :       //   InterpolationTargetVarsFromElement is called more than once
     116              :       //   with data for the same interpolation point (this is ok,
     117              :       //   and add_received_variables handles this).
     118              :       // - The only Elements that have not yet called
     119              :       //   InterpolationTargetVarsFromElement for this temporal_id are
     120              :       //   those that have data only for duplicated interpolation
     121              :       //   points, and the InterpolationTarget has already received
     122              :       //   that data from other Elements.
     123              :       // In this case, the InterpolationTarget proceeds to do its
     124              :       // work because it has all the data it needs. There is now
     125              :       // one more condition needed for the scenario that gets
     126              :       // us inside this 'if':
     127              :       // - The InterpolationTarget has already completed its work at
     128              :       //   this temporal_id, and it has cleaned up its data structures
     129              :       //   for this temporal_id before all of the remaining calls to
     130              :       //   InterpolationTargetVarsFromElement have occurred at this
     131              :       //   temporal_id, and now we are in one of those remaining
     132              :       //   calls.
     133              :       //
     134              :       // If this scenario occurs, we just return. This is because the
     135              :       // InterpolationTarget is done and there is nothing left to do
     136              :       // at this temporal_id.  Note that if there were extra work to
     137              :       // do at this temporal_id, then CompletedTemporalIds would not
     138              :       // have an entry for this temporal_id.
     139              :       return;
     140              :     }
     141              : 
     142              :     // Call set_up_interpolation only if it has not been called for this
     143              :     // temporal_id.
     144              :     // If flag_temporal_ids_for_interpolation returns an empty list, then
     145              :     // flag_temporal_ids_for_interpolation has already been called for the
     146              :     // same temporal_id (by an invocation of InterpolationTargetVarsFromElement
     147              :     // by a different Element) and hence set_up_interpolation has already
     148              :     // been called.
     149              :     if (InterpolationTarget_detail::flag_temporal_id_for_interpolation<
     150              :             InterpolationTargetTag>(make_not_null(&box), temporal_id)) {
     151              :       InterpolationTarget_detail::set_up_interpolation<InterpolationTargetTag>(
     152              :           make_not_null(&box), temporal_id, block_logical_coords);
     153              :     }
     154              : 
     155              :     if (not vars_have_already_been_received) {
     156              :       InterpolationTarget_detail::add_received_variables<
     157              :           InterpolationTargetTag>(make_not_null(&box), vars_src, global_offsets,
     158              :                                   temporal_id);
     159              :     }
     160              : 
     161              :     if (InterpolationTarget_detail::have_data_at_all_points<
     162              :             InterpolationTargetTag>(box, temporal_id, verbosity)) {
     163              :       // Check if functions of time are ready on this component. Since this
     164              :       // simple action has already been called, we don't need to resend the
     165              :       // data, so we just pass empty vectors for vars_src and
     166              :       // block_logical_coords
     167              :       if (not domain::functions_of_time_are_ready_simple_action_callback<
     168              :               domain::Tags::FunctionsOfTime,
     169              :               InterpolationTargetVarsFromElement>(
     170              :               cache, array_index,
     171              :               std::add_pointer_t<ParallelComponent>{nullptr},
     172              :               InterpolationTarget_detail::get_temporal_id_value(temporal_id),
     173              :               std::nullopt, std::decay_t<decltype(vars_src)>{},
     174              :               std::decay_t<decltype(block_logical_coords)>{}, global_offsets,
     175              :               temporal_id, true)) {
     176              :         return;
     177              :       }
     178              :       // All the valid points have been interpolated.
     179              :       // We throw away the return value of call_callbacks in this case
     180              :       // (it is known to be always true; it can be false only for
     181              :       //  sequential interpolations, which is static-asserted against above).
     182              :       InterpolationTarget_detail::call_callbacks<InterpolationTargetTag>(
     183              :           make_not_null(&box), make_not_null(&cache), temporal_id);
     184              :       InterpolationTarget_detail::clean_up_interpolation_target<
     185              :           InterpolationTargetTag>(make_not_null(&box), temporal_id);
     186              :       if (verbose_print) {
     187              :         ss << "calling callbacks and cleaning up target.";
     188              :         Parallel::printf("%s\n", ss.str());
     189              :       }
     190              :     } else if (debug_print) {
     191              :       ss << "not enough data. Waiting. See Total/valid/invalid points line.";
     192              :       Parallel::printf("%s\n", ss.str());
     193              :     }
     194              :   }
     195              : };
     196              : }  // namespace Actions
     197              : }  // namespace intrp
        

Generated by: LCOV version 2.0-1