SpECTRE Documentation Coverage Report
Current view: top level - Elliptic/Systems/SelfForce/GeneralRelativity/Actions - InitializeEffectiveSource.hpp Hit Total Coverage
Commit: 3ffcbc8ecf43797401b60bcca17d6040ee06f013 Lines: 1 15 6.7 %
Date: 2026-03-03 02:01:44
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 <optional>
       8             : #include <utility>
       9             : 
      10             : #include "DataStructures/DataBox/DataBox.hpp"
      11             : #include "DataStructures/DataBox/MetavariablesTag.hpp"
      12             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      13             : #include "DataStructures/DataBox/Prefixes.hpp"
      14             : #include "DataStructures/Variables.hpp"
      15             : #include "DataStructures/VariablesTag.hpp"
      16             : #include "Domain/BlockLogicalCoordinates.hpp"
      17             : #include "Domain/Creators/Tags/Domain.hpp"
      18             : #include "Domain/Domain.hpp"
      19             : #include "Domain/Structure/ElementId.hpp"
      20             : #include "Domain/Tags.hpp"
      21             : #include "Elliptic/DiscontinuousGalerkin/Tags.hpp"
      22             : #include "Elliptic/Systems/SelfForce/GeneralRelativity/AnalyticData/CircularOrbit.hpp"
      23             : #include "Elliptic/Systems/SelfForce/GeneralRelativity/Equations.hpp"
      24             : #include "Elliptic/Systems/SelfForce/GeneralRelativity/Tags.hpp"
      25             : #include "NumericalAlgorithms/DiscontinuousGalerkin/ApplyMassMatrix.hpp"
      26             : #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
      27             : #include "NumericalAlgorithms/DiscontinuousGalerkin/NormalDotFlux.hpp"
      28             : #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags.hpp"
      29             : #include "Parallel/AlgorithmExecution.hpp"
      30             : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
      31             : #include "Utilities/CallWithDynamicType.hpp"
      32             : #include "Utilities/MakeWithValue.hpp"
      33             : #include "Utilities/TMPL.hpp"
      34             : #include "Utilities/TaggedTuple.hpp"
      35             : 
      36             : /// \cond
      37             : namespace Parallel {
      38             : template <typename Metavariables>
      39             : struct GlobalCache;
      40             : }  // namespace Parallel
      41             : /// \endcond
      42             : 
      43           0 : namespace GrSelfForce::Actions {
      44             : 
      45             : /*!
      46             :  * \brief Initialize the effective source and singular field for the
      47             :  * gravitational self-force problem in a regularized region around the puncture.
      48             :  * Replaces 'elliptic::Actions::InitializeFixedSources' in the standard elliptic
      49             :  * initialization.
      50             :  *
      51             :  * \details The regularized region is chosen as the full block containing the
      52             :  * puncture. In this region, the `Tags::FieldIsRegularized` is set to true and
      53             :  * the effective source and the singular field are set by the
      54             :  * GrSelfForce::AnalyticData::CircularOrbit class. Outside this region, the
      55             :  * fixed source and singular field are set to zero.
      56             :  */
      57             : template <typename System, typename BackgroundTag>
      58           1 : struct InitializeEffectiveSource : tt::ConformsTo<::amr::protocols::Projector> {
      59             :  private:
      60           0 :   static constexpr size_t Dim = System::volume_dim;
      61           0 :   using fixed_sources_tag = ::Tags::Variables<
      62             :       db::wrap_tags_in<::Tags::FixedSource, typename System::primal_fields>>;
      63           0 :   using singular_vars_tag = ::Tags::Variables<tmpl::list<
      64             :       Tags::SingularField,
      65             :       ::Tags::deriv<Tags::SingularField, tmpl::size_t<Dim>, Frame::Inertial>>>;
      66           0 :   using singular_vars_on_mortars_tag =
      67             :       ::Tags::Variables<tmpl::list<Tags::SingularField,
      68             :                                    ::Tags::NormalDotFlux<Tags::SingularField>>>;
      69           0 :   using analytic_tags_list = tmpl::push_back<
      70             :       typename fixed_sources_tag::tags_list, Tags::SingularField,
      71             :       ::Tags::deriv<Tags::SingularField, tmpl::size_t<Dim>, Frame::Inertial>,
      72             :       Tags::BoyerLindquistRadius>;
      73             : 
      74             :  public:  // Iterable action
      75           0 :   using const_global_cache_tags =
      76             :       tmpl::list<elliptic::dg::Tags::Massive, BackgroundTag>;
      77           0 :   using simple_tags =
      78             :       tmpl::list<fixed_sources_tag, singular_vars_tag,
      79             :                  ::Tags::Mortars<singular_vars_on_mortars_tag, Dim>,
      80             :                  Tags::BoyerLindquistRadius, Tags::FieldIsRegularized,
      81             :                  ::Tags::Mortars<Tags::FieldIsRegularized, Dim>>;
      82           0 :   using compute_tags = tmpl::list<>;
      83             : 
      84             :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
      85             :             typename ActionList, typename ParallelComponent>
      86           0 :   static Parallel::iterable_action_return_t apply(
      87             :       db::DataBox<DbTagsList>& box,
      88             :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
      89             :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
      90             :       const ElementId<Dim>& /*array_index*/, const ActionList /*meta*/,
      91             :       const ParallelComponent* const /*meta*/) {
      92             :     db::mutate_apply<InitializeEffectiveSource>(make_not_null(&box));
      93             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
      94             :   }
      95             : 
      96             :  public:  // DataBox mutator, amr::protocols::Projector
      97           0 :   using return_tags = simple_tags;
      98           0 :   using argument_tags = tmpl::list<
      99             :       domain::Tags::Coordinates<Dim, Frame::Inertial>,
     100             :       domain::Tags::Domain<Dim>, domain::Tags::Element<Dim>,
     101             :       ::Tags::Mortars<domain::Tags::Coordinates<Dim, Frame::Inertial>, Dim>,
     102             :       BackgroundTag, elliptic::dg::Tags::Massive, domain::Tags::Mesh<Dim>,
     103             :       domain::Tags::DetInvJacobian<Frame::ElementLogical, Frame::Inertial>,
     104             :       Parallel::Tags::Metavariables>;
     105             : 
     106             :   template <typename Background, typename Metavariables, typename... AmrData>
     107           0 :   static void apply(
     108             :       const gsl::not_null<typename fixed_sources_tag::type*> fixed_sources,
     109             :       const gsl::not_null<typename singular_vars_tag::type*> singular_vars,
     110             :       const gsl::not_null<
     111             :           DirectionalIdMap<Dim, typename singular_vars_on_mortars_tag::type>*>
     112             :           singular_vars_on_mortars,
     113             :       const gsl::not_null<Scalar<DataVector>*> bl_radius,
     114             :       const gsl::not_null<bool*> field_is_regularized,
     115             :       const gsl::not_null<DirectionalIdMap<Dim, bool>*>
     116             :           neighbors_field_is_regularized,
     117             :       const tnsr::I<DataVector, Dim>& inertial_coords,
     118             :       const Domain<Dim>& domain, const Element<Dim>& element,
     119             :       const DirectionalIdMap<Dim, tnsr::I<DataVector, Dim>>&
     120             :           all_mortar_inertial_coords,
     121             :       const Background& background, const bool massive, const Mesh<Dim>& mesh,
     122             :       const Scalar<DataVector>& det_inv_jacobian, const Metavariables& /*meta*/,
     123             :       const AmrData&... /*amr_data*/) {
     124             :     const auto& circular_orbit =
     125             :         dynamic_cast<const GrSelfForce::AnalyticData::CircularOrbit&>(
     126             :             background);
     127             : 
     128             :     // Determine the regularized region
     129             :     const tnsr::I<double, Dim> puncture_pos =
     130             :         circular_orbit.puncture_position();
     131             :     const auto puncture_in_element =
     132             :         [&puncture_pos, &domain](const ElementId<Dim>& element_id) -> bool {
     133             :       // Regularize full block that contains the puncture
     134             :       const auto& block = domain.blocks()[element_id.block_id()];
     135             :       const auto block_logical_coords =
     136             :           block_logical_coordinates_single_point(puncture_pos, block);
     137             :       return block_logical_coords.has_value();
     138             :     };
     139             :     *field_is_regularized = puncture_in_element(element.id());
     140             :     neighbors_field_is_regularized->clear();
     141             :     for (const auto& [direction, neighbors] : element.neighbors()) {
     142             :       for (const auto& neighbor_id : neighbors) {
     143             :         const dg::MortarId<Dim> mortar_id{direction, neighbor_id};
     144             :         neighbors_field_is_regularized->emplace(
     145             :             mortar_id, puncture_in_element(neighbor_id));
     146             :       }
     147             :     }
     148             : 
     149             :     // Set the effective source if solving for the regular field
     150             :     const size_t num_points = mesh.number_of_grid_points();
     151             :     if (*field_is_regularized) {
     152             :       const auto vars =
     153             :           circular_orbit.variables(inertial_coords, analytic_tags_list{});
     154             :       fixed_sources->initialize(num_points);
     155             :       singular_vars->initialize(num_points);
     156             :       get<::Tags::FixedSource<Tags::MMode>>(*fixed_sources) =
     157             :           get<::Tags::FixedSource<Tags::MMode>>(vars);
     158             :       get<Tags::SingularField>(*singular_vars) = get<Tags::SingularField>(vars);
     159             :       get<::Tags::deriv<Tags::SingularField, tmpl::size_t<Dim>,
     160             :                         Frame::Inertial>>(*singular_vars) =
     161             :           get<::Tags::deriv<Tags::SingularField, tmpl::size_t<Dim>,
     162             :                             Frame::Inertial>>(vars);
     163             :       *bl_radius = get<Tags::BoyerLindquistRadius>(vars);
     164             :       // Apply DG mass matrix to the fixed sources if the DG operator is massive
     165             :       if (massive) {
     166             :         *fixed_sources /= get(det_inv_jacobian);
     167             :         ::dg::apply_mass_matrix(fixed_sources, mesh);
     168             :       }
     169             :     } else {
     170             :       *fixed_sources =
     171             :           Variables<typename fixed_sources_tag::tags_list>{num_points, 0.};
     172             :       *singular_vars =
     173             :           Variables<typename singular_vars_tag::tags_list>{num_points, 0.};
     174             :       *bl_radius = Scalar<DataVector>{num_points, 0.};
     175             :     }
     176             : 
     177             :     // Set the singular field and flux on mortars, which is needed to transform
     178             :     // between regularized and full fields
     179             :     singular_vars_on_mortars->clear();
     180             :     for (const auto& [mortar_id, mortar_inertial_coords] :
     181             :          all_mortar_inertial_coords) {
     182             :       if (*field_is_regularized ==
     183             :           neighbors_field_is_regularized->at(mortar_id)) {
     184             :         // Both elements solve for the same field. No transformation needed.
     185             :         continue;
     186             :       }
     187             :       const auto vars_on_mortar = circular_orbit.variables(
     188             :           mortar_inertial_coords, analytic_tags_list{});
     189             :       const auto background_on_mortar = circular_orbit.variables(
     190             :           mortar_inertial_coords,
     191             :           tmpl::list<Tags::Alpha, Tags::Beta, Tags::GammaRstar,
     192             :                      Tags::GammaTheta>{});
     193             :       auto& singular_vars_on_mortar = (*singular_vars_on_mortars)[mortar_id];
     194             :       singular_vars_on_mortar.initialize(
     195             :           mortar_inertial_coords.begin()->size());
     196             :       get<Tags::SingularField>(singular_vars_on_mortar) =
     197             :           get<Tags::SingularField>(vars_on_mortar);
     198             :       const auto& deriv_singular_field_on_mortar =
     199             :           get<::Tags::deriv<Tags::SingularField, tmpl::size_t<Dim>,
     200             :                             Frame::Inertial>>(vars_on_mortar);
     201             :       const auto& alpha_on_mortar = get<Tags::Alpha>(background_on_mortar);
     202             :       FluxTensorType singular_field_flux_on_mortar{};
     203             :       GrSelfForce::fluxes(make_not_null(&singular_field_flux_on_mortar),
     204             :                           alpha_on_mortar, deriv_singular_field_on_mortar);
     205             :       // Assuming mortar normal is just (1, 0) or (0, 1). This is true for the
     206             :       // rectangular domains used in the self-force problem (AlignedLattice in
     207             :       // r, theta coordinates).
     208             :       tnsr::i<DataVector, Dim> mortar_normal{
     209             :           mortar_inertial_coords.begin()->size(), 0.};
     210             :       mortar_normal.get(mortar_id.direction().dimension()) =
     211             :           mortar_id.direction().sign();
     212             :       normal_dot_flux(
     213             :           make_not_null(&get<::Tags::NormalDotFlux<Tags::SingularField>>(
     214             :               singular_vars_on_mortar)),
     215             :           mortar_normal, singular_field_flux_on_mortar);
     216             :     }
     217             :   }
     218             : };
     219             : 
     220             : }  // namespace GrSelfForce::Actions

Generated by: LCOV version 1.14