31 #include <boost/math/tools/minima.hpp> 43 throw Error(
"Shooting::get_euclidean_action: action not computed");
51 throw Error(
"Shooting::get_bubble_profile: bubble profile not computed");
57 const std::function<
double(
double)>& potential_,
58 const std::function<
double(
double)>& potential_first_,
59 const std::function<
double(
double)>& potential_second_,
60 double false_min_,
double true_min_,
double barrier_,
int dim_)
82 const std::function<
double(
double)>& potential_,
83 const std::function<
double(
double)>& potential_first_,
84 const std::function<
double(
double)>& potential_second_,
85 double false_min_,
double true_min_,
double barrier_,
int dim_,
88 if (dim_ != 3 && dim_ != 4) {
89 throw Setup_error(
"spacetime dimension must be 3 or 4");
95 bool compute_action = (options & Solver_options::Compute_action) != 0;
96 bool compute_profile = (options & Solver_options::Compute_profile) != 0;
98 if (!compute_action && !compute_profile) {
103 potential_second_, false_min_,
104 true_min_, barrier_, dim_);
114 if (compute_action) {
122 if (compute_profile) {
129 double true_min_,
double barrier_,
int dim_,
130 unsigned int options)
133 throw Setup_error(
"potential must be one dimensional");
136 const auto potential_func = [&potential_](
double phi) {
137 Eigen::VectorXd fields(1);
139 return potential_(fields);
142 const auto potential_first_ = [&potential_](
double phi) {
143 Eigen::VectorXd fields(1);
145 return potential_.
partial(fields, 0);
148 const auto potential_second_ = [&potential_](
double phi) {
149 Eigen::VectorXd fields(1);
151 return potential_.
partial(fields, 0, 0);
154 solve(potential_func, potential_first_, potential_second_,
155 false_min_, true_min_, barrier_, dim_, options);
165 double d2Vdphi2)
const 169 const double prefactor =
Abs(dVdphi / d2Vdphi2);
174 if (change / prefactor >
f_y_max) {
178 y =
asinch(1. + change / prefactor);
180 }
else if (
dim == 4) {
181 if (change / prefactor >
f_y_max) {
183 y = 0.5 *
Log(27. * Pi / 16.)
191 y =
asinc(1. - change / prefactor);
192 }
else if (
dim == 4) {
201 double dVdphi,
double d2Vdphi2)
const 205 const double prefactor =
Abs(dVdphi / d2Vdphi2);
206 const double mass =
Sqrt(
Abs(d2Vdphi2));
207 const double rho = y / mass;
212 const double sinch_y = 1. + change / prefactor;
215 }
else if (sinch_y - 1. <
f_y_min) {
220 }
else if (
dim == 4) {
221 const double f_y = 0.5 * change / prefactor;
232 const double sinc_y = 1. - change / prefactor;
236 v = -
sign_min * prefactor / rho * (
Cos(y) - sinc_y);
238 }
else if (
dim == 4) {
239 const double f_y = 0.5 * change / prefactor;
253 const double phi_zero =
unmap(lambda);
258 const double mass =
Sqrt(
Abs(mass_squared));
262 const double rho = y / mass;
265 const double x = phi_zero +
sign_min * change;
269 if (std::isnan(rho) || std::isnan(x) || std::isnan(v)) {
271 "Could not evolve fields with approximate solution");
274 return {{rho, x, v}};
280 return 2. * Pi /
Sqrt(-mass_squared);
290 constexpr
double over = 1.;
291 constexpr
double under = -1.;
293 const double phi_zero =
unmap(lambda);
297 if (std::isinf(lambda)) {
305 const double x = phi_zero;
307 const bool no_energy =
energy(x, v) < 0.;
318 return this->
ode(x, dxdt, rho);
324 double rho = evolved[0];
330 for (
int iter = 0; iter <
iter_max; ++iter) {
332 if (rho >= rho_max ||
333 Abs(drho) <= std::numeric_limits<double>::epsilon()) {
335 "Could not determine whether shot was an undershot or " 336 "overshot in shoot");
339 const double x = y[0];
340 const double v = y[1];
351 const bool no_energy =
energy(x, v) < 0.;
358 const bool undershot =
sign_min * v < 0.;
371 throw Numerical_error(
"Could not determine whether shot was an undershot or " 372 "overshot in shoot");
382 const auto shoot_ = [
this](
double l) {
return this->
shoot(l); };
383 std::pair<double, double> solution;
392 for (
int iter = 0; iter <
iter_max; ++iter) {
394 solution = boost::math::tools::bisect(shoot_, lower, upper, stop);
395 }
catch (boost::exception & e) {
401 return 0.5 * (solution.first + solution.second);
405 + std::to_string(iter_max)
406 +
" attempts extending the range.");
411 return pow(dot_phi, 2) * pow(rho,
dim - 1) /
dim;
416 const double phi_zero =
unmap(lambda);
422 return this->
ode(x, dxdt, rho);
428 double rho = evolved[0];
438 double action_no_prefactor =
interior(lambda);
442 for (iter = 0; iter <
iter_max; ++iter) {
444 if (rho >= rho_max ||
445 Abs(drho) <= std::numeric_limits<double>::epsilon()) {
447 "Could not determine whether shot was an undershot or " 448 "overshot in action");
453 const bool undershot =
sign_min * v < 0.;
457 if (overshot || undershot || arrived) {
462 const double rho_a = rho;
473 action_no_prefactor += 0.5 * (f_a + f_b) * (rho - rho_a);
479 if (iter == iter_max) {
481 "Could not determine whether shot was an undershot or " 482 "overshot in action");
492 const double phi_zero =
unmap(lambda);
494 double rho_crit = evolved[0];
498 return this->
ode(x, dxdt, rho);
501 std::vector<double> rho_vals = {rho_crit};
502 std::vector<double> field_vals = {y[0]};
505 double rho = rho_crit;
512 for (iter = 0; iter <
iter_max; ++iter) {
514 if (rho >= rho_max ||
515 Abs(drho) <= std::numeric_limits<double>::epsilon()) {
517 "Could not determine whether shot was an undershot or " 518 "overshot in profile");
523 const bool undershot =
sign_min * y[1] < 0.;
527 if (overshot || undershot || arrived) {
532 while (profiles_stepper.try_step(ode_, y, rho, drho)) {
535 rho_vals.push_back(rho);
536 field_vals.push_back(y[0]);
539 if (iter == iter_max) {
541 "Could not determine whether shot was an undershot or " 542 "overshot in profile");
546 const std::size_t num_integration_points = rho_vals.size();
547 const std::size_t num_interior_points = num_integration_points / 2;
548 const double rho_step = rho_crit / num_interior_points;
550 Eigen::VectorXd rho_values(Eigen::VectorXd::Zero(num_interior_points
551 + num_integration_points));
552 Eigen::MatrixXd field_values(
553 Eigen::MatrixXd::Zero(num_interior_points + num_integration_points, 1));
554 for (std::size_t i = 0; i < num_interior_points; ++i) {
555 rho_values(i) = i * rho_step;
558 }
catch (
const std::overflow_error & e) {
560 "bubble profile in bubble interior");
564 rho_values.segment(num_interior_points, num_integration_points)
565 = Eigen::VectorXd::Map(rho_vals.data(), num_integration_points);
566 field_values.bottomRows(num_integration_points)
567 = Eigen::VectorXd::Map(field_vals.data(), num_integration_points);
579 const double phi_zero =
unmap(lambda);
592 if (
Abs(prime_start) <= std::numeric_limits<double>::epsilon()) {
595 const double prefactor = prime_start / mass_squared;
597 const double y = rho *
Sqrt(
Abs(mass_squared));
598 double delta_phi = 0.;
599 if (mass_squared > 0) {
601 delta_phi = prefactor * (
Sinh(y) / y - 1.);
603 delta_phi = prefactor * (2. *
BesselI(1, y) / y - 1.);
607 delta_phi = prefactor * (
Sin(y) / y - 1.);
609 delta_phi = prefactor * (2. *
BesselJ(1, y) / y - 1.);
613 return phi_zero + delta_phi;
618 const double phi_zero =
unmap(lambda);
621 const double prefactor =
Abs(prime_start / mass_squared);
622 const double mass =
Sqrt(
Abs(mass_squared));
625 const double rho = evolved[0];
626 const double y = mass * rho;
629 if (mass_squared > 0.) {
632 value = (change * change) / (6. * mass);
634 value = (prefactor * prefactor) / (6. * mass_squared * rho)
635 * (1. + mass_squared * (rho * rho)
636 -
Cosh(2. * y) + 0.5 * y *
Sinh(2. * y));
638 }
else if (
dim == 4) {
640 value = 1.6875 * (change * change) / mass_squared;
642 const double bessel_1_y =
BesselI(1, y);
643 const double bessel_2_y =
BesselI(2, y);
644 value = 0.5 * (prefactor * prefactor) * rho / mass *
645 (-y * (bessel_1_y * bessel_1_y)
646 + 4. * bessel_1_y * bessel_2_y
647 + y * (bessel_2_y * bessel_2_y));
652 value = (prefactor * prefactor) / (6. *
Abs(mass_squared) * rho)
653 * (-1. +
Abs(mass_squared) * (rho * rho)
654 +
Cos(2. * y) + 0.5 * y *
Sin(2. * y));
655 }
else if (
dim == 4) {
656 const double bessel_1_y =
BesselJ(1, y);
657 const double bessel_2_y =
BesselJ(2, y);
658 value = 0.5 * (prefactor * prefactor) * rho / mass *
659 (y * (bessel_1_y * bessel_1_y)
660 - 4. * bessel_1_y * bessel_2_y
661 + y * (bessel_2_y * bessel_2_y));
evolve_type evolve(double lambda) const
Uses an approximation solution to evolve the system forward until the field changes by a required amo...
boost::array< double, 2 > state_type
double approx_root_neg_4(double a)
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))
double calculate_roll_velocity(double lambda, double y, double dVdphi, double d2Vdphi2) const
Find velocity .
auto BesselI(Order v, Argument z) -> decltype(boost::math::cyl_bessel_i(v, z))
boost::numeric::odeint::runge_kutta_dopri5< state_type > error_stepper_type
virtual double partial(const Eigen::VectorXd &coords, int i) const =0
Partial derivative WRT coordinate i at a point.
controlled_stepper_type action_stepper
double approx_root_pos_4(double a)
const Field_profiles & get_bubble_profile() const
Field_profiles calculate_bubble_profile(double lambda)
double get_euclidean_action() const
double interior(double lambda)
auto BesselJ(Order v, Argument z) -> decltype(boost::math::cyl_bessel_j(v, z))
double action_arrived_rel
double quadratic_potential_solution(double) const
double shooting()
Solve for by bisection.
double calculate_roll_time(double lambda, double dVdphi, double d2Vdphi2) const
Find the (dimensionless) time at which the field changes by a small amount, .
std::function< double(double)> potential_first
double bubble_scale() const
Characteristic scale of bubble.
boost::array< double, 3 > evolve_type
double action(double lambda)
void initialize_potential_parameters(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_)
std::function< double(double)> potential_second
void ode(const state_type &x, state_type &dxdt, double rho)
ODE for bounce solution.
double shoot(double lambda)
Performs a single shot of our shooting method.
double area_n_sphere(int n)
double integrand(double dot_phi, double rho) const
Action integrand from kinetic term without pre-factor.
virtual std::size_t get_number_of_fields() const =0
Exception indicating general setup error.
double energy(double phi, double dot_phi) const
Numerical functions for one-dimensional shooting method and area of -sphere.
double unmap(double lambda) const
One-dimensional shooting method.
std::function< double(double)> potential
Abstract base class for a generic potential.
boost::numeric::odeint::controlled_runge_kutta< error_stepper_type > controlled_stepper_type
Exception indicating generic numerical error.
Discretized set of field profiles.
controlled_stepper_type shoot_stepper