BubbleProfiler  0.3.0
by Peter Athron, Csaba Balazs, Michael Bardsley, Andrew Fowlie, Dylan Harries & Graham White
gaussian_potential.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 "gaussian_potential.hpp"
24 #include "error.hpp"
25 #include "math_wrappers.hpp"
26 
27 #include <cmath>
28 
29 namespace BubbleProfiler {
30 
32  double gamma_, double lambda_, std::size_t n_fields_)
33  : gamma(gamma_)
34  , lambda(lambda_)
35  , n_fields(n_fields_)
36 {
37  if (gamma <= 1) {
38  throw Setup_error(
39  "Gamma must be > 1 so that the origin is a false vacuum.");
40  }
41 
42  origin = Eigen::VectorXd::Zero(n_fields);
44  mu = Eigen::VectorXd::Zero(n_fields);
45 
46  for (std::size_t i = 0; i < n_fields; ++i) {
47  mu(i) = lambda / std::sqrt(n_fields);
48  }
49 
50  basis_transform = Eigen::MatrixXd::Identity(n_fields, n_fields);
51 }
52 
53 double Gaussian_potential::gaussian(const Eigen::VectorXd& coords,
54  const Eigen::VectorXd& mu) const
55 {
56  double exponent = -0.5*std::pow((coords - mu).norm(), 2);
57  return std::pow(2 * Pi, -(n_fields / 2.0)) * std::exp(exponent);
58 }
59 
61  const Eigen::VectorXd& coords, const Eigen::VectorXd& mu, int i) const
62 {
63  double exponent = -0.5*std::pow((coords - mu).norm(), 2);
64  return -std::pow(2 * Pi, -(n_fields / 2.0))
65  * (coords(i) - mu(i)) * std::exp(exponent);
66 }
67 
69  const Eigen::VectorXd& coords, const Eigen::VectorXd& mu,
70  int i, int j) const
71 {
72  double exponent = -0.5*std::pow((coords - mu).norm(), 2);
73  double delta_ij = i == j ? 1.0 : 0.0;
74  return -std::pow(2 * Pi, -(n_fields / 2.0))
75  *(delta_ij - (coords(i) - mu(i))*(coords(j) - mu(j)))*std::exp(exponent);
76  }
77 
78 double Gaussian_potential::operator()(const Eigen::VectorXd& coords) const
79 {
80  Eigen::VectorXd transformed_coords =
82  return -(gaussian(transformed_coords, origin) +
83  gamma*gaussian(transformed_coords, mu)) + constant_term;
84 }
85 
86 double Gaussian_potential::partial(const Eigen::VectorXd &coords, int i) const
87 {
88  Eigen::VectorXd transformed_coords =
90 
91  // Vector of partials in original basis
92  Eigen::VectorXd orig_partials(n_fields);
93  for (std::size_t j = 0; j < n_fields; ++j) {
94  orig_partials(j) = (-1.0)*(
95  gaussian_deriv(transformed_coords, origin, j) +
96  gamma*gaussian_deriv(transformed_coords, mu, j));
97  }
98 
99  // Transform these to the current basis
100  Eigen::VectorXd partials = (basis_transform.transpose()) * orig_partials;
101  return partials(i);
102 }
103 
105  const Eigen::VectorXd& coords, int i, int j) const
106 {
107  Eigen::VectorXd transformed_coords =
108  (basis_transform * coords) + origin_translation;
109 
110  double partial2 = 0;
111 
112  for (std::size_t k = 0; k < n_fields; ++k) {
113  for (std::size_t l = 0; l < n_fields; ++l) {
114  double orig_partial = -(
115  gaussian_deriv2(transformed_coords, origin, k, l) +
116  gamma*gaussian_deriv2(transformed_coords, mu, k, l));
117  partial2 += orig_partial *
118  basis_transform.transpose()(i, k)*basis_transform.transpose()(j,l);
119  }
120  }
121 
122  return partial2;
123 }
124 
125 
126 void Gaussian_potential::translate_origin(const Eigen::VectorXd& translation)
127 {
128  origin_translation = translation;
129 }
130 
131 void Gaussian_potential::apply_basis_change(const Eigen::MatrixXd &new_basis)
132 {
133  // Note we use the inverse transform on incoming coordinates!
134  basis_transform = basis_transform * (new_basis.transpose());
135 }
136 
138 {
139  constant_term += constant;
140 }
141 
143 {
144  return n_fields;
145 }
146 
147 } // namespace BubbleProfiler
virtual void apply_basis_change(const Eigen::MatrixXd &) override
Apply a change of basis matrix.
virtual double operator()(const Eigen::VectorXd &coords) const override
Evaluate potential at point.
contains definitions of Gaussian_potential class
double gaussian_deriv(const Eigen::VectorXd &, const Eigen::VectorXd &, int i) const
virtual double partial(const Eigen::VectorXd &coords, int i) const override
Partial derivative WRT coordinate i at a point.
virtual void add_constant_term(double) override
Add a constant offset to the potential.
Gaussian_potential(double gamma_, double lambda_, std::size_t n_fields_)
instantiate a new Gaussian potential
Exception indicating general setup error.
Definition: error.hpp:32
double gaussian(const Eigen::VectorXd &, const Eigen::VectorXd &) const
virtual std::size_t get_number_of_fields() const override
double gaussian_deriv2(const Eigen::VectorXd &, const Eigen::VectorXd &, int i, int j) const
virtual void translate_origin(const Eigen::VectorXd &) override
Shift the location of the origin by a specified vector.