31{
32 int numProcs = 0;
33 int myRank = 0;
34 size_t stage = 0;
35 ofstream myLog;
36
37 if (argc > 2)
38 {
39 cout << "USAGE: " << argv[0] << " <stage>\n"
40 << " <stage> ... Training stage (only required if training"
41 " is a multi-stage process.\n"
42 << " Execute in directory with these NNP files present:\n"
43 << " - input.data (structure file)\n"
44 << " - input.nn (NNP settings)\n"
45 << " - scaling.data (symmetry function scaling data)\n"
46 << " - \"weights(e).%%03d.data\" (weights files)\n";
47 return 1;
48 }
49
50 string suffix = "";
51 if (argc > 1)
52 {
53 stage = (size_t)atoi(argv[1]);
54 suffix =
strpr(
".stage-%zu", stage);
55 }
56
57 MPI_Init(&argc, &argv);
58 MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
59 MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
60
63 myLog.open((
strpr(
"nnp-norm2.log.%04d", myRank) + suffix).c_str());
72
74 if ( (nnpType == Training::NNPType::HDNNP_4G ||
75 nnpType == Training::NNPType::HDNNP_Q) && stage == 1)
76 {
77 throw runtime_error("ERROR: Normalization of charges not yet "
78 "implemented\n.");
79 }
80
84 {
85 throw runtime_error("ERROR: Normalization keywords found in settings, "
86 "please remove them first.\n");
87 }
88
90 {
91 throw runtime_error("ERROR: Normalization is only possible if forces "
92 "are used (keyword \"use_short_forces\").\n");
93 }
94
95
97
98
100
101
103
105 if ( (nnpType == Training::NNPType::HDNNP_4G ||
106 nnpType == Training::NNPType::HDNNP_Q) && stage == 2)
107 {
109 }
110
111 training.
log <<
"\n";
112 training.
log <<
"*** DATA SET NORMALIZATION **************"
113 "**************************************\n";
114 training.
log <<
"\n";
115
116 ofstream fileEvsV;
117 fileEvsV.open(
strpr(
"evsv.dat.%04d", myRank).c_str());
118 if (myRank == 0)
119 {
120
121 vector<string> title;
122 vector<string> colName;
123 vector<string> colInfo;
124 vector<size_t> colSize;
125 title.push_back("Energy vs. volume comparison.");
126 colSize.push_back(16);
127 colName.push_back("V_atom");
128 colInfo.push_back("Volume per atom.");
129 colSize.push_back(16);
130 colName.push_back("Eref_atom");
131 colInfo.push_back("Reference energy per atom.");
132 colSize.push_back(10);
133 colName.push_back("N");
134 colInfo.push_back("Number of atoms.");
135 colSize.push_back(16);
136 colName.push_back("V");
137 colInfo.push_back("Volume of structure.");
138 colSize.push_back(16);
139 colName.push_back("Eref");
140 colInfo.push_back("Reference energy of structure.");
141 colSize.push_back(16);
142 colName.push_back("Eref_offset");
143 colInfo.push_back("Reference energy of structure (including offset).");
146 }
147
148 size_t numAtomsTotal = 0;
149 size_t numStructures = 0;
150 double meanEnergyPerAtomRef = 0.0;
151 double meanEnergyPerAtomNnp = 0.0;
152 double sigmaEnergyPerAtomRef = 0.0;
153 double sigmaEnergyPerAtomNnp = 0.0;
154 double meanForceRef = 0.0;
155 double meanForceNnp = 0.0;
156 double sigmaForceRef = 0.0;
157 double sigmaForceNnp = 0.0;
158 training.
log <<
"Computing initial prediction for all structures...\n";
160 {
161
162 fileEvsV <<
strpr(
"%16.8E %16.8E %10zu %16.8E %16.8E %16.8E\n",
163 s.volume / s.numAtoms,
164 s.energyRef / s.numAtoms,
165 s.numAtoms,
166 s.volume,
167 s.energyRef,
170#ifdef N2P2_NO_SF_GROUPS
172#else
174#endif
178 s.clearNeighborList();
179
180 numStructures++;
181 numAtomsTotal += s.numAtoms;
182 meanEnergyPerAtomRef += s.energyRef / s.numAtoms;
183 meanEnergyPerAtomNnp += s.energy / s.numAtoms;
184 for (auto& a : s.atoms)
185 {
186 meanForceRef += a.fRef[0] + a.fRef[1] + a.fRef[2];
187 meanForceNnp += a.f [0] + a.f [1] + a.f [2];
188 }
189 }
190
191 fileEvsV.flush();
192 fileEvsV.close();
193 MPI_Barrier(MPI_COMM_WORLD);
194 training.
log <<
"Writing energy/atom vs. volume/atom data "
195 << "to \"evsv.dat\".\n";
197 MPI_Allreduce(MPI_IN_PLACE, &numStructures , 1,
MPI_SIZE_T, MPI_SUM, MPI_COMM_WORLD);
198 MPI_Allreduce(MPI_IN_PLACE, &numAtomsTotal , 1,
MPI_SIZE_T, MPI_SUM, MPI_COMM_WORLD);
199 MPI_Allreduce(MPI_IN_PLACE, &meanEnergyPerAtomRef, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
200 MPI_Allreduce(MPI_IN_PLACE, &meanEnergyPerAtomNnp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
201 MPI_Allreduce(MPI_IN_PLACE, &meanForceRef , 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
202 MPI_Allreduce(MPI_IN_PLACE, &meanForceNnp , 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
203 meanEnergyPerAtomRef /= numStructures;
204 meanEnergyPerAtomNnp /= numStructures;
205 meanForceRef /= 3 * numAtomsTotal;
206 meanForceNnp /= 3 * numAtomsTotal;
208 {
209 double ediffRef = s.energyRef / s.numAtoms - meanEnergyPerAtomRef;
210 double ediffNnp = s.energy / s.numAtoms - meanEnergyPerAtomNnp;
211 sigmaEnergyPerAtomRef += ediffRef * ediffRef;
212 sigmaEnergyPerAtomNnp += ediffNnp * ediffNnp;
213 for (auto const& a : s.atoms)
214 {
215 double fdiffRef = a.fRef[0] - meanForceRef;
216 double fdiffNnp = a.f [0] - meanForceNnp;
217 sigmaForceRef += fdiffRef * fdiffRef;
218 sigmaForceNnp += fdiffNnp * fdiffNnp;
219 fdiffRef = a.fRef[1] - meanForceRef;
220 fdiffNnp = a.f [1] - meanForceNnp;
221 sigmaForceRef += fdiffRef * fdiffRef;
222 sigmaForceNnp += fdiffNnp * fdiffNnp;
223 fdiffRef = a.fRef[2] - meanForceRef;
224 fdiffNnp = a.f [2] - meanForceNnp;
225 sigmaForceRef += fdiffRef * fdiffRef;
226 sigmaForceNnp += fdiffNnp * fdiffNnp;
227 }
228 }
229 MPI_Allreduce(MPI_IN_PLACE, &sigmaEnergyPerAtomRef, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
230 MPI_Allreduce(MPI_IN_PLACE, &sigmaEnergyPerAtomNnp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
231 MPI_Allreduce(MPI_IN_PLACE, &sigmaForceRef , 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
232 MPI_Allreduce(MPI_IN_PLACE, &sigmaForceNnp , 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
233 sigmaEnergyPerAtomRef = sqrt(sigmaEnergyPerAtomRef / (numStructures - 1));
234 sigmaEnergyPerAtomNnp = sqrt(sigmaEnergyPerAtomNnp / (numStructures - 1));
235 sigmaForceRef = sqrt(sigmaForceRef / (3 * numAtomsTotal - 1));
236 sigmaForceNnp = sqrt(sigmaForceNnp / (3 * numAtomsTotal - 1));
237 training.
log <<
"\n";
238 training.
log <<
strpr(
"Total number of structures : %zu\n", numStructures);
239 training.
log <<
strpr(
"Total number of atoms : %zu\n", numAtomsTotal);
240 training.
log <<
"----------------------------------\n";
241 training.
log <<
"Reference data statistics:\n";
242 training.
log <<
"----------------------------------\n";
243 training.
log <<
strpr(
"Mean/sigma energy per atom : %16.8E +/- %16.8E\n",
244 meanEnergyPerAtomRef,
245 sigmaEnergyPerAtomRef);
246 training.
log <<
strpr(
"Mean/sigma force : %16.8E +/- %16.8E\n",
247 meanForceRef,
248 sigmaForceRef);
249 training.
log <<
"----------------------------------\n";
250 training.
log <<
"Initial NNP prediction statistics:\n";
251 training.
log <<
"----------------------------------\n";
252 training.
log <<
strpr(
"Mean/sigma energy per atom : %16.8E +/- %16.8E\n",
253 meanEnergyPerAtomNnp,
254 sigmaEnergyPerAtomNnp);
255 training.
log <<
strpr(
"Mean/sigma force : %16.8E +/- %16.8E\n",
256 meanForceNnp,
257 sigmaForceNnp);
258 training.
log <<
"----------------------------------\n";
259 double convEnergy = sigmaForceNnp / sigmaForceRef;
260 double convLength = sigmaForceNnp;
261 training.
log <<
strpr(
"Conversion factor energy : %24.16E\n", convEnergy);
262 training.
log <<
strpr(
"Conversion factor length : %24.16E\n", convLength);
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 if (myRank == 0)
292 {
293 training.
log <<
"\n";
294 training.
log <<
"Writing backup of original settings file to "
295 "\"input.nn.bak\".\n";
296 ofstream fileSettings;
297 fileSettings.open("input.nn.bak");
299 fileSettings.close();
300
301 training.
log <<
"\n";
302 training.
log <<
"Writing extended settings file to \"input.nn\".\n";
303 training.
log <<
"Use this settings file for normalized training.\n";
304 fileSettings.open("input.nn");
305 fileSettings << "#########################################"
306 "######################################\n";
307 fileSettings << "# DATA SET NORMALIZATION\n";
308 fileSettings << "#########################################"
309 "######################################\n";
310 fileSettings <<
strpr(
"mean_energy %24.16E # nnp-norm2\n",
311 meanEnergyPerAtomRef);
312 fileSettings <<
strpr(
"conv_energy %24.16E # nnp-norm2\n", convEnergy);
313 fileSettings <<
strpr(
"conv_length %24.16E # nnp-norm2\n", convLength);
314 fileSettings << "#########################################"
315 "######################################\n";
316 fileSettings << "\n";
318 fileSettings.close();
319 }
320
321 training.
log <<
"*****************************************"
322 "**************************************\n";
323
324 myLog.close();
325
326 MPI_Finalize();
327
328 return 0;
329}
int distributeStructures(bool randomize, bool excludeRank0=false, std::string const &fileName="input.data")
Read data file and distribute structures among processors.
void setupMPI()
Initialize MPI with MPI_COMM_WORLD.
std::vector< Structure > structures
All structures in this dataset.
void setupRandomNumberGenerator()
Initialize random number generator.
void combineFiles(std::string filePrefix) const
Combine individual MPI proc files to one.
void registerStreamPointer(std::ofstream *const &streamPointer)
Register new C++ ofstream pointer.
bool writeToStdout
Turn on/off output to stdout.
NNPType getNnpType() const
Getter for Mode::nnpType.
void initialize()
Write welcome message with version information.
void setupGeneric(std::string const &nnpDir="", bool skipNormalize=false, bool initialHardness=false)
Combine multiple setup routines and provide a basic NNP setup.
void calculateAtomicNeuralNetworks(Structure &structure, bool const derivatives, std::string id="")
Calculate atomic neural networks for all atoms in given structure.
double getMaxCutoffRadius() const
Getter for Mode::maxCutoffRadius.
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.
virtual void setupSymmetryFunctionScaling(std::string const &fileName="scaling.data")
Set up symmetry function scaling from file.
bool settingsKeywordExists(std::string const &keyword) const
Check if keyword was found in settings file.
double getEnergyWithOffset(Structure const &structure, bool ref=true) const
Add atomic energy offsets and return energy.
void calculateSymmetryFunctions(Structure &structure, bool const derivatives)
Calculate all symmetry functions for all atoms in given structure.
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 loadSettingsFile(std::string const &fileName="input.nn")
Open settings file and load all keywords into memory.
void writeSettingsFile(std::ofstream *const &file) const
Write complete settings file.
void initializeWeights()
Initialize weights for all elements.
void writeWeights(std::string const &nnName, std::string const &fileNameFormat) const
Write weights to files (one file for each element).
void setStage(std::size_t stage)
Set training stage (if multiple stages are needed for NNP type).
string strpr(const char *format,...)
String version of printf function.
vector< string > createFileHeader(vector< string > const &title, vector< size_t > const &colSize, vector< string > const &colName, vector< string > const &colInfo, char const &commentChar)
void appendLinesToFile(ofstream &file, vector< string > const lines)
Append multiple lines of strings to open file stream.