1
#include "ATC_HardyKernel.h"
3
#include <iostream> //for debugging purposes; take this out after I'm done
6
#include "Quadrature.h"
10
static const double Pi = 4.0*atan(1.0);
11
static const double tol = 1.0e-8;
16
//------------------------------------------------------------------------
18
ATC_HardyKernel::ATC_HardyKernel(int nparameters, double* parameters):
19
lammpsInterface_(LammpsInterface::instance()),
20
Rc_(0),invRc_(0),nsd_(3)
26
invVol_ = 1.0/(4.0/3.0*Pi*pow(Rc_,3));
28
set_line_quadrature(line_ngauss,line_xg,line_wg);
30
// get periodicity and box bounds/lengths
31
lammpsInterface_->get_box_periodicity(periodicity[0],
32
periodicity[1],periodicity[2]);
33
lammpsInterface_->get_box_bounds(box_bounds[0][0],box_bounds[1][0],
34
box_bounds[0][1],box_bounds[1][1],
35
box_bounds[0][2],box_bounds[1][2]);
36
for (int k = 0; k < 3; k++) {
37
box_length[k] = box_bounds[1][k] - box_bounds[0][k];
41
// bond function value via quadrature
42
double ATC_HardyKernel::bond(DENS_VEC& xa, DENS_VEC&xb, double lam1, double lam2)
44
DENS_VEC xab(nsd_), q(nsd_);
48
for (int i = 0; i < line_ngauss; i++) {
49
lamg=0.5*((lam2-lam1)*line_xg[i]+(lam2+lam1));
51
double locg_value=this->value(q);
52
bhsum+=locg_value*line_wg[i];
54
return 0.5*(lam2-lam1)*bhsum;
57
// localization-volume intercepts for bond calculation
58
// bond intercept values assuming spherical support
59
void ATC_HardyKernel::bond_intercepts(DENS_VEC& xa,
60
DENS_VEC& xb, double &lam1, double &lam2)
62
if (nsd_ == 2) {// for cylinders, axis is always z!
68
double ra_n = invRc_*xa.norm(); // lambda = 1
69
double rb_n = invRc_*xb.norm(); // lambda = 0
70
bool a_in = (ra_n <= 1.0);
71
bool b_in = (rb_n <= 1.0);
77
DENS_VEC xab = xa - xb;
78
double rab_n = invRc_*xab.norm();
79
double a = rab_n*rab_n; // always at least an interatomic distance
80
double b = 2.0*invRc_*invRc_*xab.dot(xb);
81
double c = rb_n*rb_n - 1.0;
82
double discrim = b*b - 4.0*a*c; // discriminant
83
if (discrim < 0) return; // no intersection
87
double aux = -0.5*(b-sqrt(discrim));
92
double aux = -0.5*(b+sqrt(discrim));
100
else if (!a_in && b_in) {
105
if (s1 >= 0.0 && s2 <= 1.0) {
112
//------------------------------------------------------------------------
114
ATC_HardyKernelStep::ATC_HardyKernelStep
115
(int nparameters, double* parameters):
116
ATC_HardyKernel(nparameters, parameters)
118
for (int k = 0; k < nsd_; k++ ) {
119
if ((bool) periodicity[k]) {
120
if (Rc_ > 0.5*box_length[k]) {
121
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
128
double ATC_HardyKernelStep::value(DENS_VEC& x_atom)
130
double rn=invRc_*x_atom.norm();
131
if (rn <= 1.0) { return 1.0; }
135
//------------------------------------------------------------------------
136
/** a step with rectangular support suitable for a rectangular grid */
138
ATC_HardyKernelCell::ATC_HardyKernelCell
139
(int nparameters, double* parameters):
140
ATC_HardyKernel(nparameters, parameters)
145
invVol_ = 1.0/8.0/(hx*hy*hz);
146
cellBounds_.reset(6);
147
cellBounds_(0) = -hx;
149
cellBounds_(2) = -hy;
151
cellBounds_(4) = -hz;
154
for (int k = 0; k < nsd_; k++ ) {
155
if ((bool) periodicity[k]) {
156
if (parameters[k] > 0.5*box_length[k]) {
157
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
164
double ATC_HardyKernelCell::value(DENS_VEC& x_atom)
166
if ((cellBounds_(0) <= x_atom(0)) && (x_atom(0) < cellBounds_(1))
167
&& (cellBounds_(2) <= x_atom(1)) && (x_atom(1) < cellBounds_(3))
168
&& (cellBounds_(4) <= x_atom(2)) && (x_atom(2) < cellBounds_(5))) {
176
// bond intercept values for rectangular region : origin is the node position
177
void ATC_HardyKernelCell::bond_intercepts(DENS_VEC& xa,
178
DENS_VEC& xb, double &lam1, double &lam2)
183
bool a_in = (value(xa) > 0.0);
184
bool b_in = (value(xb) > 0.0);
186
// (1) both in, no intersection needed
190
// (2) for one in & one out -> one plane intersection
191
// determine the points of intersection between the line joining
192
// atoms a and b and the bounding planes of the localization volume
193
else if (a_in || b_in) {
194
DENS_VEC xab = xa - xb;
195
for (int i = 0; i < nsd_; i++) {
196
// check if segment is parallel to face
197
if (fabs(xab(i)) > tol) {
198
for (int j = 0; j < 2; j++) {
199
double s = (cellBounds_(2*i+j) - xb(i))/xab(i);
200
// check if between a & b
201
if (s >= 0 && s <= 1) {
202
bool in_bounds = false;
203
DENS_VEC x = xb + s*xab;
205
if ((cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))
206
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
211
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
212
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
217
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
218
&& (cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))) {
223
if (a_in) { lam1 = s;}
231
throw ATC_Error(0,"logic failure in HardyKernel Cell for single intersection\n");
233
// (3) both out -> corner intersection
235
lam2 = lam1; // default to no intersection
236
DENS_VEC xab = xa - xb;
237
double ss[6] = {-1,-1,-1,-1,-1,-1};
239
for (int i = 0; i < nsd_; i++) {
240
// check if segment is parallel to face
241
if (fabs(xab(i)) > tol) {
242
for (int j = 0; j < 2; j++) {
243
double s = (cellBounds_(2*i+j) - xb(i))/xab(i);
244
// check if between a & b
245
if (s >= 0 && s <= 1) {
247
DENS_VEC x = xb + s*xab;
249
if ((cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))
250
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
255
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
256
&& (cellBounds_(4) <= x(2)) && (x(2) <= cellBounds_(5))) {
261
if ((cellBounds_(0) <= x(0)) && (x(0) <= cellBounds_(1))
262
&& (cellBounds_(2) <= x(1)) && (x(1) <= cellBounds_(3))) {
271
// intersection occurs at a box edge - leave lam1 = lam2
274
lam1 = min(ss[0],ss[1]);
275
lam2 = max(ss[0],ss[1]);
278
// intersection occurs at a box vertex - leave lam1 = lam2
281
if (is != 0) throw ATC_Error(0,"logic failure in HardyKernel Cell for corner intersection\n");
286
//------------------------------------------------------------------------
288
ATC_HardyKernelCubicSphere::ATC_HardyKernelCubicSphere
289
(int nparameters, double* parameters):
290
ATC_HardyKernel(nparameters, parameters)
292
for (int k = 0; k < nsd_; k++ ) {
293
if ((bool) periodicity[k]) {
294
if (Rc_ > 0.5*box_length[k]) {
295
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
302
double ATC_HardyKernelCubicSphere::value(DENS_VEC& x_atom)
304
double r=x_atom.norm();
306
if (rn < 1.0) { return 5.0*(1.0-3.0*rn*rn+2.0*rn*rn*rn); }
309
//------------------------------------------------------------------------
311
ATC_HardyKernelQuarticSphere::ATC_HardyKernelQuarticSphere
312
(int nparameters, double* parameters):
313
ATC_HardyKernel(nparameters, parameters)
315
for (int k = 0; k < nsd_; k++ ) {
316
if ((bool) periodicity[k]) {
317
if (Rc_ > 0.5*box_length[k]) {
318
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
325
double ATC_HardyKernelQuarticSphere::value(DENS_VEC& x_atom)
327
double r=x_atom.norm();
329
if (rn < 1.0) { return 35.0/8.0*pow((1.0-rn*rn),2); }
332
//------------------------------------------------------------------------
334
ATC_HardyKernelCubicCyl::ATC_HardyKernelCubicCyl
335
(int nparameters, double* parameters):
336
ATC_HardyKernel(nparameters, parameters)
339
double Lz = box_length[2];
340
invVol_ = 1.0/(Pi*pow(Rc_,2)*Lz);
341
for (int k = 0; k < nsd_; k++ ) {
342
if ((bool) periodicity[k]) {
343
if (Rc_ > 0.5*box_length[k]) {
344
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
351
double ATC_HardyKernelCubicCyl::value(DENS_VEC& x_atom)
353
double r=sqrt(pow(x_atom(0),2)+pow(x_atom(1),2));
355
if (rn < 1.0) { return 10.0/3.0*(1.0-3.0*rn*rn+2.0*rn*rn*rn); }
360
//------------------------------------------------------------------------
362
ATC_HardyKernelQuarticCyl::ATC_HardyKernelQuarticCyl
363
(int nparameters, double* parameters):
364
ATC_HardyKernel(nparameters, parameters)
367
double Lz = box_length[2];
368
invVol_ = 1.0/(Pi*pow(Rc_,2)*Lz);
369
for (int k = 0; k < nsd_; k++ ) {
370
if ((bool) periodicity[k]) {
371
if (Rc_ > 0.5*box_length[k]) {
372
throw ATC_Error(0,"Size of localization volume is too large for periodic boundary condition");
379
double ATC_HardyKernelQuarticCyl::value(DENS_VEC& x_atom)
381
double r=sqrt(pow(x_atom(0),2)+pow(x_atom(1),2));
383
if (rn < 1.0) { return 3.0*pow((1.0-rn*rn),2); }