58#include "brains/Register.hpp"
61#include "io/DumpWriter.hpp"
62#include "lattice/Lattice.hpp"
67#include "shapedLatticeSpherical.hpp"
68#include "utils/MoLocator.hpp"
73void createMdFile(
const std::string& oldMdFileName,
74 const std::string& newMdFileName, std::vector<int> numMol);
76int main(
int argc,
char* argv[]) {
80 std::string latticeType;
81 std::string inputFileName;
82 std::string outputFileName;
85 double latticeConstant;
86 RealType particleRadius;
91 if (cmdline_parser(argc, argv, &args_info) != 0) exit(1);
98 inputFileName = args_info.
inputs[0];
100 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
101 "No input .omd file name was specified "
102 "on the command line");
103 painCave.isFatal = 1;
104 cmdline_parser_print_help();
114 Globals* simParams = oldInfo->getSimParams();
121 vector<Vector3d> sites = nanoParticle.getSites();
122 vector<Vector3d> orientations = nanoParticle.getOrientations();
125 std::random_device rd;
127 std::mt19937 gen(rd());
129 std::vector<std::size_t> vacancyTargets;
130 vector<bool> isVacancy;
135 for (
unsigned int i = 0; i < sites.size(); i++)
136 isVacancy.push_back(
false);
141 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
142 "vacancyPercent was set to a non-sensical value.");
143 painCave.isFatal = 1;
157 vOR = particleRadius;
159 if (vIR >= 0.0 && vOR <= particleRadius && vOR >= vIR) {
160 for (std::size_t i = 0; i < sites.size(); i++) {
163 if (myR >= vIR && myR <= vOR) { vacancyTargets.push_back(i); }
165 std::shuffle(vacancyTargets.begin(), vacancyTargets.end(), gen);
167 int nTargets = vacancyTargets.size();
168 vacancyTargets.resize((
int)(vF * nTargets));
170 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
171 "Removing %d atoms from randomly-selected\n"
172 "\tsites between %lf and %lf.",
173 (
int)vacancyTargets.size(), vIR, vOR);
174 painCave.isFatal = 0;
175 painCave.severity = OPENMD_INFO;
179 for (std::size_t i = 0; i < sites.size(); i++) {
181 for (std::size_t j = 0; j < vacancyTargets.size(); j++) {
182 if (i == vacancyTargets[j]) vac =
true;
184 isVacancy.push_back(vac);
188 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
189 "Something is strange about the vacancy\n"
190 "\tinner or outer radii. Check their values.");
191 painCave.isFatal = 1;
198 std::size_t nSites = sites.size() - vacancyTargets.size();
200 std::vector<Component*> components = simParams->getComponents();
201 std::vector<RealType> molFractions;
202 std::vector<RealType> shellRadii;
203 std::vector<int> nMol;
204 std::map<int, int> componentFromSite;
205 nComponents = components.size();
208 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
209 "Specify either molFraction or shellRadius "
210 "arguments, but not both!");
211 painCave.isFatal = 1;
215 if (nComponents == 1) {
216 molFractions.push_back(1.0);
217 shellRadii.push_back(particleRadius);
220 for (
int i = 0; i < nComponents; i++) {
224 RealType remainingFraction = 1.0;
225 for (
int i = 0; i < nComponents - 1; i++) {
227 remainingFraction -= molFractions[i];
229 molFractions.push_back(remainingFraction);
231 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
232 "nanoparticleBuilder can't figure out molFractions "
233 "for all of the components in the <MetaData> block.");
234 painCave.isFatal = 1;
239 for (
int i = 0; i < nComponents; i++) {
243 for (
int i = 0; i < nComponents - 1; i++) {
246 shellRadii.push_back(particleRadius);
249 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
250 "nanoparticleBuilder can't figure out the\n"
251 "\tshell radii for all of the components in the <MetaData> block.");
252 painCave.isFatal = 1;
256 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
257 "You have a multi-component <MetaData> block,\n"
258 "\tbut have not specified either molFraction or shellRadius "
260 painCave.isFatal = 1;
265 RealType totalFraction = 0.0;
269 for (
int i = 0; i < nComponents; i++) {
270 if (molFractions.at(i) < 0.0) {
271 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
272 "One of the requested molFractions was"
274 painCave.isFatal = 1;
277 if (molFractions.at(i) > 1.0) {
278 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
279 "One of the requested molFractions was"
280 " greater than one!");
281 painCave.isFatal = 1;
284 totalFraction += molFractions.at(i);
286 if (abs(totalFraction - 1.0) > 1e-6) {
287 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
288 "The sum of molFractions was not close enough to 1.0");
289 painCave.isFatal = 1;
293 int remaining = nSites;
294 for (
int i = 0; i < nComponents - 1; i++) {
295 nMol.push_back(
int((RealType)nSites * molFractions.at(i)));
296 remaining -= nMol.at(i);
298 nMol.push_back(remaining);
302 std::size_t totalMolecules = 0;
303 for (
int i = 0; i < nComponents; i++) {
304 molFractions[i] = (RealType)(nMol.at(i)) / (RealType)nSites;
305 totalMolecules += nMol.at(i);
308 if (totalMolecules != nSites) {
309 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
310 "Computed total number of molecules is not equal "
311 "to the number of lattice sites!");
312 painCave.isFatal = 1;
316 for (
unsigned int i = 0; i < shellRadii.size(); i++) {
317 if (shellRadii.at(i) > particleRadius + 1e-6) {
318 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
319 "One of the shellRadius values exceeds the particle Radius.");
320 painCave.isFatal = 1;
323 if (shellRadii.at(i) <= 0.0) {
324 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
325 "One of the shellRadius values is smaller than zero!");
326 painCave.isFatal = 1;
334 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
335 "Creating a randomized spherical nanoparticle.");
336 painCave.isFatal = 0;
337 painCave.severity = OPENMD_INFO;
341 for (
unsigned int i = 0; i < sites.size(); i++)
342 if (!isVacancy[i]) ids.push_back(i);
344 std::shuffle(ids.begin(), ids.end(), gen);
347 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
348 "Creating a core-shell spherical nanoparticle.");
349 painCave.isFatal = 0;
350 painCave.severity = OPENMD_INFO;
353 RealType smallestSoFar;
354 int myComponent = -1;
356 nMol.resize(nComponents);
358 for (
unsigned int i = 0; i < sites.size(); i++) {
361 smallestSoFar = particleRadius;
363 for (
int j = 0; j < nComponents; j++) {
364 if (myR <= shellRadii[j]) {
365 if (shellRadii[j] <= smallestSoFar) {
366 smallestSoFar = shellRadii[j];
371 componentFromSite[i] = myComponent;
380 createMdFile(inputFileName, outputFileName, nMol);
389 SimInfo::MoleculeIterator mi;
394 for (
int i = 0; i < nComponents; i++) {
399 for (
unsigned int n = 0; n < sites.size(); n++) {
401 if (componentFromSite[n] == i) {
403 locator->placeMol(sites[n], orientations[n], mol);
409 for (
int n = 0; n < nMol.at(i); n++) {
411 locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
418 hmat(0, 0) = 10.0 * particleRadius;
423 hmat(1, 1) = 10.0 * particleRadius;
428 hmat(2, 2) = 10.0 * particleRadius;
434 writer =
new DumpWriter(NewInfo, outputFileName);
436 if (writer == NULL) {
437 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
438 "Error in creating dumpwriter object ");
439 painCave.isFatal = 1;
450 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
451 "A new OpenMD file called \"%s\" has been "
453 outputFileName.c_str());
454 painCave.isFatal = 0;
455 painCave.severity = OPENMD_INFO;
460void createMdFile(
const std::string& oldMdFileName,
461 const std::string& newMdFileName, std::vector<int> nMol) {
464 const int MAXLEN = 65535;
468 oldMdFile.open(oldMdFileName.c_str());
469 newMdFile.open(newMdFileName.c_str());
470 oldMdFile.getline(buffer, MAXLEN);
473 while (!oldMdFile.eof()) {
475 if (strstr(buffer,
"nMol") != NULL) {
476 if (i < nMol.size()) {
477 snprintf(buffer, MAXLEN,
"\tnMol = %i;", nMol.at(i));
478 newMdFile << buffer << std::endl;
482 newMdFile << buffer << std::endl;
484 oldMdFile.getline(buffer, MAXLEN);
490 if (i != nMol.size()) {
491 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
492 "Couldn't replace the correct number of nMol\n"
493 "\tstatements in component blocks. Make sure that all\n"
494 "\tcomponents in the template file have nMol=1");
495 painCave.isFatal = 1;
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()
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.