n2p2 - A neural network potential package
Element.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 "Atom.h"
18#include "Element.h"
19#include "NeuralNetwork.h"
20#include "SymFnc.h"
21#include "SymFncBaseCutoff.h"
22#include "SymFncExpRad.h"
23#include "SymFncCompRad.h"
24#include "SymFncExpAngn.h"
25#include "SymFncExpAngw.h"
26#include "SymFncCompAngw.h"
27#include "SymFncCompAngn.h"
33#include "SymGrp.h"
34#include "SymGrpExpRad.h"
35#include "SymGrpCompRad.h"
36#include "SymGrpExpAngn.h"
37#include "SymGrpExpAngw.h"
38#include "SymGrpCompAngw.h"
39#include "SymGrpCompAngn.h"
45#include "utility.h"
46#include <iostream> // std::cerr
47#include <cinttypes> // PRId64
48#include <cstdlib> // atoi
49#include <algorithm> // std::sort, std::min, std::max
50#include <limits> // std::numeric_limits
51#include <stdexcept> // std::runtime_error
52
53using namespace std;
54using namespace nnp;
55
56Element::Element(size_t const index, ElementMap const& elementMap) :
57 elementMap (elementMap ),
58 index (index ),
59 atomicNumber (elementMap.atomicNumber(index)),
60 atomicEnergyOffset (0.0 ),
61 hardness (0.0 ),
62 qsigma (0.0 ),
63 symbol (elementMap.symbol(index) )
64{
65}
66
67Element::~Element()
68{
70}
71
73{
74 for (auto& s : symmetryFunctions) delete s;
75 symmetryFunctions.clear();
76 for (auto& s : symmetryFunctionGroups) delete s;
78
79 return;
80}
81
82void Element::addSymmetryFunction(string const& parameters,
83 size_t const& lineNumber)
84{
85 vector<string> args = split(reduce(parameters));
86 size_t type = (size_t)atoi(args.at(1).c_str());
87
88 if (type == 2)
89 {
91 }
92 else if (type == 3)
93 {
95 }
96 else if (type == 9)
97 {
99 }
100 else if (type == 12)
101 {
103 }
104 else if (type == 13)
105 {
107 }
108 else if (type == 20)
109 {
111 }
112 else if (type == 21)
113 {
115 }
116 else if (type == 22)
117 {
119 }
120 else if (type == 23)
121 {
123 }
124 else if (type == 24)
125 {
127 }
128 else if (type == 25)
129 {
131 }
132 else
133 {
134 throw runtime_error("ERROR: Unknown symmetry function type.\n");
135 }
136
137 symmetryFunctions.back()->setParameters(parameters);
138 symmetryFunctions.back()->setLineNumber(lineNumber);
139
140 return;
141}
142
144{
145 for (vector<SymFnc*>::iterator it = symmetryFunctions.begin();
146 it != symmetryFunctions.end(); ++it)
147 {
148 (*it)->changeLengthUnit(convLength);
149 }
150
151 return;
152}
153
155{
156 sort(symmetryFunctions.begin(),
157 symmetryFunctions.end(),
158 comparePointerTargets<SymFnc>);
159
160 for (size_t i = 0; i < symmetryFunctions.size(); ++i)
161 {
162 symmetryFunctions.at(i)->setIndex(i);
163 }
164
165 return;
166}
167
169{
170 vector<string> v;
171
172 for (vector<SymFnc*>::const_iterator
173 sf = symmetryFunctions.begin(); sf != symmetryFunctions.end(); ++sf)
174 {
175 v.push_back((*sf)->parameterLine());
176 }
177
178 return v;
179}
180
182{
183 vector<string> v;
184
185 for (vector<SymFnc*>::const_iterator
186 sf = symmetryFunctions.begin(); sf != symmetryFunctions.end(); ++sf)
187 {
188 v.push_back((*sf)->scalingLine());
189 }
190
191 return v;
192}
193
195{
196 for (vector<SymFnc*>::const_iterator
197 sf = symmetryFunctions.begin(); sf != symmetryFunctions.end(); ++sf)
198 {
199 bool createNewGroup = true;
200 for (vector<SymGrp*>::const_iterator
201 sfg = symmetryFunctionGroups.begin();
202 sfg != symmetryFunctionGroups.end(); ++sfg)
203 {
204 if ((*sfg)->addMember((*sf)))
205 {
206 createNewGroup = false;
207 break;
208 }
209 }
210 if (createNewGroup)
211 {
212 if ((*sf)->getType() == 2)
213 {
214 symmetryFunctionGroups.push_back((SymGrp*)
216 }
217 else if ((*sf)->getType() == 3)
218 {
219 symmetryFunctionGroups.push_back((SymGrp*)
221 }
222 else if ((*sf)->getType() == 9)
223 {
224 symmetryFunctionGroups.push_back((SymGrp*)
226 }
227 else if ((*sf)->getType() == 12)
228 {
229 symmetryFunctionGroups.push_back((SymGrp*)
231 }
232 else if ((*sf)->getType() == 13)
233 {
234 symmetryFunctionGroups.push_back((SymGrp*)
236 }
237 else if ((*sf)->getType() == 20)
238 {
239 symmetryFunctionGroups.push_back((SymGrp*)
241 }
242 else if ((*sf)->getType() == 21)
243 {
244 symmetryFunctionGroups.push_back((SymGrp*)
246 }
247 else if ((*sf)->getType() == 22)
248 {
249 symmetryFunctionGroups.push_back((SymGrp*)
251 }
252 else if ((*sf)->getType() == 23)
253 {
254 symmetryFunctionGroups.push_back((SymGrp*)
256 }
257 else if ((*sf)->getType() == 24)
258 {
259 symmetryFunctionGroups.push_back((SymGrp*)
261 }
262 else if ((*sf)->getType() == 25)
263 {
264 symmetryFunctionGroups.push_back((SymGrp*)
266 }
267 else
268 {
269 throw runtime_error("ERROR: Unknown symmetry function group"
270 " type.\n");
271 }
272 symmetryFunctionGroups.back()->addMember(*sf);
273 }
274 }
275
276 sort(symmetryFunctionGroups.begin(),
278 comparePointerTargets<SymGrp>);
279
280 for (size_t i = 0; i < symmetryFunctionGroups.size(); ++i)
281 {
282 symmetryFunctionGroups.at(i)->sortMembers();
283 symmetryFunctionGroups.at(i)->setIndex(i);
284 }
285
286 return;
287}
288
290{
291 symmetryFunctionTable.clear();
293 for (auto const& s : symmetryFunctions)
294 {
295 for (size_t i = 0; i < elementMap.size(); ++i)
296 {
297 if (s->checkRelevantElement(i))
298 {
299 s->setIndexPerElement(i, symmetryFunctionTable.at(i).size());
300 symmetryFunctionTable.at(i).push_back(s->getIndex());
301 }
302 }
303 }
305 for (size_t i = 0; i < elementMap.size(); ++i)
306 {
307 symmetryFunctionNumTable.push_back(symmetryFunctionTable.at(i).size());
308 }
309
310 return;
311}
312
314{
315 vector<string> v;
316
317 for (vector<SymGrp*>::const_iterator
318 it = symmetryFunctionGroups.begin();
319 it != symmetryFunctionGroups.end(); ++it)
320 {
321 vector<string> lines = (*it)->parameterLines();
322 v.insert(v.end(), lines.begin(), lines.end());
323 }
324
325 return v;
326}
327
329 double const cutoffAlpha)
330{
331 for (vector<SymFnc*>::const_iterator
332 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
333 {
334 SymFncBaseCutoff* sfcb = dynamic_cast<SymFncBaseCutoff*>(*it);
335 if (sfcb != nullptr)
336 {
337 sfcb->setCutoffFunction(cutoffType, cutoffAlpha);
338 }
339 }
340
341 return;
342}
343
345{
346 for (size_t i = 0; i < symmetryFunctions.size(); ++i)
347 {
348 string scalingLine = strpr("%d %d 0.0 0.0 0.0 0.0",
349 symmetryFunctions.at(i)->getEc(),
350 i + 1);
351 symmetryFunctions.at(i)->setScalingType(SymFnc::ST_NONE,
352 scalingLine,
353 0.0,
354 0.0);
355 }
356 for (size_t i = 0; i < symmetryFunctionGroups.size(); ++i)
357 {
358 symmetryFunctionGroups.at(i)->setScalingFactors();
359 }
360
361 return;
362}
363
365 vector<string> const& statisticsLine,
366 double Smin,
367 double Smax) const
368{
369 for (size_t i = 0; i < symmetryFunctions.size(); ++i)
370 {
371 symmetryFunctions.at(i)->setScalingType(scalingType,
372 statisticsLine.at(i),
373 Smin,
374 Smax);
375 }
376 for (size_t i = 0; i < symmetryFunctionGroups.size(); ++i)
377 {
378 symmetryFunctionGroups.at(i)->setScalingFactors();
379 }
380
381 return;
382}
383
385{
386 size_t minNeighbors = 0;
387
388 for (vector<SymFnc*>::const_iterator
389 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
390 {
391 minNeighbors = max((*it)->getMinNeighbors(), minNeighbors);
392 }
393
394 return minNeighbors;
395}
396
398{
399 double minCutoffRadius = numeric_limits<double>::max();
400
401 // MPB: Hack to work with negative radii
402 // Exploit the fact that all allowed symmetry functions are either
403 // defined for a domain > 0 or have to be symmetric around 0.
404
405 for (vector<SymFnc*>::const_iterator
406 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
407 {
408 minCutoffRadius = min((*it)->getRc(), minCutoffRadius);
409 }
410
411 return minCutoffRadius;
412}
413
415{
416 double maxCutoffRadius = 0.0;
417
418 for (vector<SymFnc*>::const_iterator
419 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
420 {
421 maxCutoffRadius = max((*it)->getRc(), maxCutoffRadius);
422 }
423
424 return maxCutoffRadius;
425}
426
427void Element::getCutoffRadii(std::vector<double>& cutoffs) const
428{
429 for (auto const& sf : symmetryFunctions)
430 {
431 double rc = sf->getRc();
432 if (!vectorContains(cutoffs,rc)) cutoffs.push_back(rc);
433 }
434}
435
437 bool const derivatives) const
438{
439 for (vector<SymFnc*>::const_iterator
440 it = symmetryFunctions.begin();
441 it != symmetryFunctions.end(); ++it)
442 {
443 (*it)->calculate(atom, derivatives);
444 }
445
446 return;
447}
448
450 bool const derivatives) const
451{
452 for (vector<SymGrp*>::const_iterator
453 it = symmetryFunctionGroups.begin();
454 it != symmetryFunctionGroups.end(); ++it)
455 {
456 (*it)->calculate(atom, derivatives);
457 }
458
459 return;
460}
461
463{
464 size_t countExtrapolationWarnings = 0;
465 double epsilon = 1000.0 * numeric_limits<double>::epsilon();
466
467 if (atom.element != index)
468 {
469 throw runtime_error("ERROR: Atom has a different element index.\n");
470 }
471
472 if (atom.numSymmetryFunctions != symmetryFunctions.size())
473 {
474 throw runtime_error("ERROR: Number of symmetry functions"
475 " does not match.\n");
476 }
477
478 for (size_t i = 0; i < atom.G.size(); ++i)
479 {
480 double const Gmin = symmetryFunctions.at(i)->getGmin();
481 double const Gmax = symmetryFunctions.at(i)->getGmax();
482 double const value = symmetryFunctions.at(i)->unscale(atom.G.at(i));
483 size_t const sfindex = symmetryFunctions.at(i)->getIndex();
484 size_t const type = symmetryFunctions.at(i)->getType();
486 {
487 statistics.addValue(sfindex, atom.G.at(i));
488 }
489
490 // Avoid "fake" EWs at the boundaries.
491 if (value + epsilon < Gmin || value - epsilon > Gmax)
492 {
493 countExtrapolationWarnings++;
495 {
497 type,
498 value,
499 Gmin,
500 Gmax,
501 symbol,
502 atom.indexStructure,
503 atom.tag);
504 }
506 {
507 cerr << strpr("### NNP EXTRAPOLATION WARNING ### "
508 "STRUCTURE: %6zu ATOM: %9" PRId64 " ELEMENT: "
509 "%2s SYMFUNC: %4zu TYPE: %2zu VALUE: %10.3E "
510 "MIN: %10.3E MAX: %10.3E\n",
511 atom.indexStructure,
512 atom.tag,
513 symbol.c_str(),
514 sfindex + 1,
515 type,
516 value,
517 Gmin,
518 Gmax);
519 }
521 {
522 throw out_of_range(
523 strpr("### NNP EXTRAPOLATION WARNING ### "
524 "STRUCTURE: %6zu ATOM: %9" PRId64 " ELEMENT: "
525 "%2s SYMFUNC: %4zu TYPE: %2zu VALUE: %10.3E "
526 "MIN: %10.3E MAX: %10.3E\n"
527 "ERROR: Symmetry function value out of range.\n",
528 atom.indexStructure,
529 atom.tag,
530 symbol.c_str(),
531 sfindex + 1,
532 type,
533 value,
534 Gmin,
535 Gmax));
536 }
537 }
538 }
539
540 return countExtrapolationWarnings;
541}
542
543#ifndef N2P2_NO_SF_CACHE
544void Element::setCacheIndices(vector<vector<SFCacheList>> cacheLists)
545{
546 this->cacheLists = cacheLists;
547 for (size_t i = 0; i < cacheLists.size(); ++i)
548 {
549 for (size_t j = 0; j < cacheLists.at(i).size(); ++j)
550 {
551 SFCacheList const& c = cacheLists.at(i).at(j);
552 for (size_t k = 0; k < c.indices.size(); ++k)
553 {
554 SymFnc*& sf = symmetryFunctions.at(c.indices.at(k));
555 sf->addCacheIndex(c.element, j, c.identifier);
556 }
557 }
558 }
559
560 return;
561}
562
563vector<size_t> Element::getCacheSizes() const
564{
565 vector<size_t> cacheSizes;
566 for (auto const& c : cacheLists)
567 {
568 cacheSizes.push_back(c.size());
569 }
570
571 return cacheSizes;
572}
573#endif
CutoffType
List of available cutoff function types.
Contains element map.
Definition: ElementMap.h:30
std::size_t size() const
Get element map size.
Definition: ElementMap.h:140
void getCutoffRadii(std::vector< double > &cutoffs) const
Get all different cutoff radii belonging to this element.
Definition: Element.cpp:427
void calculateSymmetryFunctions(Atom &atom, bool const derivatives) const
Calculate symmetry functions.
Definition: Element.cpp:436
void setCutoffFunction(CutoffFunction::CutoffType const cutoffType, double const cutoffAlpha)
Set cutoff function for all symmetry functions.
Definition: Element.cpp:328
std::vector< std::string > infoSymmetryFunctionParameters() const
Print symmetry function parameter value information.
Definition: Element.cpp:168
ElementMap elementMap
Copy of element map.
Definition: Element.h:253
void calculateSymmetryFunctionGroups(Atom &atom, bool const derivatives) const
Calculate symmetry functions via groups.
Definition: Element.cpp:449
std::vector< std::size_t > getCacheSizes() const
Get cache sizes for each neighbor atom element.
Definition: Element.cpp:563
SymFncStatistics statistics
Symmetry function statistics.
Definition: Element.h:249
void sortSymmetryFunctions()
Sort all symmetry function.
Definition: Element.cpp:154
std::vector< SymFnc * > symmetryFunctions
Vector of pointers to symmetry functions.
Definition: Element.h:275
std::vector< std::string > infoSymmetryFunctionGroups() const
Print symmetry function group info.
Definition: Element.cpp:313
void setupSymmetryFunctionMemory()
Extract relevant symmetry function combinations for derivative memory.
Definition: Element.cpp:289
std::vector< std::string > infoSymmetryFunctionScaling() const
Print symmetry function scaling information.
Definition: Element.cpp:181
double getMinCutoffRadius() const
Get minimum cutoff radius of all symmetry functions.
Definition: Element.cpp:397
std::vector< std::vector< SFCacheList > > cacheLists
Symmetry function cache lists.
Definition: Element.h:272
void setupSymmetryFunctionGroups()
Set up symmetry function groups.
Definition: Element.cpp:194
void addSymmetryFunction(std::string const &parameters, std::size_t const &lineNumber)
Add one symmetry function.
Definition: Element.cpp:82
void setCacheIndices(std::vector< std::vector< SFCacheList > > cacheLists)
Set cache indices for all symmetry functions of this element.
Definition: Element.cpp:544
std::size_t updateSymmetryFunctionStatistics(Atom const &atom)
Update symmetry function statistics.
Definition: Element.cpp:462
std::size_t index
Global index of this element.
Definition: Element.h:255
void setScaling(SymFnc::ScalingType scalingType, std::vector< std::string > const &statisticsLine, double minS, double maxS) const
Set scaling of all symmetry functions.
Definition: Element.cpp:364
std::vector< std::vector< std::size_t > > symmetryFunctionTable
List of symmetry function indices relevant for each neighbor element.
Definition: Element.h:269
std::string symbol
Element symbol.
Definition: Element.h:265
std::size_t getMinNeighbors() const
Get maximum of required minimum number of neighbors for all symmetry functions for this element.
Definition: Element.cpp:384
std::vector< SymGrp * > symmetryFunctionGroups
Vector of pointers to symmetry function groups.
Definition: Element.h:277
std::vector< std::size_t > symmetryFunctionNumTable
Number of relevant symmetry functions for each neighbor element.
Definition: Element.h:267
double getMaxCutoffRadius() const
Get maximum cutoff radius of all symmetry functions.
Definition: Element.cpp:414
void clearSymmetryFunctions()
Clear all symmetry functions and groups.
Definition: Element.cpp:72
void setScalingNone() const
Set no scaling of symmetry function.
Definition: Element.cpp:344
void changeLengthUnitSymmetryFunctions(double convLength)
Change length unit for all symmetry functions.
Definition: Element.cpp:143
Intermediate class for SFs based on cutoff functions.
void setCutoffFunction(CutoffFunction::CutoffType cutoffType, double cutoffAlpha)
Set cutoff function type and parameter.
Weighted narrow angular symmetry function with compact support (type 24)
Narrow angular symmetry function with compact support (type 21)
Weighted wide angular symmetry function with compact support (type 25)
Wide angular symmetry function with compact support (type 22)
Weighted radial symmetry function with compact support (type 23)
Radial symmetry function with compact support (type 20)
Definition: SymFncCompRad.h:56
Weighted angular symmetry function (type 13)
Angular symmetry function (type 3)
Definition: SymFncExpAngn.h:55
Angular symmetry function (type 9)
Definition: SymFncExpAngw.h:54
Weighted radial symmetry function (type 12)
Radial symmetry function (type 2)
Definition: SymFncExpRad.h:49
bool stopOnExtrapolationWarnings
Whether to raise an exception in case of extrapolation warnings.
void addValue(std::size_t index, double value)
Update symmetry function statistics with one value.
bool collectStatistics
Whether statistics are gathered.
void addExtrapolationWarning(std::size_t index, std::size_t type, double value, double Gmin, double Gmax, std::string element, std::size_t indexStructure, std::size_t indexAtom)
Add extrapolation warning entry.
bool collectExtrapolationWarnings
Whether extrapolation warnings are logged.
bool writeExtrapolationWarnings
Whether to write out extrapolation warnings immediately as they occur.
Symmetry function base class.
Definition: SymFnc.h:40
ScalingType
List of available scaling types.
Definition: SymFnc.h:44
@ ST_NONE
Definition: SymFnc.h:47
void addCacheIndex(std::size_t element, std::size_t cacheIndex, std::string cacheIdentifier)
Add one cache index for given neighbor element and check identifier.
Definition: SymFnc.cpp:106
Weighted narrow angular symmetry function with compact support (type 24)
Narrow angular symmetry function with compact support (type 21)
Weighted wide angular symmetry function with compact support (type 25)
Wide angular symmetry function with compact support (type 22)
Weighted radial symmetry function with compact support (type 23)
Radial symmetry function with compact support (type 20)
Definition: SymGrpCompRad.h:48
Weighted angular symmetry function group (type 13)
Angular symmetry function group (type 3)
Definition: SymGrpExpAngn.h:51
Angular symmetry function group (type 3)
Definition: SymGrpExpAngw.h:50
Weighted radial symmetry function group (type 12)
Radial symmetry function group (type 2)
Definition: SymGrpExpRad.h:47
Definition: Atom.h:29
string strpr(const char *format,...)
String version of printf function.
Definition: utility.cpp:90
bool vectorContains(std::vector< T > const &stdVec, T value)
Test if vector contains specified value.
Definition: utility.h:166
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
Storage for a single atom.
Definition: Atom.h:33
std::size_t numSymmetryFunctions
Number of symmetry functions used to describe the atom environment.
Definition: Atom.h:113
std::size_t indexStructure
Index number of structure this atom belongs to.
Definition: Atom.h:103
int64_t tag
Tag number of this atom.
Definition: Atom.h:105
std::size_t element
Element index of this atom.
Definition: Atom.h:107
std::vector< double > G
Symmetry function values.
Definition: Atom.h:146
List of symmetry functions corresponding to one cache identifier.
Definition: Element.h:45
std::size_t element
Neighbor element index.
Definition: Element.h:47
std::string identifier
Cache identifier string.
Definition: Element.h:49
std::vector< std::size_t > indices
Symmetry function indices for this cache.
Definition: Element.h:51