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 hydrodynamic free outflow and no inflow boundary condition to
39 : * GRMHD primitive variables.
40 : *
41 : * All primitive variables at the boundary are copied into ghost zone except :
42 : *
43 : * - If \f$n_iv^i \geq 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 normal component is zero at the interface i.e.
47 : * \f$v_\text{ghost}^i = v^i - (n_jv^j)n^i\f$.
48 : *
49 : * - However, regardless of whether the normal component of the spatial
50 : * velocity $n_iv^i$ is pointing outward or inward, the lorentz factor \f$W\f$
51 : * is copied into ghost zone without any modification.
52 : *
53 : * \note In principle we need to recompute the Lorentz factor
54 : * \f$W_\text{ghost}\f$ using $v_\text{ghost}^i$. However, the case in which
55 : * skipping that procedure becomes problematic is only when the fluid has
56 : * relativistic incoming normal speed on the external boundary, which already
57 : * implies the failure of adopting outflow type boundary conditions.
58 : *
59 : * - Divergence cleaning scalar field \f$\Phi\f$ is set to zero in ghost zone.
60 : *
61 : */
62 1 : class HydroFreeOutflow final : public BoundaryCondition {
63 : private:
64 0 : using RestMassDensity = hydro::Tags::RestMassDensity<DataVector>;
65 0 : using ElectronFraction = hydro::Tags::ElectronFraction<DataVector>;
66 0 : using Temperature = hydro::Tags::Temperature<DataVector>;
67 0 : using Pressure = hydro::Tags::Pressure<DataVector>;
68 0 : using LorentzFactorTimesSpatialVelocity =
69 : hydro::Tags::LorentzFactorTimesSpatialVelocity<DataVector, 3>;
70 0 : using MagneticField = hydro::Tags::MagneticField<DataVector, 3>;
71 0 : using DivergenceCleaningField =
72 : hydro::Tags::DivergenceCleaningField<DataVector>;
73 0 : using SpecificInternalEnergy =
74 : hydro::Tags::SpecificInternalEnergy<DataVector>;
75 0 : using SpatialVelocity = hydro::Tags::SpatialVelocity<DataVector, 3>;
76 0 : using LorentzFactor = hydro::Tags::LorentzFactor<DataVector>;
77 0 : using SqrtDetSpatialMetric = gr::Tags::SqrtDetSpatialMetric<DataVector>;
78 0 : using SpatialMetric = gr::Tags::SpatialMetric<DataVector, 3>;
79 0 : using InvSpatialMetric = gr::Tags::InverseSpatialMetric<DataVector, 3>;
80 0 : using Lapse = gr::Tags::Lapse<DataVector>;
81 0 : using Shift = gr::Tags::Shift<DataVector, 3>;
82 :
83 0 : using prim_tags_for_reconstruction =
84 : tmpl::list<RestMassDensity, ElectronFraction, Temperature,
85 : LorentzFactorTimesSpatialVelocity, MagneticField,
86 : DivergenceCleaningField>;
87 :
88 : public:
89 0 : using options = tmpl::list<>;
90 0 : static constexpr Options::String help{
91 : "Free outflow & no inflow boundary condition on GRMHD primitive "
92 : "variables"};
93 :
94 0 : HydroFreeOutflow() = default;
95 0 : HydroFreeOutflow(HydroFreeOutflow&&) = default;
96 0 : HydroFreeOutflow& operator=(HydroFreeOutflow&&) = default;
97 0 : HydroFreeOutflow(const HydroFreeOutflow&) = default;
98 0 : HydroFreeOutflow& operator=(const HydroFreeOutflow&) = default;
99 0 : ~HydroFreeOutflow() override = default;
100 :
101 0 : explicit HydroFreeOutflow(CkMigrateMessage* msg);
102 :
103 0 : WRAPPED_PUPable_decl_base_template(
104 : domain::BoundaryConditions::BoundaryCondition, HydroFreeOutflow);
105 :
106 0 : auto get_clone() const -> std::unique_ptr<
107 : domain::BoundaryConditions::BoundaryCondition> override;
108 :
109 0 : static constexpr evolution::BoundaryConditions::Type bc_type =
110 : evolution::BoundaryConditions::Type::Ghost;
111 :
112 0 : void pup(PUP::er& p) override;
113 :
114 0 : using dg_interior_evolved_variables_tags = tmpl::list<>;
115 0 : using dg_interior_primitive_variables_tags =
116 : tmpl::list<hydro::Tags::RestMassDensity<DataVector>,
117 : hydro::Tags::ElectronFraction<DataVector>,
118 : hydro::Tags::SpecificInternalEnergy<DataVector>,
119 : hydro::Tags::SpatialVelocity<DataVector, 3>,
120 : hydro::Tags::MagneticField<DataVector, 3>,
121 : hydro::Tags::LorentzFactor<DataVector>,
122 : hydro::Tags::Pressure<DataVector>,
123 : hydro::Tags::Temperature<DataVector>>;
124 0 : using dg_interior_temporary_tags = tmpl::list<Shift, Lapse, InvSpatialMetric>;
125 0 : using dg_gridless_tags = tmpl::list<>;
126 :
127 0 : static std::optional<std::string> dg_ghost(
128 : gsl::not_null<Scalar<DataVector>*> tilde_d,
129 : gsl::not_null<Scalar<DataVector>*> tilde_ye,
130 : gsl::not_null<Scalar<DataVector>*> tilde_tau,
131 : gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*> tilde_s,
132 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_b,
133 : gsl::not_null<Scalar<DataVector>*> tilde_phi,
134 :
135 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_d_flux,
136 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_ye_flux,
137 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_tau_flux,
138 : gsl::not_null<tnsr::Ij<DataVector, 3, Frame::Inertial>*> tilde_s_flux,
139 : gsl::not_null<tnsr::IJ<DataVector, 3, Frame::Inertial>*> tilde_b_flux,
140 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_phi_flux,
141 :
142 : gsl::not_null<Scalar<DataVector>*> lapse,
143 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
144 : gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*>
145 : spatial_velocity_one_form,
146 : gsl::not_null<Scalar<DataVector>*> rest_mass_density,
147 : gsl::not_null<Scalar<DataVector>*> electron_fraction,
148 : gsl::not_null<Scalar<DataVector>*> temperature,
149 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> spatial_velocity,
150 : gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*>
151 : inv_spatial_metric,
152 :
153 : const std::optional<tnsr::I<DataVector, 3, Frame::Inertial>>&
154 : /*face_mesh_velocity*/,
155 : const tnsr::i<DataVector, 3, Frame::Inertial>&
156 : outward_directed_normal_covector,
157 : const tnsr::I<DataVector, 3, Frame::Inertial>&
158 : outward_directed_normal_vector,
159 :
160 : const Scalar<DataVector>& interior_rest_mass_density,
161 : const Scalar<DataVector>& interior_electron_fraction,
162 : const Scalar<DataVector>& interior_specific_internal_energy,
163 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity,
164 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field,
165 : const Scalar<DataVector>& interior_lorentz_factor,
166 : const Scalar<DataVector>& interior_pressure,
167 : const Scalar<DataVector>& interior_temperature,
168 :
169 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift,
170 : const Scalar<DataVector>& interior_lapse,
171 : const tnsr::II<DataVector, 3, Frame::Inertial>&
172 : interior_inv_spatial_metric);
173 :
174 0 : using fd_interior_evolved_variables_tags = tmpl::list<>;
175 0 : using fd_interior_temporary_tags =
176 : tmpl::list<evolution::dg::subcell::Tags::Mesh<3>, Shift, Lapse,
177 : SpatialMetric>;
178 0 : using fd_interior_primitive_variables_tags =
179 : tmpl::list<RestMassDensity, ElectronFraction, Temperature,
180 : hydro::Tags::Pressure<DataVector>,
181 : hydro::Tags::SpecificInternalEnergy<DataVector>,
182 : hydro::Tags::LorentzFactor<DataVector>,
183 : hydro::Tags::SpatialVelocity<DataVector, 3>, MagneticField>;
184 :
185 0 : using fd_gridless_tags = tmpl::list<fd::Tags::Reconstructor>;
186 :
187 0 : static void fd_ghost(
188 : gsl::not_null<Scalar<DataVector>*> rest_mass_density,
189 : gsl::not_null<Scalar<DataVector>*> electron_fraction,
190 : gsl::not_null<Scalar<DataVector>*> temperature,
191 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
192 : lorentz_factor_times_spatial_velocity,
193 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> magnetic_field,
194 : gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field,
195 :
196 : gsl::not_null<std::optional<Variables<db::wrap_tags_in<
197 : ::Tags::Flux,
198 : typename grmhd::ValenciaDivClean::System::flux_variables,
199 : tmpl::size_t<3>, Frame::Inertial>>>*>
200 : cell_centered_ghost_fluxes,
201 :
202 : const Direction<3>& direction,
203 :
204 : // interior temporary tags
205 : const Mesh<3>& subcell_mesh,
206 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift,
207 : const Scalar<DataVector>& interior_lapse,
208 : const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric,
209 :
210 : // interior prim vars tags
211 : const Scalar<DataVector>& interior_rest_mass_density,
212 : const Scalar<DataVector>& interior_electron_fraction,
213 : const Scalar<DataVector>& interior_temperature,
214 : const Scalar<DataVector>& interior_pressure,
215 : const Scalar<DataVector>& interior_specific_internal_energy,
216 : const Scalar<DataVector>& interior_lorentz_factor,
217 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity,
218 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field,
219 :
220 : // gridless tags
221 : const fd::Reconstructor& reconstructor);
222 :
223 : // have an impl to make sharing code with GH+GRMHD easy
224 0 : static void fd_ghost_impl(
225 : gsl::not_null<Scalar<DataVector>*> rest_mass_density,
226 : gsl::not_null<Scalar<DataVector>*> electron_fraction,
227 : gsl::not_null<Scalar<DataVector>*> temperature,
228 : gsl::not_null<Scalar<DataVector>*> pressure,
229 : gsl::not_null<Scalar<DataVector>*> specific_internal_energy,
230 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
231 : lorentz_factor_times_spatial_velocity,
232 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> spatial_velocity,
233 : gsl::not_null<Scalar<DataVector>*> lorentz_factor,
234 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> magnetic_field,
235 : gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field,
236 : gsl::not_null<tnsr::ii<DataVector, 3, Frame::Inertial>*> spatial_metric,
237 : gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*>
238 : inv_spatial_metric,
239 : gsl::not_null<Scalar<DataVector>*> sqrt_det_spatial_metric,
240 : gsl::not_null<Scalar<DataVector>*> lapse,
241 : gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
242 :
243 : const Direction<3>& direction,
244 :
245 : // fd_interior_temporary_tags
246 : const Mesh<3>& subcell_mesh,
247 :
248 : // fd_interior_primitive_variables_tags
249 : const Scalar<DataVector>& interior_rest_mass_density,
250 : const Scalar<DataVector>& interior_electron_fraction,
251 : const Scalar<DataVector>& interior_temperature,
252 : const Scalar<DataVector>& interior_pressure,
253 : const Scalar<DataVector>& interior_specific_internal_energy,
254 : const Scalar<DataVector>& interior_lorentz_factor,
255 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity,
256 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field,
257 : const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric,
258 : const Scalar<DataVector>& interior_lapse,
259 : const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift,
260 :
261 : size_t ghost_zone_size, bool need_tags_for_fluxes);
262 : };
263 : } // namespace grmhd::ValenciaDivClean::BoundaryConditions
|