diff --git a/src/multicolvar/ActionVolume.cpp b/src/multicolvar/ActionVolume.cpp index 7d12425aca7aec1f50db829f193afa2643f0be14..05e26304afbe6175d6998740e5348a5bf5cfea73 100644 --- a/src/multicolvar/ActionVolume.cpp +++ b/src/multicolvar/ActionVolume.cpp @@ -86,18 +86,20 @@ bool ActionVolume::performTask( const unsigned& j ){ Vector catom_pos=mycolv->retrieveCentralAtomPos( derivativesOfFractionalCoordinates() ); - double weight; Vector wdf; + double weight; Vector wdf; weight=calculateNumberInside( catom_pos, bead, wdf ); if( not_in ){ weight = 1.0 - weight; wdf *= -1.; } if( mycolv->isDensity() ){ - setElementValue( 0, weight ); setElementValue( 1, 1.0 ); + setElementValue( 0, weight ); setElementValue( 1, 1.0 ); for(unsigned i=0;i<mycolv->getNAtoms();++i){ - addElementDerivative( mycolv->getOutputDerivativeIndex(mycolv->current,3*i+0), mycolv->getCentralAtomDerivative(i, 0, wdf ) ); - addElementDerivative( mycolv->getOutputDerivativeIndex(mycolv->current,3*i+1), mycolv->getCentralAtomDerivative(i, 1, wdf ) ); - addElementDerivative( mycolv->getOutputDerivativeIndex(mycolv->current,3*i+2), mycolv->getCentralAtomDerivative(i, 2, wdf ) ); + unsigned nx=3*linkIndex( i, mycolv->colvar_atoms[mycolv->current], mycolv->all_atoms ); + addElementDerivative( nx+0, mycolv->getCentralAtomDerivative(i, 0, wdf ) ); + addElementDerivative( nx+1, mycolv->getCentralAtomDerivative(i, 1, wdf ) ); + addElementDerivative( nx+2, mycolv->getCentralAtomDerivative(i, 2, wdf ) ); } } else { + // Copy derivatives of the colvar and the value of the colvar double colv=mycolv->getElementValue(0); setElementValue( 0, colv ); for(unsigned i=0;i<mycolv->nderivatives;++i){ addElementDerivative( mycolv->getOutputDerivativeIndex(mycolv->current,i), mycolv->getElementDerivative(i) ); @@ -106,13 +108,20 @@ bool ActionVolume::performTask( const unsigned& j ){ double ww=mycolv->getElementValue(1); setElementValue( 1, ww*weight ); - for(unsigned i=0;i<mycolv->getNAtoms();++i){ - addElementDerivative( nderivatives+mycolv->getOutputDerivativeIndex(mycolv->current,3*i+0), - ww*mycolv->getCentralAtomDerivative(i, 0, wdf ) + weight*mycolv->getElementDerivative(nderivatives+3*i+0) ); - addElementDerivative( nderivatives+mycolv->getOutputDerivativeIndex(mycolv->current,3*i+1), - ww*mycolv->getCentralAtomDerivative(i, 1, wdf ) + weight*mycolv->getElementDerivative(nderivatives+3*i+1) ); - addElementDerivative( nderivatives+mycolv->getOutputDerivativeIndex(mycolv->current,3*i+2), - ww*mycolv->getCentralAtomDerivative(i, 2, wdf ) + weight*mycolv->getElementDerivative(nderivatives+3*i+2) ); + // Add derivatives of weight if we have a weight + if( mycolv->weightHasDerivatives ){ + for(unsigned i=0;i<mycolv->nderivatives;++i){ + addElementDerivative( nderivatives+mycolv->getOutputDerivativeIndex(mycolv->current,i), weight*mycolv->getElementDerivative(nderivatives+i) ); + } + } + + // Add derivatives of central atoms + for(unsigned i=0;i<mycolv->atomsWithCatomDer.getNumberActive();++i){ + unsigned n=mycolv->atomsWithCatomDer[i]; + unsigned nx=nderivatives+3*linkIndex( n, mycolv->colvar_atoms[mycolv->current], mycolv->all_atoms); + addElementDerivative( nx+0, ww*mycolv->getCentralAtomDerivative(i, 0, wdf ) ); + addElementDerivative( nx+1, ww*mycolv->getCentralAtomDerivative(i, 1, wdf ) ); + addElementDerivative( nx+2, ww*mycolv->getCentralAtomDerivative(i, 2, wdf ) ); } } diff --git a/src/multicolvar/MultiColvar.cpp b/src/multicolvar/MultiColvar.cpp index 0a22d60375570501d638c1d9f6f94bf6b8b3a1b2..b73be9095ecd920b19dc98f0dd6578ca04646f3b 100644 --- a/src/multicolvar/MultiColvar.cpp +++ b/src/multicolvar/MultiColvar.cpp @@ -103,7 +103,11 @@ void MultiColvar::readAtoms( int& natoms ){ all_atoms.activateAll(); colvar_list.activateAll(); for(unsigned i=0;i<colvar_atoms.size();++i) colvar_atoms[i].activateAll(); ActionAtomistic::requestAtoms( all_atoms.retrieveActiveList() ); - central_derivs.resize( getNumberOfAtoms() ); + // Set up stuff for central atoms + for(unsigned i=0;i<colvar_atoms[0].fullSize();++i) atomsWithCatomDer.addIndexToList( i ); + atomsWithCatomDer.deactivateAll(); + central_derivs.resize( colvar_atoms[0].fullSize() ); + for(unsigned i=0;i<central_derivs.size();++i) central_derivs[i].zero(); } void MultiColvar::readBackboneAtoms( const std::vector<std::string>& backnames, std::vector<unsigned>& chain_lengths ){ @@ -339,7 +343,7 @@ void MultiColvar::prepare(){ } if(updatetime){ for(unsigned i=0;i<colvar_list.getNumberActive();++i) activateLinks( colvar_atoms[i], all_atoms ); - all_atoms.updateActiveMembers(); central_derivs.resize( getNumberOfAtoms() ); + all_atoms.updateActiveMembers(); ActionAtomistic::requestAtoms( all_atoms.retrieveActiveList() ); resizeFunctions(); } } @@ -391,13 +395,24 @@ bool MultiColvar::performTask( const unsigned& j ){ Vector MultiColvar::retrieveCentralAtomPos( const bool& frac ){ centralAtomDerivativesAreInFractional=frac; ibox=getPbc().getInvBox().transpose(); - for(unsigned i=0;i<central_derivs.size();++i) central_derivs[i].zero(); - if(frac) return getPbc().realToScaled( getCentralAtom() ); - return getCentralAtom(); + + // Prepare to retrieve central atom + for(unsigned i=0;i<atomsWithCatomDer.getNumberActive();++i) central_derivs[ atomsWithCatomDer[i] ].zero(); + atomsWithCatomDer.deactivateAll(); + + // Retrieve the central atom position + Vector catom_pos; + if(frac) catom_pos=getPbc().realToScaled( getCentralAtom() ); + else catom_pos=getCentralAtom(); + + // Complete the update of the active member list + atomsWithCatomDer.updateActiveMembers(); + return catom_pos; } void MultiColvar::addCentralAtomDerivatives( const unsigned& iatom, const Tensor& der ){ plumed_dbg_assert( iatom<colvar_atoms[current].getNumberActive() ); + atomsWithCatomDer.activate(iatom); if( centralAtomDerivativesAreInFractional ) central_derivs[iatom] += matmul( ibox, der ); else central_derivs[iatom] += der; } @@ -474,6 +489,21 @@ void MultiColvar::apply(){ } } +void MultiColvar::buildDerivativeIndexArrays( std::vector< DynamicList<unsigned> >& active_der ) const { + active_der.resize( colvar_atoms.size() ); + for(unsigned i=0;i<colvar_atoms.size();++i){ + for(unsigned j=0;j<colvar_atoms[i].fullSize();++j){ + active_der[i].addIndexToList( 3*colvar_atoms[i][j] + 0 ); + active_der[i].addIndexToList( 3*colvar_atoms[i][j] + 1 ); + active_der[i].addIndexToList( 3*colvar_atoms[i][j] + 2 ); + } + unsigned virs=3*getNumberOfAtoms(); + for(unsigned j=0;j<9;++j){ + active_der[i].addIndexToList( virs ); virs++; + } + } +} + StoreCentralAtomsVessel* MultiColvar::getCentralAtoms(){ // Look to see if vectors have already been created StoreCentralAtomsVessel* mycatoms; @@ -488,6 +518,6 @@ StoreCentralAtomsVessel* MultiColvar::getCentralAtoms(){ addVessel(sv); resizeFunctions(); // This makes sure resizing of vessels is done return sv; } - + } } diff --git a/src/multicolvar/MultiColvar.h b/src/multicolvar/MultiColvar.h index 9a67ef7caddbea7e8ed78542b8867dd0b4db28ef..1c3b04e31f3f9ab78ab21682a4335f0ad26dcbad 100644 --- a/src/multicolvar/MultiColvar.h +++ b/src/multicolvar/MultiColvar.h @@ -70,6 +70,7 @@ private: std::vector<Vector> pos; Tensor ibox; bool centralAtomDerivativesAreInFractional; + DynamicList<unsigned> atomsWithCatomDer; std::vector<Tensor> central_derivs; /// Read in the various GROUP keywords void readGroupsKeyword( int& natoms ); @@ -88,6 +89,8 @@ protected: void readBackboneAtoms( const std::vector<std::string>& backnames, std::vector<unsigned>& chain_lengths ); /// Add a colvar to the set of colvars we are calculating (in practise just a list of atoms) void addColvar( const std::vector<unsigned>& newatoms ); +/// Build lists of indexes of the derivatives from the colvar atoms arrays + void buildDerivativeIndexArrays( std::vector< DynamicList<unsigned> >& active_der ) const ; /// Get the separation between a pair of vectors Vector getSeparation( const Vector& vec1, const Vector& vec2 ) const ; /// Find out if it is time to do neighbor list update diff --git a/src/multicolvar/StoreCentralAtomsVessel.cpp b/src/multicolvar/StoreCentralAtomsVessel.cpp index 0581240e187cc9429efae31b5fe1998700c4c7d1..631974c5f8509d6b48b8b4e8817dc401025374b7 100644 --- a/src/multicolvar/StoreCentralAtomsVessel.cpp +++ b/src/multicolvar/StoreCentralAtomsVessel.cpp @@ -33,6 +33,8 @@ wasforced(false) { mycolv=dynamic_cast<MultiColvar*>( getAction() ); plumed_assert( mycolv ); + + mycolv->buildDerivativeIndexArrays( active_der ); } void StoreCentralAtomsVessel::resize(){ @@ -40,7 +42,7 @@ void StoreCentralAtomsVessel::resize(){ unsigned bsize=0; start.resize( nfunc +1 ); for(unsigned i=0;i<nfunc;++i){ start[i] = bsize; - bsize += 3*( 1 + 3*mycolv->colvar_atoms[i].getNumberActive() ); + bsize += 3*( 1 + mycolv->getNumberOfDerivatives() ); } start[nfunc]=bsize; resizeBuffer( bsize ); @@ -55,25 +57,36 @@ void StoreCentralAtomsVessel::prepare(){ bool StoreCentralAtomsVessel::calculate(){ Vector catom_pos=mycolv->retrieveCentralAtomPos( false ); - unsigned ibuf=start[mycolv->current]; - for(unsigned i=0;i<3;++i){ - addToBufferElement( ibuf, catom_pos[i] ); ibuf++; - for(unsigned j=0;j<mycolv->getNAtoms();++j){ - for(unsigned k=0;k<3;++k){ - addToBufferElement( ibuf, mycolv->central_derivs[j](i,k) ); ibuf++; - } + // Store the value + unsigned ibuf=start[mycolv->current], nspace = 1 + mycolv->getNumberOfDerivatives(); + for(unsigned i=0;i<3;++i){ addToBufferElement( ibuf, catom_pos[i] ); ibuf+=nspace; } + plumed_dbg_assert( ibuf==start[mycolv->current+1] ); + + // Store the derivatives + active_der[mycolv->current].deactivateAll(); + for(unsigned j=0;j<mycolv->atomsWithCatomDer.getNumberActive();++j){ + unsigned n=mycolv->atomsWithCatomDer[j]; + ibuf = start[mycolv->current] + 1 + 3*mycolv->colvar_atoms[mycolv->current][n]; + for(unsigned i=0;i<3;++i){ + active_der[mycolv->current].activate(3*n+i); + for(unsigned k=0;k<3;++k) addToBufferElement( ibuf+k, mycolv->central_derivs[n](i,k) ); + ibuf += nspace; } } - plumed_dbg_assert( ibuf==start[mycolv->current+1] ); + return true; } +void StoreCentralAtomsVessel::finish(){ + mpi_gatherActiveMembers( comm, active_der ); +} + Vector StoreCentralAtomsVessel::getPosition( const unsigned& ivec ) const { plumed_dbg_assert( ivec<mycolv->getNumberOfFunctionsInAction() ); unsigned pos=start[ivec]; Vector mypos; for(unsigned i=0;i<3;++i){ mypos[i] = getBufferElement( pos ); - pos+=3*mycolv->colvar_atoms[ivec].getNumberActive()+1; + pos+=mycolv->getNumberOfDerivatives() + 1; } plumed_dbg_assert( pos==start[ivec+1] ); return mypos; @@ -96,21 +109,17 @@ bool StoreCentralAtomsVessel::applyForce(std::vector<double>& ff){ void StoreCentralAtomsVessel::chainRuleForCentralAtom( const unsigned& iatom, const unsigned& iderno, const Vector& df, vesselbase::ActionWithVessel* act) const { plumed_dbg_assert( iatom<mycolv->getNumberOfFunctionsInAction() ); - unsigned nder=3*mycolv->colvar_atoms[iatom].getNumberActive(); - unsigned nder2=mycolv->getNumberOfDerivatives(); - for(unsigned ider=0;ider<nder;++ider){ - unsigned ibuf=start[iatom] + 1 + ider; double thisder=0.0; + unsigned nder=mycolv->getNumberOfDerivatives(); + for(unsigned ider=0;ider<active_der[iatom].getNumberActive();++ider){ + unsigned ibuf=start[iatom] + 1 + active_der[iatom][ider]; double thisder=0.0; for(unsigned jcomp=0;jcomp<3;++jcomp){ thisder+=df[jcomp]*getBufferElement(ibuf); ibuf+=(nder+1); - //unsigned ibuf=start[iatom] + jcomp*(nder+1) + 1 + ider; - //act->addElementDerivative( jder, df[jcomp]*getBufferElement(ibuf) ); } - unsigned jder = iderno*nder2 + mycolv->getOutputDerivativeIndex( iatom, ider ); + unsigned jder = iderno*nder + active_der[iatom][ider]; act->addElementDerivative( jder, thisder ); } } - } } diff --git a/src/multicolvar/StoreCentralAtomsVessel.h b/src/multicolvar/StoreCentralAtomsVessel.h index c7651b913d0d3d6ec15c4523f73b19c75158efbb..3ddc32d2b83ad400f9c5997bffd302327a9ce88f 100644 --- a/src/multicolvar/StoreCentralAtomsVessel.h +++ b/src/multicolvar/StoreCentralAtomsVessel.h @@ -22,6 +22,7 @@ #ifndef __PLUMED_multicolvar_StoreCentralAtomsVessel_h #define __PLUMED_multicolvar_StoreCentralAtomsVessel_h +#include "tools/DynamicList.h" #include "vesselbase/Vessel.h" #include "MultiColvar.h" @@ -35,6 +36,7 @@ private: MultiColvar* mycolv; std::vector<unsigned> start; bool wasforced; + std::vector< DynamicList<unsigned> > active_der; std::vector<double> forces; public: /// Constructor @@ -45,8 +47,8 @@ public: void resize(); /// This does nothing std::string description(){ return ""; } -/// This does nothing - void finish(){} +/// This should mpi gather the active atoms + void finish(); /// Add some force to the atoms void addForces( const std::vector<double>& ); /// Copy forces to local arrays diff --git a/src/tools/DynamicList.h b/src/tools/DynamicList.h index a6b674446cc233da963319b67e11b54207308822..a31ddc406ca5f8e47e37c62410d52d24bb16f295 100644 --- a/src/tools/DynamicList.h +++ b/src/tools/DynamicList.h @@ -134,21 +134,22 @@ friend void activateLinks( const DynamicList<unsigned>& , DynamicList<U>& ); template <typename U> friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList<U> >& ); private: - bool inactive; /// This is the list of all the relevent members std::vector<T> all; /// This tells us what members of all are on/off at any given time std::vector<unsigned> onoff; /// This translates a position from all to active std::vector<int> translator; +/// The current number of active members + unsigned nactive; /// This is the list of active members std::vector<T> active; public: /// Constructor - DynamicList():inactive(true){} + DynamicList():nactive(0){} /// An operator that returns the element from the current active list inline T operator [] (const unsigned& i) const { - plumed_dbg_assert(!inactive); plumed_dbg_assert( i<active.size() ); + plumed_dbg_assert( i<nactive ); return active[i]; } /// An operator that returns the element from the full list (used in neighbour lists) @@ -156,7 +157,6 @@ public: plumed_dbg_assert( i<all.size() ); return all[i]; } - inline bool get_inactive() const { return inactive; } /// Clear the list void clear(); /// Return the total number of elements in the list @@ -178,17 +178,20 @@ public: /// Get the list of active members void updateActiveMembers(); /// Retriee the list of active objects - std::vector<T>& retrieveActiveList(); + std::vector<T> retrieveActiveList(); }; template <typename T> -std::vector<T>& DynamicList<T>::retrieveActiveList(){ - return active; +std::vector<T> DynamicList<T>::retrieveActiveList(){ + std::vector<T> this_active(nactive); + for(unsigned k=0;k<nactive;++k) this_active[k]=active[k]; + return this_active; } template <typename T> void DynamicList<T>::clear() { - all.resize(0); translator.resize(0); onoff.resize(0); active.resize(0); + all.resize(0); translator.resize(0); + onoff.resize(0); active.resize(0); } template <typename T> @@ -198,39 +201,34 @@ unsigned DynamicList<T>::fullSize() const { template <typename T> unsigned DynamicList<T>::getNumberActive() const { - plumed_dbg_assert( !inactive || active.size()==0 ); - return active.size(); + return nactive; } template <typename T> void DynamicList<T>::addIndexToList( const T & ii ){ - all.push_back(ii); translator.push_back( all.size()-1 ); onoff.push_back(0); + all.push_back(ii); translator.push_back( all.size()-1 ); + onoff.push_back(0); active.push_back(ii); } template <typename T> void DynamicList<T>::deactivate( const unsigned ii ){ plumed_massert(ii<all.size(),"ii is out of bounds"); - onoff[ii]=0; inactive=true; - for(unsigned i=0;i<onoff.size();++i){ - if(onoff[i]>0){ inactive=false; break; } - } + onoff[ii]=0; } template <typename T> void DynamicList<T>::deactivateAll(){ - inactive=true; for(unsigned i=0;i<onoff.size();++i) onoff[i]=0; } template <typename T> void DynamicList<T>::activate( const unsigned ii ){ plumed_massert(ii<all.size(),"ii is out of bounds"); - inactive=false; onoff[ii]=1; + onoff[ii]=1; } template <typename T> void DynamicList<T>::activateAll(){ - inactive=false; for(unsigned i=0;i<onoff.size();++i) onoff[i]=1; updateActiveMembers(); } @@ -246,17 +244,16 @@ void DynamicList<T>::mpi_gatherActiveMembers(Communicator& comm){ template <typename T> void DynamicList<T>::updateActiveMembers(){ - unsigned kk=0; active.resize(0); + unsigned kk=0; for(unsigned i=0;i<all.size();++i){ - if( onoff[i]==1 ){ translator[i]=kk; active.push_back( all[i] ); kk++; } + if( onoff[i]==1 ){ translator[i]=kk; active[kk]=all[i]; kk++; } } - plumed_assert( kk==active.size() ); - if( kk==0 ) inactive=true; + nactive=kk; } template <typename U> unsigned linkIndex( const unsigned ii, const DynamicList<unsigned>& l1, const DynamicList<U>& l2 ){ - plumed_dbg_massert(ii<l1.active.size(),"ii is out of bounds"); + plumed_dbg_massert(ii<l1.nactive,"ii is out of bounds"); unsigned kk; kk=l1.active[ii]; plumed_dbg_massert(kk<l2.all.size(),"the lists are mismatched"); plumed_dbg_massert( l2.onoff[kk]==1, "This index is not currently in the second list" ); @@ -266,7 +263,7 @@ unsigned linkIndex( const unsigned ii, const DynamicList<unsigned>& l1, const Dy template <typename U> void activateLinks( const DynamicList<unsigned>& l1, DynamicList<U>& l2 ){ - for(unsigned i=0;i<l1.active.size();++i) l2.activate( l1.active[i] ); + for(unsigned i=0;i<l1.nactive;++i) l2.activate( l1.active[i] ); } template <typename U> diff --git a/src/vesselbase/Vessel.cpp b/src/vesselbase/Vessel.cpp index ce4265ee935253326e3c8d43a7bd06f0920a4e76..085464154d4e2e62066e0bf724d72de665306b7e 100644 --- a/src/vesselbase/Vessel.cpp +++ b/src/vesselbase/Vessel.cpp @@ -58,8 +58,8 @@ Vessel::Vessel( const VesselOptions& da ): myname(da.myname), numlab(da.numlab), action(da.action), -comm(da.action->comm), keywords(da.keywords), +comm(da.action->comm), finished_read(false), log((da.action)->log) { diff --git a/src/vesselbase/Vessel.h b/src/vesselbase/Vessel.h index 1f1689983cae0b8bf6127effe4582754ad44f9eb..3902ae68896ca4dd01ef74fb6640c5a1fb400ed0 100644 --- a/src/vesselbase/Vessel.h +++ b/src/vesselbase/Vessel.h @@ -85,8 +85,6 @@ private: const int numlab; /// The action that this vessel is created within ActionWithVessel* action; -/// A copy of the communicator - Communicator& comm; /// Something to store the buffer if this is required std::vector<double> stash; /// The start of this Vessel's buffer in buffer in the underlying ActionWithVessel @@ -102,6 +100,8 @@ private: /// This just checks we have done checkRead bool finished_read; protected: +/// A copy of the communicator + Communicator& comm; /// Return the numerical label int getNumericalLabel() const ; /// Report an error