n2p2 - A neural network potential package
SymFncExpAngnWeighted.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
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
30SymFncExpAngnWeighted::SymFncExpAngnWeighted(ElementMap const& elementMap) :
31 SymFncBaseCutoff(13, elementMap),
32 useIntegerPow(false),
33 zetaInt (0 ),
34 eta (0.0 ),
35 rs (0.0 ),
36 lambda (0.0 ),
37 zeta (0.0 )
38{
39 minNeighbors = 2;
40 parameters.insert("rs/rl");
41 parameters.insert("eta");
42 parameters.insert("zeta");
43 parameters.insert("lambda");
44}
45
47{
48 if (ec != rhs.getEc() ) return false;
49 if (type != rhs.getType()) return false;
50 SymFncExpAngnWeighted const& c =
51 dynamic_cast<SymFncExpAngnWeighted const&>(rhs);
52 if (cutoffType != c.cutoffType ) return false;
53 if (cutoffAlpha != c.cutoffAlpha) return false;
54 if (rc != c.rc ) return false;
55 if (eta != c.eta ) return false;
56 if (rs != c.rs ) return false;
57 if (zeta != c.zeta ) return false;
58 if (lambda != c.lambda ) return false;
59 return true;
60}
61
63{
64 if (ec < rhs.getEc() ) return true;
65 else if (ec > rhs.getEc() ) return false;
66 if (type < rhs.getType()) return true;
67 else if (type > rhs.getType()) return false;
68 SymFncExpAngnWeighted const& c =
69 dynamic_cast<SymFncExpAngnWeighted const&>(rhs);
70 if (cutoffType < c.cutoffType ) return true;
71 else if (cutoffType > c.cutoffType ) return false;
72 if (cutoffAlpha < c.cutoffAlpha) return true;
73 else if (cutoffAlpha > c.cutoffAlpha) return false;
74 if (rc < c.rc ) return true;
75 else if (rc > c.rc ) return false;
76 if (eta < c.eta ) return true;
77 else if (eta > c.eta ) return false;
78 if (rs < c.rs ) return true;
79 else if (rs > c.rs ) return false;
80 if (zeta < c.zeta ) return true;
81 else if (zeta > c.zeta ) return false;
82 if (lambda < c.lambda ) return true;
83 else if (lambda > c.lambda ) return false;
84 return false;
85}
86
87void SymFncExpAngnWeighted::setParameters(string const& parameterString)
88{
89 vector<string> splitLine = split(reduce(parameterString));
90
91 if (type != (size_t)atoi(splitLine.at(1).c_str()))
92 {
93 throw runtime_error("ERROR: Incorrect symmetry function type.\n");
94 }
95
96 ec = elementMap[splitLine.at(0)];
97 eta = atof(splitLine.at(2).c_str());
98 rs = atof(splitLine.at(3).c_str());
99 lambda = atof(splitLine.at(4).c_str());
100 zeta = atof(splitLine.at(5).c_str());
101 rc = atof(splitLine.at(6).c_str());
102
105
106 zetaInt = round(zeta);
107 if (fabs(zeta - zetaInt) <= numeric_limits<double>::min())
108 {
109 useIntegerPow = true;
110 }
111 else
112 {
113 useIntegerPow = false;
114 }
115
116 return;
117}
118
120{
121 this->convLength = convLength;
123 rs *= convLength;
124 rc *= convLength;
125
128
129 return;
130}
131
133{
134 string s = strpr("symfunction_short %2s %2zu %16.8E %16.8E %16.8E "
135 "%16.8E %16.8E\n",
136 elementMap[ec].c_str(),
137 type,
139 rs / convLength,
140 lambda,
141 zeta,
142 rc / convLength);
143
144 return s;
145}
146
147void SymFncExpAngnWeighted::calculate(Atom& atom, bool const derivatives) const
148{
149 double const pnorm = pow(2.0, 1.0 - zeta);
150 double const pzl = zeta * lambda;
151 double const rc2 = rc * rc;
152 double result = 0.0;
153
154 size_t numNeighbors = atom.numNeighbors;
155 // Prevent problematic condition in loop test below (j < numNeighbors - 1).
156 if (numNeighbors == 0) numNeighbors = 1;
157
158 for (size_t j = 0; j < numNeighbors - 1; j++)
159 {
160 Atom::Neighbor& nj = atom.neighbors[j];
161 size_t const nej = nj.element;
162 double const rij = nj.d;
163 if (rij < rc)
164 {
165 double const r2ij = rij * rij;
166
167 // Calculate cutoff function and derivative.
168 double pfcij;
169 double pdfcij;
170#ifndef N2P2_NO_SF_CACHE
171 if (cacheIndices[nej].size() == 0) fc.fdf(rij, pfcij, pdfcij);
172 else
173 {
174 double& cfc = nj.cache[cacheIndices[nej][0]];
175 double& cdfc = nj.cache[cacheIndices[nej][1]];
176 if (cfc < 0) fc.fdf(rij, cfc, cdfc);
177 pfcij = cfc;
178 pdfcij = cdfc;
179 }
180#else
181 fc.fdf(rij, pfcij, pdfcij);
182#endif
183 for (size_t k = j + 1; k < numNeighbors; k++)
184 {
185 Atom::Neighbor& nk = atom.neighbors[k];
186 size_t const nek = nk.element;
187 double const rik = nk.d;
188 if (rik < rc)
189 {
190 Vec3D drjk = nk.dr - nj.dr;
191 double rjk = drjk.norm2();;
192 if (rjk < rc2)
193 {
194 // Energy calculation.
195 double pfcik;
196 double pdfcik;
197#ifndef N2P2_NO_SF_CACHE
198 if (cacheIndices[nej].size() == 0)
199 {
200 fc.fdf(rik, pfcik, pdfcik);
201 }
202 else
203 {
204 double& cfc = nk.cache[cacheIndices[nek][0]];
205 double& cdfc = nk.cache[cacheIndices[nek][1]];
206 if (cfc < 0) fc.fdf(rik, cfc, cdfc);
207 pfcik = cfc;
208 pdfcik = cdfc;
209 }
210#else
211 fc.fdf(rik, pfcik, pdfcik);
212#endif
213 rjk = sqrt(rjk);
214 double pfcjk;
215 double pdfcjk;
216 fc.fdf(rjk, pfcjk, pdfcjk);
217
218 Vec3D drij = nj.dr;
219 Vec3D drik = nk.dr;
220 double costijk = drij * drik;;
221 double rinvijik = 1.0 / rij / rik;
222 costijk *= rinvijik;
223
224 double const pfc = pfcij * pfcik * pfcjk;
225 double const r2ik = rik * rik;
226 double const rijs = rij - rs;
227 double const riks = rik - rs;
228 double const rjks = rjk - rs;
229 double const pexp = elementMap.atomicNumber(nej)
231 * exp(-eta * (rijs * rijs +
232 riks * riks +
233 rjks * rjks));
234 double const plambda = 1.0 + lambda * costijk;
235 double fg = pexp;
236 if (plambda <= 0.0) fg = 0.0;
237 else
238 {
239 if (useIntegerPow)
240 {
241 fg *= pow_int(plambda, zetaInt - 1);
242 }
243 else
244 {
245 fg *= pow(plambda, zeta - 1.0);
246 }
247 }
248 result += fg * plambda * pfc;
249
250 // Force calculation.
251 if (!derivatives) continue;
252 fg *= pnorm;
253 rinvijik *= pzl;
254 costijk *= pzl;
255 double const p2etapl = 2.0 * eta * plambda;
256 double const p1 = fg * (pfc * (rinvijik - costijk
257 / r2ij - p2etapl * rijs / rij) + pfcik
258 * pfcjk * pdfcij * plambda / rij);
259 double const p2 = fg * (pfc * (rinvijik - costijk
260 / r2ik - p2etapl * riks / rik) + pfcij
261 * pfcjk * pdfcik * plambda / rik);
262 double const p3 = fg * (pfc * (rinvijik + p2etapl
263 * rjks / rjk) - pfcij * pfcik * pdfcjk
264 * plambda / rjk);
265 drij *= p1 * scalingFactor;
266 drik *= p2 * scalingFactor;
267 drjk *= p3 * scalingFactor;
268
269 // Save force contributions in Atom storage.
270 atom.dGdr[index] += drij + drik;
271#ifndef N2P2_FULL_SFD_MEMORY
272 nj.dGdr[indexPerElement[nj.element]] -= drij + drjk;
273 nk.dGdr[indexPerElement[nk.element]] -= drik - drjk;
274#else
275 nj.dGdr[index] -= drij + drjk;
276 nk.dGdr[index] -= drik - drjk;
277#endif
278 } // rjk <= rc
279 } // rik <= rc
280 } // k
281 } // rij <= rc
282 } // j
283 result *= pnorm;
284
285 atom.G[index] = scale(result);
286
287 return;
288}
289
291{
292 return strpr(getPrintFormat().c_str(),
293 index + 1,
294 elementMap[ec].c_str(),
295 type,
296 subtype.c_str(),
298 rs / convLength,
299 rc / convLength,
300 lambda,
301 zeta,
303 lineNumber + 1);
304}
305
307{
308 vector<string> v = SymFncBaseCutoff::parameterInfo();
309 string s;
310 size_t w = sfinfoWidth;
311
312 s = "eta";
313 v.push_back(strpr((pad(s, w) + "%14.8E").c_str(),
315 s = "lambda";
316 v.push_back(strpr((pad(s, w) + "%14.8E").c_str(), lambda));
317 s = "zeta";
318 v.push_back(strpr((pad(s, w) + "%14.8E").c_str(), zeta));
319 s = "rs";
320 v.push_back(strpr((pad(s, w) + "%14.8E").c_str(), rs / convLength));
321
322 return v;
323}
324
326{
327 double const& r = distance * convLength;
328 double const p = exp(-eta * (r - rs) * (r - rs)) * fc.f(r);
329
330 return p * p * p;
331}
332
334{
335 return 2.0 * pow((1.0 + lambda * cos(angle)) / 2.0, zeta);
336}
337
339{
340 return true;
341}
342
343#ifndef N2P2_NO_SF_CACHE
345{
346 vector<string> v;
347 string s("");
348
349 s += subtype;
350 s += " ";
351 s += strpr("alpha = %16.8E", cutoffAlpha);
352 s += " ";
353 s += strpr("rc = %16.8E", rc / convLength);
354
355 for (size_t i = 0; i < elementMap.size(); ++i)
356 {
357 v.push_back(strpr("%zu f ", i) + s);
358 v.push_back(strpr("%zu df ", i) + s);
359 }
360
361 return v;
362}
363#endif
double f(double r) const
Cutoff function .
void fdf(double r, double &fc, double &dfc) const
Calculate cutoff function and derivative .
void setCutoffParameter(double const alpha)
Set parameter for polynomial cutoff function (CT_POLY).
void setCutoffRadius(double const cutoffRadius)
Set cutoff radius.
Contains element map.
Definition: ElementMap.h:30
std::size_t size() const
Get element map size.
Definition: ElementMap.h:140
std::size_t atomicNumber(std::size_t index) const
Get atomic number from element index.
Definition: ElementMap.h:145
Intermediate class for SFs based on cutoff functions.
std::string subtype
Subtype string (specifies cutoff type).
CutoffFunction fc
Cutoff function used by this symmetry function.
CutoffFunction::CutoffType cutoffType
Cutoff type used by this symmetry function.
virtual std::vector< std::string > parameterInfo() const
Get description with parameter names and values.
double cutoffAlpha
Cutoff parameter .
Weighted angular symmetry function (type 13)
virtual double calculateAngularPart(double angle) const
Calculate (partial) symmetry function value for one given angle.
virtual bool checkRelevantElement(std::size_t index) const
Check whether symmetry function is relevant for given element.
int zetaInt
Integer version of .
virtual std::string getSettingsLine() const
Get settings file line from currently set parameters.
double rs
Shift of gaussian.
virtual double calculateRadialPart(double distance) const
Calculate (partial) symmetry function value for one given distance.
double lambda
Cosine shift factor.
virtual std::string parameterLine() const
Give symmetry function parameters in one line.
virtual bool operator==(SymFnc const &rhs) const
Overload == operator.
bool useIntegerPow
Whether to use integer version of power function (faster).
double eta
Width of gaussian.
virtual bool operator<(SymFnc const &rhs) const
Overload < operator.
double zeta
Exponent of cosine term.
virtual void setParameters(std::string const &parameterString)
Set symmetry function parameters.
virtual void changeLengthUnit(double convLength)
Change length unit.
virtual std::vector< std::string > getCacheIdentifiers() const
Get unique cache identifiers.
virtual void calculate(Atom &atom, bool const derivatives) const
Calculate symmetry function for one atom.
virtual std::vector< std::string > parameterInfo() const
Get description with parameter names and values.
Symmetry function base class.
Definition: SymFnc.h:40
double convLength
Data set normalization length conversion factor.
Definition: SymFnc.h:296
std::size_t type
Symmetry function type.
Definition: SymFnc.h:268
std::set< std::string > parameters
Set with symmetry function parameter IDs (lookup for printing).
Definition: SymFnc.h:300
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
ElementMap elementMap
Copy of element map.
Definition: SymFnc.h:270
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
static std::size_t const sfinfoWidth
Width of the SFINFO parameter description field (see parameterInfo()).
Definition: SymFnc.h:309
std::size_t minNeighbors
Minimum number of neighbors required.
Definition: SymFnc.h:278
std::size_t lineNumber
Line number.
Definition: SymFnc.h:274
std::string getPrintFormat() const
Generate format string for symmetry function parameter printing.
Definition: SymFnc.cpp:285
Definition: Atom.h:29
string pad(string const &input, size_t num, char fill, bool right)
Definition: utility.cpp:79
string strpr(const char *format,...)
String version of printf function.
Definition: utility.cpp:90
vector< string > split(string const &input, char delimiter)
Split string at each delimiter.
Definition: utility.cpp:33
string reduce(string const &line, string const &whitespace, string const &fill)
Replace multiple whitespaces with fill.
Definition: utility.cpp:60
double pow_int(double x, int n)
Integer version of power function, "fast exponentiation algorithm".
Definition: utility.cpp:292
size_t p
Definition: nnp-cutoff.cpp:33
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::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
std::size_t numNeighbors
Total number of neighbors.
Definition: Atom.h:109
Vector in 3 dimensional real space.
Definition: Vec3D.h:30
double norm2() const
Calculate square of norm of vector.
Definition: Vec3D.h:299