ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/SimInfo.cpp
Revision: 1534
Committed: Wed Dec 29 21:53:28 2010 UTC (14 years, 4 months ago) by gezelter
File size: 44577 byte(s)
Log Message:
getting closer to compiling

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, 24107 (2008).
39 * [4] Vardeman & Gezelter, in progress (2009).
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 "primitives/StuntDouble.hpp"
57 #include "UseTheForce/doForces_interface.h"
58 #include "UseTheForce/DarkSide/neighborLists_interface.h"
59 #include "utils/MemoryUtils.hpp"
60 #include "utils/simError.h"
61 #include "selection/SelectionManager.hpp"
62 #include "io/ForceFieldOptions.hpp"
63 #include "UseTheForce/ForceField.hpp"
64 #include "nonbonded/SwitchingFunction.hpp"
65
66 #ifdef IS_MPI
67 #include "UseTheForce/mpiComponentPlan.h"
68 #include "UseTheForce/DarkSide/simParallel_interface.h"
69 #endif
70
71 using namespace std;
72 namespace OpenMD {
73
74 SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
75 forceField_(ff), simParams_(simParams),
76 ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
77 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
78 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
79 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nInversions_(0),
80 nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0),
81 nConstraints_(0), sman_(NULL), fortranInitialized_(false),
82 calcBoxDipole_(false), useAtomicVirial_(true) {
83
84 MoleculeStamp* molStamp;
85 int nMolWithSameStamp;
86 int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
87 int nGroups = 0; //total cutoff groups defined in meta-data file
88 CutoffGroupStamp* cgStamp;
89 RigidBodyStamp* rbStamp;
90 int nRigidAtoms = 0;
91
92 vector<Component*> components = simParams->getComponents();
93
94 for (vector<Component*>::iterator i = components.begin(); i !=components.end(); ++i) {
95 molStamp = (*i)->getMoleculeStamp();
96 nMolWithSameStamp = (*i)->getNMol();
97
98 addMoleculeStamp(molStamp, nMolWithSameStamp);
99
100 //calculate atoms in molecules
101 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
102
103 //calculate atoms in cutoff groups
104 int nAtomsInGroups = 0;
105 int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
106
107 for (int j=0; j < nCutoffGroupsInStamp; j++) {
108 cgStamp = molStamp->getCutoffGroupStamp(j);
109 nAtomsInGroups += cgStamp->getNMembers();
110 }
111
112 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
113
114 nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
115
116 //calculate atoms in rigid bodies
117 int nAtomsInRigidBodies = 0;
118 int nRigidBodiesInStamp = molStamp->getNRigidBodies();
119
120 for (int j=0; j < nRigidBodiesInStamp; j++) {
121 rbStamp = molStamp->getRigidBodyStamp(j);
122 nAtomsInRigidBodies += rbStamp->getNMembers();
123 }
124
125 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
126 nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
127
128 }
129
130 //every free atom (atom does not belong to cutoff groups) is a cutoff
131 //group therefore the total number of cutoff groups in the system is
132 //equal to the total number of atoms minus number of atoms belong to
133 //cutoff group defined in meta-data file plus the number of cutoff
134 //groups defined in meta-data file
135 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
136
137 //every free atom (atom does not belong to rigid bodies) is an
138 //integrable object therefore the total number of integrable objects
139 //in the system is equal to the total number of atoms minus number of
140 //atoms belong to rigid body defined in meta-data file plus the number
141 //of rigid bodies defined in meta-data file
142 nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
143 + nGlobalRigidBodies_;
144
145 nGlobalMols_ = molStampIds_.size();
146 molToProcMap_.resize(nGlobalMols_);
147 }
148
149 SimInfo::~SimInfo() {
150 map<int, Molecule*>::iterator i;
151 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
152 delete i->second;
153 }
154 molecules_.clear();
155
156 delete sman_;
157 delete simParams_;
158 delete forceField_;
159 }
160
161
162 bool SimInfo::addMolecule(Molecule* mol) {
163 MoleculeIterator i;
164
165 i = molecules_.find(mol->getGlobalIndex());
166 if (i == molecules_.end() ) {
167
168 molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
169
170 nAtoms_ += mol->getNAtoms();
171 nBonds_ += mol->getNBonds();
172 nBends_ += mol->getNBends();
173 nTorsions_ += mol->getNTorsions();
174 nInversions_ += mol->getNInversions();
175 nRigidBodies_ += mol->getNRigidBodies();
176 nIntegrableObjects_ += mol->getNIntegrableObjects();
177 nCutoffGroups_ += mol->getNCutoffGroups();
178 nConstraints_ += mol->getNConstraintPairs();
179
180 addInteractionPairs(mol);
181
182 return true;
183 } else {
184 return false;
185 }
186 }
187
188 bool SimInfo::removeMolecule(Molecule* mol) {
189 MoleculeIterator i;
190 i = molecules_.find(mol->getGlobalIndex());
191
192 if (i != molecules_.end() ) {
193
194 assert(mol == i->second);
195
196 nAtoms_ -= mol->getNAtoms();
197 nBonds_ -= mol->getNBonds();
198 nBends_ -= mol->getNBends();
199 nTorsions_ -= mol->getNTorsions();
200 nInversions_ -= mol->getNInversions();
201 nRigidBodies_ -= mol->getNRigidBodies();
202 nIntegrableObjects_ -= mol->getNIntegrableObjects();
203 nCutoffGroups_ -= mol->getNCutoffGroups();
204 nConstraints_ -= mol->getNConstraintPairs();
205
206 removeInteractionPairs(mol);
207 molecules_.erase(mol->getGlobalIndex());
208
209 delete mol;
210
211 return true;
212 } else {
213 return false;
214 }
215 }
216
217
218 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
219 i = molecules_.begin();
220 return i == molecules_.end() ? NULL : i->second;
221 }
222
223 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
224 ++i;
225 return i == molecules_.end() ? NULL : i->second;
226 }
227
228
229 void SimInfo::calcNdf() {
230 int ndf_local;
231 MoleculeIterator i;
232 vector<StuntDouble*>::iterator j;
233 Molecule* mol;
234 StuntDouble* integrableObject;
235
236 ndf_local = 0;
237
238 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
239 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
240 integrableObject = mol->nextIntegrableObject(j)) {
241
242 ndf_local += 3;
243
244 if (integrableObject->isDirectional()) {
245 if (integrableObject->isLinear()) {
246 ndf_local += 2;
247 } else {
248 ndf_local += 3;
249 }
250 }
251
252 }
253 }
254
255 // n_constraints is local, so subtract them on each processor
256 ndf_local -= nConstraints_;
257
258 #ifdef IS_MPI
259 MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
260 #else
261 ndf_ = ndf_local;
262 #endif
263
264 // nZconstraints_ is global, as are the 3 COM translations for the
265 // entire system:
266 ndf_ = ndf_ - 3 - nZconstraint_;
267
268 }
269
270 int SimInfo::getFdf() {
271 #ifdef IS_MPI
272 MPI_Allreduce(&fdf_local,&fdf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
273 #else
274 fdf_ = fdf_local;
275 #endif
276 return fdf_;
277 }
278
279 void SimInfo::calcNdfRaw() {
280 int ndfRaw_local;
281
282 MoleculeIterator i;
283 vector<StuntDouble*>::iterator j;
284 Molecule* mol;
285 StuntDouble* integrableObject;
286
287 // Raw degrees of freedom that we have to set
288 ndfRaw_local = 0;
289
290 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
291 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
292 integrableObject = mol->nextIntegrableObject(j)) {
293
294 ndfRaw_local += 3;
295
296 if (integrableObject->isDirectional()) {
297 if (integrableObject->isLinear()) {
298 ndfRaw_local += 2;
299 } else {
300 ndfRaw_local += 3;
301 }
302 }
303
304 }
305 }
306
307 #ifdef IS_MPI
308 MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
309 #else
310 ndfRaw_ = ndfRaw_local;
311 #endif
312 }
313
314 void SimInfo::calcNdfTrans() {
315 int ndfTrans_local;
316
317 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
318
319
320 #ifdef IS_MPI
321 MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
322 #else
323 ndfTrans_ = ndfTrans_local;
324 #endif
325
326 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
327
328 }
329
330 void SimInfo::addInteractionPairs(Molecule* mol) {
331 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
332 vector<Bond*>::iterator bondIter;
333 vector<Bend*>::iterator bendIter;
334 vector<Torsion*>::iterator torsionIter;
335 vector<Inversion*>::iterator inversionIter;
336 Bond* bond;
337 Bend* bend;
338 Torsion* torsion;
339 Inversion* inversion;
340 int a;
341 int b;
342 int c;
343 int d;
344
345 // atomGroups can be used to add special interaction maps between
346 // groups of atoms that are in two separate rigid bodies.
347 // However, most site-site interactions between two rigid bodies
348 // are probably not special, just the ones between the physically
349 // bonded atoms. Interactions *within* a single rigid body should
350 // always be excluded. These are done at the bottom of this
351 // function.
352
353 map<int, set<int> > atomGroups;
354 Molecule::RigidBodyIterator rbIter;
355 RigidBody* rb;
356 Molecule::IntegrableObjectIterator ii;
357 StuntDouble* integrableObject;
358
359 for (integrableObject = mol->beginIntegrableObject(ii);
360 integrableObject != NULL;
361 integrableObject = mol->nextIntegrableObject(ii)) {
362
363 if (integrableObject->isRigidBody()) {
364 rb = static_cast<RigidBody*>(integrableObject);
365 vector<Atom*> atoms = rb->getAtoms();
366 set<int> rigidAtoms;
367 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
368 rigidAtoms.insert(atoms[i]->getGlobalIndex());
369 }
370 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
371 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
372 }
373 } else {
374 set<int> oneAtomSet;
375 oneAtomSet.insert(integrableObject->getGlobalIndex());
376 atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
377 }
378 }
379
380 for (bond= mol->beginBond(bondIter); bond != NULL;
381 bond = mol->nextBond(bondIter)) {
382
383 a = bond->getAtomA()->getGlobalIndex();
384 b = bond->getAtomB()->getGlobalIndex();
385
386 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
387 oneTwoInteractions_.addPair(a, b);
388 } else {
389 excludedInteractions_.addPair(a, b);
390 }
391 }
392
393 for (bend= mol->beginBend(bendIter); bend != NULL;
394 bend = mol->nextBend(bendIter)) {
395
396 a = bend->getAtomA()->getGlobalIndex();
397 b = bend->getAtomB()->getGlobalIndex();
398 c = bend->getAtomC()->getGlobalIndex();
399
400 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
401 oneTwoInteractions_.addPair(a, b);
402 oneTwoInteractions_.addPair(b, c);
403 } else {
404 excludedInteractions_.addPair(a, b);
405 excludedInteractions_.addPair(b, c);
406 }
407
408 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
409 oneThreeInteractions_.addPair(a, c);
410 } else {
411 excludedInteractions_.addPair(a, c);
412 }
413 }
414
415 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
416 torsion = mol->nextTorsion(torsionIter)) {
417
418 a = torsion->getAtomA()->getGlobalIndex();
419 b = torsion->getAtomB()->getGlobalIndex();
420 c = torsion->getAtomC()->getGlobalIndex();
421 d = torsion->getAtomD()->getGlobalIndex();
422
423 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
424 oneTwoInteractions_.addPair(a, b);
425 oneTwoInteractions_.addPair(b, c);
426 oneTwoInteractions_.addPair(c, d);
427 } else {
428 excludedInteractions_.addPair(a, b);
429 excludedInteractions_.addPair(b, c);
430 excludedInteractions_.addPair(c, d);
431 }
432
433 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
434 oneThreeInteractions_.addPair(a, c);
435 oneThreeInteractions_.addPair(b, d);
436 } else {
437 excludedInteractions_.addPair(a, c);
438 excludedInteractions_.addPair(b, d);
439 }
440
441 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
442 oneFourInteractions_.addPair(a, d);
443 } else {
444 excludedInteractions_.addPair(a, d);
445 }
446 }
447
448 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
449 inversion = mol->nextInversion(inversionIter)) {
450
451 a = inversion->getAtomA()->getGlobalIndex();
452 b = inversion->getAtomB()->getGlobalIndex();
453 c = inversion->getAtomC()->getGlobalIndex();
454 d = inversion->getAtomD()->getGlobalIndex();
455
456 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
457 oneTwoInteractions_.addPair(a, b);
458 oneTwoInteractions_.addPair(a, c);
459 oneTwoInteractions_.addPair(a, d);
460 } else {
461 excludedInteractions_.addPair(a, b);
462 excludedInteractions_.addPair(a, c);
463 excludedInteractions_.addPair(a, d);
464 }
465
466 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
467 oneThreeInteractions_.addPair(b, c);
468 oneThreeInteractions_.addPair(b, d);
469 oneThreeInteractions_.addPair(c, d);
470 } else {
471 excludedInteractions_.addPair(b, c);
472 excludedInteractions_.addPair(b, d);
473 excludedInteractions_.addPair(c, d);
474 }
475 }
476
477 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
478 rb = mol->nextRigidBody(rbIter)) {
479 vector<Atom*> atoms = rb->getAtoms();
480 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
481 for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
482 a = atoms[i]->getGlobalIndex();
483 b = atoms[j]->getGlobalIndex();
484 excludedInteractions_.addPair(a, b);
485 }
486 }
487 }
488
489 }
490
491 void SimInfo::removeInteractionPairs(Molecule* mol) {
492 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
493 vector<Bond*>::iterator bondIter;
494 vector<Bend*>::iterator bendIter;
495 vector<Torsion*>::iterator torsionIter;
496 vector<Inversion*>::iterator inversionIter;
497 Bond* bond;
498 Bend* bend;
499 Torsion* torsion;
500 Inversion* inversion;
501 int a;
502 int b;
503 int c;
504 int d;
505
506 map<int, set<int> > atomGroups;
507 Molecule::RigidBodyIterator rbIter;
508 RigidBody* rb;
509 Molecule::IntegrableObjectIterator ii;
510 StuntDouble* integrableObject;
511
512 for (integrableObject = mol->beginIntegrableObject(ii);
513 integrableObject != NULL;
514 integrableObject = mol->nextIntegrableObject(ii)) {
515
516 if (integrableObject->isRigidBody()) {
517 rb = static_cast<RigidBody*>(integrableObject);
518 vector<Atom*> atoms = rb->getAtoms();
519 set<int> rigidAtoms;
520 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
521 rigidAtoms.insert(atoms[i]->getGlobalIndex());
522 }
523 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
524 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
525 }
526 } else {
527 set<int> oneAtomSet;
528 oneAtomSet.insert(integrableObject->getGlobalIndex());
529 atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
530 }
531 }
532
533 for (bond= mol->beginBond(bondIter); bond != NULL;
534 bond = mol->nextBond(bondIter)) {
535
536 a = bond->getAtomA()->getGlobalIndex();
537 b = bond->getAtomB()->getGlobalIndex();
538
539 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
540 oneTwoInteractions_.removePair(a, b);
541 } else {
542 excludedInteractions_.removePair(a, b);
543 }
544 }
545
546 for (bend= mol->beginBend(bendIter); bend != NULL;
547 bend = mol->nextBend(bendIter)) {
548
549 a = bend->getAtomA()->getGlobalIndex();
550 b = bend->getAtomB()->getGlobalIndex();
551 c = bend->getAtomC()->getGlobalIndex();
552
553 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
554 oneTwoInteractions_.removePair(a, b);
555 oneTwoInteractions_.removePair(b, c);
556 } else {
557 excludedInteractions_.removePair(a, b);
558 excludedInteractions_.removePair(b, c);
559 }
560
561 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
562 oneThreeInteractions_.removePair(a, c);
563 } else {
564 excludedInteractions_.removePair(a, c);
565 }
566 }
567
568 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
569 torsion = mol->nextTorsion(torsionIter)) {
570
571 a = torsion->getAtomA()->getGlobalIndex();
572 b = torsion->getAtomB()->getGlobalIndex();
573 c = torsion->getAtomC()->getGlobalIndex();
574 d = torsion->getAtomD()->getGlobalIndex();
575
576 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
577 oneTwoInteractions_.removePair(a, b);
578 oneTwoInteractions_.removePair(b, c);
579 oneTwoInteractions_.removePair(c, d);
580 } else {
581 excludedInteractions_.removePair(a, b);
582 excludedInteractions_.removePair(b, c);
583 excludedInteractions_.removePair(c, d);
584 }
585
586 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
587 oneThreeInteractions_.removePair(a, c);
588 oneThreeInteractions_.removePair(b, d);
589 } else {
590 excludedInteractions_.removePair(a, c);
591 excludedInteractions_.removePair(b, d);
592 }
593
594 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
595 oneFourInteractions_.removePair(a, d);
596 } else {
597 excludedInteractions_.removePair(a, d);
598 }
599 }
600
601 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
602 inversion = mol->nextInversion(inversionIter)) {
603
604 a = inversion->getAtomA()->getGlobalIndex();
605 b = inversion->getAtomB()->getGlobalIndex();
606 c = inversion->getAtomC()->getGlobalIndex();
607 d = inversion->getAtomD()->getGlobalIndex();
608
609 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
610 oneTwoInteractions_.removePair(a, b);
611 oneTwoInteractions_.removePair(a, c);
612 oneTwoInteractions_.removePair(a, d);
613 } else {
614 excludedInteractions_.removePair(a, b);
615 excludedInteractions_.removePair(a, c);
616 excludedInteractions_.removePair(a, d);
617 }
618
619 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
620 oneThreeInteractions_.removePair(b, c);
621 oneThreeInteractions_.removePair(b, d);
622 oneThreeInteractions_.removePair(c, d);
623 } else {
624 excludedInteractions_.removePair(b, c);
625 excludedInteractions_.removePair(b, d);
626 excludedInteractions_.removePair(c, d);
627 }
628 }
629
630 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
631 rb = mol->nextRigidBody(rbIter)) {
632 vector<Atom*> atoms = rb->getAtoms();
633 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
634 for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
635 a = atoms[i]->getGlobalIndex();
636 b = atoms[j]->getGlobalIndex();
637 excludedInteractions_.removePair(a, b);
638 }
639 }
640 }
641
642 }
643
644
645 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
646 int curStampId;
647
648 //index from 0
649 curStampId = moleculeStamps_.size();
650
651 moleculeStamps_.push_back(molStamp);
652 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
653 }
654
655
656 /**
657 * update
658 *
659 * Performs the global checks and variable settings after the objects have been
660 * created.
661 *
662 */
663 void SimInfo::update() {
664
665 setupSimVariables();
666 setupCutoffs();
667 setupSwitching();
668 setupElectrostatics();
669 setupNeighborlists();
670
671 #ifdef IS_MPI
672 setupFortranParallel();
673 #endif
674 setupFortranSim();
675 fortranInitialized_ = true;
676
677 calcNdf();
678 calcNdfRaw();
679 calcNdfTrans();
680 }
681
682 set<AtomType*> SimInfo::getSimulatedAtomTypes() {
683 SimInfo::MoleculeIterator mi;
684 Molecule* mol;
685 Molecule::AtomIterator ai;
686 Atom* atom;
687 set<AtomType*> atomTypes;
688
689 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
690 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
691 atomTypes.insert(atom->getAtomType());
692 }
693 }
694 return atomTypes;
695 }
696
697 /**
698 * setupCutoffs
699 *
700 * Sets the values of cutoffRadius and cutoffMethod
701 *
702 * cutoffRadius : realType
703 * If the cutoffRadius was explicitly set, use that value.
704 * If the cutoffRadius was not explicitly set:
705 * Are there electrostatic atoms? Use 12.0 Angstroms.
706 * No electrostatic atoms? Poll the atom types present in the
707 * simulation for suggested cutoff values (e.g. 2.5 * sigma).
708 * Use the maximum suggested value that was found.
709 *
710 * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, SHIFTED_POTENTIAL)
711 * If cutoffMethod was explicitly set, use that choice.
712 * If cutoffMethod was not explicitly set, use SHIFTED_FORCE
713 */
714 void SimInfo::setupCutoffs() {
715
716 if (simParams_->haveCutoffRadius()) {
717 cutoffRadius_ = simParams_->getCutoffRadius();
718 } else {
719 if (usesElectrostaticAtoms_) {
720 sprintf(painCave.errMsg,
721 "SimInfo: No value was set for the cutoffRadius.\n"
722 "\tOpenMD will use a default value of 12.0 angstroms"
723 "\tfor the cutoffRadius.\n");
724 painCave.isFatal = 0;
725 painCave.severity = OPENMD_INFO;
726 simError();
727 cutoffRadius_ = 12.0;
728 } else {
729 RealType thisCut;
730 set<AtomType*>::iterator i;
731 set<AtomType*> atomTypes;
732 atomTypes = getSimulatedAtomTypes();
733 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
734 thisCut = InteractionManager::Instance()->getSuggestedCutoffRadius((*i));
735 cutoffRadius_ = max(thisCut, cutoffRadius_);
736 }
737 sprintf(painCave.errMsg,
738 "SimInfo: No value was set for the cutoffRadius.\n"
739 "\tOpenMD will use %lf angstroms.\n",
740 cutoffRadius_);
741 painCave.isFatal = 0;
742 painCave.severity = OPENMD_INFO;
743 simError();
744 }
745 }
746
747 map<string, CutoffMethod> stringToCutoffMethod;
748 stringToCutoffMethod["HARD"] = HARD;
749 stringToCutoffMethod["SWITCHING_FUNCTION"] = SWITCHING_FUNCTION;
750 stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
751 stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
752
753 if (simParams_->haveCutoffMethod()) {
754 string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
755 map<string, CutoffMethod>::iterator i;
756 i = stringToCutoffMethod.find(cutMeth);
757 if (i == stringToCutoffMethod.end()) {
758 sprintf(painCave.errMsg,
759 "SimInfo: Could not find chosen cutoffMethod %s\n"
760 "\tShould be one of: "
761 "HARD, SWITCHING_FUNCTION, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
762 cutMeth.c_str());
763 painCave.isFatal = 1;
764 painCave.severity = OPENMD_ERROR;
765 simError();
766 } else {
767 cutoffMethod_ = i->second;
768 }
769 } else {
770 sprintf(painCave.errMsg,
771 "SimInfo: No value was set for the cutoffMethod.\n"
772 "\tOpenMD will use SHIFTED_FORCE.\n");
773 painCave.isFatal = 0;
774 painCave.severity = OPENMD_INFO;
775 simError();
776 cutoffMethod_ = SHIFTED_FORCE;
777 }
778 }
779
780 /**
781 * setupSwitching
782 *
783 * Sets the values of switchingRadius and
784 * If the switchingRadius was explicitly set, use that value (but check it)
785 * If the switchingRadius was not explicitly set: use 0.85 * cutoffRadius_
786 */
787 void SimInfo::setupSwitching() {
788
789 if (simParams_->haveSwitchingRadius()) {
790 switchingRadius_ = simParams_->getSwitchingRadius();
791 if (switchingRadius_ > cutoffRadius_) {
792 sprintf(painCave.errMsg,
793 "SimInfo: switchingRadius (%f) is larger than cutoffRadius(%f)\n",
794 switchingRadius_, cutoffRadius_);
795 painCave.isFatal = 1;
796 painCave.severity = OPENMD_ERROR;
797 simError();
798 }
799 } else {
800 switchingRadius_ = 0.85 * cutoffRadius_;
801 sprintf(painCave.errMsg,
802 "SimInfo: No value was set for the switchingRadius.\n"
803 "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
804 "\tswitchingRadius = %f. for this simulation\n", switchingRadius_);
805 painCave.isFatal = 0;
806 painCave.severity = OPENMD_WARNING;
807 simError();
808 }
809
810 if (simParams_->haveSwitchingFunctionType()) {
811 string funcType = simParams_->getSwitchingFunctionType();
812 toUpper(funcType);
813 if (funcType == "CUBIC") {
814 sft_ = cubic;
815 } else {
816 if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
817 sft_ = fifth_order_poly;
818 } else {
819 // throw error
820 sprintf( painCave.errMsg,
821 "SimInfo : Unknown switchingFunctionType. (Input file specified %s .)\n"
822 "\tswitchingFunctionType must be one of: "
823 "\"cubic\" or \"fifth_order_polynomial\".",
824 funcType.c_str() );
825 painCave.isFatal = 1;
826 painCave.severity = OPENMD_ERROR;
827 simError();
828 }
829 }
830 }
831 }
832
833 /**
834 * setupNeighborlists
835 *
836 * If the skinThickness was explicitly set, use that value (but check it)
837 * If the skinThickness was not explicitly set: use 1.0 angstroms
838 */
839 void SimInfo::setupNeighborlists() {
840 if (simParams_->haveSkinThickness()) {
841 skinThickness_ = simParams_->getSkinThickness();
842 } else {
843 skinThickness_ = 1.0;
844 sprintf(painCave.errMsg,
845 "SimInfo: No value was set for the skinThickness.\n"
846 "\tOpenMD will use a default value of %f Angstroms\n"
847 "\tfor this simulation\n", skinThickness_);
848 painCave.severity = OPENMD_INFO;
849 painCave.isFatal = 0;
850 simError();
851 }
852 }
853
854 void SimInfo::setupSimVariables() {
855 useAtomicVirial_ = simParams_->getUseAtomicVirial();
856 // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true
857 calcBoxDipole_ = false;
858 if ( simParams_->haveAccumulateBoxDipole() )
859 if ( simParams_->getAccumulateBoxDipole() ) {
860 calcBoxDipole_ = true;
861 }
862
863 set<AtomType*>::iterator i;
864 set<AtomType*> atomTypes;
865 atomTypes = getSimulatedAtomTypes();
866 int usesElectrostatic = 0;
867 int usesMetallic = 0;
868 int usesDirectional = 0;
869 //loop over all of the atom types
870 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
871 usesElectrostatic |= (*i)->isElectrostatic();
872 usesMetallic |= (*i)->isMetal();
873 usesDirectional |= (*i)->isDirectional();
874 }
875
876 #ifdef IS_MPI
877 int temp;
878 temp = usesDirectional;
879 MPI_Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
880
881 temp = usesMetallic;
882 MPI_Allreduce(&temp, &usesMetallicAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
883
884 temp = usesElectrostatic;
885 MPI_Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
886 #endif
887 fInfo_.SIM_uses_PBC = usesPeriodicBoundaries_;
888 fInfo_.SIM_uses_DirectionalAtoms = usesDirectionalAtoms_;
889 fInfo_.SIM_uses_MetallicAtoms = usesMetallicAtoms_;
890 fInfo_.SIM_requires_SkipCorrection = usesElectrostaticAtoms_;
891 fInfo_.SIM_requires_SelfCorrection = usesElectrostaticAtoms_;
892 fInfo_.SIM_uses_AtomicVirial = usesAtomicVirial_;
893 }
894
895 void SimInfo::setupFortranSim() {
896 int isError;
897 int nExclude, nOneTwo, nOneThree, nOneFour;
898 vector<int> fortranGlobalGroupMembership;
899
900 notifyFortranSkinThickness(&skinThickness_);
901
902 int ljsp = cutoffMethod_ == SHIFTED_POTENTIAL ? 1 : 0;
903 int ljsf = cutoffMethod_ == SHIFTED_FORCE ? 1 : 0;
904 notifyFortranCutoffs(&cutoffRadius_, &switchingRadius_, &ljsp, &ljsf);
905
906 isError = 0;
907
908 //globalGroupMembership_ is filled by SimCreator
909 for (int i = 0; i < nGlobalAtoms_; i++) {
910 fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
911 }
912
913 //calculate mass ratio of cutoff group
914 vector<RealType> mfact;
915 SimInfo::MoleculeIterator mi;
916 Molecule* mol;
917 Molecule::CutoffGroupIterator ci;
918 CutoffGroup* cg;
919 Molecule::AtomIterator ai;
920 Atom* atom;
921 RealType totalMass;
922
923 //to avoid memory reallocation, reserve enough space for mfact
924 mfact.reserve(getNCutoffGroups());
925
926 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
927 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
928
929 totalMass = cg->getMass();
930 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
931 // Check for massless groups - set mfact to 1 if true
932 if (totalMass != 0)
933 mfact.push_back(atom->getMass()/totalMass);
934 else
935 mfact.push_back( 1.0 );
936 }
937 }
938 }
939
940 //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
941 vector<int> identArray;
942
943 //to avoid memory reallocation, reserve enough space identArray
944 identArray.reserve(getNAtoms());
945
946 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
947 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
948 identArray.push_back(atom->getIdent());
949 }
950 }
951
952 //fill molMembershipArray
953 //molMembershipArray is filled by SimCreator
954 vector<int> molMembershipArray(nGlobalAtoms_);
955 for (int i = 0; i < nGlobalAtoms_; i++) {
956 molMembershipArray[i] = globalMolMembership_[i] + 1;
957 }
958
959 //setup fortran simulation
960
961 nExclude = excludedInteractions_.getSize();
962 nOneTwo = oneTwoInteractions_.getSize();
963 nOneThree = oneThreeInteractions_.getSize();
964 nOneFour = oneFourInteractions_.getSize();
965
966 int* excludeList = excludedInteractions_.getPairList();
967 int* oneTwoList = oneTwoInteractions_.getPairList();
968 int* oneThreeList = oneThreeInteractions_.getPairList();
969 int* oneFourList = oneFourInteractions_.getPairList();
970
971 setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0],
972 &nExclude, excludeList,
973 &nOneTwo, oneTwoList,
974 &nOneThree, oneThreeList,
975 &nOneFour, oneFourList,
976 &molMembershipArray[0], &mfact[0], &nCutoffGroups_,
977 &fortranGlobalGroupMembership[0], &isError);
978
979 if( isError ){
980
981 sprintf( painCave.errMsg,
982 "There was an error setting the simulation information in fortran.\n" );
983 painCave.isFatal = 1;
984 painCave.severity = OPENMD_ERROR;
985 simError();
986 }
987
988
989 sprintf( checkPointMsg,
990 "succesfully sent the simulation information to fortran.\n");
991
992 errorCheckPoint();
993
994 // Setup number of neighbors in neighbor list if present
995 if (simParams_->haveNeighborListNeighbors()) {
996 int nlistNeighbors = simParams_->getNeighborListNeighbors();
997 setNeighbors(&nlistNeighbors);
998 }
999
1000
1001 }
1002
1003
1004 void SimInfo::setupFortranParallel() {
1005 #ifdef IS_MPI
1006 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
1007 vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
1008 vector<int> localToGlobalCutoffGroupIndex;
1009 SimInfo::MoleculeIterator mi;
1010 Molecule::AtomIterator ai;
1011 Molecule::CutoffGroupIterator ci;
1012 Molecule* mol;
1013 Atom* atom;
1014 CutoffGroup* cg;
1015 mpiSimData parallelData;
1016 int isError;
1017
1018 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
1019
1020 //local index(index in DataStorge) of atom is important
1021 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
1022 localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
1023 }
1024
1025 //local index of cutoff group is trivial, it only depends on the order of travesing
1026 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
1027 localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
1028 }
1029
1030 }
1031
1032 //fill up mpiSimData struct
1033 parallelData.nMolGlobal = getNGlobalMolecules();
1034 parallelData.nMolLocal = getNMolecules();
1035 parallelData.nAtomsGlobal = getNGlobalAtoms();
1036 parallelData.nAtomsLocal = getNAtoms();
1037 parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
1038 parallelData.nGroupsLocal = getNCutoffGroups();
1039 parallelData.myNode = worldRank;
1040 MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
1041
1042 //pass mpiSimData struct and index arrays to fortran
1043 setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
1044 &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal),
1045 &localToGlobalCutoffGroupIndex[0], &isError);
1046
1047 if (isError) {
1048 sprintf(painCave.errMsg,
1049 "mpiRefresh errror: fortran didn't like something we gave it.\n");
1050 painCave.isFatal = 1;
1051 simError();
1052 }
1053
1054 sprintf(checkPointMsg, " mpiRefresh successful.\n");
1055 errorCheckPoint();
1056
1057 #endif
1058 }
1059
1060
1061 void SimInfo::setupAccumulateBoxDipole() {
1062
1063
1064 }
1065
1066 void SimInfo::addProperty(GenericData* genData) {
1067 properties_.addProperty(genData);
1068 }
1069
1070 void SimInfo::removeProperty(const string& propName) {
1071 properties_.removeProperty(propName);
1072 }
1073
1074 void SimInfo::clearProperties() {
1075 properties_.clearProperties();
1076 }
1077
1078 vector<string> SimInfo::getPropertyNames() {
1079 return properties_.getPropertyNames();
1080 }
1081
1082 vector<GenericData*> SimInfo::getProperties() {
1083 return properties_.getProperties();
1084 }
1085
1086 GenericData* SimInfo::getPropertyByName(const string& propName) {
1087 return properties_.getPropertyByName(propName);
1088 }
1089
1090 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
1091 if (sman_ == sman) {
1092 return;
1093 }
1094 delete sman_;
1095 sman_ = sman;
1096
1097 Molecule* mol;
1098 RigidBody* rb;
1099 Atom* atom;
1100 SimInfo::MoleculeIterator mi;
1101 Molecule::RigidBodyIterator rbIter;
1102 Molecule::AtomIterator atomIter;;
1103
1104 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
1105
1106 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
1107 atom->setSnapshotManager(sman_);
1108 }
1109
1110 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
1111 rb->setSnapshotManager(sman_);
1112 }
1113 }
1114
1115 }
1116
1117 Vector3d SimInfo::getComVel(){
1118 SimInfo::MoleculeIterator i;
1119 Molecule* mol;
1120
1121 Vector3d comVel(0.0);
1122 RealType totalMass = 0.0;
1123
1124
1125 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1126 RealType mass = mol->getMass();
1127 totalMass += mass;
1128 comVel += mass * mol->getComVel();
1129 }
1130
1131 #ifdef IS_MPI
1132 RealType tmpMass = totalMass;
1133 Vector3d tmpComVel(comVel);
1134 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1135 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1136 #endif
1137
1138 comVel /= totalMass;
1139
1140 return comVel;
1141 }
1142
1143 Vector3d SimInfo::getCom(){
1144 SimInfo::MoleculeIterator i;
1145 Molecule* mol;
1146
1147 Vector3d com(0.0);
1148 RealType totalMass = 0.0;
1149
1150 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1151 RealType mass = mol->getMass();
1152 totalMass += mass;
1153 com += mass * mol->getCom();
1154 }
1155
1156 #ifdef IS_MPI
1157 RealType tmpMass = totalMass;
1158 Vector3d tmpCom(com);
1159 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1160 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1161 #endif
1162
1163 com /= totalMass;
1164
1165 return com;
1166
1167 }
1168
1169 ostream& operator <<(ostream& o, SimInfo& info) {
1170
1171 return o;
1172 }
1173
1174
1175 /*
1176 Returns center of mass and center of mass velocity in one function call.
1177 */
1178
1179 void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1180 SimInfo::MoleculeIterator i;
1181 Molecule* mol;
1182
1183
1184 RealType totalMass = 0.0;
1185
1186
1187 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1188 RealType mass = mol->getMass();
1189 totalMass += mass;
1190 com += mass * mol->getCom();
1191 comVel += mass * mol->getComVel();
1192 }
1193
1194 #ifdef IS_MPI
1195 RealType tmpMass = totalMass;
1196 Vector3d tmpCom(com);
1197 Vector3d tmpComVel(comVel);
1198 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1199 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1200 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1201 #endif
1202
1203 com /= totalMass;
1204 comVel /= totalMass;
1205 }
1206
1207 /*
1208 Return intertia tensor for entire system and angular momentum Vector.
1209
1210
1211 [ Ixx -Ixy -Ixz ]
1212 J =| -Iyx Iyy -Iyz |
1213 [ -Izx -Iyz Izz ]
1214 */
1215
1216 void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1217
1218
1219 RealType xx = 0.0;
1220 RealType yy = 0.0;
1221 RealType zz = 0.0;
1222 RealType xy = 0.0;
1223 RealType xz = 0.0;
1224 RealType yz = 0.0;
1225 Vector3d com(0.0);
1226 Vector3d comVel(0.0);
1227
1228 getComAll(com, comVel);
1229
1230 SimInfo::MoleculeIterator i;
1231 Molecule* mol;
1232
1233 Vector3d thisq(0.0);
1234 Vector3d thisv(0.0);
1235
1236 RealType thisMass = 0.0;
1237
1238
1239
1240
1241 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1242
1243 thisq = mol->getCom()-com;
1244 thisv = mol->getComVel()-comVel;
1245 thisMass = mol->getMass();
1246 // Compute moment of intertia coefficients.
1247 xx += thisq[0]*thisq[0]*thisMass;
1248 yy += thisq[1]*thisq[1]*thisMass;
1249 zz += thisq[2]*thisq[2]*thisMass;
1250
1251 // compute products of intertia
1252 xy += thisq[0]*thisq[1]*thisMass;
1253 xz += thisq[0]*thisq[2]*thisMass;
1254 yz += thisq[1]*thisq[2]*thisMass;
1255
1256 angularMomentum += cross( thisq, thisv ) * thisMass;
1257
1258 }
1259
1260
1261 inertiaTensor(0,0) = yy + zz;
1262 inertiaTensor(0,1) = -xy;
1263 inertiaTensor(0,2) = -xz;
1264 inertiaTensor(1,0) = -xy;
1265 inertiaTensor(1,1) = xx + zz;
1266 inertiaTensor(1,2) = -yz;
1267 inertiaTensor(2,0) = -xz;
1268 inertiaTensor(2,1) = -yz;
1269 inertiaTensor(2,2) = xx + yy;
1270
1271 #ifdef IS_MPI
1272 Mat3x3d tmpI(inertiaTensor);
1273 Vector3d tmpAngMom;
1274 MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1275 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1276 #endif
1277
1278 return;
1279 }
1280
1281 //Returns the angular momentum of the system
1282 Vector3d SimInfo::getAngularMomentum(){
1283
1284 Vector3d com(0.0);
1285 Vector3d comVel(0.0);
1286 Vector3d angularMomentum(0.0);
1287
1288 getComAll(com,comVel);
1289
1290 SimInfo::MoleculeIterator i;
1291 Molecule* mol;
1292
1293 Vector3d thisr(0.0);
1294 Vector3d thisp(0.0);
1295
1296 RealType thisMass;
1297
1298 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1299 thisMass = mol->getMass();
1300 thisr = mol->getCom()-com;
1301 thisp = (mol->getComVel()-comVel)*thisMass;
1302
1303 angularMomentum += cross( thisr, thisp );
1304
1305 }
1306
1307 #ifdef IS_MPI
1308 Vector3d tmpAngMom;
1309 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1310 #endif
1311
1312 return angularMomentum;
1313 }
1314
1315 StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1316 return IOIndexToIntegrableObject.at(index);
1317 }
1318
1319 void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1320 IOIndexToIntegrableObject= v;
1321 }
1322
1323 /* Returns the Volume of the simulation based on a ellipsoid with semi-axes
1324 based on the radius of gyration V=4/3*Pi*R_1*R_2*R_3
1325 where R_i are related to the principle inertia moments R_i = sqrt(C*I_i/N), this reduces to
1326 V = 4/3*Pi*(C/N)^3/2*sqrt(det(I)). See S.E. Baltazar et. al. Comp. Mat. Sci. 37 (2006) 526-536.
1327 */
1328 void SimInfo::getGyrationalVolume(RealType &volume){
1329 Mat3x3d intTensor;
1330 RealType det;
1331 Vector3d dummyAngMom;
1332 RealType sysconstants;
1333 RealType geomCnst;
1334
1335 geomCnst = 3.0/2.0;
1336 /* Get the inertial tensor and angular momentum for free*/
1337 getInertiaTensor(intTensor,dummyAngMom);
1338
1339 det = intTensor.determinant();
1340 sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1341 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(det);
1342 return;
1343 }
1344
1345 void SimInfo::getGyrationalVolume(RealType &volume, RealType &detI){
1346 Mat3x3d intTensor;
1347 Vector3d dummyAngMom;
1348 RealType sysconstants;
1349 RealType geomCnst;
1350
1351 geomCnst = 3.0/2.0;
1352 /* Get the inertial tensor and angular momentum for free*/
1353 getInertiaTensor(intTensor,dummyAngMom);
1354
1355 detI = intTensor.determinant();
1356 sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1357 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(detI);
1358 return;
1359 }
1360 /*
1361 void SimInfo::setStuntDoubleFromGlobalIndex(vector<StuntDouble*> v) {
1362 assert( v.size() == nAtoms_ + nRigidBodies_);
1363 sdByGlobalIndex_ = v;
1364 }
1365
1366 StuntDouble* SimInfo::getStuntDoubleFromGlobalIndex(int index) {
1367 //assert(index < nAtoms_ + nRigidBodies_);
1368 return sdByGlobalIndex_.at(index);
1369 }
1370 */
1371 int SimInfo::getNGlobalConstraints() {
1372 int nGlobalConstraints;
1373 #ifdef IS_MPI
1374 MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
1375 MPI_COMM_WORLD);
1376 #else
1377 nGlobalConstraints = nConstraints_;
1378 #endif
1379 return nGlobalConstraints;
1380 }
1381
1382 }//end namespace OpenMD
1383

Properties

Name Value
svn:keywords Author Id Revision Date