MDStressLab++
Loading...
Searching...
No Matches
MethodSphere.cpp
Go to the documentation of this file.
1/*
2 * MethodSphere.cpp
3 *
4 * Created on: Nov 5, 2019
5 * Author: Nikhil
6 */
7
8#include <math.h>
9#include <MethodSphere.h>
10#include <iostream>
11#include <limits>
12#include "typedef.h"
13
14
15MethodSphere::MethodSphere(double averagingDomainSize, const std::string& type) : Method<MethodSphere>(averagingDomainSize)
16{
17 double normalizer;
18 if (type =="hardy")
19 {
20 // weighting function:
21
22 //w(r)= c if r<= R/2,
23 // = 2c(1-r/R) if R/2<=r<=R
24 //where c= 8/(5\pi R^3)
25
26 normalizer= 8/(5*M_PI*pow(averagingDomainSize,3));
27 // constant polynomial
28 std::deque<double> constant{normalizer};
29 Polynomial constantPolynomial{constant};
30 //linear polynomial
31 std::deque<double> linear{2*normalizer,-2*normalizer/averagingDomainSize};
32 Polynomial linearPolynomial{linear};
33
34
35 // construct piecewise polynomial
36 std::pair<double,double> interval;
37 interval.first= 0;
38 interval.second= averagingDomainSize/2;
39 piecewisePolynomial[interval]= constantPolynomial;
40
41 interval.first= averagingDomainSize/2;
42 interval.second= averagingDomainSize;
43 piecewisePolynomial[interval]= linearPolynomial;
44 return;
45 }
46 else if (type == "virial")
47 {
48 //normalizer= 1/(M_PI*pow(averagingDomainSize,3));
49 normalizer= 3.0/(4*M_PI*pow(averagingDomainSize,3));
50 std::deque<double> constant{normalizer};
51 // constant polynomial
52 Polynomial constantPolynomial{constant};
53
54 std::pair<double,double> interval;
55 interval.first= 0;
56 interval.second= averagingDomainSize;
57 piecewisePolynomial[interval]= constantPolynomial;
58 return;
59 }
60 assert(0);
61}
62
63MethodSphere::MethodSphere(double averagingDomainSize, std::map<double,double> map) : Method<MethodSphere>(averagingDomainSize)
64{
65 // ensure the domain of map lies in between 0 and 1, and its range is non-negative
66 assert( (map.cbegin())->first >= 0 &&
67 (map.cend())->first <= 1 &&
68 (map.cbegin())->second >= 0 &&
69 (map.cend())->second >= 0 );
70
71 for (auto iter = map.cbegin(); iter != map.cend(); iter++)
72 {
73 // (y-y1)/(y2-y1) = (x-x1)/(x2-x1)
74 // y = (y2-y1)/(x2-x1) * (x-x1) + y1
75 // = y1-x1*(y2-y1)/(x2-x1) + (y2-y1)/(x2-x1) * x
76 auto nextiter= std::next(iter);
77 if (nextiter != map.cend())
78 {
79 double x1= iter->first; double x2= nextiter->first;
81 std::pair<double,double> interval{x1,x2};
82
83 double y1= iter->second; double y2= nextiter->second;
84 std::deque<double> linear{ y1-x1*(y2-y1)/(x2-x1), (y2-y1)/(x2-x1) };
85 Polynomial linearPolynomial{linear};
86 piecewisePolynomial[interval]= linearPolynomial;
87 }
88 else
89 {
90 if (abs(iter->first-1.0)>epsilon)
91 MY_ERROR("Weight function is not defined entirely on the averaging domain.");
92 break;
93 }
94 }
95 // now compute the normalizer
96 double integral= 0;
97 for(auto iter=piecewisePolynomial.cbegin(); iter!=piecewisePolynomial.cend(); iter++)
98 {
99 Polynomial temp(iter->second);
100 temp.coefficients.push_front(0); temp.coefficients.push_front(0); // Multiplying the polynomial by r^2
101 Polynomial integratedPolynomial= temp.integrate();
102 integral= integral+integratedPolynomial(iter->first.second) - integratedPolynomial(iter->first.first);
103 }
104 double normalizer = 1/(4*M_PI*integral);
105 for(auto iter=piecewisePolynomial.begin(); iter!=piecewisePolynomial.end(); iter++)
106 {
107 for(auto& coeff : iter->second.coefficients)
108 {
109 coeff= normalizer*coeff;
110 }
111 }
112}
113
114
116{
117 *this= _hardy;
118}
119
121 // TODO Auto-generated destructor stub
122}
123
124double MethodSphere::integratePolynomial(const int& degree,
125 const double& a,
126 const double& b,
127 const double& r1,
128 const double& r2) const
129{
130 assert(r1<=r2);
131 switch(degree)
132 {
133 case 0:
134 {
135 assert (a*pow(r2,2)+b+epsilon>0 && a*pow(r1,2)+b+epsilon>0);
136 return (std::sqrt(a*pow(r2,2)+b+epsilon) - std::sqrt(a*pow(r1,2)+b+epsilon))/a;
137 }
138
139 case 1:
140 {
141 assert(a*r1*r1+b+epsilon>0 && a*r2*r2+b+epsilon>0 && a>0);
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);
144
145 return ((r2*temp2-b*log(temp2+a*r2))-
146 (r1*temp1-b*log(temp1+a*r1)))/(2*pow(a,1.5));
147 }
148 default:
149 MY_ERROR("Attempt to integrate polynomial of degree not equal to 0 or 1.");
150 }
151
152}
153
154double MethodSphere::operator()(const Vector3d& vec) const
155{
156 double r= vec.norm();
157
158 auto iter = std::find_if(piecewisePolynomial.cbegin(), piecewisePolynomial.cend(),
159 [=](const std::pair< std::pair<double,double>, Polynomial>& polynomial)
160 {
161 return r>=polynomial.first.first && r<polynomial.first.second;
162 });
163
164 if (iter == piecewisePolynomial.end()) MY_ERROR("Argument out of range for the piecewise-defined weight function");
165 return (iter->second)(r);
166}
167
168double MethodSphere::bondFunction(const Vector3d& vec1, const Vector3d& vec2) const
169{
170 double r1= vec1.norm();
171 double r2= vec2.norm();
172
173 double a= 4*(vec1-vec2).squaredNorm();
174 double b= 4*pow(vec2.dot(vec1)-vec1.dot(vec1),2)-a*r1*r1;
175
176 double sPerp= (vec1.dot(vec1)-vec2.dot(vec1))/(vec1-vec2).squaredNorm();
177
178 Vector3d vecPerp;
179 vecPerp= (1-sPerp)*vec1+sPerp*vec2;
180 double rPerp= vecPerp.norm();
181 assert(rPerp<std::min(r1,r2)+epsilon);
182
184 if (rPerp>=averagingDomainSize) return 0;
185
186 r1= std::min(r1,averagingDomainSize);
187 r2= std::min(r2,averagingDomainSize);
188
189 double rmin;
190 double rmax;
191 double result= 0;
192 if (sPerp<0 || sPerp>1)
193 {
194 rmin= std::min(r1,r2);
195 rmax= std::max(r1,r2);
196
197 if (abs(rmax-rmin)>epsilon) return integrate(a,b,rmin,rmax);
198 else return 0;
199 }
200 else
201 {
202 rmin= rPerp;
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);
205
206 return result;
207 }
208 assert(0);
209}
210
211double MethodSphere::integrate(const double& a,
212 const double& b,
213 const double& rmin,
214 const double& rmax) const
215{
217 assert(rmin<=rmax && rmax<=averagingDomainSize);
218 double result= 0;
219 auto iterMin = std::find_if(piecewisePolynomial.cbegin(), piecewisePolynomial.cend(),
220 [=](const std::pair< std::pair<double,double>, Polynomial>& polynomial)
221 {
222 return rmin>=polynomial.first.first && rmin<polynomial.first.second;
223 });
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)
227 {
228 return rmax>=polynomial.first.first && rmax<polynomial.first.second;
229 });
230
231 for(auto it=iterMin; it!=piecewisePolynomial.cend(); it++)
232 {
233 double lb,ub;
234 if (it == iterMin) lb= rmin;
235 else lb= it->first.first;
236 if (it == iterMax) ub= rmax;
237 else ub= it->first.second;
238
239 int degree= 0;
240 for(const auto& coefficient : it->second.coefficients)
241 {
242 result= result + 2*coefficient*integratePolynomial(degree,a,b,lb,ub);
243 degree++;
244 }
245
246 if (it == iterMax) break;
247 }
248 return result;
249}
250
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.
virtual ~MethodSphere()
double getAveragingDomainSize() const
Gets the spatial size of the averaging domain, i.e. the support of the weighting function.
Definition Method.cpp:40
double averagingDomainSize
Definition Method.h:76
std::deque< double > coefficients
Definition Polynomial.h:20
Polynomial integrate() const
Definition Polynomial.h:35
#define MY_ERROR(message)
Definition typedef.h:17
Eigen::Matrix< double, 1, DIM, Eigen::RowMajor > Vector3d
Definition typedef.h:60
const double epsilon
Definition typedef.h:73