ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/applications/nanoparticleBuilder/nanorodBuilder.cpp
Revision: 1725
Committed: Sat May 26 18:13:43 2012 UTC (12 years, 11 months ago) by gezelter
File size: 15974 byte(s)
Log Message:
Individual ForceField classes have been removed (they were essentially
all duplicates anyway).  

ForceField has moved to brains, and since only one force field is in
play at any time, the ForceFieldFactory and Register methods have been
removed.  


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, 24107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 * Created by Kelsey M. Stocker on 2/9/12.
42 * @author Kelsey M. Stocker
43 *
44 */
45
46 #include <cstdlib>
47 #include <cstdio>
48 #include <cstring>
49 #include <cmath>
50 #include <iostream>
51 #include <string>
52 #include <map>
53 #include <fstream>
54 #include <algorithm>
55
56 #include "config.h"
57 #include "shapedLatticeRod.hpp"
58 #include "nanorodBuilderCmd.h"
59 #include "lattice/LatticeFactory.hpp"
60 #include "utils/MoLocator.hpp"
61 #include "lattice/Lattice.hpp"
62 #include "brains/Register.hpp"
63 #include "brains/SimInfo.hpp"
64 #include "brains/SimCreator.hpp"
65 #include "io/DumpWriter.hpp"
66 #include "math/Vector3.hpp"
67 #include "math/SquareMatrix3.hpp"
68 #include "utils/StringUtils.hpp"
69
70 using namespace std;
71 using namespace OpenMD;
72 void createMdFile(const std::string&oldMdFileName,
73 const std::string&newMdFileName,
74 std::vector<int> numMol);
75
76 int main(int argc, char *argv []) {
77
78 registerLattice();
79
80 gengetopt_args_info args_info;
81 std::string latticeType;
82 std::string inputFileName;
83 std::string outputFileName;
84
85 MoLocator* locator;
86 int nComponents;
87 double latticeConstant;
88 std::vector<double> lc;
89
90 RealType rodRadius;
91 RealType rodLength;
92
93 Mat3x3d hmat;
94 std::vector<Vector3d> latticePos;
95 std::vector<Vector3d> latticeOrt;
96
97 DumpWriter *writer;
98
99 // Parse Command Line Arguments
100 if (cmdline_parser(argc, argv, &args_info) != 0)
101 exit(1);
102
103 /* get lattice type */
104 latticeType = "FCC";
105
106 /* get input file name */
107 if (args_info.inputs_num)
108 inputFileName = args_info.inputs[0];
109 else {
110 sprintf(painCave.errMsg, "No input .md file name was specified "
111 "on the command line");
112 painCave.isFatal = 1;
113 cmdline_parser_print_help();
114 simError();
115 }
116
117 /* parse md file and set up the system */
118 SimCreator oldCreator;
119 SimInfo* oldInfo = oldCreator.createSim(inputFileName, false);
120
121 latticeConstant = args_info.latticeConstant_arg;
122 rodRadius = args_info.radius_arg;
123 rodLength = args_info.length_arg;
124 Globals* simParams = oldInfo->getSimParams();
125
126 /* Create nanorod */
127 shapedLatticeRod nanoRod(latticeConstant, latticeType,
128 rodRadius, rodLength);
129
130 /* Build a lattice and get lattice points for this lattice constant */
131 vector<Vector3d> sites = nanoRod.getSites();
132 vector<Vector3d> orientations = nanoRod.getOrientations();
133 std::vector<int> vacancyTargets;
134 vector<bool> isVacancy;
135
136 Vector3d myLoc;
137 RealType myR;
138
139 for (int i = 0; i < sites.size(); i++)
140 isVacancy.push_back(false);
141
142 // cerr << "checking vacancyPercent" << "\n";
143 if (args_info.vacancyPercent_given) {
144 // cerr << "vacancyPercent given" << "\n";
145 if (args_info.vacancyPercent_arg < 0.0 || args_info.vacancyPercent_arg > 100.0) {
146 sprintf(painCave.errMsg, "vacancyPercent was set to a non-sensical value.");
147 painCave.isFatal = 1;
148 simError();
149 } else {
150 RealType vF = args_info.vacancyPercent_arg / 100.0;
151 // cerr << "vacancyPercent = " << vF << "\n";
152 RealType vIR;
153 RealType vOR;
154 if (args_info.vacancyInnerRadius_given) {
155 vIR = args_info.vacancyInnerRadius_arg;
156 } else {
157 vIR = 0.0;
158 }
159 if (args_info.vacancyOuterRadius_given) {
160 vOR = args_info.vacancyOuterRadius_arg;
161 } else {
162 vOR = rodRadius;
163 }
164 if (vIR >= 0.0 && vOR <= rodRadius && vOR >= vIR) {
165
166 for (int i = 0; i < sites.size(); i++) {
167 myLoc = sites[i];
168 myR = myLoc.length();
169 if (myR >= vIR && myR <= vOR) {
170 vacancyTargets.push_back(i);
171 }
172 }
173 std::random_shuffle(vacancyTargets.begin(), vacancyTargets.end());
174
175 int nTargets = vacancyTargets.size();
176 vacancyTargets.resize((int)(vF * nTargets));
177
178
179 sprintf(painCave.errMsg, "Removing %d atoms from randomly-selected\n"
180 "\tsites between %lf and %lf.", (int) vacancyTargets.size(),
181 vIR, vOR);
182 painCave.isFatal = 0;
183 simError();
184
185 isVacancy.clear();
186 for (int i = 0; i < sites.size(); i++) {
187 bool vac = false;
188 for (int j = 0; j < vacancyTargets.size(); j++) {
189 if (i == vacancyTargets[j]) vac = true;
190 }
191 isVacancy.push_back(vac);
192 }
193
194 } else {
195 sprintf(painCave.errMsg, "Something is strange about the vacancy\n"
196 "\tinner or outer radii. Check their values.");
197 painCave.isFatal = 1;
198 simError();
199 }
200 }
201 }
202
203 /* Get number of lattice sites */
204 int nSites = sites.size() - vacancyTargets.size();
205
206 // cerr << "sites.size() = " << sites.size() << "\n";
207 // cerr << "nSites = " << nSites << "\n";
208 // cerr << "vacancyTargets = " << vacancyTargets.size() << "\n";
209
210 std::vector<Component*> components = simParams->getComponents();
211 std::vector<RealType> molFractions;
212 std::vector<RealType> shellRadii;
213 std::vector<RealType> molecularMasses;
214 std::vector<int> nMol;
215 std::map<int, int> componentFromSite;
216 nComponents = components.size();
217 // cerr << "nComponents = " << nComponents << "\n";
218
219 if (args_info.molFraction_given && args_info.shellRadius_given) {
220 sprintf(painCave.errMsg, "Specify either molFraction or shellRadius "
221 "arguments, but not both!");
222 painCave.isFatal = 1;
223 simError();
224 }
225
226 if (nComponents == 1) {
227 molFractions.push_back(1.0);
228 shellRadii.push_back(rodRadius);
229 } else if (args_info.molFraction_given) {
230 if ((int)args_info.molFraction_given == nComponents) {
231 for (int i = 0; i < nComponents; i++) {
232 molFractions.push_back(args_info.molFraction_arg[i]);
233 }
234 } else if ((int)args_info.molFraction_given == nComponents-1) {
235 RealType remainingFraction = 1.0;
236 for (int i = 0; i < nComponents-1; i++) {
237 molFractions.push_back(args_info.molFraction_arg[i]);
238 remainingFraction -= molFractions[i];
239 }
240 molFractions.push_back(remainingFraction);
241 } else {
242 sprintf(painCave.errMsg, "nanorodBuilder can't figure out molFractions "
243 "for all of the components in the <MetaData> block.");
244 painCave.isFatal = 1;
245 simError();
246 }
247 } else if ((int)args_info.shellRadius_given) {
248 if ((int)args_info.shellRadius_given == nComponents) {
249 for (int i = 0; i < nComponents; i++) {
250 shellRadii.push_back(args_info.shellRadius_arg[i]);
251 }
252 } else if ((int)args_info.shellRadius_given == nComponents-1) {
253 for (int i = 0; i < nComponents-1; i++) {
254 shellRadii.push_back(args_info.shellRadius_arg[i]);
255 }
256 shellRadii.push_back(rodRadius);
257 } else {
258 sprintf(painCave.errMsg, "nanorodBuilder can't figure out the\n"
259 "\tshell radii for all of the components in the <MetaData> block.");
260 painCave.isFatal = 1;
261 simError();
262 }
263 } else {
264 sprintf(painCave.errMsg, "You have a multi-component <MetaData> block,\n"
265 "\tbut have not specified either molFraction or shellRadius arguments.");
266 painCave.isFatal = 1;
267 simError();
268 }
269
270 if (args_info.molFraction_given) {
271 RealType totalFraction = 0.0;
272
273 /* Do some simple sanity checking*/
274
275 for (int i = 0; i < nComponents; i++) {
276 if (molFractions.at(i) < 0.0) {
277 sprintf(painCave.errMsg, "One of the requested molFractions was"
278 " less than zero!");
279 painCave.isFatal = 1;
280 simError();
281 }
282 if (molFractions.at(i) > 1.0) {
283 sprintf(painCave.errMsg, "One of the requested molFractions was"
284 " greater than one!");
285 painCave.isFatal = 1;
286 simError();
287 }
288 totalFraction += molFractions.at(i);
289 }
290 if (abs(totalFraction - 1.0) > 1e-6) {
291 sprintf(painCave.errMsg, "The sum of molFractions was not close enough to 1.0");
292 painCave.isFatal = 1;
293 simError();
294 }
295
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);
300 }
301 nMol.push_back(remaining);
302
303 // recompute actual mol fractions and perform final sanity check:
304
305 int totalMolecules = 0;
306 for (int i=0; i < nComponents; i++) {
307 molFractions[i] = (RealType)(nMol.at(i))/(RealType)nSites;
308 totalMolecules += nMol.at(i);
309 }
310 if (totalMolecules != nSites) {
311 sprintf(painCave.errMsg, "Computed total number of molecules is not equal "
312 "to the number of lattice sites!");
313 painCave.isFatal = 1;
314 simError();
315 }
316 } else {
317
318 for (int i = 0; i < shellRadii.size(); i++) {
319 if (shellRadii.at(i) > rodRadius + 1e-6 ) {
320 sprintf(painCave.errMsg, "One of the shellRadius values exceeds the rod Radius.");
321 painCave.isFatal = 1;
322 simError();
323 }
324 if (shellRadii.at(i) <= 0.0 ) {
325 sprintf(painCave.errMsg, "One of the shellRadius values is smaller than zero!");
326 painCave.isFatal = 1;
327 simError();
328 }
329 }
330 }
331
332 vector<int> ids;
333 if ((int)args_info.molFraction_given){
334 // cerr << "molFraction given 2" << "\n";
335 sprintf(painCave.errMsg, "Creating a randomized spherically-capped nanorod.");
336 painCave.isFatal = 0;
337 simError();
338 /* Random rod is the default case*/
339
340 for (int i = 0; i < sites.size(); i++)
341 if (!isVacancy[i]) ids.push_back(i);
342
343 std::random_shuffle(ids.begin(), ids.end());
344
345 } else{
346 sprintf(painCave.errMsg, "Creating an fcc nanorod.");
347 painCave.isFatal = 0;
348 simError();
349
350 RealType smallestSoFar;
351 int myComponent = -1;
352 nMol.clear();
353 nMol.resize(nComponents);
354
355 // cerr << "shellRadii[0] " << shellRadii[0] << "\n";
356 // cerr << "rodRadius " << rodRadius << "\n";
357
358 for (int i = 0; i < sites.size(); i++) {
359 myLoc = sites[i];
360 myR = myLoc.length();
361 smallestSoFar = rodRadius;
362 //cerr << "vac = " << isVacancy[i]<< "\n";
363
364 if (!isVacancy[i]) {
365
366
367 // for (int j = 0; j < nComponents; j++) {
368 // if (myR <= shellRadii[j]) {
369 // if (shellRadii[j] <= smallestSoFar) {
370 // smallestSoFar = shellRadii[j];
371 // myComponent = j;
372 // }
373 // }
374 // }
375 myComponent = 0;
376 componentFromSite[i] = myComponent;
377 nMol[myComponent]++;
378 // cerr << "nMol for myComp(" << myComponent<<") = " << nMol[myComponent] << "\n";
379 }
380 }
381 }
382 // cerr << "nMol = " << nMol.at(0) << "\n";
383
384 outputFileName = args_info.output_arg;
385
386 //creat new .md file on fly which corrects the number of molecule
387
388 createMdFile(inputFileName, outputFileName, nMol);
389
390 if (oldInfo != NULL)
391 delete oldInfo;
392
393 SimCreator newCreator;
394 SimInfo* NewInfo = newCreator.createSim(outputFileName, false);
395
396 // Place molecules
397 Molecule* mol;
398 SimInfo::MoleculeIterator mi;
399 mol = NewInfo->beginMolecule(mi);
400
401 int l = 0;
402 int whichSite = 0;
403
404 for (int i = 0; i < nComponents; i++){
405 locator = new MoLocator(NewInfo->getMoleculeStamp(i),
406 NewInfo->getForceField());
407
408 // cerr << "nMol = " << nMol.at(i) << "\n";
409 if (!args_info.molFraction_given) {
410 for (int n = 0; n < sites.size(); n++) {
411 if (!isVacancy[n]) {
412 if (componentFromSite[n] == i) {
413 mol = NewInfo->getMoleculeByGlobalIndex(l);
414 locator->placeMol(sites[n], orientations[n], mol);
415 l++;
416 }
417 }
418 }
419 } else {
420 for (int n = 0; n < nMol.at(i); n++) {
421 mol = NewInfo->getMoleculeByGlobalIndex(l);
422 locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
423 l++;
424 }
425 }
426 }
427
428 //fill Hmat
429 hmat(0, 0)= 10.0*rodRadius;
430 hmat(0, 1) = 0.0;
431 hmat(0, 2) = 0.0;
432
433 hmat(1, 0) = 0.0;
434 hmat(1, 1) = 10.0*rodRadius;
435 hmat(1, 2) = 0.0;
436
437 hmat(2, 0) = 0.0;
438 hmat(2, 1) = 0.0;
439 hmat(2, 2) = 5.0*rodLength + 2.0*rodRadius;
440
441 //set Hmat
442 NewInfo->getSnapshotManager()->getCurrentSnapshot()->setHmat(hmat);
443
444
445 //create dumpwriter and write out the coordinates
446 writer = new DumpWriter(NewInfo, outputFileName);
447
448 if (writer == NULL) {
449 sprintf(painCave.errMsg, "Error in creating dumpwriter object ");
450 painCave.isFatal = 1;
451 simError();
452 }
453
454 writer->writeDump();
455
456 // deleting the writer will put the closing at the end of the dump file
457
458 delete writer;
459
460 // cleanup a by calling sim error.....
461 sprintf(painCave.errMsg, "A new OpenMD file called \"%s\" has been "
462 "generated.\n", outputFileName.c_str());
463 painCave.isFatal = 0;
464 simError();
465 return 0;
466 }
467
468 void createMdFile(const std::string&oldMdFileName,
469 const std::string&newMdFileName,
470 std::vector<int> nMol) {
471 ifstream oldMdFile;
472 ofstream newMdFile;
473 const int MAXLEN = 65535;
474 char buffer[MAXLEN];
475
476 //create new .md file based on old .md file
477 oldMdFile.open(oldMdFileName.c_str());
478 newMdFile.open(newMdFileName.c_str());
479 oldMdFile.getline(buffer, MAXLEN);
480
481 int i = 0;
482 while (!oldMdFile.eof()) {
483
484 //correct molecule number
485 if (strstr(buffer, "nMol") != NULL) {
486 if(i<nMol.size()){
487 sprintf(buffer, "\tnMol = %i;", nMol.at(i));
488 newMdFile << buffer << std::endl;
489 i++;
490 }
491 } else
492 newMdFile << buffer << std::endl;
493
494 oldMdFile.getline(buffer, MAXLEN);
495 }
496
497 oldMdFile.close();
498 newMdFile.close();
499
500 if (i != nMol.size()) {
501 sprintf(painCave.errMsg, "Couldn't replace the correct number of nMol\n"
502 "\tstatements in component blocks. Make sure that all\n"
503 "\tcomponents in the template file have nMol=1");
504 painCave.isFatal = 1;
505 simError();
506 }
507
508 }
509