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

Generated by: LCOV version 2.0-1