ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/nanoparticleBuilder/nanorod_pentBuilder.cpp
Revision: 1796
Committed: Mon Sep 10 18:38:44 2012 UTC (12 years, 7 months ago) by gezelter
File size: 18426 byte(s)
Log Message:
Updating MPI calls to C++, fixing a DumpWriter bug, cleaning cruft

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