ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/parallel/ForceMatrixDecomposition.cpp
(Generate patch)

Comparing branches/development/src/parallel/ForceMatrixDecomposition.cpp (file contents):
Revision 1568 by gezelter, Wed May 25 16:20:37 2011 UTC vs.
Revision 1577 by gezelter, Wed Jun 8 20:26:56 2011 UTC

# Line 42 | Line 42
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 {
# Line 54 | Line 55 | namespace OpenMD {
55    void ForceMatrixDecomposition::distributeInitialData() {
56      snap_ = sman_->getCurrentSnapshot();
57      storageLayout_ = sman_->getStorageLayout();
58 +    ff_ = info_->getForceField();
59      nLocal_ = snap_->getNumberOfAtoms();
58    nGroups_ = snap_->getNumberOfCutoffGroups();
60  
61 +    nGroups_ = info_->getNLocalCutoffGroups();
62 +    // gather the information for atomtype IDs (atids):
63 +    identsLocal = info_->getIdentArray();
64 +    AtomLocalToGlobal = info_->getGlobalAtomIndices();
65 +    cgLocalToGlobal = info_->getGlobalGroupIndices();
66 +    vector<int> globalGroupMembership = info_->getGlobalGroupMembership();
67 +    vector<RealType> massFactorsLocal = info_->getMassFactors();
68 +    PairList excludes = info_->getExcludedInteractions();
69 +    PairList oneTwo = info_->getOneTwoInteractions();
70 +    PairList oneThree = info_->getOneThreeInteractions();
71 +    PairList oneFour = info_->getOneFourInteractions();
72 +
73   #ifdef IS_MPI
74  
75      AtomCommIntRow = new Communicator<Row,int>(nLocal_);
76      AtomCommRealRow = new Communicator<Row,RealType>(nLocal_);
77      AtomCommVectorRow = new Communicator<Row,Vector3d>(nLocal_);
78      AtomCommMatrixRow = new Communicator<Row,Mat3x3d>(nLocal_);
79 +    AtomCommPotRow = new Communicator<Row,potVec>(nLocal_);
80  
81      AtomCommIntColumn = new Communicator<Column,int>(nLocal_);
82      AtomCommRealColumn = new Communicator<Column,RealType>(nLocal_);
83      AtomCommVectorColumn = new Communicator<Column,Vector3d>(nLocal_);
84      AtomCommMatrixColumn = new Communicator<Column,Mat3x3d>(nLocal_);
85 +    AtomCommPotColumn = new Communicator<Column,potVec>(nLocal_);
86  
87      cgCommIntRow = new Communicator<Row,int>(nGroups_);
88      cgCommVectorRow = new Communicator<Row,Vector3d>(nGroups_);
# Line 88 | Line 103 | namespace OpenMD {
103      cgRowData.setStorageLayout(DataStorage::dslPosition);
104      cgColData.resize(nGroupsInCol_);
105      cgColData.setStorageLayout(DataStorage::dslPosition);
106 +        
107 +    identsRow.resize(nAtomsInRow_);
108 +    identsCol.resize(nAtomsInCol_);
109      
92    vector<vector<RealType> > pot_row(N_INTERACTION_FAMILIES,
93                                      vector<RealType> (nAtomsInRow_, 0.0));
94    vector<vector<RealType> > pot_col(N_INTERACTION_FAMILIES,
95                                      vector<RealType> (nAtomsInCol_, 0.0));
96
97
98    vector<RealType> pot_local(N_INTERACTION_FAMILIES, 0.0);
99    
100    // gather the information for atomtype IDs (atids):
101    vector<int> identsLocal = info_->getIdentArray();
102    identsRow.reserve(nAtomsInRow_);
103    identsCol.reserve(nAtomsInCol_);
104    
110      AtomCommIntRow->gather(identsLocal, identsRow);
111      AtomCommIntColumn->gather(identsLocal, identsCol);
112      
108    AtomLocalToGlobal = info_->getGlobalAtomIndices();
113      AtomCommIntRow->gather(AtomLocalToGlobal, AtomRowToGlobal);
114      AtomCommIntColumn->gather(AtomLocalToGlobal, AtomColToGlobal);
115      
112    cgLocalToGlobal = info_->getGlobalGroupIndices();
116      cgCommIntRow->gather(cgLocalToGlobal, cgRowToGlobal);
117      cgCommIntColumn->gather(cgLocalToGlobal, cgColToGlobal);
118  
119 <    // still need:
120 <    // topoDist
121 <    // exclude
119 >    AtomCommRealRow->gather(massFactorsLocal, massFactorsRow);
120 >    AtomCommRealColumn->gather(massFactorsLocal, massFactorsCol);
121 >
122 >    groupListRow_.clear();
123 >    groupListRow_.resize(nGroupsInRow_);
124 >    for (int i = 0; i < nGroupsInRow_; i++) {
125 >      int gid = cgRowToGlobal[i];
126 >      for (int j = 0; j < nAtomsInRow_; j++) {
127 >        int aid = AtomRowToGlobal[j];
128 >        if (globalGroupMembership[aid] == gid)
129 >          groupListRow_[i].push_back(j);
130 >      }      
131 >    }
132 >
133 >    groupListCol_.clear();
134 >    groupListCol_.resize(nGroupsInCol_);
135 >    for (int i = 0; i < nGroupsInCol_; i++) {
136 >      int gid = cgColToGlobal[i];
137 >      for (int j = 0; j < nAtomsInCol_; j++) {
138 >        int aid = AtomColToGlobal[j];
139 >        if (globalGroupMembership[aid] == gid)
140 >          groupListCol_[i].push_back(j);
141 >      }      
142 >    }
143 >
144 >    skipsForRowAtom.clear();
145 >    skipsForRowAtom.resize(nAtomsInRow_);
146 >    for (int i = 0; i < nAtomsInRow_; i++) {
147 >      int iglob = AtomRowToGlobal[i];
148 >      for (int j = 0; j < nAtomsInCol_; j++) {
149 >        int jglob = AtomColToGlobal[j];        
150 >        if (excludes.hasPair(iglob, jglob))
151 >          skipsForRowAtom[i].push_back(j);      
152 >      }      
153 >    }
154 >
155 >    toposForRowAtom.clear();
156 >    toposForRowAtom.resize(nAtomsInRow_);
157 >    for (int i = 0; i < nAtomsInRow_; i++) {
158 >      int iglob = AtomRowToGlobal[i];
159 >      int nTopos = 0;
160 >      for (int j = 0; j < nAtomsInCol_; j++) {
161 >        int jglob = AtomColToGlobal[j];        
162 >        if (oneTwo.hasPair(iglob, jglob)) {
163 >          toposForRowAtom[i].push_back(j);
164 >          topoDistRow[i][nTopos] = 1;
165 >          nTopos++;
166 >        }
167 >        if (oneThree.hasPair(iglob, jglob)) {
168 >          toposForRowAtom[i].push_back(j);
169 >          topoDistRow[i][nTopos] = 2;
170 >          nTopos++;
171 >        }
172 >        if (oneFour.hasPair(iglob, jglob)) {
173 >          toposForRowAtom[i].push_back(j);
174 >          topoDistRow[i][nTopos] = 3;
175 >          nTopos++;
176 >        }
177 >      }      
178 >    }
179 >
180 > #endif
181 >    groupList_.clear();
182 >    groupList_.resize(nGroups_);
183 >    for (int i = 0; i < nGroups_; i++) {
184 >      int gid = cgLocalToGlobal[i];
185 >      for (int j = 0; j < nLocal_; j++) {
186 >        int aid = AtomLocalToGlobal[j];
187 >        if (globalGroupMembership[aid] == gid) {
188 >          groupList_[i].push_back(j);
189 >
190 >        }
191 >      }      
192 >    }
193 >
194 >    skipsForLocalAtom.clear();
195 >    skipsForLocalAtom.resize(nLocal_);
196 >
197 >    for (int i = 0; i < nLocal_; i++) {
198 >      int iglob = AtomLocalToGlobal[i];
199 >      for (int j = 0; j < nLocal_; j++) {
200 >        int jglob = AtomLocalToGlobal[j];        
201 >        if (excludes.hasPair(iglob, jglob))
202 >          skipsForLocalAtom[i].push_back(j);      
203 >      }      
204 >    }
205 >    toposForLocalAtom.clear();
206 >    toposForLocalAtom.resize(nLocal_);
207 >    for (int i = 0; i < nLocal_; i++) {
208 >      int iglob = AtomLocalToGlobal[i];
209 >      int nTopos = 0;
210 >      for (int j = 0; j < nLocal_; j++) {
211 >        int jglob = AtomLocalToGlobal[j];        
212 >        if (oneTwo.hasPair(iglob, jglob)) {
213 >          toposForLocalAtom[i].push_back(j);
214 >          topoDistLocal[i][nTopos] = 1;
215 >          nTopos++;
216 >        }
217 >        if (oneThree.hasPair(iglob, jglob)) {
218 >          toposForLocalAtom[i].push_back(j);
219 >          topoDistLocal[i][nTopos] = 2;
220 >          nTopos++;
221 >        }
222 >        if (oneFour.hasPair(iglob, jglob)) {
223 >          toposForLocalAtom[i].push_back(j);
224 >          topoDistLocal[i][nTopos] = 3;
225 >          nTopos++;
226 >        }
227 >      }      
228 >    }    
229 >
230 >  }
231 >  
232 >  void ForceMatrixDecomposition::createGtypeCutoffMap() {
233 >
234 >    RealType tol = 1e-6;
235 >    RealType rc;
236 >    int atid;
237 >    set<AtomType*> atypes = info_->getSimulatedAtomTypes();
238 >    vector<RealType> atypeCutoff;
239 >    atypeCutoff.resize( atypes.size() );
240 >
241 >    for (set<AtomType*>::iterator at = atypes.begin(); at != atypes.end(); ++at){
242 >      rc = interactionMan_->getSuggestedCutoffRadius(*at);
243 >      atid = (*at)->getIdent();
244 >      atypeCutoff[atid] = rc;
245 >    }
246 >
247 >    vector<RealType> gTypeCutoffs;
248 >
249 >    // first we do a single loop over the cutoff groups to find the
250 >    // largest cutoff for any atypes present in this group.
251 > #ifdef IS_MPI
252 >    vector<RealType> groupCutoffRow(nGroupsInRow_, 0.0);
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 >    for (int cg2 = 0; cg2 < nGroupsInCol_; cg2++) {
279 >      vector<int> atomListCol = getAtomsInGroupColumn(cg2);
280 >      for (vector<int>::iterator jb = atomListCol.begin();
281 >           jb != atomListCol.end(); ++jb) {            
282 >        int atom2 = (*jb);
283 >        atid = identsCol[atom2];
284 >        if (atypeCutoff[atid] > groupCutoffCol[cg2]) {
285 >          groupCutoffCol[cg2] = atypeCutoff[atid];
286 >        }
287 >      }
288 >      bool gTypeFound = false;
289 >      for (int gt = 0; gt < gTypeCutoffs.size(); gt++) {
290 >        if (abs(groupCutoffCol[cg2] - gTypeCutoffs[gt]) < tol) {
291 >          groupColToGtype[cg2] = gt;
292 >          gTypeFound = true;
293 >        }
294 >      }
295 >      if (!gTypeFound) {
296 >        gTypeCutoffs.push_back( groupCutoffCol[cg2] );
297 >        groupColToGtype[cg2] = gTypeCutoffs.size() - 1;
298 >      }
299 >    }
300 > #else
301 >    vector<RealType> groupCutoff(nGroups_, 0.0);
302 >    for (int cg1 = 0; cg1 < nGroups_; cg1++) {
303 >      groupCutoff[cg1] = 0.0;
304 >      vector<int> atomList = getAtomsInGroupRow(cg1);
305 >      for (vector<int>::iterator ia = atomList.begin();
306 >           ia != atomList.end(); ++ia) {            
307 >        int atom1 = (*ia);
308 >        atid = identsLocal[atom1];
309 >        if (atypeCutoff[atid] > groupCutoff[cg1]) {
310 >          groupCutoff[cg1] = atypeCutoff[atid];
311 >        }
312 >      }
313 >
314 >      bool gTypeFound = false;
315 >      for (int gt = 0; gt < gTypeCutoffs.size(); gt++) {
316 >        if (abs(groupCutoff[cg1] - gTypeCutoffs[gt]) < tol) {
317 >          groupToGtype[cg1] = gt;
318 >          gTypeFound = true;
319 >        }
320 >      }
321 >      if (!gTypeFound) {
322 >        gTypeCutoffs.push_back( groupCutoff[cg1] );
323 >        groupToGtype[cg1] = gTypeCutoffs.size() - 1;
324 >      }      
325 >    }
326 > #endif
327 >
328 >    // Now we find the maximum group cutoff value present in the simulation
329 >
330 >    vector<RealType>::iterator groupMaxLoc = max_element(gTypeCutoffs.begin(), gTypeCutoffs.end());
331 >    RealType groupMax = *groupMaxLoc;
332 >
333 > #ifdef IS_MPI
334 >    MPI::COMM_WORLD.Allreduce(&groupMax, &groupMax, 1, MPI::REALTYPE, MPI::MAX);
335 > #endif
336 >    
337 >    RealType tradRcut = groupMax;
338 >
339 >    for (int i = 0; i < gTypeCutoffs.size();  i++) {
340 >      for (int j = 0; j < gTypeCutoffs.size();  j++) {
341 >        
342 >        RealType thisRcut;
343 >        switch(cutoffPolicy_) {
344 >        case TRADITIONAL:
345 >          thisRcut = tradRcut;
346 >        case MIX:
347 >          thisRcut = 0.5 * (gTypeCutoffs[i] + gTypeCutoffs[j]);
348 >        case MAX:
349 >          thisRcut = max(gTypeCutoffs[i], gTypeCutoffs[j]);
350 >        default:
351 >          sprintf(painCave.errMsg,
352 >                  "ForceMatrixDecomposition::createGtypeCutoffMap "
353 >                  "hit an unknown cutoff policy!\n");
354 >          painCave.severity = OPENMD_ERROR;
355 >          painCave.isFatal = 1;
356 >          simError();              
357 >        }
358 >
359 >        pair<int,int> key = make_pair(i,j);
360 >        gTypeCutoffMap[key].first = thisRcut;
361 >
362 >        if (thisRcut > largestRcut_) largestRcut_ = thisRcut;
363 >
364 >        gTypeCutoffMap[key].second = thisRcut*thisRcut;
365 >        
366 >        gTypeCutoffMap[key].third = pow(thisRcut + skinThickness_, 2);
367 >
368 >        // sanity check
369 >        
370 >        if (userChoseCutoff_) {
371 >          if (abs(gTypeCutoffMap[key].first - userCutoff_) > 0.0001) {
372 >            sprintf(painCave.errMsg,
373 >                    "ForceMatrixDecomposition::createGtypeCutoffMap "
374 >                    "user-specified rCut does not match computed group Cutoff\n");
375 >            painCave.severity = OPENMD_ERROR;
376 >            painCave.isFatal = 1;
377 >            simError();            
378 >          }
379 >        }
380 >      }
381 >    }
382 >  }
383 >
384 >
385 >  groupCutoffs ForceMatrixDecomposition::getGroupCutoffs(int cg1, int cg2) {
386 >    int i, j;
387 >
388 > #ifdef IS_MPI
389 >    i = groupRowToGtype[cg1];
390 >    j = groupColToGtype[cg2];
391 > #else
392 >    i = groupToGtype[cg1];
393 >    j = groupToGtype[cg2];
394   #endif
395 +    
396 +    return gTypeCutoffMap[make_pair(i,j)];
397    }
398 +
399 +
400 +  void ForceMatrixDecomposition::zeroWorkArrays() {
401 +
402 +    for (int j = 0; j < N_INTERACTION_FAMILIES; j++) {
403 +      longRangePot_[j] = 0.0;
404 +    }
405 +
406 + #ifdef IS_MPI
407 +    if (storageLayout_ & DataStorage::dslForce) {
408 +      fill(atomRowData.force.begin(), atomRowData.force.end(), V3Zero);
409 +      fill(atomColData.force.begin(), atomColData.force.end(), V3Zero);
410 +    }
411 +
412 +    if (storageLayout_ & DataStorage::dslTorque) {
413 +      fill(atomRowData.torque.begin(), atomRowData.torque.end(), V3Zero);
414 +      fill(atomColData.torque.begin(), atomColData.torque.end(), V3Zero);
415 +    }
416      
417 +    fill(pot_row.begin(), pot_row.end(),
418 +         Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
419  
420 +    fill(pot_col.begin(), pot_col.end(),
421 +         Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
422 +    
423 +    pot_local = Vector<RealType, N_INTERACTION_FAMILIES>(0.0);
424  
425 +    if (storageLayout_ & DataStorage::dslParticlePot) {    
426 +      fill(atomRowData.particlePot.begin(), atomRowData.particlePot.end(), 0.0);
427 +      fill(atomColData.particlePot.begin(), atomColData.particlePot.end(), 0.0);
428 +    }
429 +
430 +    if (storageLayout_ & DataStorage::dslDensity) {      
431 +      fill(atomRowData.density.begin(), atomRowData.density.end(), 0.0);
432 +      fill(atomColData.density.begin(), atomColData.density.end(), 0.0);
433 +    }
434 +
435 +    if (storageLayout_ & DataStorage::dslFunctional) {  
436 +      fill(atomRowData.functional.begin(), atomRowData.functional.end(), 0.0);
437 +      fill(atomColData.functional.begin(), atomColData.functional.end(), 0.0);
438 +    }
439 +
440 +    if (storageLayout_ & DataStorage::dslFunctionalDerivative) {      
441 +      fill(atomRowData.functionalDerivative.begin(),
442 +           atomRowData.functionalDerivative.end(), 0.0);
443 +      fill(atomColData.functionalDerivative.begin(),
444 +           atomColData.functionalDerivative.end(), 0.0);
445 +    }
446 +
447 + #else
448 +    
449 +    if (storageLayout_ & DataStorage::dslParticlePot) {      
450 +      fill(snap_->atomData.particlePot.begin(),
451 +           snap_->atomData.particlePot.end(), 0.0);
452 +    }
453 +    
454 +    if (storageLayout_ & DataStorage::dslDensity) {      
455 +      fill(snap_->atomData.density.begin(),
456 +           snap_->atomData.density.end(), 0.0);
457 +    }
458 +    if (storageLayout_ & DataStorage::dslFunctional) {
459 +      fill(snap_->atomData.functional.begin(),
460 +           snap_->atomData.functional.end(), 0.0);
461 +    }
462 +    if (storageLayout_ & DataStorage::dslFunctionalDerivative) {      
463 +      fill(snap_->atomData.functionalDerivative.begin(),
464 +           snap_->atomData.functionalDerivative.end(), 0.0);
465 +    }
466 + #endif
467 +    
468 +  }
469 +
470 +
471    void ForceMatrixDecomposition::distributeData()  {
472      snap_ = sman_->getCurrentSnapshot();
473      storageLayout_ = sman_->getStorageLayout();
# Line 156 | Line 503 | namespace OpenMD {
503   #endif      
504    }
505    
506 +  /* collects information obtained during the pre-pair loop onto local
507 +   * data structures.
508 +   */
509    void ForceMatrixDecomposition::collectIntermediateData() {
510      snap_ = sman_->getCurrentSnapshot();
511      storageLayout_ = sman_->getStorageLayout();
# Line 167 | Line 517 | namespace OpenMD {
517                                 snap_->atomData.density);
518        
519        int n = snap_->atomData.density.size();
520 <      std::vector<RealType> rho_tmp(n, 0.0);
520 >      vector<RealType> rho_tmp(n, 0.0);
521        AtomCommRealColumn->scatter(atomColData.density, rho_tmp);
522        for (int i = 0; i < n; i++)
523          snap_->atomData.density[i] += rho_tmp[i];
524      }
525   #endif
526    }
527 <  
527 >
528 >  /*
529 >   * redistributes information obtained during the pre-pair loop out to
530 >   * row and column-indexed data structures
531 >   */
532    void ForceMatrixDecomposition::distributeIntermediateData() {
533      snap_ = sman_->getCurrentSnapshot();
534      storageLayout_ = sman_->getStorageLayout();
# Line 232 | Line 586 | namespace OpenMD {
586      
587      nLocal_ = snap_->getNumberOfAtoms();
588  
589 <    vector<vector<RealType> > pot_temp(N_INTERACTION_FAMILIES,
590 <                                       vector<RealType> (nLocal_, 0.0));
589 >    vector<potVec> pot_temp(nLocal_,
590 >                            Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
591 >
592 >    // scatter/gather pot_row into the members of my column
593 >          
594 >    AtomCommPotRow->scatter(pot_row, pot_temp);
595 >
596 >    for (int ii = 0;  ii < pot_temp.size(); ii++ )
597 >      pot_local += pot_temp[ii];
598      
599 <    for (int i = 0; i < N_INTERACTION_FAMILIES; i++) {
600 <      AtomCommRealRow->scatter(pot_row[i], pot_temp[i]);
601 <      for (int ii = 0;  ii < pot_temp[i].size(); ii++ ) {
602 <        pot_local[i] += pot_temp[i][ii];
603 <      }
604 <    }
599 >    fill(pot_temp.begin(), pot_temp.end(),
600 >         Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
601 >      
602 >    AtomCommPotColumn->scatter(pot_col, pot_temp);    
603 >    
604 >    for (int ii = 0;  ii < pot_temp.size(); ii++ )
605 >      pot_local += pot_temp[ii];
606 >    
607   #endif
608    }
609  
610 +  int ForceMatrixDecomposition::getNAtomsInRow() {  
611 + #ifdef IS_MPI
612 +    return nAtomsInRow_;
613 + #else
614 +    return nLocal_;
615 + #endif
616 +  }
617 +
618 +  /**
619 +   * returns the list of atoms belonging to this group.  
620 +   */
621 +  vector<int> ForceMatrixDecomposition::getAtomsInGroupRow(int cg1){
622 + #ifdef IS_MPI
623 +    return groupListRow_[cg1];
624 + #else
625 +    return groupList_[cg1];
626 + #endif
627 +  }
628 +
629 +  vector<int> ForceMatrixDecomposition::getAtomsInGroupColumn(int cg2){
630 + #ifdef IS_MPI
631 +    return groupListCol_[cg2];
632 + #else
633 +    return groupList_[cg2];
634 + #endif
635 +  }
636    
637    Vector3d ForceMatrixDecomposition::getIntergroupVector(int cg1, int cg2){
638      Vector3d d;
# Line 284 | Line 673 | namespace OpenMD {
673      
674      snap_->wrapVector(d);
675      return d;    
676 +  }
677 +
678 +  RealType ForceMatrixDecomposition::getMassFactorRow(int atom1) {
679 + #ifdef IS_MPI
680 +    return massFactorsRow[atom1];
681 + #else
682 +    return massFactorsLocal[atom1];
683 + #endif
684 +  }
685 +
686 +  RealType ForceMatrixDecomposition::getMassFactorColumn(int atom2) {
687 + #ifdef IS_MPI
688 +    return massFactorsCol[atom2];
689 + #else
690 +    return massFactorsLocal[atom2];
691 + #endif
692 +
693    }
694      
695    Vector3d ForceMatrixDecomposition::getInteratomicVector(int atom1, int atom2){
# Line 299 | Line 705 | namespace OpenMD {
705      return d;    
706    }
707  
708 +  vector<int> ForceMatrixDecomposition::getSkipsForRowAtom(int atom1) {
709 + #ifdef IS_MPI
710 +    return skipsForRowAtom[atom1];
711 + #else
712 +    return skipsForLocalAtom[atom1];
713 + #endif
714 +  }
715 +
716 +  /**
717 +   * There are a number of reasons to skip a pair or a
718 +   * particle. Mostly we do this to exclude atoms who are involved in
719 +   * short range interactions (bonds, bends, torsions), but we also
720 +   * need to exclude some overcounted interactions that result from
721 +   * the parallel decomposition.
722 +   */
723 +  bool ForceMatrixDecomposition::skipAtomPair(int atom1, int atom2) {
724 +    int unique_id_1, unique_id_2;
725 +
726 + #ifdef IS_MPI
727 +    // in MPI, we have to look up the unique IDs for each atom
728 +    unique_id_1 = AtomRowToGlobal[atom1];
729 +    unique_id_2 = AtomColToGlobal[atom2];
730 +
731 +    // this situation should only arise in MPI simulations
732 +    if (unique_id_1 == unique_id_2) return true;
733 +    
734 +    // this prevents us from doing the pair on multiple processors
735 +    if (unique_id_1 < unique_id_2) {
736 +      if ((unique_id_1 + unique_id_2) % 2 == 0) return true;
737 +    } else {
738 +      if ((unique_id_1 + unique_id_2) % 2 == 1) return true;
739 +    }
740 + #else
741 +    // in the normal loop, the atom numbers are unique
742 +    unique_id_1 = atom1;
743 +    unique_id_2 = atom2;
744 + #endif
745 +    
746 + #ifdef IS_MPI
747 +    for (vector<int>::iterator i = skipsForRowAtom[atom1].begin();
748 +         i != skipsForRowAtom[atom1].end(); ++i) {
749 +      if ( (*i) == unique_id_2 ) return true;
750 +    }    
751 + #else
752 +    for (vector<int>::iterator i = skipsForLocalAtom[atom1].begin();
753 +         i != skipsForLocalAtom[atom1].end(); ++i) {
754 +      if ( (*i) == unique_id_2 ) return true;
755 +    }    
756 + #endif
757 +  }
758 +
759 +  int ForceMatrixDecomposition::getTopoDistance(int atom1, int atom2) {
760 +    
761 + #ifdef IS_MPI
762 +    for (int i = 0; i < toposForRowAtom[atom1].size(); i++) {
763 +      if ( toposForRowAtom[atom1][i] == atom2 ) return topoDistRow[atom1][i];
764 +    }
765 + #else
766 +    for (int i = 0; i < toposForLocalAtom[atom1].size(); i++) {
767 +      if ( toposForLocalAtom[atom1][i] == atom2 ) return topoDistLocal[atom1][i];
768 +    }
769 + #endif
770 +
771 +    // zero is default for unconnected (i.e. normal) pair interactions
772 +    return 0;
773 +  }
774 +
775    void ForceMatrixDecomposition::addForceToAtomRow(int atom1, Vector3d fg){
776   #ifdef IS_MPI
777      atomRowData.force[atom1] += fg;
# Line 320 | Line 793 | namespace OpenMD {
793      InteractionData idat;
794  
795   #ifdef IS_MPI
796 +    
797 +    idat.atypes = make_pair( ff_->getAtomType(identsRow[atom1]),
798 +                             ff_->getAtomType(identsCol[atom2]) );
799 +
800 +    
801      if (storageLayout_ & DataStorage::dslAmat) {
802        idat.A1 = &(atomRowData.aMat[atom1]);
803        idat.A2 = &(atomColData.aMat[atom2]);
# Line 340 | Line 818 | namespace OpenMD {
818        idat.rho2 = &(atomColData.density[atom2]);
819      }
820  
821 +    if (storageLayout_ & DataStorage::dslFunctional) {
822 +      idat.frho1 = &(atomRowData.functional[atom1]);
823 +      idat.frho2 = &(atomColData.functional[atom2]);
824 +    }
825 +
826      if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
827        idat.dfrho1 = &(atomRowData.functionalDerivative[atom1]);
828        idat.dfrho2 = &(atomColData.functionalDerivative[atom2]);
829      }
830 +
831 +    if (storageLayout_ & DataStorage::dslParticlePot) {
832 +      idat.particlePot1 = &(atomRowData.particlePot[atom1]);
833 +      idat.particlePot2 = &(atomColData.particlePot[atom2]);
834 +    }
835 +
836   #else
837 +
838 +    idat.atypes = make_pair( ff_->getAtomType(identsLocal[atom1]),
839 +                             ff_->getAtomType(identsLocal[atom2]) );
840 +
841      if (storageLayout_ & DataStorage::dslAmat) {
842        idat.A1 = &(snap_->atomData.aMat[atom1]);
843        idat.A2 = &(snap_->atomData.aMat[atom2]);
# Line 365 | Line 858 | namespace OpenMD {
858        idat.rho2 = &(snap_->atomData.density[atom2]);
859      }
860  
861 +    if (storageLayout_ & DataStorage::dslFunctional) {
862 +      idat.frho1 = &(snap_->atomData.functional[atom1]);
863 +      idat.frho2 = &(snap_->atomData.functional[atom2]);
864 +    }
865 +
866      if (storageLayout_ & DataStorage::dslFunctionalDerivative) {
867        idat.dfrho1 = &(snap_->atomData.functionalDerivative[atom1]);
868        idat.dfrho2 = &(snap_->atomData.functionalDerivative[atom2]);
869      }
870 +
871 +    if (storageLayout_ & DataStorage::dslParticlePot) {
872 +      idat.particlePot1 = &(snap_->atomData.particlePot[atom1]);
873 +      idat.particlePot2 = &(snap_->atomData.particlePot[atom2]);
874 +    }
875 +
876   #endif
877      return idat;
878    }
879  
880 +  
881 +  void ForceMatrixDecomposition::unpackInteractionData(InteractionData idat, int atom1, int atom2) {    
882 + #ifdef IS_MPI
883 +    pot_row[atom1] += 0.5 *  *(idat.pot);
884 +    pot_col[atom2] += 0.5 *  *(idat.pot);
885 +
886 +    atomRowData.force[atom1] += *(idat.f1);
887 +    atomColData.force[atom2] -= *(idat.f1);
888 + #else
889 +    longRangePot_ += *(idat.pot);
890 +    
891 +    snap_->atomData.force[atom1] += *(idat.f1);
892 +    snap_->atomData.force[atom2] -= *(idat.f1);
893 + #endif
894 +
895 +  }
896 +
897 +
898    InteractionData ForceMatrixDecomposition::fillSkipData(int atom1, int atom2){
899  
900      InteractionData idat;
901   #ifdef IS_MPI
902 +    idat.atypes = make_pair( ff_->getAtomType(identsRow[atom1]),
903 +                             ff_->getAtomType(identsCol[atom2]) );
904 +
905      if (storageLayout_ & DataStorage::dslElectroFrame) {
906        idat.eFrame1 = &(atomRowData.electroFrame[atom1]);
907        idat.eFrame2 = &(atomColData.electroFrame[atom2]);
# Line 385 | Line 910 | namespace OpenMD {
910        idat.t1 = &(atomRowData.torque[atom1]);
911        idat.t2 = &(atomColData.torque[atom2]);
912      }
388    if (storageLayout_ & DataStorage::dslForce) {
389      idat.t1 = &(atomRowData.force[atom1]);
390      idat.t2 = &(atomColData.force[atom2]);
391    }
913   #else
914 +    idat.atypes = make_pair( ff_->getAtomType(identsLocal[atom1]),
915 +                             ff_->getAtomType(identsLocal[atom2]) );
916 +
917      if (storageLayout_ & DataStorage::dslElectroFrame) {
918        idat.eFrame1 = &(snap_->atomData.electroFrame[atom1]);
919        idat.eFrame2 = &(snap_->atomData.electroFrame[atom2]);
# Line 398 | Line 922 | namespace OpenMD {
922        idat.t1 = &(snap_->atomData.torque[atom1]);
923        idat.t2 = &(snap_->atomData.torque[atom2]);
924      }
925 <    if (storageLayout_ & DataStorage::dslForce) {
402 <      idat.t1 = &(snap_->atomData.force[atom1]);
403 <      idat.t2 = &(snap_->atomData.force[atom2]);
404 <    }
405 < #endif
406 <    
925 > #endif    
926    }
927  
409
410
411
928    /*
929     * buildNeighborList
930     *
# Line 418 | Line 934 | namespace OpenMD {
934    vector<pair<int, int> > ForceMatrixDecomposition::buildNeighborList() {
935        
936      vector<pair<int, int> > neighborList;
937 +    groupCutoffs cuts;
938   #ifdef IS_MPI
939      cellListRow_.clear();
940      cellListCol_.clear();
# Line 425 | Line 942 | namespace OpenMD {
942      cellList_.clear();
943   #endif
944  
945 <    // dangerous to not do error checking.
429 <    RealType rCut_;
430 <
431 <    RealType rList_ = (rCut_ + skinThickness_);
945 >    RealType rList_ = (largestRcut_ + skinThickness_);
946      RealType rl2 = rList_ * rList_;
947      Snapshot* snap_ = sman_->getCurrentSnapshot();
948      Mat3x3d Hmat = snap_->getHmat();
# Line 507 | Line 1021 | namespace OpenMD {
1021      }
1022   #endif
1023  
510
511
1024      for (int m1z = 0; m1z < nCells_.z(); m1z++) {
1025        for (int m1y = 0; m1y < nCells_.y(); m1y++) {
1026          for (int m1x = 0; m1x < nCells_.x(); m1x++) {
# Line 553 | Line 1065 | namespace OpenMD {
1065                  if (m2 != m1 || cgColToGlobal[(*j2)] < cgRowToGlobal[(*j1)]) {
1066                    dr = cgColData.position[(*j2)] - cgRowData.position[(*j1)];
1067                    snap_->wrapVector(dr);
1068 <                  if (dr.lengthSquare() < rl2) {
1068 >                  cuts = getGroupCutoffs( (*j1), (*j2) );
1069 >                  if (dr.lengthSquare() < cuts.third) {
1070                      neighborList.push_back(make_pair((*j1), (*j2)));
1071                    }
1072                  }
# Line 572 | Line 1085 | namespace OpenMD {
1085                  if (m2 != m1 || (*j2) < (*j1)) {
1086                    dr = snap_->cgData.position[(*j2)] - snap_->cgData.position[(*j1)];
1087                    snap_->wrapVector(dr);
1088 <                  if (dr.lengthSquare() < rl2) {
1088 >                  cuts = getGroupCutoffs( (*j1), (*j2) );
1089 >                  if (dr.lengthSquare() < cuts.third) {
1090                      neighborList.push_back(make_pair((*j1), (*j2)));
1091                    }
1092                  }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines