n2p2 - A neural network potential package
SymFncExpAngn.cpp
Go to the documentation of this file.
1// n2p2 - A neural network potential package
2// Copyright (C) 2018 Andreas Singraber (University of Vienna)
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17#include "SymFncExpAngn.h"
18#include "Atom.h"
19#include "ElementMap.h"
20#include "utility.h"
21#include "Vec3D.h"
22#include <cstdlib> // atof, atoi
23#include <cmath> // exp, pow, cos
24#include <limits> // std::numeric_limits
25#include <stdexcept> // std::runtime_error
26
27using namespace std;
28using namespace nnp;
29
30SymFncExpAngn::SymFncExpAngn(ElementMap const& elementMap) :
31 SymFncBaseExpAng(3, elementMap)
32{
33}
34
35bool SymFncExpAngn::operator==(SymFnc const& rhs) const
36{
37 if (ec != rhs.getEc() ) return false;
38 if (type != rhs.getType()) return false;
39 SymFncExpAngn const& c = dynamic_cast<SymFncExpAngn const&>(rhs);
40 if (cutoffType != c.cutoffType ) return false;
41 if (cutoffAlpha != c.cutoffAlpha) return false;
42 if (rc != c.rc ) return false;
43 if (eta != c.eta ) return false;
44 if (zeta != c.zeta ) return false;
45 if (lambda != c.lambda ) return false;
46 if (e1 != c.e1 ) return false;
47 if (e2 != c.e2 ) return false;
48 return true;
49}
50
51bool SymFncExpAngn::operator<(SymFnc const& rhs) const
52{
53 if (ec < rhs.getEc() ) return true;
54 else if (ec > rhs.getEc() ) return false;
55 if (type < rhs.getType()) return true;
56 else if (type > rhs.getType()) return false;
57 SymFncExpAngn const& c = dynamic_cast<SymFncExpAngn const&>(rhs);
58 if (cutoffType < c.cutoffType ) return true;
59 else if (cutoffType > c.cutoffType ) return false;
60 if (cutoffAlpha < c.cutoffAlpha) return true;
61 else if (cutoffAlpha > c.cutoffAlpha) return false;
62 if (rc < c.rc ) return true;
63 else if (rc > c.rc ) return false;
64 if (eta < c.eta ) return true;
65 else if (eta > c.eta ) return false;
66 if (rs < c.rs ) return true;
67 else if (rs > c.rs ) return false;
68 if (zeta < c.zeta ) return true;
69 else if (zeta > c.zeta ) return false;
70 if (lambda < c.lambda ) return true;
71 else if (lambda > c.lambda ) return false;
72 if (e1 < c.e1 ) return true;
73 else if (e1 > c.e1 ) return false;
74 if (e2 < c.e2 ) return true;
75 else if (e2 > c.e2 ) return false;
76 return false;
77}
78
79void SymFncExpAngn::calculate(Atom& atom, bool const derivatives) const
80{
81 double const pnorm = pow(2.0, 1.0 - zeta);
82 double const pzl = zeta * lambda;
83 double const rc2 = rc * rc;
84 double result = 0.0;
85
86 //size_t numNeighbors = atom.numNeighbors;
87 size_t numNeighbors = atom.getStoredMinNumNeighbors(rc);
88 // Prevent problematic condition in loop test below (j < numNeighbors - 1).
89 if (numNeighbors == 0) numNeighbors = 1;
90
91 for (size_t j = 0; j < numNeighbors - 1; j++)
92 {
93 Atom::Neighbor& nj = atom.neighbors[j];
94 size_t const nej = nj.element;
95 double const rij = nj.d;
96 if ((e1 == nej || e2 == nej) && rij < rc)
97 {
98 double const r2ij = rij * rij;
99
100 // Calculate cutoff function and derivative.
101 double pfcij;
102 double pdfcij;
103#ifndef N2P2_NO_SF_CACHE
104 if (cacheIndices[nej].size() == 0) fc.fdf(rij, pfcij, pdfcij);
105 else
106 {
107 double& cfc = nj.cache[cacheIndices[nej][0]];
108 double& cdfc = nj.cache[cacheIndices[nej][1]];
109 if (cfc < 0) fc.fdf(rij, cfc, cdfc);
110 pfcij = cfc;
111 pdfcij = cdfc;
112 }
113#else
114 fc.fdf(rij, pfcij, pdfcij);
115#endif
116 for (size_t k = j + 1; k < numNeighbors; k++)
117 {
118 Atom::Neighbor& nk = atom.neighbors[k];
119 size_t const nek = nk.element;
120 if ((e1 == nej && e2 == nek) ||
121 (e2 == nej && e1 == nek))
122 {
123 double const rik = nk.d;
124 if (rik < rc)
125 {
126 Vec3D drjk = nk.dr - nj.dr;
127 double rjk = drjk.norm2();;
128 if (rjk < rc2)
129 {
130 // Energy calculation.
131 double pfcik;
132 double pdfcik;
133#ifndef N2P2_NO_SF_CACHE
134 if (cacheIndices[nej].size() == 0)
135 {
136 fc.fdf(rik, pfcik, pdfcik);
137 }
138 else
139 {
140 double& cfc = nk.cache[cacheIndices[nek][0]];
141 double& cdfc = nk.cache[cacheIndices[nek][1]];
142 if (cfc < 0) fc.fdf(rik, cfc, cdfc);
143 pfcik = cfc;
144 pdfcik = cdfc;
145 }
146#else
147 fc.fdf(rik, pfcik, pdfcik);
148#endif
149 rjk = sqrt(rjk);
150 double pfcjk;
151 double pdfcjk;
152 fc.fdf(rjk, pfcjk, pdfcjk);
153
154 Vec3D drij = nj.dr;
155 Vec3D drik = nk.dr;
156 double costijk = drij * drik;;
157 double rinvijik = 1.0 / rij / rik;
158 costijk *= rinvijik;
159
160 double const pfc = pfcij * pfcik * pfcjk;
161 double const r2ik = rik * rik;
162 double const rijs = rij - rs;
163 double const riks = rik - rs;
164 double const rjks = rjk - rs;
165 double const pexp = exp(-eta * (rijs * rijs +
166 riks * riks +
167 rjks * rjks));
168 double const plambda = 1.0 + lambda * costijk;
169 double fg = pexp;
170 if (plambda <= 0.0) fg = 0.0;
171 else
172 {
173 if (useIntegerPow)
174 {
175 fg *= pow_int(plambda, zetaInt - 1);
176 }
177 else
178 {
179 fg *= pow(plambda, zeta - 1.0);
180 }
181 }
182 result += fg * plambda * pfc;
183
184 // Force calculation.
185 if (!derivatives) continue;
186 fg *= pnorm;
187 rinvijik *= pzl;
188 costijk *= pzl;
189 double const p2etapl = 2.0 * eta * plambda;
190 double const p1 = fg * (pfc * (rinvijik - costijk
191 / r2ij - p2etapl * rijs / rij)
192 + pfcik * pfcjk * pdfcij * plambda
193 / rij);
194 double const p2 = fg * (pfc * (rinvijik - costijk
195 / r2ik - p2etapl * riks / rik)
196 + pfcij * pfcjk * pdfcik * plambda
197 / rik);
198 double const p3 = fg * (pfc * (rinvijik + p2etapl
199 * rjks / rjk) - pfcij * pfcik
200 * pdfcjk * plambda / rjk);
201 drij *= p1 * scalingFactor;
202 drik *= p2 * scalingFactor;
203 drjk *= p3 * scalingFactor;
204
205 // Save force contributions in Atom storage.
206 atom.dGdr[index] += drij + drik;
207#ifndef N2P2_FULL_SFD_MEMORY
208 nj.dGdr[indexPerElement[nej]] -= drij + drjk;
209 nk.dGdr[indexPerElement[nek]] -= drik - drjk;
210#else
211 nj.dGdr[index] -= drij + drjk;
212 nk.dGdr[index] -= drik - drjk;
213#endif
214 } // rjk <= rc
215 } // rik <= rc
216 } // elem
217 } // k
218 } // rij <= rc
219 } // j
220 result *= pnorm;
221
222 atom.G[index] = scale(result);
223
224 return;
225}
void fdf(double r, double &fc, double &dfc) const
Calculate cutoff function and derivative .
Contains element map.
Definition: ElementMap.h:30
CutoffFunction fc
Cutoff function used by this symmetry function.
CutoffFunction::CutoffType cutoffType
Cutoff type used by this symmetry function.
double cutoffAlpha
Cutoff parameter .
Intermediate class for angular SFs based on cutoffs and exponentials.
double lambda
Cosine shift factor.
double zeta
Exponent of cosine term.
double eta
Width of gaussian.
std::size_t e1
Element index of neighbor atom 1.
std::size_t e2
Element index of neighbor atom 2.
int zetaInt
Integer version of .
double rs
Shift of gaussian.
bool useIntegerPow
Whether to use integer version of power function (faster).
Angular symmetry function (type 3)
Definition: SymFncExpAngn.h:55
virtual bool operator==(SymFnc const &rhs) const
Overload == operator.
virtual void calculate(Atom &atom, bool const derivatives) const
Calculate symmetry function for one atom.
virtual bool operator<(SymFnc const &rhs) const
Overload < operator.
Symmetry function base class.
Definition: SymFnc.h:40
std::size_t type
Symmetry function type.
Definition: SymFnc.h:268
std::size_t index
Symmetry function index (per element).
Definition: SymFnc.h:272
double scalingFactor
Scaling factor.
Definition: SymFnc.h:294
std::size_t getType() const
Get private type member variable.
Definition: SymFnc.h:355
double rc
Cutoff radius .
Definition: SymFnc.h:292
std::vector< std::vector< std::size_t > > cacheIndices
Cache indices for each element.
Definition: SymFnc.h:306
double scale(double value) const
Apply symmetry function scaling and/or centering.
Definition: SymFnc.cpp:169
std::size_t getEc() const
Get private ec member variable.
Definition: SymFnc.h:356
std::vector< std::size_t > indexPerElement
Per-element index for derivative memory in Atom::Neighbor::dGdr arrays.
Definition: SymFnc.h:302
std::size_t ec
Element index of center atom.
Definition: SymFnc.h:276
Definition: Atom.h:29
double pow_int(double x, int n)
Integer version of power function, "fast exponentiation algorithm".
Definition: utility.cpp:292
Struct to store information on neighbor atoms.
Definition: Atom.h:36
std::vector< double > cache
Symmetry function cache (e.g. for cutoffs, compact functions).
Definition: Atom.h:49
std::size_t element
Element index of neighbor atom.
Definition: Atom.h:42
double d
Distance to neighbor atom.
Definition: Atom.h:44
Vec3D dr
Distance vector to neighbor atom.
Definition: Atom.h:46
std::vector< Vec3D > dGdr
Derivatives of symmetry functions with respect to neighbor coordinates.
Definition: Atom.h:60
Storage for a single atom.
Definition: Atom.h:33
std::vector< Neighbor > neighbors
Neighbor array (maximum number defined in macros.h.
Definition: Atom.h:170
std::size_t getStoredMinNumNeighbors(double const cutoffRadius) const
Return needed number of neighbors for a given cutoff radius from neighborCutoffs map.
Definition: Atom.cpp:329
std::vector< Vec3D > dGdr
Derivative of symmetry functions with respect to this atom's coordinates.
Definition: Atom.h:161
std::vector< double > G
Symmetry function values.
Definition: Atom.h:146
Vector in 3 dimensional real space.
Definition: Vec3D.h:30
double norm2() const
Calculate square of norm of vector.
Definition: Vec3D.h:299