BubbleProfiler  0.3.0
by Peter Athron, Csaba Balazs, Michael Bardsley, Andrew Fowlie, Dylan Harries & Graham White
thin_wall.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 
34 #include "error.hpp"
35 #include "field_profiles.hpp"
36 #include "gsl_root_finder.hpp"
37 #include "kink_profile_guesser.hpp"
38 #include "logging_manager.hpp"
40 #include "shooting.hpp"
41 #include "thin_wall_observer.hpp"
42 #include "thin_wall_potential.hpp"
43 
44 #include <fstream>
45 #include <iomanip>
46 #include <iostream>
47 #include <string>
48 #include <tuple>
49 #include <vector>
50 
51 namespace BubbleProfiler {
52 
54  double lambda{1.};
55  double a{1.};
56  double delta{0.01};
57  int dim{4};
58  bool calculate_profile{false};
59  std::string output_file{""};
60  std::string perturbations_file{""};
61  bool use_perturbative{false};
62  bool verbose{false};
63 };
64 
65 void print_usage()
66 {
67  std::cout <<
68  "Usage: thin [OPTION] <lambda> <a> <delta>\n\n"
69  "Calculate action and field profile for one-dimensional perturbed\n"
70  "quartic potential characterized by the parameters lambda, a,\n"
71  "and delta.\n\n"
72  "Example: thin -c -o 'output.txt' 1 1 0.01\n\n"
73  "Options:\n"
74  " -c, --calculate-profile calculate field profile as well\n"
75  " -f, --finite-temperature calculate using d = 3 dimensions\n"
76  " -h, --help print this help message\n"
77  " -o, --output-file=FILE write results to FILE\n"
78  " -P, --perturbations-file=FILE write perturbations to FILE\n"
79  " -p, --perturbative use the perturbative algorithm\n"
80  " -v, --verbose produce verbose output"
81  << std::endl;
82 }
83 
84 bool starts_with(const std::string& option, const std::string& prefix)
85 {
86  return !option.compare(0, prefix.size(), prefix);
87 }
88 
89 std::string get_option_value(const std::string& option,
90  const std::string& sep = "=")
91 {
92  std::string value{""};
93  const auto prefix_end = option.find(sep);
94 
95  if (prefix_end != std::string::npos) {
96  value = option.substr(prefix_end + 1);
97  }
98 
99  return value;
100 }
101 
102 void parse_positional_args(const std::vector<std::string>& args,
103  Thin_wall_options& options)
104 {
105  const auto n_positional_args = args.size();
106 
107  if (n_positional_args == 0) {
108  throw Setup_error(
109  "value of lambda must be provided");
110  } else if (n_positional_args == 1) {
111  throw Setup_error(
112  "value of a must be provided");
113  } else if (n_positional_args == 2) {
114  throw Setup_error(
115  "value of delta must be provided");
116  } else if (n_positional_args > 3) {
117  throw Setup_error(
118  "unrecognized command line argument '"
119  + args[3] + "'");
120  }
121 
122  try {
123  options.lambda = std::stod(args[0]);
124  } catch (const std::invalid_argument& e) {
125  throw Setup_error(
126  "invalid value of lambda, '" + args[0] + "'");
127  }
128 
129  try {
130  options.a = std::stod(args[1]);
131  } catch (const std::invalid_argument& e) {
132  throw Setup_error(
133  "invalid value for a, '" + args[1] + "'");
134  }
135 
136  try {
137  options.delta = std::stod(args[2]);
138  } catch (const std::invalid_argument& e) {
139  throw Setup_error(
140  "invalid value for delta, '" + args[2] + "'");
141  }
142 }
143 
144 Thin_wall_options parse_cmd_line_args(int argc, const char* argv[])
145 {
146  Thin_wall_options options;
147 
148  std::vector<std::string> positional_args;
149  int i = 1;
150  while (i < argc) {
151  const std::string opt(argv[i++]);
152 
153  if (!starts_with(opt, "-")) {
154  positional_args.push_back(opt);
155  continue;
156  }
157 
158  if (opt == "-c" || opt == "--calculate-profile") {
159  options.calculate_profile = true;
160  continue;
161  }
162 
163  if (opt == "-f" || opt == "--finite-temperature") {
164  options.dim = 3;
165  continue;
166  }
167 
168  if (opt == "-h" || opt == "--help") {
169  print_usage();
170  exit(EXIT_SUCCESS);
171  }
172 
173  if (opt == "-o") {
174  if (i == argc) {
175  throw Setup_error(
176  "'-o' given but no output file name provided");
177  }
178  const std::string filename(argv[i++]);
179  if (starts_with(filename, "-") && filename != "-") {
180  throw Setup_error(
181  "'-o' given but no output file name provided");
182  }
183  options.output_file = filename;
184  continue;
185  }
186 
187  if (starts_with(opt, "--output-file=")) {
188  const std::string filename = get_option_value(opt);
189  if (filename.empty()) {
190  throw Setup_error(
191  "'--output-file=' given but no output file name provided");
192  }
193  options.output_file = filename;
194  continue;
195  }
196 
197  if (opt == "-P") {
198  if (i == argc) {
199  throw Setup_error(
200  "'-P' given but no file name provided");
201  }
202  const std::string filename(argv[i++]);
203  if (starts_with(filename, "-") && filename != "-") {
204  throw Setup_error(
205  "'-P' given but no file name provided");
206  }
207  options.perturbations_file = filename;
208  continue;
209  }
210 
211  if (starts_with(opt, "--perturbations-file=")) {
212  const std::string filename = get_option_value(opt);
213  if (filename.empty()) {
214  throw Setup_error(
215  "'--perturbations-file=' given but no file name provided");
216  }
217  options.perturbations_file = filename;
218  continue;
219  }
220 
221  if (opt == "-p" || opt == "--perturbative") {
222  options.use_perturbative = true;
223  continue;
224  }
225 
226  if (opt == "-v" || opt == "--verbose") {
227  options.verbose = true;
228  continue;
229  }
230 
231  throw Setup_error(
232  "unrecognized command line argument '" + opt + "'");
233  }
234 
235  parse_positional_args(positional_args, options);
236 
237  return options;
238 }
239 
240 std::tuple<double, Field_profiles> solve_shooting(
241  const Thin_wall_potential& potential, int dim, bool calculate_profile)
242 {
243  const double false_min = potential.get_local_minimum_location();
244  const double barrier = potential.get_local_maximum_location();
245  const double true_min = potential.get_global_minimum_location();
246 
247  unsigned int options
248  = calculate_profile ?
249  (Shooting::Solver_options::Compute_action |
250  Shooting::Solver_options::Compute_profile)
251  : Shooting::Solver_options::Compute_action;
252 
253  Shooting profiler;
254  // Strict tolerances for thin-wall solutions
255  profiler.set_bisection_precision_bits(30);
256  profiler.set_shooting_abs_tol(1.e-15);
257  profiler.set_shooting_rel_tol(1.e-15);
258  profiler.set_action_abs_tol(1.e-15);
259  profiler.set_action_rel_tol(1.e-15);
260  profiler.set_evolve_change_rel(1.e-4);
261 
262  double action = 0.;
263  Field_profiles profile;
264 
265  profiler.solve(potential, false_min, true_min, barrier, dim,
266  options);
267 
268  if ((options & Shooting::Solver_options::Compute_action) != 0) {
269  action = profiler.get_euclidean_action();
270  }
271 
272  if ((options & Shooting::Solver_options::Compute_profile) != 0) {
273  profile = profiler.get_bubble_profile();
274  }
275 
276  return std::make_tuple(action, profile);
277 }
278 
279 std::tuple<double, Field_profiles> solve_perturbative(
280  Thin_wall_potential& potential, int dim,
281  const std::string& observer_file)
282 {
284 
285  RK4_perturbative_profiler profiler;
286 
287  profiler.set_initial_step_size(1.e-3);
288 
289  profiler.set_initial_guesser(std::make_shared<Kink_profile_guesser>());
290 
291  const double action_tol = 1.e-3;
292  const double fields_tol = 1.e-3;
293  profiler.set_convergence_tester(
294  std::make_shared<Relative_convergence_tester>(
295  action_tol, fields_tol));
296 
297  auto root_finder = std::make_shared<Root_finder>();
298  profiler.set_root_finder(root_finder);
299 
300  Eigen::VectorXd true_vacuum(1);
301  true_vacuum << potential.get_global_minimum_location();
302 
303  Eigen::VectorXd false_vacuum(1);
304  false_vacuum << potential.get_local_minimum_location();
305 
306  profiler.set_number_of_dimensions(dim);
307  profiler.set_true_vacuum_loc(true_vacuum);
308  profiler.set_false_vacuum_loc(false_vacuum);
309 
310  double action = 0.;
311  Field_profiles profile;
312 
313  if (observer_file.empty()) {
314  profiler.calculate_bubble_profile(potential);
315  } else {
316  Thin_wall_observer observer(observer_file);
317  profiler.calculate_bubble_profile(potential, observer);
318  }
319  action = profiler.get_euclidean_action();
320  profile = profiler.get_bubble_profile();
321 
322  return std::make_tuple(action, profile);
323 }
324 
325 void write_profile(std::ostream& ostr, const Field_profiles& numerical_profile)
326 {
327  ostr << "# "
328  << std::setw(16) << "rho" << ' '
329  << std::setw(16) << "numeric" << std::endl;
330 
331  const auto n_grid_points = numerical_profile.get_number_of_grid_points();
332 
333  const auto rho_values = numerical_profile.get_spatial_grid();
334  const auto numerical_values = numerical_profile.get_field_profiles();
335 
336  for (int i = 0; i < n_grid_points; ++i) {
337  ostr << " "
338  << std::setw(16) << std::setprecision(8)
339  << std::scientific << rho_values(i) << ' '
340  << std::setw(16) << std::setprecision(8)
341  << std::scientific << numerical_values(i, 0) << std::endl;
342  }
343 }
344 
345 void write_action(std::ostream& ostr, double numerical_action,
346  double thin_wall_action)
347 {
348  const double rel_diff = (numerical_action - thin_wall_action)
349  / (0.5 * (numerical_action + thin_wall_action));
350 
351  ostr << "# Numerical action = "
352  << std::setprecision(8) << std::scientific << numerical_action
353  << std::endl;
354  ostr << "# Thin wall action = "
355  << std::setprecision(8) << std::scientific << thin_wall_action
356  << std::endl;
357  ostr << "# Relative error = "
358  << std::setprecision(8) << std::scientific << rel_diff
359  << std::endl;
360 }
361 
362 } // namespace BubbleProfiler
363 
364 int main(int argc, const char* argv[])
365 {
366  using namespace BubbleProfiler;
367 
368  if (argc == 1) {
369  std::cerr << "Usage: thin [OPTION] <lambda> <a> <delta>\n"
370  << "Try 'thin --help' for more information."
371  << std::endl;
372  return EXIT_FAILURE;
373  }
374 
375  int exit_code = 0;
376  try {
377  Thin_wall_options options = parse_cmd_line_args(argc, argv);
378 
379  if (options.verbose) {
382  }
383 
384  Thin_wall_potential potential(options.lambda, options.a, options.delta);
385 
386  std::tuple<double, Field_profiles> result;
387  if (options.use_perturbative) {
388  result = solve_perturbative(potential, options.dim,
389  options.perturbations_file);
390  } else {
391  result = solve_shooting(potential, options.dim,
392  options.calculate_profile);
393  }
394 
395  std::ofstream output_file;
396  if (!options.output_file.empty()) {
397  output_file.open(options.output_file, std::ios::out);
398  }
399 
400  std::ostream& output_stream
401  = (options.output_file.empty() ? std::cout : output_file);
402 
403  if (options.calculate_profile) {
404  write_profile(output_stream, std::get<1>(result));
405  }
406 
407  const double thin_wall_action = potential.get_thin_wall_action();
408  write_action(output_stream, std::get<0>(result), thin_wall_action);
409  } catch (const Setup_error& e) {
410  std::cerr << "Error: " << e.what() << std::endl;
411  exit_code = EXIT_FAILURE;
412  } catch (const BVP_solver_error& e) {
413  std::cerr << "Error: " << e.what() << std::endl;
414  exit_code = EXIT_FAILURE;
415  } catch (const Numerical_error& e) {
416  std::cerr << "Error: " << e.what() << std::endl;
417  exit_code = EXIT_FAILURE;
418  } catch (const Error& e) {
419  std::cerr << "Error: " << e.what() << std::endl;
420  exit_code = EXIT_FAILURE;
421  } catch (...) {
422  std::cerr << "Error: unrecognized error occurred."
423  << std::endl;
424  exit_code = EXIT_FAILURE;
425  }
426 
427  return exit_code;
428 }
contains the definition of the Field_profiles clas
double get_local_minimum_location() const
returns the location of the local minimum
Exception indicating failure to integrate BVP.
Definition: error.hpp:44
void parse_positional_args(const std::vector< std::string > &args, Fubini_options &options)
std::tuple< double, Field_profiles > solve_perturbative(Generalized_fubini_potential &potential, double true_min, const std::string &observer_file)
void set_initial_guesser(std::shared_ptr< Profile_guesser > g)
const Eigen::VectorXd & get_spatial_grid() const
Get a vector of the grid point coordinates.
void set_false_vacuum_loc(const Eigen::VectorXd &fv)
Bubble_profiler_inputs parse_cmd_line_args(int argc, const char *argv[])
void set_root_finder(std::shared_ptr< Root_finder< Eigen::VectorXd > > rf)
double get_euclidean_action() const
Retrieve the action after running calculate_bubble_profile.
std::string get_option_value(const std::string &option, const std::string &sep="=")
void write_profile(std::ostream &ostr, const Field_profiles &numerical_profile, const Field_profiles &exact_profile)
void set_convergence_tester(std::shared_ptr< Profile_convergence_tester > ct)
static Logging_manager & get_manager()
std::tuple< double, Field_profiles > solve_shooting(const Generalized_fubini_potential &potential, double true_min, bool calculate_profile)
Example thin wall potential as given by Coleman.
void write_action(double action, std::ostream &ostr)
Write the value of the action to requested output stream.
double get_thin_wall_action() const
returns the approximate action in the thin-wall approximation
Solve the one-dimensional problem using the shooting method.
Definition: shooting.hpp:44
Exception indicating general setup error.
Definition: error.hpp:32
One-dimensional shooting method.
bool starts_with(const std::string &option, const std::string &prefix)
int main(int argc, const char *argv[])
Definition: thin_wall.cpp:364
Exception indicating generic numerical error.
Definition: error.hpp:116
double get_local_maximum_location() const
returns the location of the local maximum
const Field_profiles & get_bubble_profile() const
Retrieve the field profiles after running calculate_bubble_profile.
void set_bisection_precision_bits(int b)
Definition: shooting.hpp:52
Discretized set of field profiles.
Bounce solver using perturbative method.
const Eigen::MatrixXd & get_field_profiles() const
Get the field profile data in matrix form.
double get_global_minimum_location() const
returns the location of the global minimum