CDT++ 1.0.0
Causal Dynamical Triangulations in C++
Loading...
Searching...
No Matches
S3Action.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 Causal Dynamical Triangulations in C++ using CGAL
3
4 Copyright © 2014 Adam Getchell
5 ******************************************************************************/
6
18
19#ifndef INCLUDE_S3ACTION_HPP_
20#define INCLUDE_S3ACTION_HPP_
21
22#include <cmath>
23#include <stdexcept>
24#include <utility>
25
26#include "Mpfr_value.hpp"
27
28#pragma GCC diagnostic push
29#pragma GCC diagnostic ignored "-Wcomment"
30
31namespace cdt::s3_action
32{
36 class PhysicalParameters
37 {
38 long double m_alpha;
39 long double m_k;
40 long double m_lambda;
41
42 explicit constexpr PhysicalParameters(long double const alpha,
43 long double const k,
44 long double const lambda) noexcept
45 : m_alpha{alpha}, m_k{k}, m_lambda{lambda}
46 {}
47
48 friend auto make_physical_parameters(long double alpha, long double k,
49 long double lambda)
50 -> PhysicalParameters;
51
52 public:
54 [[nodiscard]] constexpr auto alpha() const noexcept { return m_alpha; }
56 [[nodiscard]] constexpr auto k() const noexcept { return m_k; }
58 [[nodiscard]] constexpr auto lambda() const noexcept { return m_lambda; }
59 };
60
68 [[nodiscard]] inline auto make_physical_parameters(long double const alpha,
69 long double const k,
70 long double const lambda)
71 -> PhysicalParameters
72 {
73 if (!std::isfinite(alpha) || !std::isfinite(k) || !std::isfinite(lambda))
74 {
75 throw std::invalid_argument("Physical parameters must be finite.");
76 }
77 if (alpha <= 0.5L)
78 {
79 throw std::domain_error("Alpha in 3D must be greater than 1/2.");
80 }
81 return PhysicalParameters{alpha, k, lambda};
82 }
83
84 namespace detail
85 {
86 [[nodiscard]] inline auto make_finite_couplings(long double const k,
87 long double const lambda)
88 -> std::pair<long double, long double>
89 {
90 if (!std::isfinite(k) || !std::isfinite(lambda))
91 {
92 throw std::invalid_argument("Physical parameters must be finite.");
93 }
94 return {k, lambda};
95 }
96 } // namespace detail
118 [[nodiscard]] inline auto
120 Int_precision const n1_tl_count, Int_precision const n3_31_13_count,
121 Int_precision const n3_22_count, long double const k_value,
122 long double const lambda_value) -> mpfr_values::Value
123 {
124 auto const [checked_k, checked_lambda] =
125 detail::make_finite_couplings(k_value, lambda_value);
126
127 // Set input parameters and constants to MPFR equivalents
128 auto const n1_tl = mpfr_values::from_integer(n1_tl_count);
129 auto const n3_31 = mpfr_values::from_integer(n3_31_13_count);
130 auto const n3_22 = mpfr_values::from_integer(n3_22_count);
131 auto const k = mpfr_values::from_long_double(checked_k);
132 auto const lambda = mpfr_values::from_long_double(checked_lambda);
133 auto const two = mpfr_values::from_integer(2);
134 auto const pi = mpfr_values::pi();
135 auto const const2673 = mpfr_values::from_decimal("2.673");
136 auto const const118 = mpfr_values::from_decimal("0.118");
137 auto const const7386 = mpfr_values::from_decimal("7.386");
138
139 // First term accumulates in r3
140 auto const r1 = mpfr_values::multiply(two, pi); // r1 = 2*pi
141 auto const r2 = mpfr_values::multiply(r1, k); // r2 = 2*pi*k
142 auto const r3 = mpfr_values::multiply(r2, n1_tl); // r3 = 2*pi*k*n1_tl
143
144 // Second term accumulates in r7
145 auto const r4 = mpfr_values::multiply(const2673, k); // r4 = 2.673*k
146 auto const r5 =
147 mpfr_values::multiply(const118, lambda); // r5 = 0.118*lambda
148 auto const r6 = mpfr_values::add(r4, r5); // r6 = r4 + r5
149 auto const r7 = mpfr_values::multiply(n3_31, r6); // r7 = n3_31*r6
150
151 // Third term accumulates in r11
152 auto const r8 = mpfr_values::multiply(const7386, k); // r8 = 7.386*k
153 auto const r9 =
154 mpfr_values::multiply(const118, lambda); // r9 = 0.118*lambda
155 auto const r10 = mpfr_values::add(r8, r9); // r10 = r8+r9
156 auto const r11 = mpfr_values::multiply(n3_22, r10); // r11 = n3_22*r10
157
158 // Result is r3+r7+r11
159 auto const r12 = mpfr_values::subtract(r7, r3); // r12 = r7-r3
160 auto const total = mpfr_values::add(r11, r12); // total = r11+r12
161
162 return total;
163 } // s3_bulk_action_alpha_minus_one_imaginary_coefficient()
164
180 [[nodiscard]] inline auto s3_bulk_action_alpha_one(
181 Int_precision const n1_tl_count, Int_precision const n3_31_13_count,
182 Int_precision const n3_22_count, long double const k_value,
183 long double const lambda_value) -> mpfr_values::Value
184 {
185 auto const [checked_k, checked_lambda] =
186 detail::make_finite_couplings(k_value, lambda_value);
187
188 // Set input parameters and constants to MPFR equivalents
189 auto const n1_tl = mpfr_values::from_integer(n1_tl_count);
190 auto const n3_31 = mpfr_values::from_integer(n3_31_13_count);
191 auto const n3_22 = mpfr_values::from_integer(n3_22_count);
192 auto const k = mpfr_values::from_long_double(checked_k);
193 auto const lambda = mpfr_values::from_long_double(checked_lambda);
194 auto const two = mpfr_values::from_integer(2);
195 auto const pi = mpfr_values::pi();
196 auto const const3548 = mpfr_values::from_decimal("-3.548");
197 auto const const167 = mpfr_values::from_decimal("-0.167");
198 auto const const5355 = mpfr_values::from_decimal("-5.355");
199 auto const const204 = mpfr_values::from_decimal("-0.204");
200
201 // First term accumulates in r3
202 auto const r1 = mpfr_values::multiply(two, pi); // r1 = 2*pi
203 auto const r2 = mpfr_values::multiply(r1, k); // r2 = 2*pi*k
204 auto const r3 = mpfr_values::multiply(r2, n1_tl); // r3 = 2*pi*k*n1_tl
205
206 // Second term accumulates in r7
207 auto const r4 = mpfr_values::multiply(const3548, k); // r4 = -3.548*k
208 auto const r5 =
209 mpfr_values::multiply(const167, lambda); // r5 = -0.167*lambda
210 auto const r6 = mpfr_values::add(r4, r5); // r6 = r4 + r5
211 auto const r7 = mpfr_values::multiply(n3_31, r6); // r7 = n3_31*r6
212
213 // Third term accumulates in r11
214 auto const r8 = mpfr_values::multiply(const5355, k); // r8 = -5.355*k
215 auto const r9 =
216 mpfr_values::multiply(const204, lambda); // r9 = -0.204*lambda
217 auto const r10 = mpfr_values::add(r8, r9); // r10 = r8+r9
218 auto const r11 = mpfr_values::multiply(n3_22, r10); // r11 = n3_22*r10
219
220 // Result is r3+r7+r11
221 auto const r12 = mpfr_values::add(r3, r7); // r12 = r3+r7
222 auto const total = mpfr_values::add(r11, r12); // total = r11+r12
223
224 return total;
225 } // s3_bulk_action_alpha_one()
226
253 [[nodiscard]] inline auto s3_bulk_action(Int_precision const n1_tl_count,
254 Int_precision const n3_31_13_count,
255 Int_precision const n3_22_count,
256 PhysicalParameters const& parameters)
258 {
259 // Set input parameters and constants to MPFR equivalents
260 auto const n1_tl = mpfr_values::from_integer(n1_tl_count);
261 auto const n3_31 = mpfr_values::from_integer(n3_31_13_count);
262 auto const n3_22 = mpfr_values::from_integer(n3_22_count);
263 auto const alpha = mpfr_values::from_long_double(parameters.alpha());
264 auto const k = mpfr_values::from_long_double(parameters.k());
265 auto const lambda = mpfr_values::from_long_double(parameters.lambda());
266 auto const two = mpfr_values::from_integer(2);
267 auto const pi = mpfr_values::pi();
268 auto const three = mpfr_values::from_integer(3);
269 auto const four = mpfr_values::from_integer(4);
270 auto const one = mpfr_values::from_integer(1);
271 auto const twelve = mpfr_values::from_integer(12);
272
273 // First term accumulates in r5
274 auto const r1 = mpfr_values::multiply(two, pi); // r1 = 2*pi
275 auto const r2 = mpfr_values::multiply(r1, k); // r2 = 2*pi*k
276 auto const r3 = mpfr_values::square_root(alpha); // r3 = sqrt(alpha)
277 auto const r4 =
278 mpfr_values::multiply(r3, r2); // r4 = r3*r2 = 2*pi*k*sqrt(alpha)
279 auto const r5 = mpfr_values::multiply(r4, n1_tl); // r5 = r4*n1_tl
280
281 // Second term accumulates in r30
282 auto const r6 = mpfr_values::square_root(three); // r6 = sqrt(3)
283 auto const r7 = mpfr_values::multiply(four, alpha); // r7 = 4*alpha
284 auto const r8 = mpfr_values::add(one, r7); // r8 = r7+1 = 4*alpha+1
285 auto const r9 =
286 mpfr_values::square_root(r8); // r9 = sqrt(r8) = sqrt(4*alpha+1)
287 auto const r10 = mpfr_values::multiply(r6, r9); // r10 = r6*r9
288 auto const r11 = mpfr_values::divide(one, r10); // r11 = 1/r10
289 auto const r12 =
290 mpfr_values::inverse_hyperbolic_sine(r11); // r12 = arcsinh(r11)
291 auto const r13 = mpfr_values::negate(three); // r13 = -3
292 auto const r14 = mpfr_values::multiply(r13, k); // r14 = r13*k = -3*k
293 // r15 = r14*r12 = -3*k*arcsinh(r11)
294 auto const r15 = mpfr_values::multiply(r14, r12);
295
296 auto const r16 = mpfr_values::multiply(two, alpha); // r16 = 2*alpha
297 auto const r17 = mpfr_values::add(r16, one); // r17 = 2*alpha+1
298 auto const r18 =
299 mpfr_values::divide(r17, r8); // r18 = (2*alpha+1)/(4*alpha+1)
300 auto const r19 = mpfr_values::arc_cosine(r18); // r19 = arccos(r18)
301 auto const r20 = mpfr_values::multiply(r14, r3); // r20 = -3*k*sqrt(alpha)
302 auto const r21 =
303 mpfr_values::multiply(r20, r19); // r21 = -3*k*sqrt(alpha)*arccos(r18)
304
305 auto const r22 = mpfr_values::multiply(three, alpha); // r22 = 3*alpha
306 auto const r23 = mpfr_values::add(r22, one); // r23 = 3*alpha+1
307 auto const r24 = mpfr_values::square_root(r23); // r24 = sqrt(3*alpha+1)
308 auto const r25 = mpfr_values::negate(lambda); // r25 = -lambda
309 auto const r26 = mpfr_values::divide(r25, twelve); // r26 = -lambda/12
310 auto const r27 =
311 mpfr_values::multiply(r26, r24); // r27 = (-lambda/12)*sqrt(3*alpha+1)
312
313 // Accumulate partial sums of second term
314 auto const r28 = mpfr_values::add(r15, r21); // r28 = r15+r21
315 auto const r29 = mpfr_values::add(r28, r27); // r29 = r28+r27
316
317 // Multiply by overall factor of n3_31
318 auto const r30 = mpfr_values::multiply(n3_31, r29); // r30 = n3_31*r29
319
320 // Third term accumulates in r51
321 auto const r31 = mpfr_values::multiply(two, k); // r31 = 2*k
322 auto const r32 = mpfr_values::square_root(two); // r32 = sqrt(2)
323 auto const r33 = mpfr_values::multiply(two, r32); // r33 = 2*sqrt(2)
324 auto const r34 = mpfr_values::square_root(r17); // r34 = sqrt(2*alpha+1)
325 auto const r35 = mpfr_values::multiply(r33, r34); // r35 = r33*r34
326 auto const r36 =
327 mpfr_values::divide(r35, r8); // r36 = 2*sqrt(2)*sqrt(2*alpha+1)/
328 // 4*alpha+1
329 auto const r37 =
330 mpfr_values::inverse_hyperbolic_sine(r36); // r37 = arcsinh(r36)
331 auto const r38 = mpfr_values::multiply(r31, r37); // r38 = 2*k*arcsinh(r36)
332
333 auto const r39 = mpfr_values::negate(one); // r39 = -1
334 auto const r40 = mpfr_values::divide(r39, r8); // r40 = -1/(4*alpha+1)
335 auto const r41 = mpfr_values::arc_cosine(r40); // r41 = arccos(r40)
336 auto const r42 = mpfr_values::negate(four); // r42 = -4
337 auto const r43 = mpfr_values::multiply(r42, k); // r43 = -4*k
338 auto const r44 = mpfr_values::multiply(r43, r3); // r44 = -4*k*sqrt(alpha)
339 auto const r45 =
340 mpfr_values::multiply(r44, r41); // r45 = -4*k*sqrt(alpha)*arccos(r40)
341
342 auto const r46 = mpfr_values::add(r7, two); // r46 = 4*alpha+2
343 auto const r47 = mpfr_values::square_root(r46); // r47 = sqrt(4*alpha+2)
344 auto const r48 =
345 mpfr_values::multiply(r26, r47); // r48 = (-lambda/12)*sqrt(4*alpha+2)
346
347 // Accumulate partial sums of third term
348 auto const r49 = mpfr_values::add(r38, r45); // r49 = r38+r45
349 auto const r50 = mpfr_values::add(r49, r48); // r50 = r49+r48
350
351 // Multiply by overall factor of n3_22
352 auto const r51 = mpfr_values::multiply(n3_22, r50); // r51 = n3_22*r50
353
354 auto const r52 = mpfr_values::add(r5, r30); // r52 = r5+r30
355 auto const total = mpfr_values::add(r51, r52); // total = r51+r52
356
357 return total;
358 } // s3_bulk_action()
359
360#pragma GCC diagnostic pop
361
362} // namespace cdt::s3_action
363
364#endif // INCLUDE_S3ACTION_HPP_
Scope-owned, value-returning MPFR operations.
auto multiply(Value const &left, Value const &right) -> Value
auto square_root(Value const &value) -> Value
auto negate(Value const &value) -> Value
auto from_integer(long const value) -> Value
auto from_long_double(long double const value) -> Value
auto inverse_hyperbolic_sine(Value const &value) -> Value
auto subtract(Value const &left, Value const &right) -> Value
auto pi() -> Value
auto add(Value const &left, Value const &right) -> Value
auto from_decimal(char const *value) -> Value
auto arc_cosine(Value const &value) -> Value
auto divide(Value const &numerator, Value const &denominator) -> Value
CGAL::Gmpfr Value
Owning arbitrary-precision floating-point value used by CDT++.
auto s3_bulk_action(Int_precision const n1_tl_count, Int_precision const n3_31_13_count, Int_precision const n3_22_count, PhysicalParameters const &parameters) -> mpfr_values::Value
Calculates the generalized S3 bulk action in terms of , , , , , and .
Definition S3Action.hpp:253
auto s3_bulk_action_alpha_minus_one_imaginary_coefficient(Int_precision const n1_tl_count, Int_precision const n3_31_13_count, Int_precision const n3_22_count, long double const k_value, long double const lambda_value) -> mpfr_values::Value
Calculates the coefficient of in the S3 bulk action.
Definition S3Action.hpp:119
auto s3_bulk_action_alpha_one(Int_precision const n1_tl_count, Int_precision const n3_31_13_count, Int_precision const n3_22_count, long double const k_value, long double const lambda_value) -> mpfr_values::Value
Calculates S3 bulk action for =1.
Definition S3Action.hpp:180
Finite physical couplings used to evaluate the Euclidean action.
Definition S3Action.hpp:37
constexpr auto k() const noexcept
Definition S3Action.hpp:56
friend auto make_physical_parameters(long double alpha, long double k, long double lambda) -> PhysicalParameters
Validate physical couplings for three-dimensional action APIs.
Definition S3Action.hpp:68
constexpr auto lambda() const noexcept
Definition S3Action.hpp:58
constexpr auto alpha() const noexcept
Definition S3Action.hpp:54
std::int32_t Int_precision
Definition Settings.hpp:30