ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/applications/randomBuilder/randomBuilder.cpp
Revision: 3041
Committed: Tue Oct 10 18:34:12 2006 UTC (17 years, 9 months ago) by gezelter
File size: 11287 byte(s)
Log Message:
fixing missing lattice arguments, adding a builder sample

File Contents

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