61#include "brains/Register.hpp"
64#include "io/DumpWriter.hpp"
65#include "lattice/Lattice.hpp"
69#include "shapedLatticePentRod.hpp"
70#include "shapedLatticeRod.hpp"
71#include "utils/Constants.hpp"
72#include "utils/MoLocator.hpp"
77void createMdFile(
const std::string& oldMdFileName,
78 const std::string& newMdFileName, std::vector<int> numMol);
80int main(
int argc,
char* argv[]) {
84 std::string latticeType;
85 std::string inputFileName;
86 std::string outputFileName;
89 double latticeConstant;
96 if (cmdline_parser(argc, argv, &args_info) != 0) exit(1);
103 inputFileName = args_info.
inputs[0];
105 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
106 "No input .omd file name was specified "
107 "on the command line");
108 painCave.isFatal = 1;
120 Globals* simParams = oldInfo->getSimParams();
127 std::random_device rd;
129 std::mt19937 gen(rd());
134 RealType phi, theta, psi;
148 RotMat3x3d rotation45(45.0 * Constants::PI / 180.0, 0.0, 0.0);
161 theta = 72.0 * Constants::PI / 180.0;
165 RotMat3x3d rotation72(phi, theta, psi);
177 vector<Vector3d> getsites = nanoRod.getSites();
178 vector<Vector3d> getorientations = nanoRod.getOrientations();
179 vector<Vector3d> sites;
180 vector<Vector3d> orientations;
182 for (
unsigned int index = 0; index < getsites.size(); index++) {
183 Vector3d mySite = getsites[index];
184 Vector3d myOrient = getorientations[index];
185 Vector3d mySite2 = rotation45 * mySite;
186 Vector3d o2 = rotation45 * myOrient;
187 sites.push_back(mySite2);
188 orientations.push_back(o2);
190 mySite2 = rotation72 * mySite2;
191 o2 = rotation72 * o2;
192 sites.push_back(mySite2);
193 orientations.push_back(o2);
195 mySite2 = rotation72 * mySite2;
196 o2 = rotation72 * o2;
197 sites.push_back(mySite2);
198 orientations.push_back(o2);
200 mySite2 = rotation72 * mySite2;
201 o2 = rotation72 * o2;
202 sites.push_back(mySite2);
203 orientations.push_back(o2);
205 mySite2 = rotation72 * mySite2;
206 o2 = rotation72 * o2;
207 sites.push_back(mySite2);
208 orientations.push_back(o2);
211 int nCenter = int((rodLength + 1.154700538 * rodRadius) / 2.88);
213 for (
unsigned int index = 0; index <= 0.5 * nCenter; index++) {
214 Vector3d myLoc_top(2.88 * index, 0.0, 0.0);
215 sites.push_back(myLoc_top);
216 orientations.push_back(Vector3d(0.0));
219 for (
unsigned int index = 1; index <= 0.5 * nCenter; index++) {
220 Vector3d myLoc_bottom(-2.88 * index, 0.0, 0.0);
221 sites.push_back(myLoc_bottom);
222 orientations.push_back(Vector3d(0.0));
225 std::vector<std::size_t> vacancyTargets;
226 vector<bool> isVacancy;
231 for (
unsigned int i = 0; i < sites.size(); i++)
232 isVacancy.push_back(
false);
239 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
240 "vacancyPercent was set to a non-sensical value.");
241 painCave.isFatal = 1;
258 if (vIR >= 0.0 && vOR <= rodRadius && vOR >= vIR) {
259 for (
unsigned int i = 0; i < sites.size(); i++) {
262 if (myR >= vIR && myR <= vOR) { vacancyTargets.push_back(i); }
264 std::shuffle(vacancyTargets.begin(), vacancyTargets.end(), gen);
266 int nTargets = vacancyTargets.size();
267 vacancyTargets.resize((
int)(vF * nTargets));
269 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
270 "Removing %d atoms from randomly-selected\n"
271 "\tsites between %lf and %lf.",
272 (
int)vacancyTargets.size(), vIR, vOR);
273 painCave.severity = OPENMD_INFO;
274 painCave.isFatal = 0;
278 for (std::size_t i = 0; i < sites.size(); i++) {
280 for (std::size_t j = 0; j < vacancyTargets.size(); j++) {
281 if (i == vacancyTargets[j]) vac =
true;
283 isVacancy.push_back(vac);
287 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
288 "Something is strange about the vacancy\n"
289 "\tinner or outer radii. Check their values.");
290 painCave.isFatal = 1;
297 int nSites = sites.size() - vacancyTargets.size();
303 std::vector<Component*> components = simParams->getComponents();
304 std::vector<RealType> molFractions;
305 std::vector<RealType> shellRadii;
306 std::vector<int> nMol;
307 std::map<int, int> componentFromSite;
308 nComponents = components.size();
312 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
313 "Specify either molFraction or shellRadius "
314 "arguments, but not both!");
315 painCave.isFatal = 1;
319 if (nComponents == 1) {
320 molFractions.push_back(1.0);
321 shellRadii.push_back(rodRadius);
324 for (
int i = 0; i < nComponents; i++) {
328 RealType remainingFraction = 1.0;
329 for (
int i = 0; i < nComponents - 1; i++) {
331 remainingFraction -= molFractions[i];
333 molFractions.push_back(remainingFraction);
335 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
336 "nanorodBuilder can't figure out molFractions "
337 "for all of the components in the <MetaData> block.");
338 painCave.isFatal = 1;
343 for (
int i = 0; i < nComponents; i++) {
347 for (
int i = 0; i < nComponents - 1; i++) {
350 shellRadii.push_back(rodRadius);
353 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
354 "nanorodBuilder can't figure out the\n"
355 "\tshell radii for all of the components in the <MetaData> block.");
356 painCave.isFatal = 1;
360 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
361 "You have a multi-component <MetaData> block,\n"
362 "\tbut have not specified either molFraction or shellRadius "
364 painCave.isFatal = 1;
369 RealType totalFraction = 0.0;
373 for (
int i = 0; i < nComponents; i++) {
374 if (molFractions.at(i) < 0.0) {
375 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
376 "One of the requested molFractions was"
378 painCave.isFatal = 1;
381 if (molFractions.at(i) > 1.0) {
382 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
383 "One of the requested molFractions was"
384 " greater than one!");
385 painCave.isFatal = 1;
388 totalFraction += molFractions.at(i);
390 if (abs(totalFraction - 1.0) > 1e-6) {
391 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
392 "The sum of molFractions was not close enough to 1.0");
393 painCave.isFatal = 1;
397 int remaining = nSites;
398 for (
int i = 0; i < nComponents - 1; i++) {
399 nMol.push_back(
int((RealType)nSites * molFractions.at(i)));
400 remaining -= nMol.at(i);
402 nMol.push_back(remaining);
406 int totalMolecules = 0;
407 for (
int i = 0; i < nComponents; i++) {
408 molFractions[i] = (RealType)(nMol.at(i)) / (RealType)nSites;
409 totalMolecules += nMol.at(i);
411 if (totalMolecules != nSites) {
412 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
413 "Computed total number of molecules is not equal "
414 "to the number of lattice sites!");
415 painCave.isFatal = 1;
419 for (
unsigned int i = 0; i < shellRadii.size(); i++) {
420 if (shellRadii.at(i) > rodRadius + 1e-6) {
421 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
422 "One of the shellRadius values exceeds the rod Radius.");
423 painCave.isFatal = 1;
426 if (shellRadii.at(i) <= 0.0) {
427 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
428 "One of the shellRadius values is smaller than zero!");
429 painCave.isFatal = 1;
438 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
439 "Creating a randomized spherically-capped nanorod.");
440 painCave.isFatal = 0;
441 painCave.severity = OPENMD_INFO;
445 for (
unsigned int i = 0; i < sites.size(); i++)
446 if (!isVacancy[i]) ids.push_back(i);
448 std::shuffle(ids.begin(), ids.end(), gen);
451 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
452 "Creating an fcc nanorod.");
453 painCave.isFatal = 0;
454 painCave.severity = OPENMD_INFO;
458 int myComponent = -1;
460 nMol.resize(nComponents);
465 for (
unsigned int i = 0; i < sites.size(); i++) {
481 componentFromSite[i] = myComponent;
495 createMdFile(inputFileName, outputFileName, nMol);
504 SimInfo::MoleculeIterator mi;
509 for (
int i = 0; i < nComponents; i++) {
515 for (
unsigned int n = 0; n < sites.size(); n++) {
517 if (componentFromSite[n] == i) {
519 locator->placeMol(sites[n], orientations[n], mol);
525 for (
int n = 0; n < nMol.at(i); n++) {
527 locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
534 hmat(0, 0) = 10.0 * rodRadius;
539 hmat(1, 1) = 10.0 * rodRadius;
544 hmat(2, 2) = 5.0 * rodLength + 2.0 * rodRadius;
550 writer =
new DumpWriter(NewInfo, outputFileName);
552 if (writer == NULL) {
553 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
554 "Error in creating dumpwriter object ");
555 painCave.isFatal = 1;
566 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
567 "A new OpenMD file called \"%s\" has been "
569 outputFileName.c_str());
570 painCave.isFatal = 0;
571 painCave.severity = OPENMD_INFO;
576void createMdFile(
const std::string& oldMdFileName,
577 const std::string& newMdFileName, std::vector<int> nMol) {
580 const int MAXLEN = 65535;
584 oldMdFile.open(oldMdFileName.c_str());
585 newMdFile.open(newMdFileName.c_str());
586 oldMdFile.getline(buffer, MAXLEN);
589 while (!oldMdFile.eof()) {
591 if (strstr(buffer,
"nMol") != NULL) {
592 if (i < nMol.size()) {
593 snprintf(buffer, MAXLEN,
"\tnMol = %i;", nMol.at(i));
594 newMdFile << buffer << std::endl;
598 newMdFile << buffer << std::endl;
600 oldMdFile.getline(buffer, MAXLEN);
606 if (i != nMol.size()) {
607 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
608 "Couldn't replace the correct number of nMol\n"
609 "\tstatements in component blocks. Make sure that all\n"
610 "\tcomponents in the template file have nMol=1");
611 painCave.isFatal = 1;
void cmdline_parser_print_help(void)
Print the help.
The only responsibility of SimCreator is to parse the meta-data file and create a SimInfo instance ba...
SimInfo * createSim(const std::string &mdFileName, bool loadInitCoords=true)
Setup Simulation.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Molecule * getMoleculeByGlobalIndex(int index)
Finds a molecule with a specified global index.
ForceField * getForceField()
Returns the force field.
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
MoleculeStamp * getMoleculeStamp(int id)
Returns the molecule stamp.
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
void setHmat(const Mat3x3d &m)
Sets the H-Matrix.
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
Real length() const
Returns the length of this vector.
Implements a spherically-capped rod-shaped lattice.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
void registerLattice()
Register all lattice.
The header file for the command line option parser generated by GNU Gengetopt version 2....
Where the command line options are stored.
unsigned int vacancyInnerRadius_given
Whether vacancyInnerRadius was given.
double vacancyPercent_arg
Percentage of atoms to remove from within vacancy range.
double vacancyOuterRadius_arg
Radius arround core-shell where vacancies should be located.
unsigned inputs_num
unamed options number
unsigned int molFraction_given
Whether molFraction was given.
double length_arg
maximum length (default='100').
double * molFraction_arg
Builds a multi-component random alloy nanoparticle.
char * output_arg
output file name.
char ** inputs
unamed options (options without names)
double * shellRadius_arg
Radius containing within it only molecules of a specific component.
unsigned int shellRadius_given
Whether shellRadius was given.
double radius_arg
Nanoparticle radius in Angstroms.
double vacancyInnerRadius_arg
Radius arround core-shell where vacancies should be located.
unsigned int vacancyPercent_given
Whether vacancyPercent was given.
double latticeConstant_arg
Lattice spacing in Angstroms for cubic lattice.
unsigned int vacancyOuterRadius_given
Whether vacancyOuterRadius was given.