ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/nanoparticleBuilder/nanorod_pentBuilder.cpp
Revision: 1879
Committed: Sun Jun 16 15:15:42 2013 UTC (12 years, 1 month ago) by gezelter
File size: 18339 byte(s)
Log Message:
MERGE OpenMD development 1783:1878 into trunk

File Contents

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