Skip to content

Commit aa27b96

Browse files
author
Roberto Di Remigio
committed
Merge branch 'Rob-green_spherical' of gitlab.com:PCMSolver/pcmsolver into Rob-green_spherical
2 parents 665c1e8 + 9a9261a commit aa27b96

File tree

5 files changed

+126
-66
lines changed

5 files changed

+126
-66
lines changed

src/bin/plot_green_spherical.cpp

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "UniformDielectric.hpp"
1515

1616
std::vector<double> generate_grid(double, double, size_t);
17-
std::string header();
1817
void case1();
1918
void case2();
2019
void case3();
@@ -40,59 +39,48 @@ std::vector<double> generate_grid(double min_val, double max_val, size_t nPoints
4039
return grid;
4140
}
4241

43-
std::string header()
44-
{
45-
std::stringstream tmp;
46-
tmp << "#" << '\t' << "x_2" << '\t' << "z_2" << '\t';
47-
tmp << "gf_value" << '\t' << "image" << '\t' << "Coulomb" << '\t';
48-
tmp << "derivativeProbe" << '\t' << "der_image" << '\t' << "der_Coulomb" << std::endl;
49-
return tmp.str();
50-
}
51-
5242
void case1()
5343
{
54-
size_t nPoints = 100;
44+
size_t nPoints = 200;
5545
double epsInside = 80.0;
5646
double epsOutside = 2.0;
5747
Eigen::Vector3d sphereCenter = Eigen::Vector3d::Zero();
5848
double sphereRadius = 100.0;
59-
double width = 10.0;
49+
double width = 9.0;
6050

61-
Eigen::Vector3d source;
62-
source << 4.0, 0.0, 85.0;
51+
Eigen::Vector3d source = Eigen::Vector3d::Zero();
6352
Eigen::Vector3d probe = Eigen::Vector3d::Zero();
6453

65-
double x_min = 10.0;
66-
double x_max = 300.0;
67-
std::vector<double> x = generate_grid(x_min, x_max, nPoints);
68-
double z_min = 10.0;
69-
double z_max = 300.0;
54+
double z_min = -20.0;
55+
double z_max = 20.0;
7056
std::vector<double> z = generate_grid(z_min, z_max, nPoints);
57+
double delta = 0.1;
7158

7259
std::ofstream out;
7360

7461
SphericalDiffuse<CollocationIntegrator, OneLayerTanh> gf(epsInside, epsOutside, width, sphereRadius, sphereCenter);
7562
LOG(gf);
7663

7764
out.open("gf_spherical_CASE1.dat");
78-
out << header();
7965
out.precision(16);
8066
for (size_t i = 0; i < nPoints; ++i) {
67+
source << 0.0, 0.0, z[i];
8168
for (size_t j = 0; j < nPoints; ++j) {
82-
probe << x[i], 0.0, z[j];
83-
out << '\t' << x[i]
69+
probe << 0.0, 0.0, (z[j] + delta);
70+
out << '\t' << i
71+
<< '\t' << j
72+
<< '\t' << z[i]
8473
<< '\t' << z[j]
85-
<< '\t' << gf.kernelS(source, probe)
86-
<< '\t' << gf.imagePotential(source, probe)
8774
<< '\t' << gf.Coulomb(source, probe)
88-
<< '\t' << gf.derivativeProbe(Eigen::Vector3d::UnitZ(), source, probe)
89-
<< '\t' << gf.CoulombDerivative(Eigen::Vector3d::UnitZ(), source, probe)
90-
<< '\t' << gf.imagePotentialDerivative(Eigen::Vector3d::UnitZ(), source, probe) << std::endl;
75+
<< '\t' << gf.imagePotential(source, probe)
76+
<< '\t' << gf.kernelS(source, probe)
77+
<< '\t' << (1.0 / gf.coefficientCoulomb(source, probe)) << std::endl;
9178
}
9279
}
9380
out.close();
9481
LOG_TIME;
9582

83+
/*
9684
UniformDielectric<AD_directional, CollocationIntegrator> gf_inside(epsInside);
9785
out.open("gf_uniform_inside_CASE1.dat");
9886
out << "#" << '\t' << "x_2" << '\t' << "z_2" << '\t';
@@ -124,4 +112,5 @@ void case1()
124112
}
125113
}
126114
out.close();
115+
*/
127116
}

src/green/SphericalDiffuse.hpp

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
101101
const Eigen::Vector3d & p1, const Eigen::Vector3d & p2) const
102102
{
103103
double eps_r2 = 0.0;
104-
// Shift p2 by origin_
105-
std::tie(eps_r2, std::ignore) = this->profile_((p2 - this->origin_).norm());
104+
std::tie(eps_r2, std::ignore) = this->epsilon(p2);
106105

107106
return (eps_r2 * this->derivativeProbe(direction, p1, p2));
108107
}
@@ -130,40 +129,30 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
130129
* \param[in] probe location of the probe charge
131130
*/
132131
double coefficientCoulomb(const Eigen::Vector3d & source, const Eigen::Vector3d & probe) const {
133-
double r1 = (source - this->origin_).norm();
134-
double r2 = (probe - this->origin_).norm();
135-
136132
// Obtain coefficient for the separation of the Coulomb singularity
137-
return this->coefficient(r1, r2);
133+
return this->coefficient_impl(source, probe);
138134
}
139135
/*! \brief Returns singular part of the Green's function
140136
* \param[in] source location of the source charge
141137
* \param[in] probe location of the probe charge
142138
*/
143139
double Coulomb(const Eigen::Vector3d & source, const Eigen::Vector3d & probe) const {
144-
Eigen::Vector3d source_shifted = source - this->origin_;
145-
Eigen::Vector3d probe_shifted = probe - this->origin_;
146-
double r1 = source_shifted.norm();
147-
double r2 = probe_shifted.norm();
148-
double r12 = (source_shifted - probe_shifted).norm();
140+
double r12 = (source - probe).norm();
149141

150142
// Obtain coefficient for the separation of the Coulomb singularity
151-
return (1.0 / (this->coefficient(r1, r2) * r12));
143+
return (1.0 / (this->coefficient_impl(source, probe) * r12));
152144
}
153145
/*! \brief Returns non-singular part of the Green's function (image potential)
154146
* \param[in] source location of the source charge
155147
* \param[in] probe location of the probe charge
156148
*/
157149
double imagePotential(const Eigen::Vector3d & source, const Eigen::Vector3d & probe) const {
158-
Eigen::Vector3d source_shifted = source - this->origin_;
159-
Eigen::Vector3d probe_shifted = probe - this->origin_;
160-
161150
// Obtain coefficient for the separation of the Coulomb singularity
162-
double Cr12 = this->coefficient(source_shifted.norm(), probe_shifted.norm());
151+
double Cr12 = this->coefficient_impl(source, probe);
163152

164153
double gr12 = 0.0;
165-
for (int L = 0; L <= maxLGreen_; ++L) {
166-
gr12 += this->functionSummation(L, source_shifted, probe_shifted, Cr12);
154+
for (int L = 1; L <= maxLGreen_; ++L) {
155+
gr12 += this->imagePotentialComponent_impl(L, source, probe, Cr12);
167156
}
168157

169158
return gr12;
@@ -215,7 +204,7 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
215204
}
216205
/*! Handle to the dielectric profile evaluation */
217206
std::tuple<double, double> epsilon(const Eigen::Vector3d & point) const {
218-
return this->profile_((point - this->origin_).norm());
207+
return this->profile_((point + this->origin_).norm());
219208
}
220209
EIGEN_MAKE_ALIGNED_OPERATOR_NEW /* See http://eigen.tuxfamily.org/dox/group__TopicStructHavingEigenMembers.html */
221210
private:
@@ -229,16 +218,14 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
229218
virtual Numerical operator()(Numerical * sp, Numerical * pp) const
230219
{
231220
// Transfer raw arrays to Eigen vectors using the Map type
232-
Eigen::Map<Eigen::Matrix<double, 3, 1> > p1(sp), p2(pp);
233-
Eigen::Vector3d source = p1 - this->origin_;
234-
Eigen::Vector3d probe = p2 - this->origin_;
221+
Eigen::Map<Eigen::Matrix<double, 3, 1> > source(sp), probe(pp);
235222

236223
// Obtain coefficient for the separation of the Coulomb singularity
237-
double Cr12 = this->coefficient(source.norm(), probe.norm());
224+
double Cr12 = this->coefficient_impl(source, probe);
238225

239226
double gr12 = 0.0;
240-
for (int L = 0; L <= maxLGreen_; ++L) {
241-
gr12 += this->functionSummation(L, source, probe, Cr12);
227+
for (int L = 1; L <= maxLGreen_; ++L) {
228+
gr12 += this->imagePotentialComponent_impl(L, source, probe, Cr12);
242229
}
243230
double r12 = (source - probe).norm();
244231

@@ -333,16 +320,18 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
333320
std::vector<RadialFunction> omega_;
334321
/*! \brief Returns L-th component of the radial part of the Green's function
335322
* \param[in] L angular momentum
336-
* \param[in] sp source point, shifted by origin_
337-
* \param[in] pp probe point, shifted by origin_
323+
* \param[in] sp source point
324+
* \param[in] pp probe point
338325
* \param[in] Cr12 Coulomb singularity separation coefficient
339-
* \note This function expects that the source and probe points have been correctly shifted
340-
* to account for the position of the origin of the dielectric sphere.
326+
* \note This function shifts the given source and probe points by the location of the
327+
* dielectric sphere.
341328
*/
342-
double functionSummation(int L, const Eigen::Vector3d & sp, const Eigen::Vector3d & pp, double Cr12) const {
343-
double r1 = sp.norm();
344-
double r2 = pp.norm();
345-
double cos_gamma = sp.dot(pp) / (r1 * r2);
329+
double imagePotentialComponent_impl(int L, const Eigen::Vector3d & sp, const Eigen::Vector3d & pp, double Cr12) const {
330+
Eigen::Vector3d sp_shift = sp + this->origin_;
331+
Eigen::Vector3d pp_shift = pp + this->origin_;
332+
double r1 = sp_shift.norm();
333+
double r2 = pp_shift.norm();
334+
double cos_gamma = sp_shift.dot(pp_shift) / (r1 * r2);
346335
// Evaluate Legendre polynomial of order L
347336
// First of all clean-up cos_gamma, Legendre polynomials
348337
// are only defined for -1 <= x <= 1
@@ -366,7 +355,7 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
366355
double d_omega2 = linearInterpolation(r2, omega_[L][0], omega_[L][2]);
367356

368357
double eps_r2 = 0.0;
369-
std::tie(eps_r2, std::ignore) = this->profile_(r2);
358+
std::tie(eps_r2, std::ignore) = this->profile_(pp_shift.norm());
370359

371360
double denominator = (d_zeta2 - d_omega2) * std::pow(r2, 2) * eps_r2;
372361

@@ -395,10 +384,14 @@ class SphericalDiffuse : public GreensFunction<Numerical, IntegratorPolicy, Prof
395384
*/
396385
RadialFunction omegaC_;
397386
/*! \brief Returns coefficient for the separation of the Coulomb singularity
398-
* \param[in] r1 first point
399-
* \param[in] r2 second point
387+
* \param[in] sp first point
388+
* \param[in] pp second point
389+
* \note This function shifts the given source and probe points by the location of the
390+
* dielectric sphere.
400391
*/
401-
double coefficient(double r1, double r2) const {
392+
double coefficient_impl(const Eigen::Vector3d & sp, const Eigen::Vector3d & pp) const {
393+
double r1 = (sp + this->origin_).norm();
394+
double r2 = (pp + this->origin_).norm();
402395
/* Value of zetaC_ at point with index 1 */
403396
double zeta1 = linearInterpolation(r1, zetaC_[0], zetaC_[1]);
404397
/* Value of zetaC_ at point with index 2 */

src/green/dielectric_profile/OneLayerErf.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class OneLayerErf
6565
* \param[in] point where to evaluate the derivative
6666
*/
6767
double derivative(double point) const {
68-
double factor = (epsilon1_ - epsilon2_) / (width_ * std::sqrt(M_PI));
68+
double factor = (epsilon2_ - epsilon1_) / (width_ * std::sqrt(M_PI));
6969
double t = (point - center_) / width_;
7070
double val = std::exp(-std::pow(t, 2));
7171
return (factor * val); //first derivative of epsilon(r)

src/green/dielectric_profile/OneLayerTanh.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class OneLayerTanh
6464
* \param[in] point where to evaluate the derivative
6565
*/
6666
double derivative(double point) const {
67-
double factor = (epsilon1_ - epsilon2_) / (2.0 * width_);
67+
double factor = (epsilon2_ - epsilon1_) / (2.0 * width_);
6868
double tanh_r = std::tanh((point - center_) / width_);
6969
return (factor * (1 - std::pow(tanh_r, 2))); //first derivative of epsilon(r)
7070
}

src/utils/SplineFunction.hpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* pcmsolver_copyright_start */
2+
/*
3+
* PCMSolver, an API for the Polarizable Continuum Model
4+
* Copyright (C) 2013 Roberto Di Remigio, Luca Frediani and contributors
5+
*
6+
* This file is part of PCMSolver.
7+
*
8+
* PCMSolver is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* PCMSolver is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with PCMSolver. If not, see <http://www.gnu.org/licenses/>.
20+
*
21+
* For information on the complete list of contributors to the
22+
* PCMSolver API, see: <http://pcmsolver.github.io/pcmsolver-doc>
23+
*/
24+
/* pcmsolver_copyright_end */
25+
26+
#ifndef SPLINEFUNCTION_HPP
27+
#define SPLINEFUNCTION_HPP
28+
29+
#include "Config.hpp"
30+
31+
#include <Eigen/Core>
32+
#include <unsupported/Eigen/Splines>
33+
34+
/*! \file SplineFunction.hpp
35+
* \class SplineFunction
36+
* \brief Spline interpolation of a function
37+
* \author Roberto Di Remigio
38+
* \date 2015
39+
*
40+
* Taken from StackOverflow http://stackoverflow.com/a/29825204/2528668
41+
*/
42+
43+
/*! Scale abscissa value to [0, 1] */
44+
inline double scale(double x) {
45+
return (x - xMin_) / (xMax_ - xMin_);
46+
}
47+
48+
/*! Scale abscissa values to [0, 1] */
49+
inline Eigen::RowVectorXd scale(const Eigen::VectorXd & x_vec) {
50+
return x_vec.unaryExpr([](double x) -> double { return scale(x); }).transpose();
51+
}
52+
53+
class SplineFunction
54+
{
55+
private:
56+
typedef Eigen::Spline<double, 1, 3> SplineFit;
57+
public:
58+
/*! \param[in] x vector with abscissa values
59+
* \param[in] y vector with function values
60+
*/
61+
SplineFunction(const Eigen::VectorXd & x, const Eigen::VectorXd & y)
62+
: xMin_(x.minCoeff()), xMax_(x.maxCoeff()),
63+
spline_(Eigen::SplineFitting<SplineFit>::Interpolate(y.transpose(),
64+
std::min<int>(x.rows() - 1, 3), scale(x))
65+
)
66+
{}
67+
/*! \brief Evaluate spline at given point
68+
* \param[in] x evaluation point
69+
*/
70+
double operator()(double x) const {
71+
return spline_(scale(x))(0);
72+
}
73+
private:
74+
double xMin_;
75+
double xMax_;
76+
SplineFit spline_;
77+
};
78+
#endif // SPLINEFUNCTION_HPP

0 commit comments

Comments
 (0)