Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <optional> 9 : 10 : #include "DataStructures/Tensor/TypeAliases.hpp" 11 : 12 : /// \cond 13 : namespace PUP { 14 : class er; 15 : } // namespace PUP 16 : /// \endcond 17 : 18 : namespace domain::CoordinateMaps { 19 : 20 : /*! 21 : * \ingroup CoordinateMapsGroup 22 : * 23 : * \brief Maps a cylindrical shell block to a region bounded by an inner 24 : * right cylinder and an outer spherical surface. 25 : * 26 : * \image html CylindricalSphericalShell.png "The shaded region is the image." 27 : * 28 : * \details The logical coordinates are: 29 : * - radial \f$\xi \in [-1,1]\f$: interpolates between the inner right 30 : * cylinder and the outer sphere. 31 : * - angular \f$\eta \in (-\pi, \pi]\f$: azimuthal angle \f$\phi\f$ (S1 32 : * periodic direction). The inverse map returns 33 : * \f$\eta = \mathrm{atan2}(z, y)\f$, which lies in \f$(-\pi, \pi]\f$. 34 : * - axial \f$\zeta \in [-1,1]\f$: blends between the lower and upper ends 35 : * of the shell. 36 : * 37 : * The physical coordinates \f$(x, y, z)\f$ are computed as follows. 38 : * Let \f$\alpha = (\xi+1)/2\f$ and \f$\beta = (\zeta+1)/2\f$. Define 39 : * 40 : * \f{align}{ 41 : * x_\mathrm{inner}(\beta) &= x^\mathrm{inner}_\mathrm{lower} 42 : * + \beta\,(x^\mathrm{inner}_\mathrm{upper} 43 : * - x^\mathrm{inner}_\mathrm{lower}), \\ 44 : * x_\mathrm{outer}(\beta) &= x^\mathrm{outer}_\mathrm{lower} 45 : * + \beta\,(x^\mathrm{outer}_\mathrm{upper} 46 : * - x^\mathrm{outer}_\mathrm{lower}), \\ 47 : * r_\mathrm{outer}(\beta) &= \sqrt{r_\mathrm{sphere}^2 48 : * - x_\mathrm{outer}(\beta)^2}. 49 : * \f} 50 : * 51 : * Then 52 : * 53 : * \f{align}{ 54 : * x &= (1-\alpha)\,x_\mathrm{inner}(\beta) 55 : * + \alpha\,x_\mathrm{outer}(\beta), \\ 56 : * r &= (1-\alpha)\,r_\mathrm{inner} 57 : * + \alpha\,r_\mathrm{outer}(\beta), \\ 58 : * y &= r\cos\eta, \quad z = r\sin\eta. 59 : * \f} 60 : * 61 : * The six block faces have the following geometry: 62 : * - \f$\xi = -1\f$ (\f$\alpha=0\f$): the inner right cylinder at 63 : * \f$r = r_\mathrm{inner}\f$, extending in \f$x\f$ from 64 : * \f$x^\mathrm{inner}_\mathrm{lower}\f$ to 65 : * \f$x^\mathrm{inner}_\mathrm{upper}\f$. 66 : * - \f$\xi = +1\f$ (\f$\alpha=1\f$): a portion of the sphere 67 : * \f$r^2 + x^2 = r_\mathrm{sphere}^2\f$. 68 : * - \f$\zeta = \pm 1\f$: generically curved surfaces in Cartesian 69 : * coordinates (ruled surfaces that blend linearly in \f$(x,r)\f$ between 70 : * the inner cylinder edge and the outer sphere edge at the corresponding 71 : * axial end). 72 : * - \f$\eta\f$ direction: periodic (connected by the cylindrical_shell 73 : * topology). 74 : * 75 : * ### Requirements 76 : * - \f$x^\mathrm{inner}_\mathrm{lower} < x^\mathrm{inner}_\mathrm{upper}\f$ 77 : * - \f$x^\mathrm{outer}_\mathrm{lower} < x^\mathrm{outer}_\mathrm{upper}\f$ 78 : * - \f$r_\mathrm{inner} > 0\f$ 79 : * - \f$|x^\mathrm{outer}_\mathrm{lower}|, 80 : * |x^\mathrm{outer}_\mathrm{upper}| < r_\mathrm{sphere}\f$ 81 : * - \f$r_\mathrm{inner} < r_\mathrm{outer}(\beta)\f$ for all 82 : * \f$\beta \in [0,1]\f$ (equivalently, 83 : * \f$r_\mathrm{inner} < \min(r_\mathrm{outer}(0), r_\mathrm{outer}(1))\f$). 84 : */ 85 1 : class CylindricalSphericalShell { 86 : public: 87 0 : static constexpr size_t dim = 3; 88 : 89 : /*! 90 : * \brief Construct the map. 91 : * 92 : * \param x_inner_lower Axial coordinate \f$x\f$ at the lower end of the 93 : * inner cylinder (\f$\xi=-1, \zeta=-1\f$). 94 : * \param x_inner_upper Axial coordinate \f$x\f$ at the upper end of the 95 : * inner cylinder (\f$\xi=-1, \zeta=+1\f$). 96 : * \param x_outer_lower Axial coordinate \f$x\f$ at the lower end of the 97 : * outer spherical face (\f$\xi=+1, \zeta=-1\f$). 98 : * \param x_outer_upper Axial coordinate \f$x\f$ at the upper end of the 99 : * outer spherical face (\f$\xi=+1, \zeta=+1\f$). 100 : * \param r_inner Radius of the inner right cylinder. 101 : * \param r_sphere Radius of the outer bounding sphere (centered at the 102 : * origin). 103 : */ 104 1 : CylindricalSphericalShell(double x_inner_lower, double x_inner_upper, 105 : double x_outer_lower, double x_outer_upper, 106 : double r_inner, double r_sphere); 107 : 108 0 : CylindricalSphericalShell() = default; 109 0 : ~CylindricalSphericalShell() = default; 110 0 : CylindricalSphericalShell(CylindricalSphericalShell&&) = default; 111 0 : CylindricalSphericalShell(const CylindricalSphericalShell&) = default; 112 0 : CylindricalSphericalShell& operator=(const CylindricalSphericalShell&) = 113 : default; 114 0 : CylindricalSphericalShell& operator=(CylindricalSphericalShell&&) = default; 115 : 116 : template <typename T> 117 0 : std::array<T, 3> operator()(const std::array<T, 3>& source_coords) const; 118 : 119 0 : std::optional<std::array<double, 3>> inverse( 120 : const std::array<double, 3>& target_coords) const; 121 : 122 : template <typename T> 123 0 : tnsr::Ij<T, 3, Frame::NoFrame> jacobian( 124 : const std::array<T, 3>& source_coords) const; 125 : 126 : template <typename T> 127 0 : tnsr::Ij<T, 3, Frame::NoFrame> inv_jacobian( 128 : const std::array<T, 3>& source_coords) const; 129 : 130 : // NOLINTNEXTLINE(google-runtime-references) 131 0 : void pup(PUP::er& p); 132 : 133 0 : static bool is_identity() { return false; } 134 : 135 0 : static constexpr bool supports_hessian{false}; 136 : 137 : private: 138 0 : friend bool operator==(const CylindricalSphericalShell& lhs, 139 : const CylindricalSphericalShell& rhs); 140 0 : double x_inner_lower_{}; 141 0 : double x_inner_upper_{}; 142 0 : double x_outer_lower_{}; 143 0 : double x_outer_upper_{}; 144 0 : double r_inner_{}; 145 0 : double r_sphere_{}; 146 : }; 147 : 148 0 : bool operator!=(const CylindricalSphericalShell& lhs, 149 : const CylindricalSphericalShell& rhs); 150 : 151 : } // namespace domain::CoordinateMaps