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
|