ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/SimCreator.cpp
Revision: 1983
Committed: Tue Apr 15 20:36:19 2014 UTC (11 years ago) by gezelter
File size: 34140 byte(s)
Log Message:
Fixes for ConstraintWriter in parallel, some cppcheck cleanup
starting preparation for 2.2 release

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

Properties

Name Value
svn:keywords Author Id Revision Date