28 std::deque<double> constant{normalizer};
36 std::pair<double,double> interval;
39 piecewisePolynomial[interval]= constantPolynomial;
43 piecewisePolynomial[interval]= linearPolynomial;
46 else if (type ==
"virial")
50 std::deque<double> constant{normalizer};
54 std::pair<double,double> interval;
57 piecewisePolynomial[interval]= constantPolynomial;
66 assert( (map.cbegin())->first >= 0 &&
67 (map.cend())->first <= 1 &&
68 (map.cbegin())->second >= 0 &&
69 (map.cend())->second >= 0 );
71 for (
auto iter = map.cbegin(); iter != map.cend(); iter++)
76 auto nextiter= std::next(iter);
77 if (nextiter != map.cend())
79 double x1= iter->first;
double x2= nextiter->first;
81 std::pair<double,double> interval{x1,x2};
83 double y1= iter->second;
double y2= nextiter->second;
84 std::deque<double> linear{ y1-x1*(y2-y1)/(x2-x1), (y2-y1)/(x2-x1) };
86 piecewisePolynomial[interval]= linearPolynomial;
90 if (abs(iter->first-1.0)>
epsilon)
91 MY_ERROR(
"Weight function is not defined entirely on the averaging domain.");
97 for(
auto iter=piecewisePolynomial.cbegin(); iter!=piecewisePolynomial.cend(); iter++)
102 integral= integral+integratedPolynomial(iter->first.second) - integratedPolynomial(iter->first.first);
104 double normalizer = 1/(4*M_PI*integral);
105 for(
auto iter=piecewisePolynomial.begin(); iter!=piecewisePolynomial.end(); iter++)
107 for(
auto& coeff : iter->second.coefficients)
109 coeff= normalizer*coeff;
124double MethodSphere::integratePolynomial(
const int& degree,
128 const double& r2)
const
136 return (std::sqrt(a*pow(r2,2)+b+
epsilon) - std::sqrt(a*pow(r1,2)+b+
epsilon))/a;
142 double temp1= std::sqrt(a)*std::sqrt(a*r1*r1 + b +
epsilon);
143 double temp2= std::sqrt(a)*std::sqrt(a*r2*r2 + b +
epsilon);
145 return ((r2*temp2-b*log(temp2+a*r2))-
146 (r1*temp1-b*log(temp1+a*r1)))/(2*pow(a,1.5));
149 MY_ERROR(
"Attempt to integrate polynomial of degree not equal to 0 or 1.");
156 double r= vec.norm();
158 auto iter = std::find_if(piecewisePolynomial.cbegin(), piecewisePolynomial.cend(),
159 [=](
const std::pair< std::pair<double,double>,
Polynomial>& polynomial)
161 return r>=polynomial.first.first && r<polynomial.first.second;
164 if (iter == piecewisePolynomial.end())
MY_ERROR(
"Argument out of range for the piecewise-defined weight function");
165 return (iter->second)(r);
170 double r1= vec1.norm();
171 double r2= vec2.norm();
173 double a= 4*(vec1-vec2).squaredNorm();
174 double b= 4*pow(vec2.dot(vec1)-vec1.dot(vec1),2)-a*r1*r1;
176 double sPerp= (vec1.dot(vec1)-vec2.dot(vec1))/(vec1-vec2).squaredNorm();
179 vecPerp= (1-sPerp)*vec1+sPerp*vec2;
180 double rPerp= vecPerp.norm();
181 assert(rPerp<std::min(r1,r2)+
epsilon);
192 if (sPerp<0 || sPerp>1)
194 rmin= std::min(r1,r2);
195 rmax= std::max(r1,r2);
197 if (abs(rmax-rmin)>
epsilon)
return integrate(a,b,rmin,rmax);
203 if (abs(r1-rmin)>
epsilon) result= integrate(a,b,rmin,r1);
204 if (abs(r2-rmin)>
epsilon) result= result+integrate(a,b,rmin,r2);
211double MethodSphere::integrate(
const double& a,
214 const double& rmax)
const
219 auto iterMin = std::find_if(piecewisePolynomial.cbegin(), piecewisePolynomial.cend(),
220 [=](
const std::pair< std::pair<double,double>,
Polynomial>& polynomial)
222 return rmin>=polynomial.first.first && rmin<polynomial.first.second;
224 if (iterMin == piecewisePolynomial.cend())
MY_ERROR(
"Lower integral limit out of range for the piecewise-defined weight function");
225 auto iterMax = std::find_if(iterMin, piecewisePolynomial.cend(),
226 [=](
const std::pair< std::pair<double,double>,
Polynomial>& polynomial)
228 return rmax>=polynomial.first.first && rmax<polynomial.first.second;
231 for(
auto it=iterMin; it!=piecewisePolynomial.cend(); it++)
234 if (it == iterMin) lb= rmin;
235 else lb= it->first.first;
236 if (it == iterMax) ub= rmax;
237 else ub= it->first.second;
240 for(
const auto& coefficient : it->second.coefficients)
242 result= result + 2*coefficient*integratePolynomial(degree,a,b,lb,ub);
246 if (it == iterMax)
break;
Implements radially symmetric weighting functions (Hardy, Virial) and its associated bond function fo...
MethodSphere(double, const std::string &type="virial")
Constructs a MethodSphere using a named weighting type.
double operator()(const Vector3d &vec) const
Evaluate the weighting function at a vector.
double bondFunction(const Vector3d &vec1, const Vector3d &vec2) const
Computes the bond function for a pair of atomic positions.
double getAveragingDomainSize() const
Gets the spatial size of the averaging domain, i.e. the support of the weighting function.
double averagingDomainSize
std::deque< double > coefficients
Polynomial integrate() const
#define MY_ERROR(message)
Eigen::Matrix< double, 1, DIM, Eigen::RowMajor > Vector3d