61#include "brains/Register.hpp"
64#include "io/DumpWriter.hpp"
65#include "lattice/Lattice.hpp"
70#include "shapedLatticeSpherical.hpp"
71#include "utils/MoLocator.hpp"
76void createMdFile(
const std::string& oldMdFileName,
77 const std::string& newMdFileName, std::vector<int> numMol);
79int main(
int argc,
char* argv[]) {
83 std::string latticeType;
84 std::string inputFileName;
85 std::string outputFileName;
88 double latticeConstant;
89 RealType particleRadius;
94 if (cmdline_parser(argc, argv, &args_info) != 0) exit(1);
101 inputFileName = args_info.
inputs[0];
103 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
104 "No input .omd file name was specified "
105 "on the command line");
106 painCave.isFatal = 1;
117 Globals* simParams = oldInfo->getSimParams();
124 vector<Vector3d> sites = nanoParticle.getSites();
125 vector<Vector3d> orientations = nanoParticle.getOrientations();
128 std::random_device rd;
130 std::mt19937 gen(rd());
132 std::vector<std::size_t> vacancyTargets;
133 vector<bool> isVacancy;
138 for (
unsigned int i = 0; i < sites.size(); i++)
139 isVacancy.push_back(
false);
144 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
145 "vacancyPercent was set to a non-sensical value.");
146 painCave.isFatal = 1;
160 vOR = particleRadius;
162 if (vIR >= 0.0 && vOR <= particleRadius && vOR >= vIR) {
163 for (std::size_t i = 0; i < sites.size(); i++) {
166 if (myR >= vIR && myR <= vOR) { vacancyTargets.push_back(i); }
168 std::shuffle(vacancyTargets.begin(), vacancyTargets.end(), gen);
170 int nTargets = vacancyTargets.size();
171 vacancyTargets.resize((
int)(vF * nTargets));
173 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
174 "Removing %d atoms from randomly-selected\n"
175 "\tsites between %lf and %lf.",
176 (
int)vacancyTargets.size(), vIR, vOR);
177 painCave.isFatal = 0;
178 painCave.severity = OPENMD_INFO;
182 for (std::size_t i = 0; i < sites.size(); i++) {
184 for (std::size_t j = 0; j < vacancyTargets.size(); j++) {
185 if (i == vacancyTargets[j]) vac =
true;
187 isVacancy.push_back(vac);
191 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
192 "Something is strange about the vacancy\n"
193 "\tinner or outer radii. Check their values.");
194 painCave.isFatal = 1;
201 std::size_t nSites = sites.size() - vacancyTargets.size();
203 std::vector<Component*> components = simParams->getComponents();
204 std::vector<RealType> molFractions;
205 std::vector<RealType> shellRadii;
206 std::vector<int> nMol;
207 std::map<int, int> componentFromSite;
208 nComponents = components.size();
211 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
212 "Specify either molFraction or shellRadius "
213 "arguments, but not both!");
214 painCave.isFatal = 1;
218 if (nComponents == 1) {
219 molFractions.push_back(1.0);
220 shellRadii.push_back(particleRadius);
223 for (
int i = 0; i < nComponents; i++) {
227 RealType remainingFraction = 1.0;
228 for (
int i = 0; i < nComponents - 1; i++) {
230 remainingFraction -= molFractions[i];
232 molFractions.push_back(remainingFraction);
234 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
235 "nanoparticleBuilder can't figure out molFractions "
236 "for all of the components in the <MetaData> block.");
237 painCave.isFatal = 1;
242 for (
int i = 0; i < nComponents; i++) {
246 for (
int i = 0; i < nComponents - 1; i++) {
249 shellRadii.push_back(particleRadius);
252 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
253 "nanoparticleBuilder can't figure out the\n"
254 "\tshell radii for all of the components in the <MetaData> block.");
255 painCave.isFatal = 1;
259 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
260 "You have a multi-component <MetaData> block,\n"
261 "\tbut have not specified either molFraction or shellRadius "
263 painCave.isFatal = 1;
268 RealType totalFraction = 0.0;
272 for (
int i = 0; i < nComponents; i++) {
273 if (molFractions.at(i) < 0.0) {
274 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
275 "One of the requested molFractions was"
277 painCave.isFatal = 1;
280 if (molFractions.at(i) > 1.0) {
281 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
282 "One of the requested molFractions was"
283 " greater than one!");
284 painCave.isFatal = 1;
287 totalFraction += molFractions.at(i);
289 if (abs(totalFraction - 1.0) > 1e-6) {
290 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
291 "The sum of molFractions was not close enough to 1.0");
292 painCave.isFatal = 1;
296 int remaining = nSites;
297 for (
int i = 0; i < nComponents - 1; i++) {
298 nMol.push_back(
int((RealType)nSites * molFractions.at(i)));
299 remaining -= nMol.at(i);
301 nMol.push_back(remaining);
305 std::size_t totalMolecules = 0;
306 for (
int i = 0; i < nComponents; i++) {
307 molFractions[i] = (RealType)(nMol.at(i)) / (RealType)nSites;
308 totalMolecules += nMol.at(i);
311 if (totalMolecules != nSites) {
312 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
313 "Computed total number of molecules is not equal "
314 "to the number of lattice sites!");
315 painCave.isFatal = 1;
319 for (
unsigned int i = 0; i < shellRadii.size(); i++) {
320 if (shellRadii.at(i) > particleRadius + 1e-6) {
321 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
322 "One of the shellRadius values exceeds the particle Radius.");
323 painCave.isFatal = 1;
326 if (shellRadii.at(i) <= 0.0) {
327 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
328 "One of the shellRadius values is smaller than zero!");
329 painCave.isFatal = 1;
337 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
338 "Creating a randomized spherical nanoparticle.");
339 painCave.isFatal = 0;
340 painCave.severity = OPENMD_INFO;
344 for (
unsigned int i = 0; i < sites.size(); i++)
345 if (!isVacancy[i]) ids.push_back(i);
347 std::shuffle(ids.begin(), ids.end(), gen);
350 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
351 "Creating a core-shell spherical nanoparticle.");
352 painCave.isFatal = 0;
353 painCave.severity = OPENMD_INFO;
356 RealType smallestSoFar;
357 int myComponent = -1;
359 nMol.resize(nComponents);
361 for (
unsigned int i = 0; i < sites.size(); i++) {
364 smallestSoFar = particleRadius;
366 for (
int j = 0; j < nComponents; j++) {
367 if (myR <= shellRadii[j]) {
368 if (shellRadii[j] <= smallestSoFar) {
369 smallestSoFar = shellRadii[j];
374 componentFromSite[i] = myComponent;
383 createMdFile(inputFileName, outputFileName, nMol);
392 SimInfo::MoleculeIterator mi;
397 for (
int i = 0; i < nComponents; i++) {
402 for (
unsigned int n = 0; n < sites.size(); n++) {
404 if (componentFromSite[n] == i) {
406 locator->placeMol(sites[n], orientations[n], mol);
412 for (
int n = 0; n < nMol.at(i); n++) {
414 locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
421 hmat(0, 0) = 10.0 * particleRadius;
426 hmat(1, 1) = 10.0 * particleRadius;
431 hmat(2, 2) = 10.0 * particleRadius;
437 writer =
new DumpWriter(NewInfo, outputFileName);
439 if (writer == NULL) {
440 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
441 "Error in creating dumpwriter object ");
442 painCave.isFatal = 1;
453 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
454 "A new OpenMD file called \"%s\" has been "
456 outputFileName.c_str());
457 painCave.isFatal = 0;
458 painCave.severity = OPENMD_INFO;
463void createMdFile(
const std::string& oldMdFileName,
464 const std::string& newMdFileName, std::vector<int> nMol) {
467 const int MAXLEN = 65535;
471 oldMdFile.open(oldMdFileName.c_str());
472 newMdFile.open(newMdFileName.c_str());
473 oldMdFile.getline(buffer, MAXLEN);
476 while (!oldMdFile.eof()) {
478 if (strstr(buffer,
"nMol") != NULL) {
479 if (i < nMol.size()) {
480 snprintf(buffer, MAXLEN,
"\tnMol = %i;", nMol.at(i));
481 newMdFile << buffer << std::endl;
485 newMdFile << buffer << std::endl;
487 oldMdFile.getline(buffer, MAXLEN);
493 if (i != nMol.size()) {
494 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
495 "Couldn't replace the correct number of nMol\n"
496 "\tstatements in component blocks. Make sure that all\n"
497 "\tcomponents in the template file have nMol=1");
498 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 spherical 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 * 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.