ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/parallel/ForceMatrixDecomposition.cpp
Revision: 1583
Committed: Thu Jun 16 22:00:08 2011 UTC (13 years, 10 months ago) by gezelter
File size: 36830 byte(s)
Log Message:
Bug squashing

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 #include "parallel/ForceMatrixDecomposition.hpp"
42 #include "math/SquareMatrix3.hpp"
43 #include "nonbonded/NonBondedInteraction.hpp"
44 #include "brains/SnapshotManager.hpp"
45 #include "brains/PairList.hpp"
46
47 using namespace std;
48 namespace OpenMD {
49
50 /**
51 * distributeInitialData is essentially a copy of the older fortran
52 * SimulationSetup
53 */
54
55 void ForceMatrixDecomposition::distributeInitialData() {
56 snap_ = sman_->getCurrentSnapshot();
57 storageLayout_ = sman_->getStorageLayout();
58 ff_ = info_->getForceField();
59 nLocal_ = snap_->getNumberOfAtoms();
60
61 nGroups_ = info_->getNLocalCutoffGroups();
62 cerr << "in dId, nGroups = " << nGroups_ << "\n";
63 // gather the information for atomtype IDs (atids):
64 idents = info_->getIdentArray();
65 AtomLocalToGlobal = info_->getGlobalAtomIndices();
66 cgLocalToGlobal = info_->getGlobalGroupIndices();
67 vector<int> globalGroupMembership = info_->getGlobalGroupMembership();
68 massFactors = info_->getMassFactors();
69 PairList excludes = info_->getExcludedInteractions();
70 PairList oneTwo = info_->getOneTwoInteractions();
71 PairList oneThree = info_->getOneThreeInteractions();
72 PairList oneFour = info_->getOneFourInteractions();
73
74 #ifdef IS_MPI
75
76 AtomCommIntRow = new Communicator<Row,int>(nLocal_);
77 AtomCommRealRow = new Communicator<Row,RealType>(nLocal_);
78 AtomCommVectorRow = new Communicator<Row,Vector3d>(nLocal_);
79 AtomCommMatrixRow = new Communicator<Row,Mat3x3d>(nLocal_);
80 AtomCommPotRow = new Communicator<Row,potVec>(nLocal_);
81
82 AtomCommIntColumn = new Communicator<Column,int>(nLocal_);
83 AtomCommRealColumn = new Communicator<Column,RealType>(nLocal_);
84 AtomCommVectorColumn = new Communicator<Column,Vector3d>(nLocal_);
85 AtomCommMatrixColumn = new Communicator<Column,Mat3x3d>(nLocal_);
86 AtomCommPotColumn = new Communicator<Column,potVec>(nLocal_);
87
88 cgCommIntRow = new Communicator<Row,int>(nGroups_);
89 cgCommVectorRow = new Communicator<Row,Vector3d>(nGroups_);
90 cgCommIntColumn = new Communicator<Column,int>(nGroups_);
91 cgCommVectorColumn = new Communicator<Column,Vector3d>(nGroups_);
92
93 nAtomsInRow_ = AtomCommIntRow->getSize();
94 nAtomsInCol_ = AtomCommIntColumn->getSize();
95 nGroupsInRow_ = cgCommIntRow->getSize();
96 nGroupsInCol_ = cgCommIntColumn->getSize();
97
98 // Modify the data storage objects with the correct layouts and sizes:
99 atomRowData.resize(nAtomsInRow_);
100 atomRowData.setStorageLayout(storageLayout_);
101 atomColData.resize(nAtomsInCol_);
102 atomColData.setStorageLayout(storageLayout_);
103 cgRowData.resize(nGroupsInRow_);
104 cgRowData.setStorageLayout(DataStorage::dslPosition);
105 cgColData.resize(nGroupsInCol_);
106 cgColData.setStorageLayout(DataStorage::dslPosition);
107
108 identsRow.resize(nAtomsInRow_);
109 identsCol.resize(nAtomsInCol_);
110
111 AtomCommIntRow->gather(idents, identsRow);
112 AtomCommIntColumn->gather(idents, identsCol);
113
114 AtomCommIntRow->gather(AtomLocalToGlobal, AtomRowToGlobal);
115 AtomCommIntColumn->gather(AtomLocalToGlobal, AtomColToGlobal);
116
117 cgCommIntRow->gather(cgLocalToGlobal, cgRowToGlobal);
118 cgCommIntColumn->gather(cgLocalToGlobal, cgColToGlobal);
119
120 AtomCommRealRow->gather(massFactors, massFactorsRow);
121 AtomCommRealColumn->gather(massFactors, massFactorsCol);
122
123 groupListRow_.clear();
124 groupListRow_.resize(nGroupsInRow_);
125 for (int i = 0; i < nGroupsInRow_; i++) {
126 int gid = cgRowToGlobal[i];
127 for (int j = 0; j < nAtomsInRow_; j++) {
128 int aid = AtomRowToGlobal[j];
129 if (globalGroupMembership[aid] == gid)
130 groupListRow_[i].push_back(j);
131 }
132 }
133
134 groupListCol_.clear();
135 groupListCol_.resize(nGroupsInCol_);
136 for (int i = 0; i < nGroupsInCol_; i++) {
137 int gid = cgColToGlobal[i];
138 for (int j = 0; j < nAtomsInCol_; j++) {
139 int aid = AtomColToGlobal[j];
140 if (globalGroupMembership[aid] == gid)
141 groupListCol_[i].push_back(j);
142 }
143 }
144
145 skipsForAtom.clear();
146 skipsForAtom.resize(nAtomsInRow_);
147 toposForAtom.clear();
148 toposForAtom.resize(nAtomsInRow_);
149 topoDist.clear();
150 topoDist.resize(nAtomsInRow_);
151 for (int i = 0; i < nAtomsInRow_; i++) {
152 int iglob = AtomRowToGlobal[i];
153
154 for (int j = 0; j < nAtomsInCol_; j++) {
155 int jglob = AtomColToGlobal[j];
156
157 if (excludes.hasPair(iglob, jglob))
158 skipsForAtom[i].push_back(j);
159
160 if (oneTwo.hasPair(iglob, jglob)) {
161 toposForAtom[i].push_back(j);
162 topoDist[i].push_back(1);
163 } else {
164 if (oneThree.hasPair(iglob, jglob)) {
165 toposForAtom[i].push_back(j);
166 topoDist[i].push_back(2);
167 } else {
168 if (oneFour.hasPair(iglob, jglob)) {
169 toposForAtom[i].push_back(j);
170 topoDist[i].push_back(3);
171 }
172 }
173 }
174 }
175 }
176
177 #endif
178
179 groupList_.clear();
180 groupList_.resize(nGroups_);
181 for (int i = 0; i < nGroups_; i++) {
182 int gid = cgLocalToGlobal[i];
183 for (int j = 0; j < nLocal_; j++) {
184 int aid = AtomLocalToGlobal[j];
185 if (globalGroupMembership[aid] == gid) {
186 groupList_[i].push_back(j);
187 }
188 }
189 }
190
191 skipsForAtom.clear();
192 skipsForAtom.resize(nLocal_);
193 toposForAtom.clear();
194 toposForAtom.resize(nLocal_);
195 topoDist.clear();
196 topoDist.resize(nLocal_);
197
198 for (int i = 0; i < nLocal_; i++) {
199 int iglob = AtomLocalToGlobal[i];
200
201 for (int j = 0; j < nLocal_; j++) {
202 int jglob = AtomLocalToGlobal[j];
203
204 if (excludes.hasPair(iglob, jglob))
205 skipsForAtom[i].push_back(j);
206
207 if (oneTwo.hasPair(iglob, jglob)) {
208 toposForAtom[i].push_back(j);
209 topoDist[i].push_back(1);
210 } else {
211 if (oneThree.hasPair(iglob, jglob)) {
212 toposForAtom[i].push_back(j);
213 topoDist[i].push_back(2);
214 } else {
215 if (oneFour.hasPair(iglob, jglob)) {
216 toposForAtom[i].push_back(j);
217 topoDist[i].push_back(3);
218 }
219 }
220 }
221 }
222 }
223
224 createGtypeCutoffMap();
225 }
226
227 void ForceMatrixDecomposition::createGtypeCutoffMap() {
228
229 RealType tol = 1e-6;
230 RealType rc;
231 int atid;
232 set<AtomType*> atypes = info_->getSimulatedAtomTypes();
233 vector<RealType> atypeCutoff;
234 atypeCutoff.resize( atypes.size() );
235
236 for (set<AtomType*>::iterator at = atypes.begin();
237 at != atypes.end(); ++at){
238 atid = (*at)->getIdent();
239
240 if (userChoseCutoff_)
241 atypeCutoff[atid] = userCutoff_;
242 else
243 atypeCutoff[atid] = interactionMan_->getSuggestedCutoffRadius(*at);
244 }
245
246 vector<RealType> gTypeCutoffs;
247
248 // first we do a single loop over the cutoff groups to find the
249 // largest cutoff for any atypes present in this group.
250 #ifdef IS_MPI
251 vector<RealType> groupCutoffRow(nGroupsInRow_, 0.0);
252 groupRowToGtype.resize(nGroupsInRow_);
253 for (int cg1 = 0; cg1 < nGroupsInRow_; cg1++) {
254 vector<int> atomListRow = getAtomsInGroupRow(cg1);
255 for (vector<int>::iterator ia = atomListRow.begin();
256 ia != atomListRow.end(); ++ia) {
257 int atom1 = (*ia);
258 atid = identsRow[atom1];
259 if (atypeCutoff[atid] > groupCutoffRow[cg1]) {
260 groupCutoffRow[cg1] = atypeCutoff[atid];
261 }
262 }
263
264 bool gTypeFound = false;
265 for (int gt = 0; gt < gTypeCutoffs.size(); gt++) {
266 if (abs(groupCutoffRow[cg1] - gTypeCutoffs[gt]) < tol) {
267 groupRowToGtype[cg1] = gt;
268 gTypeFound = true;
269 }
270 }
271 if (!gTypeFound) {
272 gTypeCutoffs.push_back( groupCutoffRow[cg1] );
273 groupRowToGtype[cg1] = gTypeCutoffs.size() - 1;
274 }
275
276 }
277 vector<RealType> groupCutoffCol(nGroupsInCol_, 0.0);
278 groupColToGtype.resize(nGroupsInCol_);
279 for (int cg2 = 0; cg2 < nGroupsInCol_; cg2++) {
280 vector<int> atomListCol = getAtomsInGroupColumn(cg2);
281 for (vector<int>::iterator jb = atomListCol.begin();
282 jb != atomListCol.end(); ++jb) {
283 int atom2 = (*jb);
284 atid = identsCol[atom2];
285 if (atypeCutoff[atid] > groupCutoffCol[cg2]) {
286 groupCutoffCol[cg2] = atypeCutoff[atid];
287 }
288 }
289 bool gTypeFound = false;
290 for (int gt = 0; gt < gTypeCutoffs.size(); gt++) {
291 if (abs(groupCutoffCol[cg2] - gTypeCutoffs[gt]) < tol) {
292 groupColToGtype[cg2] = gt;
293 gTypeFound = true;
294 }
295 }
296 if (!gTypeFound) {
297 gTypeCutoffs.push_back( groupCutoffCol[cg2] );
298 groupColToGtype[cg2] = gTypeCutoffs.size() - 1;
299 }
300 }
301 #else
302
303 vector<RealType> groupCutoff(nGroups_, 0.0);
304 groupToGtype.resize(nGroups_);
305
306 cerr << "nGroups = " << nGroups_ << "\n";
307 for (int cg1 = 0; cg1 < nGroups_; cg1++) {
308
309 groupCutoff[cg1] = 0.0;
310 vector<int> atomList = getAtomsInGroupRow(cg1);
311
312 for (vector<int>::iterator ia = atomList.begin();
313 ia != atomList.end(); ++ia) {
314 int atom1 = (*ia);
315 atid = idents[atom1];
316 if (atypeCutoff[atid] > groupCutoff[cg1]) {
317 groupCutoff[cg1] = atypeCutoff[atid];
318 }
319 }
320
321 bool gTypeFound = false;
322 for (int gt = 0; gt < gTypeCutoffs.size(); gt++) {
323 if (abs(groupCutoff[cg1] - gTypeCutoffs[gt]) < tol) {
324 groupToGtype[cg1] = gt;
325 gTypeFound = true;
326 }
327 }
328 if (!gTypeFound) {
329 gTypeCutoffs.push_back( groupCutoff[cg1] );
330 groupToGtype[cg1] = gTypeCutoffs.size() - 1;
331 }
332 }
333 #endif
334
335 cerr << "gTypeCutoffs.size() = " << gTypeCutoffs.size() << "\n";
336 // Now we find the maximum group cutoff value present in the simulation
337
338 RealType groupMax = *max_element(gTypeCutoffs.begin(), gTypeCutoffs.end());
339
340 #ifdef IS_MPI
341 MPI::COMM_WORLD.Allreduce(&groupMax, &groupMax, 1, MPI::REALTYPE, MPI::MAX);
342 #endif
343
344 RealType tradRcut = groupMax;
345
346 for (int i = 0; i < gTypeCutoffs.size(); i++) {
347 for (int j = 0; j < gTypeCutoffs.size(); j++) {
348 RealType thisRcut;
349 switch(cutoffPolicy_) {
350 case TRADITIONAL:
351 thisRcut = tradRcut;
352 break;
353 case MIX:
354 thisRcut = 0.5 * (gTypeCutoffs[i] + gTypeCutoffs[j]);
355 break;
356 case MAX:
357 thisRcut = max(gTypeCutoffs[i], gTypeCutoffs[j]);
358 break;
359 default:
360 sprintf(painCave.errMsg,
361 "ForceMatrixDecomposition::createGtypeCutoffMap "
362 "hit an unknown cutoff policy!\n");
363 painCave.severity = OPENMD_ERROR;
364 painCave.isFatal = 1;
365 simError();
366 break;
367 }
368
369 pair<int,int> key = make_pair(i,j);
370 gTypeCutoffMap[key].first = thisRcut;
371
372 if (thisRcut > largestRcut_) largestRcut_ = thisRcut;
373
374 gTypeCutoffMap[key].second = thisRcut*thisRcut;
375
376 gTypeCutoffMap[key].third = pow(thisRcut + skinThickness_, 2);
377
378 // sanity check
379
380 if (userChoseCutoff_) {
381 if (abs(gTypeCutoffMap[key].first - userCutoff_) > 0.0001) {
382 sprintf(painCave.errMsg,
383 "ForceMatrixDecomposition::createGtypeCutoffMap "
384 "user-specified rCut (%lf) does not match computed group Cutoff\n", userCutoff_);
385 painCave.severity = OPENMD_ERROR;
386 painCave.isFatal = 1;
387 simError();
388 }
389 }
390 }
391 }
392 }
393
394
395 groupCutoffs ForceMatrixDecomposition::getGroupCutoffs(int cg1, int cg2) {
396 int i, j;
397 #ifdef IS_MPI
398 i = groupRowToGtype[cg1];
399 j = groupColToGtype[cg2];
400 #else
401 i = groupToGtype[cg1];
402 j = groupToGtype[cg2];
403 #endif
404 return gTypeCutoffMap[make_pair(i,j)];
405 }
406
407 int ForceMatrixDecomposition::getTopologicalDistance(int atom1, int atom2) {
408 for (int j = 0; j < toposForAtom[atom1].size(); j++) {
409 if (toposForAtom[atom1][j] == atom2)
410 return topoDist[atom1][j];
411 }
412 return 0;
413 }
414
415 void ForceMatrixDecomposition::zeroWorkArrays() {
416 pairwisePot = 0.0;
417 embeddingPot = 0.0;
418
419 #ifdef IS_MPI
420 if (storageLayout_ & DataStorage::dslForce) {
421 fill(atomRowData.force.begin(), atomRowData.force.end(), V3Zero);
422 fill(atomColData.force.begin(), atomColData.force.end(), V3Zero);
423 }
424
425 if (storageLayout_ & DataStorage::dslTorque) {
426 fill(atomRowData.torque.begin(), atomRowData.torque.end(), V3Zero);
427 fill(atomColData.torque.begin(), atomColData.torque.end(), V3Zero);
428 }
429
430 fill(pot_row.begin(), pot_row.end(),
431 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
432
433 fill(pot_col.begin(), pot_col.end(),
434 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
435
436 if (storageLayout_ & DataStorage::dslParticlePot) {
437 fill(atomRowData.particlePot.begin(), atomRowData.particlePot.end(), 0.0);
438 fill(atomColData.particlePot.begin(), atomColData.particlePot.end(), 0.0);
439 }
440
441 if (storageLayout_ & DataStorage::dslDensity) {
442 fill(atomRowData.density.begin(), atomRowData.density.end(), 0.0);
443 fill(atomColData.density.begin(), atomColData.density.end(), 0.0);
444 }
445
446 if (storageLayout_ & DataStorage::dslFunctional) {
447 fill(atomRowData.functional.begin(), atomRowData.functional.end(), 0.0);
448 fill(atomColData.functional.begin(), atomColData.functional.end(), 0.0);
449 }
450
451 if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
452 fill(atomRowData.functionalDerivative.begin(),
453 atomRowData.functionalDerivative.end(), 0.0);
454 fill(atomColData.functionalDerivative.begin(),
455 atomColData.functionalDerivative.end(), 0.0);
456 }
457
458 #else
459
460 if (storageLayout_ & DataStorage::dslParticlePot) {
461 fill(snap_->atomData.particlePot.begin(),
462 snap_->atomData.particlePot.end(), 0.0);
463 }
464
465 if (storageLayout_ & DataStorage::dslDensity) {
466 fill(snap_->atomData.density.begin(),
467 snap_->atomData.density.end(), 0.0);
468 }
469 if (storageLayout_ & DataStorage::dslFunctional) {
470 fill(snap_->atomData.functional.begin(),
471 snap_->atomData.functional.end(), 0.0);
472 }
473 if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
474 fill(snap_->atomData.functionalDerivative.begin(),
475 snap_->atomData.functionalDerivative.end(), 0.0);
476 }
477 #endif
478
479 }
480
481
482 void ForceMatrixDecomposition::distributeData() {
483 snap_ = sman_->getCurrentSnapshot();
484 storageLayout_ = sman_->getStorageLayout();
485 #ifdef IS_MPI
486
487 // gather up the atomic positions
488 AtomCommVectorRow->gather(snap_->atomData.position,
489 atomRowData.position);
490 AtomCommVectorColumn->gather(snap_->atomData.position,
491 atomColData.position);
492
493 // gather up the cutoff group positions
494 cgCommVectorRow->gather(snap_->cgData.position,
495 cgRowData.position);
496 cgCommVectorColumn->gather(snap_->cgData.position,
497 cgColData.position);
498
499 // if needed, gather the atomic rotation matrices
500 if (storageLayout_ & DataStorage::dslAmat) {
501 AtomCommMatrixRow->gather(snap_->atomData.aMat,
502 atomRowData.aMat);
503 AtomCommMatrixColumn->gather(snap_->atomData.aMat,
504 atomColData.aMat);
505 }
506
507 // if needed, gather the atomic eletrostatic frames
508 if (storageLayout_ & DataStorage::dslElectroFrame) {
509 AtomCommMatrixRow->gather(snap_->atomData.electroFrame,
510 atomRowData.electroFrame);
511 AtomCommMatrixColumn->gather(snap_->atomData.electroFrame,
512 atomColData.electroFrame);
513 }
514 #endif
515 }
516
517 /* collects information obtained during the pre-pair loop onto local
518 * data structures.
519 */
520 void ForceMatrixDecomposition::collectIntermediateData() {
521 snap_ = sman_->getCurrentSnapshot();
522 storageLayout_ = sman_->getStorageLayout();
523 #ifdef IS_MPI
524
525 if (storageLayout_ & DataStorage::dslDensity) {
526
527 AtomCommRealRow->scatter(atomRowData.density,
528 snap_->atomData.density);
529
530 int n = snap_->atomData.density.size();
531 vector<RealType> rho_tmp(n, 0.0);
532 AtomCommRealColumn->scatter(atomColData.density, rho_tmp);
533 for (int i = 0; i < n; i++)
534 snap_->atomData.density[i] += rho_tmp[i];
535 }
536 #endif
537 }
538
539 /*
540 * redistributes information obtained during the pre-pair loop out to
541 * row and column-indexed data structures
542 */
543 void ForceMatrixDecomposition::distributeIntermediateData() {
544 snap_ = sman_->getCurrentSnapshot();
545 storageLayout_ = sman_->getStorageLayout();
546 #ifdef IS_MPI
547 if (storageLayout_ & DataStorage::dslFunctional) {
548 AtomCommRealRow->gather(snap_->atomData.functional,
549 atomRowData.functional);
550 AtomCommRealColumn->gather(snap_->atomData.functional,
551 atomColData.functional);
552 }
553
554 if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
555 AtomCommRealRow->gather(snap_->atomData.functionalDerivative,
556 atomRowData.functionalDerivative);
557 AtomCommRealColumn->gather(snap_->atomData.functionalDerivative,
558 atomColData.functionalDerivative);
559 }
560 #endif
561 }
562
563
564 void ForceMatrixDecomposition::collectData() {
565 snap_ = sman_->getCurrentSnapshot();
566 storageLayout_ = sman_->getStorageLayout();
567 #ifdef IS_MPI
568 int n = snap_->atomData.force.size();
569 vector<Vector3d> frc_tmp(n, V3Zero);
570
571 AtomCommVectorRow->scatter(atomRowData.force, frc_tmp);
572 for (int i = 0; i < n; i++) {
573 snap_->atomData.force[i] += frc_tmp[i];
574 frc_tmp[i] = 0.0;
575 }
576
577 AtomCommVectorColumn->scatter(atomColData.force, frc_tmp);
578 for (int i = 0; i < n; i++)
579 snap_->atomData.force[i] += frc_tmp[i];
580
581
582 if (storageLayout_ & DataStorage::dslTorque) {
583
584 int nt = snap_->atomData.force.size();
585 vector<Vector3d> trq_tmp(nt, V3Zero);
586
587 AtomCommVectorRow->scatter(atomRowData.torque, trq_tmp);
588 for (int i = 0; i < n; i++) {
589 snap_->atomData.torque[i] += trq_tmp[i];
590 trq_tmp[i] = 0.0;
591 }
592
593 AtomCommVectorColumn->scatter(atomColData.torque, trq_tmp);
594 for (int i = 0; i < n; i++)
595 snap_->atomData.torque[i] += trq_tmp[i];
596 }
597
598 nLocal_ = snap_->getNumberOfAtoms();
599
600 vector<potVec> pot_temp(nLocal_,
601 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
602
603 // scatter/gather pot_row into the members of my column
604
605 AtomCommPotRow->scatter(pot_row, pot_temp);
606
607 for (int ii = 0; ii < pot_temp.size(); ii++ )
608 pairwisePot += pot_temp[ii];
609
610 fill(pot_temp.begin(), pot_temp.end(),
611 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
612
613 AtomCommPotColumn->scatter(pot_col, pot_temp);
614
615 for (int ii = 0; ii < pot_temp.size(); ii++ )
616 pairwisePot += pot_temp[ii];
617 #endif
618
619 }
620
621 int ForceMatrixDecomposition::getNAtomsInRow() {
622 #ifdef IS_MPI
623 return nAtomsInRow_;
624 #else
625 return nLocal_;
626 #endif
627 }
628
629 /**
630 * returns the list of atoms belonging to this group.
631 */
632 vector<int> ForceMatrixDecomposition::getAtomsInGroupRow(int cg1){
633 #ifdef IS_MPI
634 return groupListRow_[cg1];
635 #else
636 return groupList_[cg1];
637 #endif
638 }
639
640 vector<int> ForceMatrixDecomposition::getAtomsInGroupColumn(int cg2){
641 #ifdef IS_MPI
642 return groupListCol_[cg2];
643 #else
644 return groupList_[cg2];
645 #endif
646 }
647
648 Vector3d ForceMatrixDecomposition::getIntergroupVector(int cg1, int cg2){
649 Vector3d d;
650
651 #ifdef IS_MPI
652 d = cgColData.position[cg2] - cgRowData.position[cg1];
653 #else
654 d = snap_->cgData.position[cg2] - snap_->cgData.position[cg1];
655 #endif
656
657 snap_->wrapVector(d);
658 return d;
659 }
660
661
662 Vector3d ForceMatrixDecomposition::getAtomToGroupVectorRow(int atom1, int cg1){
663
664 Vector3d d;
665
666 #ifdef IS_MPI
667 d = cgRowData.position[cg1] - atomRowData.position[atom1];
668 #else
669 d = snap_->cgData.position[cg1] - snap_->atomData.position[atom1];
670 #endif
671
672 snap_->wrapVector(d);
673 return d;
674 }
675
676 Vector3d ForceMatrixDecomposition::getAtomToGroupVectorColumn(int atom2, int cg2){
677 Vector3d d;
678
679 #ifdef IS_MPI
680 d = cgColData.position[cg2] - atomColData.position[atom2];
681 #else
682 d = snap_->cgData.position[cg2] - snap_->atomData.position[atom2];
683 #endif
684
685 snap_->wrapVector(d);
686 return d;
687 }
688
689 RealType ForceMatrixDecomposition::getMassFactorRow(int atom1) {
690 #ifdef IS_MPI
691 return massFactorsRow[atom1];
692 #else
693 return massFactors[atom1];
694 #endif
695 }
696
697 RealType ForceMatrixDecomposition::getMassFactorColumn(int atom2) {
698 #ifdef IS_MPI
699 return massFactorsCol[atom2];
700 #else
701 return massFactors[atom2];
702 #endif
703
704 }
705
706 Vector3d ForceMatrixDecomposition::getInteratomicVector(int atom1, int atom2){
707 Vector3d d;
708
709 #ifdef IS_MPI
710 d = atomColData.position[atom2] - atomRowData.position[atom1];
711 #else
712 d = snap_->atomData.position[atom2] - snap_->atomData.position[atom1];
713 #endif
714
715 snap_->wrapVector(d);
716 return d;
717 }
718
719 vector<int> ForceMatrixDecomposition::getSkipsForAtom(int atom1) {
720 return skipsForAtom[atom1];
721 }
722
723 /**
724 * There are a number of reasons to skip a pair or a
725 * particle. Mostly we do this to exclude atoms who are involved in
726 * short range interactions (bonds, bends, torsions), but we also
727 * need to exclude some overcounted interactions that result from
728 * the parallel decomposition.
729 */
730 bool ForceMatrixDecomposition::skipAtomPair(int atom1, int atom2) {
731 int unique_id_1, unique_id_2;
732
733 #ifdef IS_MPI
734 // in MPI, we have to look up the unique IDs for each atom
735 unique_id_1 = AtomRowToGlobal[atom1];
736 unique_id_2 = AtomColToGlobal[atom2];
737
738 // this situation should only arise in MPI simulations
739 if (unique_id_1 == unique_id_2) return true;
740
741 // this prevents us from doing the pair on multiple processors
742 if (unique_id_1 < unique_id_2) {
743 if ((unique_id_1 + unique_id_2) % 2 == 0) return true;
744 } else {
745 if ((unique_id_1 + unique_id_2) % 2 == 1) return true;
746 }
747 #else
748 // in the normal loop, the atom numbers are unique
749 unique_id_1 = atom1;
750 unique_id_2 = atom2;
751 #endif
752
753 for (vector<int>::iterator i = skipsForAtom[atom1].begin();
754 i != skipsForAtom[atom1].end(); ++i) {
755 if ( (*i) == unique_id_2 ) return true;
756 }
757
758 return false;
759 }
760
761
762 void ForceMatrixDecomposition::addForceToAtomRow(int atom1, Vector3d fg){
763 #ifdef IS_MPI
764 atomRowData.force[atom1] += fg;
765 #else
766 snap_->atomData.force[atom1] += fg;
767 #endif
768 }
769
770 void ForceMatrixDecomposition::addForceToAtomColumn(int atom2, Vector3d fg){
771 #ifdef IS_MPI
772 atomColData.force[atom2] += fg;
773 #else
774 snap_->atomData.force[atom2] += fg;
775 #endif
776 }
777
778 // filling interaction blocks with pointers
779 void ForceMatrixDecomposition::fillInteractionData(InteractionData &idat,
780 int atom1, int atom2) {
781 #ifdef IS_MPI
782
783 idat.atypes = make_pair( ff_->getAtomType(identsRow[atom1]),
784 ff_->getAtomType(identsCol[atom2]) );
785
786 if (storageLayout_ & DataStorage::dslAmat) {
787 idat.A1 = &(atomRowData.aMat[atom1]);
788 idat.A2 = &(atomColData.aMat[atom2]);
789 }
790
791 if (storageLayout_ & DataStorage::dslElectroFrame) {
792 idat.eFrame1 = &(atomRowData.electroFrame[atom1]);
793 idat.eFrame2 = &(atomColData.electroFrame[atom2]);
794 }
795
796 if (storageLayout_ & DataStorage::dslTorque) {
797 idat.t1 = &(atomRowData.torque[atom1]);
798 idat.t2 = &(atomColData.torque[atom2]);
799 }
800
801 if (storageLayout_ & DataStorage::dslDensity) {
802 idat.rho1 = &(atomRowData.density[atom1]);
803 idat.rho2 = &(atomColData.density[atom2]);
804 }
805
806 if (storageLayout_ & DataStorage::dslFunctional) {
807 idat.frho1 = &(atomRowData.functional[atom1]);
808 idat.frho2 = &(atomColData.functional[atom2]);
809 }
810
811 if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
812 idat.dfrho1 = &(atomRowData.functionalDerivative[atom1]);
813 idat.dfrho2 = &(atomColData.functionalDerivative[atom2]);
814 }
815
816 if (storageLayout_ & DataStorage::dslParticlePot) {
817 idat.particlePot1 = &(atomRowData.particlePot[atom1]);
818 idat.particlePot2 = &(atomColData.particlePot[atom2]);
819 }
820
821 #else
822
823 idat.atypes = make_pair( ff_->getAtomType(idents[atom1]),
824 ff_->getAtomType(idents[atom2]) );
825
826 if (storageLayout_ & DataStorage::dslAmat) {
827 idat.A1 = &(snap_->atomData.aMat[atom1]);
828 idat.A2 = &(snap_->atomData.aMat[atom2]);
829 }
830
831 if (storageLayout_ & DataStorage::dslElectroFrame) {
832 idat.eFrame1 = &(snap_->atomData.electroFrame[atom1]);
833 idat.eFrame2 = &(snap_->atomData.electroFrame[atom2]);
834 }
835
836 if (storageLayout_ & DataStorage::dslTorque) {
837 idat.t1 = &(snap_->atomData.torque[atom1]);
838 idat.t2 = &(snap_->atomData.torque[atom2]);
839 }
840
841 if (storageLayout_ & DataStorage::dslDensity) {
842 idat.rho1 = &(snap_->atomData.density[atom1]);
843 idat.rho2 = &(snap_->atomData.density[atom2]);
844 }
845
846 if (storageLayout_ & DataStorage::dslFunctional) {
847 idat.frho1 = &(snap_->atomData.functional[atom1]);
848 idat.frho2 = &(snap_->atomData.functional[atom2]);
849 }
850
851 if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
852 idat.dfrho1 = &(snap_->atomData.functionalDerivative[atom1]);
853 idat.dfrho2 = &(snap_->atomData.functionalDerivative[atom2]);
854 }
855
856 if (storageLayout_ & DataStorage::dslParticlePot) {
857 idat.particlePot1 = &(snap_->atomData.particlePot[atom1]);
858 idat.particlePot2 = &(snap_->atomData.particlePot[atom2]);
859 }
860
861 #endif
862 }
863
864
865 void ForceMatrixDecomposition::unpackInteractionData(InteractionData &idat, int atom1, int atom2) {
866 #ifdef IS_MPI
867 pot_row[atom1] += 0.5 * *(idat.pot);
868 pot_col[atom2] += 0.5 * *(idat.pot);
869
870 atomRowData.force[atom1] += *(idat.f1);
871 atomColData.force[atom2] -= *(idat.f1);
872 #else
873 pairwisePot += *(idat.pot);
874
875 snap_->atomData.force[atom1] += *(idat.f1);
876 snap_->atomData.force[atom2] -= *(idat.f1);
877 #endif
878
879 }
880
881
882 void ForceMatrixDecomposition::fillSkipData(InteractionData &idat,
883 int atom1, int atom2) {
884 // Still Missing:: skippedCharge fill must be added to DataStorage
885 #ifdef IS_MPI
886 idat.atypes = make_pair( ff_->getAtomType(identsRow[atom1]),
887 ff_->getAtomType(identsCol[atom2]) );
888
889 if (storageLayout_ & DataStorage::dslElectroFrame) {
890 idat.eFrame1 = &(atomRowData.electroFrame[atom1]);
891 idat.eFrame2 = &(atomColData.electroFrame[atom2]);
892 }
893 if (storageLayout_ & DataStorage::dslTorque) {
894 idat.t1 = &(atomRowData.torque[atom1]);
895 idat.t2 = &(atomColData.torque[atom2]);
896 }
897 #else
898 idat.atypes = make_pair( ff_->getAtomType(idents[atom1]),
899 ff_->getAtomType(idents[atom2]) );
900
901 if (storageLayout_ & DataStorage::dslElectroFrame) {
902 idat.eFrame1 = &(snap_->atomData.electroFrame[atom1]);
903 idat.eFrame2 = &(snap_->atomData.electroFrame[atom2]);
904 }
905 if (storageLayout_ & DataStorage::dslTorque) {
906 idat.t1 = &(snap_->atomData.torque[atom1]);
907 idat.t2 = &(snap_->atomData.torque[atom2]);
908 }
909 #endif
910 }
911
912
913 void ForceMatrixDecomposition::unpackSkipData(InteractionData &idat, int atom1, int atom2) {
914 #ifdef IS_MPI
915 pot_row[atom1] += 0.5 * *(idat.pot);
916 pot_col[atom2] += 0.5 * *(idat.pot);
917 #else
918 pairwisePot += *(idat.pot);
919 #endif
920
921 }
922
923
924 /*
925 * buildNeighborList
926 *
927 * first element of pair is row-indexed CutoffGroup
928 * second element of pair is column-indexed CutoffGroup
929 */
930 vector<pair<int, int> > ForceMatrixDecomposition::buildNeighborList() {
931
932 vector<pair<int, int> > neighborList;
933 groupCutoffs cuts;
934 #ifdef IS_MPI
935 cellListRow_.clear();
936 cellListCol_.clear();
937 #else
938 cellList_.clear();
939 #endif
940
941 RealType rList_ = (largestRcut_ + skinThickness_);
942 RealType rl2 = rList_ * rList_;
943 Snapshot* snap_ = sman_->getCurrentSnapshot();
944 Mat3x3d Hmat = snap_->getHmat();
945 Vector3d Hx = Hmat.getColumn(0);
946 Vector3d Hy = Hmat.getColumn(1);
947 Vector3d Hz = Hmat.getColumn(2);
948
949 nCells_.x() = (int) ( Hx.length() )/ rList_;
950 nCells_.y() = (int) ( Hy.length() )/ rList_;
951 nCells_.z() = (int) ( Hz.length() )/ rList_;
952
953 Mat3x3d invHmat = snap_->getInvHmat();
954 Vector3d rs, scaled, dr;
955 Vector3i whichCell;
956 int cellIndex;
957 int nCtot = nCells_.x() * nCells_.y() * nCells_.z();
958
959 #ifdef IS_MPI
960 cellListRow_.resize(nCtot);
961 cellListCol_.resize(nCtot);
962 #else
963 cellList_.resize(nCtot);
964 #endif
965
966 #ifdef IS_MPI
967 for (int i = 0; i < nGroupsInRow_; i++) {
968 rs = cgRowData.position[i];
969
970 // scaled positions relative to the box vectors
971 scaled = invHmat * rs;
972
973 // wrap the vector back into the unit box by subtracting integer box
974 // numbers
975 for (int j = 0; j < 3; j++) {
976 scaled[j] -= roundMe(scaled[j]);
977 scaled[j] += 0.5;
978 }
979
980 // find xyz-indices of cell that cutoffGroup is in.
981 whichCell.x() = nCells_.x() * scaled.x();
982 whichCell.y() = nCells_.y() * scaled.y();
983 whichCell.z() = nCells_.z() * scaled.z();
984
985 // find single index of this cell:
986 cellIndex = Vlinear(whichCell, nCells_);
987
988 // add this cutoff group to the list of groups in this cell;
989 cellListRow_[cellIndex].push_back(i);
990 }
991
992 for (int i = 0; i < nGroupsInCol_; i++) {
993 rs = cgColData.position[i];
994
995 // scaled positions relative to the box vectors
996 scaled = invHmat * rs;
997
998 // wrap the vector back into the unit box by subtracting integer box
999 // numbers
1000 for (int j = 0; j < 3; j++) {
1001 scaled[j] -= roundMe(scaled[j]);
1002 scaled[j] += 0.5;
1003 }
1004
1005 // find xyz-indices of cell that cutoffGroup is in.
1006 whichCell.x() = nCells_.x() * scaled.x();
1007 whichCell.y() = nCells_.y() * scaled.y();
1008 whichCell.z() = nCells_.z() * scaled.z();
1009
1010 // find single index of this cell:
1011 cellIndex = Vlinear(whichCell, nCells_);
1012
1013 // add this cutoff group to the list of groups in this cell;
1014 cellListCol_[cellIndex].push_back(i);
1015 }
1016 #else
1017 for (int i = 0; i < nGroups_; i++) {
1018 rs = snap_->cgData.position[i];
1019
1020 // scaled positions relative to the box vectors
1021 scaled = invHmat * rs;
1022
1023 // wrap the vector back into the unit box by subtracting integer box
1024 // numbers
1025 for (int j = 0; j < 3; j++) {
1026 scaled[j] -= roundMe(scaled[j]);
1027 scaled[j] += 0.5;
1028 }
1029
1030 // find xyz-indices of cell that cutoffGroup is in.
1031 whichCell.x() = nCells_.x() * scaled.x();
1032 whichCell.y() = nCells_.y() * scaled.y();
1033 whichCell.z() = nCells_.z() * scaled.z();
1034
1035 // find single index of this cell:
1036 cellIndex = Vlinear(whichCell, nCells_);
1037
1038 // add this cutoff group to the list of groups in this cell;
1039 cellList_[cellIndex].push_back(i);
1040 }
1041 #endif
1042
1043 for (int m1z = 0; m1z < nCells_.z(); m1z++) {
1044 for (int m1y = 0; m1y < nCells_.y(); m1y++) {
1045 for (int m1x = 0; m1x < nCells_.x(); m1x++) {
1046 Vector3i m1v(m1x, m1y, m1z);
1047 int m1 = Vlinear(m1v, nCells_);
1048
1049 for (vector<Vector3i>::iterator os = cellOffsets_.begin();
1050 os != cellOffsets_.end(); ++os) {
1051
1052 Vector3i m2v = m1v + (*os);
1053
1054 if (m2v.x() >= nCells_.x()) {
1055 m2v.x() = 0;
1056 } else if (m2v.x() < 0) {
1057 m2v.x() = nCells_.x() - 1;
1058 }
1059
1060 if (m2v.y() >= nCells_.y()) {
1061 m2v.y() = 0;
1062 } else if (m2v.y() < 0) {
1063 m2v.y() = nCells_.y() - 1;
1064 }
1065
1066 if (m2v.z() >= nCells_.z()) {
1067 m2v.z() = 0;
1068 } else if (m2v.z() < 0) {
1069 m2v.z() = nCells_.z() - 1;
1070 }
1071
1072 int m2 = Vlinear (m2v, nCells_);
1073
1074 #ifdef IS_MPI
1075 for (vector<int>::iterator j1 = cellListRow_[m1].begin();
1076 j1 != cellListRow_[m1].end(); ++j1) {
1077 for (vector<int>::iterator j2 = cellListCol_[m2].begin();
1078 j2 != cellListCol_[m2].end(); ++j2) {
1079
1080 // Always do this if we're in different cells or if
1081 // we're in the same cell and the global index of the
1082 // j2 cutoff group is less than the j1 cutoff group
1083
1084 if (m2 != m1 || cgColToGlobal[(*j2)] < cgRowToGlobal[(*j1)]) {
1085 dr = cgColData.position[(*j2)] - cgRowData.position[(*j1)];
1086 snap_->wrapVector(dr);
1087 cuts = getGroupCutoffs( (*j1), (*j2) );
1088 if (dr.lengthSquare() < cuts.third) {
1089 neighborList.push_back(make_pair((*j1), (*j2)));
1090 }
1091 }
1092 }
1093 }
1094 #else
1095
1096 for (vector<int>::iterator j1 = cellList_[m1].begin();
1097 j1 != cellList_[m1].end(); ++j1) {
1098 for (vector<int>::iterator j2 = cellList_[m2].begin();
1099 j2 != cellList_[m2].end(); ++j2) {
1100
1101 // Always do this if we're in different cells or if
1102 // we're in the same cell and the global index of the
1103 // j2 cutoff group is less than the j1 cutoff group
1104
1105 if (m2 != m1 || (*j2) < (*j1)) {
1106 dr = snap_->cgData.position[(*j2)] - snap_->cgData.position[(*j1)];
1107 snap_->wrapVector(dr);
1108 cuts = getGroupCutoffs( (*j1), (*j2) );
1109 if (dr.lengthSquare() < cuts.third) {
1110 neighborList.push_back(make_pair((*j1), (*j2)));
1111 }
1112 }
1113 }
1114 }
1115 #endif
1116 }
1117 }
1118 }
1119 }
1120
1121 // save the local cutoff group positions for the check that is
1122 // done on each loop:
1123 saved_CG_positions_.clear();
1124 for (int i = 0; i < nGroups_; i++)
1125 saved_CG_positions_.push_back(snap_->cgData.position[i]);
1126
1127 return neighborList;
1128 }
1129 } //end namespace OpenMD