CDT++ 1.0.0-rc1
Causal Dynamical Triangulations in C++
Loading...
Searching...
No Matches
Runtime_config.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 Causal Dynamical Triangulations in C++ using CGAL
3
4 Copyright © 2026 Adam Getchell
5 ******************************************************************************/
6
9
10#ifndef CDT_PLUSPLUS_RUNTIME_CONFIG_HPP
11#define CDT_PLUSPLUS_RUNTIME_CONFIG_HPP
12
13#include <cmath>
14#include <limits>
15#include <stdexcept>
16#include <string>
17#include <utility>
18
19#include "Utilities.hpp"
20
21namespace runtime_config
22{
26 class Triangulation
27 {
28 friend auto make_triangulation(bool spherical, bool toroidal,
29 long long simplices, long long timeslices,
30 long long dimensions, double initial_radius,
31 double foliation_spacing) -> Triangulation;
32
33 topology_type m_topology;
34 Int_precision m_simplices;
35 Int_precision m_timeslices;
36 Int_precision m_dimensions;
37 double m_initial_radius;
38 double m_foliation_spacing;
39
40 explicit Triangulation(topology_type const topology,
41 Int_precision const simplices,
42 Int_precision const timeslices,
43 Int_precision const dimensions,
44 double const initial_radius,
45 double const foliation_spacing) noexcept
46 : m_topology{topology}
47 , m_simplices{simplices}
48 , m_timeslices{timeslices}
49 , m_dimensions{dimensions}
50 , m_initial_radius{initial_radius}
51 , m_foliation_spacing{foliation_spacing}
52 {}
53
54 public:
55 Triangulation(Triangulation const&) = default;
56 Triangulation(Triangulation&&) noexcept = default;
57 auto operator=(Triangulation const&) -> Triangulation& = default;
58 auto operator=(Triangulation&&) noexcept -> Triangulation& = default;
59 ~Triangulation() = default;
60
61 [[nodiscard]] auto topology() const noexcept -> topology_type
62 { return m_topology; }
63
64 [[nodiscard]] auto simplices() const noexcept -> Int_precision
65 { return m_simplices; }
66
67 [[nodiscard]] auto timeslices() const noexcept -> Int_precision
68 { return m_timeslices; }
69
70 [[nodiscard]] auto dimensions() const noexcept -> Int_precision
71 { return m_dimensions; }
72
73 [[nodiscard]] auto initial_radius() const noexcept -> double
74 { return m_initial_radius; }
75
76 [[nodiscard]] auto foliation_spacing() const noexcept -> double
77 { return m_foliation_spacing; }
78 };
79
83 class Simulation
84 {
85 friend auto make_simulation(Triangulation const& triangulation,
86 long double alpha, long double k,
87 long double lambda, long long passes,
88 long long checkpoint, bool write_files)
89 -> Simulation;
90
91 Triangulation m_triangulation;
92 long double m_alpha;
93 long double m_k;
94 long double m_lambda;
95 Int_precision m_passes;
96 Int_precision m_checkpoint;
97 bool m_write_files;
98
99 explicit Simulation(Triangulation const& triangulation,
100 long double const alpha, long double const k,
101 long double const lambda, Int_precision const passes,
102 Int_precision const checkpoint,
103 bool const write_files) noexcept
104 : m_triangulation{triangulation}
105 , m_alpha{alpha}
106 , m_k{k}
107 , m_lambda{lambda}
108 , m_passes{passes}
109 , m_checkpoint{checkpoint}
110 , m_write_files{write_files}
111 {}
112
113 public:
114 Simulation(Simulation const&) = default;
115 Simulation(Simulation&&) noexcept = default;
116 auto operator=(Simulation const&) -> Simulation& = default;
117 auto operator=(Simulation&&) noexcept -> Simulation& = default;
118 ~Simulation() = default;
119
120 [[nodiscard]] auto triangulation() const noexcept -> Triangulation const&
121 { return m_triangulation; }
122
123 [[nodiscard]] auto alpha() const noexcept -> long double { return m_alpha; }
124
125 [[nodiscard]] auto k() const noexcept -> long double { return m_k; }
126
127 [[nodiscard]] auto lambda() const noexcept -> long double
128 { return m_lambda; }
129
130 [[nodiscard]] auto passes() const noexcept -> Int_precision
131 { return m_passes; }
132
133 [[nodiscard]] auto checkpoint() const noexcept -> Int_precision
134 { return m_checkpoint; }
135
136 [[nodiscard]] auto write_files() const noexcept -> bool
137 { return m_write_files; }
138 };
139
140 namespace detail
141 {
142 template <typename FloatingPoint>
143 [[nodiscard]] auto checked_finite(char const* name,
144 FloatingPoint const value)
145 -> FloatingPoint
146 {
147 if (!std::isfinite(value))
148 {
149 throw std::invalid_argument(std::string{name} + " must be finite.");
150 }
151 return value;
152 }
153
154 [[nodiscard]] inline auto checked_int(char const* name,
155 long long const value)
157 {
158 if (!std::in_range<Int_precision>(value))
159 {
160 throw std::out_of_range(std::string{name} +
161 " exceeds the supported integer range.");
162 }
163 return static_cast<Int_precision>(value);
164 }
165
166 [[nodiscard]] inline auto select_topology(bool const spherical,
167 bool const toroidal)
169 {
170 if (spherical == toroidal)
171 {
172 throw std::invalid_argument(
173 "Specify exactly one topology: --spherical or --toroidal.");
174 }
175 if (toroidal)
176 {
177 throw std::invalid_argument(
178 "Toroidal triangulations are not yet supported.");
179 }
180 return topology_type::SPHERICAL;
181 }
182
183 using GeneratedPopulation = utilities::Generated_population_bounds;
184
185 [[nodiscard]] inline auto make_generated_population(
186 Int_precision const simplices, Int_precision const timeslices,
187 double const initial_radius, double const foliation_spacing)
188 -> GeneratedPopulation
189 {
190 auto const bounds = utilities::generated_population_bounds(
191 Int_precision{3}, simplices, timeslices, initial_radius,
192 foliation_spacing);
193 if (bounds.points_per_timeslice < 2)
194 {
195 throw std::invalid_argument(
196 "Simplices and timeslices would create an empty triangulation; "
197 "increase the simplices per timeslice.");
198 }
199
200 auto const first_layer_points =
201 static_cast<long double>(bounds.points_per_timeslice) *
202 initial_radius;
203 if (first_layer_points < 2.0L)
204 {
205 throw std::invalid_argument(
206 "Initial radius is too small to populate the first timeslice.");
207 }
208
209 if (!std::isfinite(bounds.last_layer_points) ||
210 bounds.last_layer_points >
211 static_cast<long double>(
212 std::numeric_limits<Int_precision>::max()))
213 {
214 throw std::out_of_range(
215 "Foliation parameters generate too many points per timeslice.");
216 }
217 return bounds;
218 }
219 } // namespace detail
220
222 [[nodiscard]] inline auto make_triangulation(
223 bool const spherical, bool const toroidal, long long const simplices,
224 long long const timeslices, long long const dimensions,
225 double const initial_radius, double const foliation_spacing)
226 -> Triangulation
227 {
228 auto const topology = detail::select_topology(spherical, toroidal);
229 auto const checked_simplices =
230 detail::checked_int("Number of simplices", simplices);
231 auto const checked_timeslices =
232 detail::checked_int("Number of timeslices", timeslices);
233 auto const checked_dimensions =
234 detail::checked_int("Dimensionality", dimensions);
235
236 if (checked_dimensions != 3)
237 {
238 throw std::invalid_argument(
239 "Only three-dimensional triangulations are supported.");
240 }
241 if (checked_simplices < 2 || checked_timeslices < 2)
242 {
243 throw std::invalid_argument(
244 "Simplices and timeslices must each be at least 2.");
245 }
246
247 auto const checked_initial_radius =
248 detail::checked_finite("Initial radius", initial_radius);
249 auto const checked_foliation_spacing =
250 detail::checked_finite("Foliation spacing", foliation_spacing);
251 if (checked_initial_radius <= 0.0)
252 {
253 throw std::invalid_argument("Initial radius must be positive.");
254 }
255 if (checked_foliation_spacing <= 0.0)
256 {
257 throw std::invalid_argument("Foliation spacing must be positive.");
258 }
259
260 [[maybe_unused]] auto const population = detail::make_generated_population(
261 checked_simplices, checked_timeslices, checked_initial_radius,
262 checked_foliation_spacing);
263 return Triangulation{
264 topology, checked_simplices, checked_timeslices,
265 checked_dimensions, checked_initial_radius, checked_foliation_spacing};
266 }
267
269 [[nodiscard]] inline auto make_simulation(
270 Triangulation const& triangulation, long double const alpha,
271 long double const k, long double const lambda, long long const passes,
272 long long const checkpoint, bool const write_files) -> Simulation
273 {
274 auto const checked_alpha = detail::checked_finite("Alpha", alpha);
275 auto const checked_k = detail::checked_finite("K", k);
276 auto const checked_lambda = detail::checked_finite("Lambda", lambda);
277 if (checked_alpha <= 0.5L)
278 {
279 throw std::domain_error("Alpha in 3D must be greater than 1/2.");
280 }
281
282 auto const checked_passes = detail::checked_int("Passes", passes);
283 auto const checked_checkpoint =
284 detail::checked_int("Checkpoint interval", checkpoint);
285 if (checked_passes <= 0)
286 {
287 throw std::invalid_argument("Passes must be positive.");
288 }
289 if (checked_checkpoint <= 0)
290 {
291 throw std::invalid_argument("Checkpoint interval must be positive.");
292 }
293
294 return Simulation{triangulation, checked_alpha, checked_k,
295 checked_lambda, checked_passes, checked_checkpoint,
296 write_files};
297 }
298} // namespace runtime_config
299
300#endif // CDT_PLUSPLUS_RUNTIME_CONFIG_HPP
std::int32_t Int_precision
Definition Settings.hpp:28
Utility functions.
auto generated_population_bounds(Int_precision const dimension, Int_precision const simplices, Int_precision const timeslices, double const initial_radius, double const foliation_spacing) -> Generated_population_bounds
Calculate the generated point count and its upper bound.
topology_type
clang-15 does not support std::format
Definition Utilities.hpp:49
friend auto make_simulation(Triangulation const &triangulation, long double alpha, long double k, long double lambda, long long passes, long long checkpoint, bool write_files) -> Simulation
Validate the complete simulation configuration.
friend auto make_triangulation(bool spherical, bool toroidal, long long simplices, long long timeslices, long long dimensions, double initial_radius, double foliation_spacing) -> Triangulation
Validate raw triangulation options and narrow them into project types.