18 #ifndef BUBBLEPROFILER_GENERIC_PERTURBATIVE_PROFILER_HPP_INCLUDED 19 #define BUBBLEPROFILER_GENERIC_PERTURBATIVE_PROFILER_HPP_INCLUDED 70 template <
class Integration_policy>
115 template <
class Observer>
141 std::make_shared<Kink_profile_guesser>()};
143 std::make_shared<Relative_convergence_tester>()};
145 std::make_shared<GSL_root_finder<Eigen::Dynamic> >()};
157 Eigen::VectorXd&,
double)
const;
158 template <
class Observer>
160 Eigen::VectorXd&,
double, Observer)
const;
168 template <
class Integration_policy>
176 template <
class Integration_policy>
177 template <
class Observer>
179 Potential& potential, Observer& observer)
206 bool converged =
false;
207 while (
iteration < max_iterations && !converged) {
212 perturbations =
Field_profiles(std::get<0>(result), std::get<1>(result),
232 template <
class Integration_policy>
236 throw Domain_error(
"radial coordinates must be non-negative");
241 template <
class Integration_policy>
245 throw Domain_error(
"radial coordinates must be non-negative");
250 template <
class Integration_policy>
254 throw Setup_error(
"integration step size must be positive");
259 template <
class Integration_policy>
264 throw Setup_error(
"Perturbative_profiler::check_setup: " 265 "no convergence tester provided");
269 throw Setup_error(
"Perturbative_profiler::check_setup: " 270 "no profile guesser provided");
274 throw Setup_error(
"Perturbative_profiler::check_setup: " 275 "no root finder provided");
282 template <
class Integration_policy>
291 return guesser->get_profile_guess(potential, true_vacuum_,
n_dims,
296 template <
class Integration_policy>
302 template <
class Integration_policy>
309 template <
class Integration_policy>
310 std::tuple<Eigen::VectorXd, Eigen::MatrixXd>
319 Eigen::VectorXd domain_start_derivs(
n_fields);
320 for (
auto i = 0; i <
n_fields; ++i) {
324 const auto boundary_conditions =
325 [
n_fields, &domain_start_derivs, &domain_end_values]
326 (
const Eigen::VectorXd& start_state,
const Eigen::VectorXd& end_state) {
327 Eigen::VectorXd values(2 * n_fields);
329 values.segment(0, n_fields)
330 = end_state.segment(0, n_fields) + domain_end_values;
331 values.segment(n_fields, n_fields)
332 = start_state.segment(n_fields, n_fields) + domain_start_derivs;
340 const auto calculate_errors
341 = [
this, &system, &boundary_conditions, step_size](
342 const Eigen::VectorXd& start_state) {
343 Eigen::VectorXd end_state(start_state);
347 return boundary_conditions(start_state, end_state);
350 Eigen::VectorXd initial_guess(Eigen::VectorXd::Zero(2 * n_fields));
351 initial_guess.segment(n_fields, n_fields) -= domain_start_derivs;
353 const auto status =
root_finder->find_root(calculate_errors, initial_guess);
356 "unable to solve boundary value problem");
359 const Eigen::VectorXd domain_start_perturbations(
361 Eigen::VectorXd domain_end_perturbations(domain_start_perturbations);
363 std::vector<double> coord_values;
364 std::vector<Eigen::VectorXd> perturbation_values;
366 auto observer = [
n_fields, &coord_values, &perturbation_values](
367 const Eigen::VectorXd& state,
double rho) {
368 Eigen::VectorXd solution_values(
369 Eigen::VectorXd::Map(state.data(),
n_fields));
370 perturbation_values.push_back(solution_values);
371 coord_values.push_back(rho);
374 integrate_ivp(system, domain_end_perturbations, step_size, observer);
378 const int n_perturbation_points = coord_values.size();
379 const Eigen::VectorXd grid_points(
380 Eigen::VectorXd::Map(coord_values.data(), n_perturbation_points));
381 Eigen::MatrixXd perturbations(n_perturbation_points, n_fields);
382 for (
int i = 0; i < n_perturbation_points; ++i) {
383 perturbations.row(i) = perturbation_values[i];
386 return std::make_tuple(grid_points, perturbations);
389 template <
class Integration_policy>
391 const Eigen::VectorXd& new_grid,
const Eigen::MatrixXd& perturbations)
396 const int n_updated_points = new_grid.size();
397 const int n_fields = perturbations.cols();
402 const int n_old = old_grid.size();
403 const double old_domain_start = old_grid(0);
404 const double old_domain_end = old_grid(n_old - 1);
406 const int n_before = (new_grid.array() < old_domain_start).count();
407 const int n_after = (new_grid.array() > old_domain_end).count();
408 const int extended_grid_size = n_before + n_old + n_after;
409 Eigen::VectorXd extended_grid(extended_grid_size);
410 Eigen::MatrixXd extended_profiles(extended_grid_size, n_fields);
412 for (
int i = 0; i < n_before; ++i) {
413 extended_grid(i) = new_grid(i);
414 extended_profiles.block(0, 0, n_before, n_fields).rowwise()
415 = old_profiles.row(0);
417 extended_grid.segment(n_before, n_old) = old_grid;
418 extended_profiles.block(n_before, 0, n_old, n_fields) = old_profiles;
421 int offset = new_grid.size();
422 while (new_grid(offset - 1) > old_domain_end) {
426 for (
int i = 0; i < n_after; ++i) {
427 extended_grid(n_before + n_old + i) = new_grid(offset + i);
428 extended_profiles.block(n_before + n_old, 0, n_after, n_fields).rowwise()
429 = old_profiles.row(n_old - 1);
433 Eigen::MatrixXd interpolated_profiles(n_updated_points, n_fields);
434 for (
int i = 0; i <
n_fields; ++i) {
436 extended_grid, extended_profiles.col(i), new_grid);
439 const Eigen::MatrixXd new_profiles = interpolated_profiles + perturbations;
449 template <
class Integration_policy>
452 Eigen::VectorXd& perturbations,
double step_size)
const 454 const auto dummy_observer = [](
const Eigen::VectorXd&, double) {};
455 integrate_ivp(system, perturbations, step_size, dummy_observer);
458 template <
class Integration_policy>
459 template <
class Observer>
462 Eigen::VectorXd& perturbations,
double step_size, Observer observer)
const 464 Integration_policy::integrate_system(system, perturbations,
contains the definition of the Field_profiles clas
contains helper functions for calculating the Euclidean action
double get_domain_end() const
Exception indicating failure to integrate BVP.
void calculate_bubble_profile(Potential &, Observer &)
A default observer that does not perform any actions when called.
void set_initial_guesser(std::shared_ptr< Profile_guesser > g)
double derivative_at(int field, int order, double rho) const
Take the radial derivative of a field at a given radius.
const Eigen::VectorXd & get_spatial_grid() const
Get a vector of the grid point coordinates.
Exception indicating failure of iterative procedure to converge.
void set_false_vacuum_loc(const Eigen::VectorXd &fv)
Exception indicating function evaluation out of allowed domain.
void integrate_system_to(const Perturbations_ODE_system &, double rho) const
void set_true_vacuum_loc(const Eigen::VectorXd &tv)
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.
double get_domain_start() const
void set_convergence_tester(std::shared_ptr< Profile_convergence_tester > ct)
void log_message(Log_level level, const std::string &msg) const
void integrate_ivp(const Perturbations_ODE_system &, Eigen::VectorXd &, double) const
void set_domain_start(double start)
void update_field_profiles(const Eigen::VectorXd &, const Eigen::MatrixXd &)
std::shared_ptr< Root_finder< Eigen::VectorXd > > root_finder
int get_max_iterations() const
void set_number_of_dimensions(int d)
Eigen::VectorXd evaluate_at(double rho) const
Get all field values at a given radius.
Field_profiles construct_initial_profiles(Potential &) const
Eigen::VectorXd interpolate_f_at(const Eigen::VectorXd &x_old, const Eigen::VectorXd &y_old, const Eigen::VectorXd &x_new)
Computes interpolated function values at a new set of grid points.
contains the definition of the GSL_interpolator class
std::shared_ptr< Profile_guesser > guesser
void set_interpolation_points_fraction(double f)
void set_domain_end(double end)
double interpolation_points_fraction
std::tuple< Eigen::VectorXd, Eigen::MatrixXd > calculate_perturbation(Potential &)
Eigen::VectorXd true_vacuum
bool check_convergence(const Potential &) const
int get_number_of_fields() const
logging::Basic_logger logger
Exception indicating general setup error.
void set_number_of_dimensions(int d)
std::shared_ptr< Profile_convergence_tester > convergence_tester
Eigen::VectorXd false_vacuum
Abstract base class for a generic potential.
void set_initial_step_size(double h)
virtual void translate_origin(const Eigen::VectorXd &translation)=0
Shift the location of the origin by a specified vector.
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.
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.
void check_setup(Potential &) const
Class implementing the system of ODEs obeyed by profile perturbations.