ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/nanoparticleBuilder/nanorod_pentBuilder.cpp
Revision: 1977
Committed: Wed Mar 12 21:35:23 2014 UTC (11 years, 1 month ago) by gezelter
File size: 18434 byte(s)
Log Message:
Removed some scary errors that are really supposed to be OPENMD_INFO messages

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