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 symbol (elementMap.symbol(index) )
62{
63}
64
65Element::~Element()
66{
68}
69
71{
72 for (auto& s : symmetryFunctions) delete s;
73 symmetryFunctions.clear();
74 for (auto& s : symmetryFunctionGroups) delete s;
76
77 return;
78}
79
80void Element::addSymmetryFunction(string const& parameters,
81 size_t const& lineNumber)
82{
83 vector<string> args = split(reduce(parameters));
84 size_t type = (size_t)atoi(args.at(1).c_str());
85
86 if (type == 2)
87 {
89 }
90 else if (type == 3)
91 {
93 }
94 else if (type == 9)
95 {
97 }
98 else if (type == 12)
99 {
101 }
102 else if (type == 13)
103 {
105 }
106 else if (type == 20)
107 {
109 }
110 else if (type == 21)
111 {
113 }
114 else if (type == 22)
115 {
117 }
118 else if (type == 23)
119 {
121 }
122 else if (type == 24)
123 {
125 }
126 else if (type == 25)
127 {
129 }
130 else
131 {
132 throw runtime_error("ERROR: Unknown symmetry function type.\n");
133 }
134
135 symmetryFunctions.back()->setParameters(parameters);
136 symmetryFunctions.back()->setLineNumber(lineNumber);
137
138 return;
139}
140
142{
143 for (vector<SymFnc*>::iterator it = symmetryFunctions.begin();
144 it != symmetryFunctions.end(); ++it)
145 {
146 (*it)->changeLengthUnit(convLength);
147 }
148
149 return;
150}
151
153{
154 sort(symmetryFunctions.begin(),
155 symmetryFunctions.end(),
156 comparePointerTargets<SymFnc>);
157
158 for (size_t i = 0; i < symmetryFunctions.size(); ++i)
159 {
160 symmetryFunctions.at(i)->setIndex(i);
161 }
162
163 return;
164}
165
167{
168 vector<string> v;
169
170 for (vector<SymFnc*>::const_iterator
171 sf = symmetryFunctions.begin(); sf != symmetryFunctions.end(); ++sf)
172 {
173 v.push_back((*sf)->parameterLine());
174 }
175
176 return v;
177}
178
180{
181 vector<string> v;
182
183 for (vector<SymFnc*>::const_iterator
184 sf = symmetryFunctions.begin(); sf != symmetryFunctions.end(); ++sf)
185 {
186 v.push_back((*sf)->scalingLine());
187 }
188
189 return v;
190}
191
193{
194 for (vector<SymFnc*>::const_iterator
195 sf = symmetryFunctions.begin(); sf != symmetryFunctions.end(); ++sf)
196 {
197 bool createNewGroup = true;
198 for (vector<SymGrp*>::const_iterator
199 sfg = symmetryFunctionGroups.begin();
200 sfg != symmetryFunctionGroups.end(); ++sfg)
201 {
202 if ((*sfg)->addMember((*sf)))
203 {
204 createNewGroup = false;
205 break;
206 }
207 }
208 if (createNewGroup)
209 {
210 if ((*sf)->getType() == 2)
211 {
212 symmetryFunctionGroups.push_back((SymGrp*)
214 }
215 else if ((*sf)->getType() == 3)
216 {
217 symmetryFunctionGroups.push_back((SymGrp*)
219 }
220 else if ((*sf)->getType() == 9)
221 {
222 symmetryFunctionGroups.push_back((SymGrp*)
224 }
225 else if ((*sf)->getType() == 12)
226 {
227 symmetryFunctionGroups.push_back((SymGrp*)
229 }
230 else if ((*sf)->getType() == 13)
231 {
232 symmetryFunctionGroups.push_back((SymGrp*)
234 }
235 else if ((*sf)->getType() == 20)
236 {
237 symmetryFunctionGroups.push_back((SymGrp*)
239 }
240 else if ((*sf)->getType() == 21)
241 {
242 symmetryFunctionGroups.push_back((SymGrp*)
244 }
245 else if ((*sf)->getType() == 22)
246 {
247 symmetryFunctionGroups.push_back((SymGrp*)
249 }
250 else if ((*sf)->getType() == 23)
251 {
252 symmetryFunctionGroups.push_back((SymGrp*)
254 }
255 else if ((*sf)->getType() == 24)
256 {
257 symmetryFunctionGroups.push_back((SymGrp*)
259 }
260 else if ((*sf)->getType() == 25)
261 {
262 symmetryFunctionGroups.push_back((SymGrp*)
264 }
265 else
266 {
267 throw runtime_error("ERROR: Unknown symmetry function group"
268 " type.\n");
269 }
270 symmetryFunctionGroups.back()->addMember(*sf);
271 }
272 }
273
274 sort(symmetryFunctionGroups.begin(),
276 comparePointerTargets<SymGrp>);
277
278 for (size_t i = 0; i < symmetryFunctionGroups.size(); ++i)
279 {
280 symmetryFunctionGroups.at(i)->sortMembers();
281 symmetryFunctionGroups.at(i)->setIndex(i);
282 }
283
284 return;
285}
286
288{
289 symmetryFunctionTable.clear();
291 for (auto const& s : symmetryFunctions)
292 {
293 for (size_t i = 0; i < elementMap.size(); ++i)
294 {
295 if (s->checkRelevantElement(i))
296 {
297 s->setIndexPerElement(i, symmetryFunctionTable.at(i).size());
298 symmetryFunctionTable.at(i).push_back(s->getIndex());
299 }
300 }
301 }
303 for (size_t i = 0; i < elementMap.size(); ++i)
304 {
305 symmetryFunctionNumTable.push_back(symmetryFunctionTable.at(i).size());
306 }
307
308 return;
309}
310
312{
313 vector<string> v;
314
315 for (vector<SymGrp*>::const_iterator
316 it = symmetryFunctionGroups.begin();
317 it != symmetryFunctionGroups.end(); ++it)
318 {
319 vector<string> lines = (*it)->parameterLines();
320 v.insert(v.end(), lines.begin(), lines.end());
321 }
322
323 return v;
324}
325
327 double const cutoffAlpha)
328{
329 for (vector<SymFnc*>::const_iterator
330 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
331 {
332 SymFncBaseCutoff* sfcb = dynamic_cast<SymFncBaseCutoff*>(*it);
333 if (sfcb != nullptr)
334 {
335 sfcb->setCutoffFunction(cutoffType, cutoffAlpha);
336 }
337 }
338
339 return;
340}
341
343{
344 for (size_t i = 0; i < symmetryFunctions.size(); ++i)
345 {
346 string scalingLine = strpr("%d %d 0.0 0.0 0.0 0.0",
347 symmetryFunctions.at(i)->getEc(),
348 i + 1);
349 symmetryFunctions.at(i)->setScalingType(SymFnc::ST_NONE,
350 scalingLine,
351 0.0,
352 0.0);
353 }
354 for (size_t i = 0; i < symmetryFunctionGroups.size(); ++i)
355 {
356 symmetryFunctionGroups.at(i)->setScalingFactors();
357 }
358
359 return;
360}
361
363 vector<string> const& statisticsLine,
364 double Smin,
365 double Smax) const
366{
367 for (size_t i = 0; i < symmetryFunctions.size(); ++i)
368 {
369 symmetryFunctions.at(i)->setScalingType(scalingType,
370 statisticsLine.at(i),
371 Smin,
372 Smax);
373 }
374 for (size_t i = 0; i < symmetryFunctionGroups.size(); ++i)
375 {
376 symmetryFunctionGroups.at(i)->setScalingFactors();
377 }
378
379 return;
380}
381
383{
384 size_t minNeighbors = 0;
385
386 for (vector<SymFnc*>::const_iterator
387 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
388 {
389 minNeighbors = max((*it)->getMinNeighbors(), minNeighbors);
390 }
391
392 return minNeighbors;
393}
394
396{
397 double minCutoffRadius = numeric_limits<double>::max();
398
399 // MPB: Hack to work with negative radii
400 // Exploit the fact that all allowed symmetry functions are either
401 // defined for a domain > 0 or have to be symmetric around 0.
402
403 for (vector<SymFnc*>::const_iterator
404 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
405 {
406 minCutoffRadius = min((*it)->getRc(), minCutoffRadius);
407 }
408
409 return minCutoffRadius;
410}
411
413{
414 double maxCutoffRadius = 0.0;
415
416 for (vector<SymFnc*>::const_iterator
417 it = symmetryFunctions.begin(); it != symmetryFunctions.end(); ++it)
418 {
419 maxCutoffRadius = max((*it)->getRc(), maxCutoffRadius);
420 }
421
422 return maxCutoffRadius;
423}
424
426 bool const derivatives) const
427{
428 for (vector<SymFnc*>::const_iterator
429 it = symmetryFunctions.begin();
430 it != symmetryFunctions.end(); ++it)
431 {
432 //cerr << (*it)->getIndex() << " "
433 // << elementMap[(*it)->getEc()] << " "
434 // << (*it)->getUnique() << "\n";
435 //auto cid = (*it)->getCacheIdentifiers();
436 //for (auto icid : cid) cerr << icid << "\n";
437 //auto ci = (*it)->getCacheIndices();
438 //for (auto eci : ci)
439 //{
440 // for (auto ici : eci) cerr << ici << " ";
441 // cerr << "\n";
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 calculateSymmetryFunctions(Atom &atom, bool const derivatives) const
Calculate symmetry functions.
Definition: Element.cpp:425
void setCutoffFunction(CutoffFunction::CutoffType const cutoffType, double const cutoffAlpha)
Set cutoff function for all symmetry functions.
Definition: Element.cpp:326
std::vector< std::string > infoSymmetryFunctionParameters() const
Print symmetry function parameter value information.
Definition: Element.cpp:166
ElementMap elementMap
Copy of element map.
Definition: Element.h:236
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:232
void sortSymmetryFunctions()
Sort all symmetry function.
Definition: Element.cpp:152
std::vector< SymFnc * > symmetryFunctions
Vector of pointers to symmetry functions.
Definition: Element.h:254
std::vector< std::string > infoSymmetryFunctionGroups() const
Print symmetry function group info.
Definition: Element.cpp:311
void setupSymmetryFunctionMemory()
Extract relevant symmetry function combinations for derivative memory.
Definition: Element.cpp:287
std::vector< std::string > infoSymmetryFunctionScaling() const
Print symmetry function scaling information.
Definition: Element.cpp:179
double getMinCutoffRadius() const
Get minimum cutoff radius of all symmetry functions.
Definition: Element.cpp:395
std::vector< std::vector< SFCacheList > > cacheLists
Symmetry function cache lists.
Definition: Element.h:251
void setupSymmetryFunctionGroups()
Set up symmetry function groups.
Definition: Element.cpp:192
void addSymmetryFunction(std::string const &parameters, std::size_t const &lineNumber)
Add one symmetry function.
Definition: Element.cpp:80
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:238
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:362
std::vector< std::vector< std::size_t > > symmetryFunctionTable
List of symmetry function indices relevant for each neighbor element.
Definition: Element.h:248
std::string symbol
Element symbol.
Definition: Element.h:244
std::size_t getMinNeighbors() const
Get maximum of required minimum number of neighbors for all symmetry functions for this element.
Definition: Element.cpp:382
std::vector< SymGrp * > symmetryFunctionGroups
Vector of pointers to symmetry function groups.
Definition: Element.h:256
std::vector< std::size_t > symmetryFunctionNumTable
Number of relevant symmetry functions for each neighbor element.
Definition: Element.h:246
double getMaxCutoffRadius() const
Get maximum cutoff radius of all symmetry functions.
Definition: Element.cpp:412
void clearSymmetryFunctions()
Clear all symmetry functions and groups.
Definition: Element.cpp:70
void setScalingNone() const
Set no scaling of symmetry function.
Definition: Element.cpp:342
void changeLengthUnitSymmetryFunctions(double convLength)
Change length unit for all symmetry functions.
Definition: Element.cpp:141
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:28
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
Storage for a single atom.
Definition: Atom.h:32
std::size_t numSymmetryFunctions
Number of symmetry functions used to describe the atom environment.
Definition: Atom.h:110
std::size_t indexStructure
Index number of structure this atom belongs to.
Definition: Atom.h:100
int64_t tag
Tag number of this atom.
Definition: Atom.h:102
std::size_t element
Element index of this atom.
Definition: Atom.h:104
std::vector< double > G
Symmetry function values.
Definition: Atom.h:134
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