29#ifndef N2P2_NO_SF_CACHE
40Mode::Mode() : nnpType (
NNPType::HDNNP_2G),
42 checkExtrapolationWarnings(false ),
44 maxCutoffRadius (0.0 ),
58 log <<
"*****************************************"
59 "**************************************\n";
61 log <<
"WELCOME TO n²p², A SOFTWARE PACKAGE FOR NEURAL NETWORK "
63 log <<
"-------------------------------------------------------"
68 log <<
"------------------------------------------------------------\n";
71 log <<
"Compile date/time : " __DATE__
" " __TIME__
"\n";
72 log <<
"------------------------------------------------------------\n";
74 log <<
"Features/Flags:\n";
75 log <<
"------------------------------------------------------------\n";
76 log <<
"Symmetry function groups : ";
77#ifndef N2P2_NO_SF_GROUPS
82 log <<
"Symmetry function cache : ";
83#ifndef N2P2_NO_SF_CACHE
88 log <<
"Timing function available : ";
94 log <<
"Asymmetric polynomial SFs : ";
95#ifndef N2P2_NO_ASYM_POLY
100 log <<
"SF low neighbor number check : ";
101#ifndef N2P2_NO_NEIGH_CHECK
106 log <<
"SF derivative memory layout : ";
107#ifndef N2P2_FULL_SFD_MEMORY
112 log <<
"MPI explicitly disabled : ";
119 log <<
strpr(
"OpenMP threads : %d\n", omp_get_max_threads());
121 log <<
"------------------------------------------------------------\n";
124 log <<
"Please cite the following papers when publishing results "
125 "obtained with n²p²:\n";
126 log <<
"-----------------------------------------"
127 "--------------------------------------\n";
128 log <<
" * General citation for n²p² and the LAMMPS interface:\n";
130 log <<
" Singraber, A.; Behler, J.; Dellago, C.\n";
131 log <<
" Library-Based LAMMPS Implementation of High-Dimensional\n";
132 log <<
" Neural Network Potentials.\n";
133 log <<
" J. Chem. Theory Comput. 2019 15 (3), 1827–1840.\n";
134 log <<
" https://doi.org/10.1021/acs.jctc.8b00770\n";
135 log <<
"-----------------------------------------"
136 "--------------------------------------\n";
137 log <<
" * Additionally, if you use the NNP training features of n²p²:\n";
139 log <<
" Singraber, A.; Morawietz, T.; Behler, J.; Dellago, C.\n";
140 log <<
" Parallel Multistream Training of High-Dimensional Neural\n";
141 log <<
" Network Potentials.\n";
142 log <<
" J. Chem. Theory Comput. 2019, 15 (5), 3075–3092.\n";
143 log <<
" https://doi.org/10.1021/acs.jctc.8b01092\n";
144 log <<
"-----------------------------------------"
145 "--------------------------------------\n";
146 log <<
" * Additionally, if polynomial symmetry functions are used:\n";
148 log <<
" Bircher, M. P.; Singraber, A.; Dellago, C.\n";
149 log <<
" Improved Description of Atomic Environments Using Low-Cost\n";
150 log <<
" Polynomial Functions with Compact Support.\n";
151 log <<
" arXiv:2010.14414 [cond-mat, physics:physics] 2020.\n";
152 log <<
" https://arxiv.org/abs/2010.14414\n";
155 log <<
"*****************************************"
156 "**************************************\n";
164 log <<
"*** SETUP: SETTINGS FILE ****************"
165 "**************************************\n";
170 if (numCriticalProblems > 0)
172 throw runtime_error(
strpr(
"ERROR: %zu critical problem(s) were found "
173 "in settings file.\n", numCriticalProblems));
178 string nnpTypeString =
settings[
"nnp_type"];
187 log <<
"This settings file defines a short-range NNP (2G-HDNNP).\n";
191 log <<
"This settings file defines a NNP with electrostatics and\n"
192 "non-local charge transfer (4G-HDNNP).\n";
196 log <<
"This settings file defines a short-range NNP similar to\n"
197 "4G-HDNNP with additional charge NN but with neither\n"
198 "electrostatics nor global charge equilibration\n"
199 "(method by M. Bircher).\n";
203 throw runtime_error(
"ERROR: Unknown NNP type.\n");
206 log <<
"*****************************************"
207 "**************************************\n";
214 bool initialHardness)
224#ifndef N2P2_FULL_SFD_MEMORY
227#ifndef N2P2_NO_SF_CACHE
230#ifndef N2P2_NO_SF_GROUPS
243 log <<
"*** SETUP: NORMALIZATION ****************"
244 "**************************************\n";
257 log <<
"Data set normalization is used.\n";
264 log <<
strpr(
"Conversion factor charge : %24.16E\n",
270 log <<
"Atomic energy offsets are used in addition to"
271 " data set normalization.\n";
272 log <<
"Offsets will be subtracted from reference energies BEFORE"
273 " normalization is applied.\n";
282 log <<
"Data set normalization is not used.\n";
286 throw runtime_error(
"ERROR: Incorrect usage of normalization"
288 " Use all or none of \"mean_energy\", \"conv_energy\""
289 " and \"conv_length\".\n");
294 log <<
"*****************************************"
295 "**************************************\n";
304 log <<
"*** SETUP: ELEMENT MAP ******************"
305 "**************************************\n";
316 log <<
"*****************************************"
317 "**************************************\n";
325 log <<
"*** SETUP: ELEMENTS *********************"
326 "**************************************\n";
332 throw runtime_error(
"ERROR: Inconsistent number of elements.\n");
344 for (settings::Settings::KeyMap::const_iterator it = r.first;
345 it != r.second; ++it)
347 vector<string> args =
split(
reduce(it->second.first));
350 setAtomicEnergyOffset(atof(args.at(1).c_str()));
353 log <<
"Atomic energy offsets per element:\n";
356 log <<
strpr(
"Element %2zu: %16.8E\n",
357 i,
elements.at(i).getAtomicEnergyOffset());
359 log <<
"Energy offsets are automatically subtracted from reference "
362 log <<
"*****************************************"
363 "**************************************\n";
369 string directoryPrefix,
370 string fileNameFormat)
373 log <<
"*** SETUP: ELECTROSTATICS ***************"
374 "**************************************\n";
381 for (settings::Settings::KeyMap::const_iterator it = r.first;
382 it != r.second; ++it)
384 vector<string> args =
split(
reduce(it->second.first));
386 double hardness = atof(args.at(1).c_str());
388 elements.at(element).setHardness(hardness);
392 double hardness =
elements.at(i).getHardness();
394 log <<
strpr(
"Initial atomic hardness for element %2s: %16.8E\n",
401 string actualFileNameFormat = directoryPrefix + fileNameFormat;
402 log <<
strpr(
"Atomic hardness file name format: %s\n",
403 actualFileNameFormat.c_str());
406 string fileName =
strpr(actualFileNameFormat.c_str(),
408 log <<
strpr(
"Atomic hardness for element %2s from file %s: ",
413 if (data.size() != 1)
415 throw runtime_error(
"ERROR: Atomic hardness data is "
418 double hardness = data.at(0);
420 elements.at(i).setHardness(hardness);
428 double maxQsigma = 0.0;
430 for (settings::Settings::KeyMap::const_iterator it = r.first;
431 it != r.second; ++it)
433 vector<string> args =
split(
reduce(it->second.first));
435 double qsigma = atof(args.at(1).c_str());
437 elements.at(element).setQsigma(qsigma);
439 maxQsigma = max(qsigma, maxQsigma);
441 log <<
"Gaussian width of charge distribution per element:\n";
444 double qsigma =
elements.at(i).getQsigma();
446 log <<
strpr(
"Element %2zu: %16.8E\n",
454 string truncation_method_string =
455 settings[
"ewald_truncation_error_method"];
456 if (truncation_method_string ==
"0")
458 if (truncation_method_string ==
"1")
475 throw runtime_error(
"ERROR: ewald_truncation_error_method 1 requires "
478 log <<
strpr(
"Ewald truncation error method: %16d\n",
480 log <<
strpr(
"Ewald precision: %16.8E\n",
483 log <<
strpr(
"Ewald expected maximum charge: %16.8E\n",
496 vector<string> args =
split(
settings[
"screen_electrostatics"]);
497 double inner = atof(args.at(0).c_str());
498 double outer = atof(args.at(1).c_str());
500 if (args.size() > 2) type = args.at(2);
511 log <<
"Screening function not used.\n";
514 log <<
"*****************************************"
515 "**************************************\n";
523 log <<
"*** SETUP: CUTOFF FUNCTIONS *************"
524 "**************************************\n";
535 throw invalid_argument(
"ERROR: 0 <= alpha < 1.0 is required.\n");
539 log <<
"Inner cutoff = Symmetry function cutoff * alpha\n";
541 log <<
"Equal cutoff function type for all symmetry functions:\n";
545 log <<
"x := (r - rc * alpha) / (rc - rc * alpha)\n";
546 log <<
"f(x) = 1/2 * (cos(pi*x) + 1)\n";
551 log <<
"f(r) = tanh^3(1 - r/rc)\n";
554 log <<
"WARNING: Inner cutoff parameter not used in combination"
555 " with this cutoff function.\n";
561 log <<
"f(r) = c * tanh^3(1 - r/rc), f(0) = 1\n";
564 log <<
"WARNING: Inner cutoff parameter not used in combination"
565 " with this cutoff function.\n";
571 log <<
"x := (r - rc * alpha) / (rc - rc * alpha)\n";
572 log <<
"f(x) = (2x - 3)x^2 + 1\n";
577 log <<
"x := (r - rc * alpha) / (rc - rc * alpha)\n";
578 log <<
"f(x) = ((15 - 6x)x - 10)x^3 + 1\n";
583 log <<
"x := (r - rc * alpha) / (rc - rc * alpha)\n";
584 log <<
"f(x) = (x(x(20x - 70) + 84) - 35)x^4 + 1\n";
589 log <<
"x := (r - rc * alpha) / (rc - rc * alpha)\n";
590 log <<
"f(x) = (x(x((315 - 70x)x - 540) + 420) - 126)x^5 + 1\n";
595 log <<
"x := (r - rc * alpha) / (rc - rc * alpha)\n";
596 log <<
"f(x) = exp(-1 / 1 - x^2)\n";
602 log <<
"WARNING: Hard cutoff used!\n";
606 throw invalid_argument(
"ERROR: Unknown cutoff type.\n");
609 log <<
"*****************************************"
610 "**************************************\n";
618 log <<
"*** SETUP: SYMMETRY FUNCTIONS ***********"
619 "**************************************\n";
623 for (settings::Settings::KeyMap::const_iterator it = r.first; it != r.second; ++it)
625 vector<string> args =
split(
reduce(it->second.first));
628 elements.at(element).addSymmetryFunction(it->second.first,
632 log <<
"Abbreviations:\n";
633 log <<
"--------------\n";
634 log <<
"ind .... Symmetry function index.\n";
635 log <<
"ec ..... Central atom element.\n";
636 log <<
"tp ..... Symmetry function type.\n";
637 log <<
"sbtp ... Symmetry function subtype (e.g. cutoff type).\n";
638 log <<
"e1 ..... Neighbor 1 element.\n";
639 log <<
"e2 ..... Neighbor 2 element.\n";
640 log <<
"eta .... Gaussian width eta.\n";
641 log <<
"rs/rl... Shift distance of Gaussian or left cutoff radius "
643 log <<
"angl.... Left cutoff angle for polynomial.\n";
644 log <<
"angr.... Right cutoff angle for polynomial.\n";
645 log <<
"la ..... Angle prefactor lambda.\n";
646 log <<
"zeta ... Angle term exponent zeta.\n";
647 log <<
"rc ..... Cutoff radius / right cutoff radius for polynomial.\n";
648 log <<
"a ...... Free parameter alpha (e.g. cutoff alpha).\n";
649 log <<
"ln ..... Line number in settings file.\n";
652 for (vector<Element>::iterator it =
elements.begin();
656 it->sortSymmetryFunctions();
659 log <<
strpr(
"Short range atomic symmetry functions element %2s :\n",
660 it->getSymbol().c_str());
661 log <<
"--------------------------------------------------"
662 "-----------------------------------------------\n";
663 log <<
" ind ec tp sbtp e1 e2 eta rs/rl "
664 "rc angl angr la zeta a ln\n";
665 log <<
"--------------------------------------------------"
666 "-----------------------------------------------\n";
667 log << it->infoSymmetryFunctionParameters();
668 log <<
"--------------------------------------------------"
669 "-----------------------------------------------\n";
679 log <<
strpr(
"Minimum cutoff radius for element %2s: %f\n",
683 log <<
strpr(
"Maximum cutoff radius (global) : %f\n",
686 log <<
"*****************************************"
687 "**************************************\n";
695 log <<
"*** SETUP: SYMMETRY FUNCTION SCALING ****"
696 "**************************************\n";
699 log <<
"No scaling for symmetry functions.\n";
700 for (vector<Element>::iterator it =
elements.begin();
703 it->setScalingNone();
706 log <<
"*****************************************"
707 "**************************************\n";
715 log <<
"*** SETUP: SYMMETRY FUNCTION SCALING ****"
716 "**************************************\n";
719 log <<
"Equal scaling type for all symmetry functions:\n";
725 log <<
"Gs = Smin + (Smax - Smin) * (G - Gmin) / (Gmax - Gmin)\n";
732 log <<
"Gs = G - Gmean\n";
739 log <<
"Gs = Smin + (Smax - Smin) * (G - Gmean) / (Gmax - Gmin)\n";
745 log <<
"Gs = Smin + (Smax - Smin) * (G - Gmean) / Gsigma\n";
752 log <<
"WARNING: No symmetry function scaling!\n";
763 Smin = atof(
settings[
"scale_min_short"].c_str());
767 log <<
"WARNING: Keyword \"scale_min_short\" not found.\n";
768 log <<
" Default value for Smin = 0.0.\n";
774 Smax = atof(
settings[
"scale_max_short"].c_str());
778 log <<
"WARNING: Keyword \"scale_max_short\" not found.\n";
779 log <<
" Default value for Smax = 1.0.\n";
787 log <<
strpr(
"Symmetry function scaling statistics from file: %s\n",
789 log <<
"-----------------------------------------"
790 "--------------------------------------\n";
792 file.open(fileName.c_str());
795 throw runtime_error(
"ERROR: Could not open file: \"" + fileName
799 vector<string> lines;
800 while (getline(file, line))
802 if (line.at(0) !=
'#') lines.push_back(line);
807 log <<
"Abbreviations:\n";
808 log <<
"--------------\n";
809 log <<
"ind ..... Symmetry function index.\n";
810 log <<
"min ..... Minimum symmetry function value.\n";
811 log <<
"max ..... Maximum symmetry function value.\n";
812 log <<
"mean .... Mean symmetry function value.\n";
813 log <<
"sigma ... Standard deviation of symmetry function values.\n";
814 log <<
"sf ...... Scaling factor for derivatives.\n";
815 log <<
"Smin .... Desired minimum scaled symmetry function value.\n";
816 log <<
"Smax .... Desired maximum scaled symmetry function value.\n";
817 log <<
"t ....... Scaling type.\n";
819 for (vector<Element>::iterator it =
elements.begin();
823 log <<
strpr(
"Scaling data for symmetry functions element %2s :\n",
824 it->getSymbol().c_str());
825 log <<
"-----------------------------------------"
826 "--------------------------------------\n";
827 log <<
" ind min max mean sigma sf Smin Smax t\n";
828 log <<
"-----------------------------------------"
829 "--------------------------------------\n";
830 log << it->infoSymmetryFunctionScaling();
831 log <<
"-----------------------------------------"
832 "--------------------------------------\n";
833 lines.erase(lines.begin(), lines.begin() + it->numSymmetryFunctions());
836 log <<
"*****************************************"
837 "**************************************\n";
845 log <<
"*** SETUP: SYMMETRY FUNCTION GROUPS *****"
846 "**************************************\n";
849 log <<
"Abbreviations:\n";
850 log <<
"--------------\n";
851 log <<
"ind .... Symmetry function index.\n";
852 log <<
"ec ..... Central atom element.\n";
853 log <<
"tp ..... Symmetry function type.\n";
854 log <<
"sbtp ... Symmetry function subtype (e.g. cutoff type).\n";
855 log <<
"e1 ..... Neighbor 1 element.\n";
856 log <<
"e2 ..... Neighbor 2 element.\n";
857 log <<
"eta .... Gaussian width eta.\n";
858 log <<
"rs/rl... Shift distance of Gaussian or left cutoff radius "
860 log <<
"angl.... Left cutoff angle for polynomial.\n";
861 log <<
"angr.... Right cutoff angle for polynomial.\n";
862 log <<
"la ..... Angle prefactor lambda.\n";
863 log <<
"zeta ... Angle term exponent zeta.\n";
864 log <<
"rc ..... Cutoff radius / right cutoff radius for polynomial.\n";
865 log <<
"a ...... Free parameter alpha (e.g. cutoff alpha).\n";
866 log <<
"ln ..... Line number in settings file.\n";
867 log <<
"mi ..... Member index.\n";
868 log <<
"sfi .... Symmetry function index.\n";
869 log <<
"e ...... Recalculate exponential term.\n";
871 for (vector<Element>::iterator it =
elements.begin();
874 it->setupSymmetryFunctionGroups();
875 log <<
strpr(
"Short range atomic symmetry function groups "
876 "element %2s :\n", it->getSymbol().c_str());
877 log <<
"------------------------------------------------------"
878 "----------------------------------------------------\n";
879 log <<
" ind ec tp sbtp e1 e2 eta rs/rl "
880 "rc angl angr la zeta a ln mi sfi e\n";
881 log <<
"------------------------------------------------------"
882 "----------------------------------------------------\n";
883 log << it->infoSymmetryFunctionGroups();
884 log <<
"------------------------------------------------------"
885 "----------------------------------------------------\n";
888 log <<
"*****************************************"
889 "**************************************\n";
897 log <<
"*** SETUP: SYMMETRY FUNCTION MEMORY *****"
898 "**************************************\n";
903 e.setupSymmetryFunctionMemory();
904 vector<size_t> symmetryFunctionNumTable
905 = e.getSymmetryFunctionNumTable();
906 vector<vector<size_t>> symmetryFunctionTable
907 = e.getSymmetryFunctionTable();
908 log <<
strpr(
"Symmetry function derivatives memory table "
909 "for element %2s :\n", e.getSymbol().c_str());
910 log <<
"-----------------------------------------"
911 "--------------------------------------\n";
912 log <<
"Relevant symmetry functions for neighbors with element:\n";
915 log <<
strpr(
"- %2s: %4zu of %4zu (%5.1f %)\n",
917 symmetryFunctionNumTable.at(i),
918 e.numSymmetryFunctions(),
919 (100.0 * symmetryFunctionNumTable.at(i))
920 / e.numSymmetryFunctions());
923 log <<
"-----------------------------------------"
924 "--------------------------------------\n";
925 for (
auto isf : symmetryFunctionTable.at(i))
927 SymFnc const& sf = e.getSymmetryFunction(isf);
930 log <<
"-----------------------------------------"
931 "--------------------------------------\n";
934 log <<
"-----------------------------------------"
935 "--------------------------------------\n";
941 log <<
strpr(
"%2s - symmetry function per-element index table:\n",
942 e.getSymbol().c_str());
943 log <<
"-----------------------------------------"
944 "--------------------------------------\n";
951 log <<
"-----------------------------------------"
952 "--------------------------------------\n";
953 for (
size_t i = 0; i < e.numSymmetryFunctions(); ++i)
955 SymFnc const& sf = e.getSymmetryFunction(i);
960 if (ipe == numeric_limits<size_t>::max())
971 log <<
"-----------------------------------------"
972 "--------------------------------------\n";
977 log <<
"*****************************************"
978 "**************************************\n";
983#ifndef N2P2_NO_SF_CACHE
987 log <<
"*** SETUP: SYMMETRY FUNCTION CACHE ******"
988 "**************************************\n";
994 vector<vector<SFCacheList>> cacheLists(
numElements);
1001 size_t ne = atoi(
split(identifier)[0].c_str());
1002 bool unknown =
true;
1003 for (
auto& c : cacheLists.at(ne))
1005 if (identifier == c.identifier)
1014 cacheLists.at(ne).push_back(SFCacheList());
1015 cacheLists.at(ne).back().element = ne;
1016 cacheLists.at(ne).back().identifier = identifier;
1017 cacheLists.at(ne).back().indices.push_back(s.
getIndex());
1023 log <<
strpr(
"Multiple cache identifiers for element %2s:\n\n",
1026 double cacheUsageMean = 0.0;
1027 size_t cacheCount = 0;
1034 vector<SFCacheList>& c = cacheLists.at(j);
1035 c.erase(remove_if(c.begin(),
1039 return l.indices.size() <= 1;
1041 cacheCount += c.size();
1042 for (
size_t k = 0; k < c.size(); ++k)
1044 cacheUsageMean += c.at(k).indices.size();
1047 log <<
strpr(
"Cache %zu, Identifier \"%s\", "
1048 "Symmetry functions",
1049 k, c.at(k).identifier.c_str());
1050 for (
auto si : c.at(k).indices)
1085 cacheUsageMean /= cacheCount;
1086 log <<
strpr(
"Element %2s: in total %zu caches, "
1087 "used %3.2f times on average.\n",
1088 e.
getSymbol().c_str(), cacheCount, cacheUsageMean);
1091 log <<
"-----------------------------------------"
1092 "--------------------------------------\n";
1096 log <<
"*****************************************"
1097 "**************************************\n";
1104 bool collectExtrapolationWarnings,
1105 bool writeExtrapolationWarnings,
1106 bool stopOnExtrapolationWarnings)
1109 log <<
"*** SETUP: SYMMETRY FUNCTION STATISTICS *"
1110 "**************************************\n";
1113 log <<
"Equal symmetry function statistics for all elements.\n";
1114 log <<
strpr(
"Collect min/max/mean/sigma : %d\n",
1115 (
int)collectStatistics);
1116 log <<
strpr(
"Collect extrapolation warnings : %d\n",
1117 (
int)collectExtrapolationWarnings);
1118 log <<
strpr(
"Write extrapolation warnings immediately to stderr: %d\n",
1119 (
int)writeExtrapolationWarnings);
1120 log <<
strpr(
"Halt on any extrapolation warning : %d\n",
1121 (
int)stopOnExtrapolationWarnings);
1122 for (vector<Element>::iterator it =
elements.begin();
1125 it->statistics.collectStatistics = collectStatistics;
1126 it->statistics.collectExtrapolationWarnings =
1127 collectExtrapolationWarnings;
1128 it->statistics.writeExtrapolationWarnings = writeExtrapolationWarnings;
1129 it->statistics.stopOnExtrapolationWarnings =
1130 stopOnExtrapolationWarnings;
1134 || collectExtrapolationWarnings
1135 || writeExtrapolationWarnings
1136 || stopOnExtrapolationWarnings;
1138 log <<
"*****************************************"
1139 "**************************************\n";
1149 e.getCutoffRadii(
cutoffs.at(e.getIndex()));
1150 if ( rCutScreen > 0 &&
1153 cutoffs.at(e.getIndex()).push_back(rCutScreen);
1161 log <<
"*** SETUP: NEURAL NETWORKS **************"
1162 "**************************************\n";
1173 nns.at(
id).name =
"electronegativity";
1174 nns.at(
id).weightFileFormat =
"weightse.%03zu.data";
1175 nns.at(
id).keywordSuffix =
"_electrostatic";
1176 nns.at(
id).keywordSuffix2 =
"_charge";
1183 nns.at(
id).name =
"charge";
1184 nns.at(
id).weightFileFormat =
"weightse.%03zu.data";
1185 nns.at(
id).keywordSuffix =
"_electrostatic";
1186 nns.at(
id).keywordSuffix2 =
"_charge";
1193 nns.at(
id).name =
"short range";
1194 nns.at(
id).weightFileFormat =
"weights.%03zu.data";
1195 nns.at(
id).keywordSuffix =
"_short";
1196 nns.at(
id).keywordSuffix2 =
"_short";
1202 size_t globalNumHiddenLayers = 0;
1211 globalNumHiddenLayers = atoi(
settings[keyword].c_str());
1214 t.numLayers = globalNumHiddenLayers + 2;
1222 for (settings::Settings::KeyMap::const_iterator it = r.first;
1223 it != r.second; ++it)
1225 vector<string> args =
split(
reduce(it->second.first));
1227 size_t const n = atoi(args.at(1).c_str());
1228 nn.
topology.at(e).numLayers = n + 2;
1234 if (t.numLayers == 0)
1236 throw runtime_error(
"ERROR: Number of neural network hidden "
1237 "layers unset for some elements.\n");
1243 t.numNeuronsPerLayer.resize(t.numLayers, 0);
1244 t.activationFunctionsPerLayer.resize(t.numLayers,
1249 vector<string> globalNumNeuronsPerHiddenLayer;
1254 if (globalNumHiddenLayers != globalNumNeuronsPerHiddenLayer.size())
1256 throw runtime_error(
strpr(
"ERROR: Inconsistent global NN "
1257 "topology keyword \"%s\".\n",
1261 vector<string> globalActivationFunctions;
1266 if (globalNumHiddenLayers != globalActivationFunctions.size() - 1)
1268 throw runtime_error(
strpr(
"ERROR: Inconsistent global NN "
1269 "topology keyword \"%s\".\n",
1274 bool globalNumNeurons = (globalNumNeuronsPerHiddenLayer.size() != 0);
1275 bool globalActivation = (globalActivationFunctions.size() != 0);
1279 size_t const nsf =
elements.at(i).numSymmetryFunctions();
1304 if ((
size_t)t.
numLayers != globalNumHiddenLayers + 2)
continue;
1307 if ((j == t.
numLayers - 1) && globalActivation)
1310 globalActivationFunctions.at(t.
numLayers - 2));
1314 if (globalNumNeurons)
1317 globalNumNeuronsPerHiddenLayer.at(j - 1).c_str());
1319 if (globalActivation)
1323 globalActivationFunctions.at(j - 1));
1333 for (settings::Settings::KeyMap::const_iterator it = r.first;
1334 it != r.second; ++it)
1336 vector<string> args =
split(
reduce(it->second.first));
1338 size_t n = args.
size() - 1;
1342 throw runtime_error(
strpr(
"ERROR: Inconsistent per-element"
1343 " NN topology keyword \"%s\".\n",
1346 for (
int j = 1; j < t.
numLayers - 2; ++j)
1357 for (settings::Settings::KeyMap::const_iterator it = r.first;
1358 it != r.second; ++it)
1360 vector<string> args =
split(
reduce(it->second.first));
1362 size_t n = args.
size() - 1;
1366 throw runtime_error(
strpr(
"ERROR: Inconsistent per-element"
1367 " NN topology keyword \"%s\".\n",
1370 for (
int j = 1; j < t.
numLayers - 1; ++j)
1386 throw runtime_error(
strpr(
1387 "ERROR: NN \"%s\", element %2s: number of "
1388 "neurons for layer %d unset.\n",
1390 elements.at(i).getSymbol().c_str(),
1396 throw runtime_error(
strpr(
1397 "ERROR: NN \"%s\", element %2s: activation "
1398 "functions for layer %d unset.\n",
1400 elements.at(i).getSymbol().c_str(),
1409 log <<
strpr(
"Normalize neurons (all elements): %d\n",
1410 (
int)normalizeNeurons);
1411 log <<
"-----------------------------------------"
1412 "--------------------------------------\n";
1422 piecewise_construct,
1423 forward_as_tuple(k),
1431 nns.at(k).name.c_str(),
1434 log <<
"-----------------------------------------"
1435 "--------------------------------------\n";
1439 log <<
"*****************************************"
1440 "**************************************\n";
1452 map<string, string> fileNameFormats)
1455 log <<
"*** SETUP: NEURAL NETWORK WEIGHTS *******"
1456 "**************************************\n";
1461 string actualFileNameFormat;
1462 if (fileNameFormats.find(k) != fileNameFormats.end())
1464 actualFileNameFormat = fileNameFormats.at(k);
1466 else actualFileNameFormat =
nns.at(k).weightFileFormat;
1467 actualFileNameFormat = directoryPrefix + actualFileNameFormat;
1468 log <<
strpr(
"%s weight file name format: %s\n",
1469 cap(
nns.at(k).name).c_str(),
1470 actualFileNameFormat.c_str());
1474 log <<
"*****************************************"
1475 "**************************************\n";
1481 bool const derivatives)
1490 #pragma omp parallel for private (a, e)
1492 for (
size_t i = 0; i < structure.
atoms.size(); ++i)
1495 a = &(structure.
atoms.at(i));
1513#ifndef N2P2_NO_SF_CACHE
1517#ifndef N2P2_NO_NEIGH_CHECK
1523 log <<
strpr(
"WARNING: Structure %6zu Atom %6zu : %zu "
1546 for (
size_t i = 0; i < structure.
atoms.size(); ++i)
1548 a = &(structure.
atoms.at(i));
1562 bool const derivatives)
1571 #pragma omp parallel for private (a, e)
1573 for (
size_t i = 0; i < structure.
atoms.size(); ++i)
1576 a = &(structure.
atoms.at(i));
1594#ifndef N2P2_NO_SF_CACHE
1598#ifndef N2P2_NO_NEIGH_CHECK
1604 log <<
strpr(
"WARNING: Structure %6zu Atom %6zu : %zu "
1627 for (
size_t i = 0; i < structure.
atoms.size(); ++i)
1629 a = &(structure.
atoms.at(i));
1643 bool const derivatives,
1646 if (
id ==
"")
id =
nnk.front();
1650 for (vector<Atom>::iterator it = structure.
atoms.begin();
1651 it != structure.
atoms.end(); ++it)
1654 .neuralNetworks.at(
id);
1668 for (
auto& a : structure.
atoms)
1671 .neuralNetworks.at(
id);
1680 for (
auto& dChidGi : a.dChidG)
1689 else if (
id ==
"short")
1691 for (
auto& a : structure.
atoms)
1694 .neuralNetworks.at(
id);
1698 for (
size_t i = 0; i < a.G.size(); ++i)
1717 for (vector<Atom>::iterator it = structure.
atoms.begin();
1718 it != structure.
atoms.end(); ++it)
1722 .neuralNetworks.at(
"elec");
1723 nnCharge.
setInput(&((it->G).front()));
1733 .neuralNetworks.at(
"short");
1735 for (
size_t i = 0; i < it->G.size(); ++i)
1740 nnShort.
setInput(it->G.size(), it->charge);
1755 bool const derivativesElec)
1766 hardness(i) =
elements.at(i).getHardness();
1767 double const iSigma =
elements.at(i).getQsigma();
1768 sigmaSqrtPi(i) = sqrt(M_PI) * iSigma;
1771 double const jSigma =
elements.at(j).getQsigma();
1772 gammaSqrt2(i, j) = sqrt(2.0 * (iSigma * iSigma + jSigma * jSigma));
1786 if (derivativesElec)
1808 for (vector<Atom>::iterator it = structure.
atoms.begin();
1809 it != structure.
atoms.end(); ++it)
1834 for (vector<Atom>::iterator it = structure.
atoms.begin();
1835 it != structure.
atoms.end(); ++it)
1837 structure.
charge += it->charge;
1853 throw runtime_error(
"WARNING: Forces are not implemented yet.\n");
1859 #pragma omp parallel
1863 for (
size_t i = 0; i < structure.
atoms.size(); ++i)
1885 for (vector<size_t>::const_iterator it =
1891#ifndef N2P2_FULL_SFD_MEMORY
1892 vector<vector<size_t> >
const& tableFull
1898 size_t const numNeighbors =
1900 for (
size_t k = 0; k < numNeighbors; ++k) {
1905#ifndef N2P2_FULL_SFD_MEMORY
1926 for (
size_t i = 0; i < s.
numAtoms; ++i)
1928 auto &ai = s.
atoms[i];
1929 ai.f -= ai.pEelecpr;
1930 ai.fElec = -ai.pEelecpr;
1932 for (
size_t j = 0; j < s.
numAtoms; ++j)
1936#ifndef NNP_FULL_SFD_MEMORY
1937 vector<vector<size_t> >
const &tableFull
1946 ai.f -= lambdaTotal(j) * (ai.dAdrQ[j] + dChidr);
1947 ai.fElec -= lambdaElec(j) * (ai.dAdrQ[j] + dChidr);
1969 useDEdG = (useForces || useDEdG);
1983#ifdef NNP_NO_SF_GROUPS
1990 if (useDEdG && !useForces)
1993 for (
auto& a : structure.
atoms)
1997 a.dEdG.resize(a.numSymmetryFunctions + 1, 0.0);
1998 a.dChidG.resize(a.numSymmetryFunctions, 0.0);
2001 a.dEdG.resize(a.numSymmetryFunctions, 0.0);
2025 *
elements.at(i).getAtomicEnergyOffset();
2030 *
elements.at(i).getAtomicEnergyOffset();
2044 *
elements.at(i).getAtomicEnergyOffset();
2049 *
elements.at(i).getAtomicEnergyOffset();
2058 double result = 0.0;
2063 *
elements.at(i).getAtomicEnergyOffset();
2073 else result = structure.
energy;
2078 *
elements.at(i).getAtomicEnergyOffset();
2086 if (property ==
"energy")
return value *
convEnergy;
2088 else if (property ==
"charge")
return value *
convCharge;
2089 else if (property ==
"hardness")
2092 else throw runtime_error(
"ERROR: Unknown property to convert to "
2093 "normalized units.\n");
2112 if (property ==
"energy")
return value /
convEnergy;
2114 else if (property ==
"charge")
return value /
convCharge;
2115 else if (property ==
"hardness")
2118 else throw runtime_error(
"ERROR: Unknown property to convert to physical "
2157 for (vector<Element>::iterator it =
elements.begin();
2160 it->statistics.resetExtrapolationWarnings();
2168 size_t numExtrapolationWarnings = 0;
2170 for (vector<Element>::const_iterator it =
elements.begin();
2173 numExtrapolationWarnings +=
2174 it->statistics.countExtrapolationWarnings();
2177 return numExtrapolationWarnings;
2184 for (vector<Element>::const_iterator it =
elements.begin();
2187 v.push_back(it->numSymmetryFunctions());
2206 ofstream file(fileName.c_str());
2208 for (
size_t i = 0; i < settingsLines.size(); ++i)
2210 if (find(prune.begin(), prune.end(), i) != prune.end())
2214 file << settingsLines.at(i) <<
'\n';
2230 vector<size_t> prune;
2233 for (vector<Element>::const_iterator it =
elements.begin();
2236 for (
size_t i = 0; i < it->numSymmetryFunctions(); ++i)
2238 SymFnc const& s = it->getSymmetryFunction(i);
2241 prune.push_back(it->getSymmetryFunction(i).getLineNumber());
2251 vector<vector<double> > sensitivity)
2253 vector<size_t> prune;
2257 for (
size_t j = 0; j <
elements.at(i).numSymmetryFunctions(); ++j)
2259 if (sensitivity.at(i).at(j) < threshold)
2262 elements.at(i).getSymmetryFunction(j).getLineNumber());
2271 string const& fileNameFormat)
2273 for (vector<Element>::iterator it =
elements.begin();
2276 string fileName =
strpr(fileNameFormat.c_str(),
2277 it->getAtomicNumber());
2278 log <<
strpr(
"Setting weights for element %2s from file: %s\n",
2279 it->getSymbol().c_str(),
2282 vector<size_t>(1, 0)
CutoffType
List of available cutoff function types.
std::size_t registerElements(std::string const &elementLine)
Extract all elements and store in element map.
std::size_t size() const
Get element map size.
std::size_t atomicNumber(std::size_t index) const
Get atomic number from element index.
Contains element-specific data.
void calculateSymmetryFunctions(Atom &atom, bool const derivatives) const
Calculate symmetry functions.
void calculateSymmetryFunctionGroups(Atom &atom, bool const derivatives) const
Calculate symmetry functions via groups.
std::vector< std::size_t > getCacheSizes() const
Get cache sizes for each neighbor atom element.
std::size_t getIndex() const
Get index.
void setCacheIndices(std::vector< std::vector< SFCacheList > > cacheLists)
Set cache indices for all symmetry functions of this element.
std::size_t updateSymmetryFunctionStatistics(Atom const &atom)
Update symmetry function statistics.
SymFnc const & getSymmetryFunction(std::size_t index) const
Get symmetry function instance.
std::string getSymbol() const
Get symbol.
std::map< std::string, NeuralNetwork > neuralNetworks
Neural networks for this element.
std::size_t numSymmetryFunctions() const
Get number of symmetry functions.
std::vector< std::size_t > const & getSymmetryFunctionNumTable() const
Get number of relevant symmetry functions per element.
void setTruncMethod(EWALDTruncMethod const m)
void toNormalizedUnits(double const convEnergy, double const convLength)
Convert cutoff parameters to normalized units.
double getPrecision() const
void setMaxQSigma(double const maxWidth)
Setter for maximum width of charges.
EWALDTruncMethod getTruncMethod() const
void logEwaldCutoffs(Log &log, double const lengthConversion) const
Use after Ewald summation!
double getMaxCharge() const
void readFromArgs(std::vector< std::string > const &args)
Setup parameters from argument vector.
double physicalEnergy(Structure const &structure, bool ref=true) const
Undo normalization for a given energy of structure.
bool checkExtrapolationWarnings
std::vector< std::vector< double > > cutoffs
Matrix storing all symmetry function cut-offs for all elements.
void setupNormalization(bool standalone=true)
Set up normalization.
ElementMap elementMap
Global element map, populated by setupElementMap().
std::vector< double > minCutoffRadius
void addEnergyOffset(Structure &structure, bool ref=true)
Add atomic energy offsets to reference energy.
void initialize()
Write welcome message with version information.
void logEwaldCutoffs()
Logs Ewald params whenever they change.
virtual void setupElementMap()
Set up the element map.
void readNeuralNetworkWeights(std::string const &id, std::string const &fileName)
Read in weights for a specific type of neural network.
virtual void setupNeuralNetwork()
Set up neural networks for all elements.
virtual void setupSymmetryFunctionCache(bool verbose=false)
Set up symmetry function cache.
void setupGeneric(std::string const &nnpDir="", bool skipNormalize=false, bool initialHardness=false)
Combine multiple setup routines and provide a basic NNP setup.
@ HDNNP_2G
Short range NNP (2G-HDNNP).
@ HDNNP_Q
Short range NNP with charge NN, no electrostatics/Qeq (M.
@ HDNNP_4G
NNP with electrostatics and non-local charge transfer (4G-HDNNP).
std::vector< std::string > nnk
virtual void setupElectrostatics(bool initialHardness=false, std::string directoryPrefix="", std::string fileNameFormat="hardness.%03zu.data")
Set up electrostatics related stuff (hardness, screening, ...).
std::vector< std::size_t > pruneSymmetryFunctionsRange(double threshold)
Prune symmetry functions according to their range and write settings file.
virtual void setupNeuralNetworkWeights(std::map< std::string, std::string > fileNameFormats=std::map< std::string, std::string >())
Set up neural network weights from files with given name format.
ScreeningFunction screeningFunction
SymFnc::ScalingType scalingType
void calculateAtomicNeuralNetworks(Structure &structure, bool const derivatives, std::string id="")
Calculate atomic neural networks for all atoms in given structure.
double physical(std::string const &property, double value) const
Undo normalization for a given property.
void writePrunedSettingsFile(std::vector< std::size_t > prune, std::string fileName="output.nn") const
Copy settings file but comment out lines provided.
virtual void setupSymmetryFunctionGroups()
Set up symmetry function groups.
std::vector< Element > elements
double normalized(std::string const &property, double value) const
Apply normalization to given property.
void convertToNormalizedUnits(Structure &structure) const
Convert one structure to normalized units.
void calculateEnergy(Structure &structure) const
Calculate potential energy for a given structure.
void calculateSymmetryFunctionGroups(Structure &structure, bool const derivatives)
Calculate all symmetry function groups for all atoms in given structure.
settings::Settings settings
void setupSymmetryFunctionScalingNone()
Set up "empy" symmetry function scaling.
std::string settingsGetValue(std::string const &keyword) const
Get value for given keyword in Settings instance.
virtual void setupSymmetryFunctionScaling(std::string const &fileName="scaling.data")
Set up symmetry function scaling from file.
std::vector< std::size_t > getNumSymmetryFunctions() const
Get number of symmetry functions per element.
std::size_t getNumExtrapolationWarnings() const
Count total number of extrapolation warnings encountered for all elements and symmetry functions.
void removeEnergyOffset(Structure &structure, bool ref=true)
Remove atomic energy offsets from reference energy.
bool settingsKeywordExists(std::string const &keyword) const
Check if keyword was found in settings file.
void resetExtrapolationWarnings()
Erase all extrapolation warnings and reset counters.
double getEnergyWithOffset(Structure const &structure, bool ref=true) const
Add atomic energy offsets and return energy.
std::vector< std::size_t > minNeighbors
void convertToPhysicalUnits(Structure &structure) const
Convert one structure to physical units.
void calculateCharge(Structure &structure) const
Calculate total charge for a given structure.
virtual void setupSymmetryFunctions()
Set up all symmetry functions.
void chargeEquilibration(Structure &structure, bool const derivativesElec)
Perform global charge equilibration method.
void calculateSymmetryFunctions(Structure &structure, bool const derivatives)
Calculate all symmetry functions for all atoms in given structure.
void evaluateNNP(Structure &structure, bool useForces=true, bool useDEdG=true)
Evaluate neural network potential (includes total energy, optionally forces and in some cases charges...
void setupCutoffMatrix()
Setup matrix storing all symmetry function cut-offs for each element.
std::map< std::string, NNSetup > nns
void calculateForces(Structure &structure) const
Calculate forces for all atoms in given structure.
void setupSymmetryFunctionStatistics(bool collectStatistics, bool collectExtrapolationWarnings, bool writeExtrapolationWarnings, bool stopOnExtrapolationWarnings)
Set up symmetry function statistics collection.
void setupCutoff()
Set up cutoff function for all symmetry functions.
void loadSettingsFile(std::string const &fileName="input.nn")
Open settings file and load all keywords into memory.
std::vector< std::size_t > pruneSymmetryFunctionsSensitivity(double threshold, std::vector< std::vector< double > > sensitivity)
Prune symmetry functions with sensitivity analysis data.
double getEnergyOffset(Structure const &structure) const
Get atomic energy offset for given structure.
void setupSymmetryFunctionMemory(bool verbose=false)
Extract required memory dimensions for symmetry function derivatives.
void writeSettingsFile(std::ofstream *const &file) const
Write complete settings file.
double normalizedEnergy(Structure const &structure, bool ref=true) const
Apply normalization to given energy of structure.
CutoffFunction::CutoffType cutoffType
virtual void setupElements()
Set up all Element instances.
This class implements a feed-forward neural network.
@ AF_UNSET
Unset activation function.
void setInput(double const *const &input) const
Set neural network input layer node values.
void setConnections(double const *const &connections)
Set neural network weights and biases.
void propagate()
Propagate input information through all layers.
void calculateDEdG(double *dEdG) const
Calculate derivative of output neuron with respect to input neurons.
void getOutput(double *output) const
Get neural network output layer node values.
void setCoreFunction(CoreFunction::Type const type)
Set functional form of transition region.
double getOuter() const
Getter for outer.
void changeLengthUnits(double const conv)
Change length units of screening function.
std::vector< std::string > info() const
Get string with information of screening function.
void setInnerOuter(double inner, double outer)
Set inner and outer limit of transition region.
Symmetry function base class.
virtual std::string parameterLine() const =0
Give symmetry function parameters in one line.
double getGmin() const
Get private Gmin member variable.
double getGmax() const
Get private Gmax member variable.
std::vector< std::size_t > getIndexPerElement() const
Get private indexPerElement member variable.
virtual std::vector< std::string > getCacheIdentifiers() const
Get unique cache identifiers.
std::size_t getIndex() const
Get private index member variable.
std::vector< std::string > info() const
Get logged information about settings file.
std::string getValue(Key const &key) const override
void writeSettingsFile(std::ofstream *const &file, std::map< std::size_t, std::string > const &replacements={}) const
Write complete settings file.
std::pair< KeyMap::const_iterator, KeyMap::const_iterator > KeyRange
std::size_t loadFile(std::string const &fileName="input.nn")
Load a file with settings.
KeyRange getValues(std::string const &keyword) const
Get all keyword-value pairs for given keyword.
std::vector< std::string > getSettingsLines() const
Get complete settings file.
bool keywordExists(Key const &key, bool const exact=false) const override
@ KOLAFA_PERRAM
Method 1: Optimized in n2p2 (DOI: 10.1080/08927029208049126).
@ JACKSON_CATLOW
Method 0: Used by RuNNer (DOI: 10.1080/08927028808080944).
string cap(string word)
Capitalize first letter of word.
string strpr(const char *format,...)
String version of printf function.
bool vectorContains(std::vector< T > const &stdVec, T value)
Test if vector contains specified value.
vector< string > split(string const &input, char delimiter)
Split string at each delimiter.
map< size_t, vector< double > > readColumnsFromFile(string fileName, vector< size_t > columns, char comment)
NeuralNetwork::ActivationFunction activationFromString(std::string c)
Convert string to activation function.
string reduce(string const &line, string const &whitespace, string const &fill)
Replace multiple whitespaces with fill.
Struct to store information on neighbor atoms.
std::size_t index
Index of neighbor atom.
Storage for a single atom.
std::vector< Neighbor > neighbors
Neighbor array (maximum number defined in macros.h.
std::size_t numSymmetryFunctions
Number of symmetry functions used to describe the atom environment.
Vec3D calculateDChidr(size_t const atomIndexOfR, double const maxCutoffRadius, std::vector< std::vector< size_t > > const *const tableFull=nullptr) const
Calculate dChi/dr of this atom's Chi with respect to the coordinates of the given atom.
Vec3D f
Force vector calculated by neural network.
Vec3D calculatePairForceShort(Neighbor const &neighbor, std::vector< std::vector< std::size_t > > const *const tableFull=nullptr) const
Calculate force resulting from gradient of this atom's (short-ranged) energy contribution with respec...
bool hasSymmetryFunctionDerivatives
If symmetry function derivatives are saved for this atom.
std::size_t index
Index number of this atom.
Vec3D calculateSelfForceShort() const
Calculate force resulting from gradient of this atom's (short-ranged) energy contribution with respec...
std::size_t getStoredMinNumNeighbors(double const cutoffRadius) const
Return needed number of neighbors for a given cutoff radius from neighborCutoffs map.
std::vector< std::size_t > numSymmetryFunctionDerivatives
Number of neighbor atom symmetry function derivatives per element.
bool useChargeNeuron
If an additional charge neuron in the short-range NN is present.
std::size_t indexStructure
Index number of structure this atom belongs to.
std::size_t element
Element index of this atom.
void allocate(bool all, double const maxCutoffRadius=0.0)
Allocate vectors related to symmetry functions (G, dEdG).
bool hasSymmetryFunctions
If symmetry function values are saved for this atom.
std::size_t calculateNumNeighbors(double const cutoffRadius) const
Calculate number of neighbors for a given cutoff radius.
std::vector< std::size_t > cacheSizePerElement
Cache size for each element.
std::vector< std::size_t > neighborsUnique
List of unique neighbor indices (don't count multiple PBC images).
List of symmetry functions corresponding to one cache identifier.
std::vector< NeuralNetwork::ActivationFunction > activationFunctionsPerLayer
Activation function type per layer.
std::vector< int > numNeuronsPerLayer
Number of neurons per layer.
int numLayers
Number of NN layers (including input and output layer).
Setup data for one neural network.
std::string keywordSuffix
Suffix for keywords (NN topology related).
std::vector< Topology > topology
Per-element NN topology.
std::string id
NN identifier, e.g. "short", "charge",...
Storage for one atomic configuration.
void toPhysicalUnits(double meanEnergy, double convEnergy, double convLength, double convCharge)
Switch to physical units, shift energy and change energy, length and charge unit.
Eigen::VectorXd const calculateForceLambdaElec() const
Calculate lambda_elec vector which is needed for the electrostatic force calculation in 4G NN.
std::vector< std::size_t > numAtomsPerElement
Number of atoms of each element in this structure.
void calculateMaxCutoffRadiusOverall(EwaldSetup &ewaldSetup, double rcutScreen, double maxCutoffRadius)
Calculate maximal cut-off if cut-off of screening and real part Ewald summation are also considered.
double charge
Charge determined by neural network potential.
double calculateElectrostaticEnergy(EwaldSetup &ewaldSetup, Eigen::VectorXd hardness, Eigen::MatrixXd gammaSqrt2, Eigen::VectorXd sigmaSqrtPi, ScreeningFunction const &fs, double const fourPiEps, ErfcBuf &erfcBuf)
Compute electrostatic energy with global charge equilibration.
double energyShort
Short-range part of the potential energy predicted by NNP.
bool hasSymmetryFunctionDerivatives
If symmetry function derivatives are saved for each atom.
Eigen::VectorXd const calculateForceLambdaTotal() const
Calculate lambda_total vector which is needed for the total force calculation in 4G NN.
double energyElec
Electrostatics part of the potential energy predicted by NNP.
double energy
Potential energy determined by neural network.
double energyRef
Reference potential energy.
void toNormalizedUnits(double meanEnergy, double convEnergy, double convLength, double convCharge)
Normalize structure, shift energy and change energy, length and charge unit.
void calculateElectrostaticEnergyDerivatives(Eigen::VectorXd hardness, Eigen::MatrixXd gammaSqrt2, Eigen::VectorXd sigmaSqrtPi, ScreeningFunction const &fs, double const fourPiEps)
Calculates partial derivatives of electrostatic Energy with respect to atom's coordinates and charges...
void calculateNeighborList(double cutoffRadius, bool sortByDistance=false)
Calculate neighbor list for all atoms.
std::size_t numAtoms
Total number of atoms present in this structure.
void calculateDAdrQ(EwaldSetup &ewaldSetup, Eigen::MatrixXd gammaSqrt2, double const fourPiEps, ErfcBuf &erfcBuf)
Calculates derivative of A-matrix with respect to the atoms positions and contract it with Q.
std::vector< Atom > atoms
Vector of all atoms in this structure.
bool hasSymmetryFunctions
If symmetry function values are saved for each atom.
Vector in 3 dimensional real space.