SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Interpolation/Actions - TryToInterpolate.hpp Hit Total Coverage
Commit: 361cb8d8406bb752684a5f31c27320ec444a50e3 Lines: 1 2 50.0 %
Date: 2025-11-09 02:02:04
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 <cstddef>
       7             : #include <sstream>
       8             : #include <string>
       9             : 
      10             : #include "DataStructures/DataBox/DataBox.hpp"
      11             : #include "DataStructures/Variables.hpp"
      12             : #include "DataStructures/VariablesTag.hpp"
      13             : #include "Domain/Creators/Tags/Domain.hpp"
      14             : #include "Domain/ElementLogicalCoordinates.hpp"
      15             : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      16             : #include "Domain/TagsTimeDependent.hpp"
      17             : #include "IO/Logging/Verbosity.hpp"
      18             : #include "NumericalAlgorithms/Interpolation/IrregularInterpolant.hpp"
      19             : #include "Parallel/GlobalCache.hpp"
      20             : #include "Parallel/Info.hpp"
      21             : #include "Parallel/Invoke.hpp"
      22             : #include "Parallel/Printf/Printf.hpp"
      23             : #include "ParallelAlgorithms/Interpolation/InterpolationTargetDetail.hpp"
      24             : #include "ParallelAlgorithms/Interpolation/Tags.hpp"
      25             : #include "Utilities/Algorithm.hpp"
      26             : #include "Utilities/Gsl.hpp"
      27             : #include "Utilities/PrettyType.hpp"
      28             : #include "Utilities/StdHelpers.hpp"
      29             : #include "Utilities/System/ParallelInfo.hpp"
      30             : #include "Utilities/TMPL.hpp"
      31             : #include "Utilities/TaggedTuple.hpp"
      32             : 
      33             : /// \cond
      34             : namespace intrp {
      35             : template <typename Metavariables, typename InterpolationTargetTag>
      36             : struct InterpolationTarget;
      37             : namespace Actions {
      38             : template <typename InterpolationTargetTag>
      39             : struct InterpolationTargetReceiveVars;
      40             : }  // namespace Actions
      41             : }  // namespace intrp
      42             : /// \endcond
      43             : 
      44             : namespace intrp {
      45             : 
      46             : namespace interpolator_detail {
      47             : 
      48             : // Interpolates data onto a set of points desired by an InterpolationTarget.
      49             : template <typename InterpolationTargetTag, typename Metavariables,
      50             :           typename DbTags>
      51             : void interpolate_data(
      52             :     const gsl::not_null<db::DataBox<DbTags>*> box,
      53             :     Parallel::GlobalCache<Metavariables>& cache,
      54             :     const typename InterpolationTargetTag::temporal_id::type& temporal_id) {
      55             :   db::mutate_apply<
      56             :       tmpl::list<
      57             :           ::intrp::Tags::InterpolatedVarsHolders<Metavariables>,
      58             :           ::intrp::Tags::VolumeVarsInfo<
      59             :               Metavariables, typename InterpolationTargetTag::temporal_id>>,
      60             :       tmpl::list<domain::Tags::Domain<Metavariables::volume_dim>>>(
      61             :       [&cache, &temporal_id](
      62             :           const gsl::not_null<typename ::intrp::Tags::InterpolatedVarsHolders<
      63             :               Metavariables>::type*>
      64             :               holders,
      65             :           const gsl::not_null<typename ::intrp::Tags::VolumeVarsInfo<
      66             :               Metavariables,
      67             :               typename InterpolationTargetTag::temporal_id>::type*>
      68             :               volume_vars_info,
      69             :           const Domain<Metavariables::volume_dim>& domain) {
      70             :         auto& interp_info =
      71             :             get<Vars::HolderTag<InterpolationTargetTag, Metavariables>>(
      72             :                 *holders)
      73             :                 .infos.at(temporal_id);
      74             : 
      75             :         // Avoid compiler warning for unused variable in some 'if
      76             :         // constexpr' branches.
      77             :         (void)cache;
      78             : 
      79             :         for (auto& volume_info_outer : *volume_vars_info) {
      80             :           // Are we at the right time?
      81             :           if (volume_info_outer.first != temporal_id) {
      82             :             continue;
      83             :           }
      84             : 
      85             :           // Get list of ElementIds that have the correct temporal_id and that
      86             :           // have not yet been interpolated.
      87             :           std::vector<ElementId<Metavariables::volume_dim>> element_ids;
      88             : 
      89             :           for (const auto& volume_info_inner : volume_info_outer.second) {
      90             :             // Have we interpolated this element before?
      91             :             if (interp_info.interpolation_is_done_for_these_elements.find(
      92             :                     volume_info_inner.first) ==
      93             :                 interp_info.interpolation_is_done_for_these_elements.end()) {
      94             :               interp_info.interpolation_is_done_for_these_elements.emplace(
      95             :                   volume_info_inner.first);
      96             :               element_ids.push_back(volume_info_inner.first);
      97             :             }
      98             :           }
      99             : 
     100             :           // Get element logical coordinates.
     101             :           const auto element_coord_holders = element_logical_coordinates(
     102             :               element_ids, interp_info.block_coord_holders);
     103             : 
     104             :           // Construct local vars and interpolate.
     105             :           for (const auto& element_coord_pair : element_coord_holders) {
     106             :             const auto& element_id = element_coord_pair.first;
     107             :             auto& volume_info = volume_info_outer.second.at(element_id);
     108             :             auto& vars_to_interpolate =
     109             :                 get<::intrp::Tags::VarsToInterpolateToTarget<
     110             :                     InterpolationTargetTag>>(volume_info.vars_to_interpolate);
     111             : 
     112             :             if constexpr (InterpolationTarget_detail::
     113             :                               has_compute_vars_to_interpolate_v<
     114             :                                   InterpolationTargetTag>) {
     115             :               if (vars_to_interpolate.size() == 0) {
     116             :                 // vars_to_interpolate has not been filled for
     117             :                 // this element at this temporal_id.  So fill it.
     118             :                 vars_to_interpolate.initialize(
     119             :                     volume_info.source_vars_from_element
     120             :                         .number_of_grid_points());
     121             : 
     122             :                 InterpolationTarget_detail::compute_dest_vars_from_source_vars<
     123             :                     InterpolationTargetTag>(
     124             :                     make_not_null(&vars_to_interpolate),
     125             :                     volume_info.source_vars_from_element, domain,
     126             :                     volume_info.mesh, element_id, cache, temporal_id);
     127             :               }
     128             :             }
     129             : 
     130             :             // Now interpolate.
     131             :             const auto& element_coord_holder = element_coord_pair.second;
     132             :             intrp::Irregular<Metavariables::volume_dim> interpolator(
     133             :                 volume_info.mesh, element_coord_holder.element_logical_coords);
     134             :             // This first branch is used if compute_vars_to_interpolate exists
     135             :             // or if the vars_to_interpolate_to_target is a subset of the
     136             :             // interpolator_source_vars.
     137             :             if constexpr (
     138             :                 InterpolationTarget_detail::has_compute_vars_to_interpolate_v<
     139             :                     InterpolationTargetTag> or
     140             :                 not std::is_same_v<
     141             :                     tmpl::list_difference<
     142             :                         typename Metavariables::interpolator_source_vars,
     143             :                         typename InterpolationTargetTag::
     144             :                             vars_to_interpolate_to_target>,
     145             :                     tmpl::list<>>) {
     146             :               interp_info.vars.emplace_back(
     147             :                   interpolator.interpolate(vars_to_interpolate));
     148             :             } else {
     149             :               // If compute_vars_to_interpolate does not exist and
     150             :               // vars_to_interpolate_to_target isn't a subset of
     151             :               // interpolator_source_vars, then
     152             :               // volume_info.source_vars_from_element is the same as
     153             :               // volume_info.vars_to_interpolate.
     154             :               interp_info.vars.emplace_back(interpolator.interpolate(
     155             :                   volume_info.source_vars_from_element));
     156             :             }
     157             :             interp_info.global_offsets.emplace_back(
     158             :                 element_coord_holder.offsets);
     159             :           }
     160             :         }
     161             :       },
     162             :       box);
     163             : }
     164             : }  // namespace interpolator_detail
     165             : 
     166             : /// Check if we have enough information to interpolate.  If so, do the
     167             : /// interpolation and send data to the InterpolationTarget.
     168             : template <typename InterpolationTargetTag, typename Metavariables,
     169             :           typename DbTags>
     170           1 : void try_to_interpolate(
     171             :     const gsl::not_null<db::DataBox<DbTags>*> box,
     172             :     const gsl::not_null<Parallel::GlobalCache<Metavariables>*> cache,
     173             :     const typename InterpolationTargetTag::temporal_id::type& temporal_id) {
     174             :   const auto& holders =
     175             :       db::get<Tags::InterpolatedVarsHolders<Metavariables>>(*box);
     176             :   const auto& vars_infos =
     177             :       get<Vars::HolderTag<InterpolationTargetTag, Metavariables>>(holders)
     178             :           .infos;
     179             :   std::stringstream ss{};
     180             :   const ::Verbosity& verbosity = Parallel::get<intrp::Tags::Verbosity>(*cache);
     181             :   const bool debug_print = verbosity >= ::Verbosity::Debug;
     182             : 
     183             :   if (debug_print) {
     184             :     ss << InterpolationTarget_detail::interpolator_output_prefix<
     185             :               InterpolationTargetTag>(temporal_id)
     186             :        << ", ";
     187             :   }
     188             : 
     189             :   // If we don't yet have any points for this InterpolationTarget at
     190             :   // this temporal_id, we should exit (we can't interpolate anyway).
     191             :   if (vars_infos.count(temporal_id) == 0) {
     192             :     if (debug_print) {
     193             :       ss << "no points received yet. Can't do anything.\n";
     194             :       Parallel::printf("%s", ss.str());
     195             :     }
     196             :     return;
     197             :   }
     198             : 
     199             :   interpolator_detail::interpolate_data<InterpolationTargetTag, Metavariables>(
     200             :       box, *cache, temporal_id);
     201             : 
     202             :   // Send interpolated data only if interpolation has been done on all
     203             :   // of the local elements.
     204             :   const auto& all_num_elements =
     205             :       db::get<Tags::NumberOfElements<Metavariables::volume_dim>>(*box);
     206             :   const std::string& target_name = pretty_type::name<InterpolationTargetTag>();
     207             :   if (not all_num_elements.contains(target_name)) {
     208             :     ERROR("Target name " << target_name << " not in NumberOfElements: "
     209             :                          << keys_of(all_num_elements));
     210             :   }
     211             :   const auto& num_elements = all_num_elements.at(target_name);
     212             :   // Since some targets may not need all elements, we must specifically check if
     213             :   // we have all the necessary elements
     214             :   if (alg::all_of(num_elements, [&](const auto& element) {
     215             :         return vars_infos.at(temporal_id)
     216             :             .interpolation_is_done_for_these_elements.contains(element);
     217             :       })) {
     218             :     // Send data to InterpolationTarget, but only if the list of points is
     219             :     // non-empty.
     220             :     if (debug_print) {
     221             :       ss << "finished interpolation on all " << num_elements.size()
     222             :          << " elements on core " << Parallel::my_proc<int>(*cache);
     223             :     }
     224             : 
     225             :     if (not vars_infos.at(temporal_id).global_offsets.empty()) {
     226             :       const auto& info = vars_infos.at(temporal_id);
     227             :       auto& receiver_proxy = Parallel::get_parallel_component<
     228             :           InterpolationTarget<Metavariables, InterpolationTargetTag>>(*cache);
     229             :       Parallel::simple_action<
     230             :           Actions::InterpolationTargetReceiveVars<InterpolationTargetTag>>(
     231             :           receiver_proxy, info.vars, info.global_offsets, temporal_id);
     232             : 
     233             :       if (debug_print) {
     234             :         ss << " Sending interpolated data.\n";
     235             :       }
     236             :     } else if (debug_print) {
     237             :       ss << " Global offsets empty. Nothing to interpolate.";
     238             :     }
     239             : 
     240             :     // Clear interpolated data, since we don't need it anymore.
     241             :     db::mutate<Tags::InterpolatedVarsHolders<Metavariables>>(
     242             :         [&temporal_id](
     243             :             const gsl::not_null<
     244             :                 typename Tags::InterpolatedVarsHolders<Metavariables>::type*>
     245             :                 holders_l) {
     246             :           get<Vars::HolderTag<InterpolationTargetTag, Metavariables>>(
     247             :               *holders_l)
     248             :               .infos.erase(temporal_id);
     249             :         },
     250             :         box);
     251             :   } else if (debug_print) {
     252             :     ss << "interpolation not finished on all local elements of core "
     253             :        << Parallel::my_proc<int>(*cache) << ". Expected " << num_elements.size()
     254             :        << ", received "
     255             :        << vars_infos.at(temporal_id)
     256             :               .interpolation_is_done_for_these_elements.size();
     257             :   }
     258             : 
     259             :   if (debug_print) {
     260             :     Parallel::printf("%s\n", ss.str());
     261             :   }
     262             : }
     263             : 
     264             : }  // namespace intrp

Generated by: LCOV version 1.14