1 #ifndef DDMD_PAIR_POTENTIAL_IMPL_H 2 #define DDMD_PAIR_POTENTIAL_IMPL_H 11 #include <ddMd/potentials/pair/PairPotential.h> 12 #include <util/space/Tensor.h> 18 #define PAIR_BLOCK_SIZE 16 41 template <
class Interaction>
75 virtual void setNAtomType(
int nAtomType);
90 virtual void readParameters(std::istream& in);
126 double pairEnergy(
double rsq,
int iAtomType,
int jAtomType)
const;
137 double pairForceOverR(
double rsq,
int iAtomType,
int jAtomType)
const;
147 void set(std::string name,
int i,
int j,
double value)
148 { interactionPtr_->set(name, i, j, value); }
157 double get(std::string name,
int i,
int j)
const 158 {
return interactionPtr_->get(name, i, j); }
163 virtual double maxPairCutoff()
const;
168 virtual std::string interactionClassName()
const;
174 {
return *interactionPtr_; }
180 {
return *interactionPtr_; }
194 virtual void computeForces();
202 virtual void computeEnergy(MPI::Intracomm& communicator);
204 virtual void computeEnergy();
213 virtual void computeStress(MPI::Intracomm& communicator);
215 virtual void computeStress();
225 virtual void computePairEnergies(MPI::Intracomm& communicator);
227 virtual void computePairEnergies();
236 virtual void computeForcesAndStress(MPI::Intracomm& communicator);
238 virtual void computeForcesAndStress();
245 #ifdef PAIR_BLOCK_SIZE 260 Interaction* interactionPtr_;
269 #ifdef PAIR_BLOCK_SIZE 270 PairForce pairs_[PAIR_BLOCK_SIZE];
271 PairForce* inPairs_[PAIR_BLOCK_SIZE];
287 void computeForcesList();
297 void computeForcesCell();
309 void computeForcesNSq();
315 #include <ddMd/simulation/Simulation.h> 316 #include <ddMd/storage/AtomStorage.h> 317 #include <ddMd/storage/AtomIterator.h> 318 #include <ddMd/storage/GhostIterator.h> 319 #include <ddMd/neighbor/PairIterator.h> 320 #include <ddMd/communicate/Domain.h> 322 #include <util/space/Dimension.h> 323 #include <util/space/Vector.h> 324 #include <util/accumulators/setToZero.h> 332 using namespace Util;
337 template <
class Interaction>
341 isInitialized_(false)
343 interactionPtr_ =
new Interaction;
350 template <
class Interaction>
354 isInitialized_(false)
355 { interactionPtr_ =
new Interaction; }
360 template <
class Interaction>
363 if (interactionPtr_) {
364 delete interactionPtr_;
371 template <
class Interaction>
375 nAtomType_ = nAtomType;
382 template <
class Interaction>
390 bool nextIndent =
false;
395 isInitialized_ =
true;
401 template <
class Interaction>
408 bool nextIndent =
false;
412 isInitialized_ =
true;
418 template <
class Interaction>
428 template <
class Interaction>
double 430 int iAtomType,
int jAtomType)
const 431 {
return interaction().energy(rsq, iAtomType, jAtomType); }
436 template <
class Interaction>
double 438 int iAtomType,
int jAtomType)
const 440 if (rsq <
interaction().cutoffSq(iAtomType, jAtomType)) {
441 return interaction().forceOverR(rsq, iAtomType, jAtomType);
450 template <
class Interaction>
457 template <
class Interaction>
464 template <
class Interaction>
480 template <
class Interaction>
491 double localEnergy = 0.0;
493 localEnergy = energyList();
496 localEnergy = energyCell();
498 localEnergy = energyNSq();
508 template <
class Interaction>
520 iter.
getPair(atom0Ptr, atom1Ptr);
522 type0 = atom0Ptr->
typeId();
523 type1 = atom1Ptr->
typeId();
526 energy += interactionPtr_->energy(rsq, type0, type1);
530 iter.
getPair(atom0Ptr, atom1Ptr);
532 type0 = atom0Ptr->
typeId();
533 type1 = atom1Ptr->
typeId();
537 energy += interactionPtr_->energy(rsq, type0, type1);
539 energy += 0.5*interactionPtr_->energy(rsq, type0, type1);
549 template <
class Interaction>
562 iter.
getPair(atom0Ptr, atom1Ptr);
565 type0 = atom0Ptr->
typeId();
566 type1 = atom1Ptr->
typeId();
567 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
568 f *= interactionPtr_->forceOverR(rsq, type0, type1);
569 atom0Ptr->
force() += f;
570 atom1Ptr->
force() -= f;
576 #ifdef PAIR_BLOCK_SIZE 586 n = std::min(PAIR_BLOCK_SIZE, j);
589 for (i = 0; i < n; ++i) {
590 pairPtr = &pairs_[i];
591 iter.
getPair(atom0Ptr, atom1Ptr);
592 forcePtr = &(pairPtr->f);
594 pairPtr->ptr0 = atom0Ptr;
595 pairPtr->ptr1 = atom1Ptr;
596 pairPtr->rsq = forcePtr->
square();
603 for (i = 0; i < n; ++i) {
604 pairPtr = &pairs_[i];
605 atom0Ptr = pairPtr->ptr0;
606 atom1Ptr = pairPtr->ptr1;
607 type0 = atom0Ptr->
typeId();
608 type1 = atom1Ptr->
typeId();
609 inPairs_[m] = pairPtr;
610 if (pairPtr->rsq < interactionPtr_->cutoffSq(type0, type1)) {
616 for (i = 0; i < m; ++i) {
617 pairPtr = inPairs_[i];
618 atom0Ptr = pairPtr->ptr0;
619 atom1Ptr = pairPtr->ptr1;
620 forcePtr = &(pairPtr->f);
621 type0 = atom0Ptr->
typeId();
622 type1 = atom1Ptr->
typeId();
624 *forcePtr *= interactionPtr_->forceOverR(rsq, type0, type1);
625 atom0Ptr->
force() += *forcePtr;
627 atom1Ptr->
force() -= *forcePtr;
642 #endif // ifdef UTIL_DEBUG 644 #else // ifndef PAIR_BLOCK_SIZE 648 iter.
getPair(atom0Ptr, atom1Ptr);
651 type0 = atom0Ptr->
typeId();
652 type1 = atom1Ptr->
typeId();
653 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
654 f *= interactionPtr_->forceOverR(rsq, type0, type1);
655 atom0Ptr->
force() += f;
657 atom1Ptr->
force() -= f;
661 #endif // ifdef PAIR_BLOCK_SIZE 669 template <
class Interaction>
679 int type0, type1, na, nn, i, j;
685 na = cellPtr->
nAtom();
686 nn = neighbors.
size();
687 for (i = 0; i < na; ++i) {
688 atomPtr0 = neighbors[i]->ptr();
689 type0 = atomPtr0->
typeId();
692 for (j = 0; j < na; ++j) {
693 atomPtr1 = neighbors[j]->ptr();
694 type1 = atomPtr1->
typeId();
695 if (atomPtr1 > atomPtr0) {
698 energy += interactionPtr_->energy(rsq, type0, type1);
704 for (j = na; j < nn; ++j) {
705 atomPtr1 = neighbors[j]->ptr();
706 type1 = atomPtr1->
typeId();
709 energy += interactionPtr_->energy(rsq, type0, type1);
712 for (j = na; j < nn; ++j) {
713 atomPtr1 = neighbors[j]->ptr();
714 type1 = atomPtr1->
typeId();
718 energy += interactionPtr_->energy(rsq, type0, type1);
720 energy += 0.5*interactionPtr_->energy(rsq, type0, type1);
734 template <
class Interaction>
744 int type0, type1, na, nn, i, j;
750 na = cellPtr->
nAtom();
751 nn = neighbors.
size();
752 for (i = 0; i < na; ++i) {
753 atomPtr0 = neighbors[i]->ptr();
754 type0 = atomPtr0->
typeId();
756 for (j = 0; j < na; ++j) {
757 atomPtr1 = neighbors[j]->ptr();
758 type1 = atomPtr1->
typeId();
759 if (atomPtr1 > atomPtr0) {
762 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
763 f *= interactionPtr_->forceOverR(rsq, type0, type1);
764 atomPtr0->
force() += f;
765 atomPtr1->
force() -= f;
772 for (j = na; j < nn; ++j) {
773 atomPtr1 = neighbors[j]->ptr();
774 type1 = atomPtr1->
typeId();
777 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
778 f *= interactionPtr_->forceOverR(rsq, type0, type1);
779 atomPtr0->
force() += f;
780 atomPtr1->
force() -= f;
784 for (j = na; j < nn; ++j) {
785 atomPtr1 = neighbors[j]->ptr();
786 type1 = atomPtr1->
typeId();
789 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
790 f *= interactionPtr_->forceOverR(rsq, type0, type1);
791 atomPtr0->
force() += f;
793 atomPtr1->
force() -= f;
807 template <
class Interaction>
815 int id0, id1, type0, type1;
819 for ( ; atomIter0.
notEnd(); ++atomIter0) {
820 id0 = atomIter0->id();
821 type0 = atomIter0->typeId();
825 for ( ; atomIter1.
notEnd(); ++atomIter1) {
826 id1 = atomIter1->id();
828 if (!atomIter0->mask().isMasked(id1)) {
829 f.
subtract(atomIter0->position(), atomIter1->position());
831 type1 = atomIter1->typeId();
832 energy += interactionPtr_->energy(rsq, type0, type1);
840 for ( ; ghostIter.
notEnd(); ++ghostIter) {
841 id1 = ghostIter->id();
843 if (!atomIter0->mask().isMasked(id1)) {
844 f.
subtract(atomIter0->position(), ghostIter->position());
846 type1 = ghostIter->typeId();
847 energy += interactionPtr_->energy(rsq, type0, type1);
852 for ( ; ghostIter.
notEnd(); ++ghostIter) {
853 id1 = ghostIter->id();
854 if (!atomIter0->mask().isMasked(id1)) {
855 f.
subtract(atomIter0->position(), ghostIter->position());
857 type1 = ghostIter->typeId();
858 energy += 0.5*interactionPtr_->energy(rsq, type0, type1);
870 template <
class Interaction>
877 int type0, type1, id0, id1;
881 for ( ; atomIter0.
notEnd(); ++atomIter0) {
882 id0 = atomIter0->id();
883 type0 = atomIter0->typeId();
887 for ( ; atomIter1.
notEnd(); ++atomIter1) {
888 id1 = atomIter1->id();
890 if (!atomIter0->mask().isMasked(id1)) {
892 f.
subtract(atomIter0->position(), atomIter1->position());
894 type1 = atomIter1->typeId();
896 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
897 f *= interactionPtr_->forceOverR(rsq, type0, type1);
898 atomIter0->force() += f;
899 atomIter1->force() -= f;
909 for ( ; ghostIter.
notEnd(); ++ghostIter) {
910 id1 = ghostIter->id();
912 if (!atomIter0->mask().isMasked(id1)) {
914 f.
subtract(atomIter0->position(), ghostIter->position());
916 type1 = ghostIter->typeId();
918 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
919 f *= interactionPtr_->forceOverR(rsq, type0, type1);
920 atomIter0->force() += f;
921 ghostIter->force() -= f;
930 for ( ; ghostIter.
notEnd(); ++ghostIter) {
931 id1 = ghostIter->id();
932 if (!atomIter0->mask().isMasked(id1)) {
934 f.
subtract(atomIter0->position(), ghostIter->position());
936 type1 = ghostIter->typeId();
938 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
939 f *= interactionPtr_->forceOverR(rsq, type0, type1);
940 atomIter0->force() += f;
954 template <
class Interaction>
967 double rsq, forceOverR;
977 iter.
getPair(atom0Ptr, atom1Ptr);
980 type0 = atom0Ptr->
typeId();
981 type1 = atom1Ptr->
typeId();
982 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
984 f *= interactionPtr_->forceOverR(rsq, type0, type1);
992 iter.
getPair(atom0Ptr, atom1Ptr);
995 type0 = atom0Ptr->
typeId();
996 type1 = atom1Ptr->
typeId();
997 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
999 forceOverR = interactionPtr_->forceOverR(rsq, type0, type1);
1021 template <
class Interaction>
1047 iter.
getPair(atom0Ptr, atom1Ptr);
1050 type0 = atom0Ptr->
typeId();
1051 type1 = atom1Ptr->
typeId();
1052 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
1054 f *= interactionPtr_->forceOverR(rsq, type0, type1);
1056 atom0Ptr->
force() += f;
1057 atom1Ptr->
force() -= f;
1065 iter.
getPair(atom0Ptr, atom1Ptr);
1068 type0 = atom0Ptr->
typeId();
1069 type1 = atom1Ptr->
typeId();
1070 if (rsq < interactionPtr_->cutoffSq(type0, type1)) {
1072 f *= interactionPtr_->forceOverR(rsq, type0, type1);
1074 atom0Ptr->
force() += f;
1076 atom1Ptr->
force() -= f;
1096 template <
class Interaction>
1111 localPairEnergies.
allocate(nAtomType_, nAtomType_);
1112 for (
int i = 0; i < nAtomType_; ++i) {
1113 for (
int j = 0; j < nAtomType_; ++j) {
1114 localPairEnergies(i,j) = 0.0;
1121 iter.
getPair(atom0Ptr, atom1Ptr);
1123 type0 = atom0Ptr->
typeId();
1124 type1 = atom1Ptr->
typeId();
1127 localPairEnergies(type0, type1) += interactionPtr_->energy(rsq, type0, type1);
1131 iter.
getPair(atom0Ptr, atom1Ptr);
1133 type0 = atom0Ptr->
typeId();
1134 type1 = atom1Ptr->
typeId();
1138 localPairEnergies(type0, type1) += interactionPtr_->energy(rsq, type0, type1);
1140 localPairEnergies(type0, type1) += 0.5*interactionPtr_->energy(rsq, type0, type1);
1146 totalPairEnergies.
allocate(nAtomType_, nAtomType_);
1147 for (
int i = 0; i < nAtomType_; ++i) {
1148 for (
int j = 0; j < nAtomType_; ++j) {
1149 totalPairEnergies(i,j) = 0.0;
1154 communicator.Reduce(&localPairEnergies(0,0), &totalPairEnergies(0,0), nAtomType_*nAtomType_,
1155 MPI::DOUBLE, MPI::SUM, 0);
1156 if (communicator.Get_rank() == 0) {
const Cell * begin() const
Return pointer to first local cell in linked list.
Boundary & boundary()
Get the PairList by const reference.
int typeId() const
Get atom type index.
A Vector is a Cartesian vector.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
virtual void computeEnergy(MPI::Intracomm &communicator)
Compute the total nonBonded pair energy for all processors.
virtual void computePairEnergies(MPI::Intracomm &communicator)
Compute total pair energies for all processors Compute nonbonded forces and sress for all processors...
int nPair() const
Get the number of pairs in the PairList.
bool isStressSet() const
Is the stress set (known)?
void reduceStress(Tensor &localStress, MPI::Intracomm &communicator)
Add local stresses from all processors, set total on master.
double volume() const
Return unit cell volume.
Vector & position()
Get position Vector by reference.
PairPotentialImpl()
Default constructor (for unit testing).
Tensor & zero()
Set all elements of this tensor to zero.
void getPair(Atom *&atom1Ptr, Atom *&atom2Ptr) const
Get pointers for current pair of Atoms.
File containing preprocessor macros for error handling.
void begin(PairIterator &iterator) const
Initialize a PairIterator.
A point particle in an MD simulation.
Parallel domain decomposition (DD) MD simulation.
Main object for a domain-decomposition MD simulation.
A Tensor represents a Cartesian tensor.
virtual void computeStress(MPI::Intracomm &communicator)
Compute the total nonBonded stress for all processors.
virtual void setNAtomType(int nAtomType)
Set the maximum number of atom types.
void setPairEnergies(DMatrix< double > pairEnergies)
Set values for pair energies.
Saving / output archive for binary ostream.
bool notEnd() const
Return true if not at end of PairList.
int methodId() const
Return integer id for algorithm (0=PAIR, 1=CELL, 2=NSQ)
A fixed capacity (static) contiguous array with a variable logical size.
CellList cellList_
CellList to construct PairList or calculate nonbonded pair forces.
void unsetPairEnergies()
Mark pair energy as unknown (nullify).
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
bool isGhost() const
Is this atom a ghost?
Interaction & interaction()
Return underlying pair interaction object by reference.
int nAtom() const
Number of atoms in cell.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
virtual double pairEnergy(double rsq, int iAtomType, int jAtomType) const
Return energy for a single pair.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
const Interaction & interaction() const
Return underlying pair interaction object by const reference.
virtual void save(Serializable::OArchive &ar)
Save internal state to an output archive.
virtual double maxPairCutoff() const
Return maximum cutoff.
virtual void computeForcesAndStress(MPI::Intracomm &communicator)
Compute nonbonded forces and sress for all processors.
void incrementPairStress(const Vector &f, const Vector &dr, Tensor &stress) const
Add a pair contribution to the stress tensor.
bool reverseUpdateFlag() const
Get flag to identify if reverse communication is enabled.
PairList pairList_
Verlet pair list, to calculate nonbonded pair forces.
virtual double pairForceOverR(double rsq, int iAtomType, int jAtomType) const
Return force / separation for a single pair.
double energy() const
Return the total potential, from all processors.
Saving archive for binary istream.
Vector & force()
Get force Vector by reference.
void getNeighbors(NeighborArray &neighbors, bool reverseUpdateFlag=false) const
Fill an array with pointers to atoms in a cell and neighboring cells.
AtomStorage & storage()
Get the AtomStorage by reference.
Iterator for all ghost atoms owned by an AtomStorage.
void addParamComposite(ParamComposite &child, bool next=true)
Add a child ParamComposite object to the format array.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
void reduceEnergy(double localEnergy, MPI::Intracomm &communicator)
Add local energies from all processors, set energy on master.
Vector & subtract(const Vector &v1, const Vector &v2)
Subtract vector v2 from v1.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
virtual void loadParameters(Serializable::IArchive &ar)
Load parameters for PairList from archive, and allocate memory.
int nAtomType()
Get maximum number of atom types.
void readParameters(std::istream &in)
Initialize, by reading parameters and allocating memory for PairList.
Implementation template for a PairPotential.
virtual void computeForces()
Compute non-bonded pair forces for all atoms in this Simulation.
Iterator for pairs in a PairList.
Iterator for all atoms owned by an AtomStorage.
int size() const
Return logical size of this array (i.e., number of elements).
virtual std::string interactionClassName() const
Return pair interaction class name (e.g., "LJPair").
double square() const
Return square magnitude of this vector.
void begin(AtomIterator &iterator)
Set iterator to beginning of the set of atoms.
Abstract base class for computing nonbonded pair forces and energies.
const Cell * nextCellPtr() const
Return a pointer to neighbor cell i.
virtual void readParameters(std::istream &in)
Read pair potential interaction and pair list blocks.
bool isEnergySet() const
Is the energy set (known)?
virtual ~PairPotentialImpl()
Destructor.
A single Cell in a CellList.