ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/devel_omp/src/parallel/ForceMatrixDecomposition.cpp
Revision: 1599
Committed: Fri Jul 29 19:03:36 2011 UTC (13 years, 9 months ago) by mciznick
File size: 46360 byte(s)
Log Message:
Updated: Build neighbor list method with frequency counter. Additional parameter to md file.

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 #include "primitives/Molecule.hpp"
47
48 using namespace std;
49 namespace OpenMD {
50
51 ForceMatrixDecomposition::ForceMatrixDecomposition(SimInfo* info, InteractionManager* iMan) :
52 ForceDecomposition(info, iMan) {
53 // In a parallel computation, row and colum scans must visit all
54 // surrounding cells (not just the 14 upper triangular blocks that
55 // are used when the processor can see all pairs)
56 #ifdef IS_MPI
57 cellOffsets_.push_back( Vector3i(-1, 0, 0) );
58 cellOffsets_.push_back( Vector3i(-1,-1, 0) );
59 cellOffsets_.push_back( Vector3i( 0,-1, 0) );
60 cellOffsets_.push_back( Vector3i( 1,-1, 0) );
61 cellOffsets_.push_back( Vector3i( 0, 0,-1) );
62 cellOffsets_.push_back( Vector3i(-1, 0, 1) );
63 cellOffsets_.push_back( Vector3i(-1,-1,-1) );
64 cellOffsets_.push_back( Vector3i( 0,-1,-1) );
65 cellOffsets_.push_back( Vector3i( 1,-1,-1) );
66 cellOffsets_.push_back( Vector3i( 1, 0,-1) );
67 cellOffsets_.push_back( Vector3i( 1, 1,-1) );
68 cellOffsets_.push_back( Vector3i( 0, 1,-1) );
69 cellOffsets_.push_back( Vector3i(-1, 1,-1) );
70 #endif
71 }
72
73 /**
74 * distributeInitialData is essentially a copy of the older fortran
75 * SimulationSetup
76 */
77 void ForceMatrixDecomposition::distributeInitialData() {
78 snap_ = sman_->getCurrentSnapshot();
79 storageLayout_ = sman_->getStorageLayout();
80 ff_ = info_->getForceField();
81 nLocal_ = snap_->getNumberOfAtoms();
82
83 nGroups_ = info_->getNLocalCutoffGroups();
84 // gather the information for atomtype IDs (atids):
85 idents = info_->getIdentArray();
86 AtomLocalToGlobal = info_->getGlobalAtomIndices();
87 cgLocalToGlobal = info_->getGlobalGroupIndices();
88 vector<int> globalGroupMembership = info_->getGlobalGroupMembership();
89
90 massFactors = info_->getMassFactors();
91
92 PairList* excludes = info_->getExcludedInteractions();
93 PairList* oneTwo = info_->getOneTwoInteractions();
94 PairList* oneThree = info_->getOneThreeInteractions();
95 PairList* oneFour = info_->getOneFourInteractions();
96
97 #ifdef IS_MPI
98
99 MPI::Intracomm row = rowComm.getComm();
100 MPI::Intracomm col = colComm.getComm();
101
102 AtomPlanIntRow = new Plan<int>(row, nLocal_);
103 AtomPlanRealRow = new Plan<RealType>(row, nLocal_);
104 AtomPlanVectorRow = new Plan<Vector3d>(row, nLocal_);
105 AtomPlanMatrixRow = new Plan<Mat3x3d>(row, nLocal_);
106 AtomPlanPotRow = new Plan<potVec>(row, nLocal_);
107
108 AtomPlanIntColumn = new Plan<int>(col, nLocal_);
109 AtomPlanRealColumn = new Plan<RealType>(col, nLocal_);
110 AtomPlanVectorColumn = new Plan<Vector3d>(col, nLocal_);
111 AtomPlanMatrixColumn = new Plan<Mat3x3d>(col, nLocal_);
112 AtomPlanPotColumn = new Plan<potVec>(col, nLocal_);
113
114 cgPlanIntRow = new Plan<int>(row, nGroups_);
115 cgPlanVectorRow = new Plan<Vector3d>(row, nGroups_);
116 cgPlanIntColumn = new Plan<int>(col, nGroups_);
117 cgPlanVectorColumn = new Plan<Vector3d>(col, nGroups_);
118
119 nAtomsInRow_ = AtomPlanIntRow->getSize();
120 nAtomsInCol_ = AtomPlanIntColumn->getSize();
121 nGroupsInRow_ = cgPlanIntRow->getSize();
122 nGroupsInCol_ = cgPlanIntColumn->getSize();
123
124 // Modify the data storage objects with the correct layouts and sizes:
125 atomRowData.resize(nAtomsInRow_);
126 atomRowData.setStorageLayout(storageLayout_);
127 atomColData.resize(nAtomsInCol_);
128 atomColData.setStorageLayout(storageLayout_);
129 cgRowData.resize(nGroupsInRow_);
130 cgRowData.setStorageLayout(DataStorage::dslPosition);
131 cgColData.resize(nGroupsInCol_);
132 cgColData.setStorageLayout(DataStorage::dslPosition);
133
134 identsRow.resize(nAtomsInRow_);
135 identsCol.resize(nAtomsInCol_);
136
137 AtomPlanIntRow->gather(idents, identsRow);
138 AtomPlanIntColumn->gather(idents, identsCol);
139
140 // allocate memory for the parallel objects
141 atypesRow.resize(nAtomsInRow_);
142 atypesCol.resize(nAtomsInCol_);
143
144 for (int i = 0; i < nAtomsInRow_; i++)
145 atypesRow[i] = ff_->getAtomType(identsRow[i]);
146 for (int i = 0; i < nAtomsInCol_; i++)
147 atypesCol[i] = ff_->getAtomType(identsCol[i]);
148
149 pot_row.resize(nAtomsInRow_);
150 pot_col.resize(nAtomsInCol_);
151
152 AtomRowToGlobal.resize(nAtomsInRow_);
153 AtomColToGlobal.resize(nAtomsInCol_);
154 AtomPlanIntRow->gather(AtomLocalToGlobal, AtomRowToGlobal);
155 AtomPlanIntColumn->gather(AtomLocalToGlobal, AtomColToGlobal);
156
157 cerr << "Atoms in Local:\n";
158 for (int i = 0; i < AtomLocalToGlobal.size(); i++)
159 {
160 cerr << "i =\t" << i << "\t localAt =\t" << AtomLocalToGlobal[i] << "\n";
161 }
162 cerr << "Atoms in Row:\n";
163 for (int i = 0; i < AtomRowToGlobal.size(); i++)
164 {
165 cerr << "i =\t" << i << "\t rowAt =\t" << AtomRowToGlobal[i] << "\n";
166 }
167 cerr << "Atoms in Col:\n";
168 for (int i = 0; i < AtomColToGlobal.size(); i++)
169 {
170 cerr << "i =\t" << i << "\t colAt =\t" << AtomColToGlobal[i] << "\n";
171 }
172
173 cgRowToGlobal.resize(nGroupsInRow_);
174 cgColToGlobal.resize(nGroupsInCol_);
175 cgPlanIntRow->gather(cgLocalToGlobal, cgRowToGlobal);
176 cgPlanIntColumn->gather(cgLocalToGlobal, cgColToGlobal);
177
178 cerr << "Gruops in Local:\n";
179 for (int i = 0; i < cgLocalToGlobal.size(); i++)
180 {
181 cerr << "i =\t" << i << "\t localCG =\t" << cgLocalToGlobal[i] << "\n";
182 }
183 cerr << "Groups in Row:\n";
184 for (int i = 0; i < cgRowToGlobal.size(); i++)
185 {
186 cerr << "i =\t" << i << "\t rowCG =\t" << cgRowToGlobal[i] << "\n";
187 }
188 cerr << "Groups in Col:\n";
189 for (int i = 0; i < cgColToGlobal.size(); i++)
190 {
191 cerr << "i =\t" << i << "\t colCG =\t" << cgColToGlobal[i] << "\n";
192 }
193
194 massFactorsRow.resize(nAtomsInRow_);
195 massFactorsCol.resize(nAtomsInCol_);
196 AtomPlanRealRow->gather(massFactors, massFactorsRow);
197 AtomPlanRealColumn->gather(massFactors, massFactorsCol);
198
199 groupListRow_.clear();
200 groupListRow_.resize(nGroupsInRow_);
201 for (int i = 0; i < nGroupsInRow_; i++)
202 {
203 int gid = cgRowToGlobal[i];
204 for (int j = 0; j < nAtomsInRow_; j++)
205 {
206 int aid = AtomRowToGlobal[j];
207 if (globalGroupMembership[aid] == gid)
208 groupListRow_[i].push_back(j);
209 }
210 }
211
212 groupListCol_.clear();
213 groupListCol_.resize(nGroupsInCol_);
214 for (int i = 0; i < nGroupsInCol_; i++)
215 {
216 int gid = cgColToGlobal[i];
217 for (int j = 0; j < nAtomsInCol_; j++)
218 {
219 int aid = AtomColToGlobal[j];
220 if (globalGroupMembership[aid] == gid)
221 groupListCol_[i].push_back(j);
222 }
223 }
224
225 excludesForAtom.clear();
226 excludesForAtom.resize(nAtomsInRow_);
227 toposForAtom.clear();
228 toposForAtom.resize(nAtomsInRow_);
229 topoDist.clear();
230 topoDist.resize(nAtomsInRow_);
231 for (int i = 0; i < nAtomsInRow_; i++)
232 {
233 int iglob = AtomRowToGlobal[i];
234
235 for (int j = 0; j < nAtomsInCol_; j++)
236 {
237 int jglob = AtomColToGlobal[j];
238
239 if (excludes->hasPair(iglob, jglob))
240 excludesForAtom[i].push_back(j);
241
242 if (oneTwo->hasPair(iglob, jglob))
243 {
244 toposForAtom[i].push_back(j);
245 topoDist[i].push_back(1);
246 } else
247 {
248 if (oneThree->hasPair(iglob, jglob))
249 {
250 toposForAtom[i].push_back(j);
251 topoDist[i].push_back(2);
252 } else
253 {
254 if (oneFour->hasPair(iglob, jglob))
255 {
256 toposForAtom[i].push_back(j);
257 topoDist[i].push_back(3);
258 }
259 }
260 }
261 }
262 }
263
264 #endif
265
266 // allocate memory for the parallel objects
267 atypesLocal.resize(nLocal_);
268
269 for (int i = 0; i < nLocal_; i++)
270 atypesLocal[i] = ff_->getAtomType(idents[i]);
271
272 groupList_.clear();
273 groupList_.resize(nGroups_);
274 for (int i = 0; i < nGroups_; i++)
275 {
276 int gid = cgLocalToGlobal[i];
277 for (int j = 0; j < nLocal_; j++)
278 {
279 int aid = AtomLocalToGlobal[j];
280 if (globalGroupMembership[aid] == gid)
281 {
282 groupList_[i].push_back(j);
283 }
284 }
285 }
286
287 excludesForAtom.clear();
288 excludesForAtom.resize(nLocal_);
289 toposForAtom.clear();
290 toposForAtom.resize(nLocal_);
291 topoDist.clear();
292 topoDist.resize(nLocal_);
293
294 for (int i = 0; i < nLocal_; i++)
295 {
296 int iglob = AtomLocalToGlobal[i];
297
298 for (int j = 0; j < nLocal_; j++)
299 {
300 int jglob = AtomLocalToGlobal[j];
301
302 if (excludes->hasPair(iglob, jglob))
303 excludesForAtom[i].push_back(j);
304
305 if (oneTwo->hasPair(iglob, jglob))
306 {
307 toposForAtom[i].push_back(j);
308 topoDist[i].push_back(1);
309 } else
310 {
311 if (oneThree->hasPair(iglob, jglob))
312 {
313 toposForAtom[i].push_back(j);
314 topoDist[i].push_back(2);
315 } else
316 {
317 if (oneFour->hasPair(iglob, jglob))
318 {
319 toposForAtom[i].push_back(j);
320 topoDist[i].push_back(3);
321 }
322 }
323 }
324 }
325 }
326
327 Globals* simParams_ = info_->getSimParams();
328 if (simParams_->haveNeighborListReorderFreq())
329 {
330 neighborListReorderFreq = simParams_->getNeighborListReorderFreq();
331 } else
332 {
333 neighborListReorderFreq = 0;
334 }
335 reorderFreqCounter = 1;
336
337 createGtypeCutoffMap();
338
339 }
340
341 void ForceMatrixDecomposition::createGtypeCutoffMap() {
342
343 RealType tol = 1e-6;
344 largestRcut_ = 0.0;
345 RealType rc;
346 int atid;
347 set<AtomType*> atypes = info_->getSimulatedAtomTypes();
348
349 map<int, RealType> atypeCutoff;
350
351 for (set<AtomType*>::iterator at = atypes.begin(); at != atypes.end(); ++at)
352 {
353 atid = (*at)->getIdent();
354 if (userChoseCutoff_)
355 atypeCutoff[atid] = userCutoff_;
356 else
357 atypeCutoff[atid] = interactionMan_->getSuggestedCutoffRadius(*at);
358 }
359
360 vector<RealType> gTypeCutoffs;
361 // first we do a single loop over the cutoff groups to find the
362 // largest cutoff for any atypes present in this group.
363 #ifdef IS_MPI
364 vector<RealType> groupCutoffRow(nGroupsInRow_, 0.0);
365 groupRowToGtype.resize(nGroupsInRow_);
366 for (int cg1 = 0; cg1 < nGroupsInRow_; cg1++)
367 {
368 vector<int> atomListRow = getAtomsInGroupRow(cg1);
369 for (vector<int>::iterator ia = atomListRow.begin();
370 ia != atomListRow.end(); ++ia)
371 {
372 int atom1 = (*ia);
373 atid = identsRow[atom1];
374 if (atypeCutoff[atid] > groupCutoffRow[cg1])
375 {
376 groupCutoffRow[cg1] = atypeCutoff[atid];
377 }
378 }
379
380 bool gTypeFound = false;
381 for (int gt = 0; gt < gTypeCutoffs.size(); gt++)
382 {
383 if (abs(groupCutoffRow[cg1] - gTypeCutoffs[gt]) < tol)
384 {
385 groupRowToGtype[cg1] = gt;
386 gTypeFound = true;
387 }
388 }
389 if (!gTypeFound)
390 {
391 gTypeCutoffs.push_back( groupCutoffRow[cg1] );
392 groupRowToGtype[cg1] = gTypeCutoffs.size() - 1;
393 }
394
395 }
396 vector<RealType> groupCutoffCol(nGroupsInCol_, 0.0);
397 groupColToGtype.resize(nGroupsInCol_);
398 for (int cg2 = 0; cg2 < nGroupsInCol_; cg2++)
399 {
400 vector<int> atomListCol = getAtomsInGroupColumn(cg2);
401 for (vector<int>::iterator jb = atomListCol.begin();
402 jb != atomListCol.end(); ++jb)
403 {
404 int atom2 = (*jb);
405 atid = identsCol[atom2];
406 if (atypeCutoff[atid] > groupCutoffCol[cg2])
407 {
408 groupCutoffCol[cg2] = atypeCutoff[atid];
409 }
410 }
411 bool gTypeFound = false;
412 for (int gt = 0; gt < gTypeCutoffs.size(); gt++)
413 {
414 if (abs(groupCutoffCol[cg2] - gTypeCutoffs[gt]) < tol)
415 {
416 groupColToGtype[cg2] = gt;
417 gTypeFound = true;
418 }
419 }
420 if (!gTypeFound)
421 {
422 gTypeCutoffs.push_back( groupCutoffCol[cg2] );
423 groupColToGtype[cg2] = gTypeCutoffs.size() - 1;
424 }
425 }
426 #else
427
428 vector<RealType> groupCutoff(nGroups_, 0.0);
429 groupToGtype.resize(nGroups_);
430 for (int cg1 = 0; cg1 < nGroups_; cg1++)
431 {
432 groupCutoff[cg1] = 0.0;
433 vector<int> atomList = getAtomsInGroupRow(cg1);
434 for (vector<int>::iterator ia = atomList.begin(); ia != atomList.end(); ++ia)
435 {
436 int atom1 = (*ia);
437 atid = idents[atom1];
438 if (atypeCutoff[atid] > groupCutoff[cg1])
439 groupCutoff[cg1] = atypeCutoff[atid];
440 }
441
442 bool gTypeFound = false;
443 for (int gt = 0; gt < gTypeCutoffs.size(); gt++)
444 {
445 if (abs(groupCutoff[cg1] - gTypeCutoffs[gt]) < tol)
446 {
447 groupToGtype[cg1] = gt;
448 gTypeFound = true;
449 }
450 }
451 if (!gTypeFound)
452 {
453 gTypeCutoffs.push_back(groupCutoff[cg1]);
454 groupToGtype[cg1] = gTypeCutoffs.size() - 1;
455 }
456 }
457 #endif
458
459 // Now we find the maximum group cutoff value present in the simulation
460
461 RealType groupMax = *max_element(gTypeCutoffs.begin(), gTypeCutoffs.end());
462
463 #ifdef IS_MPI
464 MPI::COMM_WORLD.Allreduce(&groupMax, &groupMax, 1, MPI::REALTYPE,
465 MPI::MAX);
466 #endif
467
468 RealType tradRcut = groupMax;
469
470 for (int i = 0; i < gTypeCutoffs.size(); i++)
471 {
472 for (int j = 0; j < gTypeCutoffs.size(); j++)
473 {
474 RealType thisRcut;
475 switch (cutoffPolicy_) {
476 case TRADITIONAL:
477 thisRcut = tradRcut;
478 break;
479 case MIX:
480 thisRcut = 0.5 * (gTypeCutoffs[i] + gTypeCutoffs[j]);
481 break;
482 case MAX:
483 thisRcut = max(gTypeCutoffs[i], gTypeCutoffs[j]);
484 break;
485 default:
486 sprintf(painCave.errMsg, "ForceMatrixDecomposition::createGtypeCutoffMap "
487 "hit an unknown cutoff policy!\n");
488 painCave.severity = OPENMD_ERROR;
489 painCave.isFatal = 1;
490 simError();
491 break;
492 }
493
494 pair<int, int> key = make_pair(i, j);
495 gTypeCutoffMap[key].first = thisRcut;
496 if (thisRcut > largestRcut_)
497 largestRcut_ = thisRcut;
498 gTypeCutoffMap[key].second = thisRcut * thisRcut;
499 gTypeCutoffMap[key].third = pow(thisRcut + skinThickness_, 2);
500 // sanity check
501
502 if (userChoseCutoff_)
503 {
504 if (abs(gTypeCutoffMap[key].first - userCutoff_) > 0.0001)
505 {
506 sprintf(painCave.errMsg, "ForceMatrixDecomposition::createGtypeCutoffMap "
507 "user-specified rCut (%lf) does not match computed group Cutoff\n", userCutoff_);
508 painCave.severity = OPENMD_ERROR;
509 painCave.isFatal = 1;
510 simError();
511 }
512 }
513 }
514 }
515 }
516
517 groupCutoffs ForceMatrixDecomposition::getGroupCutoffs(int cg1, int cg2) {
518 int i, j;
519 #ifdef IS_MPI
520 i = groupRowToGtype[cg1];
521 j = groupColToGtype[cg2];
522 #else
523 i = groupToGtype[cg1];
524 j = groupToGtype[cg2];
525 #endif
526 return gTypeCutoffMap[make_pair(i, j)];
527 }
528
529 int ForceMatrixDecomposition::getTopologicalDistance(int atom1, int atom2) {
530 for (int j = 0; j < toposForAtom[atom1].size(); j++)
531 {
532 if (toposForAtom[atom1][j] == atom2)
533 return topoDist[atom1][j];
534 }
535 return 0;
536 }
537
538 void ForceMatrixDecomposition::zeroWorkArrays() {
539 pairwisePot = 0.0;
540 embeddingPot = 0.0;
541
542 #ifdef IS_MPI
543 if (storageLayout_ & DataStorage::dslForce)
544 {
545 fill(atomRowData.force.begin(), atomRowData.force.end(), V3Zero);
546 fill(atomColData.force.begin(), atomColData.force.end(), V3Zero);
547 }
548
549 if (storageLayout_ & DataStorage::dslTorque)
550 {
551 fill(atomRowData.torque.begin(), atomRowData.torque.end(), V3Zero);
552 fill(atomColData.torque.begin(), atomColData.torque.end(), V3Zero);
553 }
554
555 fill(pot_row.begin(), pot_row.end(),
556 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
557
558 fill(pot_col.begin(), pot_col.end(),
559 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
560
561 if (storageLayout_ & DataStorage::dslParticlePot)
562 {
563 fill(atomRowData.particlePot.begin(), atomRowData.particlePot.end(),
564 0.0);
565 fill(atomColData.particlePot.begin(), atomColData.particlePot.end(),
566 0.0);
567 }
568
569 if (storageLayout_ & DataStorage::dslDensity)
570 {
571 fill(atomRowData.density.begin(), atomRowData.density.end(), 0.0);
572 fill(atomColData.density.begin(), atomColData.density.end(), 0.0);
573 }
574
575 if (storageLayout_ & DataStorage::dslFunctional)
576 {
577 fill(atomRowData.functional.begin(), atomRowData.functional.end(),
578 0.0);
579 fill(atomColData.functional.begin(), atomColData.functional.end(),
580 0.0);
581 }
582
583 if (storageLayout_ & DataStorage::dslFunctionalDerivative)
584 {
585 fill(atomRowData.functionalDerivative.begin(),
586 atomRowData.functionalDerivative.end(), 0.0);
587 fill(atomColData.functionalDerivative.begin(),
588 atomColData.functionalDerivative.end(), 0.0);
589 }
590
591 if (storageLayout_ & DataStorage::dslSkippedCharge)
592 {
593 fill(atomRowData.skippedCharge.begin(),
594 atomRowData.skippedCharge.end(), 0.0);
595 fill(atomColData.skippedCharge.begin(),
596 atomColData.skippedCharge.end(), 0.0);
597 }
598
599 #endif
600 // even in parallel, we need to zero out the local arrays:
601
602 if (storageLayout_ & DataStorage::dslParticlePot)
603 {
604 fill(snap_->atomData.particlePot.begin(), snap_->atomData.particlePot.end(), 0.0);
605 }
606
607 if (storageLayout_ & DataStorage::dslDensity)
608 {
609 fill(snap_->atomData.density.begin(), snap_->atomData.density.end(), 0.0);
610 }
611 if (storageLayout_ & DataStorage::dslFunctional)
612 {
613 fill(snap_->atomData.functional.begin(), snap_->atomData.functional.end(), 0.0);
614 }
615 if (storageLayout_ & DataStorage::dslFunctionalDerivative)
616 {
617 fill(snap_->atomData.functionalDerivative.begin(), snap_->atomData.functionalDerivative.end(), 0.0);
618 }
619 if (storageLayout_ & DataStorage::dslSkippedCharge)
620 {
621 fill(snap_->atomData.skippedCharge.begin(), snap_->atomData.skippedCharge.end(), 0.0);
622 }
623
624 }
625
626 void ForceMatrixDecomposition::distributeData() {
627 snap_ = sman_->getCurrentSnapshot();
628 storageLayout_ = sman_->getStorageLayout();
629 #ifdef IS_MPI
630
631 // gather up the atomic positions
632 AtomPlanVectorRow->gather(snap_->atomData.position,
633 atomRowData.position);
634 AtomPlanVectorColumn->gather(snap_->atomData.position,
635 atomColData.position);
636
637 // gather up the cutoff group positions
638
639 cerr << "before gather\n";
640 for (int i = 0; i < snap_->cgData.position.size(); i++)
641 {
642 cerr << "cgpos = " << snap_->cgData.position[i] << "\n";
643 }
644
645 cgPlanVectorRow->gather(snap_->cgData.position,
646 cgRowData.position);
647
648 cerr << "after gather\n";
649 for (int i = 0; i < cgRowData.position.size(); i++)
650 {
651 cerr << "cgRpos = " << cgRowData.position[i] << "\n";
652 }
653
654 cgPlanVectorColumn->gather(snap_->cgData.position,
655 cgColData.position);
656 for (int i = 0; i < cgColData.position.size(); i++)
657 {
658 cerr << "cgCpos = " << cgColData.position[i] << "\n";
659 }
660
661 // if needed, gather the atomic rotation matrices
662 if (storageLayout_ & DataStorage::dslAmat)
663 {
664 AtomPlanMatrixRow->gather(snap_->atomData.aMat,
665 atomRowData.aMat);
666 AtomPlanMatrixColumn->gather(snap_->atomData.aMat,
667 atomColData.aMat);
668 }
669
670 // if needed, gather the atomic eletrostatic frames
671 if (storageLayout_ & DataStorage::dslElectroFrame)
672 {
673 AtomPlanMatrixRow->gather(snap_->atomData.electroFrame,
674 atomRowData.electroFrame);
675 AtomPlanMatrixColumn->gather(snap_->atomData.electroFrame,
676 atomColData.electroFrame);
677 }
678
679 #endif
680 }
681
682 /* collects information obtained during the pre-pair loop onto local
683 * data structures.
684 */
685 void ForceMatrixDecomposition::collectIntermediateData() {
686 snap_ = sman_->getCurrentSnapshot();
687 storageLayout_ = sman_->getStorageLayout();
688 #ifdef IS_MPI
689
690 if (storageLayout_ & DataStorage::dslDensity)
691 {
692
693 AtomPlanRealRow->scatter(atomRowData.density,
694 snap_->atomData.density);
695
696 int n = snap_->atomData.density.size();
697 vector<RealType> rho_tmp(n, 0.0);
698 AtomPlanRealColumn->scatter(atomColData.density, rho_tmp);
699 for (int i = 0; i < n; i++)
700 snap_->atomData.density[i] += rho_tmp[i];
701 }
702 #endif
703 }
704
705 /*
706 * redistributes information obtained during the pre-pair loop out to
707 * row and column-indexed data structures
708 */
709 void ForceMatrixDecomposition::distributeIntermediateData() {
710 snap_ = sman_->getCurrentSnapshot();
711 storageLayout_ = sman_->getStorageLayout();
712 #ifdef IS_MPI
713 if (storageLayout_ & DataStorage::dslFunctional)
714 {
715 AtomPlanRealRow->gather(snap_->atomData.functional,
716 atomRowData.functional);
717 AtomPlanRealColumn->gather(snap_->atomData.functional,
718 atomColData.functional);
719 }
720
721 if (storageLayout_ & DataStorage::dslFunctionalDerivative)
722 {
723 AtomPlanRealRow->gather(snap_->atomData.functionalDerivative,
724 atomRowData.functionalDerivative);
725 AtomPlanRealColumn->gather(snap_->atomData.functionalDerivative,
726 atomColData.functionalDerivative);
727 }
728 #endif
729 }
730
731 void ForceMatrixDecomposition::collectData() {
732 snap_ = sman_->getCurrentSnapshot();
733 storageLayout_ = sman_->getStorageLayout();
734 #ifdef IS_MPI
735 int n = snap_->atomData.force.size();
736 vector<Vector3d> frc_tmp(n, V3Zero);
737
738 AtomPlanVectorRow->scatter(atomRowData.force, frc_tmp);
739 for (int i = 0; i < n; i++)
740 {
741 snap_->atomData.force[i] += frc_tmp[i];
742 frc_tmp[i] = 0.0;
743 }
744
745 AtomPlanVectorColumn->scatter(atomColData.force, frc_tmp);
746 for (int i = 0; i < n; i++)
747 {
748 snap_->atomData.force[i] += frc_tmp[i];
749 }
750
751 if (storageLayout_ & DataStorage::dslTorque)
752 {
753
754 int nt = snap_->atomData.torque.size();
755 vector<Vector3d> trq_tmp(nt, V3Zero);
756
757 AtomPlanVectorRow->scatter(atomRowData.torque, trq_tmp);
758 for (int i = 0; i < nt; i++)
759 {
760 snap_->atomData.torque[i] += trq_tmp[i];
761 trq_tmp[i] = 0.0;
762 }
763
764 AtomPlanVectorColumn->scatter(atomColData.torque, trq_tmp);
765 for (int i = 0; i < nt; i++)
766 snap_->atomData.torque[i] += trq_tmp[i];
767 }
768
769 if (storageLayout_ & DataStorage::dslSkippedCharge)
770 {
771
772 int ns = snap_->atomData.skippedCharge.size();
773 vector<RealType> skch_tmp(ns, 0.0);
774
775 AtomPlanRealRow->scatter(atomRowData.skippedCharge, skch_tmp);
776 for (int i = 0; i < ns; i++)
777 {
778 snap_->atomData.skippedCharge[i] += skch_tmp[i];
779 skch_tmp[i] = 0.0;
780 }
781
782 AtomPlanRealColumn->scatter(atomColData.skippedCharge, skch_tmp);
783 for (int i = 0; i < ns; i++)
784 snap_->atomData.skippedCharge[i] += skch_tmp[i];
785 }
786
787 nLocal_ = snap_->getNumberOfAtoms();
788
789 vector<potVec> pot_temp(nLocal_,
790 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
791
792 // scatter/gather pot_row into the members of my column
793
794 AtomPlanPotRow->scatter(pot_row, pot_temp);
795
796 for (int ii = 0; ii < pot_temp.size(); ii++ )
797 pairwisePot += pot_temp[ii];
798
799 fill(pot_temp.begin(), pot_temp.end(),
800 Vector<RealType, N_INTERACTION_FAMILIES> (0.0));
801
802 AtomPlanPotColumn->scatter(pot_col, pot_temp);
803
804 for (int ii = 0; ii < pot_temp.size(); ii++ )
805 pairwisePot += pot_temp[ii];
806 #endif
807
808 // cerr << "pairwisePot = " << pairwisePot << "\n";
809 }
810
811 int ForceMatrixDecomposition::getNAtomsInRow() {
812 #ifdef IS_MPI
813 return nAtomsInRow_;
814 #else
815 return nLocal_;
816 #endif
817 }
818
819 /**
820 * returns the list of atoms belonging to this group.
821 */
822 vector<int> ForceMatrixDecomposition::getAtomsInGroupRow(int cg1) {
823 #ifdef IS_MPI
824 return groupListRow_[cg1];
825 #else
826 return groupList_[cg1];
827 #endif
828 }
829
830 vector<int> ForceMatrixDecomposition::getAtomsInGroupColumn(int cg2) {
831 #ifdef IS_MPI
832 return groupListCol_[cg2];
833 #else
834 return groupList_[cg2];
835 #endif
836 }
837
838 Vector3d ForceMatrixDecomposition::getIntergroupVector(int cg1, int cg2) {
839 Vector3d d;
840
841 #ifdef IS_MPI
842 d = cgColData.position[cg2] - cgRowData.position[cg1];
843 cerr << "cg1 = " << cg1 << "\tcg1p = " << cgRowData.position[cg1] << "\n";
844 cerr << "cg2 = " << cg2 << "\tcg2p = " << cgColData.position[cg2] << "\n";
845 #else
846 d = snap_->cgData.position[cg2] - snap_->cgData.position[cg1];
847 cerr << "cg1 = " << cg1 << "\tcg1p = " << snap_->cgData.position[cg1] << "\n";
848 cerr << "cg2 = " << cg2 << "\tcg2p = " << snap_->cgData.position[cg2] << "\n";
849 #endif
850
851 snap_->wrapVector(d);
852 return d;
853 }
854
855 Vector3d ForceMatrixDecomposition::getIntergroupVector(CutoffGroup *cg1, CutoffGroup *cg2) {
856 Vector3d d;
857
858 d = snap_->cgData.position[cg2->getLocalIndex()] - snap_->cgData.position[cg1->getLocalIndex()];
859 /* cerr << "cg1_gid = " << cg1->getGlobalIndex() << "\tcg1_lid = " << cg1->getLocalIndex() << "\tcg1p = "
860 << snap_->cgData.position[cg1->getLocalIndex()] << "\n";
861 cerr << "cg2_gid = " << cg2->getGlobalIndex() << "\tcg2_lid = " << cg2->getLocalIndex() << "\tcg2p = "
862 << snap_->cgData.position[cg2->getLocalIndex()] << "\n";*/
863
864 snap_->wrapVector(d);
865 return d;
866 }
867
868 Vector3d ForceMatrixDecomposition::getAtomToGroupVectorRow(int atom1, int cg1) {
869
870 Vector3d d;
871
872 #ifdef IS_MPI
873 d = cgRowData.position[cg1] - atomRowData.position[atom1];
874 #else
875 d = snap_->cgData.position[cg1] - snap_->atomData.position[atom1];
876 #endif
877
878 snap_->wrapVector(d);
879 return d;
880 }
881
882 Vector3d ForceMatrixDecomposition::getAtomToGroupVectorColumn(int atom2, int cg2) {
883 Vector3d d;
884
885 #ifdef IS_MPI
886 d = cgColData.position[cg2] - atomColData.position[atom2];
887 #else
888 d = snap_->cgData.position[cg2] - snap_->atomData.position[atom2];
889 #endif
890
891 snap_->wrapVector(d);
892 return d;
893 }
894
895 RealType ForceMatrixDecomposition::getMassFactorRow(int atom1) {
896 #ifdef IS_MPI
897 return massFactorsRow[atom1];
898 #else
899 return massFactors[atom1];
900 #endif
901 }
902
903 RealType ForceMatrixDecomposition::getMassFactorColumn(int atom2) {
904 #ifdef IS_MPI
905 return massFactorsCol[atom2];
906 #else
907 return massFactors[atom2];
908 #endif
909
910 }
911
912 Vector3d ForceMatrixDecomposition::getInteratomicVector(int atom1, int atom2) {
913 Vector3d d;
914
915 #ifdef IS_MPI
916 d = atomColData.position[atom2] - atomRowData.position[atom1];
917 #else
918 d = snap_->atomData.position[atom2] - snap_->atomData.position[atom1];
919 #endif
920
921 snap_->wrapVector(d);
922 return d;
923 }
924
925 vector<int> ForceMatrixDecomposition::getExcludesForAtom(int atom1) {
926 return excludesForAtom[atom1];
927 }
928
929 /**
930 * We need to exclude some overcounted interactions that result from
931 * the parallel decomposition.
932 */
933 bool ForceMatrixDecomposition::skipAtomPair(int atom1, int atom2) {
934 int unique_id_1, unique_id_2;
935
936 // cerr << "sap with atom1, atom2 =\t" << atom1 << "\t" << atom2 << "\n";
937 #ifdef IS_MPI
938 // in MPI, we have to look up the unique IDs for each atom
939 unique_id_1 = AtomRowToGlobal[atom1];
940 unique_id_2 = AtomColToGlobal[atom2];
941
942 cerr << "sap with uid1, uid2 =\t" << unique_id_1 << "\t" << unique_id_2 << "\n";
943 // this situation should only arise in MPI simulations
944 if (unique_id_1 == unique_id_2) return true;
945
946 // this prevents us from doing the pair on multiple processors
947 if (unique_id_1 < unique_id_2)
948 {
949 if ((unique_id_1 + unique_id_2) % 2 == 0) return true;
950 } else
951 {
952 if ((unique_id_1 + unique_id_2) % 2 == 1) return true;
953 }
954 #endif
955 return false;
956 }
957
958 /**
959 * We need to handle the interactions for atoms who are involved in
960 * the same rigid body as well as some short range interactions
961 * (bonds, bends, torsions) differently from other interactions.
962 * We'll still visit the pairwise routines, but with a flag that
963 * tells those routines to exclude the pair from direct long range
964 * interactions. Some indirect interactions (notably reaction
965 * field) must still be handled for these pairs.
966 */
967 bool ForceMatrixDecomposition::excludeAtomPair(int atom1, int atom2) {
968 int unique_id_2;
969 #ifdef IS_MPI
970 // in MPI, we have to look up the unique IDs for the row atom.
971 unique_id_2 = AtomColToGlobal[atom2];
972 #else
973 // in the normal loop, the atom numbers are unique
974 unique_id_2 = atom2;
975 #endif
976
977 for (vector<int>::iterator i = excludesForAtom[atom1].begin(); i != excludesForAtom[atom1].end(); ++i)
978 {
979 if ((*i) == unique_id_2)
980 return true;
981 }
982
983 return false;
984 }
985
986 void ForceMatrixDecomposition::addForceToAtomRow(int atom1, Vector3d fg) {
987 #ifdef IS_MPI
988 atomRowData.force[atom1] += fg;
989 #else
990 snap_->atomData.force[atom1] += fg;
991 #endif
992 }
993
994 void ForceMatrixDecomposition::addForceToAtomColumn(int atom2, Vector3d fg) {
995 #ifdef IS_MPI
996 atomColData.force[atom2] += fg;
997 #else
998 snap_->atomData.force[atom2] += fg;
999 #endif
1000 }
1001
1002 // filling interaction blocks with pointers
1003 void ForceMatrixDecomposition::fillInteractionData(InteractionData &idat, int atom1, int atom2) {
1004
1005 idat.excluded = excludeAtomPair(atom1, atom2);
1006
1007 #ifdef IS_MPI
1008 idat.atypes = make_pair( atypesRow[atom1], atypesCol[atom2]);
1009 //idat.atypes = make_pair( ff_->getAtomType(identsRow[atom1]),
1010 // ff_->getAtomType(identsCol[atom2]) );
1011
1012 if (storageLayout_ & DataStorage::dslAmat)
1013 {
1014 idat.A1 = &(atomRowData.aMat[atom1]);
1015 idat.A2 = &(atomColData.aMat[atom2]);
1016 }
1017
1018 if (storageLayout_ & DataStorage::dslElectroFrame)
1019 {
1020 idat.eFrame1 = &(atomRowData.electroFrame[atom1]);
1021 idat.eFrame2 = &(atomColData.electroFrame[atom2]);
1022 }
1023
1024 if (storageLayout_ & DataStorage::dslTorque)
1025 {
1026 idat.t1 = &(atomRowData.torque[atom1]);
1027 idat.t2 = &(atomColData.torque[atom2]);
1028 }
1029
1030 if (storageLayout_ & DataStorage::dslDensity)
1031 {
1032 idat.rho1 = &(atomRowData.density[atom1]);
1033 idat.rho2 = &(atomColData.density[atom2]);
1034 }
1035
1036 if (storageLayout_ & DataStorage::dslFunctional)
1037 {
1038 idat.frho1 = &(atomRowData.functional[atom1]);
1039 idat.frho2 = &(atomColData.functional[atom2]);
1040 }
1041
1042 if (storageLayout_ & DataStorage::dslFunctionalDerivative)
1043 {
1044 idat.dfrho1 = &(atomRowData.functionalDerivative[atom1]);
1045 idat.dfrho2 = &(atomColData.functionalDerivative[atom2]);
1046 }
1047
1048 if (storageLayout_ & DataStorage::dslParticlePot)
1049 {
1050 idat.particlePot1 = &(atomRowData.particlePot[atom1]);
1051 idat.particlePot2 = &(atomColData.particlePot[atom2]);
1052 }
1053
1054 if (storageLayout_ & DataStorage::dslSkippedCharge)
1055 {
1056 idat.skippedCharge1 = &(atomRowData.skippedCharge[atom1]);
1057 idat.skippedCharge2 = &(atomColData.skippedCharge[atom2]);
1058 }
1059
1060 #else
1061
1062 idat.atypes = make_pair(atypesLocal[atom1], atypesLocal[atom2]);
1063 //idat.atypes = make_pair( ff_->getAtomType(idents[atom1]),
1064 // ff_->getAtomType(idents[atom2]) );
1065
1066 if (storageLayout_ & DataStorage::dslAmat)
1067 {
1068 idat.A1 = &(snap_->atomData.aMat[atom1]);
1069 idat.A2 = &(snap_->atomData.aMat[atom2]);
1070 }
1071
1072 if (storageLayout_ & DataStorage::dslElectroFrame)
1073 {
1074 idat.eFrame1 = &(snap_->atomData.electroFrame[atom1]);
1075 idat.eFrame2 = &(snap_->atomData.electroFrame[atom2]);
1076 }
1077
1078 if (storageLayout_ & DataStorage::dslTorque)
1079 {
1080 idat.t1 = &(snap_->atomData.torque[atom1]);
1081 idat.t2 = &(snap_->atomData.torque[atom2]);
1082 }
1083
1084 if (storageLayout_ & DataStorage::dslDensity)
1085 {
1086 idat.rho1 = &(snap_->atomData.density[atom1]);
1087 idat.rho2 = &(snap_->atomData.density[atom2]);
1088 }
1089
1090 if (storageLayout_ & DataStorage::dslFunctional)
1091 {
1092 idat.frho1 = &(snap_->atomData.functional[atom1]);
1093 idat.frho2 = &(snap_->atomData.functional[atom2]);
1094 }
1095
1096 if (storageLayout_ & DataStorage::dslFunctionalDerivative)
1097 {
1098 idat.dfrho1 = &(snap_->atomData.functionalDerivative[atom1]);
1099 idat.dfrho2 = &(snap_->atomData.functionalDerivative[atom2]);
1100 }
1101
1102 if (storageLayout_ & DataStorage::dslParticlePot)
1103 {
1104 idat.particlePot1 = &(snap_->atomData.particlePot[atom1]);
1105 idat.particlePot2 = &(snap_->atomData.particlePot[atom2]);
1106 }
1107
1108 if (storageLayout_ & DataStorage::dslSkippedCharge)
1109 {
1110 idat.skippedCharge1 = &(snap_->atomData.skippedCharge[atom1]);
1111 idat.skippedCharge2 = &(snap_->atomData.skippedCharge[atom2]);
1112 }
1113 #endif
1114 }
1115
1116 void ForceMatrixDecomposition::unpackInteractionData(InteractionData &idat, int atom1, int atom2) {
1117 #ifdef IS_MPI
1118 pot_row[atom1] += 0.5 * *(idat.pot);
1119 pot_col[atom2] += 0.5 * *(idat.pot);
1120
1121 atomRowData.force[atom1] += *(idat.f1);
1122 atomColData.force[atom2] -= *(idat.f1);
1123 #else
1124 pairwisePot += *(idat.pot);
1125
1126 snap_->atomData.force[atom1] += *(idat.f1);
1127 snap_->atomData.force[atom2] -= *(idat.f1);
1128 #endif
1129
1130 }
1131
1132 void ForceMatrixDecomposition::reorderGroupCutoffs(vector<int> &order) {
1133 vector<int> tmp = vector<int> (groupToGtype.size());
1134
1135 for (int i = 0; i < groupToGtype.size(); ++i)
1136 {
1137 tmp[i] = groupToGtype[i];
1138 }
1139
1140 for (int i = 0; i < groupToGtype.size(); ++i)
1141 {
1142 groupToGtype[i] = tmp[order[i]];
1143 }
1144 }
1145
1146 void ForceMatrixDecomposition::reorderPosition(vector<int> &order) {
1147 Snapshot* snap_ = info_->getSnapshotManager()->getCurrentSnapshot();
1148 DataStorage* cgConfig = &(snap_->cgData);
1149 vector<Vector3d> tmp = vector<Vector3d> (nGroups_);
1150
1151 for (int i = 0; i < nGroups_; ++i)
1152 {
1153 tmp[i] = snap_->cgData.position[i];
1154 }
1155
1156 vector<int> mapPos = vector<int> (nGroups_);
1157 for (int i = 0; i < nGroups_; ++i)
1158 {
1159 snap_->cgData.position[i] = tmp[order[i]];
1160 mapPos[order[i]] = i;
1161 }
1162
1163 SimInfo::MoleculeIterator mi;
1164 Molecule* mol;
1165 Molecule::CutoffGroupIterator ci;
1166 CutoffGroup* cg;
1167
1168 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1169 {
1170 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
1171 {
1172 cg->setLocalIndex(mapPos[cg->getLocalIndex()]);
1173 }
1174 }
1175
1176 /* if (info_->getNCutoffGroups() > 0)
1177 {
1178 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1179 {
1180 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
1181 {
1182 printf("gbI:%d locI:%d x:%f y:%f z:%f\n", cg->getGlobalIndex(), cg->getLocalIndex(),
1183 cgConfig->position[cg->getLocalIndex()].x(), cgConfig->position[cg->getLocalIndex()].y(),
1184 cgConfig->position[cg->getLocalIndex()].z());
1185 }
1186 }
1187 } else
1188 {
1189 // center of mass of the group is the same as position of the atom
1190 // if cutoff group does not exist
1191 printf("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
1192 // cgConfig->position = config->position;
1193 }*/
1194 }
1195
1196 void ForceMatrixDecomposition::reorderGroupList(vector<int> &order) {
1197 vector<vector<int> > tmp = vector<vector<int> > (groupList_.size());
1198
1199 for (int i = 0; i < groupList_.size(); ++i)
1200 {
1201 tmp[i] = groupList_[i];
1202 }
1203
1204 for (int i = 0; i < groupList_.size(); ++i)
1205 {
1206 groupList_[i] = tmp[order[i]];
1207 }
1208 }
1209
1210 void ForceMatrixDecomposition::reorderMemory(vector<vector<CutoffGroup *> > &H_c_l) {
1211 int n = 0;
1212 // printf("Reorder memory time:%f!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
1213 // info_->getSnapshotManager()->getCurrentSnapshot()->getTime());
1214
1215 /* record the reordered atom indices */
1216 vector<int> k = vector<int> (nGroups_);
1217
1218 for (int c = 0; c < H_c_l.size(); ++c)
1219 {
1220 for (vector<CutoffGroup *>::iterator cg = H_c_l[c].begin(); cg != H_c_l[c].end(); ++cg)
1221 {
1222 int i = (*cg)->getGlobalIndex();
1223 k[n] = i;
1224 ++n;
1225 }
1226 }
1227
1228 // reorderGroupCutoffs(k);
1229 // reorderGroupList(k);
1230 reorderPosition(k);
1231 }
1232
1233 vector<vector<CutoffGroup *> > ForceMatrixDecomposition::buildLayerBasedNeighborList() {
1234 // printf("buildLayerBasedNeighborList; nGroups:%d\n", nGroups_);
1235 // Na = nGroups_
1236 /* cell occupancy counter */
1237 // vector<int> k_c;
1238 /* c_i - has cell containing atom i (size Na) */
1239 vector<int> c = vector<int> (nGroups_);
1240 /* l_i - layer containing atom i (size Na) */
1241 // vector<int> l;
1242
1243 RealType rList_ = (largestRcut_ + skinThickness_);
1244 Snapshot* snap_ = sman_->getCurrentSnapshot();
1245 Mat3x3d Hmat = snap_->getHmat();
1246 Vector3d Hx = Hmat.getColumn(0);
1247 Vector3d Hy = Hmat.getColumn(1);
1248 Vector3d Hz = Hmat.getColumn(2);
1249
1250 nCells_.x() = (int) (Hx.length()) / rList_;
1251 nCells_.y() = (int) (Hy.length()) / rList_;
1252 nCells_.z() = (int) (Hz.length()) / rList_;
1253
1254 Mat3x3d invHmat = snap_->getInvHmat();
1255 Vector3d rs, scaled, dr;
1256 Vector3i whichCell;
1257 int cellIndex;
1258 int nCtot = nCells_.x() * nCells_.y() * nCells_.z();
1259
1260 // k_c = vector<int> (nCtot, 0);
1261
1262 SimInfo::MoleculeIterator mi;
1263 Molecule* mol;
1264 Molecule::CutoffGroupIterator ci;
1265 CutoffGroup* cg;
1266
1267 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1268 {
1269 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
1270 {
1271 rs = snap_->cgData.position[cg->getLocalIndex()];
1272
1273 // scaled positions relative to the box vectors
1274 scaled = invHmat * rs;
1275
1276 // wrap the vector back into the unit box by subtracting integer box
1277 // numbers
1278 for (int j = 0; j < 3; j++)
1279 {
1280 scaled[j] -= roundMe(scaled[j]);
1281 scaled[j] += 0.5;
1282 }
1283
1284 // find xyz-indices of cell that cutoffGroup is in.
1285 whichCell.x() = nCells_.x() * scaled.x();
1286 whichCell.y() = nCells_.y() * scaled.y();
1287 whichCell.z() = nCells_.z() * scaled.z();
1288
1289 // printf("pos x:%f y:%f z:%f cell x:%d y:%d z:%d\n", rs.x(), rs.y(), rs.z(), whichCell.x(), whichCell.y(),
1290 // whichCell.z());
1291
1292 // find single index of this cell:
1293 cellIndex = Vlinear(whichCell, nCells_);
1294
1295 c[cg->getGlobalIndex()] = cellIndex;
1296 }
1297 }
1298
1299 // int k_c_curr;
1300 // int k_c_max = 0;
1301 /* the cell-layer occupancy matrix */
1302 vector<vector<CutoffGroup *> > H_c_l = vector<vector<CutoffGroup *> > (nCtot);
1303
1304 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1305 {
1306 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
1307
1308 {
1309 // k_c_curr = ++k_c[c[cg1->getGlobalIndex()]];
1310 // l.push_back(k_c_curr);
1311 //
1312 // /* determines the number of layers in use */
1313 // if (k_c_max < k_c_curr)
1314 // {
1315 // k_c_max = k_c_curr;
1316 // }
1317 H_c_l[c[cg->getGlobalIndex()]].push_back(/*l[*/cg/*]*/);
1318 }
1319 }
1320
1321 /* Frequency of reordering the memory */
1322 if (neighborListReorderFreq != 0)
1323 {
1324 if (reorderFreqCounter == neighborListReorderFreq)
1325 {
1326 //printf("neighborListReorderFreq:%d\n", neighborListReorderFreq);
1327 reorderMemory(H_c_l);
1328 reorderFreqCounter = 1;
1329 } else
1330 {
1331 reorderFreqCounter++;
1332 }
1333 }
1334
1335 int m;
1336 /* the neighbor matrix */
1337 vector<vector<CutoffGroup *> > neighborMatW = vector<vector<CutoffGroup *> > (nGroups_);
1338
1339 groupCutoffs cuts;
1340 CutoffGroup *cg1;
1341
1342 /* loops over objects(atoms, rigidBodies, cutoffGroups, etc.) */
1343 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1344 {
1345 for (cg1 = mol->beginCutoffGroup(ci); cg1 != NULL; cg1 = mol->nextCutoffGroup(ci))
1346 {
1347 /* c' */
1348 int c1 = c[cg1->getGlobalIndex()];
1349 Vector3i c1v = idxToV(c1, nCells_);
1350
1351 /* loops over the neighboring cells c'' */
1352 for (vector<Vector3i>::iterator os = cellOffsets_.begin(); os != cellOffsets_.end(); ++os)
1353 {
1354 Vector3i c2v = c1v + (*os);
1355
1356 if (c2v.x() >= nCells_.x())
1357 {
1358 c2v.x() = 0;
1359 } else if (c2v.x() < 0)
1360 {
1361 c2v.x() = nCells_.x() - 1;
1362 }
1363
1364 if (c2v.y() >= nCells_.y())
1365 {
1366 c2v.y() = 0;
1367 } else if (c2v.y() < 0)
1368 {
1369 c2v.y() = nCells_.y() - 1;
1370 }
1371
1372 if (c2v.z() >= nCells_.z())
1373 {
1374 c2v.z() = 0;
1375 } else if (c2v.z() < 0)
1376 {
1377 c2v.z() = nCells_.z() - 1;
1378 }
1379
1380 int c2 = Vlinear(c2v, nCells_);
1381 /* loops over layers l to access the neighbor atoms */
1382 for (vector<CutoffGroup *>::iterator cg2 = H_c_l[c2].begin(); cg2 != H_c_l[c2].end(); ++cg2)
1383 {
1384 // if i'' = 0 then break // doesn't apply to vector implementation of matrix
1385 // if(i != *j)
1386 if (c2 != c1 || (*cg2)->getGlobalIndex() < cg1->getGlobalIndex())
1387 {
1388 dr = snap_->cgData.position[(*cg2)->getLocalIndex()] - snap_->cgData.position[cg1->getLocalIndex()];
1389 snap_->wrapVector(dr);
1390 cuts = getGroupCutoffs(cg1->getGlobalIndex(), (*cg2)->getGlobalIndex());
1391 if (dr.lengthSquare() < cuts.third)
1392 {
1393 /* transposed version of Rapaport W mat, to occupy successive memory locations on CPU */
1394 neighborMatW[cg1->getGlobalIndex()].push_back((*cg2));
1395 }
1396 }
1397 }
1398 }
1399 }
1400 }
1401
1402 // save the local cutoff group positions for the check that is
1403 // done on each loop:
1404 saved_CG_positions_.clear();
1405 for (int i = 0; i < nGroups_; i++)
1406 saved_CG_positions_.push_back(snap_->cgData.position[i]);
1407
1408 return neighborMatW;
1409 }
1410
1411 /*
1412 * buildNeighborList
1413 *
1414 * first element of pair is row-indexed CutoffGroup
1415 * second element of pair is column-indexed CutoffGroup
1416 */
1417 vector<pair<int, int> > ForceMatrixDecomposition::buildNeighborList() {
1418
1419 vector<pair<int, int> > neighborList;
1420 groupCutoffs cuts;
1421 bool doAllPairs = false;
1422
1423 #ifdef IS_MPI
1424 cellListRow_.clear();
1425 cellListCol_.clear();
1426 #else
1427 cellList_.clear();
1428 #endif
1429
1430 RealType rList_ = (largestRcut_ + skinThickness_);
1431 RealType rl2 = rList_ * rList_;
1432 Snapshot* snap_ = sman_->getCurrentSnapshot();
1433 Mat3x3d Hmat = snap_->getHmat();
1434 Vector3d Hx = Hmat.getColumn(0);
1435 Vector3d Hy = Hmat.getColumn(1);
1436 Vector3d Hz = Hmat.getColumn(2);
1437
1438 nCells_.x() = (int) (Hx.length()) / rList_;
1439 nCells_.y() = (int) (Hy.length()) / rList_;
1440 nCells_.z() = (int) (Hz.length()) / rList_;
1441
1442 // handle small boxes where the cell offsets can end up repeating cells
1443
1444 if (nCells_.x() < 3)
1445 doAllPairs = true;
1446 if (nCells_.y() < 3)
1447 doAllPairs = true;
1448 if (nCells_.z() < 3)
1449 doAllPairs = true;
1450
1451 Mat3x3d invHmat = snap_->getInvHmat();
1452 Vector3d rs, scaled, dr;
1453 Vector3i whichCell;
1454 int cellIndex;
1455 int nCtot = nCells_.x() * nCells_.y() * nCells_.z();
1456
1457 #ifdef IS_MPI
1458 cellListRow_.resize(nCtot);
1459 cellListCol_.resize(nCtot);
1460 #else
1461 cellList_.resize(nCtot);
1462 #endif
1463
1464 if (!doAllPairs)
1465 {
1466 #ifdef IS_MPI
1467
1468 for (int i = 0; i < nGroupsInRow_; i++)
1469 {
1470 rs = cgRowData.position[i];
1471
1472 // scaled positions relative to the box vectors
1473 scaled = invHmat * rs;
1474
1475 // wrap the vector back into the unit box by subtracting integer box
1476 // numbers
1477 for (int j = 0; j < 3; j++)
1478 {
1479 scaled[j] -= roundMe(scaled[j]);
1480 scaled[j] += 0.5;
1481 }
1482
1483 // find xyz-indices of cell that cutoffGroup is in.
1484 whichCell.x() = nCells_.x() * scaled.x();
1485 whichCell.y() = nCells_.y() * scaled.y();
1486 whichCell.z() = nCells_.z() * scaled.z();
1487
1488 // find single index of this cell:
1489 cellIndex = Vlinear(whichCell, nCells_);
1490
1491 // add this cutoff group to the list of groups in this cell;
1492 cellListRow_[cellIndex].push_back(i);
1493 }
1494 for (int i = 0; i < nGroupsInCol_; i++)
1495 {
1496 rs = cgColData.position[i];
1497
1498 // scaled positions relative to the box vectors
1499 scaled = invHmat * rs;
1500
1501 // wrap the vector back into the unit box by subtracting integer box
1502 // numbers
1503 for (int j = 0; j < 3; j++)
1504 {
1505 scaled[j] -= roundMe(scaled[j]);
1506 scaled[j] += 0.5;
1507 }
1508
1509 // find xyz-indices of cell that cutoffGroup is in.
1510 whichCell.x() = nCells_.x() * scaled.x();
1511 whichCell.y() = nCells_.y() * scaled.y();
1512 whichCell.z() = nCells_.z() * scaled.z();
1513
1514 // find single index of this cell:
1515 cellIndex = Vlinear(whichCell, nCells_);
1516
1517 // add this cutoff group to the list of groups in this cell;
1518 cellListCol_[cellIndex].push_back(i);
1519 }
1520 #else
1521 for (int i = 0; i < nGroups_; i++)
1522 {
1523 rs = snap_->cgData.position[i];
1524
1525 // scaled positions relative to the box vectors
1526 scaled = invHmat * rs;
1527
1528 // wrap the vector back into the unit box by subtracting integer box
1529 // numbers
1530 for (int j = 0; j < 3; j++)
1531 {
1532 scaled[j] -= roundMe(scaled[j]);
1533 scaled[j] += 0.5;
1534 }
1535
1536 // find xyz-indices of cell that cutoffGroup is in.
1537 whichCell.x() = nCells_.x() * scaled.x();
1538 whichCell.y() = nCells_.y() * scaled.y();
1539 whichCell.z() = nCells_.z() * scaled.z();
1540
1541 // find single index of this cell:
1542 cellIndex = Vlinear(whichCell, nCells_);
1543
1544 // add this cutoff group to the list of groups in this cell;
1545 cellList_[cellIndex].push_back(i);
1546 }
1547 #endif
1548
1549 for (int m1z = 0; m1z < nCells_.z(); m1z++)
1550 {
1551 for (int m1y = 0; m1y < nCells_.y(); m1y++)
1552 {
1553 for (int m1x = 0; m1x < nCells_.x(); m1x++)
1554 {
1555 Vector3i m1v(m1x, m1y, m1z);
1556 int m1 = Vlinear(m1v, nCells_);
1557
1558 for (vector<Vector3i>::iterator os = cellOffsets_.begin(); os != cellOffsets_.end(); ++os)
1559 {
1560
1561 Vector3i m2v = m1v + (*os);
1562
1563 if (m2v.x() >= nCells_.x())
1564 {
1565 m2v.x() = 0;
1566 } else if (m2v.x() < 0)
1567 {
1568 m2v.x() = nCells_.x() - 1;
1569 }
1570
1571 if (m2v.y() >= nCells_.y())
1572 {
1573 m2v.y() = 0;
1574 } else if (m2v.y() < 0)
1575 {
1576 m2v.y() = nCells_.y() - 1;
1577 }
1578
1579 if (m2v.z() >= nCells_.z())
1580 {
1581 m2v.z() = 0;
1582 } else if (m2v.z() < 0)
1583 {
1584 m2v.z() = nCells_.z() - 1;
1585 }
1586
1587 int m2 = Vlinear(m2v, nCells_);
1588
1589 #ifdef IS_MPI
1590 for (vector<int>::iterator j1 = cellListRow_[m1].begin();
1591 j1 != cellListRow_[m1].end(); ++j1)
1592 {
1593 for (vector<int>::iterator j2 = cellListCol_[m2].begin();
1594 j2 != cellListCol_[m2].end(); ++j2)
1595 {
1596
1597 // In parallel, we need to visit *all* pairs of row &
1598 // column indicies and will truncate later on.
1599 dr = cgColData.position[(*j2)] - cgRowData.position[(*j1)];
1600 snap_->wrapVector(dr);
1601 cuts = getGroupCutoffs( (*j1), (*j2) );
1602 if (dr.lengthSquare() < cuts.third)
1603 {
1604 neighborList.push_back(make_pair((*j1), (*j2)));
1605 }
1606 }
1607 }
1608 #else
1609
1610 for (vector<int>::iterator j1 = cellList_[m1].begin(); j1 != cellList_[m1].end(); ++j1)
1611 {
1612 for (vector<int>::iterator j2 = cellList_[m2].begin(); j2 != cellList_[m2].end(); ++j2)
1613 {
1614
1615 // Always do this if we're in different cells or if
1616 // we're in the same cell and the global index of the
1617 // j2 cutoff group is less than the j1 cutoff group
1618
1619 if (m2 != m1 || (*j2) < (*j1))
1620 {
1621 dr = snap_->cgData.position[(*j2)] - snap_->cgData.position[(*j1)];
1622 snap_->wrapVector(dr);
1623 cuts = getGroupCutoffs((*j1), (*j2));
1624 if (dr.lengthSquare() < cuts.third)
1625 {
1626 neighborList.push_back(make_pair((*j1), (*j2)));
1627 }
1628 }
1629 }
1630 }
1631 #endif
1632 }
1633 }
1634 }
1635 }
1636 } else
1637 {
1638 // branch to do all cutoff group pairs
1639 #ifdef IS_MPI
1640 for (int j1 = 0; j1 < nGroupsInRow_; j1++)
1641 {
1642 for (int j2 = 0; j2 < nGroupsInCol_; j2++)
1643 {
1644 dr = cgColData.position[j2] - cgRowData.position[j1];
1645 snap_->wrapVector(dr);
1646 cuts = getGroupCutoffs( j1, j2 );
1647 if (dr.lengthSquare() < cuts.third)
1648 {
1649 neighborList.push_back(make_pair(j1, j2));
1650 }
1651 }
1652 }
1653 #else
1654 for (int j1 = 0; j1 < nGroups_ - 1; j1++)
1655 {
1656 for (int j2 = j1 + 1; j2 < nGroups_; j2++)
1657 {
1658 dr = snap_->cgData.position[j2] - snap_->cgData.position[j1];
1659 snap_->wrapVector(dr);
1660 cuts = getGroupCutoffs(j1, j2);
1661 if (dr.lengthSquare() < cuts.third)
1662 {
1663 neighborList.push_back(make_pair(j1, j2));
1664 }
1665 }
1666 }
1667 #endif
1668 }
1669
1670 // save the local cutoff group positions for the check that is
1671 // done on each loop:
1672 saved_CG_positions_.clear();
1673 for (int i = 0; i < nGroups_; i++)
1674 saved_CG_positions_.push_back(snap_->cgData.position[i]);
1675
1676 return neighborList;
1677 }
1678 } //end namespace OpenMD