10#ifndef CDT_PLUSPLUS_RUNTIME_CONFIG_HPP
11#define CDT_PLUSPLUS_RUNTIME_CONFIG_HPP
21namespace runtime_config
29 long long simplices,
long long timeslices,
30 long long dimensions,
double initial_radius,
31 double foliation_spacing) -> Triangulation;
37 double m_initial_radius;
38 double m_foliation_spacing;
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}
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;
62 {
return m_topology; }
64 [[nodiscard]]
auto simplices()
const noexcept ->
Int_precision
65 {
return m_simplices; }
67 [[nodiscard]]
auto timeslices()
const noexcept ->
Int_precision
68 {
return m_timeslices; }
70 [[nodiscard]]
auto dimensions()
const noexcept ->
Int_precision
71 {
return m_dimensions; }
73 [[nodiscard]]
auto initial_radius()
const noexcept ->
double
74 {
return m_initial_radius; }
76 [[nodiscard]]
auto foliation_spacing()
const noexcept ->
double
77 {
return m_foliation_spacing; }
86 long double alpha,
long double k,
87 long double lambda,
long long passes,
88 long long checkpoint,
bool write_files)
100 long double const alpha,
long double const k,
103 bool const write_files) noexcept
104 : m_triangulation{triangulation}
109 , m_checkpoint{checkpoint}
110 , m_write_files{write_files}
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;
120 [[nodiscard]]
auto triangulation()
const noexcept ->
Triangulation const&
121 {
return m_triangulation; }
123 [[nodiscard]]
auto alpha()
const noexcept ->
long double {
return m_alpha; }
125 [[nodiscard]]
auto k()
const noexcept ->
long double {
return m_k; }
127 [[nodiscard]]
auto lambda()
const noexcept ->
long double
133 [[nodiscard]]
auto checkpoint()
const noexcept ->
Int_precision
134 {
return m_checkpoint; }
136 [[nodiscard]]
auto write_files()
const noexcept ->
bool
137 {
return m_write_files; }
142 template <
typename FloatingPo
int>
143 [[nodiscard]]
auto checked_finite(
char const* name,
144 FloatingPoint
const value)
147 if (!std::isfinite(value))
149 throw std::invalid_argument(std::string{name} +
" must be finite.");
154 [[nodiscard]]
inline auto checked_int(
char const* name,
155 long long const value)
158 if (!std::in_range<Int_precision>(value))
160 throw std::out_of_range(std::string{name} +
161 " exceeds the supported integer range.");
166 [[nodiscard]]
inline auto select_topology(
bool const spherical,
170 if (spherical == toroidal)
172 throw std::invalid_argument(
173 "Specify exactly one topology: --spherical or --toroidal.");
177 throw std::invalid_argument(
178 "Toroidal triangulations are not yet supported.");
180 return topology_type::SPHERICAL;
183 using GeneratedPopulation = utilities::Generated_population_bounds;
185 [[nodiscard]]
inline auto make_generated_population(
187 double const initial_radius,
double const foliation_spacing)
188 -> GeneratedPopulation
193 if (bounds.points_per_timeslice < 2)
195 throw std::invalid_argument(
196 "Simplices and timeslices would create an empty triangulation; "
197 "increase the simplices per timeslice.");
200 auto const first_layer_points =
201 static_cast<long double>(bounds.points_per_timeslice) *
203 if (first_layer_points < 2.0L)
205 throw std::invalid_argument(
206 "Initial radius is too small to populate the first timeslice.");
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()))
214 throw std::out_of_range(
215 "Foliation parameters generate too many points per timeslice.");
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)
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);
236 if (checked_dimensions != 3)
238 throw std::invalid_argument(
239 "Only three-dimensional triangulations are supported.");
241 if (checked_simplices < 2 || checked_timeslices < 2)
243 throw std::invalid_argument(
244 "Simplices and timeslices must each be at least 2.");
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)
253 throw std::invalid_argument(
"Initial radius must be positive.");
255 if (checked_foliation_spacing <= 0.0)
257 throw std::invalid_argument(
"Foliation spacing must be positive.");
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};
271 long double const k,
long double const lambda,
long long const passes,
272 long long const checkpoint,
bool const write_files) -> Simulation
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)
279 throw std::domain_error(
"Alpha in 3D must be greater than 1/2.");
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)
287 throw std::invalid_argument(
"Passes must be positive.");
289 if (checked_checkpoint <= 0)
291 throw std::invalid_argument(
"Checkpoint interval must be positive.");
294 return Simulation{triangulation, checked_alpha, checked_k,
295 checked_lambda, checked_passes, checked_checkpoint,
std::int32_t Int_precision
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
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.