ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/brains/SimInfo.cpp
Revision: 2579
Committed: Wed Feb 1 21:06:43 2006 UTC (19 years, 3 months ago) by chrisfen
File size: 44198 byte(s)
Log Message:
Missing brace caused the last commit not to build

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. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 /**
43 * @file SimInfo.cpp
44 * @author tlin
45 * @date 11/02/2004
46 * @version 1.0
47 */
48
49 #include <algorithm>
50 #include <set>
51 #include <map>
52
53 #include "brains/SimInfo.hpp"
54 #include "math/Vector3.hpp"
55 #include "primitives/Molecule.hpp"
56 #include "UseTheForce/fCutoffPolicy.h"
57 #include "UseTheForce/DarkSide/fElectrostaticSummationMethod.h"
58 #include "UseTheForce/DarkSide/fElectrostaticScreeningMethod.h"
59 #include "UseTheForce/DarkSide/fSwitchingFunctionType.h"
60 #include "UseTheForce/doForces_interface.h"
61 #include "UseTheForce/DarkSide/electrostatic_interface.h"
62 #include "UseTheForce/DarkSide/switcheroo_interface.h"
63 #include "utils/MemoryUtils.hpp"
64 #include "utils/simError.h"
65 #include "selection/SelectionManager.hpp"
66 #include "io/ForceFieldOptions.hpp"
67 #include "UseTheForce/ForceField.hpp"
68
69 #ifdef IS_MPI
70 #include "UseTheForce/mpiComponentPlan.h"
71 #include "UseTheForce/DarkSide/simParallel_interface.h"
72 #endif
73
74 namespace oopse {
75 std::set<int> getRigidSet(int index, std::map<int, std::set<int> >& container) {
76 std::map<int, std::set<int> >::iterator i = container.find(index);
77 std::set<int> result;
78 if (i != container.end()) {
79 result = i->second;
80 }
81
82 return result;
83 }
84
85 SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
86 forceField_(ff), simParams_(simParams),
87 ndf_(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
88 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
89 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
90 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nRigidBodies_(0),
91 nIntegrableObjects_(0), nCutoffGroups_(0), nConstraints_(0),
92 sman_(NULL), fortranInitialized_(false) {
93
94 MoleculeStamp* molStamp;
95 int nMolWithSameStamp;
96 int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
97 int nGroups = 0; //total cutoff groups defined in meta-data file
98 CutoffGroupStamp* cgStamp;
99 RigidBodyStamp* rbStamp;
100 int nRigidAtoms = 0;
101 std::vector<Component*> components = simParams->getComponents();
102
103 for (std::vector<Component*>::iterator i = components.begin(); i !=components.end(); ++i) {
104 molStamp = (*i)->getMoleculeStamp();
105 nMolWithSameStamp = (*i)->getNMol();
106
107 addMoleculeStamp(molStamp, nMolWithSameStamp);
108
109 //calculate atoms in molecules
110 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
111
112 //calculate atoms in cutoff groups
113 int nAtomsInGroups = 0;
114 int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
115
116 for (int j=0; j < nCutoffGroupsInStamp; j++) {
117 cgStamp = molStamp->getCutoffGroupStamp(j);
118 nAtomsInGroups += cgStamp->getNMembers();
119 }
120
121 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
122
123 nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
124
125 //calculate atoms in rigid bodies
126 int nAtomsInRigidBodies = 0;
127 int nRigidBodiesInStamp = molStamp->getNRigidBodies();
128
129 for (int j=0; j < nRigidBodiesInStamp; j++) {
130 rbStamp = molStamp->getRigidBodyStamp(j);
131 nAtomsInRigidBodies += rbStamp->getNMembers();
132 }
133
134 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
135 nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
136
137 }
138
139 //every free atom (atom does not belong to cutoff groups) is a cutoff
140 //group therefore the total number of cutoff groups in the system is
141 //equal to the total number of atoms minus number of atoms belong to
142 //cutoff group defined in meta-data file plus the number of cutoff
143 //groups defined in meta-data file
144 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
145
146 //every free atom (atom does not belong to rigid bodies) is an
147 //integrable object therefore the total number of integrable objects
148 //in the system is equal to the total number of atoms minus number of
149 //atoms belong to rigid body defined in meta-data file plus the number
150 //of rigid bodies defined in meta-data file
151 nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
152 + nGlobalRigidBodies_;
153
154 nGlobalMols_ = molStampIds_.size();
155
156 #ifdef IS_MPI
157 molToProcMap_.resize(nGlobalMols_);
158 #endif
159
160 }
161
162 SimInfo::~SimInfo() {
163 std::map<int, Molecule*>::iterator i;
164 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
165 delete i->second;
166 }
167 molecules_.clear();
168
169 delete sman_;
170 delete simParams_;
171 delete forceField_;
172 }
173
174 int SimInfo::getNGlobalConstraints() {
175 int nGlobalConstraints;
176 #ifdef IS_MPI
177 MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
178 MPI_COMM_WORLD);
179 #else
180 nGlobalConstraints = nConstraints_;
181 #endif
182 return nGlobalConstraints;
183 }
184
185 bool SimInfo::addMolecule(Molecule* mol) {
186 MoleculeIterator i;
187
188 i = molecules_.find(mol->getGlobalIndex());
189 if (i == molecules_.end() ) {
190
191 molecules_.insert(std::make_pair(mol->getGlobalIndex(), mol));
192
193 nAtoms_ += mol->getNAtoms();
194 nBonds_ += mol->getNBonds();
195 nBends_ += mol->getNBends();
196 nTorsions_ += mol->getNTorsions();
197 nRigidBodies_ += mol->getNRigidBodies();
198 nIntegrableObjects_ += mol->getNIntegrableObjects();
199 nCutoffGroups_ += mol->getNCutoffGroups();
200 nConstraints_ += mol->getNConstraintPairs();
201
202 addExcludePairs(mol);
203
204 return true;
205 } else {
206 return false;
207 }
208 }
209
210 bool SimInfo::removeMolecule(Molecule* mol) {
211 MoleculeIterator i;
212 i = molecules_.find(mol->getGlobalIndex());
213
214 if (i != molecules_.end() ) {
215
216 assert(mol == i->second);
217
218 nAtoms_ -= mol->getNAtoms();
219 nBonds_ -= mol->getNBonds();
220 nBends_ -= mol->getNBends();
221 nTorsions_ -= mol->getNTorsions();
222 nRigidBodies_ -= mol->getNRigidBodies();
223 nIntegrableObjects_ -= mol->getNIntegrableObjects();
224 nCutoffGroups_ -= mol->getNCutoffGroups();
225 nConstraints_ -= mol->getNConstraintPairs();
226
227 removeExcludePairs(mol);
228 molecules_.erase(mol->getGlobalIndex());
229
230 delete mol;
231
232 return true;
233 } else {
234 return false;
235 }
236
237
238 }
239
240
241 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
242 i = molecules_.begin();
243 return i == molecules_.end() ? NULL : i->second;
244 }
245
246 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
247 ++i;
248 return i == molecules_.end() ? NULL : i->second;
249 }
250
251
252 void SimInfo::calcNdf() {
253 int ndf_local;
254 MoleculeIterator i;
255 std::vector<StuntDouble*>::iterator j;
256 Molecule* mol;
257 StuntDouble* integrableObject;
258
259 ndf_local = 0;
260
261 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
262 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
263 integrableObject = mol->nextIntegrableObject(j)) {
264
265 ndf_local += 3;
266
267 if (integrableObject->isDirectional()) {
268 if (integrableObject->isLinear()) {
269 ndf_local += 2;
270 } else {
271 ndf_local += 3;
272 }
273 }
274
275 }
276 }
277
278 // n_constraints is local, so subtract them on each processor
279 ndf_local -= nConstraints_;
280
281 #ifdef IS_MPI
282 MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
283 #else
284 ndf_ = ndf_local;
285 #endif
286
287 // nZconstraints_ is global, as are the 3 COM translations for the
288 // entire system:
289 ndf_ = ndf_ - 3 - nZconstraint_;
290
291 }
292
293 void SimInfo::calcNdfRaw() {
294 int ndfRaw_local;
295
296 MoleculeIterator i;
297 std::vector<StuntDouble*>::iterator j;
298 Molecule* mol;
299 StuntDouble* integrableObject;
300
301 // Raw degrees of freedom that we have to set
302 ndfRaw_local = 0;
303
304 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
305 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
306 integrableObject = mol->nextIntegrableObject(j)) {
307
308 ndfRaw_local += 3;
309
310 if (integrableObject->isDirectional()) {
311 if (integrableObject->isLinear()) {
312 ndfRaw_local += 2;
313 } else {
314 ndfRaw_local += 3;
315 }
316 }
317
318 }
319 }
320
321 #ifdef IS_MPI
322 MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
323 #else
324 ndfRaw_ = ndfRaw_local;
325 #endif
326 }
327
328 void SimInfo::calcNdfTrans() {
329 int ndfTrans_local;
330
331 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
332
333
334 #ifdef IS_MPI
335 MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
336 #else
337 ndfTrans_ = ndfTrans_local;
338 #endif
339
340 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
341
342 }
343
344 void SimInfo::addExcludePairs(Molecule* mol) {
345 std::vector<Bond*>::iterator bondIter;
346 std::vector<Bend*>::iterator bendIter;
347 std::vector<Torsion*>::iterator torsionIter;
348 Bond* bond;
349 Bend* bend;
350 Torsion* torsion;
351 int a;
352 int b;
353 int c;
354 int d;
355
356 std::map<int, std::set<int> > atomGroups;
357
358 Molecule::RigidBodyIterator rbIter;
359 RigidBody* rb;
360 Molecule::IntegrableObjectIterator ii;
361 StuntDouble* integrableObject;
362
363 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
364 integrableObject = mol->nextIntegrableObject(ii)) {
365
366 if (integrableObject->isRigidBody()) {
367 rb = static_cast<RigidBody*>(integrableObject);
368 std::vector<Atom*> atoms = rb->getAtoms();
369 std::set<int> rigidAtoms;
370 for (int i = 0; i < atoms.size(); ++i) {
371 rigidAtoms.insert(atoms[i]->getGlobalIndex());
372 }
373 for (int i = 0; i < atoms.size(); ++i) {
374 atomGroups.insert(std::map<int, std::set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
375 }
376 } else {
377 std::set<int> oneAtomSet;
378 oneAtomSet.insert(integrableObject->getGlobalIndex());
379 atomGroups.insert(std::map<int, std::set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
380 }
381 }
382
383
384
385 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
386 a = bond->getAtomA()->getGlobalIndex();
387 b = bond->getAtomB()->getGlobalIndex();
388 exclude_.addPair(a, b);
389 }
390
391 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
392 a = bend->getAtomA()->getGlobalIndex();
393 b = bend->getAtomB()->getGlobalIndex();
394 c = bend->getAtomC()->getGlobalIndex();
395 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
396 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
397 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
398
399 exclude_.addPairs(rigidSetA, rigidSetB);
400 exclude_.addPairs(rigidSetA, rigidSetC);
401 exclude_.addPairs(rigidSetB, rigidSetC);
402
403 //exclude_.addPair(a, b);
404 //exclude_.addPair(a, c);
405 //exclude_.addPair(b, c);
406 }
407
408 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
409 a = torsion->getAtomA()->getGlobalIndex();
410 b = torsion->getAtomB()->getGlobalIndex();
411 c = torsion->getAtomC()->getGlobalIndex();
412 d = torsion->getAtomD()->getGlobalIndex();
413 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
414 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
415 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
416 std::set<int> rigidSetD = getRigidSet(d, atomGroups);
417
418 exclude_.addPairs(rigidSetA, rigidSetB);
419 exclude_.addPairs(rigidSetA, rigidSetC);
420 exclude_.addPairs(rigidSetA, rigidSetD);
421 exclude_.addPairs(rigidSetB, rigidSetC);
422 exclude_.addPairs(rigidSetB, rigidSetD);
423 exclude_.addPairs(rigidSetC, rigidSetD);
424
425 /*
426 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end());
427 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end());
428 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end());
429 exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end());
430 exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end());
431 exclude_.addPairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end());
432
433
434 exclude_.addPair(a, b);
435 exclude_.addPair(a, c);
436 exclude_.addPair(a, d);
437 exclude_.addPair(b, c);
438 exclude_.addPair(b, d);
439 exclude_.addPair(c, d);
440 */
441 }
442
443 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
444 std::vector<Atom*> atoms = rb->getAtoms();
445 for (int i = 0; i < atoms.size() -1 ; ++i) {
446 for (int j = i + 1; j < atoms.size(); ++j) {
447 a = atoms[i]->getGlobalIndex();
448 b = atoms[j]->getGlobalIndex();
449 exclude_.addPair(a, b);
450 }
451 }
452 }
453
454 }
455
456 void SimInfo::removeExcludePairs(Molecule* mol) {
457 std::vector<Bond*>::iterator bondIter;
458 std::vector<Bend*>::iterator bendIter;
459 std::vector<Torsion*>::iterator torsionIter;
460 Bond* bond;
461 Bend* bend;
462 Torsion* torsion;
463 int a;
464 int b;
465 int c;
466 int d;
467
468 std::map<int, std::set<int> > atomGroups;
469
470 Molecule::RigidBodyIterator rbIter;
471 RigidBody* rb;
472 Molecule::IntegrableObjectIterator ii;
473 StuntDouble* integrableObject;
474
475 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
476 integrableObject = mol->nextIntegrableObject(ii)) {
477
478 if (integrableObject->isRigidBody()) {
479 rb = static_cast<RigidBody*>(integrableObject);
480 std::vector<Atom*> atoms = rb->getAtoms();
481 std::set<int> rigidAtoms;
482 for (int i = 0; i < atoms.size(); ++i) {
483 rigidAtoms.insert(atoms[i]->getGlobalIndex());
484 }
485 for (int i = 0; i < atoms.size(); ++i) {
486 atomGroups.insert(std::map<int, std::set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
487 }
488 } else {
489 std::set<int> oneAtomSet;
490 oneAtomSet.insert(integrableObject->getGlobalIndex());
491 atomGroups.insert(std::map<int, std::set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
492 }
493 }
494
495
496 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
497 a = bond->getAtomA()->getGlobalIndex();
498 b = bond->getAtomB()->getGlobalIndex();
499 exclude_.removePair(a, b);
500 }
501
502 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
503 a = bend->getAtomA()->getGlobalIndex();
504 b = bend->getAtomB()->getGlobalIndex();
505 c = bend->getAtomC()->getGlobalIndex();
506
507 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
508 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
509 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
510
511 exclude_.removePairs(rigidSetA, rigidSetB);
512 exclude_.removePairs(rigidSetA, rigidSetC);
513 exclude_.removePairs(rigidSetB, rigidSetC);
514
515 //exclude_.removePair(a, b);
516 //exclude_.removePair(a, c);
517 //exclude_.removePair(b, c);
518 }
519
520 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
521 a = torsion->getAtomA()->getGlobalIndex();
522 b = torsion->getAtomB()->getGlobalIndex();
523 c = torsion->getAtomC()->getGlobalIndex();
524 d = torsion->getAtomD()->getGlobalIndex();
525
526 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
527 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
528 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
529 std::set<int> rigidSetD = getRigidSet(d, atomGroups);
530
531 exclude_.removePairs(rigidSetA, rigidSetB);
532 exclude_.removePairs(rigidSetA, rigidSetC);
533 exclude_.removePairs(rigidSetA, rigidSetD);
534 exclude_.removePairs(rigidSetB, rigidSetC);
535 exclude_.removePairs(rigidSetB, rigidSetD);
536 exclude_.removePairs(rigidSetC, rigidSetD);
537
538 /*
539 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end());
540 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end());
541 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end());
542 exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end());
543 exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end());
544 exclude_.removePairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end());
545
546
547 exclude_.removePair(a, b);
548 exclude_.removePair(a, c);
549 exclude_.removePair(a, d);
550 exclude_.removePair(b, c);
551 exclude_.removePair(b, d);
552 exclude_.removePair(c, d);
553 */
554 }
555
556 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
557 std::vector<Atom*> atoms = rb->getAtoms();
558 for (int i = 0; i < atoms.size() -1 ; ++i) {
559 for (int j = i + 1; j < atoms.size(); ++j) {
560 a = atoms[i]->getGlobalIndex();
561 b = atoms[j]->getGlobalIndex();
562 exclude_.removePair(a, b);
563 }
564 }
565 }
566
567 }
568
569
570 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
571 int curStampId;
572
573 //index from 0
574 curStampId = moleculeStamps_.size();
575
576 moleculeStamps_.push_back(molStamp);
577 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
578 }
579
580 void SimInfo::update() {
581
582 setupSimType();
583
584 #ifdef IS_MPI
585 setupFortranParallel();
586 #endif
587
588 setupFortranSim();
589
590 //setup fortran force field
591 /** @deprecate */
592 int isError = 0;
593
594 setupElectrostaticSummationMethod( isError );
595 setupSwitchingFunction();
596
597 if(isError){
598 sprintf( painCave.errMsg,
599 "ForceField error: There was an error initializing the forceField in fortran.\n" );
600 painCave.isFatal = 1;
601 simError();
602 }
603
604
605 setupCutoff();
606
607 calcNdf();
608 calcNdfRaw();
609 calcNdfTrans();
610
611 fortranInitialized_ = true;
612 }
613
614 std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
615 SimInfo::MoleculeIterator mi;
616 Molecule* mol;
617 Molecule::AtomIterator ai;
618 Atom* atom;
619 std::set<AtomType*> atomTypes;
620
621 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
622
623 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
624 atomTypes.insert(atom->getAtomType());
625 }
626
627 }
628
629 return atomTypes;
630 }
631
632 void SimInfo::setupSimType() {
633 std::set<AtomType*>::iterator i;
634 std::set<AtomType*> atomTypes;
635 atomTypes = getUniqueAtomTypes();
636
637 int useLennardJones = 0;
638 int useElectrostatic = 0;
639 int useEAM = 0;
640 int useSC = 0;
641 int useCharge = 0;
642 int useDirectional = 0;
643 int useDipole = 0;
644 int useGayBerne = 0;
645 int useSticky = 0;
646 int useStickyPower = 0;
647 int useShape = 0;
648 int useFLARB = 0; //it is not in AtomType yet
649 int useDirectionalAtom = 0;
650 int useElectrostatics = 0;
651 //usePBC and useRF are from simParams
652 int usePBC = simParams_->getUsePeriodicBoundaryConditions();
653 int useRF;
654 int useSF;
655 std::string myMethod;
656
657 // set the useRF logical
658 useRF = 0;
659 useSF = 0;
660
661
662 if (simParams_->haveElectrostaticSummationMethod()) {
663 std::string myMethod = simParams_->getElectrostaticSummationMethod();
664 toUpper(myMethod);
665 if (myMethod == "REACTION_FIELD") {
666 useRF=1;
667 } else {
668 if (myMethod == "SHIFTED_FORCE") {
669 useSF = 1;
670 }
671 }
672 }
673
674 //loop over all of the atom types
675 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
676 useLennardJones |= (*i)->isLennardJones();
677 useElectrostatic |= (*i)->isElectrostatic();
678 useEAM |= (*i)->isEAM();
679 useSC |= (*i)->isSC();
680 useCharge |= (*i)->isCharge();
681 useDirectional |= (*i)->isDirectional();
682 useDipole |= (*i)->isDipole();
683 useGayBerne |= (*i)->isGayBerne();
684 useSticky |= (*i)->isSticky();
685 useStickyPower |= (*i)->isStickyPower();
686 useShape |= (*i)->isShape();
687 }
688
689 if (useSticky || useStickyPower || useDipole || useGayBerne || useShape) {
690 useDirectionalAtom = 1;
691 }
692
693 if (useCharge || useDipole) {
694 useElectrostatics = 1;
695 }
696
697 #ifdef IS_MPI
698 int temp;
699
700 temp = usePBC;
701 MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
702
703 temp = useDirectionalAtom;
704 MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
705
706 temp = useLennardJones;
707 MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
708
709 temp = useElectrostatics;
710 MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
711
712 temp = useCharge;
713 MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
714
715 temp = useDipole;
716 MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
717
718 temp = useSticky;
719 MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
720
721 temp = useStickyPower;
722 MPI_Allreduce(&temp, &useStickyPower, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
723
724 temp = useGayBerne;
725 MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
726
727 temp = useEAM;
728 MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
729
730 temp = useSC;
731 MPI_Allreduce(&temp, &useSC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
732
733 temp = useShape;
734 MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
735
736 temp = useFLARB;
737 MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
738
739 temp = useRF;
740 MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
741
742 temp = useSF;
743 MPI_Allreduce(&temp, &useSF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
744
745 #endif
746
747 fInfo_.SIM_uses_PBC = usePBC;
748 fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
749 fInfo_.SIM_uses_LennardJones = useLennardJones;
750 fInfo_.SIM_uses_Electrostatics = useElectrostatics;
751 fInfo_.SIM_uses_Charges = useCharge;
752 fInfo_.SIM_uses_Dipoles = useDipole;
753 fInfo_.SIM_uses_Sticky = useSticky;
754 fInfo_.SIM_uses_StickyPower = useStickyPower;
755 fInfo_.SIM_uses_GayBerne = useGayBerne;
756 fInfo_.SIM_uses_EAM = useEAM;
757 fInfo_.SIM_uses_SC = useSC;
758 fInfo_.SIM_uses_Shapes = useShape;
759 fInfo_.SIM_uses_FLARB = useFLARB;
760 fInfo_.SIM_uses_RF = useRF;
761 fInfo_.SIM_uses_SF = useSF;
762
763 if( myMethod == "REACTION_FIELD") {
764
765 if (simParams_->haveDielectric()) {
766 fInfo_.dielect = simParams_->getDielectric();
767 } else {
768 sprintf(painCave.errMsg,
769 "SimSetup Error: No Dielectric constant was set.\n"
770 "\tYou are trying to use Reaction Field without"
771 "\tsetting a dielectric constant!\n");
772 painCave.isFatal = 1;
773 simError();
774 }
775 }
776
777 }
778
779 void SimInfo::setupFortranSim() {
780 int isError;
781 int nExclude;
782 std::vector<int> fortranGlobalGroupMembership;
783
784 nExclude = exclude_.getSize();
785 isError = 0;
786
787 //globalGroupMembership_ is filled by SimCreator
788 for (int i = 0; i < nGlobalAtoms_; i++) {
789 fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
790 }
791
792 //calculate mass ratio of cutoff group
793 std::vector<double> mfact;
794 SimInfo::MoleculeIterator mi;
795 Molecule* mol;
796 Molecule::CutoffGroupIterator ci;
797 CutoffGroup* cg;
798 Molecule::AtomIterator ai;
799 Atom* atom;
800 double totalMass;
801
802 //to avoid memory reallocation, reserve enough space for mfact
803 mfact.reserve(getNCutoffGroups());
804
805 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
806 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
807
808 totalMass = cg->getMass();
809 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
810 // Check for massless groups - set mfact to 1 if true
811 if (totalMass != 0)
812 mfact.push_back(atom->getMass()/totalMass);
813 else
814 mfact.push_back( 1.0 );
815 }
816
817 }
818 }
819
820 //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
821 std::vector<int> identArray;
822
823 //to avoid memory reallocation, reserve enough space identArray
824 identArray.reserve(getNAtoms());
825
826 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
827 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
828 identArray.push_back(atom->getIdent());
829 }
830 }
831
832 //fill molMembershipArray
833 //molMembershipArray is filled by SimCreator
834 std::vector<int> molMembershipArray(nGlobalAtoms_);
835 for (int i = 0; i < nGlobalAtoms_; i++) {
836 molMembershipArray[i] = globalMolMembership_[i] + 1;
837 }
838
839 //setup fortran simulation
840 int nGlobalExcludes = 0;
841 int* globalExcludes = NULL;
842 int* excludeList = exclude_.getExcludeList();
843 setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, excludeList ,
844 &nGlobalExcludes, globalExcludes, &molMembershipArray[0],
845 &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
846
847 if( isError ){
848
849 sprintf( painCave.errMsg,
850 "There was an error setting the simulation information in fortran.\n" );
851 painCave.isFatal = 1;
852 painCave.severity = OOPSE_ERROR;
853 simError();
854 }
855
856 #ifdef IS_MPI
857 sprintf( checkPointMsg,
858 "succesfully sent the simulation information to fortran.\n");
859 MPIcheckPoint();
860 #endif // is_mpi
861 }
862
863
864 #ifdef IS_MPI
865 void SimInfo::setupFortranParallel() {
866
867 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
868 std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
869 std::vector<int> localToGlobalCutoffGroupIndex;
870 SimInfo::MoleculeIterator mi;
871 Molecule::AtomIterator ai;
872 Molecule::CutoffGroupIterator ci;
873 Molecule* mol;
874 Atom* atom;
875 CutoffGroup* cg;
876 mpiSimData parallelData;
877 int isError;
878
879 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
880
881 //local index(index in DataStorge) of atom is important
882 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
883 localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
884 }
885
886 //local index of cutoff group is trivial, it only depends on the order of travesing
887 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
888 localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
889 }
890
891 }
892
893 //fill up mpiSimData struct
894 parallelData.nMolGlobal = getNGlobalMolecules();
895 parallelData.nMolLocal = getNMolecules();
896 parallelData.nAtomsGlobal = getNGlobalAtoms();
897 parallelData.nAtomsLocal = getNAtoms();
898 parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
899 parallelData.nGroupsLocal = getNCutoffGroups();
900 parallelData.myNode = worldRank;
901 MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
902
903 //pass mpiSimData struct and index arrays to fortran
904 setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
905 &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal),
906 &localToGlobalCutoffGroupIndex[0], &isError);
907
908 if (isError) {
909 sprintf(painCave.errMsg,
910 "mpiRefresh errror: fortran didn't like something we gave it.\n");
911 painCave.isFatal = 1;
912 simError();
913 }
914
915 sprintf(checkPointMsg, " mpiRefresh successful.\n");
916 MPIcheckPoint();
917
918
919 }
920
921 #endif
922
923 void SimInfo::setupCutoff() {
924
925 ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
926
927 // Check the cutoff policy
928 int cp = TRADITIONAL_CUTOFF_POLICY; // Set to traditional by default
929
930 std::string myPolicy;
931 if (forceFieldOptions_.haveCutoffPolicy()){
932 myPolicy = forceFieldOptions_.getCutoffPolicy();
933 }else if (simParams_->haveCutoffPolicy()) {
934 myPolicy = simParams_->getCutoffPolicy();
935 }
936
937 if (!myPolicy.empty()){
938 toUpper(myPolicy);
939 if (myPolicy == "MIX") {
940 cp = MIX_CUTOFF_POLICY;
941 } else {
942 if (myPolicy == "MAX") {
943 cp = MAX_CUTOFF_POLICY;
944 } else {
945 if (myPolicy == "TRADITIONAL") {
946 cp = TRADITIONAL_CUTOFF_POLICY;
947 } else {
948 // throw error
949 sprintf( painCave.errMsg,
950 "SimInfo error: Unknown cutoffPolicy. (Input file specified %s .)\n\tcutoffPolicy must be one of: \"Mix\", \"Max\", or \"Traditional\".", myPolicy.c_str() );
951 painCave.isFatal = 1;
952 simError();
953 }
954 }
955 }
956 }
957 notifyFortranCutoffPolicy(&cp);
958
959 // Check the Skin Thickness for neighborlists
960 double skin;
961 if (simParams_->haveSkinThickness()) {
962 skin = simParams_->getSkinThickness();
963 notifyFortranSkinThickness(&skin);
964 }
965
966 // Check if the cutoff was set explicitly:
967 if (simParams_->haveCutoffRadius()) {
968 rcut_ = simParams_->getCutoffRadius();
969 if (simParams_->haveSwitchingRadius()) {
970 rsw_ = simParams_->getSwitchingRadius();
971 } else {
972 if (fInfo_.SIM_uses_Charges |
973 fInfo_.SIM_uses_Dipoles |
974 fInfo_.SIM_uses_RF) {
975
976 rsw_ = 0.85 * rcut_;
977 sprintf(painCave.errMsg,
978 "SimCreator Warning: No value was set for the switchingRadius.\n"
979 "\tOOPSE will use a default value of 85 percent of the cutoffRadius.\n"
980 "\tswitchingRadius = %f. for this simulation\n", rsw_);
981 painCave.isFatal = 0;
982 simError();
983 } else {
984 rsw_ = rcut_;
985 sprintf(painCave.errMsg,
986 "SimCreator Warning: No value was set for the switchingRadius.\n"
987 "\tOOPSE will use the same value as the cutoffRadius.\n"
988 "\tswitchingRadius = %f. for this simulation\n", rsw_);
989 painCave.isFatal = 0;
990 simError();
991 }
992 }
993
994 notifyFortranCutoffs(&rcut_, &rsw_);
995
996 } else {
997
998 // For electrostatic atoms, we'll assume a large safe value:
999 if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
1000 sprintf(painCave.errMsg,
1001 "SimCreator Warning: No value was set for the cutoffRadius.\n"
1002 "\tOOPSE will use a default value of 15.0 angstroms"
1003 "\tfor the cutoffRadius.\n");
1004 painCave.isFatal = 0;
1005 simError();
1006 rcut_ = 15.0;
1007
1008 if (simParams_->haveElectrostaticSummationMethod()) {
1009 std::string myMethod = simParams_->getElectrostaticSummationMethod();
1010 toUpper(myMethod);
1011 if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") {
1012 if (simParams_->haveSwitchingRadius()){
1013 sprintf(painCave.errMsg,
1014 "SimInfo Warning: A value was set for the switchingRadius\n"
1015 "\teven though the electrostaticSummationMethod was\n"
1016 "\tset to %s\n", myMethod.c_str());
1017 painCave.isFatal = 1;
1018 simError();
1019 }
1020 }
1021 }
1022
1023 if (simParams_->haveSwitchingRadius()){
1024 rsw_ = simParams_->getSwitchingRadius();
1025 } else {
1026 sprintf(painCave.errMsg,
1027 "SimCreator Warning: No value was set for switchingRadius.\n"
1028 "\tOOPSE will use a default value of\n"
1029 "\t0.85 * cutoffRadius for the switchingRadius\n");
1030 painCave.isFatal = 0;
1031 simError();
1032 rsw_ = 0.85 * rcut_;
1033 }
1034 notifyFortranCutoffs(&rcut_, &rsw_);
1035 } else {
1036 // We didn't set rcut explicitly, and we don't have electrostatic atoms, so
1037 // We'll punt and let fortran figure out the cutoffs later.
1038
1039 notifyFortranYouAreOnYourOwn();
1040
1041 }
1042 }
1043 }
1044
1045 void SimInfo::setupElectrostaticSummationMethod( int isError ) {
1046
1047 int errorOut;
1048 int esm = NONE;
1049 int sm = UNDAMPED;
1050 double alphaVal;
1051 double dielectric;
1052
1053 errorOut = isError;
1054 alphaVal = simParams_->getDampingAlpha();
1055 dielectric = simParams_->getDielectric();
1056
1057 if (simParams_->haveElectrostaticSummationMethod()) {
1058 std::string myMethod = simParams_->getElectrostaticSummationMethod();
1059 toUpper(myMethod);
1060 if (myMethod == "NONE") {
1061 esm = NONE;
1062 } else {
1063 if (myMethod == "SWITCHING_FUNCTION") {
1064 esm = SWITCHING_FUNCTION;
1065 } else {
1066 if (myMethod == "SHIFTED_POTENTIAL") {
1067 esm = SHIFTED_POTENTIAL;
1068 } else {
1069 if (myMethod == "SHIFTED_FORCE") {
1070 esm = SHIFTED_FORCE;
1071 } else {
1072 if (myMethod == "REACTION_FIELD") {
1073 esm = REACTION_FIELD;
1074 } else {
1075 // throw error
1076 sprintf( painCave.errMsg,
1077 "SimInfo error: Unknown electrostaticSummationMethod.\n"
1078 "\t(Input file specified %s .)\n"
1079 "\telectrostaticSummationMethod must be one of: \"none\",\n"
1080 "\t\"shifted_potential\", \"shifted_force\", or \n"
1081 "\t\"reaction_field\".\n", myMethod.c_str() );
1082 painCave.isFatal = 1;
1083 simError();
1084 }
1085 }
1086 }
1087 }
1088 }
1089 }
1090
1091 if (simParams_->haveElectrostaticScreeningMethod()) {
1092 std::string myScreen = simParams_->getElectrostaticScreeningMethod();
1093 toUpper(myScreen);
1094 if (myScreen == "UNDAMPED") {
1095 sm = UNDAMPED;
1096 } else {
1097 if (myScreen == "DAMPED") {
1098 sm = DAMPED;
1099 if (!simParams_->haveDampingAlpha()) {
1100 //throw error
1101 sprintf( painCave.errMsg,
1102 "SimInfo warning: dampingAlpha was not specified in the input file.\n"
1103 "\tA default value of %f (1/ang) will be used.\n", alphaVal);
1104 painCave.isFatal = 0;
1105 simError();
1106 }
1107 } else {
1108 // throw error
1109 sprintf( painCave.errMsg,
1110 "SimInfo error: Unknown electrostaticScreeningMethod.\n"
1111 "\t(Input file specified %s .)\n"
1112 "\telectrostaticScreeningMethod must be one of: \"undamped\"\n"
1113 "or \"damped\".\n", myScreen.c_str() );
1114 painCave.isFatal = 1;
1115 simError();
1116 }
1117 }
1118 }
1119
1120 // let's pass some summation method variables to fortran
1121 setElectrostaticSummationMethod( &esm );
1122 setFortranElectrostaticMethod( &esm );
1123 setScreeningMethod( &sm );
1124 setDampingAlpha( &alphaVal );
1125 setReactionFieldDielectric( &dielectric );
1126 initFortranFF( &errorOut );
1127 }
1128
1129 void SimInfo::setupSwitchingFunction() {
1130 int ft = CUBIC;
1131
1132 if (simParams_->haveSwitchingFunctionType()) {
1133 std::string funcType = simParams_->getSwitchingFunctionType();
1134 toUpper(funcType);
1135 if (funcType == "CUBIC") {
1136 ft = CUBIC;
1137 } else {
1138 if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
1139 ft = FIFTH_ORDER_POLY;
1140 } else {
1141 // throw error
1142 sprintf( painCave.errMsg,
1143 "SimInfo error: Unknown switchingFunctionType. (Input file specified %s .)\n\tswitchingFunctionType must be one of: \"cubic\" or \"fifth_order_polynomial\".", funcType.c_str() );
1144 painCave.isFatal = 1;
1145 simError();
1146 }
1147 }
1148 }
1149
1150 // send switching function notification to switcheroo
1151 setFunctionType(&ft);
1152
1153 }
1154
1155 void SimInfo::addProperty(GenericData* genData) {
1156 properties_.addProperty(genData);
1157 }
1158
1159 void SimInfo::removeProperty(const std::string& propName) {
1160 properties_.removeProperty(propName);
1161 }
1162
1163 void SimInfo::clearProperties() {
1164 properties_.clearProperties();
1165 }
1166
1167 std::vector<std::string> SimInfo::getPropertyNames() {
1168 return properties_.getPropertyNames();
1169 }
1170
1171 std::vector<GenericData*> SimInfo::getProperties() {
1172 return properties_.getProperties();
1173 }
1174
1175 GenericData* SimInfo::getPropertyByName(const std::string& propName) {
1176 return properties_.getPropertyByName(propName);
1177 }
1178
1179 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
1180 if (sman_ == sman) {
1181 return;
1182 }
1183 delete sman_;
1184 sman_ = sman;
1185
1186 Molecule* mol;
1187 RigidBody* rb;
1188 Atom* atom;
1189 SimInfo::MoleculeIterator mi;
1190 Molecule::RigidBodyIterator rbIter;
1191 Molecule::AtomIterator atomIter;;
1192
1193 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
1194
1195 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
1196 atom->setSnapshotManager(sman_);
1197 }
1198
1199 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
1200 rb->setSnapshotManager(sman_);
1201 }
1202 }
1203
1204 }
1205
1206 Vector3d SimInfo::getComVel(){
1207 SimInfo::MoleculeIterator i;
1208 Molecule* mol;
1209
1210 Vector3d comVel(0.0);
1211 double totalMass = 0.0;
1212
1213
1214 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1215 double mass = mol->getMass();
1216 totalMass += mass;
1217 comVel += mass * mol->getComVel();
1218 }
1219
1220 #ifdef IS_MPI
1221 double tmpMass = totalMass;
1222 Vector3d tmpComVel(comVel);
1223 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1224 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1225 #endif
1226
1227 comVel /= totalMass;
1228
1229 return comVel;
1230 }
1231
1232 Vector3d SimInfo::getCom(){
1233 SimInfo::MoleculeIterator i;
1234 Molecule* mol;
1235
1236 Vector3d com(0.0);
1237 double totalMass = 0.0;
1238
1239 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1240 double mass = mol->getMass();
1241 totalMass += mass;
1242 com += mass * mol->getCom();
1243 }
1244
1245 #ifdef IS_MPI
1246 double tmpMass = totalMass;
1247 Vector3d tmpCom(com);
1248 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1249 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1250 #endif
1251
1252 com /= totalMass;
1253
1254 return com;
1255
1256 }
1257
1258 std::ostream& operator <<(std::ostream& o, SimInfo& info) {
1259
1260 return o;
1261 }
1262
1263
1264 /*
1265 Returns center of mass and center of mass velocity in one function call.
1266 */
1267
1268 void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1269 SimInfo::MoleculeIterator i;
1270 Molecule* mol;
1271
1272
1273 double totalMass = 0.0;
1274
1275
1276 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1277 double mass = mol->getMass();
1278 totalMass += mass;
1279 com += mass * mol->getCom();
1280 comVel += mass * mol->getComVel();
1281 }
1282
1283 #ifdef IS_MPI
1284 double tmpMass = totalMass;
1285 Vector3d tmpCom(com);
1286 Vector3d tmpComVel(comVel);
1287 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1288 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1289 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1290 #endif
1291
1292 com /= totalMass;
1293 comVel /= totalMass;
1294 }
1295
1296 /*
1297 Return intertia tensor for entire system and angular momentum Vector.
1298
1299
1300 [ Ixx -Ixy -Ixz ]
1301 J =| -Iyx Iyy -Iyz |
1302 [ -Izx -Iyz Izz ]
1303 */
1304
1305 void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1306
1307
1308 double xx = 0.0;
1309 double yy = 0.0;
1310 double zz = 0.0;
1311 double xy = 0.0;
1312 double xz = 0.0;
1313 double yz = 0.0;
1314 Vector3d com(0.0);
1315 Vector3d comVel(0.0);
1316
1317 getComAll(com, comVel);
1318
1319 SimInfo::MoleculeIterator i;
1320 Molecule* mol;
1321
1322 Vector3d thisq(0.0);
1323 Vector3d thisv(0.0);
1324
1325 double thisMass = 0.0;
1326
1327
1328
1329
1330 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1331
1332 thisq = mol->getCom()-com;
1333 thisv = mol->getComVel()-comVel;
1334 thisMass = mol->getMass();
1335 // Compute moment of intertia coefficients.
1336 xx += thisq[0]*thisq[0]*thisMass;
1337 yy += thisq[1]*thisq[1]*thisMass;
1338 zz += thisq[2]*thisq[2]*thisMass;
1339
1340 // compute products of intertia
1341 xy += thisq[0]*thisq[1]*thisMass;
1342 xz += thisq[0]*thisq[2]*thisMass;
1343 yz += thisq[1]*thisq[2]*thisMass;
1344
1345 angularMomentum += cross( thisq, thisv ) * thisMass;
1346
1347 }
1348
1349
1350 inertiaTensor(0,0) = yy + zz;
1351 inertiaTensor(0,1) = -xy;
1352 inertiaTensor(0,2) = -xz;
1353 inertiaTensor(1,0) = -xy;
1354 inertiaTensor(1,1) = xx + zz;
1355 inertiaTensor(1,2) = -yz;
1356 inertiaTensor(2,0) = -xz;
1357 inertiaTensor(2,1) = -yz;
1358 inertiaTensor(2,2) = xx + yy;
1359
1360 #ifdef IS_MPI
1361 Mat3x3d tmpI(inertiaTensor);
1362 Vector3d tmpAngMom;
1363 MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1364 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1365 #endif
1366
1367 return;
1368 }
1369
1370 //Returns the angular momentum of the system
1371 Vector3d SimInfo::getAngularMomentum(){
1372
1373 Vector3d com(0.0);
1374 Vector3d comVel(0.0);
1375 Vector3d angularMomentum(0.0);
1376
1377 getComAll(com,comVel);
1378
1379 SimInfo::MoleculeIterator i;
1380 Molecule* mol;
1381
1382 Vector3d thisr(0.0);
1383 Vector3d thisp(0.0);
1384
1385 double thisMass;
1386
1387 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1388 thisMass = mol->getMass();
1389 thisr = mol->getCom()-com;
1390 thisp = (mol->getComVel()-comVel)*thisMass;
1391
1392 angularMomentum += cross( thisr, thisp );
1393
1394 }
1395
1396 #ifdef IS_MPI
1397 Vector3d tmpAngMom;
1398 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1399 #endif
1400
1401 return angularMomentum;
1402 }
1403
1404
1405 }//end namespace oopse
1406