BubbleProfiler  0.3.0
by Peter Athron, Csaba Balazs, Michael Bardsley, Andrew Fowlie, Dylan Harries & Graham White
euclidean_action.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of BubbleProfiler.
3  *
4  * BubbleProfiler is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * BubbleProfiler is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with BubbleProfiler. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
23 #include "euclidean_action.hpp"
24 #include "error.hpp"
25 #include "field_profiles.hpp"
26 #include "numeric.hpp"
27 #include "potential.hpp"
28 
29 #include <cmath>
30 
31 namespace BubbleProfiler {
32 
64  const Potential& /* potential */, const Field_profiles& profiles,
65  std::size_t max_intervals, double rel_tol, double abs_tol,
66  Integration_rule rule)
67 {
68  const int n_fields = profiles.get_number_of_fields();
69  const int d = profiles.get_number_of_dimensions();
70  const double domain_start = profiles.get_domain_start();
71  const double domain_end = profiles.get_domain_end();
72 
73  // finite domain correction
74  double correction = 0;
75  for (int i = 0; i < n_fields; ++i) {
76  const double deriv = profiles.derivative_at(i, 1, domain_end);
77  correction += 0.5 * deriv * deriv;
78  }
79 
80  const auto integrand
81  = [&profiles, n_fields, d, correction](double rho)
82  {
83  double result = 0.;
84  for (int i = 0; i < n_fields; ++i) {
85  const double deriv = profiles.derivative_at(i, 1, rho);
86  result += 0.5 * deriv * deriv;
87  }
88 
89  result -= correction;
90  result *= std::pow(rho, d - 1);
91 
92  return result;
93  };
94 
95  const auto result = integrate_gsl_qag(integrand, domain_start, domain_end,
96  abs_tol, rel_tol, max_intervals, rule);
97 
98  const auto error = std::get<0>(result);
99  if (error) {
100  throw Numerical_error("calculation of action failed with error code: "
101  + std::to_string(error));
102  }
103 
104  return 2. * area_n_sphere(d - 1) * std::get<1>(result) / d;
105 }
106 
139  const Potential& potential, const Field_profiles& profiles,
140  std::size_t max_intervals, double rel_tol, double abs_tol,
141  Integration_rule rule)
142 {
143  const int d = profiles.get_number_of_dimensions();
144  const double domain_start = profiles.get_domain_start();
145  const double domain_end = profiles.get_domain_end();
146 
147  // finite domain correction
148  double correction = potential(profiles.evaluate_at(domain_end));
149 
150  const auto integrand
151  = [&potential, &profiles, d, correction](double rho)
152  {
153  double result = potential(profiles.evaluate_at(rho));
154  result -= correction;
155  result *= std::pow(rho, d - 1);
156 
157  return result;
158  };
159 
160  const auto result = integrate_gsl_qag(integrand, domain_start, domain_end,
161  abs_tol, rel_tol, max_intervals, rule);
162 
163  const auto error = std::get<0>(result);
164  if (error) {
165  throw Numerical_error("calculation of action failed with error code: "
166  + std::to_string(error));
167  }
168 
169  return 2. * area_n_sphere(d - 1) * std::get<1>(result) / (2. - d);
170 }
171 
199  const Potential& potential, const Field_profiles& profiles,
200  std::size_t max_intervals, double rel_tol,
201  double abs_tol, Integration_rule rule)
202 {
203  const int n_fields = profiles.get_number_of_fields();
204  const int d = profiles.get_number_of_dimensions();
205  const double domain_start = profiles.get_domain_start();
206  const double domain_end = profiles.get_domain_end();
207 
208  // finite domain correction
209  double correction = 0.;
210  for (int i = 0; i < n_fields; ++i) {
211  const double deriv = profiles.derivative_at(i, 1, domain_end);
212  correction += 0.5 * deriv * deriv;
213  }
214  correction += potential(profiles.evaluate_at(domain_end));
215 
216  const auto integrand
217  = [&potential, &profiles, n_fields, d, correction](double rho)
218  {
219  double result = 0.;
220  for (int i = 0; i < n_fields; ++i) {
221  const double deriv = profiles.derivative_at(i, 1, rho);
222  result += 0.5 * deriv * deriv;
223  }
224 
225  result += potential(profiles.evaluate_at(rho));
226  result -= correction;
227  result *= pow(rho, d - 1);
228 
229  return result;
230  };
231 
232  const auto result = integrate_gsl_qag(integrand, domain_start, domain_end,
233  abs_tol, rel_tol, max_intervals, rule);
234 
235  const auto error = std::get<0>(result);
236  if (error) {
237  throw Numerical_error("calculation of action failed with error code: "
238  + std::to_string(error));
239  }
240 
241  return area_n_sphere(d - 1) * std::get<1>(result);
242 }
243 
258  const Potential& potential, const Field_profiles& profiles,
259  std::size_t max_intervals, double rel_tol,
260  double abs_tol, Integration_rule rule,
261  bool use_kinetic)
262 {
263  return use_kinetic ?
264  calculate_kinetic_action(potential, profiles, max_intervals,
265  rel_tol, abs_tol, rule) :
266  calculate_potential_action(potential, profiles, max_intervals,
267  rel_tol, abs_tol, rule);
268 }
269 
270 } // namespace BubbleProfiler
contains the definition of the Field_profiles clas
contains helper functions for calculating the Euclidean action
double calculate_potential_action(const Potential &potential, const Field_profiles &profiles, std::size_t max_intervals=1000, double rel_tol=1.e-4, double abs_tol=1.e-4, Integration_rule rule=Integration_rule::GK31)
Calculates the action using only the potential term contributions.
double derivative_at(int field, int order, double rho) const
Take the radial derivative of a field at a given radius.
double calculate_kinetic_action(const Potential &potential, const Field_profiles &profiles, std::size_t max_intervals=1000, double rel_tol=1.e-4, double abs_tol=1.e-4, Integration_rule rule=Integration_rule::GK31)
Calculates the action using only the kinetic term contributions.
std::tuple< int, double, double > integrate_gsl_qag(F f, double a, double b, double abs_tol, double rel_tol, std::size_t max_intervals, Integration_rule rule)
Eigen::VectorXd evaluate_at(double rho) const
Get all field values at a given radius.
double area_n_sphere(int n)
Definition: numeric.cpp:29
Numerical functions for one-dimensional shooting method and area of -sphere.
double calculate_full_action(const Potential &potential, const Field_profiles &profiles, std::size_t max_intervals=1000, double rel_tol=1.e-4, double abs_tol=1.e-4, Integration_rule rule=Integration_rule::GK31)
Calculates the action using all terms in the action integrand.
Abstract base class for a generic potential.
Definition: potential.hpp:36
Exception indicating generic numerical error.
Definition: error.hpp:116
double calculate_action(const Potential &potential, const Field_profiles &profiles, std::size_t max_intervals=1000, double rel_tol=1.e-4, double abs_tol=1.e-4, Integration_rule rule=Integration_rule::GK31, bool use_kinetic=true)
Calculates the action using either the kinetic or potential terms.
Discretized set of field profiles.