ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/SimCreator.cpp
Revision: 1976
Committed: Wed Mar 12 20:01:15 2014 UTC (11 years, 1 month ago) by gezelter
File size: 35457 byte(s)
Log Message:
Revision string moves to its own cpp file that is compiled, and out of a 
defined string.  This will make it a bit easier to migrate to git when 
the time comes.

File Contents

# User Rev Content
1 gezelter 403 /*
2 gezelter 1880 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 gezelter 403 *
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 gezelter 1390 * 1. Redistributions of source code must retain the above copyright
10 gezelter 403 * notice, this list of conditions and the following disclaimer.
11     *
12 gezelter 1390 * 2. Redistributions in binary form must reproduce the above copyright
13 gezelter 403 * 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 gezelter 1390 *
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 gezelter 1782 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 gezelter 403 */
42    
43     /**
44     * @file SimCreator.cpp
45     * @author tlin
46     * @date 11/03/2004
47     * @version 1.0
48     */
49 gezelter 1938
50     #ifdef IS_MPI
51     #include "mpi.h"
52     #include "math/ParallelRandNumGen.hpp"
53     #endif
54    
55 tim 845 #include <exception>
56 tim 770 #include <iostream>
57     #include <sstream>
58     #include <string>
59    
60 gezelter 403 #include "brains/MoleculeCreator.hpp"
61     #include "brains/SimCreator.hpp"
62     #include "brains/SimSnapshotManager.hpp"
63     #include "io/DumpReader.hpp"
64 gezelter 1782 #include "brains/ForceField.hpp"
65 gezelter 403 #include "utils/simError.h"
66     #include "utils/StringUtils.hpp"
67 gezelter 1976 #include "utils/Revision.hpp"
68 gezelter 403 #include "math/SeqRandNumGen.hpp"
69 tim 770 #include "mdParser/MDLexer.hpp"
70     #include "mdParser/MDParser.hpp"
71     #include "mdParser/MDTreeParser.hpp"
72     #include "mdParser/SimplePreprocessor.hpp"
73 tim 816 #include "antlr/ANTLRException.hpp"
74     #include "antlr/TokenStreamRecognitionException.hpp"
75     #include "antlr/TokenStreamIOException.hpp"
76     #include "antlr/TokenStreamException.hpp"
77     #include "antlr/RecognitionException.hpp"
78     #include "antlr/CharStreamException.hpp"
79 tim 770
80 tim 816 #include "antlr/MismatchedCharException.hpp"
81     #include "antlr/MismatchedTokenException.hpp"
82     #include "antlr/NoViableAltForCharException.hpp"
83     #include "antlr/NoViableAltException.hpp"
84 tim 770
85 gezelter 1782 #include "types/DirectionalAdapter.hpp"
86     #include "types/MultipoleAdapter.hpp"
87     #include "types/EAMAdapter.hpp"
88     #include "types/SuttonChenAdapter.hpp"
89     #include "types/PolarizableAdapter.hpp"
90     #include "types/FixedChargeAdapter.hpp"
91     #include "types/FluctuatingChargeAdapter.hpp"
92    
93 gezelter 403
94 gezelter 1390 namespace OpenMD {
95 chrisfen 417
96 gezelter 1782 Globals* SimCreator::parseFile(std::istream& rawMetaDataStream, const std::string& filename, int mdFileVersion, int startOfMetaDataBlock ){
97 tim 1024 Globals* simParams = NULL;
98     try {
99 tim 770
100 tim 1024 // Create a preprocessor that preprocesses md file into an ostringstream
101     std::stringstream ppStream;
102 tim 770 #ifdef IS_MPI
103 tim 1024 int streamSize;
104     const int masterNode = 0;
105 gezelter 1793
106 tim 1024 if (worldRank == masterNode) {
107 gezelter 1969 MPI_Bcast(&mdFileVersion, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
108     // MPI::COMM_WORLD.Bcast(&mdFileVersion, 1, MPI::INT, masterNode);
109 gezelter 1782 #endif
110 tim 1024 SimplePreprocessor preprocessor;
111 gezelter 1969 preprocessor.preprocess(rawMetaDataStream, filename,
112     startOfMetaDataBlock, ppStream);
113 tim 770
114     #ifdef IS_MPI
115 gezelter 1969 //broadcasting the stream size
116 tim 1024 streamSize = ppStream.str().size() +1;
117 gezelter 1971 MPI_Bcast(&streamSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
118 gezelter 1969 MPI_Bcast(static_cast<void*>(const_cast<char*>(ppStream.str().c_str())),
119     streamSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
120    
121     // MPI::COMM_WORLD.Bcast(&streamSize, 1, MPI::LONG, masterNode);
122     // MPI::COMM_WORLD.Bcast(static_cast<void*>(const_cast<char*>(ppStream.str().c_str())),
123     // streamSize, MPI::CHAR, masterNode);
124 gezelter 1879
125 tim 1024 } else {
126 gezelter 1782
127 gezelter 1969 MPI_Bcast(&mdFileVersion, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
128     // MPI::COMM_WORLD.Bcast(&mdFileVersion, 1, MPI::INT, masterNode);
129    
130 tim 1024 //get stream size
131 gezelter 1971 MPI_Bcast(&streamSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
132 gezelter 1969 // MPI::COMM_WORLD.Bcast(&streamSize, 1, MPI::LONG, masterNode);
133 tim 1024 char* buf = new char[streamSize];
134     assert(buf);
135 tim 770
136 tim 1024 //receive file content
137 gezelter 1969 MPI_Bcast(buf, streamSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
138     // MPI::COMM_WORLD.Bcast(buf, streamSize, MPI::CHAR, masterNode);
139    
140 tim 1024 ppStream.str(buf);
141 gezelter 1313 delete [] buf;
142 tim 1024 }
143 tim 770 #endif
144 tim 1024 // Create a scanner that reads from the input stream
145     MDLexer lexer(ppStream);
146     lexer.setFilename(filename);
147     lexer.initDeferredLineCount();
148 chrisfen 417
149 tim 1024 // Create a parser that reads from the scanner
150     MDParser parser(lexer);
151     parser.setFilename(filename);
152 tim 770
153 tim 1024 // Create an observer that synchorizes file name change
154     FilenameObserver observer;
155     observer.setLexer(&lexer);
156     observer.setParser(&parser);
157     lexer.setObserver(&observer);
158 chrisfen 417
159 tim 1024 antlr::ASTFactory factory;
160     parser.initializeASTFactory(factory);
161     parser.setASTFactory(&factory);
162     parser.mdfile();
163     // Create a tree parser that reads information into Globals
164     MDTreeParser treeParser;
165     treeParser.initializeASTFactory(factory);
166     treeParser.setASTFactory(&factory);
167     simParams = treeParser.walkTree(parser.getAST());
168     }
169 tim 845
170 tim 816
171 tim 1024 catch(antlr::MismatchedCharException& e) {
172     sprintf(painCave.errMsg,
173     "parser exception: %s %s:%d:%d\n",
174     e.getMessage().c_str(),e.getFilename().c_str(), e.getLine(), e.getColumn());
175     painCave.isFatal = 1;
176     simError();
177     }
178     catch(antlr::MismatchedTokenException &e) {
179     sprintf(painCave.errMsg,
180     "parser exception: %s %s:%d:%d\n",
181     e.getMessage().c_str(),e.getFilename().c_str(), e.getLine(), e.getColumn());
182     painCave.isFatal = 1;
183     simError();
184     }
185     catch(antlr::NoViableAltForCharException &e) {
186     sprintf(painCave.errMsg,
187     "parser exception: %s %s:%d:%d\n",
188     e.getMessage().c_str(),e.getFilename().c_str(), e.getLine(), e.getColumn());
189     painCave.isFatal = 1;
190     simError();
191     }
192     catch(antlr::NoViableAltException &e) {
193     sprintf(painCave.errMsg,
194     "parser exception: %s %s:%d:%d\n",
195     e.getMessage().c_str(),e.getFilename().c_str(), e.getLine(), e.getColumn());
196     painCave.isFatal = 1;
197     simError();
198     }
199 tim 845
200 tim 1024 catch(antlr::TokenStreamRecognitionException& e) {
201     sprintf(painCave.errMsg,
202     "parser exception: %s %s:%d:%d\n",
203     e.getMessage().c_str(),e.getFilename().c_str(), e.getLine(), e.getColumn());
204     painCave.isFatal = 1;
205     simError();
206     }
207 tim 845
208 tim 1024 catch(antlr::TokenStreamIOException& e) {
209     sprintf(painCave.errMsg,
210     "parser exception: %s\n",
211     e.getMessage().c_str());
212     painCave.isFatal = 1;
213     simError();
214     }
215 tim 845
216 tim 1024 catch(antlr::TokenStreamException& e) {
217     sprintf(painCave.errMsg,
218     "parser exception: %s\n",
219     e.getMessage().c_str());
220     painCave.isFatal = 1;
221     simError();
222     }
223     catch (antlr::RecognitionException& e) {
224     sprintf(painCave.errMsg,
225     "parser exception: %s %s:%d:%d\n",
226     e.getMessage().c_str(),e.getFilename().c_str(), e.getLine(), e.getColumn());
227     painCave.isFatal = 1;
228     simError();
229     }
230     catch (antlr::CharStreamException& e) {
231     sprintf(painCave.errMsg,
232     "parser exception: %s\n",
233     e.getMessage().c_str());
234     painCave.isFatal = 1;
235     simError();
236     }
237 gezelter 1390 catch (OpenMDException& e) {
238 tim 1024 sprintf(painCave.errMsg,
239     "%s\n",
240     e.getMessage().c_str());
241     painCave.isFatal = 1;
242     simError();
243     }
244     catch (std::exception& e) {
245     sprintf(painCave.errMsg,
246     "parser exception: %s\n",
247     e.what());
248     painCave.isFatal = 1;
249     simError();
250     }
251 tim 770
252 gezelter 1782 simParams->setMDfileVersion(mdFileVersion);
253 tim 1024 return simParams;
254 gezelter 403 }
255 chrisfen 417
256 chrisfen 514 SimInfo* SimCreator::createSim(const std::string & mdFileName,
257     bool loadInitCoords) {
258 gezelter 1782
259 tim 1024 const int bufferSize = 65535;
260     char buffer[bufferSize];
261     int lineNo = 0;
262     std::string mdRawData;
263     int metaDataBlockStart = -1;
264     int metaDataBlockEnd = -1;
265 gezelter 1810 int i, j;
266 gezelter 1879 streamoff mdOffset;
267 gezelter 1782 int mdFileVersion;
268 tim 1024
269 gezelter 1810 // Create a string for embedding the version information in the MetaData
270     std::string version;
271     version.assign("## Last run using OpenMD Version: ");
272     version.append(OPENMD_VERSION_MAJOR);
273     version.append(".");
274     version.append(OPENMD_VERSION_MINOR);
275 gezelter 1790
276 gezelter 1976 std::string svnrev(g_REVISION, strnlen(g_REVISION, 20));
277 gezelter 1810 //convert a macro from compiler to a string in c++
278 gezelter 1976 // STR_DEFINE(svnrev, SVN_REV );
279 gezelter 1810 version.append(" Revision: ");
280     // If there's no SVN revision, just call this the RELEASE revision.
281     if (!svnrev.empty()) {
282     version.append(svnrev);
283     } else {
284     version.append("RELEASE");
285     }
286    
287 tim 1024 #ifdef IS_MPI
288     const int masterNode = 0;
289     if (worldRank == masterNode) {
290     #endif
291    
292 gezelter 1790 std::ifstream mdFile_;
293     mdFile_.open(mdFileName.c_str(), ifstream::in | ifstream::binary);
294 tim 1024
295     if (mdFile_.fail()) {
296     sprintf(painCave.errMsg,
297     "SimCreator: Cannot open file: %s\n",
298     mdFileName.c_str());
299     painCave.isFatal = 1;
300     simError();
301     }
302    
303     mdFile_.getline(buffer, bufferSize);
304     ++lineNo;
305     std::string line = trimLeftCopy(buffer);
306 gezelter 1390 i = CaseInsensitiveFind(line, "<OpenMD");
307 gezelter 1287 if (static_cast<size_t>(i) == string::npos) {
308 gezelter 1390 // try the older file strings to see if that works:
309     i = CaseInsensitiveFind(line, "<OOPSE");
310     }
311    
312     if (static_cast<size_t>(i) == string::npos) {
313     // still no luck!
314 tim 1024 sprintf(painCave.errMsg,
315 gezelter 1390 "SimCreator: File: %s is not a valid OpenMD file!\n",
316 tim 1024 mdFileName.c_str());
317     painCave.isFatal = 1;
318     simError();
319     }
320 gezelter 1782
321     // found the correct opening string, now try to get the file
322     // format version number.
323 tim 1024
324 gezelter 1782 StringTokenizer tokenizer(line, "=<> \t\n\r");
325     std::string fileType = tokenizer.nextToken();
326     toUpper(fileType);
327    
328     mdFileVersion = 0;
329    
330     if (fileType == "OPENMD") {
331     while (tokenizer.hasMoreTokens()) {
332     std::string token(tokenizer.nextToken());
333     toUpper(token);
334     if (token == "VERSION") {
335     mdFileVersion = tokenizer.nextTokenAsInt();
336     break;
337     }
338     }
339     }
340    
341 tim 1024 //scan through the input stream and find MetaData tag
342     while(mdFile_.getline(buffer, bufferSize)) {
343     ++lineNo;
344    
345     std::string line = trimLeftCopy(buffer);
346     if (metaDataBlockStart == -1) {
347     i = CaseInsensitiveFind(line, "<MetaData>");
348     if (i != string::npos) {
349     metaDataBlockStart = lineNo;
350     mdOffset = mdFile_.tellg();
351     }
352     } else {
353     i = CaseInsensitiveFind(line, "</MetaData>");
354     if (i != string::npos) {
355     metaDataBlockEnd = lineNo;
356     }
357     }
358     }
359    
360     if (metaDataBlockStart == -1) {
361     sprintf(painCave.errMsg,
362     "SimCreator: File: %s did not contain a <MetaData> tag!\n",
363     mdFileName.c_str());
364     painCave.isFatal = 1;
365     simError();
366     }
367     if (metaDataBlockEnd == -1) {
368     sprintf(painCave.errMsg,
369     "SimCreator: File: %s did not contain a closed MetaData block!\n",
370     mdFileName.c_str());
371     painCave.isFatal = 1;
372     simError();
373     }
374    
375     mdFile_.clear();
376     mdFile_.seekg(0);
377     mdFile_.seekg(mdOffset);
378    
379     mdRawData.clear();
380    
381 gezelter 1810 bool foundVersion = false;
382    
383 tim 1024 for (int i = 0; i < metaDataBlockEnd - metaDataBlockStart - 1; ++i) {
384     mdFile_.getline(buffer, bufferSize);
385 gezelter 1810 std::string line = trimLeftCopy(buffer);
386     j = CaseInsensitiveFind(line, "## Last run using OpenMD Version");
387     if (static_cast<size_t>(j) != string::npos) {
388     foundVersion = true;
389     mdRawData += version;
390     } else {
391     mdRawData += buffer;
392     }
393 tim 1024 mdRawData += "\n";
394     }
395 gezelter 1810
396     if (!foundVersion) mdRawData += version + "\n";
397    
398 tim 1024 mdFile_.close();
399    
400     #ifdef IS_MPI
401     }
402     #endif
403    
404     std::stringstream rawMetaDataStream(mdRawData);
405    
406 gezelter 403 //parse meta-data file
407 gezelter 1782 Globals* simParams = parseFile(rawMetaDataStream, mdFileName, mdFileVersion,
408     metaDataBlockStart + 1);
409 chrisfen 417
410 gezelter 403 //create the force field
411 gezelter 1782 ForceField * ff = new ForceField(simParams->getForceField());
412 gezelter 1277
413 gezelter 403 if (ff == NULL) {
414 chrisfen 514 sprintf(painCave.errMsg,
415     "ForceField Factory can not create %s force field\n",
416 tim 665 simParams->getForceField().c_str());
417 gezelter 403 painCave.isFatal = 1;
418     simError();
419     }
420 chrisfen 417
421 gezelter 403 if (simParams->haveForceFieldFileName()) {
422     ff->setForceFieldFileName(simParams->getForceFieldFileName());
423     }
424    
425     std::string forcefieldFileName;
426     forcefieldFileName = ff->getForceFieldFileName();
427 chrisfen 417
428 gezelter 403 if (simParams->haveForceFieldVariant()) {
429     //If the force field has variant, the variant force field name will be
430     //Base.variant.frc. For exampel EAM.u6.frc
431 chrisfen 417
432 gezelter 403 std::string variant = simParams->getForceFieldVariant();
433 chrisfen 417
434 gezelter 403 std::string::size_type pos = forcefieldFileName.rfind(".frc");
435     variant = "." + variant;
436     if (pos != std::string::npos) {
437     forcefieldFileName.insert(pos, variant);
438     } else {
439     //If the default force field file name does not containt .frc suffix, just append the .variant
440     forcefieldFileName.append(variant);
441     }
442     }
443    
444     ff->parse(forcefieldFileName);
445     //create SimInfo
446 tim 770 SimInfo * info = new SimInfo(ff, simParams);
447 tim 1024
448     info->setRawMetaData(mdRawData);
449 tim 490
450 gezelter 945 //gather parameters (SimCreator only retrieves part of the
451     //parameters)
452 gezelter 403 gatherParameters(info, mdFileName);
453 chrisfen 417
454 gezelter 403 //divide the molecules and determine the global index of molecules
455     #ifdef IS_MPI
456     divideMolecules(info);
457     #endif
458 chrisfen 417
459 gezelter 403 //create the molecules
460     createMolecules(info);
461 chrisfen 417
462 gezelter 1782 //find the storage layout
463    
464     int storageLayout = computeStorageLayout(info);
465    
466 gezelter 945 //allocate memory for DataStorage(circular reference, need to
467     //break it)
468 gezelter 1782 info->setSnapshotManager(new SimSnapshotManager(info, storageLayout));
469 gezelter 403
470 gezelter 945 //set the global index of atoms, rigidbodies and cutoffgroups
471     //(only need to be set once, the global index will never change
472     //again). Local indices of atoms and rigidbodies are already set
473     //by MoleculeCreator class which actually delegates the
474     //responsibility to LocalIndexManager.
475 gezelter 403 setGlobalIndex(info);
476 chrisfen 417
477 gezelter 1287 //Although addInteractionPairs is called inside SimInfo's addMolecule
478 gezelter 945 //method, at that point atoms don't have the global index yet
479     //(their global index are all initialized to -1). Therefore we
480 gezelter 1287 //have to call addInteractionPairs explicitly here. A way to work
481 gezelter 945 //around is that we can determine the beginning global indices of
482     //atoms before they get created.
483 gezelter 403 SimInfo::MoleculeIterator mi;
484     Molecule* mol;
485     for (mol= info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) {
486 gezelter 1287 info->addInteractionPairs(mol);
487 gezelter 403 }
488    
489     if (loadInitCoords)
490 tim 1024 loadCoordinates(info, mdFileName);
491 gezelter 403 return info;
492     }
493 chrisfen 417
494 gezelter 403 void SimCreator::gatherParameters(SimInfo *info, const std::string& mdfile) {
495 chrisfen 417
496 tim 749 //figure out the output file names
497 gezelter 403 std::string prefix;
498 chrisfen 417
499 gezelter 403 #ifdef IS_MPI
500 chrisfen 417
501 gezelter 403 if (worldRank == 0) {
502     #endif // is_mpi
503     Globals * simParams = info->getSimParams();
504     if (simParams->haveFinalConfig()) {
505     prefix = getPrefix(simParams->getFinalConfig());
506     } else {
507     prefix = getPrefix(mdfile);
508     }
509 chrisfen 417
510 gezelter 403 info->setFinalConfigFileName(prefix + ".eor");
511     info->setDumpFileName(prefix + ".dump");
512     info->setStatFileName(prefix + ".stat");
513 chrisfen 417 info->setRestFileName(prefix + ".zang");
514    
515 gezelter 403 #ifdef IS_MPI
516 chrisfen 417
517 gezelter 403 }
518 chrisfen 417
519 gezelter 403 #endif
520 chrisfen 417
521 gezelter 403 }
522 chrisfen 417
523 gezelter 403 #ifdef IS_MPI
524     void SimCreator::divideMolecules(SimInfo *info) {
525 tim 963 RealType a;
526 gezelter 403 int nProcessors;
527     std::vector<int> atomsPerProc;
528     int nGlobalMols = info->getNGlobalMolecules();
529 gezelter 1879 std::vector<int> molToProcMap(nGlobalMols, -1); // default to an
530     // error
531     // condition:
532 gezelter 403
533 gezelter 1969 MPI_Comm_size( MPI_COMM_WORLD, &nProcessors);
534     //nProcessors = MPI::COMM_WORLD.Get_size();
535 chrisfen 417
536 gezelter 403 if (nProcessors > nGlobalMols) {
537     sprintf(painCave.errMsg,
538     "nProcessors (%d) > nMol (%d)\n"
539     "\tThe number of processors is larger than\n"
540     "\tthe number of molecules. This will not result in a \n"
541     "\tusable division of atoms for force decomposition.\n"
542     "\tEither try a smaller number of processors, or run the\n"
543 gezelter 1879 "\tsingle-processor version of OpenMD.\n", nProcessors,
544     nGlobalMols);
545 chrisfen 417
546 gezelter 403 painCave.isFatal = 1;
547     simError();
548     }
549 chrisfen 417
550 gezelter 403 Globals * simParams = info->getSimParams();
551 gezelter 1879 SeqRandNumGen* myRandom; //divide labor does not need Parallel
552     //random number generator
553 gezelter 403 if (simParams->haveSeed()) {
554 gezelter 1879 int seedValue = simParams->getSeed();
555 gezelter 403 myRandom = new SeqRandNumGen(seedValue);
556     }else {
557     myRandom = new SeqRandNumGen();
558     }
559 chrisfen 417
560    
561 gezelter 403 a = 3.0 * nGlobalMols / info->getNGlobalAtoms();
562 chrisfen 417
563 gezelter 403 //initialize atomsPerProc
564     atomsPerProc.insert(atomsPerProc.end(), nProcessors, 0);
565 chrisfen 417
566 gezelter 403 if (worldRank == 0) {
567 gezelter 1879 RealType numerator = info->getNGlobalAtoms();
568     RealType denominator = nProcessors;
569     RealType precast = numerator / denominator;
570     int nTarget = (int)(precast + 0.5);
571 chrisfen 417
572 gezelter 1879 for(int i = 0; i < nGlobalMols; i++) {
573 gezelter 1801
574 gezelter 1879 int done = 0;
575     int loops = 0;
576 chrisfen 417
577 gezelter 403 while (!done) {
578     loops++;
579 chrisfen 417
580 gezelter 403 // Pick a processor at random
581 chrisfen 417
582 gezelter 1879 int which_proc = (int) (myRandom->rand() * nProcessors);
583 chrisfen 417
584 gezelter 403 //get the molecule stamp first
585     int stampId = info->getMoleculeStampId(i);
586     MoleculeStamp * moleculeStamp = info->getMoleculeStamp(stampId);
587 chrisfen 417
588 gezelter 403 // How many atoms does this processor have so far?
589 gezelter 1879 int old_atoms = atomsPerProc[which_proc];
590     int add_atoms = moleculeStamp->getNAtoms();
591     int new_atoms = old_atoms + add_atoms;
592 chrisfen 417
593 gezelter 403 // If we've been through this loop too many times, we need
594     // to just give up and assign the molecule to this processor
595     // and be done with it.
596 chrisfen 417
597 gezelter 403 if (loops > 100) {
598 gezelter 1801
599 gezelter 403 sprintf(painCave.errMsg,
600 gezelter 1801 "There have been 100 attempts to assign molecule %d to an\n"
601     "\tunderworked processor, but there's no good place to\n"
602     "\tleave it. OpenMD is assigning it at random to processor %d.\n",
603 gezelter 403 i, which_proc);
604 gezelter 1801
605 gezelter 403 painCave.isFatal = 0;
606 gezelter 1801 painCave.severity = OPENMD_INFO;
607 gezelter 403 simError();
608 chrisfen 417
609 gezelter 403 molToProcMap[i] = which_proc;
610     atomsPerProc[which_proc] += add_atoms;
611 chrisfen 417
612 gezelter 403 done = 1;
613     continue;
614     }
615 chrisfen 417
616 gezelter 403 // If we can add this molecule to this processor without sending
617     // it above nTarget, then go ahead and do it:
618 chrisfen 417
619 gezelter 403 if (new_atoms <= nTarget) {
620     molToProcMap[i] = which_proc;
621     atomsPerProc[which_proc] += add_atoms;
622 chrisfen 417
623 gezelter 403 done = 1;
624     continue;
625     }
626 chrisfen 417
627 gezelter 403 // The only situation left is when new_atoms > nTarget. We
628     // want to accept this with some probability that dies off the
629     // farther we are from nTarget
630 chrisfen 417
631 gezelter 403 // roughly: x = new_atoms - nTarget
632     // Pacc(x) = exp(- a * x)
633     // where a = penalty / (average atoms per molecule)
634 chrisfen 417
635 gezelter 1879 RealType x = (RealType)(new_atoms - nTarget);
636     RealType y = myRandom->rand();
637 chrisfen 417
638 gezelter 403 if (y < exp(- a * x)) {
639     molToProcMap[i] = which_proc;
640     atomsPerProc[which_proc] += add_atoms;
641 chrisfen 417
642 gezelter 403 done = 1;
643     continue;
644     } else {
645     continue;
646     }
647     }
648     }
649 chrisfen 417
650 gezelter 403 delete myRandom;
651 gezelter 1801
652 gezelter 403 // Spray out this nonsense to all other processors:
653 gezelter 1969 MPI_Bcast(&molToProcMap[0], nGlobalMols, MPI_INT, 0, MPI_COMM_WORLD);
654     // MPI::COMM_WORLD.Bcast(&molToProcMap[0], nGlobalMols, MPI::INT, 0);
655 gezelter 403 } else {
656 chrisfen 417
657 gezelter 403 // Listen to your marching orders from processor 0:
658 gezelter 1969 MPI_Bcast(&molToProcMap[0], nGlobalMols, MPI_INT, 0, MPI_COMM_WORLD);
659     // MPI::COMM_WORLD.Bcast(&molToProcMap[0], nGlobalMols, MPI::INT, 0);
660 gezelter 1801
661 gezelter 403 }
662 chrisfen 417
663 gezelter 403 info->setMolToProcMap(molToProcMap);
664     sprintf(checkPointMsg,
665     "Successfully divided the molecules among the processors.\n");
666 gezelter 1241 errorCheckPoint();
667 gezelter 403 }
668 chrisfen 417
669 gezelter 403 #endif
670 chrisfen 417
671 gezelter 403 void SimCreator::createMolecules(SimInfo *info) {
672     MoleculeCreator molCreator;
673     int stampId;
674 chrisfen 417
675 gezelter 403 for(int i = 0; i < info->getNGlobalMolecules(); i++) {
676 chrisfen 417
677 gezelter 403 #ifdef IS_MPI
678 chrisfen 417
679 gezelter 403 if (info->getMolToProc(i) == worldRank) {
680     #endif
681 chrisfen 417
682 gezelter 403 stampId = info->getMoleculeStampId(i);
683 gezelter 1782 Molecule * mol = molCreator.createMolecule(info->getForceField(),
684     info->getMoleculeStamp(stampId),
685     stampId, i,
686     info->getLocalIndexManager());
687 chrisfen 417
688 gezelter 403 info->addMolecule(mol);
689 chrisfen 417
690 gezelter 403 #ifdef IS_MPI
691 chrisfen 417
692 gezelter 403 }
693 chrisfen 417
694 gezelter 403 #endif
695 chrisfen 417
696 gezelter 403 } //end for(int i=0)
697     }
698 chrisfen 417
699 gezelter 1782 int SimCreator::computeStorageLayout(SimInfo* info) {
700    
701     Globals* simParams = info->getSimParams();
702     int nRigidBodies = info->getNGlobalRigidBodies();
703     set<AtomType*> atomTypes = info->getSimulatedAtomTypes();
704     set<AtomType*>::iterator i;
705     bool hasDirectionalAtoms = false;
706     bool hasFixedCharge = false;
707 gezelter 1879 bool hasDipoles = false;
708     bool hasQuadrupoles = false;
709 gezelter 1782 bool hasPolarizable = false;
710     bool hasFluctuatingCharge = false;
711     bool hasMetallic = false;
712     int storageLayout = 0;
713     storageLayout |= DataStorage::dslPosition;
714     storageLayout |= DataStorage::dslVelocity;
715     storageLayout |= DataStorage::dslForce;
716    
717     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
718    
719     DirectionalAdapter da = DirectionalAdapter( (*i) );
720     MultipoleAdapter ma = MultipoleAdapter( (*i) );
721     EAMAdapter ea = EAMAdapter( (*i) );
722     SuttonChenAdapter sca = SuttonChenAdapter( (*i) );
723     PolarizableAdapter pa = PolarizableAdapter( (*i) );
724     FixedChargeAdapter fca = FixedChargeAdapter( (*i) );
725     FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter( (*i) );
726    
727     if (da.isDirectional()){
728     hasDirectionalAtoms = true;
729     }
730 gezelter 1879 if (ma.isDipole()){
731     hasDipoles = true;
732 gezelter 1782 }
733 gezelter 1879 if (ma.isQuadrupole()){
734     hasQuadrupoles = true;
735     }
736 gezelter 1782 if (ea.isEAM() || sca.isSuttonChen()){
737     hasMetallic = true;
738     }
739     if ( fca.isFixedCharge() ){
740     hasFixedCharge = true;
741     }
742     if ( fqa.isFluctuatingCharge() ){
743     hasFluctuatingCharge = true;
744     }
745     if ( pa.isPolarizable() ){
746     hasPolarizable = true;
747     }
748     }
749    
750     if (nRigidBodies > 0 || hasDirectionalAtoms) {
751     storageLayout |= DataStorage::dslAmat;
752     if(storageLayout & DataStorage::dslVelocity) {
753     storageLayout |= DataStorage::dslAngularMomentum;
754     }
755     if (storageLayout & DataStorage::dslForce) {
756     storageLayout |= DataStorage::dslTorque;
757     }
758     }
759 gezelter 1879 if (hasDipoles) {
760     storageLayout |= DataStorage::dslDipole;
761 gezelter 1782 }
762 gezelter 1879 if (hasQuadrupoles) {
763     storageLayout |= DataStorage::dslQuadrupole;
764     }
765 gezelter 1782 if (hasFixedCharge || hasFluctuatingCharge) {
766     storageLayout |= DataStorage::dslSkippedCharge;
767     }
768     if (hasMetallic) {
769     storageLayout |= DataStorage::dslDensity;
770     storageLayout |= DataStorage::dslFunctional;
771     storageLayout |= DataStorage::dslFunctionalDerivative;
772     }
773     if (hasPolarizable) {
774     storageLayout |= DataStorage::dslElectricField;
775     }
776     if (hasFluctuatingCharge){
777     storageLayout |= DataStorage::dslFlucQPosition;
778     if(storageLayout & DataStorage::dslVelocity) {
779     storageLayout |= DataStorage::dslFlucQVelocity;
780     }
781     if (storageLayout & DataStorage::dslForce) {
782     storageLayout |= DataStorage::dslFlucQForce;
783     }
784     }
785    
786     // if the user has asked for them, make sure we've got the memory for the
787     // objects defined.
788    
789     if (simParams->getOutputParticlePotential()) {
790     storageLayout |= DataStorage::dslParticlePot;
791     }
792    
793     if (simParams->havePrintHeatFlux()) {
794     if (simParams->getPrintHeatFlux()) {
795     storageLayout |= DataStorage::dslParticlePot;
796     }
797     }
798    
799 gezelter 1879 if (simParams->getOutputElectricField() | simParams->haveElectricField()) {
800 gezelter 1782 storageLayout |= DataStorage::dslElectricField;
801     }
802 gezelter 1879
803 gezelter 1782 if (simParams->getOutputFluctuatingCharges()) {
804     storageLayout |= DataStorage::dslFlucQPosition;
805     storageLayout |= DataStorage::dslFlucQVelocity;
806     storageLayout |= DataStorage::dslFlucQForce;
807     }
808    
809 gezelter 1879 info->setStorageLayout(storageLayout);
810    
811 gezelter 1782 return storageLayout;
812     }
813    
814 gezelter 403 void SimCreator::setGlobalIndex(SimInfo *info) {
815     SimInfo::MoleculeIterator mi;
816     Molecule::AtomIterator ai;
817     Molecule::RigidBodyIterator ri;
818     Molecule::CutoffGroupIterator ci;
819 gezelter 1953 Molecule::BondIterator boi;
820     Molecule::BendIterator bei;
821     Molecule::TorsionIterator ti;
822     Molecule::InversionIterator ii;
823 tim 1024 Molecule::IntegrableObjectIterator ioi;
824 gezelter 1953 Molecule* mol;
825     Atom* atom;
826     RigidBody* rb;
827     CutoffGroup* cg;
828     Bond* bond;
829     Bend* bend;
830     Torsion* torsion;
831     Inversion* inversion;
832 gezelter 403 int beginAtomIndex;
833     int beginRigidBodyIndex;
834     int beginCutoffGroupIndex;
835 gezelter 1953 int beginBondIndex;
836     int beginBendIndex;
837     int beginTorsionIndex;
838     int beginInversionIndex;
839 gezelter 403 int nGlobalAtoms = info->getNGlobalAtoms();
840 gezelter 1802 int nGlobalRigidBodies = info->getNGlobalRigidBodies();
841 chrisfen 417
842 gezelter 403 beginAtomIndex = 0;
843 gezelter 1953 // The rigid body indices begin immediately after the atom indices:
844 gezelter 1782 beginRigidBodyIndex = info->getNGlobalAtoms();
845 gezelter 403 beginCutoffGroupIndex = 0;
846 gezelter 1953 beginBondIndex = 0;
847     beginBendIndex = 0;
848     beginTorsionIndex = 0;
849     beginInversionIndex = 0;
850    
851 gezelter 1782 for(int i = 0; i < info->getNGlobalMolecules(); i++) {
852 chrisfen 417
853 gezelter 1782 #ifdef IS_MPI
854     if (info->getMolToProc(i) == worldRank) {
855     #endif
856     // stuff to do if I own this molecule
857     mol = info->getMoleculeByGlobalIndex(i);
858    
859 gezelter 1953 // The local index(index in DataStorge) of the atom is important:
860     for(atom = mol->beginAtom(ai); atom != NULL;
861     atom = mol->nextAtom(ai)) {
862 gezelter 1782 atom->setGlobalIndex(beginAtomIndex++);
863     }
864    
865     for(rb = mol->beginRigidBody(ri); rb != NULL;
866     rb = mol->nextRigidBody(ri)) {
867     rb->setGlobalIndex(beginRigidBodyIndex++);
868     }
869    
870 gezelter 1953 // The local index of other objects only depends on the order
871     // of traversal:
872 gezelter 1782 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
873     cg = mol->nextCutoffGroup(ci)) {
874     cg->setGlobalIndex(beginCutoffGroupIndex++);
875     }
876 gezelter 1953 for(bond = mol->beginBond(boi); bond != NULL;
877     bond = mol->nextBond(boi)) {
878     bond->setGlobalIndex(beginBondIndex++);
879     }
880     for(bend = mol->beginBend(bei); bend != NULL;
881     bend = mol->nextBend(bei)) {
882     bend->setGlobalIndex(beginBendIndex++);
883     }
884     for(torsion = mol->beginTorsion(ti); torsion != NULL;
885     torsion = mol->nextTorsion(ti)) {
886     torsion->setGlobalIndex(beginTorsionIndex++);
887     }
888     for(inversion = mol->beginInversion(ii); inversion != NULL;
889     inversion = mol->nextInversion(ii)) {
890     inversion->setGlobalIndex(beginInversionIndex++);
891     }
892 gezelter 1782
893     #ifdef IS_MPI
894     } else {
895    
896     // stuff to do if I don't own this molecule
897    
898     int stampId = info->getMoleculeStampId(i);
899     MoleculeStamp* stamp = info->getMoleculeStamp(stampId);
900    
901     beginAtomIndex += stamp->getNAtoms();
902     beginRigidBodyIndex += stamp->getNRigidBodies();
903     beginCutoffGroupIndex += stamp->getNCutoffGroups() + stamp->getNFreeAtoms();
904 gezelter 1953 beginBondIndex += stamp->getNBonds();
905     beginBendIndex += stamp->getNBends();
906     beginTorsionIndex += stamp->getNTorsions();
907     beginInversionIndex += stamp->getNInversions();
908 gezelter 403 }
909 gezelter 1782 #endif
910    
911     } //end for(int i=0)
912    
913 gezelter 403 //fill globalGroupMembership
914     std::vector<int> globalGroupMembership(info->getNGlobalAtoms(), 0);
915 gezelter 1953 for(mol = info->beginMolecule(mi); mol != NULL;
916     mol = info->nextMolecule(mi)) {
917     for (cg = mol->beginCutoffGroup(ci); cg != NULL;
918     cg = mol->nextCutoffGroup(ci)) {
919 gezelter 403 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
920     globalGroupMembership[atom->getGlobalIndex()] = cg->getGlobalIndex();
921     }
922 chrisfen 417
923 gezelter 403 }
924     }
925 gezelter 1782
926 gezelter 403 #ifdef IS_MPI
927     // Since the globalGroupMembership has been zero filled and we've only
928     // poked values into the atoms we know, we can do an Allreduce
929     // to get the full globalGroupMembership array (We think).
930     // This would be prettier if we could use MPI_IN_PLACE like the MPI-2
931     // docs said we could.
932 gezelter 1313 std::vector<int> tmpGroupMembership(info->getNGlobalAtoms(), 0);
933 gezelter 1969 MPI_Allreduce(&globalGroupMembership[0],
934     &tmpGroupMembership[0], nGlobalAtoms,
935     MPI_INT, MPI_SUM, MPI_COMM_WORLD);
936     // MPI::COMM_WORLD.Allreduce(&globalGroupMembership[0],
937     // &tmpGroupMembership[0], nGlobalAtoms,
938     // MPI::INT, MPI::SUM);
939 gezelter 403 info->setGlobalGroupMembership(tmpGroupMembership);
940     #else
941     info->setGlobalGroupMembership(globalGroupMembership);
942     #endif
943 chrisfen 417
944 gezelter 403 //fill molMembership
945 gezelter 1802 std::vector<int> globalMolMembership(info->getNGlobalAtoms() +
946     info->getNGlobalRigidBodies(), 0);
947 gezelter 403
948 gezelter 1802 for(mol = info->beginMolecule(mi); mol != NULL;
949     mol = info->nextMolecule(mi)) {
950 gezelter 403 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
951     globalMolMembership[atom->getGlobalIndex()] = mol->getGlobalIndex();
952     }
953 gezelter 1802 for (rb = mol->beginRigidBody(ri); rb != NULL;
954     rb = mol->nextRigidBody(ri)) {
955     globalMolMembership[rb->getGlobalIndex()] = mol->getGlobalIndex();
956     }
957 gezelter 403 }
958 chrisfen 417
959 gezelter 403 #ifdef IS_MPI
960 gezelter 1802 std::vector<int> tmpMolMembership(info->getNGlobalAtoms() +
961     info->getNGlobalRigidBodies(), 0);
962 gezelter 1969 MPI_Allreduce(&globalMolMembership[0], &tmpMolMembership[0],
963     nGlobalAtoms + nGlobalRigidBodies,
964     MPI_INT, MPI_SUM, MPI_COMM_WORLD);
965     // MPI::COMM_WORLD.Allreduce(&globalMolMembership[0], &tmpMolMembership[0],
966     // nGlobalAtoms + nGlobalRigidBodies,
967     // MPI::INT, MPI::SUM);
968 chrisfen 417
969 gezelter 403 info->setGlobalMolMembership(tmpMolMembership);
970     #else
971     info->setGlobalMolMembership(globalMolMembership);
972     #endif
973 tim 1024
974     // nIOPerMol holds the number of integrable objects per molecule
975     // here the molecules are listed by their global indices.
976    
977     std::vector<int> nIOPerMol(info->getNGlobalMolecules(), 0);
978 gezelter 1802 for (mol = info->beginMolecule(mi); mol != NULL;
979     mol = info->nextMolecule(mi)) {
980 tim 1024 nIOPerMol[mol->getGlobalIndex()] = mol->getNIntegrableObjects();
981     }
982 chrisfen 417
983 tim 1024 #ifdef IS_MPI
984     std::vector<int> numIntegrableObjectsPerMol(info->getNGlobalMolecules(), 0);
985 gezelter 1969 MPI_Allreduce(&nIOPerMol[0], &numIntegrableObjectsPerMol[0],
986     info->getNGlobalMolecules(), MPI_INT, MPI_SUM, MPI_COMM_WORLD);
987     // MPI::COMM_WORLD.Allreduce(&nIOPerMol[0], &numIntegrableObjectsPerMol[0],
988     // info->getNGlobalMolecules(), MPI::INT, MPI::SUM);
989 tim 1024 #else
990     std::vector<int> numIntegrableObjectsPerMol = nIOPerMol;
991     #endif
992    
993 gezelter 1313 std::vector<int> startingIOIndexForMol(info->getNGlobalMolecules());
994    
995     int startingIndex = 0;
996     for (int i = 0; i < info->getNGlobalMolecules(); i++) {
997     startingIOIndexForMol[i] = startingIndex;
998     startingIndex += numIntegrableObjectsPerMol[i];
999     }
1000    
1001     std::vector<StuntDouble*> IOIndexToIntegrableObject(info->getNGlobalIntegrableObjects(), (StuntDouble*)NULL);
1002 gezelter 1802 for (mol = info->beginMolecule(mi); mol != NULL;
1003     mol = info->nextMolecule(mi)) {
1004 tim 1024 int myGlobalIndex = mol->getGlobalIndex();
1005     int globalIO = startingIOIndexForMol[myGlobalIndex];
1006 gezelter 1782 for (StuntDouble* sd = mol->beginIntegrableObject(ioi); sd != NULL;
1007     sd = mol->nextIntegrableObject(ioi)) {
1008     sd->setGlobalIntegrableObjectIndex(globalIO);
1009     IOIndexToIntegrableObject[globalIO] = sd;
1010 gezelter 1313 globalIO++;
1011 tim 1024 }
1012     }
1013 gezelter 1782
1014 gezelter 1313 info->setIOIndexToIntegrableObject(IOIndexToIntegrableObject);
1015    
1016 gezelter 403 }
1017 chrisfen 417
1018 tim 1024 void SimCreator::loadCoordinates(SimInfo* info, const std::string& mdFileName) {
1019 gezelter 1879
1020 tim 1024 DumpReader reader(info, mdFileName);
1021 gezelter 403 int nframes = reader.getNFrames();
1022 gezelter 1879
1023 gezelter 403 if (nframes > 0) {
1024     reader.readFrame(nframes - 1);
1025     } else {
1026     //invalid initial coordinate file
1027 chrisfen 417 sprintf(painCave.errMsg,
1028     "Initial configuration file %s should at least contain one frame\n",
1029 tim 1024 mdFileName.c_str());
1030 gezelter 403 painCave.isFatal = 1;
1031     simError();
1032     }
1033     //copy the current snapshot to previous snapshot
1034     info->getSnapshotManager()->advance();
1035     }
1036 chrisfen 417
1037 gezelter 1390 } //end namespace OpenMD
1038 gezelter 403
1039    

Properties

Name Value
svn:keywords Author Id Revision Date