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 <memory> 9 : #include <string> 10 : #include <unordered_map> 11 : #include <vector> 12 : 13 : #include "Domain/Creators/DomainCreator.hpp" 14 : #include "Domain/Creators/TimeDependence/TimeDependence.hpp" 15 : #include "Options/Context.hpp" 16 : #include "Options/String.hpp" 17 : #include "Utilities/TMPL.hpp" 18 : 19 : /// \cond 20 : template <size_t VolumeDim> 21 : class Domain; 22 : namespace domain { 23 : namespace CoordinateMaps { 24 : class Affine; 25 : template <typename Map1, typename Map2> 26 : class ProductOf2Maps; 27 : template <typename Map1, typename Map2, typename Map3> 28 : class ProductOf3Maps; 29 : } // namespace CoordinateMaps 30 : 31 : template <typename SourceFrame, typename TargetFrame, typename... Maps> 32 : class CoordinateMap; 33 : } // namespace domain 34 : /// \endcond 35 : 36 : namespace domain::creators { 37 : 38 : /// \brief Create a domain consisting of a single Block with the topology of a 39 : /// hypertorus in `Dim` dimensions. 40 : /// 41 : /// \details The domain will have topology S1 (i.e. is periodic) in each 42 : /// dimension. Therefore the domain has no external boundaries. The domain 43 : /// cannot be refined, and is intended for using DG with a Fourier basis in 44 : /// each dimension. If you want to h-refine a periodic domain, use one of 45 : /// the rectilinear domain creators (i.e. Interval, Rectangle, or Brick). 46 : template <size_t Dim> 47 1 : class Hypertorus : public DomainCreator<Dim> { 48 : private: 49 : static_assert(Dim == 1 or Dim == 2 or Dim == 3, 50 : "Hypertorus domain is only implemented in 1, 2, or 3 " 51 : "dimensions."); 52 : 53 0 : using Affine = CoordinateMaps::Affine; 54 0 : using Affine2D = CoordinateMaps::ProductOf2Maps<Affine, Affine>; 55 0 : using Affine3D = CoordinateMaps::ProductOf3Maps<Affine, Affine, Affine>; 56 : 57 : public: 58 0 : using maps_list = tmpl::list<domain::CoordinateMap< 59 : Frame::BlockLogical, Frame::Inertial, 60 : tmpl::conditional_t<Dim == 1, Affine, 61 : tmpl::conditional_t<Dim == 2, Affine2D, Affine3D>>>>; 62 : 63 0 : static std::string name() { 64 : if constexpr (Dim == 1) { 65 : return "PeriodicInterval"; 66 : } else if constexpr (Dim == 2) { 67 : return "PeriodicRectangle"; 68 : } else { 69 : return "PeriodicBrick"; 70 : } 71 : } 72 : 73 : /// Lower coordinate bound in each dimension 74 1 : struct LowerBound { 75 0 : using type = std::array<double, Dim>; 76 0 : static constexpr Options::String help = {"Lower bound in each dimension."}; 77 : }; 78 : 79 : /// Upper coordinate bound in each dimension 80 1 : struct UpperBound { 81 0 : using type = std::array<double, Dim>; 82 0 : static constexpr Options::String help = {"Upper bound in each dimension."}; 83 : }; 84 : 85 : /// \brief Initial maximum mode number \f$M\f$ retained in the Fourier basis 86 : /// in each dimension 87 : /// 88 : /// \details The number of grid points will be \f$2M + 1\f$. 89 1 : struct InitialMaximumModeNumber { 90 0 : using type = std::array<size_t, Dim>; 91 0 : static constexpr Options::String help = { 92 : "Initial value of M, the maximum retained mode in the Fourier basis."}; 93 : }; 94 : 95 : /// Time dependence for the domain. Specify `None` for no time dependent maps 96 1 : struct TimeDependence { 97 0 : using type = 98 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<Dim>>; 99 0 : static constexpr Options::String help = { 100 : "The time dependence of the moving mesh domain."}; 101 : }; 102 : 103 : template <typename Metavariables> 104 0 : using options = tmpl::list<LowerBound, UpperBound, InitialMaximumModeNumber, 105 : TimeDependence>; 106 : 107 0 : static constexpr Options::String help{"A periodic rectilinear domain."}; 108 : 109 0 : Hypertorus( 110 : const std::array<double, Dim>& lower_bounds, 111 : const std::array<double, Dim>& upper_bounds, 112 : const std::array<size_t, Dim>& initial_max_modes, 113 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<Dim>> 114 : time_dependence = nullptr, 115 : const Options::Context& context = {}); 116 : 117 0 : Hypertorus() = default; 118 0 : Hypertorus(const Hypertorus&) = delete; 119 0 : Hypertorus(Hypertorus&&) = default; 120 0 : Hypertorus& operator=(const Hypertorus&) = delete; 121 0 : Hypertorus& operator=(Hypertorus&&) = default; 122 0 : ~Hypertorus() override = default; 123 : 124 0 : Domain<Dim> create_domain() const override; 125 : 126 : std::vector<DirectionMap< 127 : Dim, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>> 128 1 : external_boundary_conditions() const override; 129 : 130 1 : std::vector<std::array<size_t, Dim>> initial_extents() const override; 131 : 132 1 : std::vector<std::array<size_t, Dim>> initial_refinement_levels() 133 : const override; 134 : 135 1 : auto functions_of_time(const std::unordered_map<std::string, double>& 136 : initial_expiration_times = {}) const 137 : -> std::unordered_map< 138 : std::string, 139 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override; 140 : 141 1 : std::vector<std::string> block_names() const override { return block_names_; } 142 : 143 : std::unordered_map<std::string, std::unordered_set<std::string>> 144 1 : block_groups() const override { 145 : return {{name(), {name()}}}; 146 : } 147 : 148 : private: 149 0 : std::array<double, Dim> lower_bounds_{}; 150 0 : std::array<double, Dim> upper_bounds_{}; 151 0 : std::array<size_t, Dim> initial_num_points_{}; 152 : std::unique_ptr<domain::creators::time_dependence::TimeDependence<Dim>> 153 0 : time_dependence_; 154 0 : inline static const std::vector<std::string> block_names_{name()}; 155 : }; 156 : 157 0 : using PeriodicInterval = Hypertorus<1>; 158 0 : using PeriodicRectangle = Hypertorus<2>; 159 0 : using PeriodicBrick = Hypertorus<3>; 160 : 161 : } // namespace domain::creators