# | Line 35 | Line 35 | |
---|---|---|
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, 24107 (2008). |
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 | */ | |
# | Line 44 | Line 44 | |
44 | * @file SimCreator.cpp | |
45 | * @author tlin | |
46 | * @date 11/03/2004 | |
47 | – | * @time 13:51am |
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> | |
# | Line 59 | Line 64 | |
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" | |
# | Line 84 | Line 90 | |
90 | #include "types/FixedChargeAdapter.hpp" | |
91 | #include "types/FluctuatingChargeAdapter.hpp" | |
92 | ||
87 | – | #ifdef IS_MPI |
88 | – | #include "mpi.h" |
89 | – | #include "math/ParallelRandNumGen.hpp" |
90 | – | #endif |
93 | ||
94 | namespace OpenMD { | |
95 | ||
# | Line 100 | Line 102 | namespace OpenMD { | |
102 | #ifdef IS_MPI | |
103 | int streamSize; | |
104 | const int masterNode = 0; | |
105 | < | int commStatus; |
105 | > | |
106 | if (worldRank == masterNode) { | |
107 | < | commStatus = MPI_Bcast(&mdFileVersion, 1, MPI_INT, masterNode, MPI_COMM_WORLD); |
107 | > | MPI_Bcast(&mdFileVersion, 1, MPI_INT, masterNode, MPI_COMM_WORLD); |
108 | #endif | |
109 | SimplePreprocessor preprocessor; | |
110 | < | preprocessor.preprocess(rawMetaDataStream, filename, startOfMetaDataBlock, ppStream); |
110 | > | preprocessor.preprocess(rawMetaDataStream, filename, |
111 | > | startOfMetaDataBlock, ppStream); |
112 | ||
113 | #ifdef IS_MPI | |
114 | < | //brocasting the stream size |
114 | > | //broadcasting the stream size |
115 | streamSize = ppStream.str().size() +1; | |
116 | < | commStatus = MPI_Bcast(&streamSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD); |
117 | < | |
118 | < | commStatus = MPI_Bcast(static_cast<void*>(const_cast<char*>(ppStream.str().c_str())), streamSize, MPI_CHAR, masterNode, MPI_COMM_WORLD); |
116 | < | |
117 | < | |
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 | < | commStatus = MPI_Bcast(&mdFileVersion, 1, MPI_INT, masterNode, MPI_COMM_WORLD); |
121 | > | MPI_Bcast(&mdFileVersion, 1, MPI_INT, masterNode, MPI_COMM_WORLD); |
122 | ||
123 | //get stream size | |
124 | < | commStatus = MPI_Bcast(&streamSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD); |
124 | < | |
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 | < | commStatus = MPI_Bcast(buf, streamSize, MPI_CHAR, masterNode, MPI_COMM_WORLD); |
130 | < | |
129 | > | MPI_Bcast(buf, streamSize, MPI_CHAR, masterNode, MPI_COMM_WORLD); |
130 | > | |
131 | ppStream.str(buf); | |
132 | delete [] buf; | |
133 | – | |
133 | } | |
134 | #endif | |
135 | // Create a scanner that reads from the input stream | |
# | Line 152 | Line 151 | namespace OpenMD { | |
151 | parser.initializeASTFactory(factory); | |
152 | parser.setASTFactory(&factory); | |
153 | parser.mdfile(); | |
155 | – | |
154 | // Create a tree parser that reads information into Globals | |
155 | MDTreeParser treeParser; | |
156 | treeParser.initializeASTFactory(factory); | |
# | Line 255 | Line 253 | namespace OpenMD { | |
253 | std::string mdRawData; | |
254 | int metaDataBlockStart = -1; | |
255 | int metaDataBlockEnd = -1; | |
256 | < | int i; |
257 | < | streamoff mdOffset(0); |
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) { | |
# | Line 354 | Line 369 | namespace OpenMD { | |
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 | < | mdRawData += buffer; |
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 | < | |
386 | > | |
387 | > | if (!foundVersion) mdRawData += version + "\n"; |
388 | > | |
389 | mdFile_.close(); | |
390 | ||
391 | #ifdef IS_MPI | |
# | Line 487 | Line 513 | namespace OpenMD { | |
513 | ||
514 | #ifdef IS_MPI | |
515 | void SimCreator::divideMolecules(SimInfo *info) { | |
490 | – | RealType numerator; |
491 | – | RealType denominator; |
492 | – | RealType precast; |
493 | – | RealType x; |
494 | – | RealType y; |
516 | RealType a; | |
496 | – | int old_atoms; |
497 | – | int add_atoms; |
498 | – | int new_atoms; |
499 | – | int nTarget; |
500 | – | int done; |
501 | – | int i; |
502 | – | int j; |
503 | – | int loops; |
504 | – | int which_proc; |
517 | int nProcessors; | |
518 | std::vector<int> atomsPerProc; | |
519 | int nGlobalMols = info->getNGlobalMolecules(); | |
520 | < | std::vector<int> molToProcMap(nGlobalMols, -1); // default to an error condition: |
520 | > | std::vector<int> molToProcMap(nGlobalMols, -1); // default to an |
521 | > | // error |
522 | > | // condition: |
523 | ||
524 | < | MPI_Comm_size(MPI_COMM_WORLD, &nProcessors); |
524 | > | MPI_Comm_size( MPI_COMM_WORLD, &nProcessors); |
525 | ||
526 | if (nProcessors > nGlobalMols) { | |
527 | sprintf(painCave.errMsg, | |
# | Line 516 | Line 530 | namespace OpenMD { | |
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, nGlobalMols); |
533 | > | "\tsingle-processor version of OpenMD.\n", nProcessors, |
534 | > | nGlobalMols); |
535 | ||
536 | painCave.isFatal = 1; | |
537 | simError(); | |
538 | } | |
539 | ||
525 | – | int seedValue; |
540 | Globals * simParams = info->getSimParams(); | |
541 | < | SeqRandNumGen* myRandom; //divide labor does not need Parallel random number generator |
541 | > | SeqRandNumGen* myRandom; //divide labor does not need Parallel |
542 | > | //random number generator |
543 | if (simParams->haveSeed()) { | |
544 | < | seedValue = simParams->getSeed(); |
544 | > | int seedValue = simParams->getSeed(); |
545 | myRandom = new SeqRandNumGen(seedValue); | |
546 | }else { | |
547 | myRandom = new SeqRandNumGen(); | |
# | Line 539 | Line 554 | namespace OpenMD { | |
554 | atomsPerProc.insert(atomsPerProc.end(), nProcessors, 0); | |
555 | ||
556 | if (worldRank == 0) { | |
557 | < | numerator = info->getNGlobalAtoms(); |
558 | < | denominator = nProcessors; |
559 | < | precast = numerator / denominator; |
560 | < | nTarget = (int)(precast + 0.5); |
557 | > | RealType numerator = info->getNGlobalAtoms(); |
558 | > | RealType denominator = nProcessors; |
559 | > | RealType precast = numerator / denominator; |
560 | > | int nTarget = (int)(precast + 0.5); |
561 | ||
562 | < | for(i = 0; i < nGlobalMols; i++) { |
563 | < | done = 0; |
564 | < | loops = 0; |
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 | < | which_proc = (int) (myRandom->rand() * nProcessors); |
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 | < | old_atoms = atomsPerProc[which_proc]; |
580 | < | add_atoms = moleculeStamp->getNAtoms(); |
581 | < | new_atoms = old_atoms + add_atoms; |
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 | < | "I've tried 100 times to assign molecule %d to a " |
591 | < | " processor, but can't find a good spot.\n" |
592 | < | "I'm assigning it at random to processor %d.\n", |
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 | < | |
594 | > | |
595 | painCave.isFatal = 0; | |
596 | + | painCave.severity = OPENMD_INFO; |
597 | simError(); | |
598 | ||
599 | molToProcMap[i] = which_proc; | |
# | Line 604 | Line 622 | namespace OpenMD { | |
622 | // Pacc(x) = exp(- a * x) | |
623 | // where a = penalty / (average atoms per molecule) | |
624 | ||
625 | < | x = (RealType)(new_atoms - nTarget); |
626 | < | y = myRandom->rand(); |
625 | > | RealType x = (RealType)(new_atoms - nTarget); |
626 | > | RealType y = myRandom->rand(); |
627 | ||
628 | if (y < exp(- a * x)) { | |
629 | molToProcMap[i] = which_proc; | |
# | Line 620 | Line 638 | namespace OpenMD { | |
638 | } | |
639 | ||
640 | delete myRandom; | |
641 | < | |
641 | > | |
642 | // Spray out this nonsense to all other processors: | |
625 | – | |
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: | |
630 | – | |
648 | MPI_Bcast(&molToProcMap[0], nGlobalMols, MPI_INT, 0, MPI_COMM_WORLD); | |
649 | + | |
650 | } | |
651 | ||
652 | info->setMolToProcMap(molToProcMap); | |
# | Line 675 | Line 693 | namespace OpenMD { | |
693 | set<AtomType*>::iterator i; | |
694 | bool hasDirectionalAtoms = false; | |
695 | bool hasFixedCharge = false; | |
696 | < | bool hasMultipoles = false; |
696 | > | bool hasDipoles = false; |
697 | > | bool hasQuadrupoles = false; |
698 | bool hasPolarizable = false; | |
699 | bool hasFluctuatingCharge = false; | |
700 | bool hasMetallic = false; | |
# | Line 697 | Line 716 | namespace OpenMD { | |
716 | if (da.isDirectional()){ | |
717 | hasDirectionalAtoms = true; | |
718 | } | |
719 | < | if (ma.isMultipole()){ |
720 | < | hasMultipoles = true; |
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 | } | |
# | Line 723 | Line 745 | namespace OpenMD { | |
745 | storageLayout |= DataStorage::dslTorque; | |
746 | } | |
747 | } | |
748 | < | if (hasMultipoles) { |
749 | < | storageLayout |= DataStorage::dslElectroFrame; |
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 | } | |
# | Line 760 | Line 785 | namespace OpenMD { | |
785 | } | |
786 | } | |
787 | ||
788 | < | if (simParams->getOutputElectricField()) { |
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 | ||
# | Line 777 | Line 805 | namespace OpenMD { | |
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; |
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 | < | //rigidbody's index begins right after atom's |
832 | > | // The rigid body indices begin immediately after the atom indices: |
833 | beginRigidBodyIndex = info->getNGlobalAtoms(); | |
834 | beginCutoffGroupIndex = 0; | |
835 | < | |
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 | |
# | Line 800 | Line 845 | namespace OpenMD { | |
845 | // stuff to do if I own this molecule | |
846 | mol = info->getMoleculeByGlobalIndex(i); | |
847 | ||
848 | < | //local index(index in DataStorge) of atom is important |
849 | < | for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { |
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 | ||
# | Line 810 | Line 856 | namespace OpenMD { | |
856 | rb->setGlobalIndex(beginRigidBodyIndex++); | |
857 | } | |
858 | ||
859 | < | //local index of cutoff group is trivial, it only depends on |
860 | < | //the order of travesing |
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 { | |
# | Line 828 | Line 890 | namespace OpenMD { | |
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 | ||
# | Line 835 | Line 901 | namespace OpenMD { | |
901 | ||
902 | //fill globalGroupMembership | |
903 | std::vector<int> globalGroupMembership(info->getNGlobalAtoms(), 0); | |
904 | < | for(mol = info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) { |
905 | < | for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) { |
906 | < | |
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 | } | |
# | Line 852 | Line 919 | namespace OpenMD { | |
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], &tmpGroupMembership[0], nGlobalAtoms, |
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(), 0); |
932 | > | std::vector<int> globalMolMembership(info->getNGlobalAtoms() + |
933 | > | info->getNGlobalRigidBodies(), 0); |
934 | ||
935 | < | for(mol = info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) { |
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(), 0); |
948 | < | |
949 | < | MPI_Allreduce(&globalMolMembership[0], &tmpMolMembership[0], nGlobalAtoms, |
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); | |
# | Line 883 | Line 959 | namespace OpenMD { | |
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; mol = info->nextMolecule(mi)) { |
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); |
970 | > | info->getNGlobalMolecules(), MPI_INT, MPI_SUM, MPI_COMM_WORLD); |
971 | #else | |
972 | std::vector<int> numIntegrableObjectsPerMol = nIOPerMol; | |
973 | #endif | |
# | Line 904 | Line 981 | namespace OpenMD { | |
981 | } | |
982 | ||
983 | std::vector<StuntDouble*> IOIndexToIntegrableObject(info->getNGlobalIntegrableObjects(), (StuntDouble*)NULL); | |
984 | < | for (mol = info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) { |
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; | |
# | Line 920 | Line 998 | namespace OpenMD { | |
998 | } | |
999 | ||
1000 | void SimCreator::loadCoordinates(SimInfo* info, const std::string& mdFileName) { | |
923 | – | Globals* simParams; |
924 | – | |
925 | – | simParams = info->getSimParams(); |
1001 | ||
1002 | DumpReader reader(info, mdFileName); | |
1003 | int nframes = reader.getNFrames(); | |
1004 | < | |
1004 | > | |
1005 | if (nframes > 0) { | |
1006 | reader.readFrame(nframes - 1); | |
1007 | } else { |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |