ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/applications/nanoparticleBuilder/nanoparticleBuilder.cpp
Revision: 3044
Committed: Fri Oct 13 20:16:59 2006 UTC (17 years, 9 months ago) by chuckv
File size: 10881 byte(s)
Log Message:
Changed nanoparticle builder for new dump syntax.

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. 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 #include <algorithm>
51
52 #include "config.h"
53 #include "shapedLatticeSpherical.hpp"
54 #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 std::vector<int> numMol);
71
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 std::string outPrefix;
82 std::string outputFileName;
83 std::string outInitFileName;
84
85
86
87 Lattice *simpleLat;
88 MoLocator* locator;
89 int* numMol;
90 int nComponents;
91 double latticeConstant;
92 std::vector<double> lc;
93 double mass;
94
95 const double rhoConvertConst = 1.661;
96 double density;
97 double particleRadius;
98
99
100
101 Mat3x3d hmat;
102 std::vector<Vector3d> latticePos;
103 std::vector<Vector3d> latticeOrt;
104 int numMolPerCell;
105 int nShells; /* Number of shells in nanoparticle*/
106
107
108 DumpWriter *writer;
109
110 // Parse Command Line Arguments
111 if (cmdline_parser(argc, argv, &args_info) != 0)
112 exit(1);
113
114
115
116 /* get lattice type */
117 latticeType = "FCC";
118
119 /* get input file name */
120 if (args_info.inputs_num)
121 inputFileName = args_info.inputs[0];
122 else {
123 sprintf(painCave.errMsg, "No input .md file name was specified"
124 "on the command line");
125 painCave.isFatal = 1;
126 cmdline_parser_print_help();
127 simError();
128 }
129
130 /* parse md file and set up the system */
131 SimCreator oldCreator;
132 SimInfo* oldInfo = oldCreator.createSim(inputFileName, false);
133
134
135 latticeConstant = args_info.latticeCnst_arg;
136 particleRadius = args_info.radius_arg;
137 Globals* simParams = oldInfo->getSimParams();
138
139
140 /* create Molocators */
141 locator = new MoLocator(oldInfo->getMoleculeStamp(0), oldInfo->getForceField());
142
143 /* Create nanoparticle */
144 shapedLatticeSpherical nanoParticle(latticeConstant,latticeType,particleRadius);
145
146 /* Build a lattice and get lattice points for this lattice constant */
147 vector<Vector3d> sites = nanoParticle.getPoints();
148 vector<Vector3d> orientations = nanoParticle.getPointsOrt();
149
150 std::cout <<"nSites: " << sites.size() << std::endl;
151
152 /* Get number of lattice sites */
153 int nSites = sites.size();
154
155
156
157
158 std::vector<Component*> components = simParams->getComponents();
159 std::vector<RealType> molFractions;
160 std::vector<RealType> molecularMasses;
161 std::vector<int> nMol;
162 nComponents = components.size();
163
164
165
166 if (nComponents == 1) {
167 molFractions.push_back(1.0);
168 } else {
169 if (args_info.molFraction_given == nComponents) {
170 for (int i = 0; i < nComponents; i++) {
171 molFractions.push_back(args_info.molFraction_arg[i]);
172 }
173 } else if (args_info.molFraction_given == nComponents-1) {
174 RealType remainingFraction = 1.0;
175 for (int i = 0; i < nComponents-1; i++) {
176 molFractions.push_back(args_info.molFraction_arg[i]);
177 remainingFraction -= molFractions[i];
178 }
179 molFractions.push_back(remainingFraction);
180 } else {
181 sprintf(painCave.errMsg, "nanoparticleBuilder can't figure out molFractions "
182 "for all of the components in the <MetaData> block.");
183 painCave.isFatal = 1;
184 simError();
185 }
186 }
187
188 RealType totalFraction = 0.0;
189
190 /* Do some simple sanity checking*/
191
192
193
194 for (int i = 0; i < nComponents; i++) {
195 if (molFractions.at(i) < 0.0) {
196 sprintf(painCave.errMsg, "One of the requested molFractions was"
197 " less than zero!");
198 painCave.isFatal = 1;
199 simError();
200 }
201 if (molFractions.at(i) > 1.0) {
202 sprintf(painCave.errMsg, "One of the requested molFractions was"
203 " greater than one!");
204 painCave.isFatal = 1;
205 simError();
206 }
207 totalFraction += molFractions.at(i);
208 }
209 if (abs(totalFraction - 1.0) > 1e-6) {
210 sprintf(painCave.errMsg, "The sum of molFractions was not close enough to 1.0");
211 painCave.isFatal = 1;
212 simError();
213 }
214
215 int remaining = nSites;
216 for (int i=0; i < nComponents-1; i++) {
217 nMol.push_back(int((RealType)nSites * molFractions.at(i)));
218 remaining -= nMol.at(i);
219 }
220 nMol.push_back(remaining);
221
222
223
224 // recompute actual mol fractions and perform final sanity check:
225
226 int totalMolecules = 0;
227 RealType totalMass = 0.0;
228 for (int i=0; i < nComponents; i++) {
229 molFractions[i] = (RealType)(nMol.at(i))/(RealType)nSites;
230 totalMolecules += nMol.at(i);
231 molecularMasses.push_back(getMolMass(oldInfo->getMoleculeStamp(i),
232 oldInfo->getForceField()));
233 totalMass += (RealType)(nMol.at(i)) * molecularMasses.at(i);
234 }
235 RealType avgMass = totalMass / (RealType) totalMolecules;
236
237 if (totalMolecules != nSites) {
238 sprintf(painCave.errMsg, "Computed total number of molecules is not equal "
239 "to the number of lattice sites!");
240 painCave.isFatal = 1;
241 simError();
242 }
243
244
245
246
247 vector<int> ids;
248 for (int i = 0; i < sites.size(); i++) ids.push_back(i);
249 /* Random particle is the default case*/
250 if (!args_info.ShellRadius_given){
251 /* do the iPod thing, Shuffle da vector */
252 std::random_shuffle(ids.begin(), ids.end());
253 } else{ /*Handle core-shell with multiple components.*/
254 std::cout << "Creating a core-shell nanoparticle." << std::endl;
255 if (nComponents != args_info.ShellRadius_given + 1){
256 sprintf(painCave.errMsg, "Number of .md components "
257 "does not match the number of shell radius specifications");
258 painCave.isFatal = 1;
259 simError();
260 }
261
262 }
263
264
265
266
267 outputFileName = args_info.output_arg;
268
269
270 //creat new .md file on fly which corrects the number of molecule
271 createMdFile(inputFileName, outputFileName, nMol);
272
273 if (oldInfo != NULL)
274 delete oldInfo;
275
276
277 // We need to read in new siminfo object.
278 //parse md file and set up the system
279 //SimCreator NewCreator;
280 SimCreator newCreator;
281 SimInfo* NewInfo = newCreator.createSim(outputFileName, false);
282
283
284 // Place molecules
285 Molecule* mol;
286 SimInfo::MoleculeIterator mi;
287 mol = NewInfo->beginMolecule(mi);
288 int l = 0;
289
290 for (int i = 0; i < nComponents; i++){
291 locator = new MoLocator(NewInfo->getMoleculeStamp(i),
292 NewInfo->getForceField());
293 for (int n = 0; n < nMol.at(i); n++) {
294 mol = NewInfo->getMoleculeByGlobalIndex(l);
295 locator->placeMol(sites[ids[l]], orientations[ids[l]], mol);
296 l++;
297 }
298 }
299
300
301
302 //fill Hmat
303 hmat(0, 0)= 2.0*particleRadius;
304 hmat(0, 1) = 0.0;
305 hmat(0, 2) = 0.0;
306
307 hmat(1, 0) = 0.0;
308 hmat(1, 1) = 2.0*particleRadius;
309 hmat(1, 2) = 0.0;
310
311 hmat(2, 0) = 0.0;
312 hmat(2, 1) = 0.0;
313 hmat(2, 2) = 2.0*particleRadius;
314
315 //set Hmat
316 NewInfo->getSnapshotManager()->getCurrentSnapshot()->setHmat(hmat);
317
318
319 //create dumpwriter and write out the coordinates
320 writer = new DumpWriter(NewInfo,outputFileName);
321
322 if (writer == NULL) {
323 sprintf(painCave.errMsg, "Error in creating dumpwrite object ");
324 painCave.isFatal = 1;
325 simError();
326 }
327
328 writer->writeDump();
329 std::cout << "new initial configuration file: " << outInitFileName
330 << " is generated." << std::endl;
331
332
333 // deleting the writer will put the closing at the end of the dump file
334 delete writer;
335
336 // cleanup a by calling sim error.....
337 sprintf(painCave.errMsg, "A new OOPSE MD file called \"%s\" has been "
338 "generated.\n", outputFileName.c_str());
339 painCave.isFatal = 0;
340 simError();
341 return 0;
342 }
343
344 void createMdFile(const std::string&oldMdFileName, const std::string&newMdFileName,
345 std::vector<int> nMol) {
346 ifstream oldMdFile;
347 ofstream newMdFile;
348 const int MAXLEN = 65535;
349 char buffer[MAXLEN];
350
351 //create new .md file based on old .md file
352 oldMdFile.open(oldMdFileName.c_str());
353 newMdFile.open(newMdFileName.c_str());
354
355 oldMdFile.getline(buffer, MAXLEN);
356
357 int i = 0;
358 while (!oldMdFile.eof()) {
359
360 //correct molecule number
361 if (strstr(buffer, "nMol") != NULL) {
362 if(i<nMol.size()){
363 sprintf(buffer, "\tnMol = %i;", nMol.at(i));
364 newMdFile << buffer << std::endl;
365 i++;
366 }
367 } else
368 newMdFile << buffer << std::endl;
369
370 oldMdFile.getline(buffer, MAXLEN);
371 }
372
373 oldMdFile.close();
374 newMdFile.close();
375 }
376