--- branches/development/src/parallel/ForceDecomposition.cpp 2011/01/17 21:34:36 1540 +++ branches/development/src/parallel/ForceMatrixDecomposition.cpp 2011/05/12 17:00:14 1562 @@ -38,140 +38,455 @@ * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008). * [4] Vardeman & Gezelter, in progress (2009). */ -#include "parallel/ForceDecomposition.hpp" -#include "parallel/Communicator.hpp" +#include "parallel/ForceMatrixDecomposition.hpp" #include "math/SquareMatrix3.hpp" +#include "nonbonded/NonBondedInteraction.hpp" +#include "brains/SnapshotManager.hpp" +using namespace std; namespace OpenMD { - void ForceDecomposition::distributeInitialData() { -#ifdef IS_MPI + /** + * distributeInitialData is essentially a copy of the older fortran + * SimulationSetup + */ + + void ForceMatrixDecomposition::distributeInitialData() { + snap_ = sman_->getCurrentSnapshot(); + storageLayout_ = sman_->getStorageLayout(); +#ifdef IS_MPI + int nLocal = snap_->getNumberOfAtoms(); + int nGroups = snap_->getNumberOfCutoffGroups(); + + AtomCommIntRow = new Communicator(nLocal); + AtomCommRealRow = new Communicator(nLocal); + AtomCommVectorRow = new Communicator(nLocal); + AtomCommMatrixRow = new Communicator(nLocal); - int nAtoms; - int nGroups; + AtomCommIntColumn = new Communicator(nLocal); + AtomCommRealColumn = new Communicator(nLocal); + AtomCommVectorColumn = new Communicator(nLocal); + AtomCommMatrixColumn = new Communicator(nLocal); - AtomCommRealI = new Communicator(nAtoms); - AtomCommVectorI = new Communicator(nAtoms); - AtomCommMatrixI = new Communicator(nAtoms); + cgCommIntRow = new Communicator(nGroups); + cgCommVectorRow = new Communicator(nGroups); + cgCommIntColumn = new Communicator(nGroups); + cgCommVectorColumn = new Communicator(nGroups); - AtomCommRealJ = new Communicator(nAtoms); - AtomCommVectorJ = new Communicator(nAtoms); - AtomCommMatrixJ = new Communicator(nAtoms); + int nAtomsInRow = AtomCommIntRow->getSize(); + int nAtomsInCol = AtomCommIntColumn->getSize(); + int nGroupsInRow = cgCommIntRow->getSize(); + int nGroupsInCol = cgCommIntColumn->getSize(); - cgCommVectorI = new Communicator(nGroups); - cgCommVectorJ = new Communicator(nGroups); - // more to come + // Modify the data storage objects with the correct layouts and sizes: + atomRowData.resize(nAtomsInRow); + atomRowData.setStorageLayout(storageLayout_); + atomColData.resize(nAtomsInCol); + atomColData.setStorageLayout(storageLayout_); + cgRowData.resize(nGroupsInRow); + cgRowData.setStorageLayout(DataStorage::dslPosition); + cgColData.resize(nGroupsInCol); + cgColData.setStorageLayout(DataStorage::dslPosition); + + vector > pot_row(N_INTERACTION_FAMILIES, + vector (nAtomsInRow, 0.0)); + vector > pot_col(N_INTERACTION_FAMILIES, + vector (nAtomsInCol, 0.0)); + + + vector pot_local(N_INTERACTION_FAMILIES, 0.0); + + // gather the information for atomtype IDs (atids): + vector identsLocal = info_->getIdentArray(); + identsRow.reserve(nAtomsInRow); + identsCol.reserve(nAtomsInCol); + + AtomCommIntRow->gather(identsLocal, identsRow); + AtomCommIntColumn->gather(identsLocal, identsCol); + + AtomLocalToGlobal = info_->getGlobalAtomIndices(); + AtomCommIntRow->gather(AtomLocalToGlobal, AtomRowToGlobal); + AtomCommIntColumn->gather(AtomLocalToGlobal, AtomColToGlobal); + + cgLocalToGlobal = info_->getGlobalGroupIndices(); + cgCommIntRow->gather(cgLocalToGlobal, cgRowToGlobal); + cgCommIntColumn->gather(cgLocalToGlobal, cgColToGlobal); + + // still need: + // topoDist + // exclude #endif } - void ForceDecomposition::distributeData() { + void ForceMatrixDecomposition::distributeData() { + snap_ = sman_->getCurrentSnapshot(); + storageLayout_ = sman_->getStorageLayout(); #ifdef IS_MPI - Snapshot* snap = sman_->getCurrentSnapshot(); // gather up the atomic positions - AtomCommVectorI->gather(snap->atomData.position, - snap->atomIData.position); - AtomCommVectorJ->gather(snap->atomData.position, - snap->atomJData.position); + AtomCommVectorRow->gather(snap_->atomData.position, + atomRowData.position); + AtomCommVectorColumn->gather(snap_->atomData.position, + atomColData.position); // gather up the cutoff group positions - cgCommVectorI->gather(snap->cgData.position, - snap->cgIData.position); - cgCommVectorJ->gather(snap->cgData.position, - snap->cgJData.position); + cgCommVectorRow->gather(snap_->cgData.position, + cgRowData.position); + cgCommVectorColumn->gather(snap_->cgData.position, + cgColData.position); // if needed, gather the atomic rotation matrices - if (snap->atomData.getStorageLayout() & DataStorage::dslAmat) { - AtomCommMatrixI->gather(snap->atomData.aMat, - snap->atomIData.aMat); - AtomCommMatrixJ->gather(snap->atomData.aMat, - snap->atomJData.aMat); + if (storageLayout_ & DataStorage::dslAmat) { + AtomCommMatrixRow->gather(snap_->atomData.aMat, + atomRowData.aMat); + AtomCommMatrixColumn->gather(snap_->atomData.aMat, + atomColData.aMat); } // if needed, gather the atomic eletrostatic frames - if (snap->atomData.getStorageLayout() & DataStorage::dslElectroFrame) { - AtomCommMatrixI->gather(snap->atomData.electroFrame, - snap->atomIData.electroFrame); - AtomCommMatrixJ->gather(snap->atomData.electroFrame, - snap->atomJData.electroFrame); + if (storageLayout_ & DataStorage::dslElectroFrame) { + AtomCommMatrixRow->gather(snap_->atomData.electroFrame, + atomRowData.electroFrame); + AtomCommMatrixColumn->gather(snap_->atomData.electroFrame, + atomColData.electroFrame); } #endif } - void ForceDecomposition::collectIntermediateData() { + void ForceMatrixDecomposition::collectIntermediateData() { + snap_ = sman_->getCurrentSnapshot(); + storageLayout_ = sman_->getStorageLayout(); #ifdef IS_MPI - Snapshot* snap = sman_->getCurrentSnapshot(); - if (snap->atomData.getStorageLayout() & DataStorage::dslDensity) { - AtomCommRealI->scatter(snap->atomIData.density, - snap->atomData.density); - std::vector rho_tmp; - int n = snap->getNumberOfAtoms(); - rho_tmp.reserve( n ); - AtomCommRealJ->scatter(snap->atomJData.density, rho_tmp); + if (storageLayout_ & DataStorage::dslDensity) { + + AtomCommRealRow->scatter(atomRowData.density, + snap_->atomData.density); + + int n = snap_->atomData.density.size(); + std::vector rho_tmp(n, 0.0); + AtomCommRealColumn->scatter(atomColData.density, rho_tmp); for (int i = 0; i < n; i++) - snap->atomData.density[i] += rho_tmp[i]; + snap_->atomData.density[i] += rho_tmp[i]; } #endif } - void ForceDecomposition::distributeIntermediateData() { + void ForceMatrixDecomposition::distributeIntermediateData() { + snap_ = sman_->getCurrentSnapshot(); + storageLayout_ = sman_->getStorageLayout(); #ifdef IS_MPI - Snapshot* snap = sman_->getCurrentSnapshot(); - if (snap->atomData.getStorageLayout() & DataStorage::dslFunctional) { - AtomCommRealI->gather(snap->atomData.functional, - snap->atomIData.functional); - AtomCommRealJ->gather(snap->atomData.functional, - snap->atomJData.functional); + if (storageLayout_ & DataStorage::dslFunctional) { + AtomCommRealRow->gather(snap_->atomData.functional, + atomRowData.functional); + AtomCommRealColumn->gather(snap_->atomData.functional, + atomColData.functional); } - if (snap->atomData.getStorageLayout() & DataStorage::dslFunctionalDerivative) { - AtomCommRealI->gather(snap->atomData.functionalDerivative, - snap->atomIData.functionalDerivative); - AtomCommRealJ->gather(snap->atomData.functionalDerivative, - snap->atomJData.functionalDerivative); + if (storageLayout_ & DataStorage::dslFunctionalDerivative) { + AtomCommRealRow->gather(snap_->atomData.functionalDerivative, + atomRowData.functionalDerivative); + AtomCommRealColumn->gather(snap_->atomData.functionalDerivative, + atomColData.functionalDerivative); } #endif } - void ForceDecomposition::collectData() { -#ifdef IS_MPI - Snapshot* snap = sman_->getCurrentSnapshot(); - int n = snap->getNumberOfAtoms(); - - std::vector frc_tmp; - frc_tmp.reserve( n ); + void ForceMatrixDecomposition::collectData() { + snap_ = sman_->getCurrentSnapshot(); + storageLayout_ = sman_->getStorageLayout(); +#ifdef IS_MPI + int n = snap_->atomData.force.size(); + vector frc_tmp(n, V3Zero); - AtomCommVectorI->scatter(snap->atomIData.force, frc_tmp); - for (int i = 0; i < n; i++) - snap->atomData.force[i] += frc_tmp[i]; + AtomCommVectorRow->scatter(atomRowData.force, frc_tmp); + for (int i = 0; i < n; i++) { + snap_->atomData.force[i] += frc_tmp[i]; + frc_tmp[i] = 0.0; + } - AtomCommVectorJ->scatter(snap->atomJData.force, frc_tmp); + AtomCommVectorColumn->scatter(atomColData.force, frc_tmp); for (int i = 0; i < n; i++) - snap->atomData.force[i] += frc_tmp[i]; + snap_->atomData.force[i] += frc_tmp[i]; - if (snap->atomData.getStorageLayout() & DataStorage::dslTorque) { - std::vector trq_tmp; - trq_tmp.reserve( n ); + if (storageLayout_ & DataStorage::dslTorque) { + + int nt = snap_->atomData.force.size(); + vector trq_tmp(nt, V3Zero); + + AtomCommVectorRow->scatter(atomRowData.torque, trq_tmp); + for (int i = 0; i < n; i++) { + snap_->atomData.torque[i] += trq_tmp[i]; + trq_tmp[i] = 0.0; + } - AtomCommVectorI->scatter(snap->atomIData.torque, trq_tmp); + AtomCommVectorColumn->scatter(atomColData.torque, trq_tmp); for (int i = 0; i < n; i++) - snap->atomData.torque[i] += trq_tmp[i]; - - AtomCommVectorJ->scatter(snap->atomJData.torque, trq_tmp); - for (int i = 0; i < n; i++) - snap->atomData.torque[i] += trq_tmp[i]; + snap_->atomData.torque[i] += trq_tmp[i]; } - // Still need pot! + int nLocal = snap_->getNumberOfAtoms(); + + vector > pot_temp(N_INTERACTION_FAMILIES, + vector (nLocal, 0.0)); + for (int i = 0; i < N_INTERACTION_FAMILIES; i++) { + AtomCommRealRow->scatter(pot_row[i], pot_temp[i]); + for (int ii = 0; ii < pot_temp[i].size(); ii++ ) { + pot_local[i] += pot_temp[i][ii]; + } + } +#endif + } + + Vector3d ForceMatrixDecomposition::getIntergroupVector(int cg1, int cg2){ + Vector3d d; + +#ifdef IS_MPI + d = cgColData.position[cg2] - cgRowData.position[cg1]; +#else + d = snap_->cgData.position[cg2] - snap_->cgData.position[cg1]; +#endif + + snap_->wrapVector(d); + return d; + } + + Vector3d ForceMatrixDecomposition::getAtomToGroupVectorRow(int atom1, int cg1){ + + Vector3d d; + +#ifdef IS_MPI + d = cgRowData.position[cg1] - atomRowData.position[atom1]; +#else + d = snap_->cgData.position[cg1] - snap_->atomData.position[atom1]; #endif + + snap_->wrapVector(d); + return d; } + Vector3d ForceMatrixDecomposition::getAtomToGroupVectorColumn(int atom2, int cg2){ + Vector3d d; + +#ifdef IS_MPI + d = cgColData.position[cg2] - atomColData.position[atom2]; +#else + d = snap_->cgData.position[cg2] - snap_->atomData.position[atom2]; +#endif + + snap_->wrapVector(d); + return d; + } + + Vector3d ForceMatrixDecomposition::getInteratomicVector(int atom1, int atom2){ + Vector3d d; + +#ifdef IS_MPI + d = atomColData.position[atom2] - atomRowData.position[atom1]; +#else + d = snap_->atomData.position[atom2] - snap_->atomData.position[atom1]; +#endif + + snap_->wrapVector(d); + return d; + } + + void ForceMatrixDecomposition::addForceToAtomRow(int atom1, Vector3d fg){ +#ifdef IS_MPI + atomRowData.force[atom1] += fg; +#else + snap_->atomData.force[atom1] += fg; +#endif + } + + void ForceMatrixDecomposition::addForceToAtomColumn(int atom2, Vector3d fg){ +#ifdef IS_MPI + atomColData.force[atom2] += fg; +#else + snap_->atomData.force[atom2] += fg; +#endif + + } + + // filling interaction blocks with pointers + InteractionData ForceMatrixDecomposition::fillInteractionData(int atom1, int atom2) { + + InteractionData idat; +#ifdef IS_MPI + if (storageLayout_ & DataStorage::dslAmat) { + idat.A1 = &(atomRowData.aMat[atom1]); + idat.A2 = &(atomColData.aMat[atom2]); + } + + if (storageLayout_ & DataStorage::dslElectroFrame) { + idat.eFrame1 = &(atomRowData.electroFrame[atom1]); + idat.eFrame2 = &(atomColData.electroFrame[atom2]); + } + + if (storageLayout_ & DataStorage::dslTorque) { + idat.t1 = &(atomRowData.torque[atom1]); + idat.t2 = &(atomColData.torque[atom2]); + } + + if (storageLayout_ & DataStorage::dslDensity) { + idat.rho1 = &(atomRowData.density[atom1]); + idat.rho2 = &(atomColData.density[atom2]); + } + + if (storageLayout_ & DataStorage::dslFunctionalDerivative) { + idat.dfrho1 = &(atomRowData.functionalDerivative[atom1]); + idat.dfrho2 = &(atomColData.functionalDerivative[atom2]); + } +#else + if (storageLayout_ & DataStorage::dslAmat) { + idat.A1 = &(snap_->atomData.aMat[atom1]); + idat.A2 = &(snap_->atomData.aMat[atom2]); + } + + if (storageLayout_ & DataStorage::dslElectroFrame) { + idat.eFrame1 = &(snap_->atomData.electroFrame[atom1]); + idat.eFrame2 = &(snap_->atomData.electroFrame[atom2]); + } + + if (storageLayout_ & DataStorage::dslTorque) { + idat.t1 = &(snap_->atomData.torque[atom1]); + idat.t2 = &(snap_->atomData.torque[atom2]); + } + + if (storageLayout_ & DataStorage::dslDensity) { + idat.rho1 = &(snap_->atomData.density[atom1]); + idat.rho2 = &(snap_->atomData.density[atom2]); + } + + if (storageLayout_ & DataStorage::dslFunctionalDerivative) { + idat.dfrho1 = &(snap_->atomData.functionalDerivative[atom1]); + idat.dfrho2 = &(snap_->atomData.functionalDerivative[atom2]); + } +#endif + + } + InteractionData ForceMatrixDecomposition::fillSkipData(int atom1, int atom2){ + InteractionData idat; + skippedCharge1 + skippedCharge2 + rij + d + electroMult + sw + f +#ifdef IS_MPI + + if (storageLayout_ & DataStorage::dslElectroFrame) { + idat.eFrame1 = &(atomRowData.electroFrame[atom1]); + idat.eFrame2 = &(atomColData.electroFrame[atom2]); + } + if (storageLayout_ & DataStorage::dslTorque) { + idat.t1 = &(atomRowData.torque[atom1]); + idat.t2 = &(atomColData.torque[atom2]); + } + + + } + SelfData ForceMatrixDecomposition::fillSelfData(int atom1) { + } + + + /* + * buildNeighborList + * + * first element of pair is row-indexed CutoffGroup + * second element of pair is column-indexed CutoffGroup + */ + vector > buildNeighborList() { + Vector3d dr, invWid, rs, shift; + Vector3i cc, m1v, m2s; + RealType rrNebr; + int c, j1, j2, m1, m1x, m1y, m1z, m2, n, offset; + + + vector > neighborList; + Vector3i nCells; + Vector3d invWid, r; + + rList_ = (rCut_ + skinThickness_); + rl2 = rList_ * rList_; + + snap_ = sman_->getCurrentSnapshot(); + Mat3x3d Hmat = snap_->getHmat(); + Vector3d Hx = Hmat.getColumn(0); + Vector3d Hy = Hmat.getColumn(1); + Vector3d Hz = Hmat.getColumn(2); + + nCells.x() = (int) ( Hx.length() )/ rList_; + nCells.y() = (int) ( Hy.length() )/ rList_; + nCells.z() = (int) ( Hz.length() )/ rList_; + + for (i = 0; i < nGroupsInRow; i++) { + rs = cgRowData.position[i]; + snap_->scaleVector(rs); + } + + + VDiv (invWid, cells, region); + for (n = nMol; n < nMol + cells.componentProduct(); n ++) cellList[n] = -1; + for (n = 0; n < nMol; n ++) { + VSAdd (rs, mol[n].r, 0.5, region); + VMul (cc, rs, invWid); + c = VLinear (cc, cells) + nMol; + cellList[n] = cellList[c]; + cellList[c] = n; + } + nebrTabLen = 0; + for (m1z = 0; m1z < cells.z(); m1z++) { + for (m1y = 0; m1y < cells.y(); m1y++) { + for (m1x = 0; m1x < cells.x(); m1x++) { + Vector3i m1v(m1x, m1y, m1z); + m1 = VLinear(m1v, cells) + nMol; + for (offset = 0; offset < nOffset_; offset++) { + m2v = m1v + cellOffsets_[offset]; + shift = V3Zero(); + + if (m2v.x() >= cells.x) { + m2v.x() = 0; + shift.x() = region.x(); + } else if (m2v.x() < 0) { + m2v.x() = cells.x() - 1; + shift.x() = - region.x(); + } + + if (m2v.y() >= cells.y()) { + m2v.y() = 0; + shift.y() = region.y(); + } else if (m2v.y() < 0) { + m2v.y() = cells.y() - 1; + shift.y() = - region.y(); + } + + m2 = VLinear (m2v, cells) + nMol; + for (j1 = cellList[m1]; j1 >= 0; j1 = cellList[j1]) { + for (j2 = cellList[m2]; j2 >= 0; j2 = cellList[j2]) { + if (m1 != m2 || j2 < j1) { + dr = mol[j1].r - mol[j2].r; + VSub (dr, mol[j1].r, mol[j2].r); + VVSub (dr, shift); + if (VLenSq (dr) < rrNebr) { + neighborList.push_back(make_pair(j1, j2)); + } + } + } + } + } + } + } + } + } + + } //end namespace OpenMD