1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
|
// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: pairExpRDFIntegrator.C,v 1.18 2004/11/07 19:54:59 oliver Exp $
//
#include <BALL/SOLVATION/pairExpRDFIntegrator.h>
#include <limits>
using namespace std;
namespace BALL
{
const char* PairExpRDFIntegrator::Option::VERBOSITY = "verbosity";
const char* PairExpRDFIntegrator::Option::SAMPLES = "samples";
const int PairExpRDFIntegrator::Default::VERBOSITY = 0;
const int PairExpRDFIntegrator::Default::SAMPLES = 30;
PairExpRDFIntegrator::PairExpRDFIntegrator()
: RDFIntegrator(),
alpha_(0.0),
C1_(0.0),
C2_(0.0),
R_ij_o_(0.0),
k1_(0.0),
k2_(0.0)
{
options.setDefaultInteger(Option::VERBOSITY, Default::VERBOSITY);
options.setDefaultInteger(Option::SAMPLES, Default::SAMPLES);
}
PairExpRDFIntegrator::PairExpRDFIntegrator
(const PairExpRDFIntegrator& integrator)
: RDFIntegrator(integrator),
options(integrator.options),
alpha_(integrator.alpha_),
C1_(integrator.C1_),
C2_(integrator.C2_),
R_ij_o_(integrator.R_ij_o_),
k1_(integrator.k1_),
k2_(integrator.k2_)
{
}
PairExpRDFIntegrator::PairExpRDFIntegrator(double alpha, double C1,
double C2, double R_ij_o, double k1, double k2,
const RadialDistributionFunction& rdf)
: RDFIntegrator(rdf),
alpha_(alpha),
C1_(C1),
C2_(C2),
R_ij_o_(R_ij_o),
k1_(k1),
k2_(k2)
{
options.setDefaultInteger(Option::VERBOSITY, Default::VERBOSITY);
options.setDefaultInteger(Option::SAMPLES, Default::SAMPLES);
}
PairExpRDFIntegrator::~PairExpRDFIntegrator()
{
clear();
valid_ = false;
}
void PairExpRDFIntegrator::clear()
{
alpha_ = 0.0;
C1_ = 0.0;
C2_ = 0.0;
R_ij_o_ = 0.0;
k1_ = 0.0;
k2_ = 0.0;
// ?????: options.clear() ?
RDFIntegrator::clear();
}
const PairExpRDFIntegrator& PairExpRDFIntegrator::operator =
(const PairExpRDFIntegrator& integrator)
{
alpha_ = integrator.alpha_;
C1_ = integrator.C1_;
C2_ = integrator.C2_;
R_ij_o_ = integrator.R_ij_o_;
k1_ = integrator.k1_;
k2_ = integrator.k2_;
options = integrator.options;
RDFIntegrator::operator = (integrator);
return *this;
}
void PairExpRDFIntegrator::setConstants(double alpha, double C1, double C2,
double R_ij_o, double k1, double k2)
{
alpha_ = alpha;
C1_ = C1;
C2_ = C2;
R_ij_o_ = R_ij_o;
k1_ = k1;
k2_ = k2;
}
double PairExpRDFIntegrator::integrateToInf(double from) const
{
PiecewisePolynomial poly = getRDF().getRepresentation();
Interval interval;
double FROM;
double val = 0.0;
// In order to get the right interval and coefficients we have to
// project limits
FROM = project(from);
Size k = poly.getIntervalIndex(FROM);
if (k == INVALID_Position)
{
// no error message, because getIntervalIndex() handles this
return 0.0;
}
// now build the interval we want to integrate
Size number_of_intervals = (Size)poly.getIntervals().size();
interval = poly.getInterval(number_of_intervals - 1);
// the last interval has to be defined to infinity
if (interval.second != std::numeric_limits<double>::infinity())
{
Log.error() << "PairExpRDFIntegrator::integrateToInf(): "
<< "Last interval must have infinity as upper limit." << endl;
getRDF().dump();
return 0.0;
}
// the point from where the integration to inf will start. As interval
// is an interval of the RDF we have to project it to the integration
// beam
double lower_inf = unproject(interval.first);
// if the integration starts below the lower bound of the last
// interval, we have to integrate the whole thing to that point.
if (from < lower_inf)
{
interval = Interval(from, lower_inf);
val = numericallyIntegrateInterval(interval);
}
// now compute the rest of the integral, i. e. the term to infinity.
// only for readibility
double a = poly.getCoefficients(number_of_intervals - 1)[0];
double r = lower_inf;
double b = alpha_ / R_ij_o_;
double d = pow(R_ij_o_, 6);
double exp_br = exp( - b * r );
double r3 = r * r * r;
double infval = a / (3 * pow(b, 3) * r3) *
(
C1_ * 3 * b * b * r3 * r * r * exp_br
+ C1_ * 6 * b * r3 * r * exp_br
+ C1_ * 6 * r3 * exp_br
- C2_ * d * b * b * b
);
val += infval;
return val;
}
double PairExpRDFIntegrator::integrateToInf(double from, double alpha,
double C1, double C2, double R_ij_o, double k1, double k2)
{
setConstants(alpha, C1, C2, R_ij_o, k1, k2);
return integrateToInf(from);
}
double PairExpRDFIntegrator::integrate(double from, double to) const
{
Interval interval(from, to);
return numericallyIntegrateInterval(interval);
}
double PairExpRDFIntegrator::integrate(double from, double to, double alpha,
double C1, double C2, double R_ij_o, double k1, double k2)
{
setConstants(alpha, C1, C2, R_ij_o, k1, k2);
return integrate(from, to);
}
double PairExpRDFIntegrator::operator () (double x) const
{
return integrateToInf(x);
}
double PairExpRDFIntegrator::numericallyIntegrateInterval(Interval interval)
const
{
int samples = (int) options.getInteger(Option::SAMPLES);
int verbosity = (int) options.getInteger(Option::VERBOSITY);
double r = interval.first;
double R = interval.second;
double b = alpha_/R_ij_o_;
double R_ij_o_6 = pow(R_ij_o_, 6);
if (verbosity > 9)
{
Log.info() << "r = " << r << endl;
Log.info() << "R = " << R << endl;
Log.info() << "b = " << b << endl;
Log.info() << "R_ij_o_6 = " << R_ij_o_6 << endl;
Log.info() << "k1 = " << k1_ << endl;
Log.info() << "k2 = " << k2_ << endl;
}
// this is the case where we have to consider the geometry of the
// situation. As this seems analytically impossible, we have to do it
// numerically. The method we use is the trapezium method.
double area = 0;
if (verbosity > 9)
{
Log.info() << "Using " << samples
<< " sample points for numerical integration" << endl;
}
unsigned int n = samples;
// lower case variables are for the potential term
double x = r;
double s = (R-r)/n;
// upper case variables are for the rdf term (representing the
// geometrical correction)
double X = sqrt((r*r + k1_ * r + k2_));
double S = (sqrt((R*R + k1_ * R + k2_))-X)/n;
while (n > 0)
{
// DEBUG
/*
Log.info() << "rdf(" << X << ") = " << getRDF()(X) << endl;
Log.info() << "e^(-b*" << x << ") - R_ij_o/(" << x << ")^6 = " <<
(C1_ * exp(-b*x) - C2_ * R_ij_o_6/pow(x,6)) << endl;
Log.info() << "e^(-b*" << x << ") = " << C1_ * exp(-b*x) << endl;
Log.info() << "R_ij_o/(" << x << ")^6 = " << C2_ * R_ij_o_6/pow(x,6) << endl;
*/
area += (x*x*(C1_ * exp(-b*x) - C2_ * R_ij_o_6/pow(x,6)) * getRDF()(X)
+ (x+s)*(x+s)*(C1_ * exp(-b*(x+s)) - C2_ * R_ij_o_6/pow(x+s,6)) *
getRDF()(X+S)) /2.0 * s;
x += s;
X += S;
--n;
}
return area;
}
void PairExpRDFIntegrator::dump(ostream& stream, Size /* depth */) const
{
stream << "[PairExpRDFIntegrator:]" << endl;
stream << "alpha_ = " << alpha_ << endl;
stream << "C1_ = " << C1_ << endl;
stream << "C2_ = " << C2_ << endl;
stream << "R_ij_o_ = " << R_ij_o_ << endl;
stream << "k1_ = " << k1_ << endl;
stream << "k2_ = " << k2_ << endl;
getRDF().dump();
}
double PairExpRDFIntegrator::project(double x) const
{
return sqrt(x*x + k1_ * x + k2_);
}
double PairExpRDFIntegrator::unproject(double x) const
{
return sqrt(x*x - k1_*k1_ / 4 - k2_) - k1_ / 2;
}
bool PairExpRDFIntegrator::operator ==
(const PairExpRDFIntegrator& integrator) const
{
return (RDFIntegrator::operator == (integrator)
&& (alpha_ == integrator.alpha_)
&& (C1_ == integrator.C1_)
&& (C2_ == integrator.C2_)
&& (R_ij_o_ == integrator.R_ij_o_)
&& (k1_ == integrator.k1_)
&& (k2_ == integrator.k2_)
&& (options == integrator.options));
}
} // namespace BALL
|