ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/applications/nanoparticleBuilder/nanoparticleBuilder.cpp
Revision: 3051
Committed: Tue Oct 17 17:51:52 2006 UTC (17 years, 11 months ago) by gezelter
File size: 12651 byte(s)
Log Message:
bug fixes

File Contents

# User Rev Content
1 chuckv 2352 /*
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. Acknowledgement of the program authors must be made in any
10     * publication of scientific results based in part on use of the
11     * program. An acceptable form of acknowledgement is citation of
12     * the article in which the program was described (Matthew
13     * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14     * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15     * Parallel Simulation Engine for Molecular Dynamics,"
16     * J. Comput. Chem. 26, pp. 252-271 (2005))
17     *
18     * 2. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 3. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in the
23     * documentation and/or other materials provided with the
24     * distribution.
25     *
26     * This software is provided "AS IS," without a warranty of any
27     * kind. All express or implied conditions, representations and
28     * warranties, including any implied warranty of merchantability,
29     * fitness for a particular purpose or non-infringement, are hereby
30     * excluded. The University of Notre Dame and its licensors shall not
31     * be liable for any damages suffered by licensee as a result of
32     * using, modifying or distributing the software or its
33     * derivatives. In no event will the University of Notre Dame or its
34     * licensors be liable for any lost revenue, profit or data, or for
35     * direct, indirect, special, consequential, incidental or punitive
36     * damages, however caused and regardless of the theory of liability,
37     * arising out of the use of or inability to use software, even if the
38     * University of Notre Dame has been advised of the possibility of
39     * such damages.
40     */
41    
42     #include <cstdlib>
43     #include <cstdio>
44     #include <cstring>
45     #include <cmath>
46     #include <iostream>
47     #include <string>
48     #include <map>
49     #include <fstream>
50 chuckv 2657 #include <algorithm>
51 chuckv 2352
52     #include "config.h"
53 chuckv 2657 #include "shapedLatticeSpherical.hpp"
54 chuckv 2352 #include "nanoparticleBuilderCmd.h"
55     #include "lattice/LatticeFactory.hpp"
56     #include "utils/MoLocator.hpp"
57     #include "lattice/Lattice.hpp"
58     #include "brains/Register.hpp"
59     #include "brains/SimInfo.hpp"
60     #include "brains/SimCreator.hpp"
61     #include "io/DumpWriter.hpp"
62     #include "math/Vector3.hpp"
63     #include "math/SquareMatrix3.hpp"
64     #include "utils/StringUtils.hpp"
65    
66     using namespace std;
67     using namespace oopse;
68     void createMdFile(const std::string&oldMdFileName,
69     const std::string&newMdFileName,
70 chuckv 3044 std::vector<int> numMol);
71 chuckv 2352
72     int main(int argc, char *argv []) {
73    
74     //register force fields
75     registerForceFields();
76     registerLattice();
77    
78     gengetopt_args_info args_info;
79     std::string latticeType;
80     std::string inputFileName;
81 chuckv 3044 std::string outputFileName;
82 chuckv 2352
83 chuckv 2657 MoLocator* locator;
84     int nComponents;
85 chuckv 2352 double latticeConstant;
86     std::vector<double> lc;
87 gezelter 3051
88 chuckv 2657 double particleRadius;
89 chuckv 2352
90     Mat3x3d hmat;
91     std::vector<Vector3d> latticePos;
92     std::vector<Vector3d> latticeOrt;
93 chuckv 3044
94 chuckv 2352 DumpWriter *writer;
95    
96 chuckv 2574 // Parse Command Line Arguments
97 chuckv 2352 if (cmdline_parser(argc, argv, &args_info) != 0)
98     exit(1);
99 gezelter 3046
100 chuckv 2352 /* get lattice type */
101 chuckv 3044 latticeType = "FCC";
102    
103 chuckv 2352 /* get input file name */
104     if (args_info.inputs_num)
105     inputFileName = args_info.inputs[0];
106     else {
107 gezelter 3051 sprintf(painCave.errMsg, "No input .md file name was specified"
108     "on the command line");
109 chuckv 3044 painCave.isFatal = 1;
110 chuckv 2352 cmdline_parser_print_help();
111 chuckv 3044 simError();
112 chuckv 2352 }
113    
114     /* parse md file and set up the system */
115     SimCreator oldCreator;
116     SimInfo* oldInfo = oldCreator.createSim(inputFileName, false);
117    
118     latticeConstant = args_info.latticeCnst_arg;
119     particleRadius = args_info.radius_arg;
120 chuckv 2657 Globals* simParams = oldInfo->getSimParams();
121 chuckv 2352
122 chuckv 2657 /* Create nanoparticle */
123 gezelter 3046 shapedLatticeSpherical nanoParticle(latticeConstant, latticeType,
124     particleRadius);
125 chuckv 2672
126 chuckv 2657 /* Build a lattice and get lattice points for this lattice constant */
127 gezelter 3046 vector<Vector3d> sites = nanoParticle.getSites();
128     vector<Vector3d> orientations = nanoParticle.getOrientations();
129 chuckv 3044
130     std::cout <<"nSites: " << sites.size() << std::endl;
131    
132 chuckv 2657 /* Get number of lattice sites */
133 chuckv 3044 int nSites = sites.size();
134    
135     std::vector<Component*> components = simParams->getComponents();
136     std::vector<RealType> molFractions;
137 gezelter 3051 std::vector<RealType> shellRadii;
138 chuckv 3044 std::vector<RealType> molecularMasses;
139     std::vector<int> nMol;
140 gezelter 3051 std::map<int, int> componentFromSite;
141 chuckv 3044 nComponents = components.size();
142    
143 gezelter 3051 if (args_info.molFraction_given && args_info.ShellRadius_given) {
144     sprintf(painCave.errMsg, "Specify either molFraction or ShellRadius "
145     "arguments, but not both!");
146     painCave.isFatal = 1;
147     simError();
148     }
149    
150     if (nComponents == 1) {
151 chuckv 3044 molFractions.push_back(1.0);
152 gezelter 3051 shellRadii.push_back(particleRadius);
153     } else if (args_info.molFraction_given) {
154     if ((int)args_info.molFraction_given == nComponents) {
155     for (int i = 0; i < nComponents; i++) {
156     molFractions.push_back(args_info.molFraction_arg[i]);
157     }
158     } else if ((int)args_info.molFraction_given == nComponents-1) {
159     RealType remainingFraction = 1.0;
160     for (int i = 0; i < nComponents-1; i++) {
161     molFractions.push_back(args_info.molFraction_arg[i]);
162     remainingFraction -= molFractions[i];
163     }
164     molFractions.push_back(remainingFraction);
165     } else {
166     sprintf(painCave.errMsg, "nanoparticleBuilder can't figure out molFractions "
167     "for all of the components in the <MetaData> block.");
168 chuckv 3044 painCave.isFatal = 1;
169     simError();
170     }
171 gezelter 3051 } else if ((int)args_info.ShellRadius_given) {
172     if ((int)args_info.ShellRadius_given == nComponents) {
173     for (int i = 0; i < nComponents; i++) {
174     shellRadii.push_back(args_info.ShellRadius_arg[i]);
175     }
176     } else if ((int)args_info.ShellRadius_given == nComponents-1) {
177     for (int i = 0; i < nComponents-1; i++) {
178     shellRadii.push_back(args_info.ShellRadius_arg[i]);
179     }
180     shellRadii.push_back(particleRadius);
181     } else {
182     sprintf(painCave.errMsg, "nanoparticleBuilder can't figure out the shell radii "
183     "for all of the components in the <MetaData> block.");
184 chuckv 3044 painCave.isFatal = 1;
185     simError();
186     }
187 gezelter 3051 } else {
188     sprintf(painCave.errMsg, "You have a multi-component <MetaData> block, but have not "
189     "specified either molFraction or ShellRadius arguments.");
190 chuckv 3044 painCave.isFatal = 1;
191     simError();
192     }
193 gezelter 3051
194     if (args_info.molFraction_given) {
195     RealType totalFraction = 0.0;
196    
197     /* Do some simple sanity checking*/
198    
199     for (int i = 0; i < nComponents; i++) {
200     if (molFractions.at(i) < 0.0) {
201     sprintf(painCave.errMsg, "One of the requested molFractions was"
202     " less than zero!");
203     painCave.isFatal = 1;
204     simError();
205     }
206     if (molFractions.at(i) > 1.0) {
207     sprintf(painCave.errMsg, "One of the requested molFractions was"
208     " greater than one!");
209     painCave.isFatal = 1;
210     simError();
211     }
212     totalFraction += molFractions.at(i);
213     }
214     if (abs(totalFraction - 1.0) > 1e-6) {
215     sprintf(painCave.errMsg, "The sum of molFractions was not close enough to 1.0");
216     painCave.isFatal = 1;
217     simError();
218     }
219    
220     int remaining = nSites;
221     for (int i=0; i < nComponents-1; i++) {
222     nMol.push_back(int((RealType)nSites * molFractions.at(i)));
223     remaining -= nMol.at(i);
224     }
225     nMol.push_back(remaining);
226    
227     // recompute actual mol fractions and perform final sanity check:
228    
229     int totalMolecules = 0;
230     for (int i=0; i < nComponents; i++) {
231     molFractions[i] = (RealType)(nMol.at(i))/(RealType)nSites;
232     totalMolecules += nMol.at(i);
233     }
234    
235     if (totalMolecules != nSites) {
236     sprintf(painCave.errMsg, "Computed total number of molecules is not equal "
237     "to the number of lattice sites!");
238     painCave.isFatal = 1;
239     simError();
240     }
241     } else {
242 chuckv 3044
243 gezelter 3051 for (int i = 0; i < shellRadii.size(); i++) {
244     if (shellRadii.at(i) > particleRadius + 1e-6 ) {
245     sprintf(painCave.errMsg, "One of the shellRadius values exceeds the particle Radius.");
246     painCave.isFatal = 1;
247     simError();
248     }
249     if (shellRadii.at(i) <= 0.0 ) {
250     sprintf(painCave.errMsg, "One of the shellRadius values is smaller than zero!");
251     painCave.isFatal = 1;
252     simError();
253     }
254     }
255 chuckv 3044 }
256 gezelter 3051
257 chuckv 3044 vector<int> ids;
258     for (int i = 0; i < sites.size(); i++) ids.push_back(i);
259 chuckv 2352 /* Random particle is the default case*/
260 gezelter 3051 if ((int)args_info.molFraction_given){
261     sprintf(painCave.errMsg, "Creating a randomized spherical nanoparticle.");
262     painCave.isFatal = 0;
263     simError();
264 chuckv 3044 std::random_shuffle(ids.begin(), ids.end());
265 gezelter 3051 } else{
266     sprintf(painCave.errMsg, "Creating a core-shell spherical nanoparticle.");
267     painCave.isFatal = 0;
268     simError();
269 chuckv 2352
270 gezelter 3051 Vector3d myLoc;
271     RealType myR;
272     RealType smallestSoFar;
273     int myComponent = -1;
274     nMol.clear();
275     nMol.resize(nComponents);
276    
277     for (int i = 0; i < sites.size(); i++) {
278     myLoc = sites[i];
279     myR = myLoc.length();
280     smallestSoFar = particleRadius;
281    
282     for (int j = 0; j < nComponents; j++) {
283     if (myR <= shellRadii[j]) {
284     if (shellRadii[j] <= smallestSoFar) {
285     smallestSoFar = shellRadii[j];
286     myComponent = j;
287     }
288     }
289     }
290     componentFromSite[i] = myComponent;
291     nMol[myComponent]++;
292     }
293     }
294 chuckv 2737
295 chuckv 3044 outputFileName = args_info.output_arg;
296    
297 chuckv 2737
298 gezelter 3051 //creat new .md file on fly which corrects the number of molecule
299 chuckv 3044 createMdFile(inputFileName, outputFileName, nMol);
300 chuckv 2352
301     if (oldInfo != NULL)
302     delete oldInfo;
303    
304 chuckv 2737 SimCreator newCreator;
305 chuckv 3044 SimInfo* NewInfo = newCreator.createSim(outputFileName, false);
306 gezelter 3051
307 chuckv 2657 // Place molecules
308 chuckv 2352 Molecule* mol;
309     SimInfo::MoleculeIterator mi;
310     mol = NewInfo->beginMolecule(mi);
311 chuckv 2737 int l = 0;
312 chuckv 3044
313     for (int i = 0; i < nComponents; i++){
314     locator = new MoLocator(NewInfo->getMoleculeStamp(i),
315     NewInfo->getForceField());
316 gezelter 3051
317     if (args_info.ShellRadius_given) {
318     for (int n = 0; n < sites.size(); n++) {
319     if (componentFromSite[n] == i) {
320     mol = NewInfo->getMoleculeByGlobalIndex(l);
321     locator->placeMol(sites[n], orientations[n], mol);
322     l++;
323     }
324     }
325     } else {
326     for (int n = 0; n < nMol.at(i); n++) {
327     mol = NewInfo->getMoleculeByGlobalIndex(l);
328     locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
329     l++;
330     }
331 chuckv 3044 }
332 gezelter 3051 }
333 chuckv 2352
334     //fill Hmat
335 gezelter 3051 hmat(0, 0)= 10.0*particleRadius;
336 chuckv 2352 hmat(0, 1) = 0.0;
337     hmat(0, 2) = 0.0;
338    
339     hmat(1, 0) = 0.0;
340 gezelter 3051 hmat(1, 1) = 10.0*particleRadius;
341 chuckv 2352 hmat(1, 2) = 0.0;
342    
343     hmat(2, 0) = 0.0;
344     hmat(2, 1) = 0.0;
345 gezelter 3051 hmat(2, 2) = 10.0*particleRadius;
346 chuckv 2352
347     //set Hmat
348     NewInfo->getSnapshotManager()->getCurrentSnapshot()->setHmat(hmat);
349    
350    
351     //create dumpwriter and write out the coordinates
352 gezelter 3046 writer = new DumpWriter(NewInfo, outputFileName);
353 chuckv 2352
354     if (writer == NULL) {
355 chuckv 3044 sprintf(painCave.errMsg, "Error in creating dumpwrite object ");
356 gezelter 3051 painCave.isFatal = 1;
357     simError();
358 chuckv 2352 }
359    
360     writer->writeDump();
361 chuckv 3044
362     // deleting the writer will put the closing at the end of the dump file
363 gezelter 3046
364 chuckv 3044 delete writer;
365    
366     // cleanup a by calling sim error.....
367     sprintf(painCave.errMsg, "A new OOPSE MD file called \"%s\" has been "
368     "generated.\n", outputFileName.c_str());
369     painCave.isFatal = 0;
370     simError();
371 chuckv 2352 return 0;
372     }
373    
374 gezelter 3051 void createMdFile(const std::string&oldMdFileName,
375     const std::string&newMdFileName,
376 chuckv 3044 std::vector<int> nMol) {
377 chuckv 2352 ifstream oldMdFile;
378     ofstream newMdFile;
379     const int MAXLEN = 65535;
380     char buffer[MAXLEN];
381    
382     //create new .md file based on old .md file
383     oldMdFile.open(oldMdFileName.c_str());
384     newMdFile.open(newMdFileName.c_str());
385    
386     oldMdFile.getline(buffer, MAXLEN);
387 chuckv 2657
388     int i = 0;
389 chuckv 2352 while (!oldMdFile.eof()) {
390    
391     //correct molecule number
392     if (strstr(buffer, "nMol") != NULL) {
393 chuckv 3044 if(i<nMol.size()){
394     sprintf(buffer, "\tnMol = %i;", nMol.at(i));
395 chuckv 2737 newMdFile << buffer << std::endl;
396     i++;
397     }
398 chuckv 2352 } else
399     newMdFile << buffer << std::endl;
400    
401     oldMdFile.getline(buffer, MAXLEN);
402     }
403    
404     oldMdFile.close();
405     newMdFile.close();
406     }
407