BubbleProfiler  0.3.0
by Peter Athron, Csaba Balazs, Michael Bardsley, Andrew Fowlie, Dylan Harries & Graham White
logarithmic.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 
35 #include "error.hpp"
36 #include "field_profiles.hpp"
37 #include "gsl_root_finder.hpp"
38 #include "kink_profile_guesser.hpp"
40 #include "logging_manager.hpp"
41 #include "logarithmic_observer.hpp"
43 #include "shooting.hpp"
44 
45 #include <fstream>
46 #include <iomanip>
47 #include <iostream>
48 #include <string>
49 #include <tuple>
50 #include <vector>
51 
52 namespace BubbleProfiler {
53 
55  double m{1.};
56  double w{1.};
57  bool calculate_profile{false};
58  double global_min{-1.};
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: logarithmic [OPTION] <m> <w>\n\n"
69  "Calculate action and field profile for one-dimensional logarthmic\n"
70  "potential characterized by the parameters m and w.\n\n"
71  "Example: logarithmic -c -o 'output.txt' 1 1\n\n"
72  "Options:\n"
73  " -c, --calculate-profile calculate field profile as well\n"
74  " -g, --global-minimum=MIN use MIN as location of true vacuum\n"
75  " -h, --help print this help message\n"
76  " -o, --output-file=FILE write results to FILE\n"
77  " -P, --perturbations-file=FILE write perturbations to FILE\n"
78  " -p, --perturbative use the perturbative algorithm\n"
79  " -v, --verbose produce verbose output"
80  << std::endl;
81 }
82 
83 bool starts_with(const std::string& option, const std::string& prefix)
84 {
85  return !option.compare(0, prefix.size(), prefix);
86 }
87 
88 std::string get_option_value(const std::string& option,
89  const std::string& sep = "=")
90 {
91  std::string value{""};
92  const auto prefix_end = option.find(sep);
93 
94  if (prefix_end != std::string::npos) {
95  value = option.substr(prefix_end + 1);
96  }
97 
98  return value;
99 }
100 
101 void parse_positional_args(const std::vector<std::string>& args,
102  Logarithmic_options& options)
103 {
104  const auto n_positional_args = args.size();
105 
106  if (n_positional_args == 0) {
107  throw Setup_error(
108  "value of m must be provided");
109  } else if (n_positional_args == 1) {
110  throw Setup_error(
111  "value of w must be provided");
112  } else if (n_positional_args > 2) {
113  throw Setup_error(
114  "unrecognized command line argument '"
115  + args[2] + "'");
116  }
117 
118  try {
119  options.m = std::stod(args[0]);
120  } catch (const std::invalid_argument& e) {
121  throw Setup_error(
122  "invalid value of m, '" + args[0] + "'");
123  }
124 
125  try {
126  options.w = std::stod(args[1]);
127  } catch (const std::invalid_argument& e) {
128  throw Setup_error(
129  "invalid value for w, '" + args[1] + "'");
130  }
131 }
132 
133 double parse_global_min(const std::string& value)
134 {
135  if (value.empty()) {
136  throw Setup_error(
137  "'-g' or '--global-minimum' given but no value specified");
138  }
139 
140  double global_min = 0.;
141  try {
142  global_min = std::stod(value);
143  } catch (const std::invalid_argument& e) {
144  throw Setup_error(
145  "invalid global minimum location '" + value + "'");
146  }
147 
148  if (global_min <= 0.) {
149  throw Setup_error(
150  "explicitly specified true vacuum must be positive");
151  }
152 
153  return global_min;
154 }
155 
156 Logarithmic_options parse_cmd_line_args(int argc, const char* argv[])
157 {
158  Logarithmic_options options;
159 
160  std::vector<std::string> positional_args;
161  int i = 1;
162  while (i < argc) {
163  const std::string opt(argv[i++]);
164 
165  if (!starts_with(opt, "-")) {
166  positional_args.push_back(opt);
167  continue;
168  }
169 
170  if (opt == "-c" || opt == "--calculate-profile") {
171  options.calculate_profile = true;
172  continue;
173  }
174 
175  if (opt == "-g") {
176  if (i == argc) {
177  throw Setup_error(
178  "'-g' given but no value for true vacuum provided");
179  }
180  const std::string value(argv[i++]);
181  options.global_min = parse_global_min(value);
182  continue;
183  }
184 
185  if (starts_with(opt, "--global-minimum=")) {
186  const std::string value = get_option_value(opt);
187  options.global_min = parse_global_min(value);
188  continue;
189  }
190 
191  if (opt == "-h" || opt == "--help") {
192  print_usage();
193  exit(EXIT_SUCCESS);
194  }
195 
196  if (opt == "-o") {
197  if (i == argc) {
198  throw Setup_error(
199  "'-o' given but no output file name provided");
200  }
201  const std::string filename(argv[i++]);
202  if (starts_with(filename, "-") && filename != "-") {
203  throw Setup_error(
204  "'-o' given but no output file name provided");
205  }
206  options.output_file = filename;
207  continue;
208  }
209 
210  if (starts_with(opt, "--output-file=")) {
211  const std::string filename = get_option_value(opt);
212  if (filename.empty()) {
213  throw Setup_error(
214  "'--output-file=' given but no output file name provided");
215  }
216  options.output_file = filename;
217  continue;
218  }
219 
220  if (opt == "-P") {
221  if (i == argc) {
222  throw Setup_error(
223  "'-P' given but no file name provided");
224  }
225  const std::string filename(argv[i++]);
226  if (starts_with(filename, "-") && filename != "-") {
227  throw Setup_error(
228  "'-P' given but no file name provided");
229  }
230  options.perturbations_file = filename;
231  continue;
232  }
233 
234  if (starts_with(opt, "--perturbations-file=")) {
235  const std::string filename = get_option_value(opt);
236  if (filename.empty()) {
237  throw Setup_error(
238  "'--perturbations-file=' given but no file name provided");
239  }
240  options.perturbations_file = filename;
241  continue;
242  }
243 
244  if (opt == "-p" || opt == "--perturbative") {
245  options.use_perturbative = true;
246  continue;
247  }
248 
249  if (opt == "-v" || opt == "--verbose") {
250  options.verbose = true;
251  continue;
252  }
253 
254  throw Setup_error(
255  "unrecognized command line argument '" + opt + "'");
256  }
257 
258  parse_positional_args(positional_args, options);
259 
260  return options;
261 }
262 
263 std::tuple<double, Field_profiles> solve_shooting(
264  const Logarithmic_potential& potential, double true_min,
265  bool calculate_profile)
266 {
267  const double false_min = potential.get_local_minimum_location();
268  const double barrier = potential.get_local_maximum_location();
269 
270  const int dim = 4;
271 
272  unsigned int options
273  = calculate_profile ?
274  (Shooting::Solver_options::Compute_action |
275  Shooting::Solver_options::Compute_profile)
276  : Shooting::Solver_options::Compute_action;
277 
278  double action = 0.;
279  Field_profiles profile;
280 
281  Shooting profiler;
282  profiler.solve(potential, false_min, true_min, barrier, dim,
283  options);
284 
285  if ((options & Shooting::Solver_options::Compute_action) != 0) {
286  action = profiler.get_euclidean_action();
287  }
288 
289  if ((options & Shooting::Solver_options::Compute_profile) != 0) {
290  profile = profiler.get_bubble_profile();
291  }
292 
293  return std::make_tuple(action, profile);
294 }
295 
296 std::tuple<double, Field_profiles> solve_perturbative(
297  Logarithmic_potential& potential, double true_min,
298  const std::string& observer_file)
299 {
301 
302  RK4_perturbative_profiler profiler;
303 
304  profiler.set_initial_step_size(1.e-3);
305 
306  profiler.set_initial_guesser(std::make_shared<Kink_profile_guesser>());
307 
308  const double action_tol = 1.e-3;
309  const double fields_tol = 1.e-3;
310  profiler.set_convergence_tester(
311  std::make_shared<Relative_convergence_tester>(
312  action_tol, fields_tol));
313 
314  auto root_finder = std::make_shared<Root_finder>();
315  profiler.set_root_finder(root_finder);
316 
317  const int dim = 4;
318 
319  Eigen::VectorXd true_vacuum(1);
320  true_vacuum << true_min;
321 
322  Eigen::VectorXd false_vacuum(1);
323  false_vacuum << potential.get_local_minimum_location();
324 
325  profiler.set_number_of_dimensions(dim);
326  profiler.set_true_vacuum_loc(true_vacuum);
327  profiler.set_false_vacuum_loc(false_vacuum);
328 
329  double action = 0.;
330  Field_profiles profile;
331 
332  if (observer_file.empty()) {
333  profiler.calculate_bubble_profile(potential);
334  } else {
335  Logarithmic_observer observer(potential, observer_file);
336  profiler.calculate_bubble_profile(potential, observer);
337  }
338  action = profiler.get_euclidean_action();
339  profile = profiler.get_bubble_profile();
340 
341  return std::make_tuple(action, profile);
342 }
343 
344 void write_profile(std::ostream& ostr, const Field_profiles& numerical_profile,
345  const Field_profiles& exact_profile)
346 {
347  ostr << "# "
348  << std::setw(16) << "rho" << ' '
349  << std::setw(16) << "numeric" << ' '
350  << std::setw(16) << "exact" << std::endl;
351 
352  const auto n_grid_points = numerical_profile.get_number_of_grid_points();
353  if (n_grid_points != exact_profile.get_number_of_grid_points()) {
354  throw Setup_error(
355  "number of grid points do not match in numerical and exact solution");
356  }
357 
358  const auto rho_values = numerical_profile.get_spatial_grid();
359  const auto numerical_values = numerical_profile.get_field_profiles();
360  const auto exact_values = exact_profile.get_field_profiles();
361 
362  for (int i = 0; i < n_grid_points; ++i) {
363  ostr << " "
364  << std::setw(16) << std::setprecision(8)
365  << std::scientific << rho_values(i) << ' '
366  << std::setw(16) << std::setprecision(8)
367  << std::scientific << numerical_values(i, 0) << ' '
368  << std::setw(16) << std::setprecision(8)
369  << std::scientific << exact_values(i, 0) << std::endl;
370  }
371 }
372 
373 void write_action(std::ostream& ostr, double numerical_action,
374  double exact_action)
375 {
376  const double rel_diff = (numerical_action - exact_action)
377  / (0.5 * (numerical_action + exact_action));
378 
379  ostr << "# Numerical action = "
380  << std::setprecision(8) << std::scientific << numerical_action
381  << std::endl;
382  ostr << "# Exact action = "
383  << std::setprecision(8) << std::scientific << exact_action
384  << std::endl;
385  ostr << "# Relative error = "
386  << std::setprecision(8) << std::scientific << rel_diff
387  << std::endl;
388 }
389 
390 } // namespace BubbleProfiler
391 
392 int main(int argc, const char* argv[])
393 {
394  using namespace BubbleProfiler;
395 
396  if (argc == 1) {
397  std::cerr << "Usage: logarithmic [OPTION] <m> <w>\n"
398  << "Try 'logarithmic --help' for more information."
399  << std::endl;
400  return EXIT_FAILURE;
401  }
402 
403  int exit_code = 0;
404  try {
405  Logarithmic_options options = parse_cmd_line_args(argc, argv);
406 
407  if (options.global_min <= 0.) {
408  options.global_min = 10. * std::abs(options.w);
409  }
410 
411  if (options.verbose) {
414  }
415 
416  Logarithmic_potential potential(options.m, options.w);
417 
418  // Sanity check on potential
419  const double local_min = potential.get_local_minimum_location();
420  if (potential(options.global_min) > potential(local_min)) {
421  throw Setup_error(
422  "true minimum of potential greater than false minimum");
423  }
424 
425  std::tuple<double, Field_profiles> result;
426  if (options.use_perturbative) {
427  result = solve_perturbative(potential, options.global_min,
428  options.perturbations_file);
429  } else {
430  result = solve_shooting(potential, options.global_min,
431  options.calculate_profile);
432  }
433 
434  std::ofstream output_file;
435  if (!options.output_file.empty()) {
436  output_file.open(options.output_file, std::ios::out);
437  }
438 
439  std::ostream& output_stream
440  = (options.output_file.empty() ? std::cout : output_file);
441 
442  if (options.calculate_profile) {
443  const Field_profiles profiles = std::get<1>(result);
444  const Field_profiles exact_profile
445  = potential.get_profile(profiles.get_spatial_grid());
446  write_profile(output_stream, std::get<1>(result), exact_profile);
447  }
448 
449  const double exact_action = potential.get_action();
450  write_action(output_stream, std::get<0>(result), exact_action);
451  } catch (const Setup_error& e) {
452  std::cerr << "Error: " << e.what() << std::endl;
453  exit_code = EXIT_FAILURE;
454  } catch (const BVP_solver_error& e) {
455  std::cerr << "Error: " << e.what() << std::endl;
456  exit_code = EXIT_FAILURE;
457  } catch (const Numerical_error& e) {
458  std::cerr << "Error: " << e.what() << std::endl;
459  exit_code = EXIT_FAILURE;
460  } catch (const Error& e) {
461  std::cerr << "Error: " << e.what() << std::endl;
462  exit_code = EXIT_FAILURE;
463  } catch (...) {
464  std::cerr << "Error: unrecognized error occurred."
465  << std::endl;
466  exit_code = EXIT_FAILURE;
467  }
468 
469  return exit_code;
470 }
contains the definition of the Field_profiles clas
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 solve(const std::function< double(double)> &potential_, const std::function< double(double)> &potential_first_, const std::function< double(double)> &potential_second_, double false_min_, double true_min_, double barrier_, int dim_=3, unsigned int options=(Solver_options::Compute_action|Solver_options::Compute_profile))
Definition: shooting.cpp:81
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)
auto abs(const Eigen::MatrixBase< Derived > &m) -> decltype(m.cwiseAbs())
static Logging_manager & get_manager()
const Field_profiles & get_bubble_profile() const
Definition: shooting.cpp:48
double get_euclidean_action() const
Definition: shooting.cpp:40
std::tuple< double, Field_profiles > solve_shooting(const Generalized_fubini_potential &potential, double true_min, bool calculate_profile)
void write_action(double action, std::ostream &ostr)
Write the value of the action to requested output stream.
Field_profiles get_profile(const Eigen::VectorXd &) const
int main(int argc, const char *argv[])
double parse_global_min(const std::string &value)
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)
Exception indicating generic numerical error.
Definition: error.hpp:116
const Field_profiles & get_bubble_profile() const
Retrieve the field profiles after running calculate_bubble_profile.
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.