ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/SimCreator.cpp
Revision: 1879
Committed: Sun Jun 16 15:15:42 2013 UTC (11 years, 10 months ago) by gezelter
File size: 32744 byte(s)
Log Message:
MERGE OpenMD development 1783:1878 into trunk

File Contents

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

Properties

Name Value
svn:keywords Author Id Revision Date