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
|