26 normalizer= 8/(5*M_PI*pow(averagingDomainSize,3));
28 std::deque<double> constant{normalizer};
31 std::deque<double> linear{2*normalizer,-2*normalizer/averagingDomainSize};
36 std::pair<double,double> interval;
38 interval.second= averagingDomainSize/2;
39 piecewisePolynomial[interval]= constantPolynomial;
41 interval.first= averagingDomainSize/2;
43 piecewisePolynomial[interval]= linearPolynomial;
46 else if (type ==
"virial")
48 normalizer= 1/(M_PI*pow(averagingDomainSize,3));
49 std::deque<double> constant{normalizer};
53 std::pair<double,double> interval;
56 piecewisePolynomial[interval]= constantPolynomial;
65 assert( (map.cbegin())->first >= 0 &&
66 (map.cend())->first <= 1 &&
67 (map.cbegin())->second >= 0 &&
68 (map.cend())->second >= 0 );
70 for (
auto iter = map.cbegin(); iter != map.cend(); iter++)
75 auto nextiter= std::next(iter);
76 if (nextiter != map.cend())
78 double x1= iter->first;
double x2= nextiter->first;
80 std::pair<double,double> interval{x1,x2};
82 double y1= iter->second;
double y2= nextiter->second;
83 std::deque<double> linear{ y1-x1*(y2-y1)/(x2-x1), (y2-y1)/(x2-x1) };
85 piecewisePolynomial[interval]= linearPolynomial;
89 if (abs(iter->first-1.0)>
epsilon)
90 MY_ERROR(
"Weight function is not defined entirely on the averaging domain.");
96 for(
auto iter=piecewisePolynomial.cbegin(); iter!=piecewisePolynomial.cend(); iter++)
101 integral= integral+integratedPolynomial(iter->first.second) - integratedPolynomial(iter->first.first);
103 double normalizer = 1/(4*M_PI*integral);
104 for(
auto iter=piecewisePolynomial.begin(); iter!=piecewisePolynomial.end(); iter++)
106 for(
auto& coeff : iter->second.coefficients)
108 coeff= normalizer*coeff;
123 double MethodSphere::integratePolynomial(
const int& degree,
127 const double& r2)
const 135 return (std::sqrt(a*pow(r2,2)+b+
epsilon) - std::sqrt(a*pow(r1,2)+b+
epsilon))/a;
141 double temp1= std::sqrt(a)*std::sqrt(a*r1*r1 + b +
epsilon);
142 double temp2= std::sqrt(a)*std::sqrt(a*r2*r2 + b +
epsilon);
144 return ((r2*temp2-b*log(temp2+a*r2))-
145 (r1*temp1-b*log(temp1+a*r1)))/(2*pow(a,1.5));
148 MY_ERROR(
"Attempt to integrate polynomial of degree not equal to 0 or 1.");
155 double r= vec.norm();
157 auto iter = std::find_if(piecewisePolynomial.cbegin(), piecewisePolynomial.cend(),
158 [=](
const std::pair< std::pair<double,double>,
Polynomial>& polynomial)
160 return r>=polynomial.first.first && r<polynomial.first.second;
163 if (iter == piecewisePolynomial.end())
MY_ERROR(
"Argument out of range for the piecewise-defined weight function");
164 return (iter->second)(r);
169 double r1= vec1.norm();
170 double r2= vec2.norm();
172 double a= 4*(vec1-vec2).squaredNorm();
173 double b= 4*pow(vec2.dot(vec1)-vec1.dot(vec1),2)-a*r1*r1;
175 double sPerp= (vec1.dot(vec1)-vec2.dot(vec1))/(vec1-vec2).squaredNorm();
178 vecPerp= (1-sPerp)*vec1+sPerp*vec2;
179 double rPerp= vecPerp.norm();
180 assert(rPerp<std::min(r1,r2)+
epsilon);
183 if (rPerp>=averagingDomainSize)
return 0;
185 r1= std::min(r1,averagingDomainSize);
186 r2= std::min(r2,averagingDomainSize);
191 if (sPerp<0 || sPerp>1)
193 rmin= std::min(r1,r2);
194 rmax= std::max(r1,r2);
196 if (abs(rmax-rmin)>
epsilon)
return integrate(a,b,rmin,rmax);
202 if (abs(r1-rmin)>
epsilon) result= integrate(a,b,rmin,r1);
203 if (abs(r2-rmin)>
epsilon) result= result+integrate(a,b,rmin,r2);
210 double MethodSphere::integrate(
const double& a,
213 const double& rmax)
const 216 assert(rmin<=rmax && rmax<=averagingDomainSize);
218 auto iterMin = std::find_if(piecewisePolynomial.cbegin(), piecewisePolynomial.cend(),
219 [=](
const std::pair< std::pair<double,double>,
Polynomial>& polynomial)
221 return rmin>=polynomial.first.first && rmin<polynomial.first.second;
223 if (iterMin == piecewisePolynomial.cend())
MY_ERROR(
"Lower integral limit out of range for the piecewise-defined weight function");
224 auto iterMax = std::find_if(iterMin, piecewisePolynomial.cend(),
225 [=](
const std::pair< std::pair<double,double>,
Polynomial>& polynomial)
227 return rmax>=polynomial.first.first && rmax<polynomial.first.second;
230 for(
auto it=iterMin; it!=piecewisePolynomial.cend(); it++)
233 if (it == iterMin) lb= rmin;
234 else lb= it->first.first;
235 if (it == iterMax) ub= rmax;
236 else ub= it->first.second;
239 for(
const auto& coefficient : it->second.coefficients)
241 result= result + 2*coefficient*integratePolynomial(degree,a,b,lb,ub);
245 if (it == iterMax)
break;
double bondFunction(const Vector3d &vec1, const Vector3d &vec2) const
double operator()(const Vector3d &vec) const
Polynomial integrate() const
double averagingDomainSize
double getAveragingDomainSize() const
MethodSphere(double, std::string)
#define MY_ERROR(message)
Eigen::Matrix< double, 1, DIM, Eigen::RowMajor > Vector3d
std::deque< double > coefficients