--- branches/development/src/parallel/ForceDecomposition.cpp 2011/01/11 18:58:12 1538 +++ branches/development/src/parallel/ForceDecomposition.cpp 2011/03/18 19:31:52 1544 @@ -1,13 +1,6 @@ -/** - * @file ForceDecomposition.cpp - * @author Charles Vardeman - * @date 08/18/2010 - * @time 11:56am - * @version 1.0 +/* + * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved. * - * @section LICENSE - * Copyright (c) 2010 The University of Notre Dame. All Rights Reserved. - * * The University of Notre Dame grants you ("Licensee") a * non-exclusive, royalty free, license to use, modify and * redistribute this software in source and binary code form, provided @@ -45,93 +38,195 @@ * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008). * [4] Vardeman & Gezelter, in progress (2009). */ +#include "parallel/ForceDecomposition.hpp" +#include "math/SquareMatrix3.hpp" +#include "nonbonded/NonBondedInteraction.hpp" +#include "brains/SnapshotManager.hpp" +using namespace std; +namespace OpenMD { + /** + * distributeInitialData is essentially a copy of the older fortran + * SimulationSetup + */ + + void ForceDecomposition::distributeInitialData() { +#ifdef IS_MPI + Snapshot* snap = sman_->getCurrentSnapshot(); + int nLocal = snap->getNumberOfAtoms(); + int nGroups = snap->getNumberOfCutoffGroups(); -/* -*- c++ -*- */ -#include "config.h" -#include -#ifdef IS_MPI -#include -#endif + AtomCommIntI = new Communicator(nLocal); + AtomCommRealI = new Communicator(nLocal); + AtomCommVectorI = new Communicator(nLocal); + AtomCommMatrixI = new Communicator(nLocal); -#include -#include -#include -#include -#include "parallel/ForceDecomposition.hpp" + AtomCommIntJ = new Communicator(nLocal); + AtomCommRealJ = new Communicator(nLocal); + AtomCommVectorJ = new Communicator(nLocal); + AtomCommMatrixJ = new Communicator(nLocal); + cgCommIntI = new Communicator(nGroups); + cgCommVectorI = new Communicator(nGroups); + cgCommIntJ = new Communicator(nGroups); + cgCommVectorJ = new Communicator(nGroups); -using namespace std; -using namespace OpenMD; + int nAtomsInRow = AtomCommIntI->getSize(); + int nAtomsInCol = AtomCommIntJ->getSize(); + int nGroupsInRow = cgCommIntI->getSize(); + int nGroupsInCol = cgCommIntJ->getSize(); -//__static -#ifdef IS_MPI -static vector communictors; -#endif + 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); -//____ MPITypeTraits -template -struct MPITypeTraits; + // gather the information for atomtype IDs (atids): + AtomCommIntI->gather(info_->getIdentArray(), identsRow); + AtomCommIntJ->gather(info_->getIdentArray(), identsCol); -#ifdef IS_MPI -template<> -struct MPITypeTraits { - static const MPI::Datatype datatype; -}; -const MPI_Datatype MPITypeTraits::datatype = MY_MPI_REAL; + AtomLocalToGlobal = info_->getLocalToGlobalAtomIndex(); + AtomCommIntI->gather(AtomLocalToGlobal, AtomRowToGlobal); + AtomCommIntJ->gather(AtomLocalToGlobal, AtomColToGlobal); -template<> -struct MPITypeTraits { - static const MPI::Datatype datatype; -}; -const MPI::Datatype MPITypeTraits::datatype = MPI_INT; -#endif + cgLocalToGlobal = info_->getLocalToGlobalCutoffGroupIndex(); + cgCommIntI->gather(cgLocalToGlobal, cgRowToGlobal); + cgCommIntJ->gather(cgLocalToGlobal, cgColToGlobal); -/** -* Constructor for ForceDecomposition Parallel Decomposition Method -* Will try to construct a symmetric grid of processors. Ideally, the -* number of processors will be a square ex: 4, 9, 16, 25. -* -*/ + + -ForceDecomposition::ForceDecomposition() { -#ifdef IS_MPI - int nProcs = MPI::COMM_WORLD.Get_size(); - int worldRank = MPI::COMM_WORLD.Get_rank(); + + // still need: + // topoDist + // exclude #endif + } + - // First time through, construct column stride. - if (communicators.size() == 0) - { - int nColumnsMax = (int) round(sqrt((float) nProcs)); - for (int i = 0; i < nProcs; ++i) - { - if (nProcs%i==0) nColumns=i; + + void ForceDecomposition::distributeData() { +#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); + + // gather up the cutoff group positions + cgCommVectorI->gather(snap->cgData.position, + snap->cgIData.position); + cgCommVectorJ->gather(snap->cgData.position, + snap->cgJData.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 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); + } +#endif + } + + void ForceDecomposition::collectIntermediateData() { +#ifdef IS_MPI + Snapshot* snap = sman_->getCurrentSnapshot(); + + if (snap->atomData.getStorageLayout() & DataStorage::dslDensity) { - int nRows = nProcs/nColumns; - myRank_ = (int) worldRank%nColumns; + AtomCommRealI->scatter(snap->atomIData.density, + snap->atomData.density); + + int n = snap->atomData.density.size(); + std::vector rho_tmp(n, 0.0); + AtomCommRealJ->scatter(snap->atomJData.density, rho_tmp); + for (int i = 0; i < n; i++) + snap->atomData.density[i] += rho_tmp[i]; + } +#endif } - else - { - myRank_ = myRank/nColumns; + + void ForceDecomposition::distributeIntermediateData() { +#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 (snap->atomData.getStorageLayout() & DataStorage::dslFunctionalDerivative) { + AtomCommRealI->gather(snap->atomData.functionalDerivative, + snap->atomIData.functionalDerivative); + AtomCommRealJ->gather(snap->atomData.functionalDerivative, + snap->atomJData.functionalDerivative); + } +#endif } - MPI::Comm newComm = MPI:COMM_WORLD.Split(myRank_,0); - isColumn_ = false; -} + void ForceDecomposition::collectData() { +#ifdef IS_MPI + Snapshot* snap = sman_->getCurrentSnapshot(); + + 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]; + frc_tmp[i] = 0.0; + } + + AtomCommVectorJ->scatter(snap->atomJData.force, frc_tmp); + for (int i = 0; i < n; i++) + snap->atomData.force[i] += frc_tmp[i]; + + + if (snap->atomData.getStorageLayout() & DataStorage::dslTorque) { -ForceDecomposition::gather(sendbuf, receivebuf){ - communicators(myIndex_).Allgatherv(); -} + int nt = snap->atomData.force.size(); + vector trq_tmp(nt, V3Zero); + AtomCommVectorI->scatter(snap->atomIData.torque, trq_tmp); + for (int i = 0; i < n; i++) { + snap->atomData.torque[i] += trq_tmp[i]; + trq_tmp[i] = 0.0; + } + + AtomCommVectorJ->scatter(snap->atomJData.torque, trq_tmp); + for (int i = 0; i < n; i++) + snap->atomData.torque[i] += trq_tmp[i]; + } + + int nLocal = snap->getNumberOfAtoms(); - -ForceDecomposition::scatter(sbuffer, rbuffer){ - communicators(myIndex_).Reduce_scatter(sbuffer, recevbuf. recvcounts, MPI::DOUBLE, MPI::SUM); -} - - + vector > pot_temp(N_INTERACTION_FAMILIES, + vector (nLocal, 0.0)); + + for (int i = 0; i < N_INTERACTION_FAMILIES; i++) { + AtomCommRealI->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 + } + +} //end namespace OpenMD