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 <pup.h> 8 : 9 : #include "DataStructures/CachedTempBuffer.hpp" 10 : #include "DataStructures/DataBox/Prefixes.hpp" 11 : #include "DataStructures/DataVector.hpp" 12 : #include "DataStructures/TaggedTuple.hpp" 13 : #include "DataStructures/Tensor/Tensor.hpp" 14 : #include "Elliptic/Systems/Poisson/Tags.hpp" 15 : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp" 16 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 17 : #include "Options/String.hpp" 18 : #include "PointwiseFunctions/InitialDataUtilities/AnalyticSolution.hpp" 19 : #include "Utilities/ContainerHelpers.hpp" 20 : #include "Utilities/Gsl.hpp" 21 : #include "Utilities/TMPL.hpp" 22 : 23 : namespace Poisson::Solutions { 24 : 25 : namespace detail { 26 : template <typename DataType, size_t Dim> 27 : struct MoustacheVariables { 28 : using Cache = CachedTempBuffer< 29 : Tags::Field<DataType>, 30 : ::Tags::deriv<Tags::Field<DataType>, tmpl::size_t<Dim>, Frame::Inertial>, 31 : ::Tags::Flux<Tags::Field<DataType>, tmpl::size_t<Dim>, Frame::Inertial>, 32 : ::Tags::FixedSource<Tags::Field<DataType>>>; 33 : 34 : const tnsr::I<DataType, Dim>& x; 35 : 36 : void operator()(gsl::not_null<Scalar<DataType>*> field, 37 : gsl::not_null<Cache*> cache, 38 : Tags::Field<DataType> /*meta*/) const; 39 : void operator()(gsl::not_null<tnsr::i<DataType, Dim>*> field_gradient, 40 : gsl::not_null<Cache*> cache, 41 : ::Tags::deriv<Tags::Field<DataType>, tmpl::size_t<Dim>, 42 : Frame::Inertial> /*meta*/) const; 43 : void operator()(gsl::not_null<tnsr::I<DataType, Dim>*> flux_for_field, 44 : gsl::not_null<Cache*> cache, 45 : ::Tags::Flux<Tags::Field<DataType>, tmpl::size_t<Dim>, 46 : Frame::Inertial> /*meta*/) const; 47 : void operator()(gsl::not_null<Scalar<DataType>*> fixed_source_for_field, 48 : gsl::not_null<Cache*> cache, 49 : ::Tags::FixedSource<Tags::Field<DataType>> /*meta*/) const; 50 : }; 51 : } // namespace detail 52 : 53 : /*! 54 : * \brief A solution to the Poisson equation with a discontinuous first 55 : * derivative. 56 : * 57 : * \details This implements the solution \f$u(x,y)=x\left(1-x\right) 58 : * y\left(1-y\right)\left(\left(x-\frac{1}{2}\right)^2+\left(y- 59 : * \frac{1}{2}\right)^2\right)^\frac{3}{2}\f$ to the Poisson equation 60 : * in two dimensions, and 61 : * \f$u(x)=x\left(1-x\right)\left|x-\frac{1}{2}\right|^3\f$ in one dimension. 62 : * Their boundary conditions vanish on the square \f$[0,1]^2\f$ or interval 63 : * \f$[0,1]\f$, respectively. 64 : * 65 : * The corresponding source \f$f=-\Delta u\f$ has a discontinuous first 66 : * derivative at \f$\frac{1}{2}\f$. This accomplishes two things: 67 : * 68 : * - It makes it useful to test the convergence behaviour of our elliptic DG 69 : * solver. 70 : * - It makes it look like a moustache (at least in 1D). 71 : * 72 : * This solution is taken from \cite Stamm2010. 73 : */ 74 : template <size_t Dim> 75 1 : class Moustache : public elliptic::analytic_data::AnalyticSolution { 76 : public: 77 0 : using options = tmpl::list<>; 78 0 : static constexpr Options::String help{ 79 : "A solution with a discontinuous first derivative of its source at 1/2 " 80 : "that also happens to look like a moustache. It vanishes at zero and one " 81 : "in each dimension"}; 82 : 83 0 : Moustache() = default; 84 0 : Moustache(const Moustache&) = default; 85 0 : Moustache& operator=(const Moustache&) = default; 86 0 : Moustache(Moustache&&) = default; 87 0 : Moustache& operator=(Moustache&&) = default; 88 0 : ~Moustache() override = default; 89 0 : std::unique_ptr<elliptic::analytic_data::AnalyticSolution> get_clone() 90 : const override { 91 : return std::make_unique<Moustache>(*this); 92 : } 93 : 94 : /// \cond 95 : explicit Moustache(CkMigrateMessage* m) 96 : : elliptic::analytic_data::AnalyticSolution(m) {} 97 : using PUP::able::register_constructor; 98 : WRAPPED_PUPable_decl_template(Moustache); // NOLINT 99 : /// \endcond 100 : 101 : template <typename DataType, typename... RequestedTags> 102 0 : tuples::TaggedTuple<RequestedTags...> variables( 103 : const tnsr::I<DataType, Dim>& x, 104 : tmpl::list<RequestedTags...> /*meta*/) const { 105 : using VarsComputer = detail::MoustacheVariables<DataType, Dim>; 106 : typename VarsComputer::Cache cache{get_size(*x.begin())}; 107 : const VarsComputer computer{x}; 108 : return {cache.get_var(computer, RequestedTags{})...}; 109 : } 110 : 111 : template <typename... RequestedTags> 112 0 : tuples::TaggedTuple<RequestedTags...> variables( 113 : const tnsr::I<DataVector, Dim>& x, const Mesh<Dim>& /*mesh*/, 114 : const InverseJacobian<DataVector, Dim, Frame::ElementLogical, 115 : Frame::Inertial>& /*inv_jacobian*/, 116 : tmpl::list<RequestedTags...> meta) const { 117 : return variables(x, meta); 118 : } 119 : }; 120 : 121 : /// \cond 122 : template <size_t Dim> 123 : PUP::able::PUP_ID Moustache<Dim>::my_PUP_ID = 0; // NOLINT 124 : /// \endcond 125 : 126 : template <size_t Dim> 127 0 : constexpr bool operator==(const Moustache<Dim>& /*lhs*/, 128 : const Moustache<Dim>& /*rhs*/) { 129 : return true; 130 : } 131 : 132 : template <size_t Dim> 133 0 : constexpr bool operator!=(const Moustache<Dim>& lhs, 134 : const Moustache<Dim>& rhs) { 135 : return not(lhs == rhs); 136 : } 137 : 138 : } // namespace Poisson::Solutions