35int main(
int argc,
char* argv[])
39 cout <<
"USAGE: " << argv[0] <<
" <rcut> <nbin> <adf> <elem1 "
40 <<
"<elem2 <elem3...>>>\n"
41 <<
" <rcut> .... Cutoff radius.\n"
42 <<
" <nbin> .... Number of histogram bins.\n"
43 <<
" <adf> ..... Calculate angle distribution (0/1).\n"
44 <<
" <elemN> ... Symbol for Nth element.\n"
45 <<
" Execute in directory with these NNP files present:\n"
46 <<
" - input.data (structure file)\n";
56 log <<
"*** NNP-DIST ****************************"
57 "**************************************\n";
60 size_t numElements = argc - 4;
61 log <<
strpr(
"Number of elements: %zu\n", numElements);
64 for (
size_t i = 5; i < numElements + 4; ++i)
69 log <<
strpr(
"Element string : %s\n", elements.c_str());
70 double cutoffRadius = atof(argv[1]);
71 log <<
strpr(
"Cutoff radius : %f\n", cutoffRadius);
72 size_t numBins = (size_t)atoi(argv[2]);
73 log <<
strpr(
"Histogram bins : %zu\n", numBins);
74 bool calcAdf = (bool)atoi(argv[3]);
75 log <<
strpr(
"Calculate ADF : %d\n", calcAdf);
77 double minCellLength = numeric_limits<double>::max();
78 double maxCellLength = 0.0;
79 vector<size_t> periodicStructures;
80 vector<vector<double>> cellLengths(3);
82 size_t numRdf = numElements * (numElements + 1);
84 log <<
strpr(
"Number of RDFs : %zu\n", numRdf);
88 numAdf = numElements * numElements * (numElements + 1);
91 log <<
strpr(
"Number of ADFs : %zu\n", numAdf);
92 log <<
"*****************************************"
93 "**************************************\n";
98 double dr = cutoffRadius / numBins;
99 map<pair<size_t, size_t>, vector<double>* > rhist;
100 map<pair<size_t, size_t>, vector<double>* > rdf;
101 double da = 180.0 / numBins;
102 vector<map<pair<size_t, size_t>, vector<double>* > > ahist(numElements);
103 vector<map<pair<size_t, size_t>, vector<double>* > > adf(numElements);
105 for (
size_t i = 0; i < numElements; ++i)
107 for (
size_t j = i; j < numElements; ++j)
109 pair<size_t, size_t> e(i, j);
110 rhist[e] =
new vector<double>(numBins, 0);
111 rdf [e] =
new vector<double>(numBins, 0.0);
114 rhist[make_pair(j, i)] = rhist[e];
115 rdf [make_pair(j, i)] = rdf [e];
121 for (
size_t i = 0; i < numElements; ++i)
123 for (
size_t j = 0; j < numElements; ++j)
125 for (
size_t k = j; k < numElements; ++k)
127 pair<size_t, size_t> e(j, k);
128 ahist.at(i)[e] =
new vector<double>(numBins, 0);
129 adf.at(i) [e] =
new vector<double>(numBins, 0.0);
132 ahist.at(i)[make_pair(k, j)] = ahist.at(i)[e];
133 adf.at(i) [make_pair(k, j)] = adf.at(i) [e];
141 inputFile.open(
"input.data");
145 size_t countStructures = 0;
146 size_t countPeriodicStructures = 0;
147 vector<double> numberDensity(numElements, 0.0);
148 while (inputFile.peek() != EOF)
154 periodicStructures.push_back(countStructures);
155 for (
size_t i = 0; i < 3; ++i)
157 cellLengths.at(i).push_back(structure.
box[i].
norm());
160 for (vector<Atom>::const_iterator it = structure.
atoms.begin();
161 it != structure.
atoms.end(); ++it)
163 for (
size_t j = 0; j < it->numNeighbors; ++j)
165 size_t const ei = it->element;
168 double const rij = nj.
d;
169 pair<size_t, size_t> e(ei, ej);
172 rhist[e]->at((
size_t)floor(rij / dr)) += 1.0;
176 rhist[e]->at((
size_t)floor(rij / dr)) += 0.5;
180 for (
size_t k = j + 1; k < it->numNeighbors; ++k)
184 e = make_pair(ej, ek);
185 double theta = nj.
dr * nk.
dr / (nj.
d * nk.
d);
190 ahist.at(ei)[e]->at(0) += 1.0;
194 else if (theta <= -1.0)
196 ahist.at(ei)[e]->at(numBins - 1) += 1.0;
200 theta = acos(theta) * 180.0 / M_PI;
202 ->at((
size_t)floor(theta / da)) += 1.0;
209 if (structure.
isPeriodic) countPeriodicStructures++;
210 double const volume = structure.
volume;
211 for (
size_t i = 0; i < numElements; ++i)
216 numberDensity.at(i) += nni / volume;
218 for (
size_t j = i; j < numElements; ++j)
221 if (nni == 0 || nnj == 0)
continue;
222 pair<size_t, size_t> e(i, j);
223 for (
size_t n = 0; n < numBins; ++n)
225 double r = (n + 0.5) * dr;
228 rhist[e]->at(n) *= volume / (nni * nnj);
230 rdf[e]->at(n) += rhist[e]->at(n)
231 / (4.0 * M_PI * r * r * dr);
234 rhist[e]->resize(numBins, 0.0);
239 for (
size_t i = 0; i < numElements; ++i)
241 for (
size_t j = 0; j < numElements; ++j)
243 for (
size_t k = j; k < numElements; ++k)
245 pair<size_t, size_t> e(j, k);
246 double countAngles = 0.0;
247 for (
size_t n = 0; n < numBins; ++n)
249 countAngles += ahist.at(i)[e]->at(n);
253 for (
size_t n = 0; n < numBins; ++n)
255 adf.at(i)[e]->at(n) += ahist.at(i)[e]->at(n)
259 ahist.at(i)[e]->clear();
260 ahist.at(i)[e]->resize(numBins, 0.0);
265 log <<
strpr(
"Configuration %7zu: %7zu atoms\n",
270 log <<
"*****************************************"
271 "**************************************\n";
272 log <<
strpr(
"Number of structures: %9zu\n", countStructures);
273 log <<
strpr(
"Number of periodic structures: %9zu\n",
274 countPeriodicStructures);
276 if (countStructures == countPeriodicStructures) calcCn =
true;
279 vector<double>::const_iterator minnd = min_element(
280 numberDensity.begin(), numberDensity.end());
281 for (
size_t i = 0; i < numElements; ++i)
283 log <<
strpr(
"Number density (ratio) of element %2s: %16.8E "
284 "(%.2f)\n", elementMap[i].c_str(),
285 numberDensity.at(i), numberDensity.at(i) / (*minnd));
290 if (countPeriodicStructures > 0)
292 outputFile.open(
"cell-lengths.out");
295 vector<string> title;
296 vector<string> colName;
297 vector<string> colInfo;
298 vector<size_t> colSize;
299 title.push_back(
"Unit cell vector lengths for each periodic "
301 colSize.push_back(10);
302 colName.push_back(
"index");
303 colInfo.push_back(
"Index of periodic structure in data set "
304 "(starting with 1).");
305 colSize.push_back(16);
306 colName.push_back(
"norm(A)");
307 colInfo.push_back(
"Norm of 1st unit cell vector.");
308 colSize.push_back(16);
309 colName.push_back(
"norm(B)");
310 colInfo.push_back(
"Norm of 2nd unit cell vector.");
311 colSize.push_back(16);
312 colName.push_back(
"norm(C)");
313 colInfo.push_back(
"Norm of 3rd unit cell vector.");
321 for (
size_t i = 0; i < periodicStructures.size(); ++i)
323 outputFile <<
strpr(
"%10zu %16.8E %16.8E %16.8E\n",
324 periodicStructures.at(i) + 1,
325 cellLengths.at(0).at(i),
326 cellLengths.at(1).at(i),
327 cellLengths.at(2).at(i));
328 for (
size_t j = 0; j < 3; ++j)
330 minCellLength = min(minCellLength, cellLengths.at(j).at(i));
331 maxCellLength = max(maxCellLength, cellLengths.at(j).at(i));
337 log <<
strpr(
"Minimum unit cell vector length : %16.8E\n",
339 log <<
strpr(
"Maximum unit cell vector length : %16.8E\n",
342 log <<
"*****************************************"
343 "**************************************\n";
345 for (
size_t i = 0; i < numElements; ++i)
347 for (
size_t j = i; j < numElements; ++j)
349 pair<size_t, size_t> e(i, j);
350 string fileName =
strpr(
"rdf_%s_%s.out",
351 elementMap[i].c_str(),
352 elementMap[j].c_str());
353 log <<
strpr(
"Writing RDF for element combination (%2s/%2s) "
355 elementMap[i].c_str(),
356 elementMap[j].c_str(),
358 outputFile.open(fileName.c_str());
361 vector<string> title;
362 vector<string> colName;
363 vector<string> colInfo;
364 vector<size_t> colSize;
365 title.push_back(
strpr(
"Radial distribution function for element "
366 "combination %2s-%2s.",
367 elementMap[i].c_str(),
368 elementMap[j].c_str()));
369 colSize.push_back(16);
370 colName.push_back(
"dist_bin_l");
371 colInfo.push_back(
"Distance, left bin limit.");
372 colSize.push_back(16);
373 colName.push_back(
"dist_bin_r");
374 colInfo.push_back(
"Distance, right bin limit.");
375 colSize.push_back(16);
376 colName.push_back(
"rdf");
377 colInfo.push_back(
"Radial distribution function, standard "
378 "normalization (-> 1 for r -> inf)");
379 colSize.push_back(16);
380 colName.push_back(
"rdf_max1");
381 colInfo.push_back(
"Radial distribution function, maximum "
385 colSize.push_back(16);
386 colName.push_back(
"cn");
387 colInfo.push_back(
"Coordination number.");
395 vector<double> cn(rdf[e]->size(), 0.0);
396 double integral = 0.0;
397 double const pre = 4.0 * M_PI * dr * 0.5
398 / countStructures / countStructures;
399 double maxRdf = *max_element(rdf[e]->begin(), rdf[e]->end());
400 for (
size_t n = 0; n < numBins; ++n)
402 double const low = n * dr;
403 double const center = (n + 0.5) * dr;
404 double const high = (n + 1) * dr;
405 outputFile <<
strpr(
"%16.8E %16.8E %16.8E %16.8E",
408 rdf[e]->at(n) / countStructures,
409 rdf[e]->at(n) / maxRdf);
414 integral += pre * center * center * numberDensity.at(j)
415 * (rdf[e]->at(n-1) + rdf[e]->at(n));
417 outputFile <<
strpr(
" %16.8E", integral);
428 for (
size_t i = 0; i < numElements; ++i)
430 for (
size_t j = 0; j < numElements; ++j)
432 for (
size_t k = j; k < numElements; ++k)
434 pair<size_t, size_t> e(j, k);
435 string fileName =
strpr(
"adf_%s_%s_%s.out",
436 elementMap[i].c_str(),
437 elementMap[j].c_str(),
438 elementMap[k].c_str());
439 log <<
strpr(
"Writing ADF for element combination "
440 "(%2s/%2s/%2s) to file %s.\n",
441 elementMap[i].c_str(),
442 elementMap[j].c_str(),
443 elementMap[k].c_str(),
445 outputFile.open(fileName.c_str());
448 vector<string> title;
449 vector<string> colName;
450 vector<string> colInfo;
451 vector<size_t> colSize;
452 title.push_back(
strpr(
"Angular distribution function for "
453 "element combination %2s-%2s-%2s.",
454 elementMap[i].c_str(),
455 elementMap[j].c_str(),
456 elementMap[k].c_str()));
457 colSize.push_back(16);
458 colName.push_back(
"angle_bin_l");
459 colInfo.push_back(
"Angle [degree], left bin limit.");
460 colSize.push_back(16);
461 colName.push_back(
"angle_bin_r");
462 colInfo.push_back(
"Angle [degree], right bin limit.");
463 colSize.push_back(16);
464 colName.push_back(
"adf");
465 colInfo.push_back(
"Angular distribution function, "
466 "probability normalization "
468 colSize.push_back(16);
469 colName.push_back(
"adf_max1");
470 colInfo.push_back(
"Angular distribution function, maximum "
478 double maxAdf = *max_element(adf.at(i)[e]->begin(),
479 adf.at(i)[e]->end());
480 for (
size_t n = 0; n < numBins; ++n)
482 double const low = n * da;
483 double const high = (n + 1) * da;
484 outputFile <<
strpr(
"%16.8E %16.8E %16.8E %16.8E\n",
489 adf.at(i)[e]->at(n) / maxAdf);
492 delete adf.at(i) [e];
493 delete ahist.at(i)[e];
499 log <<
"*****************************************"
500 "**************************************\n";
std::size_t registerElements(std::string const &elementLine)
Extract all elements and store in element map.
Logging class for library output.
void registerStreamPointer(std::ofstream *const &streamPointer)
Register new C++ ofstream pointer.
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.
int main(int argc, char *argv[])
Struct to store information on neighbor atoms.
std::size_t element
Element index of neighbor atom.
double d
Distance to neighbor atom.
Vec3D dr
Distance vector to neighbor atom.
Storage for one atomic configuration.
Vec3D box[3]
Simulation box vectors.
std::vector< std::size_t > numAtomsPerElement
Number of atoms of each element in this structure.
bool isPeriodic
If periodic boundary conditions apply.
void setElementMap(ElementMap const &elementMap)
Set element map of structure.
void readFromFile(std::string const fileName="input.data")
Read configuration from file.
void reset()
Reset everything but elementMap.
double volume
Simulation box volume.
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.
std::vector< Atom > atoms
Vector of all atoms in this structure.
double norm() const
Calculate norm of vector.