Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <memory>
7 : #include <optional>
8 : #include <pup.h>
9 : #include <string>
10 :
11 : #include "DataStructures/DataBox/PrefixHelpers.hpp"
12 : #include "DataStructures/DataBox/Prefixes.hpp"
13 : #include "DataStructures/Tensor/TypeAliases.hpp"
14 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
15 : #include "Evolution/BoundaryConditions/Type.hpp"
16 : #include "Evolution/DgSubcell/Tags/Mesh.hpp"
17 : #include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/BoundaryCondition.hpp"
18 : #include "Evolution/Systems/GrMhd/ValenciaDivClean/FiniteDifference/Tag.hpp"
19 : #include "Evolution/Systems/GrMhd/ValenciaDivClean/System.hpp"
20 : #include "Options/String.hpp"
21 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
22 : #include "PointwiseFunctions/Hydro/Tags.hpp"
23 : #include "PointwiseFunctions/Hydro/Temperature.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : /// \cond
27 : class DataVector;
28 : template <size_t VolumeDim>
29 : class Direction;
30 : namespace gsl {
31 : template <typename T>
32 : class not_null;
33 : } // namespace gsl
34 : /// \endcond
35 :
36 : namespace grmhd::ValenciaDivClean::BoundaryConditions {
37 : /*!
38 : * \brief Apply "soft" reflective boundary condition as described in
39 : * \cite Shiokawa2011ih.
40 : *
41 : * All primitive variables at the boundary are copied into ghost zone except :
42 : *
43 : * - If \f$n_iv^i \leq 0\f$ where \f$v^i\f$ is spatial velocity and \f$n_i\f$
44 : * is outward directed normal covector, copy the values of \f$v^i\f$ at the
45 : * boundary to ghost zone. If \f$n_iv^i>0\f$, spatial velocity in the ghost zone
46 : * is modified such that the sign of normal component is inverted at the
47 : * interface i.e. \f$v_\text{ghost}^i = v^i - 2*(n_jv^j)n^i\f$.
48 : *
49 : * - If \f$n_iB^i \leq 0\f$ where \f$B^i\f$ is magnetic field and \f$n_i\f$
50 : * is outward directed normal covector, copy the values of \f$B^i\f$ at the
51 : * boundary to ghost zone. If \f$n_iB^i>0\f$, magnetic field in the ghost zone
52 : * is modified such that the sign of normal component is inverted at the
53 : * interface i.e. \f$B_\text{ghost}^i = B^i - 2*(n_jB^j)n^i\f$.
54 : *
55 : * - If reflect_both is true, then spatial velocity and magnetic field are
56 : * are inverted regardless of whether the normal component is pointing outward
57 : * or inward.
58 : *
59 : * - However, regardless of whether the normal component of the spatial
60 : * velocity $n_iv^i$ is pointing outward or inward, the lorentz factor \f$W\f$
61 : * is copied into ghost zone without any modification.
62 : *
63 : * - Divergence cleaning scalar field \f$\Phi\f$ is set to zero in ghost zone.
64 : *
65 : */
66 1 : class Reflective final : public BoundaryCondition {
67 : private:
68 0 : bool reflect_both_{false};
69 :
70 0 : using RestMassDensity = hydro::Tags::RestMassDensity<DataVector>;
71 0 : using ElectronFraction = hydro::Tags::ElectronFraction<DataVector>;
72 0 : using Temperature = hydro::Tags::Temperature<DataVector>;
73 0 : using Pressure = hydro::Tags::Pressure<DataVector>;
74 0 : using LorentzFactorTimesSpatialVelocity =
75 : hydro::Tags::LorentzFactorTimesSpatialVelocity<DataVector, 3>;
76 0 : using MagneticField = hydro::Tags::MagneticField<DataVector, 3>;
77 0 : using DivergenceCleaningField =
78 : hydro::Tags::DivergenceCleaningField<DataVector>;
79 0 : using SpecificInternalEnergy =
80 : hydro::Tags::SpecificInternalEnergy<DataVector>;
81 0 : using SpatialVelocity = hydro::Tags::SpatialVelocity<DataVector, 3>;
82 0 : using LorentzFactor = hydro::Tags::LorentzFactor<DataVector>;
83 0 : using SqrtDetSpatialMetric = gr::Tags::SqrtDetSpatialMetric<DataVector>;
84 0 : using SpatialMetric = gr::Tags::SpatialMetric<DataVector, 3>;
85 0 : using InvSpatialMetric = gr::Tags::InverseSpatialMetric<DataVector, 3>;
86 0 : using Lapse = gr::Tags::Lapse<DataVector>;
87 0 : using Shift = gr::Tags::Shift<DataVector, 3>;
88 :
89 0 : using prim_tags_for_reconstruction =
90 : tmpl::list<RestMassDensity, ElectronFraction, Temperature,
91 : LorentzFactorTimesSpatialVelocity, MagneticField,
92 : DivergenceCleaningField>;
93 :
94 : template <typename T>
95 0 : using Flux = ::Tags::Flux<T, tmpl::size_t<3>, Frame::Inertial>;
96 :
97 : public:
98 0 : struct ReflectBoth {
99 0 : using type = bool;
100 0 : static constexpr Options::String help = {
101 : "Reflect both outgoing and incoming normal component of "
102 : "spatial velocity and magnetic field."};
103 : };
104 0 : using options = tmpl::list<ReflectBoth>;
105 0 : static constexpr Options::String help{
106 : "Reflective boundary conditions, inverting the sign "
107 : "of outgoing normal component of spatial velocity "
108 : "and magnetic field."};
109 :
110 0 : Reflective() = default;
111 0 : Reflective(Reflective&&) = default;
112 0 : Reflective& operator=(Reflective&&) = default;
113 0 : Reflective(const Reflective&) = default;
114 0 : Reflective& operator=(const Reflective&) = default;
115 0 : ~Reflective() override = default;
116 :
117 0 : explicit Reflective(bool reflect_both);
118 :
119 0 : explicit Reflective(CkMigrateMessage* msg);
120 :
121 0 : WRAPPED_PUPable_decl_base_template(
122 : domain::BoundaryConditions::BoundaryCondition, Reflective);
123 :
124 0 : auto get_clone() const -> std::unique_ptr<
125 : domain::BoundaryConditions::BoundaryCondition> override;
126 :
127 0 : static constexpr evolution::BoundaryConditions::Type bc_type =
128 : evolution::BoundaryConditions::Type::Ghost;
129 :
130 0 : void pup(PUP::er& p) override;
131 :
132 0 : using dg_interior_evolved_variables_tags = tmpl::list<>;
133 0 : using dg_interior_primitive_variables_tags =
134 : tmpl::list<hydro::Tags::RestMassDensity<DataVector>,
135 : hydro::Tags::ElectronFraction<DataVector>,
136 : hydro::Tags::SpecificInternalEnergy<DataVector>,
137 : hydro::Tags::SpatialVelocity<DataVector, 3>,
138 : hydro::Tags::MagneticField<DataVector, 3>,
139 : hydro::Tags::LorentzFactor<DataVector>,
140 : hydro::Tags::Pressure<DataVector>,
141 : hydro::Tags::Temperature<DataVector>>;
142 0 : using dg_interior_temporary_tags = tmpl::list<Shift, Lapse, InvSpatialMetric>;
143 0 : using dg_gridless_tags = tmpl::list<>;
144 :
145 0 : std::optional<std::string> dg_ghost(
146 : gsl::not_null<Scalar<DataVector>*> tilde_d,
147 : gsl::not_null<Scalar<DataVector>*> tilde_ye,
148 : gsl::not_null<Scalar<DataVector>*> tilde_tau,
149 : gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*> tilde_s,
150 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_b,
151 : gsl::not_null<Scalar<DataVector>*> tilde_phi,
152 :
153 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_d_flux,
154 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_ye_flux,
155 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_tau_flux,
156 : gsl::not_null<tnsr::Ij<DataVector, 3, Frame::Inertial>*> tilde_s_flux,
157 : gsl::not_null<tnsr::IJ<DataVector, 3, Frame::Inertial>*> tilde_b_flux,
158 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_phi_flux,
159 :
160 : gsl::not_null<Scalar<DataVector>*> lapse,
161 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
162 : gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*>
163 : spatial_velocity_one_form,
164 : gsl::not_null<Scalar<DataVector>*> rest_mass_density,
165 : gsl::not_null<Scalar<DataVector>*> electron_fraction,
166 : gsl::not_null<Scalar<DataVector>*> temperature,
167 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> spatial_velocity,
168 : gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*>
169 : inv_spatial_metric,
170 :
171 : const std::optional<tnsr::I<DataVector, 3, Frame::Inertial>>&
172 : /*face_mesh_velocity*/,
173 : const tnsr::i<DataVector, 3, Frame::Inertial>&
174 : outward_directed_normal_covector,
175 : const tnsr::I<DataVector, 3, Frame::Inertial>&
176 : outward_directed_normal_vector,
177 :
178 : const Scalar<DataVector>& interior_rest_mass_density,
179 : const Scalar<DataVector>& interior_electron_fraction,
180 : const Scalar<DataVector>& interior_specific_internal_energy,
181 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity,
182 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field,
183 : const Scalar<DataVector>& interior_lorentz_factor,
184 : const Scalar<DataVector>& interior_pressure,
185 : const Scalar<DataVector>& interior_temperature,
186 :
187 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift,
188 : const Scalar<DataVector>& interior_lapse,
189 : const tnsr::II<DataVector, 3, Frame::Inertial>&
190 : interior_inv_spatial_metric) const;
191 :
192 0 : using fd_interior_evolved_variables_tags = tmpl::list<>;
193 0 : using fd_interior_temporary_tags =
194 : tmpl::list<evolution::dg::subcell::Tags::Mesh<3>, Shift, Lapse,
195 : SpatialMetric>;
196 0 : using fd_interior_primitive_variables_tags =
197 : tmpl::list<RestMassDensity, ElectronFraction, Temperature,
198 : hydro::Tags::Pressure<DataVector>,
199 : hydro::Tags::SpecificInternalEnergy<DataVector>,
200 : hydro::Tags::LorentzFactor<DataVector>,
201 : hydro::Tags::SpatialVelocity<DataVector, 3>, MagneticField>;
202 :
203 0 : using fd_gridless_tags = tmpl::list<fd::Tags::Reconstructor>;
204 :
205 0 : void fd_ghost(
206 : gsl::not_null<Scalar<DataVector>*> rest_mass_density,
207 : gsl::not_null<Scalar<DataVector>*> electron_fraction,
208 : gsl::not_null<Scalar<DataVector>*> temperature,
209 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
210 : lorentz_factor_times_spatial_velocity,
211 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> magnetic_field,
212 : gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field,
213 :
214 : gsl::not_null<std::optional<Variables<db::wrap_tags_in<
215 : Flux, typename grmhd::ValenciaDivClean::System::flux_variables>>>*>
216 : cell_centered_ghost_fluxes,
217 :
218 : const Direction<3>& direction,
219 :
220 : // interior temporary tags
221 : const Mesh<3>& subcell_mesh,
222 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift,
223 : const Scalar<DataVector>& interior_lapse,
224 : const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric,
225 :
226 : // interior prim vars tags
227 : const Scalar<DataVector>& interior_rest_mass_density,
228 : const Scalar<DataVector>& interior_electron_fraction,
229 : const Scalar<DataVector>& interior_temperature,
230 : const Scalar<DataVector>& interior_pressure,
231 : const Scalar<DataVector>& interior_specific_internal_energy,
232 : const Scalar<DataVector>& interior_lorentz_factor,
233 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity,
234 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field,
235 :
236 : // gridless tags
237 : const fd::Reconstructor& reconstructor) const;
238 :
239 : // have an impl to make sharing code with GH+GRMHD easy
240 0 : void fd_ghost_impl(
241 : gsl::not_null<Scalar<DataVector>*> rest_mass_density,
242 : gsl::not_null<Scalar<DataVector>*> electron_fraction,
243 : gsl::not_null<Scalar<DataVector>*> temperature,
244 : gsl::not_null<Scalar<DataVector>*> pressure,
245 : gsl::not_null<Scalar<DataVector>*> specific_internal_energy,
246 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
247 : lorentz_factor_times_spatial_velocity,
248 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> spatial_velocity,
249 : gsl::not_null<Scalar<DataVector>*> lorentz_factor,
250 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> magnetic_field,
251 : gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field,
252 : gsl::not_null<tnsr::ii<DataVector, 3, Frame::Inertial>*> spatial_metric,
253 : gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*>
254 : inv_spatial_metric,
255 : gsl::not_null<Scalar<DataVector>*> sqrt_det_spatial_metric,
256 : gsl::not_null<Scalar<DataVector>*> lapse,
257 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
258 :
259 : const Direction<3>& direction,
260 :
261 : // fd_interior_temporary_tags
262 : const Mesh<3>& subcell_mesh,
263 :
264 : // fd_interior_primitive_variables_tags
265 : const Scalar<DataVector>& interior_rest_mass_density,
266 : const Scalar<DataVector>& interior_electron_fraction,
267 : const Scalar<DataVector>& interior_temperature,
268 : const Scalar<DataVector>& interior_pressure,
269 : const Scalar<DataVector>& interior_specific_internal_energy,
270 : const Scalar<DataVector>& interior_lorentz_factor,
271 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity,
272 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field,
273 : const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric,
274 : const Scalar<DataVector>& interior_lapse,
275 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift,
276 :
277 : size_t ghost_zone_size, bool need_tags_for_fluxes) const;
278 : };
279 : } // namespace grmhd::ValenciaDivClean::BoundaryConditions
|