ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/nanoparticleBuilder/nanoparticleBuilder.cpp
Revision: 2071
Committed: Sat Mar 7 21:41:51 2015 UTC (10 years, 1 month ago) by gezelter
File size: 15278 byte(s)
Log Message:
Reducing the number of warnings when using g++ to compile.

File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This software is provided "AS IS," without a warranty of any
18 * kind. All express or implied conditions, representations and
19 * warranties, including any implied warranty of merchantability,
20 * fitness for a particular purpose or non-infringement, are hereby
21 * excluded. The University of Notre Dame and its licensors shall not
22 * be liable for any damages suffered by licensee as a result of
23 * using, modifying or distributing the software or its
24 * derivatives. In no event will the University of Notre Dame or its
25 * licensors be liable for any lost revenue, profit or data, or for
26 * direct, indirect, special, consequential, incidental or punitive
27 * damages, however caused and regardless of the theory of liability,
28 * arising out of the use of or inability to use software, even if the
29 * University of Notre Dame has been advised of the possibility of
30 * such damages.
31 *
32 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33 * research, please cite the appropriate papers when you publish your
34 * work. Good starting points are:
35 *
36 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43 #include <cstdlib>
44 #include <cstdio>
45 #include <cstring>
46 #include <cmath>
47 #include <iostream>
48 #include <string>
49 #include <map>
50 #include <fstream>
51 #include <algorithm>
52
53 #include "config.h"
54 #include "shapedLatticeSpherical.hpp"
55 #include "nanoparticleBuilderCmd.h"
56 #include "lattice/LatticeFactory.hpp"
57 #include "utils/MoLocator.hpp"
58 #include "lattice/Lattice.hpp"
59 #include "brains/Register.hpp"
60 #include "brains/SimInfo.hpp"
61 #include "brains/SimCreator.hpp"
62 #include "io/DumpWriter.hpp"
63 #include "math/Vector3.hpp"
64 #include "math/SquareMatrix3.hpp"
65 #include "utils/StringUtils.hpp"
66
67 using namespace std;
68 using namespace OpenMD;
69 void createMdFile(const std::string&oldMdFileName,
70 const std::string&newMdFileName,
71 std::vector<int> numMol);
72
73 int main(int argc, char *argv []) {
74
75 registerLattice();
76
77 gengetopt_args_info args_info;
78 std::string latticeType;
79 std::string inputFileName;
80 std::string outputFileName;
81 MoLocator* locator;
82 int nComponents;
83 double latticeConstant;
84 RealType particleRadius;
85 Mat3x3d hmat;
86 DumpWriter *writer;
87
88 // Parse Command Line Arguments
89 if (cmdline_parser(argc, argv, &args_info) != 0)
90 exit(1);
91
92 /* get lattice type */
93 latticeType = "FCC";
94
95 /* get input file name */
96 if (args_info.inputs_num)
97 inputFileName = args_info.inputs[0];
98 else {
99 sprintf(painCave.errMsg, "No input .md file name was specified "
100 "on the command line");
101 painCave.isFatal = 1;
102 cmdline_parser_print_help();
103 simError();
104 }
105
106 /* parse md file and set up the system */
107 SimCreator oldCreator;
108 SimInfo* oldInfo = oldCreator.createSim(inputFileName, false);
109
110 latticeConstant = args_info.latticeConstant_arg;
111 particleRadius = args_info.radius_arg;
112 Globals* simParams = oldInfo->getSimParams();
113
114 /* Create nanoparticle */
115 shapedLatticeSpherical nanoParticle(latticeConstant, latticeType,
116 particleRadius);
117
118 /* Build a lattice and get lattice points for this lattice constant */
119 vector<Vector3d> sites = nanoParticle.getSites();
120 vector<Vector3d> orientations = nanoParticle.getOrientations();
121
122
123 std::vector<std::size_t> vacancyTargets;
124 vector<bool> isVacancy;
125
126 Vector3d myLoc;
127 RealType myR;
128
129 for (unsigned int i = 0; i < sites.size(); i++)
130 isVacancy.push_back(false);
131
132 if (args_info.vacancyPercent_given) {
133 if (args_info.vacancyPercent_arg < 0.0 || args_info.vacancyPercent_arg > 100.0) {
134 sprintf(painCave.errMsg,
135 "vacancyPercent was set to a non-sensical value.");
136 painCave.isFatal = 1;
137 simError();
138 } else {
139 RealType vF = args_info.vacancyPercent_arg / 100.0;
140 RealType vIR;
141 RealType vOR;
142 if (args_info.vacancyInnerRadius_given) {
143 vIR = args_info.vacancyInnerRadius_arg;
144 } else {
145 vIR = 0.0;
146 }
147 if (args_info.vacancyOuterRadius_given) {
148 vOR = args_info.vacancyOuterRadius_arg;
149 } else {
150 vOR = particleRadius;
151 }
152 if (vIR >= 0.0 && vOR <= particleRadius && vOR >= vIR) {
153
154 for (std::size_t i = 0; i < sites.size(); i++) {
155 myLoc = sites[i];
156 myR = myLoc.length();
157 if (myR >= vIR && myR <= vOR) {
158 vacancyTargets.push_back(i);
159 }
160 }
161 std::random_shuffle(vacancyTargets.begin(), vacancyTargets.end());
162
163 int nTargets = vacancyTargets.size();
164 vacancyTargets.resize((int)(vF * nTargets));
165
166
167 sprintf(painCave.errMsg, "Removing %d atoms from randomly-selected\n"
168 "\tsites between %lf and %lf.", (int) vacancyTargets.size(),
169 vIR, vOR);
170 painCave.isFatal = 0;
171 painCave.severity = OPENMD_INFO;
172 simError();
173
174 isVacancy.clear();
175 for (std::size_t i = 0; i < sites.size(); i++) {
176 bool vac = false;
177 for (std::size_t j = 0; j < vacancyTargets.size(); j++) {
178 if (i == vacancyTargets[j]) vac = true;
179 }
180 isVacancy.push_back(vac);
181 }
182
183 } else {
184 sprintf(painCave.errMsg, "Something is strange about the vacancy\n"
185 "\tinner or outer radii. Check their values.");
186 painCave.isFatal = 1;
187 simError();
188 }
189 }
190 }
191
192 /* Get number of lattice sites */
193 std::size_t nSites = sites.size() - vacancyTargets.size();
194
195 std::vector<Component*> components = simParams->getComponents();
196 std::vector<RealType> molFractions;
197 std::vector<RealType> shellRadii;
198 std::vector<int> nMol;
199 std::map<int, int> componentFromSite;
200 nComponents = components.size();
201
202 if (args_info.molFraction_given && args_info.shellRadius_given) {
203 sprintf(painCave.errMsg, "Specify either molFraction or shellRadius "
204 "arguments, but not both!");
205 painCave.isFatal = 1;
206 simError();
207 }
208
209 if (nComponents == 1) {
210 molFractions.push_back(1.0);
211 shellRadii.push_back(particleRadius);
212 } else if (args_info.molFraction_given) {
213 if ((int)args_info.molFraction_given == nComponents) {
214 for (int i = 0; i < nComponents; i++) {
215 molFractions.push_back(args_info.molFraction_arg[i]);
216 }
217 } else if ((int)args_info.molFraction_given == nComponents-1) {
218 RealType remainingFraction = 1.0;
219 for (int i = 0; i < nComponents-1; i++) {
220 molFractions.push_back(args_info.molFraction_arg[i]);
221 remainingFraction -= molFractions[i];
222 }
223 molFractions.push_back(remainingFraction);
224 } else {
225 sprintf(painCave.errMsg, "nanoparticleBuilder can't figure out molFractions "
226 "for all of the components in the <MetaData> block.");
227 painCave.isFatal = 1;
228 simError();
229 }
230 } else if ((int)args_info.shellRadius_given) {
231 if ((int)args_info.shellRadius_given == nComponents) {
232 for (int i = 0; i < nComponents; i++) {
233 shellRadii.push_back(args_info.shellRadius_arg[i]);
234 }
235 } else if ((int)args_info.shellRadius_given == nComponents-1) {
236 for (int i = 0; i < nComponents-1; i++) {
237 shellRadii.push_back(args_info.shellRadius_arg[i]);
238 }
239 shellRadii.push_back(particleRadius);
240 } else {
241 sprintf(painCave.errMsg, "nanoparticleBuilder can't figure out the\n"
242 "\tshell radii for all of the components in the <MetaData> block.");
243 painCave.isFatal = 1;
244 simError();
245 }
246 } else {
247 sprintf(painCave.errMsg, "You have a multi-component <MetaData> block,\n"
248 "\tbut have not specified either molFraction or shellRadius arguments.");
249 painCave.isFatal = 1;
250 simError();
251 }
252
253 if (args_info.molFraction_given) {
254 RealType totalFraction = 0.0;
255
256 /* Do some simple sanity checking*/
257
258 for (int i = 0; i < nComponents; i++) {
259 if (molFractions.at(i) < 0.0) {
260 sprintf(painCave.errMsg, "One of the requested molFractions was"
261 " less than zero!");
262 painCave.isFatal = 1;
263 simError();
264 }
265 if (molFractions.at(i) > 1.0) {
266 sprintf(painCave.errMsg, "One of the requested molFractions was"
267 " greater than one!");
268 painCave.isFatal = 1;
269 simError();
270 }
271 totalFraction += molFractions.at(i);
272 }
273 if (abs(totalFraction - 1.0) > 1e-6) {
274 sprintf(painCave.errMsg,
275 "The sum of molFractions was not close enough to 1.0");
276 painCave.isFatal = 1;
277 simError();
278 }
279
280 int remaining = nSites;
281 for (int i=0; i < nComponents-1; i++) {
282 nMol.push_back(int((RealType)nSites * molFractions.at(i)));
283 remaining -= nMol.at(i);
284 }
285 nMol.push_back(remaining);
286
287 // recompute actual mol fractions and perform final sanity check:
288
289 std::size_t totalMolecules = 0;
290 for (int i=0; i < nComponents; i++) {
291 molFractions[i] = (RealType)(nMol.at(i))/(RealType)nSites;
292 totalMolecules += nMol.at(i);
293 }
294
295 if (totalMolecules != nSites) {
296 sprintf(painCave.errMsg,
297 "Computed total number of molecules is not equal "
298 "to the number of lattice sites!");
299 painCave.isFatal = 1;
300 simError();
301 }
302 } else {
303
304 for (unsigned int i = 0; i < shellRadii.size(); i++) {
305 if (shellRadii.at(i) > particleRadius + 1e-6 ) {
306 sprintf(painCave.errMsg,
307 "One of the shellRadius values exceeds the particle Radius.");
308 painCave.isFatal = 1;
309 simError();
310 }
311 if (shellRadii.at(i) <= 0.0 ) {
312 sprintf(painCave.errMsg,
313 "One of the shellRadius values is smaller than zero!");
314 painCave.isFatal = 1;
315 simError();
316 }
317 }
318 }
319
320 vector<int> ids;
321 if ((int)args_info.molFraction_given){
322 sprintf(painCave.errMsg, "Creating a randomized spherical nanoparticle.");
323 painCave.isFatal = 0;
324 painCave.severity = OPENMD_INFO;
325 simError();
326 /* Random particle is the default case*/
327
328 for (unsigned int i = 0; i < sites.size(); i++)
329 if (!isVacancy[i]) ids.push_back(i);
330
331 std::random_shuffle(ids.begin(), ids.end());
332
333 } else{
334 sprintf(painCave.errMsg, "Creating a core-shell spherical nanoparticle.");
335 painCave.isFatal = 0;
336 painCave.severity = OPENMD_INFO;
337 simError();
338
339 RealType smallestSoFar;
340 int myComponent = -1;
341 nMol.clear();
342 nMol.resize(nComponents);
343
344 for (unsigned int i = 0; i < sites.size(); i++) {
345 myLoc = sites[i];
346 myR = myLoc.length();
347 smallestSoFar = particleRadius;
348 if (!isVacancy[i]) {
349 for (int j = 0; j < nComponents; j++) {
350 if (myR <= shellRadii[j]) {
351 if (shellRadii[j] <= smallestSoFar) {
352 smallestSoFar = shellRadii[j];
353 myComponent = j;
354 }
355 }
356 }
357 componentFromSite[i] = myComponent;
358 nMol[myComponent]++;
359 }
360 }
361 }
362
363 outputFileName = args_info.output_arg;
364
365 //creat new .md file on fly which corrects the number of molecule
366 createMdFile(inputFileName, outputFileName, nMol);
367
368 delete oldInfo;
369
370 SimCreator newCreator;
371 SimInfo* NewInfo = newCreator.createSim(outputFileName, false);
372
373 // Place molecules
374 Molecule* mol;
375 SimInfo::MoleculeIterator mi;
376 mol = NewInfo->beginMolecule(mi);
377
378 int l = 0;
379
380 for (int i = 0; i < nComponents; i++){
381 locator = new MoLocator(NewInfo->getMoleculeStamp(i),
382 NewInfo->getForceField());
383
384 if (!args_info.molFraction_given) {
385 for (unsigned int n = 0; n < sites.size(); n++) {
386 if (!isVacancy[n]) {
387 if (componentFromSite[n] == i) {
388 mol = NewInfo->getMoleculeByGlobalIndex(l);
389 locator->placeMol(sites[n], orientations[n], mol);
390 l++;
391 }
392 }
393 }
394 } else {
395 for (int n = 0; n < nMol.at(i); n++) {
396 mol = NewInfo->getMoleculeByGlobalIndex(l);
397 locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
398 l++;
399 }
400 }
401 }
402
403 //fill Hmat
404 hmat(0, 0)= 10.0*particleRadius;
405 hmat(0, 1) = 0.0;
406 hmat(0, 2) = 0.0;
407
408 hmat(1, 0) = 0.0;
409 hmat(1, 1) = 10.0*particleRadius;
410 hmat(1, 2) = 0.0;
411
412 hmat(2, 0) = 0.0;
413 hmat(2, 1) = 0.0;
414 hmat(2, 2) = 10.0*particleRadius;
415
416 //set Hmat
417 NewInfo->getSnapshotManager()->getCurrentSnapshot()->setHmat(hmat);
418
419
420 //create dumpwriter and write out the coordinates
421 writer = new DumpWriter(NewInfo, outputFileName);
422
423 if (writer == NULL) {
424 sprintf(painCave.errMsg, "Error in creating dumpwriter object ");
425 painCave.isFatal = 1;
426 simError();
427 }
428
429 writer->writeDump();
430
431 // deleting the writer will put the closing at the end of the dump file
432
433 delete writer;
434
435 // cleanup a by calling sim error.....
436 sprintf(painCave.errMsg, "A new OpenMD file called \"%s\" has been "
437 "generated.\n", outputFileName.c_str());
438 painCave.isFatal = 0;
439 painCave.severity = OPENMD_INFO;
440 simError();
441 return 0;
442 }
443
444 void createMdFile(const std::string&oldMdFileName,
445 const std::string&newMdFileName,
446 std::vector<int> nMol) {
447 ifstream oldMdFile;
448 ofstream newMdFile;
449 const int MAXLEN = 65535;
450 char buffer[MAXLEN];
451
452 //create new .md file based on old .md file
453 oldMdFile.open(oldMdFileName.c_str());
454 newMdFile.open(newMdFileName.c_str());
455 oldMdFile.getline(buffer, MAXLEN);
456
457 unsigned int i = 0;
458 while (!oldMdFile.eof()) {
459
460 //correct molecule number
461 if (strstr(buffer, "nMol") != NULL) {
462 if(i<nMol.size()){
463 sprintf(buffer, "\tnMol = %i;", nMol.at(i));
464 newMdFile << buffer << std::endl;
465 i++;
466 }
467 } else
468 newMdFile << buffer << std::endl;
469
470 oldMdFile.getline(buffer, MAXLEN);
471 }
472
473 oldMdFile.close();
474 newMdFile.close();
475
476 if (i != nMol.size()) {
477 sprintf(painCave.errMsg, "Couldn't replace the correct number of nMol\n"
478 "\tstatements in component blocks. Make sure that all\n"
479 "\tcomponents in the template file have nMol=1");
480 painCave.isFatal = 1;
481 simError();
482 }
483
484 }
485

Properties

Name Value
svn:keywords Author Id Revision Date