diff --git a/src/analysis/AnalysisWithLandmarks.cpp b/src/analysis/AnalysisWithLandmarks.cpp index 9d158790d7a917747c0128e5b5b232fcd779590c..32df489ef81ee3acbd4677d0629e7c01bb6f91be 100644 --- a/src/analysis/AnalysisWithLandmarks.cpp +++ b/src/analysis/AnalysisWithLandmarks.cpp @@ -71,7 +71,7 @@ void AnalysisWithLandmarks::performAnalysis(){ analyzeLandmarks(); } -void AnalysisWithLandmarks::performTask(){ +void AnalysisWithLandmarks::performTask( const unsigned& taskIndex, const unsigned& current, vesselbase::MultiValue& myvals ){ plumed_merror("Should not be here"); } diff --git a/src/analysis/AnalysisWithLandmarks.h b/src/analysis/AnalysisWithLandmarks.h index 011998f70258b30431f5729000ac69b02580ba8b..bd9842ddd8e5ad488ee684671b545284440a3acc 100644 --- a/src/analysis/AnalysisWithLandmarks.h +++ b/src/analysis/AnalysisWithLandmarks.h @@ -53,7 +53,7 @@ public: void performAnalysis(); virtual void analyzeLandmarks()=0; /// This does nothing - void performTask(); + void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ); }; } diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp index 59f25dafd783f5c10e9daffe9c4f4c6193e8c230..a6fb5ff3ccaaa9bcc5ef9dc095276b947bbe9135 100644 --- a/src/analysis/Histogram.cpp +++ b/src/analysis/Histogram.cpp @@ -124,7 +124,7 @@ public: static void registerKeywords( Keywords& keys ); Histogram(const ActionOptions&ao); void performAnalysis(); - void performTask(); + void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ); }; PLUMED_REGISTER_ACTION(Histogram,"HISTOGRAM") @@ -212,7 +212,7 @@ unnormalized(false) log.printf("\n"); } -void Histogram::performTask(){ plumed_error(); } +void Histogram::performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ){ plumed_error(); } void Histogram::performAnalysis(){ // Back up old histogram files diff --git a/src/crystallization/DFSClustering.cpp b/src/crystallization/DFSClustering.cpp index 193cf84c19aa77cd7a3147a188e4bf19cfba19d1..26f5e7aa105d7f91c6f6dc818e0e79efd5acf5c0 100644 --- a/src/crystallization/DFSClustering.cpp +++ b/src/crystallization/DFSClustering.cpp @@ -41,8 +41,6 @@ private: unsigned clustr; /// Used to identify the cluster we are working on int number_of_cluster; -/// The values from the underlying colvar - std::vector<double> myvals; /// The number of neighbors each atom has std::vector<unsigned> nneigh; /// The adjacency list @@ -68,7 +66,7 @@ public: void completeCalculation(); /// Derivatives of elements of adjacency matrix are unimportant. We thus /// overwrite this routine as this makes the code faster - void updateActiveAtoms(){} + void updateActiveAtoms( multicolvar::AtomValuePack& myatoms ){} }; PLUMED_REGISTER_ACTION(DFSClustering,"DFSCLUSTERING") @@ -100,8 +98,6 @@ color(getFullNumberOfBaseTasks()) if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); if( clustr>getFullNumberOfBaseTasks() ) error("cluster selected is invalid - too few atoms in system"); - // Set myvals size equal to number of components in vector + 1 (for norm) - myvals.resize( getBaseMultiColvar(0)->getNumberOfQuantities() - 4 ); // Setup the various things this will calculate readVesselKeywords(); } @@ -150,31 +146,25 @@ void DFSClustering::completeCalculation(){ } unsigned size=comm.Get_size(), rank=comm.Get_rank(); -// for(unsigned i=0;i<cluster_sizes.size();++i) printf("HELLO CLUSTER %d %d \n",i,cluster_sizes[i].first ); // Now calculate properties of the largest cluster ActionWithVessel::doJobsRequiredBeforeTaskList(); // Note we loose adjacency data by doing this // Get size for buffer unsigned bsize=0; std::vector<double> buffer( getSizeOfBuffer( bsize ), 0.0 ); + std::vector<double> vals( getNumberOfQuantities() ); + vesselbase::MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + vesselbase::MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); // Get rid of bogus derivatives clearDerivatives(); getAdjacencyVessel()->setFinishedTrue(); for(unsigned j=rank;j<myatoms.size();j+=size){ // Note loop above over array containing atoms so this is load balanced unsigned i=myatoms[j]; // Need to copy values from base action - extractValueForBaseTask( i, myvals ); - // getValueForBaseTask( i, myvals ); - setElementValue(0, myvals[0] ); setElementValue(1, 1.0 ); - for(unsigned i=0;i<myvals.size()-1;++i) setElementValue(2+i, myvals[1+i] ); - // Prepare dynamic lists - atoms_with_derivatives.deactivateAll(); - // Copy derivatives from base action - extractWeightedAverageAndDerivatives( i, 1.0 ); - // Update all dynamic lists - atoms_with_derivatives.updateActiveMembers(); + getVectorForTask( i, false, vals ); + for(unsigned i=0;i<vals.size();++i) myvals.setValue( i, vals[i] ); + if( !doNotCalculateDerivatives() ) getVectorDerivatives( i, false, myvals ); // Run calculate all vessels - calculateAllVessels( buffer ); - // Must clear element values and derivatives - clearAfterTask(); + calculateAllVessels( i, myvals, bvals, buffer ); + myvals.clearAll(); } // MPI Gather everything if( buffer.size()>0 ) comm.Sum( buffer ); diff --git a/src/crystallization/Fccubic.cpp b/src/crystallization/Fccubic.cpp index b3e569e8c5c8ff58575315f8468c771e8cb10919..a7d40a05e8743a93c805826e00e97f8b6f59c116 100644 --- a/src/crystallization/Fccubic.cpp +++ b/src/crystallization/Fccubic.cpp @@ -47,8 +47,7 @@ public: static void registerKeywords( Keywords& keys ); Fccubic(const ActionOptions&); // active methods: - virtual double compute(); - Vector getCentralAtom(); + virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } }; @@ -96,15 +95,14 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double Fccubic::compute(){ - weightHasDerivatives=true; +double Fccubic::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){ double value=0, norm=0, dfunc; Vector distance; // Calculate the coordination number Vector myder, fder; double sw, t0, t1, t2, t3, x2, x4, y2, y4, z2, z4, r8, tmp; - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPosition(0), getPosition(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); double d2 = distance.modulo2(); if( d2<rcut2 ){ sw = switchingFunction.calculateSqr( d2, dfunc ); @@ -137,29 +135,24 @@ double Fccubic::compute(){ fder = (+dfunc)*tmp*distance + sw*myder; - addAtomsDerivatives( 0, -fder ); - addAtomsDerivatives( i, +fder ); - addBoxDerivatives( Tensor(distance,-fder) ); - addAtomsDerivativeOfWeight( 0, (-dfunc)*distance ); - addAtomsDerivativeOfWeight( i, (+dfunc)*distance ); - addBoxDerivativesOfWeight( (-dfunc)*Tensor(distance,distance) ); + myatoms.addAtomsDerivatives( 1, 0, -fder ); + myatoms.addAtomsDerivatives( 1, i, +fder ); + myatoms.addBoxDerivatives( 1, Tensor(distance,-fder) ); + myatoms.addAtomsDerivatives( 0, 0, (-dfunc)*distance ); + myatoms.addAtomsDerivatives( 0, i, (+dfunc)*distance ); + myatoms.addBoxDerivatives( 0, (-dfunc)*Tensor(distance,distance) ); } } - setElementValue(0, value); setElementValue(1, norm ); + myatoms.setValue(1, value); myatoms.setValue(0, norm ); // values -> der of... value [0], weight[1], x coord [2], y, z... [more magic] - updateActiveAtoms(); quotientRule( 0, 1, 0 ); clearDerivativesAfterTask(1); + updateActiveAtoms( myatoms ); myatoms.getUnderlyingMultiValue().quotientRule( 1, 0, 1 ); // Weight doesn't really have derivatives (just use the holder for convenience) - weightHasDerivatives=false; setElementValue( 1, 1.0 ); + myatoms.getUnderlyingMultiValue().clear(0); myatoms.setValue( 0, 1.0 ); return value / norm; // this is equivalent to getting an "atomic" CV } -Vector Fccubic::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - } } diff --git a/src/crystallization/Gradient.cpp b/src/crystallization/Gradient.cpp index a33b937252fae17267281ec45585039f9ec45965..498664c3ab45b829d6e16eef27a02bbbde4db79f 100644 --- a/src/crystallization/Gradient.cpp +++ b/src/crystallization/Gradient.cpp @@ -79,9 +79,9 @@ nbins(3) } // Find number of quantities - if( getPntrToMultiColvar()->isDensity() ) vend=1; - else if( getPntrToMultiColvar()->getNumberOfQuantities()==5 ) vend=1; - else vend= 1 + getPntrToMultiColvar()->getNumberOfQuantities()-5; // +1 is for weight + if( getPntrToMultiColvar()->isDensity() ) vend=2; + else if( getPntrToMultiColvar()->getNumberOfQuantities()==2 ) vend=2; + else vend = getPntrToMultiColvar()->getNumberOfQuantities(); nquantities = vend + nbins[0] + nbins[1] + nbins[2]; // Output some nice information @@ -100,19 +100,16 @@ nbins(3) finishTaskListUpdate(); } -unsigned Gradient::getCentralAtomElementIndex(){ - plumed_error(); -} - void Gradient::setupRegions(){ // if( !getPbc().isOrthorombic() ) error("cell must be orthorhombic when using gradient"); } -void Gradient::calculateAllVolumes(){ - Vector cpos = pbcDistance( getPosition(0), getPntrToMultiColvar()->retrieveCentralAtomPos() ); - Vector oderiv, fpos = getPbc().realToScaled( cpos ); +void Gradient::calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals ){ + Vector cpos = pbcDistance( getPosition(0), getPntrToMultiColvar()->getCentralAtomPos( curr ) ); + // Note we use the pbc from base multicolvar so that we get numerical derivatives correct + Vector oderiv, fpos = (getPntrToMultiColvar()->getPbc()).realToScaled( cpos ); - Vector deriv; unsigned nbase=vend; + Vector deriv; unsigned nbase=vend; std::vector<Vector> refder(1); Tensor vir; vir.zero(); for(unsigned idir=0;idir<3;++idir){ deriv[0]=deriv[1]=deriv[2]=0.0; double delx = 1.0 / static_cast<double>( nbins[idir] ); @@ -120,10 +117,11 @@ void Gradient::calculateAllVolumes(){ // Calculate what box we are in bead.set( -0.5+jbead*delx, -0.5+(jbead+1)*delx, sigma ); double weight=bead.calculate( fpos[0], deriv[idir] ); - oderiv = getPbc().realToScaled( deriv ); + oderiv = (getPntrToMultiColvar()->getPbc()).realToScaled( deriv ); // Set and derivatives - setNumberInVolume( nbase+jbead, weight, oderiv ); - addReferenceAtomDerivatives( nbase+jbead, 0, -oderiv ); + refder[0]=-oderiv; // vir = -Tensor(cpos,oderiv); + setNumberInVolume( nbase+jbead, curr, weight, oderiv, vir, refder, outvals ); +// addReferenceAtomDerivatives( nbase+jbead, 0, -oderiv ); // addBoxDerivatives( nbase+jbead, -Tensor(cpos,oderiv) ); } nbase += nbins[idir]; diff --git a/src/crystallization/Gradient.h b/src/crystallization/Gradient.h index 80be920dc845b805e6c578253c9a715297edde02..b16d0376d9d5dceb29675a01e0892136aee328b8 100644 --- a/src/crystallization/Gradient.h +++ b/src/crystallization/Gradient.h @@ -43,14 +43,10 @@ public: Gradient(const ActionOptions&); /// Get the number of quantities that are calculated each time virtual unsigned getNumberOfQuantities(); -/// This just throws an error - unsigned getCentralAtomElementIndex(); /// Check on pbc - is it orthorhombic void setupRegions(); /// Calculate whats in the volume - void calculateAllVolumes(); - double getValueForTolerance(); - unsigned getIndexOfWeight(); + void calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals ); }; inline @@ -58,17 +54,6 @@ unsigned Gradient::getNumberOfQuantities(){ return nquantities; } -inline -double Gradient::getValueForTolerance(){ - return 1.0; -} - -inline -unsigned Gradient::getIndexOfWeight(){ - plumed_error(); - return 1; -} - } } #endif diff --git a/src/crystallization/GradientVessel.cpp b/src/crystallization/GradientVessel.cpp index ba2466bb1a11ecbd3d7e134b3706220e1f94442b..0f2d6372dbfebd5719bac50621cdfc11e52120f7 100644 --- a/src/crystallization/GradientVessel.cpp +++ b/src/crystallization/GradientVessel.cpp @@ -34,15 +34,15 @@ private: bool isdens; unsigned nweights, ncomponents; std::vector<unsigned> starts; - std::vector<double> val_interm; - Matrix<double> der_interm; +// std::vector<double> val_interm; +// Matrix<double> der_interm; public: static void registerKeywords( Keywords& keys ); static void reserveKeyword( Keywords& keys ); GradientVessel( const vesselbase::VesselOptions& da ); std::string function_description(); void resize(); - bool calculate( std::vector<double>& buffer ); + bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ); void finish( const std::vector<double>& buffer ); }; @@ -63,7 +63,12 @@ FunctionVessel(da) Gradient* vg=dynamic_cast<Gradient*>( getAction() ); plumed_assert( vg ); isdens=(vg->getPntrToMultiColvar())->isDensity(); nweights = vg->nbins[0] + vg->nbins[1] + vg->nbins[2]; - ncomponents = vg->vend; + if( (vg->getPntrToMultiColvar())->getNumberOfQuantities()>2 ){ + ncomponents = (vg->getPntrToMultiColvar())->getNumberOfQuantities() - 2; + } else { + ncomponents = 1; + } + // ncomponents = vg->vend; starts.push_back(0); if( vg->nbins[0]>0 ){ @@ -91,29 +96,34 @@ void GradientVessel::resize(){ unsigned nder=getAction()->getNumberOfDerivatives(); resizeBuffer( (1+nder)*(ncomponents+1)*nweights ); setNumberOfDerivatives( nder ); - val_interm.resize( ncomponents*nweights ); - der_interm.resize( ncomponents*nweights, nder ); +// val_interm.resize( ncomponents*nweights ); +// der_interm.resize( ncomponents*nweights, nder ); } else { setNumberOfDerivatives(0); resizeBuffer( (ncomponents+1)*nweights ); - val_interm.resize( ncomponents*nweights ); +// val_interm.resize( ncomponents*nweights ); } } -bool GradientVessel::calculate( std::vector<double>& buffer ){ +bool GradientVessel::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ){ unsigned nder=getAction()->getNumberOfDerivatives(); + unsigned wstart, cstart; if( ncomponents==1 ){ cstart=1; wstart=2; } else { cstart=2; wstart=2+ncomponents; } + for(unsigned iw=0;iw<nweights;++iw){ unsigned xx = (ncomponents+1)*iw; - double weight=getAction()->getElementValue(ncomponents + iw); + double weight=myvals.get(wstart+iw); // getAction()->getElementValue(ncomponents + iw); buffer[bufstart+xx*(nder+1)] += weight; + myvals.chainRule( wstart + iw, xx, 1, 0, 1.0, bufstart, buffer ); // addValueIgnoringTolerance( xx, weight ); - getAction()->chainRuleForElementDerivatives( xx , ncomponents + iw, 1.0, bufstart, buffer ); + // getAction()->chainRuleForElementDerivatives( xx , ncomponents + iw, 1.0, bufstart, buffer ); for(unsigned jc=0;jc<ncomponents;++jc){ - double colvar=getAction()->getElementValue( jc ); + double colvar=myvals.get( cstart + jc ); // getAction()->getElementValue( jc ); // addValueIgnoringTolerance( xx + 1 + jc, weight*colvar ); buffer[bufstart+(xx+1+jc)*(nder+1) ] += weight*colvar; - getAction()->chainRuleForElementDerivatives( xx + 1 + jc, jc, weight, bufstart, buffer ); - getAction()->chainRuleForElementDerivatives( xx + 1 + jc, ncomponents + iw, colvar, bufstart, buffer ); + myvals.chainRule( cstart + jc, xx + 1 + jc, 1, 0, weight, bufstart, buffer ); + myvals.chainRule( wstart + iw, xx + 1 + jc, 1, 0, colvar, bufstart, buffer ); + // getAction()->chainRuleForElementDerivatives( xx + 1 + jc, jc, weight, bufstart, buffer ); + // getAction()->chainRuleForElementDerivatives( xx + 1 + jc, ncomponents + iw, colvar, bufstart, buffer ); } } @@ -121,14 +131,15 @@ bool GradientVessel::calculate( std::vector<double>& buffer ){ } void GradientVessel::finish( const std::vector<double>& buffer ){ - der_interm=0; // Clear all interim derivatives + std::vector<double> val_interm( ncomponents*nweights ); unsigned nder = getAction()->getNumberOfDerivatives(); + Matrix<double> der_interm( ncomponents*nweights, nder ); der_interm=0; if( isdens ){ for(unsigned iw=0;iw<nweights;++iw){ val_interm[iw] = buffer[bufstart + 2*iw*(1+nder)]; // getFinalValue( 2*iw ); if( getAction()->derivativesAreRequired() ){ - unsigned wstart = 2*iw*(nder+1) + 1; + unsigned wstart = bufstart + 2*iw*(nder+1) + 1; for(unsigned jder=0;jder<nder;++jder) der_interm( iw, jder ) += buffer[ wstart + jder ]; // getBufferElement( wstart + jder ); } } @@ -136,7 +147,7 @@ void GradientVessel::finish( const std::vector<double>& buffer ){ for(unsigned iw=0;iw<nweights;++iw){ unsigned xx = (ncomponents+1)*iw; double ww=buffer[bufstart + xx*(1+nder)]; // getFinalValue( xx ); - for(unsigned jc=0;jc<ncomponents;++jc) val_interm[ iw*ncomponents + jc ] = buffer[bufstart + (xx+1+jc)*(1+nder)]; //getFinalValue( xx + 1 + jc ) / ww; + for(unsigned jc=0;jc<ncomponents;++jc) val_interm[ iw*ncomponents + jc ] = buffer[bufstart + (xx+1+jc)*(1+nder)] / ww; //getFinalValue( xx + 1 + jc ) / ww; if( getAction()->derivativesAreRequired() ){ unsigned wstart = bufstart + xx*(nder+1) + 1; for(unsigned jc=0;jc<ncomponents;++jc){ diff --git a/src/crystallization/MoleculeOrientation.cpp b/src/crystallization/MoleculeOrientation.cpp index 01e7aa08028295c3f52691c71caaf4a99e7ba02a..9517bd0ca6b8a50ba2c584fc0439af62bd4c002e 100644 --- a/src/crystallization/MoleculeOrientation.cpp +++ b/src/crystallization/MoleculeOrientation.cpp @@ -54,8 +54,7 @@ private: public: static void registerKeywords( Keywords& keys ); MoleculeOrientation( const ActionOptions& ao ); - void calculateVector(); - Vector getCentralAtom(); + void calculateVector( multicolvar::AtomValuePack& myatoms ); }; PLUMED_REGISTER_ACTION(MoleculeOrientation,"MOLECULES") @@ -80,40 +79,45 @@ VectorMultiColvar(ao) if( all_atoms.size()==0 ) error("No atoms were specified"); ActionAtomistic::requestAtoms( all_atoms ); - setVectorDimensionality( 3, false, natoms ); + setVectorDimensionality( 3, natoms ); + + if( natoms==3 ){ + std::vector<bool> catom_ind(3, false); catom_ind[2]=true; + setAtomsForCentralAtom( catom_ind ); + } } -void MoleculeOrientation::calculateVector(){ - Vector distance; distance=getSeparation( getPosition(0), getPosition(1) ); +void MoleculeOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ){ + Vector distance; distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - addAtomsDerivative( 0, 0, Vector(-1.0,0,0) ); - addAtomsDerivative( 0, 1, Vector(+1.0,0,0) ); - addBoxDerivatives( 0, Tensor(distance,Vector(-1.0,0,0)) ); - addComponent( 0, distance[0] ); + myatoms.addAtomsDerivatives( 2, 0, Vector(-1.0,0,0) ); + myatoms.addAtomsDerivatives( 2, 1, Vector(+1.0,0,0) ); + myatoms.addBoxDerivatives( 2, Tensor(distance,Vector(-1.0,0,0)) ); + myatoms.addValue( 2, distance[0] ); - addAtomsDerivative( 1, 0, Vector(0,-1.0,0) ); - addAtomsDerivative( 1, 1, Vector(0,+1.0,0) ); - addBoxDerivatives( 1, Tensor(distance,Vector(0,-1.0,0)) ); - addComponent( 1, distance[1] ); + myatoms.addAtomsDerivatives( 3, 0, Vector(0,-1.0,0) ); + myatoms.addAtomsDerivatives( 3, 1, Vector(0,+1.0,0) ); + myatoms.addBoxDerivatives( 3, Tensor(distance,Vector(0,-1.0,0)) ); + myatoms.addValue( 3, distance[1] ); - addAtomsDerivative( 2, 0, Vector(0,0,-1.0) ); - addAtomsDerivative( 2, 1, Vector(0,0,+1.0) ); - addBoxDerivatives( 2, Tensor(distance,Vector(0,0,-1.0)) ); - addComponent( 2, distance[2] ); + myatoms.addAtomsDerivatives( 4, 0, Vector(0,0,-1.0) ); + myatoms.addAtomsDerivatives( 4, 1, Vector(0,0,+1.0) ); + myatoms.addBoxDerivatives( 4, Tensor(distance,Vector(0,0,-1.0)) ); + myatoms.addValue( 4, distance[2] ); } -Vector MoleculeOrientation::getCentralAtom(){ - if( getNAtoms()==2 ){ - Vector com; com.zero(); - com+=0.5*getPosition(0); - com+=0.5*getPosition(1); - addCentralAtomDerivatives( 0, 0.5*Tensor::identity() ); - addCentralAtomDerivatives( 1, 0.5*Tensor::identity() ); - return com; - } - addCentralAtomDerivatives( 2, Tensor::identity() ); - return getPosition(2); -} +// Vector MoleculeOrientation::getCentralAtom(){ +// if( getNAtoms()==2 ){ +// Vector com; com.zero(); +// com+=0.5*getPosition(0); +// com+=0.5*getPosition(1); +// addCentralAtomDerivatives( 0, 0.5*Tensor::identity() ); +// addCentralAtomDerivatives( 1, 0.5*Tensor::identity() ); +// return com; +// } +// addCentralAtomDerivatives( 2, Tensor::identity() ); +// return getPosition(2); +// } } } diff --git a/src/crystallization/MoleculePlane.cpp b/src/crystallization/MoleculePlane.cpp index 71baafd501aa98ebfaefdb2cb97335661ac3ab63..b38129161bcc46b792fff08698136c1da69a512e 100644 --- a/src/crystallization/MoleculePlane.cpp +++ b/src/crystallization/MoleculePlane.cpp @@ -41,8 +41,7 @@ private: public: static void registerKeywords( Keywords& keys ); MoleculePlane( const ActionOptions& ao ); - void calculateVector(); - Vector getCentralAtom(); + void calculateVector( multicolvar::AtomValuePack& myatoms ); }; PLUMED_REGISTER_ACTION(MoleculePlane,"PLANES") @@ -69,78 +68,78 @@ VectorMultiColvar(ao) if( all_atoms.size()==0 ) error("No atoms were specified"); ActionAtomistic::requestAtoms( all_atoms ); - setVectorDimensionality( 3, false, natoms ); + setVectorDimensionality( 3, natoms ); } -void MoleculePlane::calculateVector(){ +void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ){ Vector d1, d2, cp; - if( getNAtoms()==3 ){ - d1=getSeparation( getPosition(1), getPosition(0) ); - d2=getSeparation( getPosition(1), getPosition(2) ); + if( myatoms.getNumberOfAtoms()==3 ){ + d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); + d2=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); } else { - d1=getSeparation( getPosition(1), getPosition(0) ); - d2=getSeparation( getPosition(2), getPosition(3) ); + d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); + d2=getSeparation( myatoms.getPosition(2), myatoms.getPosition(3) ); } cp = crossProduct( d1, d2 ); - addAtomsDerivative( 0, 0, crossProduct( Vector(-1.0,0,0), d2 ) ); - if( getNAtoms()==3 ){ - addAtomsDerivative( 0, 1, crossProduct( Vector(+1.0,0,0), d2 ) + crossProduct( Vector(-1.0,0,0), d1 ) ); - addAtomsDerivative( 0, 2, crossProduct( Vector(+1.0,0,0), d1 ) ); + myatoms.addAtomsDerivatives( 2, 0, crossProduct( Vector(-1.0,0,0), d2 ) ); + if( myatoms.getNumberOfAtoms()==3 ){ + myatoms.addAtomsDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ) + crossProduct( Vector(-1.0,0,0), d1 ) ); + myatoms.addAtomsDerivatives( 2, 2, crossProduct( Vector(+1.0,0,0), d1 ) ); } else { - addAtomsDerivative( 0, 1, crossProduct( Vector(+1.0,0,0), d2 ) ); - addAtomsDerivative( 0, 2, crossProduct( Vector(-1.0,0,0), d1 ) ); - addAtomsDerivative( 0, 3, crossProduct( Vector(+1.0,0,0), d1 ) ); + myatoms.addAtomsDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ) ); + myatoms.addAtomsDerivatives( 2, 2, crossProduct( Vector(-1.0,0,0), d1 ) ); + myatoms.addAtomsDerivatives( 2, 3, crossProduct( Vector(+1.0,0,0), d1 ) ); } - addBoxDerivatives( 0, Tensor(d1,crossProduct(Vector(+1.0,0,0), d2)) + Tensor( d2, crossProduct(Vector(-1.0,0,0), d1)) ); - addComponent( 0, cp[0] ); + myatoms.addBoxDerivatives( 2, Tensor(d1,crossProduct(Vector(+1.0,0,0), d2)) + Tensor( d2, crossProduct(Vector(-1.0,0,0), d1)) ); + myatoms.addValue( 2, cp[0] ); - addAtomsDerivative( 1, 0, crossProduct( Vector(0,-1.0,0), d2 ) ); - if( getNAtoms()==3 ){ - addAtomsDerivative( 1, 1, crossProduct( Vector(0,+1.0,0), d2 ) + crossProduct( Vector(0,-1.0,0), d1 ) ); - addAtomsDerivative( 1, 2, crossProduct( Vector(0,+1.0,0), d1 ) ); + myatoms.addAtomsDerivatives( 3, 0, crossProduct( Vector(0,-1.0,0), d2 ) ); + if( myatoms.getNumberOfAtoms()==3 ){ + myatoms.addAtomsDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ) + crossProduct( Vector(0,-1.0,0), d1 ) ); + myatoms.addAtomsDerivatives( 3, 2, crossProduct( Vector(0,+1.0,0), d1 ) ); } else { - addAtomsDerivative( 1, 1, crossProduct( Vector(0,+1.0,0), d2 ) ); - addAtomsDerivative( 1, 2, crossProduct( Vector(0,-1.0,0), d1 ) ); - addAtomsDerivative( 1, 3, crossProduct( Vector(0,+1.0,0), d1 ) ); + myatoms.addAtomsDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ) ); + myatoms.addAtomsDerivatives( 3, 2, crossProduct( Vector(0,-1.0,0), d1 ) ); + myatoms.addAtomsDerivatives( 3, 3, crossProduct( Vector(0,+1.0,0), d1 ) ); } - addBoxDerivatives( 1, Tensor(d1,crossProduct(Vector(0,+1.0,0), d2)) + Tensor( d2, crossProduct(Vector(0,-1.0,0), d1)) ); - addComponent( 1, cp[1] ); + myatoms.addBoxDerivatives( 3, Tensor(d1,crossProduct(Vector(0,+1.0,0), d2)) + Tensor( d2, crossProduct(Vector(0,-1.0,0), d1)) ); + myatoms.addValue( 3, cp[1] ); - addAtomsDerivative( 2, 0, crossProduct( Vector(0,0,-1.0), d2 ) ); - if( getNAtoms()==3 ){ - addAtomsDerivative( 2, 1, crossProduct( Vector(0,0,+1.0), d2 ) + crossProduct( Vector(0,0,-1.0), d1 ) ); - addAtomsDerivative( 2, 2, crossProduct( Vector(0,0,+1.0), d1 ) ); + myatoms.addAtomsDerivatives( 4, 0, crossProduct( Vector(0,0,-1.0), d2 ) ); + if( myatoms.getNumberOfAtoms()==3 ){ + myatoms.addAtomsDerivatives( 4, 1, crossProduct( Vector(0,0,+1.0), d2 ) + crossProduct( Vector(0,0,-1.0), d1 ) ); + myatoms.addAtomsDerivatives( 4, 2, crossProduct( Vector(0,0,+1.0), d1 ) ); } else { - addAtomsDerivative( 2, 1, crossProduct( Vector(0,0,-1.0), d2 ) ); - addAtomsDerivative( 2, 2, crossProduct( Vector(0,0,-1.0), d1 ) ); - addAtomsDerivative( 2, 3, crossProduct( Vector(0,0,+1.0), d1 ) ); + myatoms.addAtomsDerivatives( 4, 1, crossProduct( Vector(0,0,-1.0), d2 ) ); + myatoms.addAtomsDerivatives( 4, 2, crossProduct( Vector(0,0,-1.0), d1 ) ); + myatoms.addAtomsDerivatives( 4, 3, crossProduct( Vector(0,0,+1.0), d1 ) ); } - addBoxDerivatives( 2, Tensor(d1,crossProduct(Vector(0,0,+1.0), d2)) + Tensor( d2, crossProduct(Vector(0,0,-1.0), d1)) ); - addComponent( 2, cp[2] ); + myatoms.addBoxDerivatives( 4, Tensor(d1,crossProduct(Vector(0,0,+1.0), d2)) + Tensor( d2, crossProduct(Vector(0,0,-1.0), d1)) ); + myatoms.addValue( 4, cp[2] ); } -Vector MoleculePlane::getCentralAtom(){ - Vector com; com.zero(); - if( getNAtoms()==3 ){ - com+=(1.0/3.0)*getPosition(0); - com+=(1.0/3.0)*getPosition(1); - com+=(1.0/3.0)*getPosition(2); - addCentralAtomDerivatives( 0, (1.0/3.0)*Tensor::identity() ); - addCentralAtomDerivatives( 1, (1.0/3.0)*Tensor::identity() ); - addCentralAtomDerivatives( 2, (1.0/3.0)*Tensor::identity() ); - return com; - } - com+=0.25*getPosition(0); - com+=0.25*getPosition(1); - com+=0.25*getPosition(2); - com+=0.25*getPosition(3); - addCentralAtomDerivatives( 0, 0.25*Tensor::identity() ); - addCentralAtomDerivatives( 1, 0.25*Tensor::identity() ); - addCentralAtomDerivatives( 2, 0.25*Tensor::identity() ); - addCentralAtomDerivatives( 3, 0.25*Tensor::identity() ); - return com; -} +// Vector MoleculePlane::getCentralAtom(){ +// Vector com; com.zero(); +// if( getNAtoms()==3 ){ +// com+=(1.0/3.0)*getPosition(0); +// com+=(1.0/3.0)*getPosition(1); +// com+=(1.0/3.0)*getPosition(2); +// addCentralAtomDerivatives( 0, (1.0/3.0)*Tensor::identity() ); +// addCentralAtomDerivatives( 1, (1.0/3.0)*Tensor::identity() ); +// addCentralAtomDerivatives( 2, (1.0/3.0)*Tensor::identity() ); +// return com; +// } +// com+=0.25*getPosition(0); +// com+=0.25*getPosition(1); +// com+=0.25*getPosition(2); +// com+=0.25*getPosition(3); +// addCentralAtomDerivatives( 0, 0.25*Tensor::identity() ); +// addCentralAtomDerivatives( 1, 0.25*Tensor::identity() ); +// addCentralAtomDerivatives( 2, 0.25*Tensor::identity() ); +// addCentralAtomDerivatives( 3, 0.25*Tensor::identity() ); +// return com; +// } } } diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp index 34c3554bf630c8bbc432df09c7727726ea9f4e56..a6d8042b881c795b5fe48d6032eb0e38f231e564 100644 --- a/src/crystallization/OrientationSphere.cpp +++ b/src/crystallization/OrientationSphere.cpp @@ -45,15 +45,6 @@ OrientationSphere::OrientationSphere(const ActionOptions&ao): Action(ao), MultiColvarFunction(ao) { - // Resize everything that stores a vector now that we know the - // number of components - unsigned ncomponents=getBaseMultiColvar(0)->getNumberOfQuantities() - 5; - catom_orient.resize( ncomponents ); - catom_der.resize( ncomponents ); - this_orient.resize( ncomponents ); - - // Weight of this does not have derivatives - weightHasDerivatives=false; // Read in the switching function std::string sw, errors; parse("SWITCH",sw); if(sw.length()>0){ @@ -74,63 +65,70 @@ MultiColvarFunction(ao) buildSymmetryFunctionLists(); } -void OrientationSphere::calculateWeight(){ - weightHasDerivatives=true; // The weight has no derivatives really - setElementValue(1,1.0); -} - -double OrientationSphere::compute(){ +double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){ // Make sure derivatives for central atom are only calculated once VectorMultiColvar* vv = dynamic_cast<VectorMultiColvar*>( getBaseMultiColvar(0) ); vv->firstcall=true; - weightHasDerivatives=true; // The weight has no derivatives really double d2, sw, value=0, denom=0, dot, f_dot, dot_df, dfunc; Vector distance; + unsigned ncomponents=getBaseMultiColvar(0)->getNumberOfQuantities(); + unsigned nder=getNumberOfDerivatives(); + std::vector<double> catom_orient( ncomponents ), this_orient( ncomponents ), catom_der( ncomponents ); + + Vector catom_pos = myatoms.getPosition(0); + getVectorForTask( myatoms.getIndex(0), true, catom_orient ); + multicolvar::CatomPack atom0; + vesselbase::MultiValue myder0(ncomponents,nder), myder1(ncomponents,nder); + if( !doNotCalculateDerivatives() ){ + atom0=getCentralAtomPackFromInput( myatoms.getIndex(0) ); + getVectorDerivatives( myatoms.getIndex(0), true, myder0 ); + } - getVectorForBaseTask(0, catom_orient ); - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( catom_pos, myatoms.getPosition(i) ); d2 = distance.modulo2(); if( d2<rcut2 ){ sw = switchingFunction.calculateSqr( d2, dfunc ); - getVectorForBaseTask( i, this_orient ); + getVectorForTask( myatoms.getIndex(i), true, this_orient ); // Calculate the dot product wrt to this position - dot=0; for(unsigned k=0;k<catom_orient.size();++k) dot+=catom_orient[k]*this_orient[k]; + dot=0; for(unsigned k=2;k<catom_orient.size();++k) dot+=catom_orient[k]*this_orient[k]; f_dot = transformDotProduct( dot, dot_df ); - // N.B. We are assuming here that the imaginary part of the dot product is zero - for(unsigned k=0;k<catom_orient.size();++k){ - this_orient[k]*=sw*dot_df; catom_der[k]=sw*dot_df*catom_orient[k]; - } - - // Set the derivatives wrt of the numerator - addOrientationDerivatives( 0, this_orient ); - addOrientationDerivatives( i, catom_der ); - addCentralAtomsDerivatives( 0, 0, f_dot*(-dfunc)*distance ); - addCentralAtomsDerivatives( i, 0, f_dot*(dfunc)*distance ); - addBoxDerivatives( f_dot*(-dfunc)*Tensor(distance,distance) ); + + if( !doNotCalculateDerivatives() ){ + // N.B. We are assuming here that the imaginary part of the dot product is zero + for(unsigned k=2;k<catom_orient.size();++k){ + this_orient[k]*=sw*dot_df; catom_der[k]=sw*dot_df*catom_orient[k]; + } + getVectorDerivatives( myatoms.getIndex(i), true, myder1 ); + mergeVectorDerivatives( 1, 2, this_orient.size(), myatoms.getIndex(0), this_orient, myder0, myatoms ); + mergeVectorDerivatives( 1, 2, catom_der.size(), myatoms.getIndex(i), catom_der, myder1, myatoms ); + myatoms.addComDerivatives( 1, f_dot*(-dfunc)*distance, atom0 ); + multicolvar::CatomPack atom1=getCentralAtomPackFromInput( myatoms.getIndex(i) ); + myatoms.addComDerivatives( 1, f_dot*(dfunc)*distance, atom1 ); + myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) ); + myder1.clearAll(); + + myatoms.addComDerivatives( 0, (-dfunc)*distance, atom0 ); + myatoms.addComDerivatives( 0, (dfunc)*distance, atom1 ); + myatoms.addBoxDerivatives( 0, (-dfunc)*Tensor(distance,distance) ); + + } value += sw*f_dot; - // Set the derivatives wrt to the numerator - addCentralAtomsDerivatives( 0, 1, (-dfunc)*distance ); - addCentralAtomsDerivatives( i, 1, (dfunc)*distance ); - addBoxDerivativesOfWeight( (-dfunc)*Tensor(distance,distance) ); denom += sw; } } // Now divide everything - unsigned nder = getNumberOfDerivatives(); - for(unsigned i=0;i<nder;++i){ - setElementDerivative( i, getElementDerivative(i)/denom - (value*getElementDerivative(nder+i))/(denom*denom) ); - setElementDerivative( nder + i, 0.0 ); - } - weightHasDerivatives=false; // Weight has no derivatives we just use the holder for weight to store some stuff - return value / denom; -} + double denom2=denom*denom; + updateActiveAtoms( myatoms ); vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue(); + for(unsigned i=0;i<myvals.getNumberActive();++i){ + unsigned ider=myvals.getActiveIndex(i); + myvals.setDerivative( 1, ider, myvals.getDerivative(1,ider)/denom - (value*myvals.getDerivative(0,ider))/denom2 ); + } + myvals.clear(0); myvals.setValue( 0, 1.0 ); -Vector OrientationSphere::getCentralAtom(){ - addDerivativeOfCentralAtomPos( 0, Tensor::identity() ); - return getPositionOfCentralAtom(0); + return value / denom; } } diff --git a/src/crystallization/OrientationSphere.h b/src/crystallization/OrientationSphere.h index 44e6a46c69d46cb5e772e167320aa61efced1888..1b137910ae3e1c8b14efc11b6baf38d3d52902e1 100644 --- a/src/crystallization/OrientationSphere.h +++ b/src/crystallization/OrientationSphere.h @@ -34,16 +34,12 @@ namespace crystallization { class OrientationSphere : public multicolvar::MultiColvarFunction { private: double rcut2; - std::vector<double> catom_orient, catom_der, this_orient; - std::vector<double> catom_iorient, catom_ider, this_iorient; SwitchingFunction switchingFunction; public: static void registerKeywords( Keywords& keys ); OrientationSphere(const ActionOptions&); - double compute(); - void calculateWeight(); + double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); virtual double transformDotProduct( const double& dot, double& df ); - Vector getCentralAtom(); bool isPeriodic(){ return false; } }; diff --git a/src/crystallization/SimpleCubic.cpp b/src/crystallization/SimpleCubic.cpp index 22ea326e2440da4ed2bcc5dbd2094734384e130a..09ab4b73fc83cc8eab7c7f434c499afaf1b01115 100644 --- a/src/crystallization/SimpleCubic.cpp +++ b/src/crystallization/SimpleCubic.cpp @@ -64,8 +64,7 @@ public: static void registerKeywords( Keywords& keys ); SimpleCubic(const ActionOptions&); // active methods: - virtual double compute(); - Vector getCentralAtom(); + virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } }; @@ -113,15 +112,14 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double SimpleCubic::compute(){ - weightHasDerivatives=true; +double SimpleCubic::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){ double d2, value=0, norm=0, dfunc; Vector distance; // Calculate the coordination number Vector myder, fder; double sw, t1, t2, t3, x2, x3, x4, y2, y3, y4, z2, z3, z4, r4, tmp; - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPosition(0), getPosition(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); d2 = distance.modulo2(); if( d2<rcut2 ){ sw = switchingFunction.calculateSqr( d2, dfunc ); @@ -147,32 +145,26 @@ double SimpleCubic::compute(){ myder[2] = 4*z3/t2-4*distance[2]*t3; value += sw*tmp; fder = (+dfunc)*tmp*distance + sw*myder; - addAtomsDerivatives( 0, -fder ); - addAtomsDerivatives( i, +fder ); + myatoms.addAtomsDerivatives( 1, 0, -fder ); + myatoms.addAtomsDerivatives( 1, i, +fder ); // Tens is a constructor that you build by taking the vector product of two vectors (remember the scalars!) - addBoxDerivatives( Tensor(distance,-fder) ); + myatoms.addBoxDerivatives( 1, Tensor(distance,-fder) ); norm += sw; - addAtomsDerivativeOfWeight( 0, (-dfunc)*distance ); - addAtomsDerivativeOfWeight( i, (+dfunc)*distance ); - addBoxDerivativesOfWeight( (-dfunc)*Tensor(distance,distance) ); + myatoms.addAtomsDerivatives( 0, 0, (-dfunc)*distance ); + myatoms.addAtomsDerivatives( 0, i, (+dfunc)*distance ); + myatoms.addBoxDerivatives( 0, (-dfunc)*Tensor(distance,distance) ); } } - setElementValue(0, value); setElementValue(1, norm ); + myatoms.setValue(1, value); myatoms.setValue(0, norm ); // values -> der of... value [0], weight[1], x coord [2], y, z... [more magic] - updateActiveAtoms(); quotientRule( 0, 1, 0 ); clearDerivativesAfterTask(1); - // Weight doesn't really have derivatives (just use the holder for convenience) - weightHasDerivatives=false; setElementValue( 1, 1.0 ); + updateActiveAtoms( myatoms ); myatoms.getUnderlyingMultiValue().quotientRule( 1, 0, 1 ); + myatoms.getUnderlyingMultiValue().clear(0); myatoms.setValue( 0, 1.0 ); return value / norm; // this is equivalent to getting an "atomic" CV } -Vector SimpleCubic::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - } } diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp index 9a1761791899f544b9f609f4a27852178be6da03..61382e07519f5c290397e9a969f970a8fbe968ae 100644 --- a/src/crystallization/Steinhardt.cpp +++ b/src/crystallization/Steinhardt.cpp @@ -61,18 +61,19 @@ VectorMultiColvar(ao) } void Steinhardt::setAngularMomentum( const unsigned& ang ){ - tmom=ang; setVectorDimensionality( 2*ang + 1, true, 2 ); + tmom=ang; setVectorDimensionality( 2*(2*ang + 1), 2 ); } -void Steinhardt::calculateVector(){ +void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ){ double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; Vector distance, dz, myrealvec, myimagvec, real_dz, imag_dz; // The square root of -1 std::complex<double> ii( 0.0, 1.0 ), dp_x, dp_y, dp_z; + unsigned ncomp=2*tmom+1; double sw, poly_ass, dlen, nbond=0.0; std::complex<double> powered; - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPosition(0), getPosition(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); dlen=distance.modulo(); if( dlen<rcut ){ sw = switchingFunction.calculate( dlen, dfunc ); @@ -81,9 +82,9 @@ void Steinhardt::calculateVector(){ double dlen3 = dlen*dlen*dlen; // Store derivatives of weight - MultiColvarBase::addAtomsDerivatives( 0, current_atoms[0], (-dfunc)*distance ); - MultiColvarBase::addAtomsDerivatives( 0, current_atoms[i], (+dfunc)*distance ); - MultiColvarBase::addBoxDerivatives( 0, (-dfunc)*Tensor( distance,distance ) ); + myatoms.addAtomsDerivatives( 1, 0, (-dfunc)*distance ); + myatoms.addAtomsDerivatives( 1, i, (+dfunc)*distance ); + myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor( distance,distance ) ); // Do stuff for m=0 poly_ass=deriv_poly( 0, distance[2]/dlen, dpoly_ass ); @@ -92,11 +93,11 @@ void Steinhardt::calculateVector(){ // Derivative wrt to the vector connecting the two atoms myrealvec = (+sw)*dpoly_ass*dz + poly_ass*(+dfunc)*distance; // Accumulate the derivatives - addAtomsDerivative( tmom, 0, -myrealvec ); - addAtomsDerivative( tmom, i, myrealvec ); - addBoxDerivatives( tmom, Tensor( -myrealvec,distance ) ); + myatoms.addAtomsDerivatives( 2 + tmom, 0, -myrealvec ); + myatoms.addAtomsDerivatives( 2 + tmom, i, myrealvec ); + myatoms.addBoxDerivatives( 2 + tmom, Tensor( -myrealvec,distance ) ); // And store the vector function - addComponent( tmom, sw*poly_ass ); + myatoms.addValue( 2 + tmom, sw*poly_ass ); // The complex number of which we have to take powers std::complex<double> com1( distance[0]/dlen ,distance[1]/dlen ); @@ -128,38 +129,38 @@ void Steinhardt::calculateVector(){ myimagvec = (+sw)*dpoly_ass*imag_z*dz + (+dfunc)*distance*itq6 + (+sw)*poly_ass*imag_dz; // Real part - addComponent( tmom+m, sw*tq6 ); - addAtomsDerivative( tmom+m, 0, -myrealvec ); - addAtomsDerivative( tmom+m, i, myrealvec ); - addBoxDerivatives( tmom+m, Tensor( -myrealvec,distance ) ); + myatoms.addValue( 2+tmom+m, sw*tq6 ); + myatoms.addAtomsDerivatives( 2+tmom+m, 0, -myrealvec ); + myatoms.addAtomsDerivatives( 2+tmom+m, i, myrealvec ); + myatoms.addBoxDerivatives( 2+tmom+m, Tensor( -myrealvec,distance ) ); // Imaginary part - addImaginaryComponent( tmom+m, sw*itq6 ); - addImaginaryAtomsDerivative( tmom+m, 0, -myimagvec ); - addImaginaryAtomsDerivative( tmom+m, i, myimagvec ); - addImaginaryBoxDerivatives( tmom+m, Tensor( -myimagvec,distance ) ); + myatoms.addValue( 2+ncomp+tmom+m, sw*itq6 ); + myatoms.addAtomsDerivatives( 2+ncomp+tmom+m, 0, -myimagvec ); + myatoms.addAtomsDerivatives( 2+ncomp+tmom+m, i, myimagvec ); + myatoms.addBoxDerivatives( 2+ncomp+tmom+m, Tensor( -myimagvec,distance ) ); // Store -m part of vector double pref=pow(-1.0,m); // -m part of vector is just +m part multiplied by (-1.0)**m and multiplied by complex // conjugate of Legendre polynomial // Real part - addComponent( tmom-m, pref*sw*tq6 ); - addAtomsDerivative( tmom-m, 0, -pref*myrealvec ); - addAtomsDerivative( tmom-m, i, pref*myrealvec ); - addBoxDerivatives( tmom-m, pref*Tensor( -myrealvec,distance ) ); + myatoms.addValue( 2+tmom-m, pref*sw*tq6 ); + myatoms.addAtomsDerivatives( 2+tmom-m, 0, -pref*myrealvec ); + myatoms.addAtomsDerivatives( 2+tmom-m, i, pref*myrealvec ); + myatoms.addBoxDerivatives( 2+tmom-m, pref*Tensor( -myrealvec,distance ) ); // Imaginary part - addImaginaryComponent( tmom-m, -pref*sw*itq6 ); - addImaginaryAtomsDerivative( tmom-m, 0, pref*myimagvec ); - addImaginaryAtomsDerivative( tmom-m, i, -pref*myimagvec ); - addImaginaryBoxDerivatives( tmom-m, pref*Tensor( myimagvec,distance ) ); + myatoms.addValue( 2+ncomp+tmom-m, -pref*sw*itq6 ); + myatoms.addAtomsDerivatives( 2+ncomp+tmom-m, 0, pref*myimagvec ); + myatoms.addAtomsDerivatives( 2+ncomp+tmom-m, i, -pref*myimagvec ); + myatoms.addBoxDerivatives( 2+ncomp+tmom-m, pref*Tensor( myimagvec,distance ) ); } } } // Normalize - setElementValue(0, nbond ); updateActiveAtoms(); - for(unsigned i=0;i<2*getNumberOfComponentsInVector();++i) quotientRule( 5+i, 0, 5+i ); + myatoms.setValue(1, nbond ); updateActiveAtoms( myatoms ); + for(unsigned i=0;i<getNumberOfComponentsInVector();++i) myatoms.getUnderlyingMultiValue().quotientRule( 2+i, 1, 2+i ); // Clear tempory stuff - clearDerivativesAfterTask(0); + myatoms.getUnderlyingMultiValue().clear(1); } double Steinhardt::deriv_poly( const unsigned& m, const double& val, double& df ){ @@ -179,11 +180,5 @@ double Steinhardt::deriv_poly( const unsigned& m, const double& val, double& df return normaliz[m]*res; } -Vector Steinhardt::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); - -} - } } diff --git a/src/crystallization/Steinhardt.h b/src/crystallization/Steinhardt.h index dee921aadf5ad3d8a32a49c707403ab5212ea43b..542ccc3582b076691fe2f5bec3090dd1600a8145 100644 --- a/src/crystallization/Steinhardt.h +++ b/src/crystallization/Steinhardt.h @@ -41,8 +41,7 @@ protected: public: static void registerKeywords( Keywords& keys ); Steinhardt( const ActionOptions& ao ); - void calculateVector(); - Vector getCentralAtom(); + void calculateVector( multicolvar::AtomValuePack& myatoms ); double deriv_poly( const unsigned&, const double&, double& ); }; diff --git a/src/crystallization/StoreVectorsVessel.cpp b/src/crystallization/StoreVectorsVessel.cpp deleted file mode 100644 index 56e73490ec31e61daf832186763199e806bf80c2..0000000000000000000000000000000000000000 --- a/src/crystallization/StoreVectorsVessel.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013,2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#include "vesselbase/VesselRegister.h" -#include "vesselbase/ActionWithVessel.h" -#include "multicolvar/MultiColvarFunction.h" -#include "StoreVectorsVessel.h" -#include "VectorMultiColvar.h" - -namespace PLMD { -namespace crystallization{ - -void StoreVectorsVessel::registerKeywords( Keywords& keys ){ - vesselbase::StoreDataVessel::registerKeywords(keys); -} - -StoreVectorsVessel::StoreVectorsVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da), -store_director(true) -{ - vecs=dynamic_cast<VectorMultiColvar*>( getAction() ); - plumed_assert( vecs ); - if( vecs->complexvec ) ncomponents=2*vecs->ncomponents; - else ncomponents = vecs->ncomponents; - - completeSetup( 5, ncomponents ); myfvec.resize( ncomponents ); -} - -void StoreVectorsVessel::usedInFunction( const bool& store ){ - store_director=store; resize(); -} - -void StoreVectorsVessel::recompute( const unsigned& ivec, const unsigned& jstore ){ - plumed_dbg_assert( vecs->derivativesAreRequired() && usingLowMem() ); - // Set the task we want to reperform - setTaskToRecompute( ivec ); - // Reperform the task - vecs->performTask(); - // Store the derivatives - storeDerivativesLowMem( jstore ); - // Normalize the vector if it is required - std::vector<double> fake_buffer; - if( store_director ) normalizeVector( jstore, fake_buffer ); - // Clear up afterwards - vecs->clearAfterTask(); - -} - -bool StoreVectorsVessel::calculate( std::vector<double>& buffer ){ - if( !hard_cut ){ - storeValues( vecs->getCurrentPositionInTaskList(), buffer ); // Store the values of the components of the vector - if(!store_director) return true; - if( !usingLowMem() ) normalizeVector( vecs->getCurrentPositionInTaskList(), buffer ); - else normalizeVector( -1, buffer ); // Ensures vector components are normalized - } else { - if( getAction()->getElementValue(getAction()->getIndexOfWeight())>wtol ){ - storeValues( vecs->getCurrentPositionInTaskList(), buffer ); - if(!store_director) return true; - if( !usingLowMem() ) normalizeVector( vecs->getCurrentPositionInTaskList(), buffer ); - else normalizeVector( -1, buffer ); // Ensures vector components are normalized - } - } - return true; -} - -void StoreVectorsVessel::normalizeVector( const int& jstore, std::vector<double>& buffer ){ - unsigned myelem = vecs->getCurrentPositionInTaskList(); - bool lowmemory = usingLowMem(); double norm2=0.0, norm; - - if( (lowmemory && jstore<0) || !lowmemory ){ - for(unsigned icomp=0;icomp<ncomponents;++icomp) norm2 += getComponent( myelem, icomp ) * getComponent( myelem, icomp ); - norm=sqrt( norm2 ); - for(unsigned icomp=0;icomp<ncomponents;++icomp){ - myfvec[icomp]=getComponent( myelem, icomp ); - setComponent( myelem, icomp, getComponent( myelem, icomp ) / norm ); - } - } else { - for(unsigned icomp=0;icomp<ncomponents;++icomp){ - myfvec[icomp] = vecs->getElementValue( 5+icomp ); norm2 += myfvec[icomp] * myfvec[icomp]; - } - norm=sqrt( norm2 ); - } - double norm3=norm2*norm, weight = 1.0 / norm, wdf = -1.0 / norm3; - - if( !lowmemory && vecs->derivativesAreRequired() ) { - plumed_dbg_assert( jstore<getAction()->getFullNumberOfTasks() ); - for(unsigned ider=0;ider<getNumberOfDerivatives(myelem);++ider){ - double comp2=0.0; unsigned ibuf = myelem * ncomponents * getNumberOfDerivativeSpacesPerComponent() + 1 + ider; - for(unsigned jcomp=0;jcomp<ncomponents;++jcomp){ - //comp2 += myfvec[jcomp]*getBufferElement(ibuf); - ibuf += getNumberOfDerivativeSpacesPerComponent(); - } - ibuf = bufstart + myelem * ncomponents * getNumberOfDerivativeSpacesPerComponent() + 1 + ider; - for(unsigned jcomp=0;jcomp<ncomponents;++jcomp){ - buffer[ibuf] = weight*buffer[ibuf] + wdf*comp2*myfvec[jcomp]; - // setBufferElement( ibuf, weight*getBufferElement(ibuf) + wdf*comp2*myfvec[jcomp] ); - ibuf += getNumberOfDerivativeSpacesPerComponent(); - } - } - } else if( jstore>0 && vecs->derivativesAreRequired() ) { - unsigned maxder = vecs->getNumberOfDerivatives(); - for(unsigned ider=0;ider<getNumberOfDerivatives(jstore);++ider){ - double comp2=0.0; unsigned ibuf = jstore * ncomponents * maxder + ider; - for(unsigned jcomp=0;jcomp<ncomponents;++jcomp){ - comp2 += myfvec[jcomp]*getLocalDerivative( ibuf ); - ibuf += maxder; - } - ibuf = jstore * ncomponents * maxder + ider; - for(unsigned jcomp=0;jcomp<ncomponents;++jcomp){ - setLocalDerivative( ibuf, weight*getLocalDerivative( ibuf ) + wdf*comp2*myfvec[jcomp] ); - ibuf += maxder; - } - } - } -} - -void StoreVectorsVessel::chainRuleForComponent( const unsigned& icolv, const unsigned& jin, const unsigned& jout, const unsigned& base_cv_no, - const double& weight, multicolvar::MultiColvarFunction* funcout ){ - plumed_dbg_assert( vecs->derivativesAreRequired() ); - - if( usingLowMem() ){ - unsigned ibuf = ( icolv*ncomponents + jin ) * getAction()->getNumberOfDerivatives(); - for(unsigned ider=0;ider<getNumberOfDerivatives(icolv);++ider){ - funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( icolv, ider ), weight*getLocalDerivative(ibuf+ider) ); - } - } else { - unsigned ibuf = (icolv*ncomponents + jin ) * getNumberOfDerivativeSpacesPerComponent() + 1; - for(unsigned ider=0;ider<getNumberOfDerivatives(icolv);++ider){ - //funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( icolv, ider ), weight*getBufferElement(ibuf+ider) ); - } - } -} - -void StoreVectorsVessel::chainRuleForVector( const unsigned& icolv, const unsigned& jout, const unsigned& base_cv_no, - const std::vector<double>& df, multicolvar::MultiColvarFunction* funcout ){ - plumed_dbg_assert( vecs->derivativesAreRequired() ); - - chainRule( icolv, df ); - for(unsigned ider=0;ider<getNumberOfDerivatives(icolv);++ider){ - funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( icolv, ider ), getFinalDerivative(ider) ); - } -} - -} -} diff --git a/src/crystallization/StoreVectorsVessel.h b/src/crystallization/StoreVectorsVessel.h deleted file mode 100644 index d44c0ae499327713cda0ff61b175ba223a56538c..0000000000000000000000000000000000000000 --- a/src/crystallization/StoreVectorsVessel.h +++ /dev/null @@ -1,74 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013,2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#ifndef __PLUMED_crystallization_StoreVectorsVessel_h -#define __PLUMED_crystallization_StoreVectorsVessel_h - -#include "tools/DynamicList.h" -#include "vesselbase/StoreDataVessel.h" - -namespace PLMD { - -namespace crystallization { - -class VectorMultiColvar; - -class StoreVectorsVessel : public vesselbase::StoreDataVessel { -friend class VectorMultiColvar; -private: -/// We want to store the director rather than the value - bool store_director; - unsigned ncomponents; - std::vector<double> myfvec; - VectorMultiColvar* vecs; - void normalizeVector( const int&, std::vector<double>& ); -public: - static void registerKeywords( Keywords& keys ); -/// Constructor - StoreVectorsVessel( const vesselbase::VesselOptions& ); -/// This turns on the full use of this action for storage - void usedInFunction( const bool& ); -/// This makes sure vectors are normalized (they are already stored) - bool calculate( std::vector<double>& buffer ); -/// This reperforms a calculation - void recompute( const unsigned& , const unsigned& ); -/// This does nothing - std::string description(){ return ""; } -/// Get the orientation of the ith vector - void getVector( const unsigned& , std::vector<double>& ); -/// Chain rule for component - void chainRuleForComponent( const unsigned& , const unsigned& , const unsigned& jout, const unsigned& , const double& , multicolvar::MultiColvarFunction* ); -/// Chain rule for whole vector - void chainRuleForVector( const unsigned& , const unsigned& , const unsigned& , const std::vector<double>& , multicolvar::MultiColvarFunction* ); -}; - -inline -void StoreVectorsVessel::getVector( const unsigned& imol, std::vector<double>& vec ){ - plumed_dbg_assert( vec.size()==getNumberOfComponents() ); - for(unsigned i=0;i<getNumberOfComponents();++i) vec[i]=getComponent( imol, i ); -} - - - -} -} -#endif - diff --git a/src/crystallization/Tetrahedral.cpp b/src/crystallization/Tetrahedral.cpp index bac2cb483cae229325ad92c113378c3af2a03ed2..886075a556fb74ca2b26bb1d0e26b33a7cea5489 100644 --- a/src/crystallization/Tetrahedral.cpp +++ b/src/crystallization/Tetrahedral.cpp @@ -50,8 +50,7 @@ public: static void registerKeywords( Keywords& keys ); Tetrahedral(const ActionOptions&); // active methods: - virtual double compute(); - Vector getCentralAtom(); + virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } }; @@ -99,8 +98,7 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double Tetrahedral::compute(){ - weightHasDerivatives=true; +double Tetrahedral::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){ double value=0, norm=0, dfunc; Vector distance; // Calculate the coordination number @@ -108,8 +106,8 @@ double Tetrahedral::compute(){ double sw, sp1, sp2, sp3, sp4; double sp1c, sp2c, sp3c, sp4c, r3, r5, tmp; double d2, t1, t2, t3, t4, tt1, tt2, tt3, tt4; - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPosition(0), getPosition(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); d2 = distance.modulo2(); if( d2<rcut2 ){ sw = switchingFunction.calculateSqr( d2, dfunc ); @@ -139,32 +137,26 @@ double Tetrahedral::compute(){ myder[2] = (tt1-(distance[2]*t1)) + (-tt2-(distance[2]*t2)) + (-tt3-(distance[2]*t3)) + (tt4-(distance[2]*t4)); value += sw*tmp; fder = (+dfunc)*tmp*distance + sw*myder; - addAtomsDerivatives( 0, -fder ); - addAtomsDerivatives( i, +fder ); + myatoms.addAtomsDerivatives( 1, 0, -fder ); + myatoms.addAtomsDerivatives( 1, i, +fder ); // Tens is a constructor that you build by taking the vector product of two vectors (remember the scalars!) - addBoxDerivatives( Tensor(distance,-fder) ); + myatoms.addBoxDerivatives( 1, Tensor(distance,-fder) ); norm += sw; - addAtomsDerivativeOfWeight( 0, (-dfunc)*distance ); - addAtomsDerivativeOfWeight( i, (+dfunc)*distance ); - addBoxDerivativesOfWeight( (-dfunc)*Tensor(distance,distance) ); + myatoms.addAtomsDerivatives( 0, 0, (-dfunc)*distance ); + myatoms.addAtomsDerivatives( 0, i, (+dfunc)*distance ); + myatoms.addBoxDerivatives( 0, (-dfunc)*Tensor(distance,distance) ); } } - setElementValue(0, value); setElementValue(1, norm ); + myatoms.setValue(1, value); myatoms.setValue(0, norm ); // values -> der of... value [0], weight[1], x coord [2], y, z... [more magic] - updateActiveAtoms(); quotientRule( 0, 1, 0 ); clearDerivativesAfterTask(1); - // Weight doesn't really have derivatives (just use the holder for convenience) - weightHasDerivatives=false; setElementValue( 1, 1.0 ); + updateActiveAtoms( myatoms ); myatoms.getUnderlyingMultiValue().quotientRule( 1, 0, 1 ); + myatoms.getUnderlyingMultiValue().clear(0); myatoms.setValue( 0, 1.0 ); return value / norm; // this is equivalent to getting an "atomic" CV } -Vector Tetrahedral::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - } } diff --git a/src/crystallization/VectorMean.cpp b/src/crystallization/VectorMean.cpp index 2afa504fbbc3c0227d9aa392abc4918de62cd6ea..64c1927014970844564478f04cd044b22123d5e5 100644 --- a/src/crystallization/VectorMean.cpp +++ b/src/crystallization/VectorMean.cpp @@ -29,15 +29,13 @@ namespace PLMD { namespace crystallization { class VectorMean : public vesselbase::FunctionVessel { -private: - unsigned ncomp, vstart, wnum; public: static void registerKeywords( Keywords& keys ); static void reserveKeyword( Keywords& keys ); VectorMean( const vesselbase::VesselOptions& da ); std::string function_description(); void resize(); - bool calculate( std::vector<double>& buffer ); + bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ); void finish( const std::vector<double>& buffer ); }; @@ -56,15 +54,6 @@ void VectorMean::reserveKeyword( Keywords& keys ){ VectorMean::VectorMean( const vesselbase::VesselOptions& da ) : FunctionVessel(da) { - usetol=true; - multicolvar::ActionVolume* vg=dynamic_cast<multicolvar::ActionVolume*>( getAction() ); - if( vg ){ - ncomp = getAction()->getNumberOfQuantities() - 2; - vstart=1; wnum=ncomp+1; - } else { - vstart=5; wnum=1; - ncomp = getAction()->getNumberOfQuantities() - 5; - } } std::string VectorMean::function_description(){ @@ -72,7 +61,7 @@ std::string VectorMean::function_description(){ } void VectorMean::resize(){ - if( ncomp==0 ) ncomp=getAction()->getNumberOfQuantities() - 5; + unsigned ncomp=getAction()->getNumberOfQuantities() - 2; if( getAction()->derivativesAreRequired() ){ unsigned nder=getAction()->getNumberOfDerivatives(); @@ -84,36 +73,34 @@ void VectorMean::resize(){ } } -bool VectorMean::calculate( std::vector<double>& buffer ){ - double weight=getAction()->getElementValue(wnum); - unsigned nder=getAction()->getNumberOfDerivatives(); - plumed_dbg_assert( weight>=getTolerance() ); - // bool addval = addValueUsingTolerance( 0, weight ); +bool VectorMean::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ){ + unsigned ncomp=getAction()->getNumberOfQuantities()-2, nder=getAction()->getNumberOfDerivatives(); + + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); buffer[bufstart] += weight; - if( diffweight ) getAction()->chainRuleForElementDerivatives( 0, wnum, 1.0, bufstart, buffer ); + if( diffweight ) myvals.chainRule( 0, 0, 1, 0, 1.0, bufstart, buffer ); for(unsigned i=0;i<ncomp;++i){ - double colvar=getAction()->getElementValue( vstart + i ); + double colvar=myvals.get(2+i); buffer[bufstart + (1+i)*(1+nder)] += weight*colvar; - // addValueIgnoringTolerance( 1 + i, weight*colvar ); - getAction()->chainRuleForElementDerivatives( 1+i, vstart+i, weight, bufstart, buffer ); - if( diffweight ) getAction()->chainRuleForElementDerivatives( 1+i, wnum, colvar, bufstart, buffer ); + myvals.chainRule( 2+i, 1+i, 1, 0, weight, bufstart, buffer ); + if( diffweight ) myvals.chainRule( 0, 1+i, 1, 0, colvar, bufstart, buffer ); } return true; } void VectorMean::finish( const std::vector<double>& buffer ){ - double sum=0, ww=buffer[bufstart]; // getFinalValue(0); + unsigned ncomp=getAction()->getNumberOfQuantities()-2; + double sum=0, ww=buffer[bufstart]; unsigned nder=getAction()->getNumberOfDerivatives(); for(unsigned i=0;i<ncomp;++i){ double tmp = buffer[bufstart+(nder+1)*(i+1)] / ww; sum+=tmp*tmp; } - double tw = 1.0 / sqrt(sum); - setOutputValue( sqrt(sum) ); + double tw = 1.0 / sqrt(sum); setOutputValue( sqrt(sum) ); if( !getAction()->derivativesAreRequired() ) return; for(unsigned icomp=0;icomp<ncomp;++icomp){ - double tmp = buffer[(icomp+1)*(1+nder)] / ww; // getFinalValue(icomp+1) / ww; + double tmp = buffer[(icomp+1)*(1+nder)] / ww; unsigned bstart = bufstart + (1+icomp)*(nder+1) + 1; for(unsigned jder=0;jder<nder;++jder) addDerivativeToFinalValue( jder, (tw*tmp/ww)*( buffer[bstart + jder] - tmp*buffer[bufstart + 1 + jder] ) ); } diff --git a/src/crystallization/VectorMultiColvar.cpp b/src/crystallization/VectorMultiColvar.cpp index 627e65e41838afe755df914ef53cb285bc84d7c0..414cf8962cb9a162cdac30b540d191e8bd37744e 100644 --- a/src/crystallization/VectorMultiColvar.cpp +++ b/src/crystallization/VectorMultiColvar.cpp @@ -32,169 +32,180 @@ void VectorMultiColvar::registerKeywords( Keywords& keys ){ VectorMultiColvar::VectorMultiColvar(const ActionOptions& ao): PLUMED_MULTICOLVAR_INIT(ao), -firstcall(false), -vecs(NULL) +store_director(true), +firstcall(false) { setLowMemOption(true); } -void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp, const bool& comp, const int& nat ){ - // Store number of derivatives and if vectors are complex - ncomponents = ncomp; complexvec=comp; - if(complexvec) dervec.resize( 2*ncomponents ); - else dervec.resize( ncomponents ); +void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp, const int& nat ){ + // Store number of derivatives + ncomponents = ncomp; // Read in the atoms if we are using multicolvar reading int natoms=nat; readAtoms( natoms ); // Create the store vector object - std::string param; vesselbase::VesselOptions da("","",0,param,this); - Keywords keys; StoreVectorsVessel::registerKeywords( keys ); - vesselbase::VesselOptions da2(da,keys); - vecs = new StoreVectorsVessel(da2); - // Add the vessel to the base - addVessel(vecs); - // Read in any vessels - readVesselKeywords(); +// std::string param; vesselbase::VesselOptions da("","",0,param,this); +// Keywords keys; StoreVectorsVessel::registerKeywords( keys ); +// vesselbase::VesselOptions da2(da,keys); +// vecs = new StoreVectorsVessel(da2); +// // Add the vessel to the base +// addVessel(vecs); +// // Read in any vessels +// readVesselKeywords(); // Resize a holder for the derivatives of the norm of the vector } void VectorMultiColvar::doNotCalculateDirector(){ - vecs->store_director=false; + store_director=false; // Need a sanity check in here so that you don't use the same instance of Q4 to calcualte vectors and directors } -double VectorMultiColvar::doCalculation(){ +double VectorMultiColvar::doCalculation( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ){ // Now calculate the vector - calculateVector(); + calculateVector( myatoms ); // Sort out the active derivatives - updateActiveAtoms(); + updateActiveAtoms( myatoms ); // Now calculate the norm of the vector (this is what we return here) - double norm=0, inorm; - if(complexvec){ - for(unsigned i=0;i<ncomponents;++i) norm += getComponent(i)*getComponent(i) + getImaginaryComponent(i)*getImaginaryComponent(i); - norm=sqrt(norm); inorm = 1.0 / norm; - for(unsigned i=0;i<ncomponents;++i){ dervec[i] = inorm*getComponent(i); dervec[ncomponents+i] = inorm*getImaginaryComponent(i); } - } else { - for(unsigned i=0;i<ncomponents;++i) norm += getComponent(i)*getComponent(i); - norm=sqrt(norm); inorm = 1.0 / norm; - for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*getComponent(i); - } - + double norm=0; + for(unsigned i=0;i<ncomponents;++i) norm += myatoms.getValue(2+i)*myatoms.getValue(2+i); + norm=sqrt(norm); + if( !doNotCalculateDerivatives() ){ - if( usingLowMem() ){ - vecs->storeDerivativesLowMem( 0 ); - vecs->chainRule( 0, dervec ); - } else { - //vecs->storeDerivativesHighMem( getCurrentPositionInTaskList() ); - vecs->chainRule( getCurrentPositionInTaskList(), dervec ); + double inorm = 1.0 / norm; std::vector<double> dervec( ncomponents ); + for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*myatoms.getValue(2+i); + + vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue(); + for(unsigned j=0;j<myvals.getNumberActive();++j){ + unsigned jder=myvals.getActiveIndex(j); + for(unsigned i=0;i<ncomponents;++i) myvals.addDerivative( 1, jder, dervec[i]*myvals.getDerivative( 2+i, jder ) ); } - - // Add derivatives to base multicolvars - Vector tmpd; - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned k=atoms_with_derivatives[i]; - tmpd[0]=vecs->getFinalDerivative(3*i+0); - tmpd[1]=vecs->getFinalDerivative(3*i+1); - tmpd[2]=vecs->getFinalDerivative(3*i+2); - MultiColvarBase::addAtomsDerivatives( 0, k, tmpd ); - } - unsigned vvbase=3*atoms_with_derivatives.getNumberActive(); Tensor tmpv; - for(unsigned i=0;i<3;++i){ - for(unsigned j=0;j<3;++j){ - tmpv(i,j) = vecs->getFinalDerivative( vvbase+3*i+j ); - } - } - MultiColvarBase::addBoxDerivatives( 0, tmpv ); } + // if(complexvec){ + // for(unsigned i=0;i<ncomponents;++i) norm += getComponent(i)*getComponent(i) + getImaginaryComponent(i)*getImaginaryComponent(i); + // norm=sqrt(norm); inorm = 1.0 / norm; + // for(unsigned i=0;i<ncomponents;++i){ dervec[i] = inorm*getComponent(i); dervec[ncomponents+i] = inorm*getImaginaryComponent(i); } + // } else { + // for(unsigned i=0;i<ncomponents;++i) norm += getComponent(i)*getComponent(i); + // norm=sqrt(norm); inorm = 1.0 / norm; + // for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*getComponent(i); + // } + + // if( !doNotCalculateDerivatives() ){ + // if( usingLowMem() ){ + // vecs->storeDerivativesLowMem( 0 ); + // vecs->chainRule( 0, dervec ); + // } else { + // //vecs->storeDerivativesHighMem( getCurrentPositionInTaskList() ); + // vecs->chainRule( getCurrentPositionInTaskList(), dervec ); + // } + + // // Add derivatives to base multicolvars + // Vector tmpd; + // for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ + // unsigned k=atoms_with_derivatives[i]; + // tmpd[0]=vecs->getFinalDerivative(3*i+0); + // tmpd[1]=vecs->getFinalDerivative(3*i+1); + // tmpd[2]=vecs->getFinalDerivative(3*i+2); + // MultiColvarBase::addAtomsDerivatives( 0, k, tmpd ); + // } + // unsigned vvbase=3*atoms_with_derivatives.getNumberActive(); Tensor tmpv; + // for(unsigned i=0;i<3;++i){ + // for(unsigned j=0;j<3;++j){ + // tmpv(i,j) = vecs->getFinalDerivative( vvbase+3*i+j ); + // } + // } + // MultiColvarBase::addBoxDerivatives( 0, tmpv ); + // } return norm; } -vesselbase::StoreDataVessel* VectorMultiColvar::buildDataStashes( const bool& allow_wcutoff, const double& wtol ){ - // Build everyting for the multicolvar - vesselbase::StoreDataVessel* vsv=MultiColvarBase::buildDataStashes( allow_wcutoff, wtol ); - if( allow_wcutoff ) vsv->setHardCutoffOnWeight( wtol ); - // Resize the variable - vecs->resize(); - // And make sure we set up the vector storage correctly - vv1.resize( 1 ); vv2.resize( getNumberOfQuantities() - 5 ); - // And return - return vsv; -} - -void VectorMultiColvar::getValueForTask( const unsigned& iatom, std::vector<double>& vals ){ - plumed_dbg_assert( vecs && vals.size()==(getNumberOfQuantities()-4) ); - MultiColvarBase::getValueForTask( iatom, vv1 ); vecs->getVector( iatom, vv2 ); - vals[0]=vv1[0]; for(unsigned i=0;i<vv2.size();++i) vals[i+1]=vv2[i]; -} - -void VectorMultiColvar::addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func ){ - if( usingLowMem() ){ - vecs->recompute( iatom, 1 ); - for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( 1, j, 5+j, base_cv_no, weight, func ); - } else { - for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( iatom, j, 5+j, base_cv_no, weight, func ); - } -} - -void VectorMultiColvar::finishWeightedAverageCalculation( multicolvar::MultiColvarFunction* func ){ - // And calculate the norm of the vector - double norm=0, inorm; std::vector<unsigned> tmpindices( 1 + func->getNumberOfDerivatives() ); - if(complexvec){ - for(unsigned i=0;i<ncomponents;++i){ - // Calculate average vector - func->quotientRule(5+i, 1, 5+i); func->quotientRule(5+ncomponents+i, 1, 5+ncomponents+i); - // Calculate length of vector - norm += func->getElementValue(5+i)*func->getElementValue(5+i) + func->getElementValue(5+ncomponents+i)*func->getElementValue(5+ncomponents+i); - } - norm=sqrt(norm); inorm = 1.0 / norm; - for(unsigned i=0;i<ncomponents;++i){ - dervec[i] = inorm*func->getElementValue(5+i); dervec[ncomponents+i] = inorm*func->getElementValue(5+ncomponents+i); - } - func->getIndexList( 1, 0, func->getNumberOfDerivatives(), tmpindices ); - unsigned nder = func->getNumberOfDerivatives(); - for(unsigned i=0;i<tmpindices[0];++i){ - unsigned ind = tmpindices[1+i]; - for(unsigned j=0;j<ncomponents;++j){ - func->addElementDerivative( ind, dervec[j]*func->getElementDerivative(nder*(5+j) + ind) ); - func->addElementDerivative( ind, dervec[ncomponents+j]*func->getElementDerivative(nder*(5+ncomponents+j) + ind) ); - } - } - } else { - for(unsigned i=0;i<ncomponents;++i){ - // Calculate average vector - func->quotientRule(5+i, 1, 5+i); - // Calculate length of vector - norm += func->getElementValue(5+i)*func->getElementValue(5+i); - } - norm=sqrt(norm); inorm = 1.0 / norm; - for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*func->getElementValue(5+i); - func->getIndexList( 1, 0, func->getNumberOfDerivatives(), tmpindices ); - // And set derivatives given magnitude of the vector - unsigned nder = func->getNumberOfDerivatives(); - for(unsigned i=0;i<tmpindices[0];++i){ - unsigned ind = tmpindices[1+i]; - for(unsigned j=0;j<ncomponents;++j){ - func->addElementDerivative( ind, dervec[j]*func->getElementDerivative(nder*(5+j) + ind) ); - } - } - } - func->setElementValue( 0, norm ); -} - -void VectorMultiColvar::addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, - const std::vector<double>& der, multicolvar::MultiColvarFunction* func ){ - if( usingLowMem() ){ - if(jstore==1){ - if(firstcall){ vecs->recompute( iatom, jstore ); firstcall=false; } - vecs->chainRuleForVector( jstore, 0, base_cv_no, der, func ); - } else { - vecs->recompute( iatom, jstore ); - vecs->chainRuleForVector( jstore, 0, base_cv_no, der, func ); - } - } else { - vecs->chainRuleForVector( iatom, 0, base_cv_no, der, func ); - } -} +// vesselbase::StoreDataVessel* VectorMultiColvar::buildDataStashes( const bool& allow_wcutoff, const double& wtol ){ +// // Build everyting for the multicolvar +// vesselbase::StoreDataVessel* vsv=MultiColvarBase::buildDataStashes( allow_wcutoff, wtol ); +// if( allow_wcutoff ) vsv->setHardCutoffOnWeight( wtol ); +// // Resize the variable +// vecs->resize(); +// // And make sure we set up the vector storage correctly +// vv1.resize( 1 ); vv2.resize( getNumberOfQuantities() - 5 ); +// // And return +// return vsv; +// } +// +// void VectorMultiColvar::getValueForTask( const unsigned& iatom, std::vector<double>& vals ){ +// plumed_dbg_assert( vecs && vals.size()==(getNumberOfQuantities()-4) ); +// MultiColvarBase::getValueForTask( iatom, vv1 ); vecs->getVector( iatom, vv2 ); +// vals[0]=vv1[0]; for(unsigned i=0;i<vv2.size();++i) vals[i+1]=vv2[i]; +// } + +// void VectorMultiColvar::addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func ){ +// if( usingLowMem() ){ +// vecs->recompute( iatom, 1 ); +// for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( 1, j, 5+j, base_cv_no, weight, func ); +// } else { +// for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( iatom, j, 5+j, base_cv_no, weight, func ); +// } +// } + +// void VectorMultiColvar::finishWeightedAverageCalculation( multicolvar::MultiColvarFunction* func ){ +// // And calculate the norm of the vector +// double norm=0, inorm; std::vector<unsigned> tmpindices( 1 + func->getNumberOfDerivatives() ); +// if(complexvec){ +// for(unsigned i=0;i<ncomponents;++i){ +// // Calculate average vector +// func->quotientRule(5+i, 1, 5+i); func->quotientRule(5+ncomponents+i, 1, 5+ncomponents+i); +// // Calculate length of vector +// norm += func->getElementValue(5+i)*func->getElementValue(5+i) + func->getElementValue(5+ncomponents+i)*func->getElementValue(5+ncomponents+i); +// } +// norm=sqrt(norm); inorm = 1.0 / norm; +// for(unsigned i=0;i<ncomponents;++i){ +// dervec[i] = inorm*func->getElementValue(5+i); dervec[ncomponents+i] = inorm*func->getElementValue(5+ncomponents+i); +// } +// func->getIndexList( 1, 0, func->getNumberOfDerivatives(), tmpindices ); +// unsigned nder = func->getNumberOfDerivatives(); +// for(unsigned i=0;i<tmpindices[0];++i){ +// unsigned ind = tmpindices[1+i]; +// for(unsigned j=0;j<ncomponents;++j){ +// func->addElementDerivative( ind, dervec[j]*func->getElementDerivative(nder*(5+j) + ind) ); +// func->addElementDerivative( ind, dervec[ncomponents+j]*func->getElementDerivative(nder*(5+ncomponents+j) + ind) ); +// } +// } +// } else { +// for(unsigned i=0;i<ncomponents;++i){ +// // Calculate average vector +// func->quotientRule(5+i, 1, 5+i); +// // Calculate length of vector +// norm += func->getElementValue(5+i)*func->getElementValue(5+i); +// } +// norm=sqrt(norm); inorm = 1.0 / norm; +// for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*func->getElementValue(5+i); +// func->getIndexList( 1, 0, func->getNumberOfDerivatives(), tmpindices ); +// // And set derivatives given magnitude of the vector +// unsigned nder = func->getNumberOfDerivatives(); +// for(unsigned i=0;i<tmpindices[0];++i){ +// unsigned ind = tmpindices[1+i]; +// for(unsigned j=0;j<ncomponents;++j){ +// func->addElementDerivative( ind, dervec[j]*func->getElementDerivative(nder*(5+j) + ind) ); +// } +// } +// } +// func->setElementValue( 0, norm ); +// } + +// void VectorMultiColvar::addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, +// const std::vector<double>& der, multicolvar::MultiColvarFunction* func ){ +// if( usingLowMem() ){ +// if(jstore==1){ +// if(firstcall){ vecs->recompute( iatom, jstore ); firstcall=false; } +// vecs->chainRuleForVector( jstore, 0, base_cv_no, der, func ); +// } else { +// vecs->recompute( iatom, jstore ); +// vecs->chainRuleForVector( jstore, 0, base_cv_no, der, func ); +// } +// } else { +// vecs->chainRuleForVector( iatom, 0, base_cv_no, der, func ); +// } +// } void VectorMultiColvar::addForcesOnAtoms( const std::vector<double>& inforces ){ plumed_dbg_assert( inforces.size()==getNumberOfDerivatives() ); @@ -204,25 +215,25 @@ void VectorMultiColvar::addForcesOnAtoms( const std::vector<double>& inforces ){ setForcesOnAtoms( oldforces ); } -void VectorMultiColvar::copyElementsToBridgedColvar( multicolvar::BridgedMultiColvarFunction* func ){ - MultiColvarBase::copyElementsToBridgedColvar( func ); - - for(unsigned icomp=5;icomp<getNumberOfQuantities();++icomp){ - func->setElementValue( icomp-4, getElementValue(icomp) ); - unsigned nbase = icomp * getNumberOfDerivatives(); - unsigned nbasev = (icomp-4) * func->getNumberOfDerivatives(); - for(unsigned jatom=0;jatom<atoms_with_derivatives.getNumberActive();++jatom){ - unsigned n=atoms_with_derivatives[jatom], nx=nbase + 3*n, ny=nbasev + 3*n; - func->addElementDerivative( ny+0, getElementDerivative(nx+0) ); - func->addElementDerivative( ny+1, getElementDerivative(nx+1) ); - func->addElementDerivative( ny+2, getElementDerivative(nx+2) ); - } - unsigned nwvir=nbase + 3*getNumberOfAtoms(), nwvirv=nbasev + 3*getNumberOfAtoms(); - for(unsigned k=0;k<9;++k){ - func->addElementDerivative( nwvirv, getElementDerivative(nwvir) ); nwvir++; nwvirv++; - } - } -} +// void VectorMultiColvar::copyElementsToBridgedColvar( multicolvar::BridgedMultiColvarFunction* func ){ +// MultiColvarBase::copyElementsToBridgedColvar( func ); +// +// for(unsigned icomp=5;icomp<getNumberOfQuantities();++icomp){ +// func->setElementValue( icomp-4, getElementValue(icomp) ); +// unsigned nbase = icomp * getNumberOfDerivatives(); +// unsigned nbasev = (icomp-4) * func->getNumberOfDerivatives(); +// for(unsigned jatom=0;jatom<atoms_with_derivatives.getNumberActive();++jatom){ +// unsigned n=atoms_with_derivatives[jatom], nx=nbase + 3*n, ny=nbasev + 3*n; +// func->addElementDerivative( ny+0, getElementDerivative(nx+0) ); +// func->addElementDerivative( ny+1, getElementDerivative(nx+1) ); +// func->addElementDerivative( ny+2, getElementDerivative(nx+2) ); +// } +// unsigned nwvir=nbase + 3*getNumberOfAtoms(), nwvirv=nbasev + 3*getNumberOfAtoms(); +// for(unsigned k=0;k<9;++k){ +// func->addElementDerivative( nwvirv, getElementDerivative(nwvir) ); nwvir++; nwvirv++; +// } +// } +// } } } diff --git a/src/crystallization/VectorMultiColvar.h b/src/crystallization/VectorMultiColvar.h index f5921f10c46042187321d127eb774ae2c7e5aa41..e0324a27383193aa7bfce83204d9d7c08e4b8288 100644 --- a/src/crystallization/VectorMultiColvar.h +++ b/src/crystallization/VectorMultiColvar.h @@ -24,62 +24,56 @@ #include "tools/Matrix.h" #include "multicolvar/MultiColvar.h" -#include "StoreVectorsVessel.h" namespace PLMD { namespace crystallization { class VectorMultiColvar : public multicolvar::MultiColvar { -friend class StoreVectorsVessel; friend class OrientationSphere; friend class VolumeGradientBase; private: -/// Are the vectors complex - bool complexvec; +/// Are we storing the director of the vector of the vector + bool store_director; /// Used to make sure central atom position is only calculated /// once when using orientation sphere bool firstcall; /// How many components does the vector have unsigned ncomponents; -/// This object stores the vectors - StoreVectorsVessel* vecs; -/// This is a tempory vector that is used to store derivatives - std::vector<double> dervec; /// These are tempory vectors that are used to store values and directors std::vector<double> vv1, vv2; protected: /// Set the dimensionality of the vector - void setVectorDimensionality( const unsigned&, const bool&, const int& ); -/// Add some value to the ith component of the vector - void addComponent( const unsigned&, const double& ); -/// Get the ith component - double getComponent( const unsigned& ) const ; -/// Set the ith component - void setComponent( const unsigned&, const double& ); -/// Add derivatives of ith component of vector with repect to jth atom - void addAtomsDerivative( const unsigned&, const unsigned&, const Vector& ); -/// Add atomic derivatives to all components of matrix (note iatom is treated literally here - cf above) - void addAtomDerivativeToAllRealComponents( const unsigned& iatom, const std::vector<double>& vec, const Vector& avec ); -/// Add derivatives of ith component of vector with respect to the box - void addBoxDerivatives( const unsigned&, const Tensor& ); -/// Add box derivatives to all components of matrix - void addBoxDerivativesToAllRealComponents( const std::vector<double>& vec, const Tensor& avec ); -/// Add some value to the imaginary part of the ith component of the vector - void addImaginaryComponent( const unsigned&, const double& ); -/// Get the ith component - double getImaginaryComponent( const unsigned& ) const ; -/// Set the ith component - void setImaginaryComponent( const unsigned&, const double& ); -/// Add derivatives of the imaginary part of the ith component of vector with repect to jth atom - void addImaginaryAtomsDerivative( const unsigned&, const unsigned&, const Vector& ); -/// Add atomic derivatives to all components of matrix (note iatom is treated literally here - cf above) - void addAtomDerivativeToAllImagComponents( const unsigned& iatom, const std::vector<double>& vec, const Vector& avec ); -/// Add derivatives of the imaginary part of the ith component of vector with respect to the box - void addImaginaryBoxDerivatives( const unsigned&, const Tensor& ); -/// Add box derivatives to all components of matrix - void addBoxDerivativesToAllImagComponents( const std::vector<double>& vec, const Tensor& avec ); -/// This can be used to accumulate derivative from a store of vectors - void accumulateDerivativesFromVector( const unsigned& ivec, const unsigned& base_cv_no, const double& weight, StoreVectorsVessel* vectors ); + void setVectorDimensionality( const unsigned&, const int& ); +// /// Add some value to the ith component of the vector +// void addComponent( const unsigned&, const double& ); +// /// Get the ith component +// double getComponent( const unsigned& ) const ; +// /// Set the ith component +// void setComponent( const unsigned&, const double& ); +// /// Add derivatives of ith component of vector with repect to jth atom +// void addAtomsDerivative( const unsigned&, const unsigned&, const Vector& ); +// /// Add atomic derivatives to all components of matrix (note iatom is treated literally here - cf above) +// void addAtomDerivativeToAllRealComponents( const unsigned& iatom, const std::vector<double>& vec, const Vector& avec ); +// /// Add derivatives of ith component of vector with respect to the box +// void addBoxDerivatives( const unsigned&, const Tensor& ); +// /// Add box derivatives to all components of matrix +// void addBoxDerivativesToAllRealComponents( const std::vector<double>& vec, const Tensor& avec ); +// /// Add some value to the imaginary part of the ith component of the vector +// void addImaginaryComponent( const unsigned&, const double& ); +// /// Get the ith component +// double getImaginaryComponent( const unsigned& ) const ; +// /// Set the ith component +// void setImaginaryComponent( const unsigned&, const double& ); +// /// Add derivatives of the imaginary part of the ith component of vector with repect to jth atom +// void addImaginaryAtomsDerivative( const unsigned&, const unsigned&, const Vector& ); +// /// Add atomic derivatives to all components of matrix (note iatom is treated literally here - cf above) +// void addAtomDerivativeToAllImagComponents( const unsigned& iatom, const std::vector<double>& vec, const Vector& avec ); +// /// Add derivatives of the imaginary part of the ith component of vector with respect to the box +// void addImaginaryBoxDerivatives( const unsigned&, const Tensor& ); +// /// Add box derivatives to all components of matrix +// void addBoxDerivativesToAllImagComponents( const std::vector<double>& vec, const Tensor& avec ); +// /// This can be used to accumulate derivative from a store of vectors +// void accumulateDerivativesFromVector( const unsigned& ivec, const unsigned& base_cv_no, const double& weight, StoreVectorsVessel* vectors ); /// Used in vector average to add forces from vector the the forces from here void addForcesOnAtoms( const std::vector<double>& inforces ); public: @@ -89,32 +83,32 @@ public: /// The norm of a vector is not periodic virtual bool isPeriodic(){ return false; } /// Calculate the multicolvar - double doCalculation(); + double doCalculation( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ); /// This shouldn't do anything - double compute(){ plumed_error(); } + double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){ plumed_error(); } /// Calculate the vector - virtual void calculateVector()=0; + virtual void calculateVector( multicolvar::AtomValuePack& myatoms )=0; /// Get the number of components in the vector unsigned getNumberOfComponentsInVector() const ; /// Get the number of quantities we are calculating per step unsigned getNumberOfQuantities(); /// Create places to store the data - vesselbase::StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol ); +// vesselbase::StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol ); /// Get the vector - void getValueForTask( const unsigned& iatom, std::vector<double>& vals ); +// void getValueForTask( const unsigned& iatom, std::vector<double>& vals ); /// Used to accumulate values - void addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func ); +// void addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func ); /// Used for calculating weighted averages - void finishWeightedAverageCalculation( multicolvar::MultiColvarFunction* func ); +// void finishWeightedAverageCalculation( multicolvar::MultiColvarFunction* func ); /// Used in functions to add derivatives to the orientation vector - void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, - const std::vector<double>& der, multicolvar::MultiColvarFunction* func ); +// void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, +// const std::vector<double>& der, multicolvar::MultiColvarFunction* func ); /// Can we differentiate the orientation - yes we can the multicolvar is a vector bool hasDifferentiableOrientation() const { return true; } /// This makes sure we are not calculating the director when we do LocalAverage virtual void doNotCalculateDirector(); /// Used by ActionVolume - void copyElementsToBridgedColvar( multicolvar::BridgedMultiColvarFunction* func ); +// void copyElementsToBridgedColvar( multicolvar::BridgedMultiColvarFunction* func ); }; inline @@ -122,71 +116,70 @@ unsigned VectorMultiColvar::getNumberOfComponentsInVector() const { return ncomponents; } -inline -void VectorMultiColvar::addComponent( const unsigned& icomp, const double& val ){ - plumed_dbg_assert( icomp<ncomponents ); - addElementValue( 5 + icomp, val ); -} - -inline -void VectorMultiColvar::setComponent( const unsigned& icomp, const double& val ){ - plumed_dbg_assert( icomp<ncomponents ); - setElementValue( 5 + icomp, val ); -} - -inline -double VectorMultiColvar::getComponent( const unsigned& icomp ) const { - plumed_dbg_assert( icomp<ncomponents ); - return getElementValue( 5 + icomp ); -} - - -inline -void VectorMultiColvar::addAtomsDerivative( const unsigned& icomp, const unsigned& jatom, const Vector& der ){ - plumed_dbg_assert( icomp<ncomponents && jatom<getNAtoms() ); - MultiColvarBase::addAtomsDerivatives( 5 + icomp, current_atoms[jatom], der ); -} - -inline -void VectorMultiColvar::addBoxDerivatives( const unsigned& icomp, const Tensor& vir ){ - plumed_dbg_assert( icomp<ncomponents ); - MultiColvarBase::addBoxDerivatives( 5 + icomp, vir ); -} - -inline -void VectorMultiColvar::addImaginaryComponent( const unsigned& icomp, const double& val ){ - plumed_dbg_assert( icomp<ncomponents && complexvec ); - addElementValue( 5 + ncomponents + icomp, val ); -} - -inline -void VectorMultiColvar::setImaginaryComponent( const unsigned& icomp, const double& val ){ - plumed_dbg_assert( icomp<ncomponents && complexvec ); - setElementValue( 5 + ncomponents + icomp, val ); -} - -inline -double VectorMultiColvar::getImaginaryComponent( const unsigned& icomp ) const { - plumed_dbg_assert( icomp<ncomponents && complexvec ); - return getElementValue( 5 + ncomponents + icomp ); -} - -inline -void VectorMultiColvar::addImaginaryAtomsDerivative( const unsigned& icomp, const unsigned& jatom, const Vector& der){ - plumed_dbg_assert( icomp<ncomponents && complexvec && jatom<getNAtoms() ); - MultiColvarBase::addAtomsDerivatives( 5 + ncomponents + icomp, current_atoms[jatom], der ); -} - -inline -void VectorMultiColvar::addImaginaryBoxDerivatives( const unsigned& icomp, const Tensor& vir ){ - plumed_dbg_assert( icomp<ncomponents && complexvec ); - MultiColvarBase::addBoxDerivatives( 5 + ncomponents + icomp, vir ); -} +// inline +// void VectorMultiColvar::addComponent( const unsigned& icomp, const double& val ){ +// plumed_dbg_assert( icomp<ncomponents ); +// addElementValue( 5 + icomp, val ); +// } +// +// inline +// void VectorMultiColvar::setComponent( const unsigned& icomp, const double& val ){ +// plumed_dbg_assert( icomp<ncomponents ); +// setElementValue( 5 + icomp, val ); +// } +// +// inline +// double VectorMultiColvar::getComponent( const unsigned& icomp ) const { +// plumed_dbg_assert( icomp<ncomponents ); +// return getElementValue( 5 + icomp ); +// } +// +// +// inline +// void VectorMultiColvar::addAtomsDerivative( const unsigned& icomp, const unsigned& jatom, const Vector& der ){ +// plumed_dbg_assert( icomp<ncomponents && jatom<getNAtoms() ); +// MultiColvarBase::addAtomsDerivatives( 5 + icomp, current_atoms[jatom], der ); +// } + +// inline +// void VectorMultiColvar::addBoxDerivatives( const unsigned& icomp, const Tensor& vir ){ +// plumed_dbg_assert( icomp<ncomponents ); +// MultiColvarBase::addBoxDerivatives( 5 + icomp, vir ); +// } +// +// inline +// void VectorMultiColvar::addImaginaryComponent( const unsigned& icomp, const double& val ){ +// plumed_dbg_assert( icomp<ncomponents && complexvec ); +// addElementValue( 5 + ncomponents + icomp, val ); +// } +// +// inline +// void VectorMultiColvar::setImaginaryComponent( const unsigned& icomp, const double& val ){ +// plumed_dbg_assert( icomp<ncomponents && complexvec ); +// setElementValue( 5 + ncomponents + icomp, val ); +// } +// +// inline +// double VectorMultiColvar::getImaginaryComponent( const unsigned& icomp ) const { +// plumed_dbg_assert( icomp<ncomponents && complexvec ); +// return getElementValue( 5 + ncomponents + icomp ); +// } +// +// inline +// void VectorMultiColvar::addImaginaryAtomsDerivative( const unsigned& icomp, const unsigned& jatom, const Vector& der){ +// plumed_dbg_assert( icomp<ncomponents && complexvec && jatom<getNAtoms() ); +// MultiColvarBase::addAtomsDerivatives( 5 + ncomponents + icomp, current_atoms[jatom], der ); +// } +// +// inline +// void VectorMultiColvar::addImaginaryBoxDerivatives( const unsigned& icomp, const Tensor& vir ){ +// plumed_dbg_assert( icomp<ncomponents && complexvec ); +// MultiColvarBase::addBoxDerivatives( 5 + ncomponents + icomp, vir ); +// } inline unsigned VectorMultiColvar::getNumberOfQuantities(){ - if( complexvec ) return 5 + 2*ncomponents; - return 5 + ncomponents; + return 2 + ncomponents; } } diff --git a/src/crystallization/VectorSum.cpp b/src/crystallization/VectorSum.cpp index 0e4d75292afc7808b14464f802041f0c4c1f46d4..f12e098f988bd470e7d47e4ee6ae10c85bd01ad2 100644 --- a/src/crystallization/VectorSum.cpp +++ b/src/crystallization/VectorSum.cpp @@ -29,15 +29,13 @@ namespace PLMD { namespace crystallization { class VectorSum : public vesselbase::FunctionVessel { -private: - unsigned ncomp, vstart, wnum; public: static void registerKeywords( Keywords& keys ); static void reserveKeyword( Keywords& keys ); VectorSum( const vesselbase::VesselOptions& da ); std::string function_description(); void resize(); - bool calculate( std::vector<double>& buffer ); + bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ); void finish( const std::vector<double>& buffer ); }; @@ -56,15 +54,6 @@ void VectorSum::reserveKeyword( Keywords& keys ){ VectorSum::VectorSum( const vesselbase::VesselOptions& da ) : FunctionVessel(da) { - usetol=true; - multicolvar::ActionVolume* vg=dynamic_cast<multicolvar::ActionVolume*>( getAction() ); - if( vg ){ - ncomp = getAction()->getNumberOfQuantities() - 2; - vstart=1; wnum=ncomp+1; - } else { - vstart=5; wnum=1; - ncomp = getAction()->getNumberOfQuantities() - 5; - } } std::string VectorSum::function_description(){ @@ -72,39 +61,39 @@ std::string VectorSum::function_description(){ } void VectorSum::resize(){ - if( ncomp==0 ) ncomp=getAction()->getNumberOfQuantities() - 5; + unsigned ncomp=getAction()->getNumberOfQuantities() - 2; if( getAction()->derivativesAreRequired() ){ unsigned nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*(ncomp+1) ); + resizeBuffer( (1+nder)*ncomp ); setNumberOfDerivatives( nder ); } else { setNumberOfDerivatives(0); - resizeBuffer(ncomp+1); + resizeBuffer(ncomp); } } -bool VectorSum::calculate( std::vector<double>& buffer ){ - double weight=getAction()->getElementValue(wnum); - unsigned nder=getAction()->getNumberOfDerivatives(); +bool VectorSum::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ){ + unsigned ncomp=getAction()->getNumberOfQuantities()-2, nder=getAction()->getNumberOfDerivatives(); + + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); - // bool addval = addValueUsingTolerance( 0, weight ); buffer[bufstart] += weight; - if( diffweight ) getAction()->chainRuleForElementDerivatives( 0, wnum, 1.0, bufstart, buffer ); for(unsigned i=0;i<ncomp;++i){ - double colvar=getAction()->getElementValue( vstart + i ); - buffer[bufstart + (1+i)*(1+nder)] += weight*colvar; - // addValueIgnoringTolerance( 1 + i, weight*colvar ); - getAction()->chainRuleForElementDerivatives( 1+i, vstart+i, weight, bufstart, buffer ); - if( diffweight ) getAction()->chainRuleForElementDerivatives( 1+i, wnum, colvar, bufstart, buffer ); + double colvar=myvals.get(2+i); + buffer[bufstart + i*(1+nder)] += weight*colvar; + myvals.chainRule( 2+i, i, 1, 0, weight, bufstart, buffer ); + if( diffweight ) myvals.chainRule( 0, i, 1, 0, colvar, bufstart, buffer ); } return true; } void VectorSum::finish( const std::vector<double>& buffer ){ + unsigned ncomp=getAction()->getNumberOfQuantities()-2; + double sum=0; unsigned nder=getAction()->getNumberOfDerivatives(); for(unsigned i=0;i<ncomp;++i){ - double tmp = buffer[bufstart+(nder+1)*(i+1)]; // getFinalValue(i+1); + double tmp = buffer[bufstart+(nder+1)*i]; sum+=tmp*tmp; } double tw = 1.0 / sqrt(sum); @@ -112,8 +101,8 @@ void VectorSum::finish( const std::vector<double>& buffer ){ if( !getAction()->derivativesAreRequired() ) return; for(unsigned icomp=0;icomp<ncomp;++icomp){ - double tmp = buffer[(icomp+1)*(1+nder)]; // getFinalValue(icomp+1); - unsigned bstart = bufstart + (1+icomp)*(nder+1) + 1; + double tmp = buffer[icomp*(1+nder)]; + unsigned bstart = bufstart + icomp*(nder+1) + 1; for(unsigned jder=0;jder<nder;++jder) addDerivativeToFinalValue( jder, tw*tmp*buffer[bstart + jder] ); } } diff --git a/src/manyrestraints/ManyRestraintsBase.cpp b/src/manyrestraints/ManyRestraintsBase.cpp index 05aa13bd21231d42d8015a25a6fd8e35ad9d3cef..f2bc0b9981e9042c25e2bc5d9afe0016ee2a1fc6 100644 --- a/src/manyrestraints/ManyRestraintsBase.cpp +++ b/src/manyrestraints/ManyRestraintsBase.cpp @@ -46,6 +46,7 @@ ActionWithInputVessel(ao) // Read in the vessel we are action on readArgument("bridge"); aves=dynamic_cast<ActionWithVessel*>( getDependencies()[0] ); + plumed_assert( getDependencies().size()==1 && aves ); log.printf(" adding restraints on variables calculated by %s action with label %s\n", aves->getName().c_str(),aves->getLabel().c_str()); @@ -64,16 +65,26 @@ void ManyRestraintsBase::doJobsRequiredBeforeTaskList(){ ActionWithValue::clearDerivatives(); } -void ManyRestraintsBase::applyChainRuleForDerivatives( const double& df ){ - // Value (this could be optimized more -- GAT) - for(unsigned i=0;i<aves->getNumberOfDerivatives();++i){ - setElementDerivative( i, df*aves->getElementDerivative(i) ); - } - // And weights - unsigned nder=aves->getNumberOfDerivatives(); - for(unsigned i=0;i<aves->getNumberOfDerivatives();++i){ - setElementDerivative( nder+i, aves->getElementDerivative(nder+i) ); - } +void ManyRestraintsBase::transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){ + outvals.setValue( 0, invals.get(0) ); + + // Get the potential + double dval, val=calcPotential( invals.get(1), dval ); + + if( val>getTolerance() ){ + outvals.setValue( 1, val ); + for(unsigned i=0;i<invals.getNumberActive();++i){ + unsigned jder=invals.getActiveIndex(i); + outvals.addDerivative( 1, jder, dval*invals.getDerivative( 1, jder ) ); + } + + // Now update the outvals derivatives lists + outvals.emptyActiveMembers(); + for(unsigned j=0;j<invals.getNumberActive();++j) outvals.updateIndex( invals.getActiveIndex(j) ); + outvals.sortActiveList(); + return; + } + outvals.setValue( 1, 0.0 ); } void ManyRestraintsBase::apply(){ diff --git a/src/manyrestraints/ManyRestraintsBase.h b/src/manyrestraints/ManyRestraintsBase.h index 8ab405ee233f667d86c47f2763d75f15232de031..468e01508690def8f0b60a05d0e74e2f65fea503 100644 --- a/src/manyrestraints/ManyRestraintsBase.h +++ b/src/manyrestraints/ManyRestraintsBase.h @@ -40,27 +40,26 @@ class ManyRestraintsBase : private: /// Pointer to underlying action with vessel vesselbase::ActionWithVessel* aves; -protected: -/// Get the value of the current cv - double getValue(); -/// Get the weight of the current cv - double getWeight(); -/// Apply the chain rule to calculate the derivatives - void applyChainRuleForDerivatives( const double& df ); public: static void registerKeywords( Keywords& keys ); ManyRestraintsBase(const ActionOptions&); bool isPeriodic(){ return false; } unsigned getNumberOfDerivatives(); /// Routines that have to be defined so as not to have problems with virtual methods - void deactivate_task(){}; + void deactivate_task( const unsigned & task_index ){}; /// Don't actually clear the derivatives when this is called from plumed main. /// They are calculated inside another action and clearing them would be bad void clearDerivatives(){} /// Do jobs required before tasks are undertaken void doJobsRequiredBeforeTaskList(); +/// This actually does the calculation + void transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ); +/// Calculate the potential + virtual double calcPotential( const double& val, double& df )=0; // Calculate does nothing void calculate(){}; +/// This should never be called + void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ){ plumed_error(); } /// Deactivate task now does nothing void apply(); void applyBridgeForces( const std::vector<double>& bb ){ plumed_assert( bb.size()==0 ); } @@ -71,16 +70,6 @@ unsigned ManyRestraintsBase::getNumberOfDerivatives(){ return aves->getNumberOfDerivatives(); } -inline -double ManyRestraintsBase::getValue(){ - return aves->getElementValue(0); -} - -inline -double ManyRestraintsBase::getWeight(){ - return aves->getElementValue(1); -} - } } diff --git a/src/manyrestraints/UWalls.cpp b/src/manyrestraints/UWalls.cpp index c297b9ccd1db4eb7e39eabeb5af4e131181257f3..7292a7872853f4776c57393a961ec21865e0dbee 100644 --- a/src/manyrestraints/UWalls.cpp +++ b/src/manyrestraints/UWalls.cpp @@ -69,7 +69,7 @@ private: public: static void registerKeywords( Keywords& keys ); UWalls( const ActionOptions& ); - void performTask(); + double calcPotential( const double& val, double& df ); }; PLUMED_REGISTER_ACTION(UWalls,"UWALLS") @@ -95,23 +95,16 @@ ManyRestraintsBase(ao) checkRead(); } -void UWalls::performTask(){ - double value=getValue(); - double uscale = (value - at + offset)/eps; +double UWalls::calcPotential( const double& val, double& df ){ + double uscale = (val - at + offset)/eps; if( uscale > 0. ){ double power = pow( uscale, exp ); - double f = ( kappa / eps ) * exp * power / uscale; + df = ( kappa / eps ) * exp * power / uscale; - setElementValue( 0, kappa*power ); setElementValue( 1, getWeight() ); - // Add derivatives - applyChainRuleForDerivatives( f ); - - return; + return kappa*power; } - // We need do nothing more if this is not true - setElementValue( 1, 0.0 ); - return; + return 0.0; } } diff --git a/src/mapping/Mapping.cpp b/src/mapping/Mapping.cpp index 9dce33318f58fd43f23794008e6d05aaa83c7d11..25fc1a0dfd98f3849048d80f3d8c8d231bd0b312 100644 --- a/src/mapping/Mapping.cpp +++ b/src/mapping/Mapping.cpp @@ -189,32 +189,33 @@ void Mapping::calculateNumericalDerivatives( ActionWithValue* a ){ } } -void Mapping::mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ){ - unsigned cur = getCurrentTask(), frameno=ider*getNumberOfReferencePoints() + cur; - for(unsigned i=0;i<getNumberOfArguments();++i){ - buffer[start+ i*stride] += df*dfframes[frameno]*mymap->getArgumentDerivative(cur,i); - } +void Mapping::transferDerivatives( const unsigned& ider, const unsigned& fno, const unsigned& cur, vesselbase::MultiValue& myvals ){ + if( !derivativesAreRequired() ) return; + + unsigned frameno=fno*getNumberOfReferencePoints() + cur; + for(unsigned i=0;i<getNumberOfArguments();++i) myvals.addDerivative( ider, i, dfframes[frameno]*mymap->getArgumentDerivative(cur,i) ); + if( getNumberOfAtoms()>0 ){ Vector ader; Tensor tmpvir; tmpvir.zero(); - unsigned n=getNumberOfArguments(); + unsigned n=getNumberOfArguments(); for(unsigned i=0;i<getNumberOfAtoms();++i){ - ader=mymap->getAtomDerivatives( cur, i ); - buffer[start+n*stride] += df*dfframes[frameno]*ader[0]; n++; - buffer[start+n*stride] += df*dfframes[frameno]*ader[1]; n++; - buffer[start+n*stride] += df*dfframes[frameno]*ader[2]; n++; + ader=mymap->getAtomDerivatives( cur, i ); + myvals.addDerivative( ider, n, dfframes[frameno]*ader[0] ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*ader[1] ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*ader[2] ); n++; tmpvir += -1.0*Tensor( getPosition(i), ader ); } - Tensor vir; + Tensor vir; if( !mymap->getVirial( cur, vir ) ) vir=tmpvir; - buffer[start+n*stride] += df*dfframes[frameno]*vir(0,0); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(0,1); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(0,2); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(1,0); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(1,1); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(1,2); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(2,0); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(2,1); n++; - buffer[start+n*stride] += df*dfframes[frameno]*vir(2,2); + myvals.addDerivative( ider, n, dfframes[frameno]*vir(0,0) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(0,1) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(0,2) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(1,0) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(1,1) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(1,2) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(2,0) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(2,1) ); n++; + myvals.addDerivative( ider, n, dfframes[frameno]*vir(2,2) ); } } diff --git a/src/mapping/Mapping.h b/src/mapping/Mapping.h index f5e8a13f0bc97170cc5585a369e82755e5005439..25ab9dad96eb7d0dcb5d3eeb09dc8c8133338d1e 100644 --- a/src/mapping/Mapping.h +++ b/src/mapping/Mapping.h @@ -58,7 +58,9 @@ protected: /// Store the distance function void storeDistanceFunction( const unsigned& ifunc ); /// Get the value of the weight - double getWeight() const ; + double getWeight( const unsigned& weight ) const ; +/// Transfer the derivatives to a MultiValue object + void transferDerivatives( const unsigned& ider, const unsigned& fno, const unsigned& cur, vesselbase::MultiValue& myvals ); public: static void registerKeywords( Keywords& keys ); Mapping(const ActionOptions&); @@ -85,11 +87,7 @@ public: /// Get the name of the ith argument std::string getArgumentName( unsigned& iarg ); /// Get the value of the ith property for the current frame - double getPropertyValue( const unsigned& iprop ) const ; -/// Return the current value of the high dimensional function - double getCurrentHighDimFunctionValue( const unsigned& ider ) const ; -/// Perform chain rule for derivatives - void mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ); + double getPropertyValue( const unsigned& current, const unsigned& iprop ) const ; /// Stuff to do before we do the calculation void prepare(); /// Apply the forces @@ -131,20 +129,14 @@ std::string Mapping::getPropertyName( const unsigned& iprop ) const { } inline -double Mapping::getPropertyValue( const unsigned& iprop ) const { +double Mapping::getPropertyValue( const unsigned& cur, const unsigned& iprop ) const { plumed_dbg_assert( iprop<getNumberOfProperties() ); - return mymap->getPropertyValue( getCurrentTask(), iprop ); + return mymap->getPropertyValue( cur, iprop ); } inline -double Mapping::getWeight() const { - return mymap->getWeight( getCurrentTask() ); -} - -inline -double Mapping::getCurrentHighDimFunctionValue( const unsigned& ider ) const { - plumed_dbg_assert( ider<2 ); - return fframes[ider*getNumberOfReferencePoints() + getCurrentTask()]; +double Mapping::getWeight( const unsigned& current ) const { + return mymap->getWeight( current ); } inline diff --git a/src/mapping/PathBase.cpp b/src/mapping/PathBase.cpp index eeb4f98896597c2a136bdfbb2752def722e164cc..789edae8e310fcb4b3577b8aae1cf93eefa3b7db 100644 --- a/src/mapping/PathBase.cpp +++ b/src/mapping/PathBase.cpp @@ -55,11 +55,12 @@ void PathBase::calculate(){ runAllTasks(); } -void PathBase::performTask(){ +void PathBase::performTask( const unsigned& task_index, const unsigned& current, vesselbase::MultiValue& myvals ){ // Calculate the distance from the frame - double val=calculateDistanceFunction( getCurrentTask(), true ); + double val=calculateDistanceFunction( current, true ); // Put the element value in element zero - setElementValue( 1, val ); setElementValue( 0, 1.0 ); + myvals.setValue( 0, val ); myvals.setValue( 1, 1.0 ); + transferDerivatives( 0, 0, current, myvals ); return; } diff --git a/src/mapping/PathBase.h b/src/mapping/PathBase.h index 541c864dcc2f6d42379ed254201487056c527018..238a80d07b074e4984d4a02fb13733b31851a296 100644 --- a/src/mapping/PathBase.h +++ b/src/mapping/PathBase.h @@ -35,7 +35,7 @@ public: PathBase(const ActionOptions&); double getLambda(); void calculate(); - void performTask(); + void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ); double transformHD( const double& dist, double& df ); }; diff --git a/src/mapping/SpathVessel.cpp b/src/mapping/SpathVessel.cpp index ee157ca5d8cdd78f86c0aa98162b33a3927a2d1d..525244eb2fc36b68638ce0225554f98fe9d2a5d9 100644 --- a/src/mapping/SpathVessel.cpp +++ b/src/mapping/SpathVessel.cpp @@ -30,6 +30,7 @@ class SpathVessel : public vesselbase::FunctionVessel { private: bool foundoneclose; unsigned mycoordnumber; + unsigned nderiv; Mapping* mymap; public: static void registerKeywords( Keywords& keys ); @@ -37,7 +38,7 @@ public: SpathVessel( const vesselbase::VesselOptions& da ); std::string function_description(); void prepare(); - bool calculate( std::vector<double>& buffer ); + bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ); }; PLUMED_REGISTER_VESSEL(SpathVessel,"SPATH") @@ -58,7 +59,11 @@ FunctionVessel(da) plumed_massert( mymap, "SpathVessel can only be used with mappings"); // Retrieve the index of the property in the underlying mapping mycoordnumber=mymap->getPropertyIndex( getLabel() ); - usetol=true; norm=true; + usetol=true; norm=true; nderiv=mymap->getNumberOfDerivatives(); + + for(unsigned i=0;i<mymap->getFullNumberOfTasks();++i){ + if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); + } } std::string SpathVessel::function_description(){ @@ -69,9 +74,15 @@ void SpathVessel::prepare(){ foundoneclose=false; } -bool SpathVessel::calculate( std::vector<double>& buffer ){ - double pp=mymap->getPropertyValue( mycoordnumber ); - return addToBuffers( pp, 0.0, buffer ); +bool SpathVessel::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer ){ + double pp=mymap->getPropertyValue( current, mycoordnumber ), weight=myvals.get(0); + if( weight<getTolerance() ) return false; + buffer[bufstart] += weight*pp; buffer[bufstart+1+nderiv] += weight; + if( getAction()->derivativesAreRequired() ){ + myvals.chainRule( 0, 0, 1, 0, pp, bufstart, buffer ); + myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); + } + return true; } } diff --git a/src/mapping/ZpathVessel.cpp b/src/mapping/ZpathVessel.cpp index c01e52255d2c8f0619a062066ea1c196770ebfd9..c5ee11d54c8121a674a14ae5501cec3ec6c2de6b 100644 --- a/src/mapping/ZpathVessel.cpp +++ b/src/mapping/ZpathVessel.cpp @@ -34,7 +34,7 @@ public: static void reserveKeyword( Keywords& keys ); ZpathVessel( const vesselbase::VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); double finalTransform( const double& val, double& dv ); }; @@ -61,8 +61,8 @@ std::string ZpathVessel::function_description(){ return "the distance from the low-dimensional manifold"; } -bool ZpathVessel::calculate( std::vector<double>& buffer ){ - return addToBuffers( 1.0, 0.0, buffer ); +double ZpathVessel::calcTransform( const double& val, double& dv ){ + dv=0.0; return 1.0; } double ZpathVessel::finalTransform( const double& val, double& dv ){ diff --git a/src/multicolvar/ActionVolume.cpp b/src/multicolvar/ActionVolume.cpp index a51ba9e094bc55d790a7299eb94e5b79e625a430..2ef73aec2bce36a17fca94e101c9071ea730cddf 100644 --- a/src/multicolvar/ActionVolume.cpp +++ b/src/multicolvar/ActionVolume.cpp @@ -39,9 +39,9 @@ Action(ao), VolumeGradientBase(ao) { // Find number of quantities - if( getPntrToMultiColvar()->isDensity() ) nquantities=5; // Value + catom + weight - else if( getPntrToMultiColvar()->getNumberOfQuantities()==5 ) nquantities=5; // Value + catom + weight - else nquantities = 1 + 3 + getPntrToMultiColvar()->getNumberOfQuantities()-5 + 1; // Norm + catom + vector + weight + if( getPntrToMultiColvar()->isDensity() ) nquantities=2; // Value + weight + else if( getPntrToMultiColvar()->getNumberOfQuantities()==2 ) nquantities=2; // Value + weight + else nquantities = 1 + getPntrToMultiColvar()->getNumberOfQuantities()-2 + 1; // Norm + vector + weight // Output some nice information std::string functype=getPntrToMultiColvar()->getName(); @@ -61,13 +61,16 @@ VolumeGradientBase(ao) } } -void ActionVolume::calculateAllVolumes(){ - Vector catom_pos=getPntrToMultiColvar()->retrieveCentralAtomPos(); +void ActionVolume::calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals ){ + Vector catom_pos=getPntrToMultiColvar()->getCentralAtomPos( curr ); - double weight; Vector wdf; - weight=calculateNumberInside( catom_pos, bead, wdf ); - if( not_in ){ weight = 1.0 - weight; wdf *= -1.; } - setNumberInVolume( nquantities-1, weight, wdf ); + double weight; Vector wdf; Tensor vir; std::vector<Vector> refders( getNumberOfAtoms() ); + weight=calculateNumberInside( catom_pos, bead, wdf, vir, refders ); + if( not_in ){ + weight = 1.0 - weight; wdf *= -1.; vir *=-1; + for(unsigned i=0;i<refders.size();++i) refders[i]*=-1; + } + setNumberInVolume( 0, curr, weight, wdf, vir, refders, outvals ); } } diff --git a/src/multicolvar/ActionVolume.h b/src/multicolvar/ActionVolume.h index 72a40810ad06fb271e883935a3ae6f40afcf5125..10a459b341b19d594fd36fc20c409b03a0d93f1a 100644 --- a/src/multicolvar/ActionVolume.h +++ b/src/multicolvar/ActionVolume.h @@ -47,18 +47,14 @@ private: HistogramBead bead; protected: double getSigma() const ; - void addReferenceAtomDerivatives( const unsigned& iatom, const Vector& der ); - void addBoxDerivatives( const Tensor& vir ); public: static void registerKeywords( Keywords& keys ); ActionVolume(const ActionOptions&); /// Get the number of quantities that are calculated each time virtual unsigned getNumberOfQuantities(); /// Calculate whats in the volume - void calculateAllVolumes(); - virtual double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives )=0; - double getValueForTolerance(); - unsigned getIndexOfWeight(); + void calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals ); + virtual double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders )=0; unsigned getCentralAtomElementIndex(); }; @@ -72,28 +68,6 @@ double ActionVolume::getSigma() const { return sigma; } -inline -void ActionVolume::addReferenceAtomDerivatives( const unsigned& iatom, const Vector& der ){ - if( not_in ) VolumeGradientBase::addReferenceAtomDerivatives( nquantities-1, iatom, -1.0*der ); - else VolumeGradientBase::addReferenceAtomDerivatives( nquantities-1, iatom, der ); -} - -inline -void ActionVolume::addBoxDerivatives( const Tensor& vir ){ - if( not_in ) VolumeGradientBase::addBoxDerivatives( nquantities-1, -1.0*vir ); - else VolumeGradientBase::addBoxDerivatives( nquantities-1, vir ); -} - -inline -double ActionVolume::getValueForTolerance(){ - return getElementValue( nquantities-1 ); -} - -inline -unsigned ActionVolume::getIndexOfWeight(){ - return nquantities-1; -} - inline unsigned ActionVolume::getCentralAtomElementIndex(){ return 1; diff --git a/src/multicolvar/AdjacencyMatrixAction.cpp b/src/multicolvar/AdjacencyMatrixAction.cpp index eb9af257a1be05c6abf86cc8e2ecb7ecc458e069..0b2664b6467f8a0b8f802dc66befe025a004554b 100644 --- a/src/multicolvar/AdjacencyMatrixAction.cpp +++ b/src/multicolvar/AdjacencyMatrixAction.cpp @@ -37,8 +37,8 @@ Action(ao), MultiColvarFunction(ao), tmpdf(1) { + use_orient=false; if( keywords.exists("USE_ORIENTATION") ) parseFlag("USE_ORIENTATION",use_orient); - else use_orient=true; // Weight of this does have derivatives weightHasDerivatives=true; // Read in the switching function @@ -78,6 +78,9 @@ tmpdf(1) // Build atom lists buildAtomListWithPairs( true ); + + if( use_orient && getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) error("using orientation but no orientations in base colvars"); + // Build active elements array for(unsigned i=0;i<getFullNumberOfTasks();++i) active_elements.addIndexToList( i ); active_elements.setupMPICommunication( comm ); @@ -102,10 +105,6 @@ tmpdf(1) addVessel( mat ); // And resize everything resizeFunctions(); - - // One component for regular multicolvar and nelements for vectormulticolvar - unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities() - 5;; - orient0.resize( ncomp ); orient1.resize( ncomp ); } void AdjacencyMatrixAction::doJobsRequiredBeforeTaskList(){ @@ -118,22 +117,24 @@ void AdjacencyMatrixAction::doJobsRequiredBeforeTaskList(){ else dertime=true; } -void AdjacencyMatrixAction::calculateWeight(){ - Vector distance = getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(1) ); - double dfunc, sw = switchingFunction( getBaseColvarNumber(0),getBaseColvarNumber(1) ).calculate( distance.modulo(), dfunc ); - setElementValue(1,sw); +void AdjacencyMatrixAction::calculateWeight( AtomValuePack& myatoms ){ + Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ),getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( distance.modulo(), dfunc ); + myatoms.setValue(0,sw); } -double AdjacencyMatrixAction::compute(){ - active_elements.activate( getCurrentPositionInTaskList() ); +double AdjacencyMatrixAction::compute( const unsigned& tindex, AtomValuePack& myatoms ){ + active_elements.activate( tindex ); - double f_dot, dot_df; + double f_dot, dot_df; + unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities(); + std::vector<double> orient0(ncomp), orient1(ncomp); if( use_orient ){ - getVectorForBaseTask( 0, orient0 ); - getVectorForBaseTask( 1, orient1 ); + getVectorForTask( myatoms.getIndex(0), true, orient0 ); + getVectorForTask( myatoms.getIndex(1), true, orient1 ); double dot; dot=0; - for(unsigned k=0;k<orient0.size();++k) dot+=orient0[k]*orient1[k]; + for(unsigned k=2;k<orient0.size();++k) dot+=orient0[k]*orient1[k]; f_dot=0.5*( 1 + dot ); dot_df=0.5; // Add smac stuff here if required } else { @@ -141,43 +142,44 @@ double AdjacencyMatrixAction::compute(){ } // Retrieve the weight of the connection - double weight = getElementValue(1); + double weight = myatoms.getValue(0); if( dertime && !doNotCalculateDerivatives() ){ // Add contribution due to separation between atoms - Vector distance = getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(1) ); - double dfunc, sw = switchingFunction( getBaseColvarNumber(0), getBaseColvarNumber(1) ).calculate( distance.modulo(), dfunc ); - addCentralAtomsDerivatives( 0, 0, (-dfunc)*f_dot*distance ); - addCentralAtomsDerivatives( 1, 0, (dfunc)*f_dot*distance ); - MultiColvarBase::addBoxDerivatives( 0, (-dfunc)*f_dot*Tensor(distance,distance) ); + Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(0) ) ).calculate( distance.modulo(), dfunc ); + CatomPack atom0=getCentralAtomPackFromInput( myatoms.getIndex(0) ); + myatoms.addComDerivatives( 1, (-dfunc)*f_dot*distance, atom0 ); + CatomPack atom1=getCentralAtomPackFromInput( myatoms.getIndex(1) ); + + myatoms.addComDerivatives( 1, (dfunc)*f_dot*distance, atom1 ); + myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) ); // And derivatives of orientation if( use_orient ){ - for(unsigned k=0;k<orient0.size();++k){ + for(unsigned k=2;k<orient0.size();++k){ orient0[k]*=sw*dot_df; orient1[k]*=sw*dot_df; } - addOrientationDerivatives( 0, orient1 ); - addOrientationDerivatives( 1, orient0 ); + vesselbase::MultiValue myder0(0,0); getVectorDerivatives( myatoms.getIndex(0), true, myder0 ); + mergeVectorDerivatives( 1, 2, orient1.size(), myatoms.getIndex(0), orient1, myder0, myatoms ); + vesselbase::MultiValue myder1(0,0); getVectorDerivatives( myatoms.getIndex(1), true, myder1 ); + mergeVectorDerivatives( 1, 2, orient0.size(), myatoms.getIndex(1), orient0, myder1, myatoms ); } } return weight*f_dot; } -void AdjacencyMatrixAction::setMatrixIndexesForTask( const unsigned& ii ){ - unsigned icolv = active_elements[ii], tcode = getTaskCode( icolv ); - bool check = MultiColvarBase::setupCurrentAtomList( tcode ); - plumed_assert( check ); -} - void AdjacencyMatrixAction::retrieveMatrix( Matrix<double>& mymatrix ){ // Gather active elements in matrix if(!gathered) active_elements.mpi_gatherActiveMembers( comm ); gathered=true; - + + std::vector<unsigned> myatoms(2); std::vector<double> vals(2); for(unsigned i=0;i<active_elements.getNumberActive();++i){ - setMatrixIndexesForTask( i ); - unsigned j = current_atoms[1], k = current_atoms[0]; - mymatrix(k,j)=mymatrix(j,k)=getMatrixElement( i ); + decodeIndexToAtoms( getTaskCode(active_elements[i]), myatoms ); + unsigned j = myatoms[1], k = myatoms[0]; + mat->retrieveValue( active_elements[i], false, vals ); + mymatrix(k,j)=mymatrix(j,k)=vals[1]; } } @@ -192,26 +194,14 @@ void AdjacencyMatrixAction::retrieveAdjacencyLists( std::vector<unsigned>& nneig for(unsigned i=0;i<nneigh.size();++i) nneigh[i]=0; // And set up the adjacency list + std::vector<unsigned> myatoms(2); for(unsigned i=0;i<active_elements.getNumberActive();++i){ - setMatrixIndexesForTask( i ); - unsigned j = current_atoms[1], k = current_atoms[0]; + decodeIndexToAtoms( getTaskCode(active_elements[i]), myatoms ); + unsigned j = myatoms[1], k = myatoms[0]; adj_list(k,nneigh[k])=j; nneigh[k]++; adj_list(j,nneigh[j])=k; nneigh[j]++; } } -void AdjacencyMatrixAction::addDerivativesOnMatrixElement( const unsigned& ielem, const unsigned& jrow, const double& df, Matrix<double>& der ){ - plumed_dbg_assert( ielem<active_elements.getNumberActive() ); - tmpdf[0]=df; unsigned jelem=active_elements[ielem]; - - if( usingLowMem() ){ - mat->recompute( jelem, 0 ); mat->chainRule( 0, tmpdf ); - for(unsigned i=0;i<mat->getNumberOfDerivatives(0);++i) der( jrow, mat->getStoredIndex(0,i) ) += mat->getFinalDerivative(i); - } else { - mat->chainRule( jelem, tmpdf ); - for(unsigned i=0;i<mat->getNumberOfDerivatives(jelem);++i) der( jrow, mat->getStoredIndex(jelem,i) ) += mat->getFinalDerivative(i); - } -} - } } diff --git a/src/multicolvar/AdjacencyMatrixAction.h b/src/multicolvar/AdjacencyMatrixAction.h index eb0d3ee0a23713ec4067140c31135dc704ce06e5..e397e89c0a62a1f684695a9c682f7f10c4d394ad 100644 --- a/src/multicolvar/AdjacencyMatrixAction.h +++ b/src/multicolvar/AdjacencyMatrixAction.h @@ -40,7 +40,7 @@ private: /// This is the vessel that stores the adjacency matrix AdjacencyMatrixVessel* mat; /// Tempory vectors for storing vectors - std::vector<double> tmpdf, orient0, orient1; + std::vector<double> tmpdf; /// switching function Matrix<SwitchingFunction> switchingFunction; /// Which matrix elements have value @@ -57,15 +57,15 @@ protected: unsigned getNumberOfActiveMatrixElements(); /// Put the indices of the matrix elements in current atoms void setMatrixIndexesForTask( const unsigned& ii ); -/// Get an element of the adjacency matrix - double getMatrixElement( const unsigned& ielem ) const ; +/// Get the matrix elements that are active + unsigned getActiveMatrixElement( const unsigned& ival ) const ; /// Add derivatives to a matrix element void addDerivativesOnMatrixElement( const unsigned& ielem, const unsigned& jrow, const double& df, Matrix<double>& der ); public: static void registerKeywords( Keywords& keys ); AdjacencyMatrixAction(const ActionOptions&); - double compute(); - void calculateWeight(); + double compute( const unsigned& tindex, AtomValuePack& myatoms ); + void calculateWeight( AtomValuePack& myatoms ); void doJobsRequiredBeforeTaskList(); /// Finish the calculation virtual void completeCalculation()=0; @@ -81,13 +81,14 @@ unsigned AdjacencyMatrixAction::getNumberOfActiveMatrixElements(){ } inline -double AdjacencyMatrixAction::getMatrixElement( const unsigned& ielem ) const { - return mat->getComponent( active_elements[ielem], 0 ); +AdjacencyMatrixVessel* AdjacencyMatrixAction::getAdjacencyVessel(){ + return mat; } inline -AdjacencyMatrixVessel* AdjacencyMatrixAction::getAdjacencyVessel(){ - return mat; +unsigned AdjacencyMatrixAction::getActiveMatrixElement( const unsigned& ival ) const { + plumed_dbg_assert( ival<active_elements.getNumberActive() ); + return active_elements[ival]; } } diff --git a/src/multicolvar/AdjacencyMatrixVessel.cpp b/src/multicolvar/AdjacencyMatrixVessel.cpp index b80706788391419dab487bf24f6ba91a1770d845..44cab0b72e306d282c136b414178f23299daba7c 100644 --- a/src/multicolvar/AdjacencyMatrixVessel.cpp +++ b/src/multicolvar/AdjacencyMatrixVessel.cpp @@ -31,12 +31,10 @@ void AdjacencyMatrixVessel::registerKeywords( Keywords& keys ){ } AdjacencyMatrixVessel::AdjacencyMatrixVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da), -tmpdf(1) +StoreDataVessel(da) { function=dynamic_cast<AdjacencyMatrixAction*>( getAction() ); plumed_assert( function ); - completeSetup( 0, 1 ); nrows = function->getFullNumberOfTasks(); } void AdjacencyMatrixVessel::prepare(){ @@ -48,19 +46,6 @@ void AdjacencyMatrixVessel::setFinishedTrue(){ finished=true; } -void AdjacencyMatrixVessel::recompute( const unsigned& ivec, const unsigned& jstore ){ - plumed_dbg_assert( function->usingLowMem() && function->dertime ); - - // Set the task we want to reperform - setTaskToRecompute( ivec ); - // Reperform the task - if( function->dertime ){ - function->performTask(); - storeDerivativesLowMem( jstore ); - function->clearAfterTask(); - } -} - void AdjacencyMatrixVessel::finish( const std::vector<double>& buffer ){ if( !finished ){ finished=true; diff --git a/src/multicolvar/AdjacencyMatrixVessel.h b/src/multicolvar/AdjacencyMatrixVessel.h index 38c64e61d77d9418ee046aa9ed86f07df4d0d15c..c78b790e39d987bf61e55e16a7ff5af9651cee29 100644 --- a/src/multicolvar/AdjacencyMatrixVessel.h +++ b/src/multicolvar/AdjacencyMatrixVessel.h @@ -32,36 +32,22 @@ class AdjacencyMatrixAction; class AdjacencyMatrixVessel : public vesselbase::StoreDataVessel { friend class VectorMultiColvar; private: - unsigned nrows; /// Pointer to underlying action AdjacencyMatrixAction* function; /// Has the vessel been finished bool finished; -/// Tempory vector for chain rule - std::vector<double> tmpdf; public: static void registerKeywords( Keywords& keys ); /// Constructor AdjacencyMatrixVessel( const vesselbase::VesselOptions& ); /// Ensures that finish is set properly void prepare(); -/// This does nothing - std::string description(){ return ""; } -/// This recomputes the colvar - void recompute( const unsigned& ivec, const unsigned& jstore ); -/// Get the i,j th element of the matrix - double getElement( const unsigned& ivec ); /// Set the finished flag true void setFinishedTrue(); /// Finish the calculation void finish( const std::vector<double>& buffer ); }; -inline -double AdjacencyMatrixVessel::getElement( const unsigned& ivec ){ - return getComponent( ivec, 0 ); -} - } } #endif diff --git a/src/multicolvar/AlphaBeta.cpp b/src/multicolvar/AlphaBeta.cpp index 139cfa1d86b7de4033a282aa692e617c6adf00bd..085fd49c123d609300a0976aeb85ccc9365a2c5f 100644 --- a/src/multicolvar/AlphaBeta.cpp +++ b/src/multicolvar/AlphaBeta.cpp @@ -98,9 +98,8 @@ private: public: static void registerKeywords( Keywords& keys ); AlphaBeta(const ActionOptions&); - virtual double compute(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); bool isPeriodic(){ return false; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(AlphaBeta,"ALPHABETA") @@ -120,6 +119,10 @@ PLUMED_MULTICOLVAR_INIT(ao) int natoms=4; readAtoms( natoms ); // Resize target target.resize( getFullNumberOfTasks() ); + // Setup central atom indices + std::vector<bool> catom_ind(4, false); + catom_ind[1]=catom_ind[2]=true; + setAtomsForCentralAtom( catom_ind ); // Read in reference values unsigned ntarget=0; @@ -145,16 +148,15 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double AlphaBeta::compute(){ +double AlphaBeta::compute( const unsigned& tindex, AtomValuePack& myatoms ){ Vector d0,d1,d2; - d0=getSeparation(getPosition(1),getPosition(0)); - d1=getSeparation(getPosition(2),getPosition(1)); - d2=getSeparation(getPosition(3),getPosition(2)); + d0=getSeparation(myatoms.getPosition(1),myatoms.getPosition(0)); + d1=getSeparation(myatoms.getPosition(2),myatoms.getPosition(1)); + d2=getSeparation(myatoms.getPosition(3),myatoms.getPosition(2)); Vector dd0,dd1,dd2; PLMD::Torsion t; double value = t.compute(d0,d1,d2,dd0,dd1,dd2); - unsigned tindex = getCurrentPositionInTaskList(); double svalue = -0.5*sin(value-target[tindex]); double cvalue = 1.+cos(value-target[tindex]); @@ -163,21 +165,15 @@ double AlphaBeta::compute(){ dd2 *= svalue; value = 0.5*cvalue; - addAtomsDerivatives(0,dd0); - addAtomsDerivatives(1,dd1-dd0); - addAtomsDerivatives(2,dd2-dd1); - addAtomsDerivatives(3,-dd2); + myatoms.addAtomsDerivatives(1, 0,dd0); + myatoms.addAtomsDerivatives(1, 1,dd1-dd0); + myatoms.addAtomsDerivatives(1, 2,dd2-dd1); + myatoms.addAtomsDerivatives(1, 3,-dd2); - addBoxDerivatives (-(extProduct(d0,dd0)+extProduct(d1,dd1)+extProduct(d2,dd2))); + myatoms.addBoxDerivatives(1, -(extProduct(d0,dd0)+extProduct(d1,dd1)+extProduct(d2,dd2))); return value; } -Vector AlphaBeta::getCentralAtom(){ - addCentralAtomDerivatives( 1, 0.5*Tensor::identity() ); - addCentralAtomDerivatives( 2, 0.5*Tensor::identity() ); - return 0.5*( getPosition(1) + getPosition(2) ); -} - } } diff --git a/src/multicolvar/Angles.cpp b/src/multicolvar/Angles.cpp index 203d185f3c478188bb259371c4a719e73fcfd0c8..5d412c9fe8329f5751e6fcfc26c5816d9ce22edd 100644 --- a/src/multicolvar/Angles.cpp +++ b/src/multicolvar/Angles.cpp @@ -94,11 +94,10 @@ public: static void registerKeywords( Keywords& keys ); Angles(const ActionOptions&); /// Updates neighbor list - virtual double compute(); + virtual double compute( const unsigned& tindex, AtomValuePack& ); /// Returns the number of coordinates of the field - void calculateWeight(); + void calculateWeight( AtomValuePack& ); bool isPeriodic(){ return false; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(Angles,"ANGLES") @@ -165,48 +164,46 @@ use_sf(false) // And check everything has been read in correctly checkRead(); + // Setup stuff for central atom + std::vector<bool> catom_ind(3, false); catom_ind[0]=true; + setAtomsForCentralAtom( catom_ind ); } -void Angles::calculateWeight(){ - dij=getSeparation( getPosition(0), getPosition(2) ); - dik=getSeparation( getPosition(0), getPosition(1) ); - if(!use_sf){ setWeight(1.0); return; } +void Angles::calculateWeight( AtomValuePack& myatoms ){ + dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) ); + dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + if(!use_sf){ myatoms.setValue( 0, 1.0 ); return; } double w1, w2, dw1, dw2, wtot; double ldij = dij.modulo2(), ldik = dik.modulo2(); if( use_sf ){ - if( ldij>rcut2_1 || ldik>rcut2_2 ){ setWeight(0.0); return; } + if( ldij>rcut2_1 || ldik>rcut2_2 ){ myatoms.setValue(0,0.0); return; } } w1=sf1.calculateSqr( ldij, dw1 ); w2=sf2.calculateSqr( ldik, dw2 ); wtot=w1*w2; dw1*=w2; dw2*=w1; - setWeight( wtot ); - addAtomsDerivativeOfWeight( 1, dw2*dik ); - addAtomsDerivativeOfWeight( 0, -dw1*dij - dw2*dik ); - addAtomsDerivativeOfWeight( 2, dw1*dij ); - addBoxDerivativesOfWeight( (-dw1)*Tensor(dij,dij) + (-dw2)*Tensor(dik,dik) ); + myatoms.setValue( 0, wtot ); + myatoms.addAtomsDerivatives( 0, 1, dw2*dik ); + myatoms.addAtomsDerivatives( 0, 0, -dw1*dij - dw2*dik ); + myatoms.addAtomsDerivatives( 0, 2, dw1*dij ); + myatoms.addBoxDerivatives( 0, (-dw1)*Tensor(dij,dij) + (-dw2)*Tensor(dik,dik) ); } -double Angles::compute(){ +double Angles::compute( const unsigned& tindex, AtomValuePack& myatoms ){ Vector ddij,ddik; PLMD::Angle a; double angle=a.compute(dij,dik,ddij,ddik); // And finish the calculation - addAtomsDerivatives( 1, ddik ); - addAtomsDerivatives( 0, - ddik - ddij ); - addAtomsDerivatives( 2, ddij ); - addBoxDerivatives( -(Tensor(dij,ddij)+Tensor(dik,ddik)) ); + myatoms.addAtomsDerivatives( 1, 1, ddik ); + myatoms.addAtomsDerivatives( 1, 0, - ddik - ddij ); + myatoms.addAtomsDerivatives( 1, 2, ddij ); + myatoms.addBoxDerivatives( 1, -(Tensor(dij,ddij)+Tensor(dik,ddik)) ); return angle; } -Vector Angles::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - } } diff --git a/src/multicolvar/AtomValuePack.cpp b/src/multicolvar/AtomValuePack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a42dab9a8946ec6a60b8ffd7faf057f0e43689dd --- /dev/null +++ b/src/multicolvar/AtomValuePack.cpp @@ -0,0 +1,58 @@ +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Copyright (c) 2011-2014 The plumed team + (see the PEOPLE file at the root of the distribution for a list of names) + + See http://www.plumed-code.org for more information. + + This file is part of plumed, version 2. + + plumed is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + plumed is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with plumed. If not, see <http://www.gnu.org/licenses/>. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ +#include "AtomValuePack.h" +#include "CatomPack.h" + +namespace PLMD { +namespace multicolvar { + +AtomValuePack::AtomValuePack( vesselbase::MultiValue& vals, MultiColvarBase* mcolv ): +myvals(vals), +mycolv(mcolv) +{ + indices.resize( mycolv->getNumberOfDerivatives() ); +} + +void AtomValuePack::updateUsingIndices(){ + if( myvals.updateComplete() ) return; + myvals.emptyActiveMembers(); + for(unsigned i=0;i<natoms;++i){ + myvals.updateIndex( 3*indices[i] + 0 ); + myvals.updateIndex( 3*indices[i] + 1 ); + myvals.updateIndex( 3*indices[i] + 2 ); + } + unsigned nvir=3*mycolv->getNumberOfAtoms(); + for(unsigned i=0;i<9;++i) myvals.updateIndex( nvir + i ); + myvals.sortActiveList(); +} + +void AtomValuePack::addComDerivatives( const unsigned& ind, const Vector& der, CatomPack& catom_der ){ + for(unsigned ider=0;ider<catom_der.getNumberOfAtomsWithDerivatives();++ider){ + unsigned jder=3*catom_der.getIndex(ider); + myvals.addDerivative( ind, jder+0, catom_der.getDerivative(ider,0,der) ); + myvals.addDerivative( ind, jder+1, catom_der.getDerivative(ider,1,der) ); + myvals.addDerivative( ind, jder+2, catom_der.getDerivative(ider,2,der) ); + } +} + +} +} diff --git a/src/multicolvar/AtomValuePack.h b/src/multicolvar/AtomValuePack.h new file mode 100644 index 0000000000000000000000000000000000000000..ffe0bbe0f6be42e639b764ba71ca6cd2077b0b82 --- /dev/null +++ b/src/multicolvar/AtomValuePack.h @@ -0,0 +1,151 @@ +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Copyright (c) 2011-2014 The plumed team + (see the PEOPLE file at the root of the distribution for a list of names) + + See http://www.plumed-code.org for more information. + + This file is part of plumed, version 2. + + plumed is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + plumed is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with plumed. If not, see <http://www.gnu.org/licenses/>. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ +#ifndef __PLUMED_multicolvar_AtomValuePack_h +#define __PLUMED_multicolvar_AtomValuePack_h + +#include "vesselbase/MultiValue.h" +#include "MultiColvarBase.h" + +namespace PLMD { +namespace multicolvar { + +class CatomPack; + +class AtomValuePack { +private: +/// Copy of the values that we are adding to + vesselbase::MultiValue& myvals; +/// Copy of the underlying multicolvar + MultiColvarBase* mycolv; +/// Number of atoms at the moment + unsigned natoms; +/// Atom indices + std::vector<unsigned> indices; +public: + AtomValuePack( vesselbase::MultiValue& vals, MultiColvarBase* mcolv ); +/// Set the number of atoms + void setNumberOfAtoms( const unsigned& ); +/// Set the index for one of the atoms + void setIndex( const unsigned& , const unsigned& ); +/// + unsigned getIndex( const unsigned& j ) const ; +/// + unsigned getNumberOfAtoms() const ; +/// Get the position of the ith atom + Vector getPosition( const unsigned& ); +/// + void setValue( const unsigned& , const double& ); +/// + void addValue( const unsigned& ival, const double& vv ); +/// + double getValue( const unsigned& ) const ; +/// + void addDerivative( const unsigned& , const unsigned& , const double& ); +/// + void addAtomsDerivatives( const unsigned& , const unsigned& , const Vector& ); +/// + void addBoxDerivatives( const unsigned& , const Tensor& ); +/// + void updateUsingIndices(); +/// + void updateDynamicList(); +/// + void addComDerivatives( const unsigned& , const Vector& , CatomPack& ); +/// + vesselbase::MultiValue& getUnderlyingMultiValue(); +}; + +inline +void AtomValuePack::setNumberOfAtoms( const unsigned& nat ){ + natoms=nat; +} + +inline +unsigned AtomValuePack::getNumberOfAtoms() const { + return natoms; +} + +inline +void AtomValuePack::setIndex( const unsigned& j, const unsigned& ind ){ + plumed_dbg_assert( j<natoms ); indices[j]=ind; +} + +inline +unsigned AtomValuePack::getIndex( const unsigned& j ) const { + plumed_dbg_assert( j<natoms ); return indices[j]; +} + +inline +Vector AtomValuePack::getPosition( const unsigned& iatom ){ + plumed_dbg_assert( iatom<natoms ); + return mycolv->getPositionOfAtomForLinkCells( indices[iatom] ); +} + +inline +void AtomValuePack::setValue( const unsigned& ival, const double& vv ){ + myvals.setValue( ival, vv ); +} + +inline +void AtomValuePack::addValue( const unsigned& ival, const double& vv ){ + myvals.addValue( ival, vv ); +} + +inline +double AtomValuePack::getValue( const unsigned& ival ) const { + return myvals.get( ival ); +} + +inline +void AtomValuePack::addDerivative( const unsigned& ival, const unsigned& jder, const double& der ){ + myvals.addDerivative( ival, jder, der ); +} + +inline +void AtomValuePack::addAtomsDerivatives( const unsigned& ival, const unsigned& jder, const Vector& der ){ + plumed_dbg_assert( jder<natoms ); + myvals.addDerivative( ival, 3*indices[jder] + 0, der[0] ); + myvals.addDerivative( ival, 3*indices[jder] + 1, der[1] ); + myvals.addDerivative( ival, 3*indices[jder] + 2, der[2] ); +} + +inline +void AtomValuePack::addBoxDerivatives( const unsigned& ival , const Tensor& vir ){ + unsigned nvir=3*mycolv->getNumberOfAtoms(); + for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addDerivative( ival, nvir + 3*i+j, vir(i,j) ); +} + +inline +void AtomValuePack::updateDynamicList(){ + if( myvals.updateComplete() ) return; + myvals.updateDynamicList(); +} + +inline +vesselbase::MultiValue& AtomValuePack::getUnderlyingMultiValue(){ + return myvals; +} + +} +} +#endif + diff --git a/src/multicolvar/Bridge.cpp b/src/multicolvar/Bridge.cpp index 6a44ef6f5bb36d7c75a7b8846cd4d3b55b628916..21ed24ecdb48d138c053e2dde56c5dbee1fb5c8c 100644 --- a/src/multicolvar/Bridge.cpp +++ b/src/multicolvar/Bridge.cpp @@ -68,10 +68,9 @@ public: static void registerKeywords( Keywords& keys ); Bridge(const ActionOptions&); // active methods: - virtual double compute(); - void calculateWeight(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); + void calculateWeight( AtomValuePack& myatoms ); bool isPeriodic(){ return false; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(Bridge,"BRIDGE") @@ -99,6 +98,9 @@ PLUMED_MULTICOLVAR_INIT(ao) if( all_atoms.size()>0 ) ActionAtomistic::requestAtoms( all_atoms ); // Setup the multicolvar base setupMultiColvarBase(); + // Setup Central atom atoms + std::vector<bool> catom_ind(3, false); catom_ind[0]=true; + setAtomsForCentralAtom( catom_ind ); std::string sfinput,errors; parse("SWITCH",sfinput); if( sfinput.length()>0 ){ @@ -136,33 +138,28 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -void Bridge::calculateWeight(){ - Vector dij=getSeparation( getPosition(0), getPosition(2) ); +void Bridge::calculateWeight( AtomValuePack& myatoms ){ + Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) ); double ldij = dij.modulo2(); - if( ldij>rcut2 ) { setWeight(0); return; } + if( ldij>rcut2 ) { myatoms.setValue(0,0); return; } double dw, w=sf2.calculateSqr( ldij, dw ); - setWeight( w ); + myatoms.setValue( 0, w ); - addAtomsDerivativeOfWeight( 0, -dw*dij ); - addAtomsDerivativeOfWeight( 2, dw*dij ); - addBoxDerivativesOfWeight( (-dw)*Tensor(dij,dij) ); + myatoms.addAtomsDerivatives( 0, 0, -dw*dij ); + myatoms.addAtomsDerivatives( 0, 2, dw*dij ); + myatoms.addBoxDerivatives( 0, (-dw)*Tensor(dij,dij) ); } -double Bridge::compute(){ - Vector dik=getSeparation( getPosition(0), getPosition(1) ); +double Bridge::compute( const unsigned& tindex, AtomValuePack& myatoms ){ + Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dw, w=sf1.calculateSqr( dik.modulo2(), dw ); // And finish the calculation - addAtomsDerivatives( 0, -dw*dik ); - addAtomsDerivatives( 1, dw*dik ); - addBoxDerivatives( (-dw)*Tensor(dik,dik) ); + myatoms.addAtomsDerivatives( 1, 0, -dw*dik ); + myatoms.addAtomsDerivatives( 1, 1, dw*dik ); + myatoms.addBoxDerivatives( 1, (-dw)*Tensor(dik,dik) ); return w; } -Vector Bridge::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - } } diff --git a/src/multicolvar/BridgedMultiColvarFunction.cpp b/src/multicolvar/BridgedMultiColvarFunction.cpp index 4dfa3d47fcd5637fa7e64d4bca769c7309124033..1cdb192ef2183b9d40f3b9b953d417f77fff415e 100644 --- a/src/multicolvar/BridgedMultiColvarFunction.cpp +++ b/src/multicolvar/BridgedMultiColvarFunction.cpp @@ -46,106 +46,68 @@ MultiColvarBase(ao) if( checkNumericalDerivatives() ) mycolv->useNumericalDerivatives(); myBridgeVessel = mycolv->addBridgingVessel( this ); addDependency(mycolv); - weightHasDerivatives=true; + weightHasDerivatives=true; usespecies=mycolv->usespecies; // Number of tasks is the same as the number in the underlying MultiColvar for(unsigned i=0;i<mycolv->getFullNumberOfTasks();++i) addTaskToList( mycolv->getTaskCode(i) ); - // Do all setup stuff in MultiColvarBase - resizeLocalArrays(); } -void BridgedMultiColvarFunction::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ - mycolv->getIndexList( ntotal, jstore, maxder, indices ); -} - -void BridgedMultiColvarFunction::performTask(){ - atoms_with_derivatives.deactivateAll(); - - if( !myBridgeVessel->prerequisitsCalculated() ){ - mycolv->setTaskIndexToCompute( getCurrentPositionInTaskList() ); - mycolv->performTask(); +//void BridgedMultiColvarFunction::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ +// mycolv->getIndexList( ntotal, jstore, maxder, indices ); +//} + +void BridgedMultiColvarFunction::transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){ + completeTask( current, invals, outvals ); + + // Now update the outvals derivatives lists + outvals.emptyActiveMembers(); + if( mycolv->isDensity() ){ + for(unsigned j=0;j<3;++j) outvals.updateIndex( 3*current+j ); + for(unsigned j=invals.getNumberOfDerivatives()-9;j<invals.getNumberOfDerivatives();++j) outvals.updateIndex(j); } else { - + for(unsigned j=0;j<invals.getNumberActive();++j) outvals.updateIndex( invals.getActiveIndex(j) ); } - - completeTask(); - atoms_with_derivatives.updateActiveMembers(); + for(unsigned j=invals.getNumberOfDerivatives();j<outvals.getNumberOfDerivatives();++j) outvals.updateIndex( j ); + outvals.sortActiveList(); } -Vector BridgedMultiColvarFunction::retrieveCentralAtomPos(){ - if( atomsWithCatomDer.getNumberActive()==0 ){ - Vector cvec = mycolv->retrieveCentralAtomPos(); - - // Copy the value and derivatives from the MultiColvar - atomsWithCatomDer.emptyActiveMembers(); - for(unsigned i=0;i<3;++i){ - setElementValue( getCentralAtomElementIndex() + i, mycolv->getElementValue( mycolv->getCentralAtomElementIndex() + i ) ); - unsigned nbase = ( getCentralAtomElementIndex() + i)*getNumberOfDerivatives(); - unsigned nbas2 = ( mycolv->getCentralAtomElementIndex() + i )*mycolv->getNumberOfDerivatives(); - for(unsigned j=0;j<mycolv->atomsWithCatomDer.getNumberActive();++j){ - unsigned n=mycolv->atomsWithCatomDer[j], nx=3*n; atomsWithCatomDer.activate(n); - addElementDerivative(nbase + nx + 0, mycolv->getElementDerivative(nbas2 + nx + 0) ); - addElementDerivative(nbase + nx + 1, mycolv->getElementDerivative(nbas2 + nx + 1) ); - addElementDerivative(nbase + nx + 2, mycolv->getElementDerivative(nbas2 + nx + 2) ); - } - } - atomsWithCatomDer.updateActiveMembers(); // This can perhaps be faster - return cvec; - } - Vector cvec; - for(unsigned i=0;i<3;++i) cvec[i]=getElementValue(1+i); - return cvec; -} +/// These two functions (commented out one underneath) are needed and are a bit tricky +void BridgedMultiColvarFunction::performTask( const unsigned& taskIndex, const unsigned& current, vesselbase::MultiValue& myvals ){ + //atoms_with_derivatives.deactivateAll(); -void BridgedMultiColvarFunction::mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ){ - unsigned vstart=getNumberOfDerivatives()*ider; - // Merge atom derivatives - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned iatom=3*atoms_with_derivatives[i]; - buffer[start + iatom*stride ] += df*getElementDerivative(vstart+iatom); iatom++; - buffer[start + iatom*stride ] += df*getElementDerivative(vstart+iatom); iatom++; - buffer[start + iatom*stride ] += df*getElementDerivative(vstart+iatom); - } - // Merge virial derivatives - unsigned nvir=3*mycolv->getNumberOfAtoms(); - for(unsigned j=0;j<9;++j){ - buffer[start+nvir*stride] += df*getElementDerivative(vstart+nvir); nvir++; - } - // Merge local atom derivatives - for(unsigned j=0;j<getNumberOfAtoms();++j){ - buffer[start + stride*nvir] += df*getElementDerivative(vstart+nvir); nvir++; - buffer[start + stride*nvir] += df*getElementDerivative(vstart+nvir); nvir++; - buffer[start + stride*nvir] += df*getElementDerivative(vstart+nvir); nvir++; - } - plumed_dbg_assert( nvir==getNumberOfDerivatives() ); -} + // GAT this is for recomputing - this needs to work -- how? + if( !myBridgeVessel->prerequisitsCalculated() ){ + mycolv->performTask( taskIndex, current, myvals ); + } -void BridgedMultiColvarFunction::clearDerivativesAfterTask( const unsigned& ider ){ - unsigned vstart=getNumberOfDerivatives()*ider; - if( derivativesAreRequired() ){ - // Clear atom derivatives - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned iatom=vstart+3*atoms_with_derivatives[i]; - setElementDerivative( iatom, 0.0 ); iatom++; - setElementDerivative( iatom, 0.0 ); iatom++; - setElementDerivative( iatom, 0.0 ); - } - // Clear virial contribution - unsigned nvir=vstart+3*mycolv->getNumberOfAtoms(); - for(unsigned j=0;j<9;++j){ - setElementDerivative( nvir, 0.0 ); nvir++; - } - // Clear derivatives of local atoms - for(unsigned j=0;j<getNumberOfAtoms();++j){ - setElementDerivative( nvir, 0.0 ); nvir++; - setElementDerivative( nvir, 0.0 ); nvir++; - setElementDerivative( nvir, 0.0 ); nvir++; - } - plumed_dbg_assert( (nvir-vstart)==getNumberOfDerivatives() ); - } - // Clear values - thisval_wasset[ider]=false; setElementValue( ider, 0.0 ); thisval_wasset[ider]=false; + // completeTask( myvals, outvals ); -- also need this + //atoms_with_derivatives.updateActiveMembers(); } +// Vector BridgedMultiColvarFunction::retrieveCentralAtomPos(){ +// if( atomsWithCatomDer.getNumberActive()==0 ){ +// Vector cvec = mycolv->retrieveCentralAtomPos(); +// +// // Copy the value and derivatives from the MultiColvar +// atomsWithCatomDer.emptyActiveMembers(); +// for(unsigned i=0;i<3;++i){ +// setElementValue( getCentralAtomElementIndex() + i, mycolv->getElementValue( mycolv->getCentralAtomElementIndex() + i ) ); +// unsigned nbase = ( getCentralAtomElementIndex() + i)*getNumberOfDerivatives(); +// unsigned nbas2 = ( mycolv->getCentralAtomElementIndex() + i )*mycolv->getNumberOfDerivatives(); +// for(unsigned j=0;j<mycolv->atomsWithCatomDer.getNumberActive();++j){ +// unsigned n=mycolv->atomsWithCatomDer[j], nx=3*n; atomsWithCatomDer.activate(n); +// addElementDerivative(nbase + nx + 0, mycolv->getElementDerivative(nbas2 + nx + 0) ); +// addElementDerivative(nbase + nx + 1, mycolv->getElementDerivative(nbas2 + nx + 1) ); +// addElementDerivative(nbase + nx + 2, mycolv->getElementDerivative(nbas2 + nx + 2) ); +// } +// } +// atomsWithCatomDer.updateActiveMembers(); // This can perhaps be faster +// return cvec; +// } +// Vector cvec; +// for(unsigned i=0;i<3;++i) cvec[i]=getElementValue(1+i); +// return cvec; +// } + void BridgedMultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ){ if(!a){ a=dynamic_cast<ActionWithValue*>(this); @@ -171,7 +133,7 @@ bool BridgedMultiColvarFunction::isPeriodic(){ return mycolv->isPeriodic(); } -void BridgedMultiColvarFunction::deactivate_task(){ +void BridgedMultiColvarFunction::deactivate_task( const unsigned& taskno ){ plumed_merror("This should never be called"); } diff --git a/src/multicolvar/BridgedMultiColvarFunction.h b/src/multicolvar/BridgedMultiColvarFunction.h index 67632d8dbf063c6bd36193a583b9371a79ced1c7..192c16c2272425d7544c6556d04456f180975076 100644 --- a/src/multicolvar/BridgedMultiColvarFunction.h +++ b/src/multicolvar/BridgedMultiColvarFunction.h @@ -61,25 +61,22 @@ public: /// Is the output quantity periodic bool isPeriodic(); /// Routines that have to be defined so as not to have problems with virtual methods - void deactivate_task(); + void deactivate_task( const unsigned& taskno ); void calculate(){} /// This does the task - void performTask(); - virtual void completeTask()=0; + void transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ); + void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ); + virtual void completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals )=0; /// Get the central atom position Vector retrieveCentralAtomPos(); /// We need our own calculate numerical derivatives here void calculateNumericalDerivatives( ActionWithValue* a=NULL ); void apply(){}; -/// These routines replace the virtual routines in ActionWithVessel for -/// code optimization - void mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ); - void clearDerivativesAfterTask( const unsigned& ider ); /// Is this atom currently being copied bool isCurrentlyActive( const unsigned& ); /// This should not be called Vector calculateCentralAtomPosition(){ plumed_error(); } - double compute(){ plumed_error(); } + double compute( const unsigned& tindex, AtomValuePack& myvals ){ plumed_error(); } Vector getPositionOfAtomForLinkCells( const unsigned& iatom ){ plumed_error(); } void updateActiveAtoms(){ plumed_error(); } void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ); @@ -106,6 +103,11 @@ unsigned BridgedMultiColvarFunction::getSizeOfAtomsWithDerivatives(){ return mycolv->getNumberOfAtoms(); } +inline +Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ){ + return mycolv->getPositionOfAtomForLinkCells(iatom); +} + } } #endif diff --git a/src/vesselbase/StoreValueAndWeightVessel.cpp b/src/multicolvar/CatomPack.cpp similarity index 76% rename from src/vesselbase/StoreValueAndWeightVessel.cpp rename to src/multicolvar/CatomPack.cpp index 925b2f10da8965f42959dadc0eeed71ccd855d54..bea0e8dae2257d76a5cb792b594ade55493a364f 100644 --- a/src/vesselbase/StoreValueAndWeightVessel.cpp +++ b/src/multicolvar/CatomPack.cpp @@ -19,19 +19,13 @@ You should have received a copy of the GNU Lesser General Public License along with plumed. If not, see <http://www.gnu.org/licenses/>. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#include "StoreValueAndWeightVessel.h" +#include "CatomPack.h" -namespace PLMD { -namespace vesselbase { +namespace PLMD{ +namespace multicolvar{ -void StoreValueAndWeightVessel::registerKeywords( Keywords& keys ){ - StoreDataVessel::registerKeywords( keys ); -} - -StoreValueAndWeightVessel::StoreValueAndWeightVessel( const VesselOptions& da): -StoreDataVessel(da) -{ - completeSetup( 0, 2 ); +void CatomPack::resize( const unsigned& size ){ + indices.resize(size); derivs.resize(size); } } diff --git a/src/multicolvar/CatomPack.h b/src/multicolvar/CatomPack.h new file mode 100644 index 0000000000000000000000000000000000000000..5e54b05d28f90b0ca279f859e1d08729336f165d --- /dev/null +++ b/src/multicolvar/CatomPack.h @@ -0,0 +1,78 @@ +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Copyright (c) 2011-2014 The plumed team + (see the PEOPLE file at the root of the distribution for a list of names) + + See http://www.plumed-code.org for more information. + + This file is part of plumed, version 2. + + plumed is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + plumed is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with plumed. If not, see <http://www.gnu.org/licenses/>. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ +#ifndef __PLUMED_multicolvar_CatomPack_h +#define __PLUMED_multicolvar_CatomPack_h + +#include <vector> +#include "tools/Exception.h" +#include "tools/Tensor.h" +#include "tools/Vector.h" + +namespace PLMD { +namespace multicolvar { + +class CatomPack { +private: + std::vector<unsigned> indices; + std::vector<Tensor> derivs; +public: + void resize( const unsigned& ); + void setIndex( const unsigned& , const unsigned& ); + void setDerivative( const unsigned& , const Tensor& ); + unsigned getNumberOfAtomsWithDerivatives() const ; + unsigned getIndex( const unsigned& ) const ; + double getDerivative( const unsigned&, const unsigned& , const Vector& ) const ; +}; + +inline +void CatomPack::setIndex( const unsigned& jind, const unsigned& ind ){ + plumed_dbg_assert( jind<indices.size() ); + indices[jind]=ind; +} + +inline +void CatomPack::setDerivative( const unsigned& jind , const Tensor& der ){ + plumed_dbg_assert( jind<indices.size() ); + derivs[jind]=der; +} + +inline +unsigned CatomPack::getNumberOfAtomsWithDerivatives() const { + return indices.size(); +} + +inline +unsigned CatomPack::getIndex( const unsigned& jind ) const { + plumed_dbg_assert( jind<indices.size() ); + return indices[jind]; +} + +inline +double CatomPack::getDerivative( const unsigned& iatom, const unsigned& jcomp, const Vector& df ) const { + plumed_dbg_assert( iatom<indices.size() ); + return df[jcomp]*derivs[iatom](jcomp,0) + df[jcomp]*derivs[iatom](jcomp,1) + df[jcomp]*derivs[iatom](jcomp,2); +} + +} +} + +#endif diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp index e42d6622cc7acfcc0c36e02d05577aaa972af0d2..7545b773a21c6790e39173deaf3ed915b6a0f68f 100644 --- a/src/multicolvar/CoordinationNumbers.cpp +++ b/src/multicolvar/CoordinationNumbers.cpp @@ -71,8 +71,7 @@ public: static void registerKeywords( Keywords& keys ); CoordinationNumbers(const ActionOptions&); // active methods: - virtual double compute(); - Vector getCentralAtom(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } }; @@ -120,32 +119,27 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double CoordinationNumbers::compute(){ +double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myatoms ){ double value=0, dfunc; Vector distance; // Calculate the coordination number double d2, sw; - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPosition(0), getPosition(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); d2 = distance.modulo2(); if( d2<rcut2 ){ sw = switchingFunction.calculateSqr( d2, dfunc ); value += sw; - addAtomsDerivatives( 0, (-dfunc)*distance ); - addAtomsDerivatives( i, (dfunc)*distance ); - addBoxDerivatives( (-dfunc)*Tensor(distance,distance) ); + myatoms.addAtomsDerivatives( 1, 0, (-dfunc)*distance ); + myatoms.addAtomsDerivatives( 1, i, (dfunc)*distance ); + myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); } } return value; } -Vector CoordinationNumbers::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - } } diff --git a/src/multicolvar/DHEnergy.cpp b/src/multicolvar/DHEnergy.cpp deleted file mode 100644 index 67db87b478bbd8dedfe8e187997a9217c0c8c4b5..0000000000000000000000000000000000000000 --- a/src/multicolvar/DHEnergy.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013,2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#include "vesselbase/VesselRegister.h" -#include "vesselbase/FunctionVessel.h" -#include "core/PlumedMain.h" -#include "core/Atoms.h" -#include "MultiColvar.h" - -namespace PLMD { -namespace multicolvar { - -class DHEnergy : public vesselbase::FunctionVessel { -private: - MultiColvar* mycolv; - double I, T; - double k; // Inverse Debye screening length - double constant; - double epsilon; -public: - static void registerKeywords( Keywords& keys ); - static void reserveKeyword( Keywords& keys ); - DHEnergy( const vesselbase::VesselOptions& da ); - std::string function_description(); - bool calculate( std::vector<double>& buffer ); -}; - -PLUMED_REGISTER_VESSEL(DHEnergy,"DHENERGY") - -void DHEnergy::registerKeywords( Keywords& keys ){ - FunctionVessel::registerKeywords( keys ); - keys.add("compulsory","I","1.0","Ionic strength (M)"); - keys.add("compulsory","TEMP","300.0","Simulation temperature (K)"); - keys.add("compulsory","EPSILON","80.0","Dielectric constant of solvent"); -} - -void DHEnergy::reserveKeyword( Keywords& keys ){ - keys.reserve("numbered","DHENERGY","calculate the Debye-Huckel interaction energy. This is a alternative " - "implementation of \\ref DHENERGY that is particularly useful if you " - "want to calculate the Debye-Huckel interaction energy and some other " - "function of set of distances between the atoms in the two groups. " - "The input for this keyword should read " - "DHENERGY={I=\\f$I\\f$ TEMP=\\f$T\\f$ EPSILON=\\f$\\epsilon\\f$}."); - keys.addOutputComponent("dhenergy","DHENERGY","the Debye-Huckel interaction energy. You can calculate " - "this quantity multiple times using different parameters"); -} - -DHEnergy::DHEnergy( const vesselbase::VesselOptions& da ) : -FunctionVessel(da) -{ - mycolv=dynamic_cast<MultiColvar*>( getAction() ); - plumed_massert( mycolv, "DHENERGY can only be used with MultiColvars and should only be used with DISTANCES"); - - parse("I",I); parse("TEMP",T); parse("EPSILON",epsilon); - - Atoms& catoms( getAction()->plumed.getAtoms() ); - if( catoms.usingNaturalUnits() ) error("DHENERGY cannot be used for calculations performed with natural units"); - constant=138.935458111/catoms.getUnits().getEnergy()/catoms.getUnits().getLength(); - k=sqrt(I/(epsilon*T))*502.903741125*catoms.getUnits().getLength(); -} - -std::string DHEnergy::function_description(){ - std::ostringstream ostr; - ostr<<"the Debye-Huckel interaction energy "<<getAction()->plumed.cite("Do, Carloni, Varani and Bussi, J. Chem. Theory Comput. 9, 1720 (2013)")<<"."; - ostr<<" Parameters : temperature "<<T<<" K, ionic strength "<<I<<" M, "; - ostr<<"solvent dielectric constant "<<epsilon; - return ostr.str(); -} - -bool DHEnergy::calculate( std::vector<double>& buffer ){ - if( mycolv->getAbsoluteIndex(0)==mycolv->getAbsoluteIndex(1) ) return false; - - double val=getAction()->getElementValue(0), invdistance = 1.0 / val; - double f=exp(-k*val)*invdistance*constant*mycolv->getCharge(0)*mycolv->getCharge(1)/epsilon; - double dval=-(k+invdistance)*f; - return addToBuffers( f, dval, buffer ); -} - -} -} diff --git a/src/multicolvar/Density.cpp b/src/multicolvar/Density.cpp index 5d1fe23d51f79f8886b61a542c65f5c8968fef34..149db001ce2133a266a32f20300bd8e97df39203 100644 --- a/src/multicolvar/Density.cpp +++ b/src/multicolvar/Density.cpp @@ -54,16 +54,15 @@ public: static void registerKeywords( Keywords& keys ); Density(const ActionOptions&); // active methods: - virtual double compute(); - Vector getCentralAtom(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } bool isDensity(){ return true; } bool hasDifferentiableOrientation() const { return true; } - void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, - const std::vector<double>& weight, MultiColvarFunction* func ){} +// void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, +// const std::vector<double>& weight, MultiColvarFunction* func ){} void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ); - unsigned getNumberOfQuantities(); +// unsigned getNumberOfQuantities(); void getValueForTask( const unsigned& iatom, std::vector<double>& vals ); }; @@ -82,22 +81,17 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double Density::compute(){ +double Density::compute( const unsigned& tindex, AtomValuePack& myvals ){ return 1.0; } -Vector Density::getCentralAtom(){ - addCentralAtomDerivatives( 0, Tensor::identity() ); - return getPosition(0); -} - void Density::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ indices[jstore]=0; } -unsigned Density::getNumberOfQuantities(){ - return 6; -} +// unsigned Density::getNumberOfQuantities(){ +// return 2; +// } void Density::getValueForTask( const unsigned& iatom, std::vector<double>& vals ){ plumed_dbg_assert( vals.size()==2 ); vals[0]=vals[1]=1.0; diff --git a/src/multicolvar/DihedralCorrelation.cpp b/src/multicolvar/DihedralCorrelation.cpp index 0cca50e08e62c505b56ce124d170fc4662eee82a..579f737b51446ae510f2e84f47c6e7ed59ad91f2 100644 --- a/src/multicolvar/DihedralCorrelation.cpp +++ b/src/multicolvar/DihedralCorrelation.cpp @@ -85,9 +85,8 @@ private: public: static void registerKeywords( Keywords& keys ); DihedralCorrelation(const ActionOptions&); - virtual double compute(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); bool isPeriodic(){ return false; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(DihedralCorrelation,"DIHCOR") @@ -102,6 +101,10 @@ PLUMED_MULTICOLVAR_INIT(ao) { // Read in the atoms int natoms=8; readAtoms( natoms ); + // Stuff for central atoms + std::vector<bool> catom_ind(8, false); + catom_ind[1]=catom_ind[2]=catom_ind[5]=catom_ind[6]=true; + setAtomsForCentralAtom( catom_ind ); // And setup the ActionWithVessel if( getNumberOfVessels()==0 ){ @@ -114,19 +117,19 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double DihedralCorrelation::compute(){ +double DihedralCorrelation::compute( const unsigned& tindex, AtomValuePack& myatoms ){ Vector d10,d11,d12; - d10=getSeparation(getPosition(1),getPosition(0)); - d11=getSeparation(getPosition(2),getPosition(1)); - d12=getSeparation(getPosition(3),getPosition(2)); + d10=getSeparation(myatoms.getPosition(1),myatoms.getPosition(0)); + d11=getSeparation(myatoms.getPosition(2),myatoms.getPosition(1)); + d12=getSeparation(myatoms.getPosition(3),myatoms.getPosition(2)); Vector dd10,dd11,dd12; PLMD::Torsion t1; double phi1 = t1.compute(d10,d11,d12,dd10,dd11,dd12); Vector d20,d21,d22; - d20=getSeparation(getPosition(5),getPosition(4)); - d21=getSeparation(getPosition(6),getPosition(5)); - d22=getSeparation(getPosition(7),getPosition(6)); + d20=getSeparation(myatoms.getPosition(5),myatoms.getPosition(4)); + d21=getSeparation(myatoms.getPosition(6),myatoms.getPosition(5)); + d22=getSeparation(myatoms.getPosition(7),myatoms.getPosition(6)); Vector dd20,dd21,dd22; PLMD::Torsion t2; double phi2 = t2.compute( d20, d21, d22, dd20, dd21, dd22 ); @@ -138,32 +141,24 @@ double DihedralCorrelation::compute(){ dd11 *= 0.5*sin( phi2 - phi1 ); dd12 *= 0.5*sin( phi2 - phi1 ); // And add - addAtomsDerivatives(0,dd10); - addAtomsDerivatives(1,dd11-dd10); - addAtomsDerivatives(2,dd12-dd11); - addAtomsDerivatives(3,-dd12); - addBoxDerivatives (-(extProduct(d10,dd10)+extProduct(d11,dd11)+extProduct(d12,dd12))); + myatoms.addAtomsDerivatives(1, 0, dd10); + myatoms.addAtomsDerivatives(1, 1, dd11-dd10); + myatoms.addAtomsDerivatives(1, 2, dd12-dd11); + myatoms.addAtomsDerivatives(1, 3, -dd12); + myatoms.addBoxDerivatives (1, -(extProduct(d10,dd10)+extProduct(d11,dd11)+extProduct(d12,dd12))); // Derivative wrt phi2 dd20 *= -0.5*sin( phi2 - phi1 ); dd21 *= -0.5*sin( phi2 - phi1 ); dd22 *= -0.5*sin( phi2 - phi1 ); // And add - addAtomsDerivatives(4,dd20); - addAtomsDerivatives(5,dd21-dd20); - addAtomsDerivatives(6,dd22-dd21); - addAtomsDerivatives(7,-dd22); - addBoxDerivatives (-(extProduct(d20,dd20)+extProduct(d21,dd21)+extProduct(d22,dd22))); + myatoms.addAtomsDerivatives(1, 4, dd20); + myatoms.addAtomsDerivatives(1, 5, dd21-dd20); + myatoms.addAtomsDerivatives(1, 6, dd22-dd21); + myatoms.addAtomsDerivatives(1, 7, -dd22); + myatoms.addBoxDerivatives(1, -(extProduct(d20,dd20)+extProduct(d21,dd21)+extProduct(d22,dd22))); return value; } -Vector DihedralCorrelation::getCentralAtom(){ - addCentralAtomDerivatives( 1, 0.25*Tensor::identity() ); - addCentralAtomDerivatives( 2, 0.25*Tensor::identity() ); - addCentralAtomDerivatives( 5, 0.25*Tensor::identity() ); - addCentralAtomDerivatives( 6, 0.25*Tensor::identity() ); - return 0.25*( getPosition(1) + getPosition(2) + getPosition(5) + getPosition(6) ); -} - } } diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp index 06f34c3eddda44f4f1f915973334541b963e6ba0..207f74029b859ba83c5785e19e816c27a0393612 100644 --- a/src/multicolvar/Distances.cpp +++ b/src/multicolvar/Distances.cpp @@ -82,10 +82,9 @@ public: static void registerKeywords( Keywords& keys ); Distances(const ActionOptions&); // active methods: - virtual double compute(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(Distances,"DISTANCES") @@ -93,7 +92,7 @@ PLUMED_REGISTER_ACTION(Distances,"DISTANCES") void Distances::registerKeywords( Keywords& keys ){ MultiColvar::registerKeywords( keys ); keys.use("ATOMS"); - keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); keys.use("DHENERGY"); + keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); // keys.use("DHENERGY"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " @@ -139,25 +138,19 @@ PLUMED_MULTICOLVAR_INIT(ao) } } -double Distances::compute(){ +double Distances::compute( const unsigned& tindex, AtomValuePack& myatoms ){ Vector distance; - distance=getSeparation( getPosition(0), getPosition(1) ); + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); const double value=distance.modulo(); const double invvalue=1.0/value; // And finish the calculation - addAtomsDerivatives( 0,-invvalue*distance ); - addAtomsDerivatives( 1, invvalue*distance ); - addBoxDerivatives( -invvalue*Tensor(distance,distance) ); + myatoms.addAtomsDerivatives( 1, 0,-invvalue*distance ); + myatoms.addAtomsDerivatives( 1, 1, invvalue*distance ); + myatoms.addBoxDerivatives( 1, -invvalue*Tensor(distance,distance) ); return value; } -Vector Distances::getCentralAtom(){ - addCentralAtomDerivatives( 0, 0.5*Tensor::identity() ); - addCentralAtomDerivatives( 1, 0.5*Tensor::identity() ); - return 0.5*( getPosition(0) + getPosition(1) ); -} - } } diff --git a/src/multicolvar/DumpMultiColvar.cpp b/src/multicolvar/DumpMultiColvar.cpp index cb7f88160d92ff324817de898c9c40fa63b85d20..d70b178e68e80e951fb0c824a8da76fe368fa3a0 100644 --- a/src/multicolvar/DumpMultiColvar.cpp +++ b/src/multicolvar/DumpMultiColvar.cpp @@ -32,6 +32,7 @@ #include "core/ActionSet.h" #include "MultiColvarBase.h" #include "vesselbase/ActionWithInputVessel.h" +#include "vesselbase/StoreDataVessel.h" using namespace std; @@ -132,15 +133,21 @@ void DumpMultiColvar::update(){ lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) ); } - std::vector<double> cvals( mycolv->getNumberOfQuantities()-4 ); + vesselbase::StoreDataVessel* stash=dynamic_cast<vesselbase::StoreDataVessel*>( getPntrToArgument() ); + plumed_dbg_assert( stash ); + std::vector<double> cvals( mycolv->getNumberOfQuantities() ); for(unsigned i=0;i<mycolv->getFullNumberOfTasks();++i){ const char* defname="X"; const char* name=defname; - Vector apos = mycolv->getCentralAtomPosition(i); + Vector apos = mycolv->getCentralAtomPos( mycolv->getTaskCode(i) ); of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz).c_str(),name,lenunit*apos[0],lenunit*apos[1],lenunit*apos[2]); - mycolv->getValueForTask( i, cvals ); - for(unsigned j=0;j<cvals.size();++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]); + stash->retrieveValue( i, true, cvals ); + if( mycolv->weightWithDerivatives() ){ + for(unsigned j=0;j<cvals.size();++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]); + } else { + for(unsigned j=1;j<cvals.size();++j) of.printf((" "+fmt_xyz).c_str(),cvals[j]); + } of.printf("\n"); } } diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index b7851bfa7dbf339c44a363ef4c2ddad55a1f1bbb..ea0536c559f3fc9476ebda02ef215572f5a8721c 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -84,10 +84,6 @@ class LocalAverage : public MultiColvarFunction { private: /// Cutoff double rcut2; -/// Ensures we deal with vectors properly - unsigned jstart; -/// The values of the quantities we need to differentiate - std::vector<double> values; /// The switching function that tells us if atoms are close enough together SwitchingFunction switchingFunction; public: @@ -96,9 +92,7 @@ public: /// We have to overwrite this here unsigned getNumberOfQuantities(); /// Actually do the calculation - double compute(); -/// This returns the position of the central atom - Vector getCentralAtom(); + double compute( const unsigned& tindex, AtomValuePack& myatoms ); /// Is the variable periodic bool isPeriodic(){ return false; } }; @@ -118,16 +112,14 @@ void LocalAverage::registerKeywords( Keywords& keys ){ keys.remove("LOWMEM"); keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); + if( keys.reserved("VMEAN") ) keys.use("VMEAN"); + if( keys.reserved("VSUM") ) keys.use("VSUM"); } LocalAverage::LocalAverage(const ActionOptions& ao): Action(ao), MultiColvarFunction(ao) { - // One component for regular multicolvar and nelements for vectormulticolvar - if( getBaseMultiColvar(0)->getNumberOfQuantities()==5 ){ values.resize( 1 ); jstart=0; } - else { values.resize( getBaseMultiColvar(0)->getNumberOfQuantities() - 5 ); jstart=5; } - // Read in the switching function std::string sw, errors; parse("SWITCH",sw); if(sw.length()>0){ @@ -142,62 +134,112 @@ MultiColvarFunction(ao) log.printf(" averaging over central molecule and those within %s\n",( switchingFunction.description() ).c_str() ); rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); setLinkCellCutoff( 2.*switchingFunction.get_dmax() ); buildSymmetryFunctionLists(); - for(unsigned i=0;i<getNumberOfBaseMultiColvars();++i) getBaseMultiColvar(i)->doNotCalculateDirector(); } unsigned LocalAverage::getNumberOfQuantities(){ - return jstart + values.size(); + return getBaseMultiColvar(0)->getNumberOfQuantities(); } -double LocalAverage::compute(){ - weightHasDerivatives=true; +double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ){ + Vector distance; double d2, sw, dfunc, nbond=1; CatomPack atom0, atom1; + std::vector<double> values( getBaseMultiColvar(0)->getNumberOfQuantities() ); + vesselbase::MultiValue myder(values.size(), getNumberOfDerivatives()); - Vector distance; double d2, sw, dfunc, nbond=1; + getVectorForTask( myatoms.getIndex(0), false, values ); + if( values.size()>2 ){ + for(unsigned j=2;j<values.size();++j) myatoms.addValue( j, values[j] ); + } else { + myatoms.addValue( 1, values[1] ); + } - getVectorForBaseTask( 0, values ); - for(unsigned j=0;j<values.size();++j) addElementValue( jstart + j, values[j] ); + Vector catom_pos=myatoms.getPosition(0); + if( !doNotCalculateDerivatives() ){ + atom0=getCentralAtomPackFromInput( myatoms.getIndex(0) ); + getVectorDerivatives( myatoms.getIndex(0), false, myder ); + if( values.size()>2 ){ + for(unsigned j=0;j<myder.getNumberActive();++j){ + unsigned jder=myder.getActiveIndex(j); + for(unsigned k=2;k<values.size();++k) myatoms.addDerivative( k, jder, myder.getDerivative(k,jder) ); + } + } else { + for(unsigned j=0;j<myder.getNumberActive();++j){ + unsigned jder=myder.getActiveIndex(j); + myatoms.addDerivative( 1, jder, myder.getDerivative(1,jder) ); + } + } + myder.clearAll(); + } - accumulateWeightedAverageAndDerivatives( 0, 1.0 ); - for(unsigned i=1;i<getNAtoms();++i){ - distance=getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(i) ); + for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){ + distance=getSeparation( catom_pos, myatoms.getPosition(i) ); d2 = distance.modulo2(); if( d2<rcut2 ){ sw = switchingFunction.calculateSqr( d2, dfunc ); - Tensor vir(distance,distance); - getVectorForBaseTask( i, values ); - accumulateWeightedAverageAndDerivatives( i, sw ); - for(unsigned j=0;j<values.size();++j){ - addElementValue( jstart + j, sw*values[j] ); - addCentralAtomsDerivatives( 0, jstart+j, (-dfunc)*values[j]*distance ); - addCentralAtomsDerivatives( i, jstart+j, (+dfunc)*values[j]*distance ); - MultiColvarBase::addBoxDerivatives( jstart+j, (-dfunc)*values[j]*vir ); // This is a complex number? + getVectorForTask( myatoms.getIndex(i), false, values ); + if( values.size()>2 ){ + for(unsigned j=2;j<values.size();++j) myatoms.addValue( j, sw*values[j] ); + } else { + myatoms.addValue( 1, sw*values[1] ); } nbond += sw; - addCentralAtomsDerivatives( 0, 1, (-dfunc)*distance ); - addCentralAtomsDerivatives( i, 1, (+dfunc)*distance ); - MultiColvarBase::addBoxDerivatives( 1, (-dfunc)*vir ); + + if( !doNotCalculateDerivatives() ){ + Tensor vir(distance,distance); + getVectorDerivatives( myatoms.getIndex(i), false, myder ); + atom1=getCentralAtomPackFromInput( myatoms.getIndex(i) ); + if( values.size()>2 ){ + for(unsigned j=0;j<myder.getNumberActive();++j){ + unsigned jder=myder.getActiveIndex(j); + for(unsigned k=2;k<values.size();++k) myatoms.addDerivative( k, jder, sw*myder.getDerivative(k,jder) ); + } + for(unsigned k=2;k<values.size();++k){ + myatoms.addComDerivatives( k, (-dfunc)*values[k]*distance, atom0 ); + myatoms.addComDerivatives( k, (+dfunc)*values[k]*distance, atom1 ); + myatoms.addBoxDerivatives( k, (-dfunc)*values[k]*vir ); + } + } else { + for(unsigned j=0;j<myder.getNumberActive();++j){ + unsigned jder=myder.getActiveIndex(j); + myatoms.addDerivative( 1, jder, sw*myder.getDerivative(1,jder) ); + } + myatoms.addComDerivatives( 1, (-dfunc)*values[1]*distance, atom0 ); + myatoms.addComDerivatives( 1, (+dfunc)*values[1]*distance, atom1 ); + myatoms.addBoxDerivatives( 1, (-dfunc)*values[1]*vir ); + } + // And the bit we use to average the vector + myatoms.addComDerivatives( 0, (-dfunc)*distance, atom0 ); + myatoms.addComDerivatives( 0, (+dfunc)*distance, atom1 ); + myatoms.addBoxDerivatives( 0, (-dfunc)*vir ); + myder.clearAll(); + } } } // Set the tempory weight - setElementValue( 1, nbond ); - // Update all dynamic lists - updateActiveAtoms(); - // Finish the calculation - getBaseMultiColvar(0)->finishWeightedAverageCalculation( this ); - - // Clear working derivatives - clearDerivativesAfterTask(1); - // Weight doesn't really have derivatives (just use the holder for convenience) - weightHasDerivatives=false; setElementValue( 1, 1.0 ); + myatoms.setValue( 0, nbond ); updateActiveAtoms( myatoms ); + if( values.size()>2){ + double norm=0; + vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue(); + for(unsigned i=2;i<values.size();++i){ + myvals.quotientRule( i, 0, i ); + // Calculate length of vector + norm+=myvals.get(i)*myvals.get(i); + } + norm=sqrt(norm); myatoms.setValue(1, norm); double inorm = 1.0 / norm; + for(unsigned j=0;j<myvals.getNumberActive();++j){ + unsigned jder=myvals.getActiveIndex(j); + for(unsigned i=2;i<values.size();++i){ + myvals.addDerivative( 1, jder, myvals.get(i)*inorm*myvals.getDerivative(i,jder) ); + } + } + } else { + myatoms.getUnderlyingMultiValue().quotientRule( 1, 0, 1 ); + } + // Weight doesn't really have derivatives (just use the holder for convenience) + myatoms.getUnderlyingMultiValue().clear(0); myatoms.setValue( 0, 1.0 ); - return getElementValue(0); + return myatoms.getValue(1); } -Vector LocalAverage::getCentralAtom(){ - addDerivativeOfCentralAtomPos( 0, Tensor::identity() ); - return getPositionOfCentralAtom(0); -} - } } diff --git a/src/multicolvar/MultiColvar.cpp b/src/multicolvar/MultiColvar.cpp index 56d2f1be238bca722ff9e757fb5b7571dccc5dad..d44c61a1e593f83f6bd34bd1a9dcd3af5f9536f0 100644 --- a/src/multicolvar/MultiColvar.cpp +++ b/src/multicolvar/MultiColvar.cpp @@ -102,7 +102,7 @@ void MultiColvar::readAtomsLikeKeyword( const std::string & key, int& natoms, st t.resize(0); } if( all_atoms.size()>0 ){ - current_atoms.resize( natoms ); nblock=ablocks[0].size(); + nblock=ablocks[0].size(); if( natoms<4 ) resizeBookeepingArray( nblock, nblock ); for(unsigned i=0;i<nblock;++i){ @@ -137,7 +137,7 @@ void MultiColvar::readGroupsKeyword( int& natoms, std::vector<AtomNumber>& all_a std::vector<AtomNumber> t; parseAtomList("GROUP",t); if( !t.empty() ){ - ablocks.resize( natoms ); current_atoms.resize( natoms ); + ablocks.resize( natoms ); for(unsigned i=0;i<t.size();++i) all_atoms.push_back( t[i] ); if(natoms==2){ nblock=t.size(); for(unsigned i=0;i<2;++i) ablocks[i].resize(nblock); @@ -180,7 +180,7 @@ void MultiColvar::readGroupsKeyword( int& natoms, std::vector<AtomNumber>& all_a void MultiColvar::readTwoGroups( const std::string& key1, const std::string& key2, std::vector<AtomNumber>& all_atoms ){ plumed_assert( all_atoms.size()==0 ); - ablocks.resize( 2 ); current_atoms.resize( 2 ); + ablocks.resize( 2 ); std::vector<AtomNumber> t1, t2; std::vector<unsigned> newlist; parseAtomList(key1,t1); parseAtomList(key2,t2); @@ -219,7 +219,7 @@ void MultiColvar::readTwoGroups( const std::string& key1, const std::string& key void MultiColvar::readThreeGroups( const std::string& key1, const std::string& key2, const std::string& key3, const bool& allow2, std::vector<AtomNumber>& all_atoms ){ plumed_assert( all_atoms.size()==0 ); - ablocks.resize( 3 ); current_atoms.resize( 3 ); + ablocks.resize( 3 ); std::vector<AtomNumber> t1, t2, t3; std::vector<unsigned> newlist; parseAtomList(key1,t1); parseAtomList(key2,t2); @@ -307,7 +307,7 @@ void MultiColvar::readSpeciesKeyword( int& natoms, std::vector<AtomNumber>& all_ if( !t.empty() ){ for(unsigned i=0;i<t.size();++i) all_atoms.push_back( t[i] ); if( keywords.exists("SPECIESA") && keywords.exists("SPECIESB") ){ - plumed_assert( natoms==2 ); current_atoms.resize( t.size() ); + plumed_assert( natoms==2 ); for(unsigned i=0;i<t.size();++i) addTaskToList(i); ablocks[0].resize( t.size() ); for(unsigned i=0;i<t.size();++i) ablocks[0][i]=i; if( !verbose_output ){ @@ -319,7 +319,7 @@ void MultiColvar::readSpeciesKeyword( int& natoms, std::vector<AtomNumber>& all_ } else if( !( keywords.exists("SPECIESA") && keywords.exists("SPECIESB") ) ){ std::vector<unsigned> newlist; usespecies=false; verbose_output=false; // Make sure we don't do verbose output log.printf(" involving atoms : "); - current_atoms.resize(1); ablocks.resize(1); ablocks[0].resize( t.size() ); + ablocks.resize(1); ablocks[0].resize( t.size() ); for(unsigned i=0;i<t.size();++i){ addTaskToList(i); ablocks[0][i]=i; log.printf(" %d",t[i].serial() ); } @@ -333,7 +333,6 @@ void MultiColvar::readSpeciesKeyword( int& natoms, std::vector<AtomNumber>& all_ if( !t1.empty() ){ parseAtomList("SPECIESB",t2); if ( t2.empty() ) error("SPECIESB keyword defines no atoms or is missing. Use either SPECIESA and SPECIESB or just SPECIES"); - current_atoms.resize( 1 + t2.size() ); for(unsigned i=0;i<t1.size();++i){ all_atoms.push_back( t1[i] ); addTaskToList(i); } ablocks[0].resize( t2.size() ); unsigned k=0; @@ -364,19 +363,8 @@ void MultiColvar::calculate(){ runAllTasks(); } -void MultiColvar::updateActiveAtoms(){ - if( atoms_with_derivatives.updateComplete() ) return; - atoms_with_derivatives.emptyActiveMembers(); - for(unsigned i=0;i<getNAtoms();++i) atoms_with_derivatives.updateIndex( current_atoms[i] ); - atoms_with_derivatives.sortActiveList(); -} - -Vector MultiColvar::calculateCentralAtomPosition(){ - Vector catom=getCentralAtom(); - atomsWithCatomDer.emptyActiveMembers(); - for(unsigned i=0;i<getNAtoms();++i) atomsWithCatomDer.updateIndex( current_atoms[i] ); - atomsWithCatomDer.sortActiveList(); - return catom; +void MultiColvar::updateActiveAtoms( AtomValuePack& myatoms ){ + myatoms.updateUsingIndices(); } } diff --git a/src/multicolvar/MultiColvar.h b/src/multicolvar/MultiColvar.h index 5547d26e7966e0d394a12b1f1d7108438f6b7568..3b1c728e233588157f5f6c54667e2cb3b3ebda81 100644 --- a/src/multicolvar/MultiColvar.h +++ b/src/multicolvar/MultiColvar.h @@ -23,6 +23,7 @@ #define __PLUMED_multicolvar_MultiColvar_h #include "MultiColvarBase.h" +#include "AtomValuePack.h" #include "tools/SwitchingFunction.h" #include <vector> @@ -56,12 +57,6 @@ protected: void readThreeGroups( const std::string& key1, const std::string& key2, const std::string& key3, const bool& allow2, std::vector<AtomNumber>& all_atoms ); /// Add a collective variable void addColvar( const std::vector<unsigned>& newatoms ); -/// Add some derivatives for an atom - void addAtomsDerivatives(const int&,const Vector&); -/// Set the derivative of the weight (used in MEAN and HISTOGRAM) - void addAtomsDerivativeOfWeight( const unsigned& i, const Vector& wder ); -/// Add derivatives to the central atom position - void addCentralAtomDerivatives( const unsigned& iatom, const Tensor& der ); public: MultiColvar(const ActionOptions&); ~MultiColvar(){} @@ -71,17 +66,7 @@ public: /// Calculate the multicolvar virtual void calculate(); /// Update the atoms that have derivatives - void updateActiveAtoms(); -/// Calculate the position of the central atom - Vector calculateCentralAtomPosition(); -/// Get the position of the central atom - virtual Vector getCentralAtom()=0; -/// Get the mass of atom iatom - double getMass(unsigned) const ; -/// Get the charge of atom iatom - double getCharge(unsigned) const ; -/// Get the absolute index of atom iatom - AtomNumber getAbsoluteIndex(unsigned) const ; + void updateActiveAtoms( AtomValuePack& myatoms ); /// This is used in MultiColvarBase only - it is used to setup the link cells Vector getPositionOfAtomForLinkCells( const unsigned& iatom ); /// Atoms are always active @@ -93,41 +78,6 @@ Vector MultiColvar::getPositionOfAtomForLinkCells( const unsigned& iatom ){ return ActionAtomistic::getPosition( iatom ); } -inline -const Vector & MultiColvar::getPosition( unsigned iatom ) const { - return ActionAtomistic::getPosition( current_atoms[iatom] ); -} - -inline -double MultiColvar::getMass(unsigned iatom ) const { - return ActionAtomistic::getMass( current_atoms[iatom] ); -} - -inline -double MultiColvar::getCharge(unsigned iatom ) const { - return ActionAtomistic::getCharge( current_atoms[iatom] ); -} - -inline -AtomNumber MultiColvar::getAbsoluteIndex(unsigned iatom) const { - return ActionAtomistic::getAbsoluteIndex( current_atoms[iatom] ); -} - -inline -void MultiColvar::addAtomsDerivatives(const int& iatom, const Vector& der){ - MultiColvarBase::addAtomsDerivatives( 0, current_atoms[iatom], der ); -} - -inline -void MultiColvar::addAtomsDerivativeOfWeight( const unsigned& iatom, const Vector& wder ){ - MultiColvarBase::addAtomsDerivatives( 1, current_atoms[iatom], wder ); -} - -inline -void MultiColvar::addCentralAtomDerivatives( const unsigned& iatom, const Tensor& der ){ - MultiColvarBase::addCentralAtomDerivatives( current_atoms[iatom], der ); -} - } } diff --git a/src/multicolvar/MultiColvarBase.cpp b/src/multicolvar/MultiColvarBase.cpp index e018ea9f058ca89f84e0b6a08c42a711ff826c43..62e9ef8a559cd27d0c27eaee865dbf3a5b1e3ca1 100644 --- a/src/multicolvar/MultiColvarBase.cpp +++ b/src/multicolvar/MultiColvarBase.cpp @@ -20,10 +20,13 @@ along with plumed. If not, see <http://www.gnu.org/licenses/>. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "MultiColvarBase.h" -#include "MultiColvarFunction.h" +//#include "MultiColvarFunction.h" #include "BridgedMultiColvarFunction.h" #include "vesselbase/Vessel.h" #include "tools/Pbc.h" +#include "AtomValuePack.h" +#include "CatomPack.h" +#include "CatomPack.h" #include <vector> #include <string> @@ -63,8 +66,8 @@ ActionWithValue(ao), ActionWithVessel(ao), usepbc(false), linkcells(comm), -mycatoms(NULL), // This will be destroyed by ActionWithVesel -myvalues(NULL), // This will be destroyed by ActionWithVesel +//mycatoms(NULL), // This will be destroyed by ActionWithVesel +//myvalues(NULL), // This will be destroyed by ActionWithVesel usespecies(false) { if( keywords.exists("NOPBC") ){ @@ -91,14 +94,26 @@ void MultiColvarBase::setupMultiColvarBase(){ if( !usespecies && ablocks.size()<4 ){ decoder.resize( ablocks.size() ); unsigned code=1; for(unsigned i=0;i<ablocks.size();++i){ decoder[ablocks.size()-1-i]=code; code *= nblock; } - } - // Resize stuff here - resizeLocalArrays(); + use_for_central_atom.resize( ablocks.size(), true ); + numberForCentralAtom = 1.0 / static_cast<double>( ablocks.size() ); + } else if( !usespecies ){ + use_for_central_atom.resize( ablocks.size(), true ); + numberForCentralAtom = 1.0 / static_cast<double>( ablocks.size() ); + } // Setup underlying ActionWithVessel readVesselKeywords(); } +void MultiColvarBase::setAtomsForCentralAtom( const std::vector<bool>& catom_ind ){ + unsigned nat=0; plumed_assert( catom_ind.size()==ablocks.size() ); + for(unsigned i=0;i<catom_ind.size();++i){ + use_for_central_atom[i]=catom_ind[i]; + if( use_for_central_atom[i] ) nat++; + } + plumed_dbg_assert( nat>0 ); numberForCentralAtom = 1.0 / static_cast<double>( nat ); +} + void MultiColvarBase::turnOnDerivatives(){ ActionWithValue::turnOnDerivatives(); needsDerivatives(); @@ -106,17 +121,17 @@ void MultiColvarBase::turnOnDerivatives(){ } void MultiColvarBase::setLinkCellCutoff( const double& lcut ){ - plumed_assert( usespecies || current_atoms.size()<4 ); + plumed_assert( usespecies || ablocks.size()<4 ); linkcells.setCutoff( lcut ); } void MultiColvarBase::setupLinkCells(){ if( !linkcells.enabled() ) return ; - unsigned iblock, jblock; + unsigned iblock; if( usespecies ){ iblock=0; - } else if( current_atoms.size()<4 ){ + } else if( ablocks.size()<4 ){ iblock=1; } else { plumed_error(); @@ -164,7 +179,7 @@ void MultiColvarBase::setupLinkCells(){ std::vector<unsigned> active_tasks( getFullNumberOfTasks(), 0 ); for(unsigned i=rank;i<ablocks[0].size();i+=stride){ if( !isCurrentlyActive( ablocks[0][i] ) ) continue; - natomsper=1; linked_atoms[0]=ltmp_ind[0]; // Note we always check atom 0 because it is simpler than changing LinkCells.cpp + unsigned natomsper=1; linked_atoms[0]=ltmp_ind[0]; // Note we always check atom 0 because it is simpler than changing LinkCells.cpp linkcells.retrieveNeighboringAtoms( getPositionOfAtomForLinkCells( ablocks[0][i] ), natomsper, linked_atoms ); for(unsigned j=0;j<natomsper;++j){ for(unsigned k=bookeeping(i,linked_atoms[j]).first;k<bookeeping(i,linked_atoms[j]).second;++k) active_tasks[k]=1; @@ -178,284 +193,235 @@ void MultiColvarBase::setupLinkCells(){ } } -void MultiColvarBase::resizeLocalArrays(){ - atoms_with_derivatives.clear(); - for(unsigned i=0;i<getSizeOfAtomsWithDerivatives();++i) atoms_with_derivatives.addIndexToList( i ); - atoms_with_derivatives.deactivateAll(); - // Set up stuff for central atoms - atomsWithCatomDer.clear(); - for(unsigned i=0;i<getSizeOfAtomsWithDerivatives();++i) atomsWithCatomDer.addIndexToList( i ); - atomsWithCatomDer.deactivateAll(); +void MultiColvarBase::decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms ){ + plumed_dbg_assert( atoms.size()==ablocks.size() && !usespecies && ablocks.size()<4 ); + unsigned scode = taskCode; + for(unsigned i=0;i<ablocks.size();++i){ + unsigned ind=( scode / decoder[i] ); + atoms[i] = ablocks[i][ind]; + scode -= ind*decoder[i]; + } } -bool MultiColvarBase::setupCurrentAtomList( const unsigned& taskCode ){ +bool MultiColvarBase::setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms ){ if( usespecies ){ - natomsper=1; + unsigned natomsper=1; std::vector<unsigned> current_atoms( getNumberOfAtoms() ); if( isDensity() ) return true; current_atoms[0]=taskCode; linkcells.retrieveNeighboringAtoms( getPositionOfAtomForLinkCells(current_atoms[0]), natomsper, current_atoms ); + myatoms.setNumberOfAtoms( natomsper ); + for(unsigned i=0;i<natomsper;++i) myatoms.setIndex( i, current_atoms[i] ); return natomsper>1; - } else if( current_atoms.size()<4 ){ - natomsper=current_atoms.size(); - unsigned scode = taskCode; - for(unsigned i=0;i<ablocks.size();++i){ - unsigned ind=( scode / decoder[i] ); - current_atoms[i]=ablocks[i][ind]; - scode -= ind*decoder[i]; - } + } else if( ablocks.size()<4 ){ + std::vector<unsigned> atoms( ablocks.size() ); + decodeIndexToAtoms( taskCode, atoms ); myatoms.setNumberOfAtoms( ablocks.size() ); + for(unsigned i=0;i<ablocks.size();++i) myatoms.setIndex( i, atoms[i] ); } else { - natomsper=current_atoms.size(); - for(unsigned i=0;i<ablocks.size();++i) current_atoms[i]=ablocks[i][taskCode]; + myatoms.setNumberOfAtoms( ablocks.size() ); + for(unsigned i=0;i<ablocks.size();++i) myatoms.setIndex( i, ablocks[i][taskCode] ); } return true; } -void MultiColvarBase::performTask(){ - // Currently no atoms have derivatives so deactivate those that are active - atoms_with_derivatives.deactivateAll(); - // Currently no central atoms have derivatives so deactive them all - atomsWithCatomDer.deactivateAll(); +void MultiColvarBase::performTask( const unsigned& task_index, const unsigned& current, vesselbase::MultiValue& myvals ){ + + AtomValuePack myatoms( myvals, this ); // Retrieve the atom list - if( !setupCurrentAtomList( getCurrentTask() ) ) return; + if( !setupCurrentAtomList( current, myatoms ) ) return; // Do a quick check on the size of this contribution - calculateWeight(); // printf("HELLO WEIGHT %f \n",getElementValue(1) ); - if( getElementValue(1)<getTolerance() ){ - updateActiveAtoms(); + calculateWeight( myatoms ); + if( myatoms.getValue(0)<getTolerance() ){ + updateActiveAtoms( myatoms ); return; } // Compute everything - double vv=doCalculation(); - // Set the value of this element in ActionWithVessel - setElementValue( 0, vv ); + double vv=doCalculation( task_index, myatoms ); + myatoms.setValue( 1, vv ); return; } -double MultiColvarBase::doCalculation(){ - double val=compute(); updateActiveAtoms(); - return val; +void MultiColvarBase::calculateWeight( AtomValuePack& myatoms ){ + myatoms.setValue( 0, 1.0 ); } -Vector MultiColvarBase::retrieveCentralAtomPos(){ - if( atomsWithCatomDer.getNumberActive()==0 ){ - Vector cvec = calculateCentralAtomPosition(); - for(unsigned i=0;i<3;++i) setElementValue( getCentralAtomElementIndex()+i, cvec[i] ); - return cvec; - } - Vector cvec; - for(unsigned i=0;i<3;++i) cvec[i]=getElementValue( 2+i ); - return cvec; +double MultiColvarBase::doCalculation( const unsigned& taskIndex, AtomValuePack& myatoms ){ + double val=compute( taskIndex, myatoms ); updateActiveAtoms( myatoms ); + return val; } -void MultiColvarBase::addCentralAtomDerivatives( const unsigned& iatom, const Tensor& der ){ - plumed_dbg_assert( iatom<getNumberOfAtoms() ); - atomsWithCatomDer.activate(iatom); - unsigned nder = 3*getNumberOfAtoms() + 9; - for(unsigned i=0;i<3;++i){ - for(unsigned j=0;j<3;++j){ - addElementDerivative( (getCentralAtomElementIndex()+j)*nder + 3*iatom + i, der(j,i) ); +Vector MultiColvarBase::getCentralAtomPos( const unsigned& taskIndex ){ + unsigned curr=getTaskCode( taskIndex ); + + if( usespecies || isDensity() ){ + return getPositionOfAtomForLinkCells(curr); + } else if( ablocks.size()<4 ){ + // double factor=1.0/static_cast<double>( ablocks.size() ); + Vector mypos; mypos.zero(); + std::vector<unsigned> atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); + for(unsigned i=0;i<ablocks.size();++i){ + if( use_for_central_atom[i] ) mypos+=numberForCentralAtom*getPositionOfAtomForLinkCells(atoms[i]); } + return mypos; + } else { + Vector mypos; mypos.zero(); + for(unsigned i=0;i<ablocks.size();++i){ + if( use_for_central_atom[i] ) mypos+=numberForCentralAtom*getPositionOfAtomForLinkCells(ablocks[i][curr]); + } + return mypos; } } -double MultiColvarBase::getCentralAtomDerivative( const unsigned& iatom, const unsigned& jcomp, const Vector& df ){ - plumed_dbg_assert( atomsWithCatomDer.isActive(iatom) && jcomp<3 ); - unsigned nder = 3*getNumberOfAtoms() + 9; - return df[0]*getElementDerivative( (getCentralAtomElementIndex()+0)*nder + 3*iatom + jcomp ) + - df[1]*getElementDerivative( (getCentralAtomElementIndex()+1)*nder + 3*iatom + jcomp ) + - df[2]*getElementDerivative( (getCentralAtomElementIndex()+2)*nder + 3*iatom + jcomp ); -} +CatomPack MultiColvarBase::getCentralAtomPack( const unsigned& basn, const unsigned& taskIndex ){ + unsigned curr=getTaskCode( taskIndex ); + + CatomPack mypack; + if(usespecies){ + mypack.resize(1); + mypack.setIndex( 0, basn + curr ); + mypack.setDerivative( 0, Tensor::identity() ); + } else if( ablocks.size()<4 ){ + mypack.resize(ablocks.size()); + unsigned k=0; + std::vector<unsigned> atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); + for(unsigned i=0;i<ablocks.size();++i){ + if( use_for_central_atom[i] ){ + mypack.setIndex( k, basn + atoms[i] ); + mypack.setDerivative( k, numberForCentralAtom*Tensor::identity() ); + k++; + } + } + } else { + unsigned k=0; + for(unsigned i=0;i<ablocks.size();++i){ + if( use_for_central_atom[i] ){ + mypack.setIndex( k, basn + ablocks[i][curr] ); + mypack.setDerivative( k, numberForCentralAtom*Tensor::identity() ); + k++; + } + } + } + return mypack; +} Vector MultiColvarBase::getSeparation( const Vector& vec1, const Vector& vec2 ) const { if(usepbc){ return pbcDistance( vec1, vec2 ); } else{ return delta( vec1, vec2 ); } } -void MultiColvarBase::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ - plumed_dbg_assert( !doNotCalculateDerivatives() ); - indices[jstore]=3*atoms_with_derivatives.getNumberActive() + 9; - if( indices[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); - - unsigned kder = ntotal + jstore*maxder; - for(unsigned jder=0;jder<atoms_with_derivatives.getNumberActive();++jder){ - unsigned iatom = 3*atoms_with_derivatives[jder]; - for(unsigned icomp=0;icomp<3;++icomp){ indices[ kder ] = iatom+icomp; kder++; } - } - unsigned nbase = 3*getNumberOfAtoms(); - for(unsigned icomp=0;icomp<9;++icomp){ indices[ kder ] = nbase + icomp; kder++; } -} - -void MultiColvarBase::getCentralAtomIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ) const { - plumed_dbg_assert( !doNotCalculateDerivatives() ); - - indices[jstore]=3*atomsWithCatomDer.getNumberActive(); - if( indices[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); - - unsigned kder = ntotal + jstore*maxder; - for(unsigned jder=0;jder<atomsWithCatomDer.getNumberActive();++jder){ - unsigned iatom = 3*atomsWithCatomDer[jder]; - for(unsigned icomp=0;icomp<3;++icomp){ indices[ kder ] = iatom+icomp; kder++; } - } -} +// void MultiColvarBase::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ +// plumed_dbg_assert( !doNotCalculateDerivatives() ); +// indices[jstore]=3*atoms_with_derivatives.getNumberActive() + 9; +// if( indices[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); +// +// unsigned kder = ntotal + jstore*maxder; +// for(unsigned jder=0;jder<atoms_with_derivatives.getNumberActive();++jder){ +// unsigned iatom = 3*atoms_with_derivatives[jder]; +// for(unsigned icomp=0;icomp<3;++icomp){ indices[ kder ] = iatom+icomp; kder++; } +// } +// unsigned nbase = 3*getNumberOfAtoms(); +// for(unsigned icomp=0;icomp<9;++icomp){ indices[ kder ] = nbase + icomp; kder++; } +// } void MultiColvarBase::activateIndexes( const unsigned& istart, const unsigned& number, const std::vector<unsigned>& indexes ){ plumed_assert( number>0 ); for(unsigned i=0;i<number-9;i+=3){ - plumed_dbg_assert( indexes[istart+i]%3==0 ); unsigned iatom=indexes[istart+i]/3; - atoms_with_derivatives.activate( iatom ); - } -} - -void MultiColvarBase::quotientRule( const unsigned& uder, const unsigned& vder, const unsigned& iout ){ - unsigned ustart=uder*getNumberOfDerivatives(); - unsigned vstart=vder*getNumberOfDerivatives(); - unsigned istart=iout*getNumberOfDerivatives(); - double weight = getElementValue( vder ), pref = getElementValue( uder ) / (weight*weight); - if( !doNotCalculateDerivatives() ){ - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned n=3*atoms_with_derivatives[i], nx=n, ny=n+1, nz=n+2; - setElementDerivative( istart + nx, getElementDerivative(ustart+nx) / weight - pref*getElementDerivative(vstart+nx) ); - setElementDerivative( istart + ny, getElementDerivative(ustart+ny) / weight - pref*getElementDerivative(vstart+ny) ); - setElementDerivative( istart + nz, getElementDerivative(ustart+nz) / weight - pref*getElementDerivative(vstart+nz) ); - } - unsigned vbase=3*getNumberOfAtoms(); - for(unsigned i=0;i<9;++i){ - setElementDerivative( istart + vbase + i, getElementDerivative(ustart+vbase+i) / weight - pref*getElementDerivative(vstart+vbase+i) ); - } + plumed_dbg_assert( indexes[istart+i]%3==0 ); // unsigned iatom=indexes[istart+i]/3; + //atoms_with_derivatives.activate( iatom ); } - thisval_wasset[iout]=false; setElementValue( iout, getElementValue(uder) / weight ); } -void MultiColvarBase::mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ){ - unsigned vstart=getNumberOfDerivatives()*ider; - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned iatom=3*atoms_with_derivatives[i]; - buffer[start+iatom*stride] += df*getElementDerivative(vstart+iatom); iatom++; - buffer[start+iatom*stride] += df*getElementDerivative(vstart+iatom); iatom++; - buffer[start+iatom*stride] += df*getElementDerivative(vstart+iatom); - } - unsigned nvir=3*getNumberOfAtoms(); - for(unsigned j=0;j<9;++j){ - buffer[start+nvir*stride] += df*getElementDerivative(vstart+nvir); nvir++; - } -} - -void MultiColvarBase::clearDerivativesAfterTask( const unsigned& ider ){ - unsigned vstart=getNumberOfDerivatives()*ider; - thisval_wasset[ider]=false; setElementValue( ider, 0.0 ); - thisval_wasset[ider]=false; - if( ider>1 && ider<5 && derivativesAreRequired() ){ - for(unsigned i=0;i<atomsWithCatomDer.getNumberActive();++i){ - unsigned iatom=vstart+3*atomsWithCatomDer[i]; - setElementDerivative( iatom, 0.0 ); iatom++; - setElementDerivative( iatom, 0.0 ); iatom++; - setElementDerivative( iatom, 0.0 ); - } - } else if( derivativesAreRequired() ) { - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned iatom=vstart+3*atoms_with_derivatives[i]; - setElementDerivative( iatom, 0.0 ); iatom++; - setElementDerivative( iatom, 0.0 ); iatom++; - setElementDerivative( iatom, 0.0 ); - } - unsigned nvir=vstart+3*getNumberOfAtoms(); - for(unsigned j=0;j<9;++j){ - setElementDerivative( nvir, 0.0 ); nvir++; - } - } -} +// void MultiColvarBase::quotientRule( const unsigned& uder, const unsigned& vder, const unsigned& iout ){ +// unsigned ustart=uder*getNumberOfDerivatives(); +// unsigned vstart=vder*getNumberOfDerivatives(); +// unsigned istart=iout*getNumberOfDerivatives(); +// double weight = getElementValue( vder ), pref = getElementValue( uder ) / (weight*weight); +// if( !doNotCalculateDerivatives() ){ +// for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ +// unsigned n=3*atoms_with_derivatives[i], nx=n, ny=n+1, nz=n+2; +// setElementDerivative( istart + nx, getElementDerivative(ustart+nx) / weight - pref*getElementDerivative(vstart+nx) ); +// setElementDerivative( istart + ny, getElementDerivative(ustart+ny) / weight - pref*getElementDerivative(vstart+ny) ); +// setElementDerivative( istart + nz, getElementDerivative(ustart+nz) / weight - pref*getElementDerivative(vstart+nz) ); +// } +// unsigned vbase=3*getNumberOfAtoms(); +// for(unsigned i=0;i<9;++i){ +// setElementDerivative( istart + vbase + i, getElementDerivative(ustart+vbase+i) / weight - pref*getElementDerivative(vstart+vbase+i) ); +// } +// } +// thisval_wasset[iout]=false; setElementValue( iout, getElementValue(uder) / weight ); +// } void MultiColvarBase::apply(){ if( getForcesFromVessels( forcesToApply ) ) setForcesOnAtoms( forcesToApply ); } -vesselbase::StoreDataVessel* MultiColvarBase::buildDataStashes( const bool& allow_wcutoff, const double& wtol ){ - // Check if vessels have already been setup - for(unsigned i=0;i<getNumberOfVessels();++i){ - StoreColvarVessel* ssc=dynamic_cast<StoreColvarVessel*>( getPntrToVessel(i) ); - if(ssc){ - if( allow_wcutoff && !ssc->weightCutoffIsOn() ) error("Cannot have more than one data stash with different properties"); - if( !allow_wcutoff && ssc->weightCutoffIsOn() ) error("Cannot have more than one data stash with different properties"); - return ssc; - } - } - - // Setup central atoms - vesselbase::VesselOptions da("","",0,"",this); - mycatoms=new StoreCentralAtomsVessel(da); - if( allow_wcutoff ) mycatoms->setHardCutoffOnWeight( wtol ); - addVessel(mycatoms); - - // Setup store values vessel - vesselbase::VesselOptions ta("","",0,"",this); - myvalues=new StoreColvarVessel(ta); - if( allow_wcutoff ) myvalues->setHardCutoffOnWeight( wtol ); - addVessel(myvalues); - - // Make sure resizing of vessels is done - resizeFunctions(); - return myvalues; -} - - -Vector MultiColvarBase::getCentralAtomPosition( const unsigned& iatom ) const { - plumed_dbg_assert( mycatoms ); - return mycatoms->getPosition( iatom ); -} - -void MultiColvarBase::addCentralAtomDerivativeToFunction( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, const Vector& der, MultiColvarFunction* func ){ - plumed_dbg_assert( mycatoms ); - if( usingLowMem() ){ - mycatoms->recompute( iatom, 0 ); ; - mycatoms->addAtomsDerivatives( 0, jout, base_cv_no, der, func ); - } else{ - mycatoms->addAtomsDerivatives( iatom, jout, base_cv_no, der, func ); - } -} - -void MultiColvarBase::getValueForTask( const unsigned& iatom, std::vector<double>& vals ){ - // plumed_dbg_assert( myvalues && vals.size()==1 ); // Problem if we want to do MultiColvar + Bridge + MultiColvarFunction - vals[0]=myvalues->getValue( iatom ); -} - -void MultiColvarBase::copyElementsToBridgedColvar( BridgedMultiColvarFunction* func ){ - func->setElementValue( 0, getElementValue(0) ); - for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ - unsigned n=atoms_with_derivatives[i], nx=3*n; - func->atoms_with_derivatives.activate(n); - func->addElementDerivative( nx+0, getElementDerivative(nx+0) ); - func->addElementDerivative( nx+1, getElementDerivative(nx+1) ); - func->addElementDerivative( nx+2, getElementDerivative(nx+2) ); - } - unsigned nvir=3*getNumberOfAtoms(); - for(unsigned i=0;i<9;++i){ - func->addElementDerivative( nvir, getElementDerivative(nvir) ); nvir++; - } -} - -void MultiColvarBase::addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, MultiColvarFunction* func ){ - plumed_dbg_assert( myvalues ); - if( usingLowMem() ){ - myvalues->recompute( iatom, 0 ); - myvalues->chainRuleForComponent( 0, 0, base_cv_no, weight, func ); - } else { - myvalues->chainRuleForComponent( iatom, 0, base_cv_no, weight, func ); - } -} - -bool MultiColvarBase::storedValueIsActive( const unsigned& iatom ){ - return myvalues->storedValueIsActive( iatom ); -} - -void MultiColvarBase::finishWeightedAverageCalculation( MultiColvarFunction* func ){ - func->quotientRule( 0, 1, 0 ); -} - -void MultiColvarBase::addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, - const std::vector<double>& weight, MultiColvarFunction* func ) { - plumed_merror("This should not be called - invalid use of multicolvar in function"); -} +// vesselbase::StoreDataVessel* MultiColvarBase::buildDataStashes( const bool& allow_wcutoff, const double& wtol ){ +// // Check if vessels have already been setup +// for(unsigned i=0;i<getNumberOfVessels();++i){ +// StoreColvarVessel* ssc=dynamic_cast<StoreColvarVessel*>( getPntrToVessel(i) ); +// if(ssc){ +// if( allow_wcutoff && !ssc->weightCutoffIsOn() ) error("Cannot have more than one data stash with different properties"); +// if( !allow_wcutoff && ssc->weightCutoffIsOn() ) error("Cannot have more than one data stash with different properties"); +// return ssc; +// } +// } +// +// // Setup central atoms +// // vesselbase::VesselOptions da("","",0,"",this); +// // mycatoms=new StoreCentralAtomsVessel(da); +// // if( allow_wcutoff ) mycatoms->setHardCutoffOnWeight( wtol ); +// // addVessel(mycatoms); +// +// // Setup store values vessel +// vesselbase::VesselOptions ta("","",0,"",this); +// myvalues=new StoreColvarVessel(ta); +// if( allow_wcutoff ) myvalues->setHardCutoffOnWeight( wtol ); +// addVessel(myvalues); +// +// // Make sure resizing of vessels is done +// resizeFunctions(); +// return myvalues; +// } + + +//void MultiColvarBase::addCentralAtomDerivativeToFunction( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, const Vector& der, MultiColvarFunction* func ){ +//// plumed_dbg_assert( mycatoms ); +//// if( usingLowMem() ){ +//// mycatoms->recompute( iatom, 0 ); ; +//// mycatoms->addAtomsDerivatives( 0, jout, base_cv_no, der, func ); +//// } else{ +//// mycatoms->addAtomsDerivatives( iatom, jout, base_cv_no, der, func ); +//// } +//} + +// void MultiColvarBase::getValueForTask( const unsigned& iatom, std::vector<double>& vals ){ +// // plumed_dbg_assert( myvalues && vals.size()==1 ); // Problem if we want to do MultiColvar + Bridge + MultiColvarFunction +// vals[0]=myvalues->getValue( iatom ); +// } +// +// bool MultiColvarBase::storedValueIsActive( const unsigned& iatom ){ +// return myvalues->storedValueIsActive( iatom ); +// } + +// void MultiColvarBase::finishWeightedAverageCalculation( MultiColvarFunction* func ){ +// // func->quotientRule( 0, 1, 0 ); +// } + +// void MultiColvarBase::addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, +// const std::vector<double>& weight, MultiColvarFunction* func ) { +// plumed_merror("This should not be called - invalid use of multicolvar in function"); +// } + +// void MultiColvarBase::addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, MultiColvarFunction* func ){ +// plumed_dbg_assert( myvalues ); +// if( usingLowMem() ){ +// myvalues->recompute( iatom, 0 ); +// myvalues->chainRuleForComponent( 0, 0, base_cv_no, weight, func ); +// } else { +// myvalues->chainRuleForComponent( iatom, 0, base_cv_no, weight, func ); +// } +// } } } diff --git a/src/multicolvar/MultiColvarBase.h b/src/multicolvar/MultiColvarBase.h index b9438965b3b4b89805cbd5e1d762df7926a78893..06b2cdf93620e878de06abc8df6cbb4d0188f850 100644 --- a/src/multicolvar/MultiColvarBase.h +++ b/src/multicolvar/MultiColvarBase.h @@ -27,13 +27,15 @@ #include "tools/DynamicList.h" #include "tools/LinkCells.h" #include "vesselbase/ActionWithVessel.h" -#include "StoreColvarVessel.h" -#include "StoreCentralAtomsVessel.h" +// #include "StoreColvarVessel.h" +// #include "StoreCentralAtomsVessel.h" #include <vector> namespace PLMD { namespace multicolvar { +class AtomValuePack; +class CatomPack; class BridgedMultiColvarFunction; class MultiColvarBase : @@ -50,26 +52,21 @@ friend class MultiColvar; private: /// Use periodic boundary conditions bool usepbc; -/// Variables used for central atoms - Tensor ibox; - DynamicList<unsigned> atomsWithCatomDer; /// The forces we are going to apply to things std::vector<double> forcesToApply; /// Stuff for link cells - this is used to make coordination number like variables faster LinkCells linkcells; /// This remembers where the boundaries are for the tasks. It makes link cells work fast Matrix<std::pair<unsigned,unsigned> > bookeeping; -/// A copy of the vessel containing the catoms - StoreCentralAtomsVessel* mycatoms; +/// Bool vector telling us which atoms are required to calculate central atom position + std::vector<bool> use_for_central_atom; +/// 1/number of atoms involved in central atoms + double numberForCentralAtom; /// A copy of the vessel containg the values of each colvar - StoreColvarVessel* myvalues; -/// This resizes the local arrays after neighbor list updates and during initialization - void resizeLocalArrays(); +// StoreColvarVessel* myvalues; /// This resizes the arrays that are used for link cell update void resizeBookeepingArray( const unsigned& num1, const unsigned& num2 ); protected: -/// A dynamic list containing those atoms with derivatives - DynamicList<unsigned> atoms_with_derivatives; /// Using the species keyword to read in atoms bool usespecies; /// Number of atoms in each block @@ -78,14 +75,12 @@ protected: std::vector<unsigned> decoder; /// Blocks of atom numbers std::vector< std::vector<unsigned> > ablocks; -/// Number of atoms in the cv - set at start of calculation - unsigned natomsper; -/// Vector containing the indices of the current atoms - std::vector<unsigned> current_atoms; /// Add a task to the list of tasks void addTaskToList( const unsigned& taskCode ); /// Finish setting up the multicolvar base void setupMultiColvarBase(); +/// Set which atoms are to be used to calculate the central atom position + void setAtomsForCentralAtom( const std::vector<bool>& catom_ind ); /// Set the value of the cutoff for the link cells void setLinkCellCutoff( const double& lcut ); /// Setup link cells in order to make this calculation faster @@ -94,91 +89,62 @@ protected: Vector getSeparation( const Vector& vec1, const Vector& vec2 ) const ; /// Do we use pbc to calculate this quantity bool usesPbc() const ; -/// Add some derivatives for an atom - void addAtomsDerivatives(const unsigned&, const unsigned&, const Vector& ); -/// Add some derivatives for a box - void addBoxDerivatives(const unsigned&, const Tensor& ); -/// Add some derivatives of the value to the virial - void addBoxDerivatives(const Tensor&); -/// Retrieve derivative of central atom position wrt jcomp'th component of position of iatom'th atom - double getCentralAtomDerivative( const unsigned& iatom, const unsigned& jcomp, const Vector& df ); -/// Set a weight for this colvar (used in MEAN and HISTOGRAM) - void setWeight( const double& weight ); -/// Set the derivative of the weight (used in MEAN and HISTOGRAM) - void addBoxDerivativesOfWeight( const Tensor& vir ); /// Get the number of atoms in this particular colvar unsigned getNAtoms() const; -/// Add derivative of central atom position wrt to position of iatom'th atom - void addCentralAtomDerivatives( const unsigned& iatom, const Tensor& der ); -/// Get the indices for the central atom - void getCentralAtomIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ) const ; /// This sets up the list of atoms that are involved in this colvar - bool setupCurrentAtomList( const unsigned& taskCode ); + bool setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms ); +/// Decode indices if there are 2 or 3 atoms involved + void decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms ); public: MultiColvarBase(const ActionOptions&); ~MultiColvarBase(){} static void registerKeywords( Keywords& keys ); -/// Used in setupCurrentAtomList to get atom numbers -/// Base quantities are different in MultiColvar and MultiColvarFunction /// Turn on the derivatives virtual void turnOnDerivatives(); /// Prepare for the calculation /// Perform one of the tasks - virtual void performTask(); + virtual void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ); /// This gets the position of an atom for the link cell setup virtual Vector getPositionOfAtomForLinkCells( const unsigned& iatom )=0; /// And a virtual function which actually computes the colvar - virtual double doCalculation(); + virtual double doCalculation( const unsigned& tindex, AtomValuePack& myatoms ); /// Update the atoms that have derivatives - virtual void updateActiveAtoms()=0; + virtual void updateActiveAtoms( AtomValuePack& myatoms ){}; /// This is replaced once we have a function to calculate the cv - virtual double compute()=0; -/// These replace the functions in ActionWithVessel to make the code faster - virtual void mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ); - virtual void clearDerivativesAfterTask( const unsigned& ider ); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms )=0; /// Apply the forces from this action virtual void apply(); /// Get the number of derivatives for this action virtual unsigned getNumberOfDerivatives(); // N.B. This is replacing the virtual function in ActionWithValue -/// Get number size of atoms with derivatives array - virtual unsigned getSizeOfAtomsWithDerivatives(); /// Checks if an task is being performed at the present time virtual bool isCurrentlyActive( const unsigned& code )=0; -/// Get the number of quantities that are calculated each time - virtual unsigned getNumberOfQuantities(); +/// + virtual CatomPack getCentralAtomPack( const unsigned& basn, const unsigned& curr ); /// Get the index where the central atom is stored - virtual unsigned getCentralAtomElementIndex(); -/// Retrieve the position of the central atom - virtual Vector retrieveCentralAtomPos(); + virtual Vector getCentralAtomPos( const unsigned& curr ); /// You can use this to screen contributions that are very small so we can avoid expensive (and pointless) calculations - virtual void calculateWeight(); -/// A virtual routine to get the position of the central atom - used for things like cv gradient - virtual Vector calculateCentralAtomPosition()=0; + virtual void calculateWeight( AtomValuePack& myatoms ); /// Get the list of indices that have derivatives - virtual void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ); +// virtual void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ); /// Is this a density? virtual bool isDensity(){ return false; } /// Store central atoms so that this can be used in a function - virtual vesselbase::StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol ); +// virtual vesselbase::StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol ); /// Calculate and store getElementValue(uder)/getElementValue(vder) and its derivatives in getElementValue(iout) - void quotientRule( const unsigned& uder, const unsigned& vder, const unsigned& iout ); +// void quotientRule( const unsigned& uder, const unsigned& vder, const unsigned& iout ); /// Activate the atoms that have derivatives from a storeDataVessel void activateIndexes( const unsigned& istart, const unsigned& number, const std::vector<unsigned>& indexes ); -/// Get the position of the iatom th central atom (used in multicolvarfunction) - Vector getCentralAtomPosition( const unsigned& iatom ) const ; /// Add central atom derivatives to a multicolvar function - void addCentralAtomDerivativeToFunction( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, const Vector& der, MultiColvarFunction* func ); +// void addCentralAtomDerivativeToFunction( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, const Vector& der, MultiColvarFunction* func ); /// Get the value for this task - virtual void getValueForTask( const unsigned& iatom, std::vector<double>& vals ); -//// Used in ActionVolume and Gradient - virtual void copyElementsToBridgedColvar( BridgedMultiColvarFunction* ); +// virtual void getValueForTask( const unsigned& iatom, std::vector<double>& vals ); /// Used to accumulate values - virtual void addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, MultiColvarFunction* func ); +// virtual void addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, MultiColvarFunction* func ); /// Used for calculating weighted averages - virtual void finishWeightedAverageCalculation( MultiColvarFunction* func ); +// virtual void finishWeightedAverageCalculation( MultiColvarFunction* func ); /// Add derivatives to the orientations - virtual void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, - const std::vector<double>& weight, MultiColvarFunction* func ); +// virtual void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, +// const std::vector<double>& weight, MultiColvarFunction* func ); /// Is the iatom'th stored value currently active bool storedValueIsActive( const unsigned& iatom ); /// This is true if multicolvar is calculating a vector or if the multicolvar is the density @@ -197,58 +163,39 @@ bool MultiColvarBase::usesPbc() const { return usepbc; } -inline -unsigned MultiColvarBase::getNumberOfQuantities(){ - return 5; -} - -inline -unsigned MultiColvarBase::getCentralAtomElementIndex(){ - return 2; -} - -inline -unsigned MultiColvarBase::getNAtoms() const { - return natomsper; // colvar_atoms[current].getNumberActive(); -} - -inline -void MultiColvarBase::addAtomsDerivatives(const unsigned& ielem, const unsigned& iatom, const Vector& der ){ - atoms_with_derivatives.activate(iatom); - unsigned ibase=ielem*getNumberOfDerivatives() + 3*iatom; - for(unsigned i=0;i<3;++i) addElementDerivative( ibase + i, der[i] ); -} +// inline +// unsigned MultiColvarBase::getNAtoms() const { +// return natomsper; // colvar_atoms[current].getNumberActive(); +// } + +// inline +// void MultiColvarBase::addAtomsDerivatives(const unsigned& ielem, const unsigned& iatom, const Vector& der ){ +// atoms_with_derivatives.activate(iatom); +// unsigned ibase=ielem*getNumberOfDerivatives() + 3*iatom; +// for(unsigned i=0;i<3;++i) addElementDerivative( ibase + i, der[i] ); +// } +// +// inline +// void MultiColvarBase::addBoxDerivatives(const unsigned& ielem, const Tensor& vir ){ +// unsigned ibase=ielem*getNumberOfDerivatives() + 3*getNumberOfAtoms(); +// for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) addElementDerivative( ibase+3*i+j, vir(i,j) ); +// } +// +// inline +// void MultiColvarBase::addBoxDerivatives(const Tensor& vir){ +// addBoxDerivatives( 0, vir ); +// } + +// inline +// void MultiColvarBase::setWeight( const double& weight ){ +// setElementValue( 1, weight ); +// } + +// inline +// void MultiColvarBase::addBoxDerivativesOfWeight( const Tensor& vir ){ +// addBoxDerivatives( 1, vir ); +// } -inline -void MultiColvarBase::addBoxDerivatives(const unsigned& ielem, const Tensor& vir ){ - unsigned ibase=ielem*getNumberOfDerivatives() + 3*getNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) addElementDerivative( ibase+3*i+j, vir(i,j) ); -} - -inline -void MultiColvarBase::addBoxDerivatives(const Tensor& vir){ - addBoxDerivatives( 0, vir ); -} - -inline -void MultiColvarBase::calculateWeight(){ - setElementValue( 1, 1.0 ); -} - -inline -void MultiColvarBase::setWeight( const double& weight ){ - setElementValue( 1, weight ); -} - -inline -void MultiColvarBase::addBoxDerivativesOfWeight( const Tensor& vir ){ - addBoxDerivatives( 1, vir ); -} - -inline -unsigned MultiColvarBase::getSizeOfAtomsWithDerivatives(){ - return getNumberOfAtoms(); -} } } diff --git a/src/multicolvar/MultiColvarFilter.cpp b/src/multicolvar/MultiColvarFilter.cpp index db194977173338aa91ee5fada8d5ce0f3f085100..8e583713309da03f66e53424a8adabdab90a4976 100644 --- a/src/multicolvar/MultiColvarFilter.cpp +++ b/src/multicolvar/MultiColvarFilter.cpp @@ -43,38 +43,29 @@ void MultiColvarFilter::doJobsRequiredBeforeTaskList(){ ActionWithVessel::doJobsRequiredBeforeTaskList(); } -void MultiColvarFilter::completeTask(){ - MultiColvarBase* mcolv=getPntrToMultiColvar(); - // Copy the derivatives across - mcolv->copyElementsToBridgedColvar( this ); +void MultiColvarFilter::completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){ + invals.copyValues( outvals ); + if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); + // Retrive the value of the multicolvar and apply filter - double val=getElementValue(0), df, weight=applyFilter( val, df ); + double val=invals.get(1), df, weight=applyFilter( val, df ); // Now propegate derivatives - if( !mcolv->weightHasDerivatives ){ - unsigned nstart=getNumberOfDerivatives(); setElementValue( 1, weight ); - for(unsigned i=0;i<mcolv->atoms_with_derivatives.getNumberActive();++i){ - unsigned n=mcolv->atoms_with_derivatives[i], nx=3*n; - atoms_with_derivatives.activate(n); - addElementDerivative( nstart+nx+0, df*getElementDerivative(nx+0) ); - addElementDerivative( nstart+nx+1, df*getElementDerivative(nx+1) ); - addElementDerivative( nstart+nx+2, df*getElementDerivative(nx+2) ); - } - for(unsigned i=3*mcolv->getNumberOfAtoms();i<mcolv->getNumberOfDerivatives();++i){ - addElementDerivative( nstart+i, df*getElementDerivative(i) ); + if( !getPntrToMultiColvar()->weightHasDerivatives ){ + outvals.setValue( 0, weight ); + if( derivativesAreRequired() ){ + for(unsigned i=0;i<invals.getNumberActive();++i){ + unsigned jder=invals.getActiveIndex(i); + outvals.addDerivative( 0, jder, df*invals.getDerivative(1, jder ) ); + } } } else { - unsigned nstart=getNumberOfDerivatives(); - double ww=mcolv->getElementValue(1); setElementValue( 1, ww*weight ); - for(unsigned i=0;i<mcolv->atoms_with_derivatives.getNumberActive();++i){ - unsigned n=mcolv->atoms_with_derivatives[i], nx=3*n; - atoms_with_derivatives.activate(n); - addElementDerivative( nstart+nx+0, weight*mcolv->getElementDerivative(nstart+nx+0) + ww*df*getElementDerivative(nx+0) ); - addElementDerivative( nstart+nx+1, weight*mcolv->getElementDerivative(nstart+nx+0) + ww*df*getElementDerivative(nx+1) ); - addElementDerivative( nstart+nx+2, weight*mcolv->getElementDerivative(nstart+nx+0) + ww*df*getElementDerivative(nx+2) ); - } - for(unsigned i=3*mcolv->getNumberOfAtoms();i<mcolv->getNumberOfDerivatives();++i){ - addElementDerivative( nstart+i, weight*mcolv->getElementDerivative(nstart+i) + ww*df*getElementDerivative(i) ); + double ww=outvals.get(0); outvals.setValue( 0, ww*weight ); + if( derivativesAreRequired() ){ + for(unsigned i=0;i<outvals.getNumberActive();++i){ + unsigned ider=outvals.getActiveIndex(i); + outvals.setDerivative( 0, ider, weight*outvals.getDerivative(1,ider) + ww*df*outvals.getDerivative(0,ider) ); + } } } } diff --git a/src/multicolvar/MultiColvarFilter.h b/src/multicolvar/MultiColvarFilter.h index ea44d76f4fc1c1b3589d4ec786ba060155d533a5..5fa523ede97ba2f521e714288c71d422b1ba874c 100644 --- a/src/multicolvar/MultiColvarFilter.h +++ b/src/multicolvar/MultiColvarFilter.h @@ -43,7 +43,7 @@ public: /// Get the number of quantities in the colvar unsigned getNumberOfQuantities(); /// Actually do what we are asked - void completeTask(); + void completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ); /// Do the filtering virtual double applyFilter( const double& val, double& df )=0; /// Just checks there are no bridging forces diff --git a/src/multicolvar/MultiColvarFunction.cpp b/src/multicolvar/MultiColvarFunction.cpp index 3304f262b4a2b339966ac7085a84d1af2d3161fb..a562c64db80fef731b8f6b5bb0fab8b524a5f0f4 100644 --- a/src/multicolvar/MultiColvarFunction.cpp +++ b/src/multicolvar/MultiColvarFunction.cpp @@ -42,7 +42,8 @@ MultiColvarBase(ao), wtolerance(0.0) { // Read in the arguments - std::string mname; std::vector<std::string> mlabs; parseVector("DATA",mlabs); + std::string mname; + std::vector<std::string> mlabs; parseVector("DATA",mlabs); log.printf(" using colvars calculated by actions "); bool useweights=false; for(unsigned i=0;i<mlabs.size();++i){ log.printf("%s ",mlabs[i].c_str() ); @@ -51,7 +52,6 @@ wtolerance(0.0) // Check all base multicolvars are of same type if( i==0 ){ mname = mycolv->getName(); - tvals.resize( mycolv->getNumberOfQuantities()-4 ); if( mycolv->isPeriodic() ) error("multicolvar functions don't work with this multicolvar"); } else { if( mname!=mycolv->getName() ) error("All input multicolvars must be of same type"); @@ -67,10 +67,13 @@ wtolerance(0.0) // And track which variable stores each colvar for(unsigned j=0;j<mycolv->getFullNumberOfTasks();++j) colvar_label.push_back( i ); } - log.printf("\n"); + log.printf("\n"); if( keywords.exists("WTOL") && useweights ){ - parse("WTOL",wtolerance); + parse("WTOL",wtolerance); log.printf(" only considering those colvars with a weight greater than %f \n",wtolerance); + for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasedata.push_back( mybasemulticolvars[i]->buildDataStashes( true, wtolerance ) ); + } else { + for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasedata.push_back( mybasemulticolvars[i]->buildDataStashes( false, 0.0 ) ); } } @@ -95,11 +98,11 @@ void MultiColvarFunction::buildSymmetryFunctionLists(){ if( mybasemulticolvars.size()>2 ) error("Found too many multicolvars in DATA specification. You can use either 1 or 2"); // Make sure information is stored in the required multicolvars - if( keywords.exists("WTOL") ){ - for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( true, wtolerance ); - } else { - for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( false, 0.0 ); - } +// if( keywords.exists("WTOL") ){ +// for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( true, wtolerance ); +// } else { +// for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( false, 0.0 ); +// } usespecies=true; ablocks.resize( 1 ); for(unsigned i=0;i<mybasemulticolvars[0]->getFullNumberOfTasks();++i) addTaskToList( i ); @@ -109,7 +112,8 @@ void MultiColvarFunction::buildSymmetryFunctionLists(){ ntotal += mybasemulticolvars[i]->getFullNumberOfTasks(); } unsigned k=0, start=0; - current_atoms.resize( 1 + ntotal ); ablocks[0].resize( ntotal ); + // current_atoms.resize( 1 + ntotal ); + ablocks[0].resize( ntotal ); for(unsigned i=0;i<mybasemulticolvars.size();++i){ for(unsigned j=0;j<mybasemulticolvars[i]->getFullNumberOfTasks();++j){ ablocks[0][k]=start + j; k++; @@ -125,10 +129,10 @@ void MultiColvarFunction::buildSets(){ if( mybasemulticolvars[i]->getFullNumberOfTasks()!=nblock ){ error("mismatch between numbers of tasks in various base multicolvars"); } - mybasemulticolvars[i]->buildDataStashes( false, 0.0 ); +// mybasemulticolvars[i]->buildDataStashes( false, 0.0 ); } ablocks.resize( mybasemulticolvars.size() ); - usespecies=false; current_atoms.resize( mybasemulticolvars.size() ); + usespecies=false; // current_atoms.resize( mybasemulticolvars.size() ); for(unsigned i=0;i<mybasemulticolvars.size();++i){ ablocks[i].resize( nblock ); for(unsigned j=0;j<nblock;++j) ablocks[i][j]=i*nblock+j; @@ -149,13 +153,13 @@ void MultiColvarFunction::buildAtomListWithPairs( const bool& allow_intra_group if( !allow_intra_group && mybasemulticolvars.size()>2 ) error("only two input multicolvars allowed with this function"); // Make sure information is stored in the required multicolvars - if( keywords.exists("WTOL") ){ - for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( true, wtolerance ); - } else { - for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( false, 0.0 ); - } +// if( keywords.exists("WTOL") ){ +// for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( true, wtolerance ); +// } else { +// for(unsigned i=0;i<mybasemulticolvars.size();++i) mybasemulticolvars[i]->buildDataStashes( false, 0.0 ); +// } - usespecies=false; ablocks.resize(2); current_atoms.resize( 2 ); + usespecies=false; ablocks.resize(2); // current_atoms.resize( 2 ); if( !allow_intra_group && mybasemulticolvars.size()==2 ){ nblock = mybasemulticolvars[0]->getFullNumberOfTasks(); if( mybasemulticolvars[1]->getFullNumberOfTasks()>nblock ) nblock = mybasemulticolvars[1]->getFullNumberOfTasks(); @@ -237,35 +241,73 @@ void MultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ){ } } -void MultiColvarFunction::addStoredDerivative( const unsigned& jout, const unsigned& base_cv_no, const unsigned& base_index, const double& der ){ - plumed_dbg_assert( jout<getNumberOfQuantities() && base_cv_no<mybasemulticolvars.size() && base_index<mybasemulticolvars[base_cv_no]->getNumberOfDerivatives() ); - - unsigned mbase = 3*mybasemulticolvars[base_cv_no]->getSizeOfAtomsWithDerivatives(), tbase = 3*getNumberOfAtoms(); - if( base_index>=mbase ){ - // Add virial element - unsigned jindex = base_index - mbase + tbase; - addElementDerivative( jout*getNumberOfDerivatives() + jindex, der ); - } else { - // Add atomic element - unsigned offset=0; for(unsigned i=0;i<base_cv_no;++i) offset += 3*mybasemulticolvars[i]->getNumberOfAtoms(); - unsigned jindex = offset + base_index; - plumed_dbg_assert( jindex<3*getNumberOfAtoms() ); - addElementDerivative( jout*getNumberOfDerivatives() + jindex, der ); - unsigned iatom = ( jindex / 3 ); - atoms_with_derivatives.activate( iatom ); - } +void MultiColvarFunction::updateActiveAtoms( AtomValuePack& myatoms ){ + myatoms.updateDynamicList(); } -void MultiColvarFunction::updateActiveAtoms(){ - if( atoms_with_derivatives.updateComplete() ) return; - atoms_with_derivatives.updateActiveMembers(); +void MultiColvarFunction::getVectorDerivatives( const unsigned& ind, const bool& normed, vesselbase::MultiValue& myder ){ + plumed_dbg_assert( ind<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ind]; + plumed_dbg_assert( mybasedata[mmc]->storedValueIsActive( convertToLocalIndex(ind,mmc) ) ); + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); + mybasedata[mmc]->retrieveDerivatives( convertToLocalIndex(ind,mmc), normed, myder ); } -Vector MultiColvarFunction::calculateCentralAtomPosition(){ - Vector catom=getCentralAtom(); - atomsWithCatomDer.updateActiveMembers(); - return catom; +void MultiColvarFunction::mergeVectorDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, + const unsigned& jatom, const std::vector<double>& der, + vesselbase::MultiValue& myder, AtomValuePack& myatoms ){ + plumed_dbg_assert( ival<myatoms.getUnderlyingMultiValue().getNumberOfValues() ); + plumed_dbg_assert( start<myder.getNumberOfValues() && end<=myder.getNumberOfValues() ); + plumed_dbg_assert( der.size()==myder.getNumberOfValues() && jatom<getFullNumberOfBaseTasks() ); + + unsigned mmc=colvar_label[jatom]; plumed_dbg_assert( mybasedata[mmc]->storedValueIsActive( convertToLocalIndex(jatom,mmc) ) ); + + // Get start of indices for this atom + unsigned basen=0; for(unsigned i=0;i<mmc;++i) basen+=3*mybasemulticolvars[i]->getNumberOfAtoms(); + // Now get the start of the virial + unsigned virbas = 3*getNumberOfAtoms(); + + vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue(); + for(unsigned j=0;j<myder.getNumberActive();++j){ + unsigned jder=myder.getActiveIndex(j); + if( jder<3*mybasemulticolvars[mmc]->getNumberOfAtoms() ){ + unsigned kder=basen+jder; + for(unsigned icomp=start;icomp<end;++icomp){ + myvals.addDerivative( ival, kder, der[icomp]*myder.getDerivative( icomp, jder ) ); + } + } else { + unsigned kder=virbas + (jder - 3*mybasemulticolvars[mmc]->getNumberOfAtoms()); + for(unsigned icomp=start;icomp<end;++icomp){ + myvals.addDerivative( ival, kder, der[icomp]*myder.getDerivative( icomp, jder ) ); + } + } + } } + + +// void MultiColvarFunction::addStoredDerivative( const unsigned& jout, const unsigned& base_cv_no, const unsigned& base_index, const double& der ){ +// plumed_dbg_assert( jout<getNumberOfQuantities() && base_cv_no<mybasemulticolvars.size() && base_index<mybasemulticolvars[base_cv_no]->getNumberOfDerivatives() ); +// +// unsigned mbase = 3*mybasemulticolvars[base_cv_no]->getSizeOfAtomsWithDerivatives(), tbase = 3*getNumberOfAtoms(); +// if( base_index>=mbase ){ +// // Add virial element +// unsigned jindex = base_index - mbase + tbase; +// addElementDerivative( jout*getNumberOfDerivatives() + jindex, der ); +// } else { +// // Add atomic element +// unsigned offset=0; for(unsigned i=0;i<base_cv_no;++i) offset += 3*mybasemulticolvars[i]->getNumberOfAtoms(); +// unsigned jindex = offset + base_index; +// plumed_dbg_assert( jindex<3*getNumberOfAtoms() ); +// addElementDerivative( jout*getNumberOfDerivatives() + jindex, der ); +// unsigned iatom = ( jindex / 3 ); +// atoms_with_derivatives.activate( iatom ); +// } +// } + +// Vector MultiColvarFunction::calculateCentralAtomPosition(){ +// Vector catom=getCentralAtom(); +// atomsWithCatomDer.updateActiveMembers(); +// return catom; +// } } } diff --git a/src/multicolvar/MultiColvarFunction.h b/src/multicolvar/MultiColvarFunction.h index 6105ab60bef18f0789234bf20e67830d5b4ba5e9..cd8e95ab1b4a5c31d945dff97d8f530b23fb75fb 100644 --- a/src/multicolvar/MultiColvarFunction.h +++ b/src/multicolvar/MultiColvarFunction.h @@ -24,7 +24,9 @@ #include "tools/Matrix.h" #include "MultiColvarBase.h" -#include "StoreCentralAtomsVessel.h" +#include "AtomValuePack.h" +#include "CatomPack.h" +#include "vesselbase/StoreDataVessel.h" namespace PLMD { namespace multicolvar { @@ -33,8 +35,10 @@ class MultiColvarFunction : public MultiColvarBase { private: /// Tolerance used for weights of elements double wtolerance; -/// The multicolvar from which we construct these quantities - std::vector<multicolvar::MultiColvarBase*> mybasemulticolvars; +/// The multicolvars from which we construct these quantities + std::vector<MultiColvarBase*> mybasemulticolvars; +/// The vessels in these multicolvars in which the data is stored + std::vector<vesselbase::StoreDataVessel*> mybasedata; /// This is used to keep track of what is calculated where std::vector<unsigned> colvar_label; /// A tempory vector that is used for retrieving vectors @@ -44,28 +48,38 @@ private: protected: /// Get the total number of tasks that this calculation is based on unsigned getFullNumberOfBaseTasks() const ; +/// Get the derivatives for the central atom with index ind + CatomPack getCentralAtomPackFromInput( const unsigned& ind ); +/// + void getVectorForTask( const unsigned& ind, const bool& normed, std::vector<double>& orient0 ); +/// + void getVectorDerivatives( const unsigned& ind, const bool& normed, vesselbase::MultiValue& myder0 ); +/// + void mergeVectorDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, + const unsigned& jatom, const std::vector<double>& der, + vesselbase::MultiValue& myder, AtomValuePack& myatoms ); /// Get the index of the ith colvar we are using - unsigned getColvarIndex( const unsigned& ) const; +// unsigned getColvarIndex( const unsigned& ) const; /// Get the position of one of the central atoms - Vector getPositionOfCentralAtom(const unsigned&) const; +// Vector getPositionOfCentralAtom(const unsigned&) const; /// Add derivatives of value wrt to an atomic position - void addCentralAtomsDerivatives( const unsigned& , const unsigned& , const Vector& ); +// void addCentralAtomsDerivatives( const unsigned& , const unsigned& , const Vector& ); /// Extract the value for the iatom th base task (this ignores current_atoms) - void extractValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ); +// void extractValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ); /// Retrieve the value calculated by the iatom th base task (this uses current_atoms) - void getValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ); +// void getValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ); /// Retrieve the vector calculated by the iatom th base task (this uses current_atoms) - void getVectorForBaseTask( const unsigned& iatom, std::vector<double>& vecs ); +// void getVectorForBaseTask( const unsigned& iatom, std::vector<double>& vecs ); /// Add the derivatives of this quantity (this ignores current_atoms) - void extractWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ); +// void extractWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ); /// Add the value and derivatives of this quantity (this uses current_atoms) - void accumulateWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ); +// void accumulateWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ); /// Add derivative wrt to the position of the central atom - void addDerivativeOfCentralAtomPos( const unsigned& iatom, const Tensor& der ); +// void addDerivativeOfCentralAtomPos( const unsigned& iatom, const Tensor& der ); /// Convert an index in the global array to an index in the individual base colvars unsigned convertToLocalIndex( const unsigned& index, const unsigned& mcv_code ) const ; /// Add derivatives to the orientation - void addOrientationDerivatives( const unsigned& iatom, const std::vector<double>& der ); +// void addOrientationDerivatives( const unsigned& iatom, const std::vector<double>& der ); /// Build sets by taking one multicolvar from each base void buildSets(); /// Build colvars for atoms as if they were symmetry functions @@ -82,21 +96,21 @@ public: MultiColvarFunction(const ActionOptions&); static void registerKeywords( Keywords& keys ); /// Active element in atoms_with_derivatives - void atomHasDerivative( const unsigned& iatom ); +// void atomHasDerivative( const unsigned& iatom ); /// Resize the dynamic arrays - void resizeDynamicArrays(); +// void resizeDynamicArrays(); /// Update the atoms that are active - virtual void updateActiveAtoms(); + virtual void updateActiveAtoms( AtomValuePack& myatoms ); /// Regular calculate void calculate(); /// Calculate the numerical derivatives for this action void calculateNumericalDerivatives( ActionWithValue* a=NULL ); /// Calculate the position of the central atom - Vector calculateCentralAtomPosition(); +// Vector calculateCentralAtomPosition(); /// Get the position of the central atom - virtual Vector getCentralAtom()=0; +// virtual Vector getCentralAtom()=0; /// Add derivatives from storage vessels in MultiColvarBase - void addStoredDerivative( const unsigned&, const unsigned&, const unsigned&, const double& ); +// void addStoredDerivative( const unsigned&, const unsigned&, const unsigned&, const double& ); /// This is used in MultiColvarBase only - it is used to setup the link cells Vector getPositionOfAtomForLinkCells( const unsigned& iatom ); /// Some things can be inactive in functions @@ -106,7 +120,7 @@ public: inline bool MultiColvarFunction::isCurrentlyActive( const unsigned& code ){ plumed_dbg_assert( code<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[code]; - return mybasemulticolvars[mmc]->storedValueIsActive( convertToLocalIndex(code,mmc) ); + return mybasedata[mmc]->storedValueIsActive( convertToLocalIndex(code,mmc) ); } inline @@ -135,83 +149,98 @@ unsigned MultiColvarFunction::convertToLocalIndex( const unsigned& index, const inline unsigned MultiColvarFunction::getBaseColvarNumber( const unsigned& iatom ) const { - return colvar_label[ current_atoms[iatom] ]; + return colvar_label[iatom]; } inline Vector MultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ){ plumed_dbg_assert( iatom<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ iatom ]; - return mybasemulticolvars[mmc]->getCentralAtomPosition( convertToLocalIndex(iatom,mmc) ); -} - -inline -Vector MultiColvarFunction::getPositionOfCentralAtom( const unsigned& iatom ) const { - plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; - return mybasemulticolvars[mmc]->getCentralAtomPosition( convertToLocalIndex(current_atoms[iatom],mmc) ); -} - -inline -void MultiColvarFunction::addCentralAtomsDerivatives( const unsigned& iatom, const unsigned& jout, const Vector& der ){ - if( doNotCalculateDerivatives() ) return ; - - plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; - mybasemulticolvars[mmc]->addCentralAtomDerivativeToFunction( convertToLocalIndex(current_atoms[iatom],mmc), jout, mmc, der, this ); -} - -inline -void MultiColvarFunction::atomHasDerivative( const unsigned& iatom ){ - plumed_dbg_assert( !doNotCalculateDerivatives() ); - atoms_with_derivatives.activate( iatom ); -} - -inline -void MultiColvarFunction::addDerivativeOfCentralAtomPos( const unsigned& iatom, const Tensor& der ){ - if( doNotCalculateDerivatives() ) return; - - plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; Vector tmpder; - for(unsigned i=0;i<3;++i){ - for(unsigned j=0;j<3;++j) tmpder[j]=der(i,j); - mybasemulticolvars[mmc]->addCentralAtomDerivativeToFunction( convertToLocalIndex(current_atoms[iatom],mmc), (2+i), mmc, tmpder, this ); - } -} - -inline -void MultiColvarFunction::extractValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ){ - unsigned mmc = colvar_label[iatom]; mybasemulticolvars[mmc]->getValueForTask( convertToLocalIndex(iatom,mmc), vals ); -} - -inline -void MultiColvarFunction::getValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ){ - plumed_dbg_assert( iatom<natomsper ); extractValueForBaseTask( current_atoms[iatom], vals ); -} - -inline -void MultiColvarFunction::getVectorForBaseTask( const unsigned& iatom, std::vector<double>& vec ){ - plumed_dbg_assert( vec.size()==mybasemulticolvars[0]->getNumberOfQuantities()-5 && tvals.size()>1 ); - getValueForBaseTask( iatom, tvals ); for(unsigned i=0;i<vec.size();++i) vec[i]=tvals[i+1]; -} - -inline -void MultiColvarFunction::extractWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ){ - if( doNotCalculateDerivatives() ) return; - unsigned mmc = colvar_label[iatom]; - mybasemulticolvars[mmc]->addWeightedValueDerivatives( convertToLocalIndex(iatom, mmc), mmc, weight, this ); -} - -inline -void MultiColvarFunction::accumulateWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ){ - if( doNotCalculateDerivatives() ) return; - plumed_dbg_assert( iatom<natomsper ); extractWeightedAverageAndDerivatives( current_atoms[iatom], weight ); -} - -inline -void MultiColvarFunction::addOrientationDerivatives( const unsigned& iatom , const std::vector<double>& der ){ - if( doNotCalculateDerivatives() ) return; - - plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; - unsigned jout=2; if( usespecies && iatom==0 ) jout=1; - mybasemulticolvars[mmc]->addOrientationDerivativesToBase( convertToLocalIndex(current_atoms[iatom],mmc), jout, mmc, der, this ); -} + return mybasemulticolvars[mmc]->getCentralAtomPos( convertToLocalIndex(iatom,mmc) ); +} + +inline +CatomPack MultiColvarFunction::getCentralAtomPackFromInput( const unsigned& ind ){ + plumed_dbg_assert( ind<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ind]; + unsigned basen=0; + for(unsigned i=0;i<mmc;++i) basen+=mybasemulticolvars[i]->getNumberOfAtoms(); + return mybasemulticolvars[mmc]->getCentralAtomPack( basen, convertToLocalIndex(ind,mmc) ); +} + +inline +void MultiColvarFunction::getVectorForTask( const unsigned& ind, const bool& normed, std::vector<double>& orient ){ + plumed_dbg_assert( ind<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ind]; + plumed_dbg_assert( mybasedata[mmc]->storedValueIsActive( convertToLocalIndex(ind,mmc) ) ); + mybasedata[mmc]->retrieveValue( convertToLocalIndex(ind,mmc), normed, orient ); +} + +// inline +// Vector MultiColvarFunction::getPositionOfCentralAtom( const unsigned& iatom ) const { +// plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; +// return mybasemulticolvars[mmc]->getCentralAtomPosition( convertToLocalIndex(current_atoms[iatom],mmc) ); +// } +// +// inline +// void MultiColvarFunction::addCentralAtomsDerivatives( const unsigned& iatom, const unsigned& jout, const Vector& der ){ +// if( doNotCalculateDerivatives() ) return ; +// +// plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; +// mybasemulticolvars[mmc]->addCentralAtomDerivativeToFunction( convertToLocalIndex(current_atoms[iatom],mmc), jout, mmc, der, this ); +// } + +// inline +// void MultiColvarFunction::atomHasDerivative( const unsigned& iatom ){ +// plumed_dbg_assert( !doNotCalculateDerivatives() ); +// atoms_with_derivatives.activate( iatom ); +// } + +// inline +// void MultiColvarFunction::addDerivativeOfCentralAtomPos( const unsigned& iatom, const Tensor& der ){ +// if( doNotCalculateDerivatives() ) return; +// +// plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; Vector tmpder; +// for(unsigned i=0;i<3;++i){ +// for(unsigned j=0;j<3;++j) tmpder[j]=der(i,j); +// mybasemulticolvars[mmc]->addCentralAtomDerivativeToFunction( convertToLocalIndex(current_atoms[iatom],mmc), (2+i), mmc, tmpder, this ); +// } +// } + +// inline +// void MultiColvarFunction::extractValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ){ +// unsigned mmc = colvar_label[iatom]; mybasemulticolvars[mmc]->getValueForTask( convertToLocalIndex(iatom,mmc), vals ); +// } +// +// inline +// void MultiColvarFunction::getValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ){ +// plumed_dbg_assert( iatom<natomsper ); extractValueForBaseTask( current_atoms[iatom], vals ); +// } + +// inline +// void MultiColvarFunction::getVectorForBaseTask( const unsigned& iatom, std::vector<double>& vec ){ +// plumed_dbg_assert( vec.size()==mybasemulticolvars[0]->getNumberOfQuantities()-5 && tvals.size()>1 ); +// getValueForBaseTask( iatom, tvals ); for(unsigned i=0;i<vec.size();++i) vec[i]=tvals[i+1]; +// } + +// inline +// void MultiColvarFunction::extractWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ){ +// if( doNotCalculateDerivatives() ) return; +// unsigned mmc = colvar_label[iatom]; +// mybasemulticolvars[mmc]->addWeightedValueDerivatives( convertToLocalIndex(iatom, mmc), mmc, weight, this ); +// } +// +// inline +// void MultiColvarFunction::accumulateWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ){ +// if( doNotCalculateDerivatives() ) return; +// plumed_dbg_assert( iatom<natomsper ); extractWeightedAverageAndDerivatives( current_atoms[iatom], weight ); +// } +// +// inline +// void MultiColvarFunction::addOrientationDerivatives( const unsigned& iatom , const std::vector<double>& der ){ +// if( doNotCalculateDerivatives() ) return; +// +// plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; +// unsigned jout=2; if( usespecies && iatom==0 ) jout=1; +// mybasemulticolvars[mmc]->addOrientationDerivativesToBase( convertToLocalIndex(current_atoms[iatom],mmc), jout, mmc, der, this ); +// } } } diff --git a/src/multicolvar/NumberOfLinks.cpp b/src/multicolvar/NumberOfLinks.cpp index 730539252a62070a504b8d0f763de01a5bb37f31..dbc11d8b89556408456f3f7f070da0f58fd92bbb 100644 --- a/src/multicolvar/NumberOfLinks.cpp +++ b/src/multicolvar/NumberOfLinks.cpp @@ -75,11 +75,9 @@ public: static void registerKeywords( Keywords& keys ); NumberOfLinks(const ActionOptions&); /// Do the stuff with the switching functions - void calculateWeight(); + void calculateWeight( AtomValuePack& myatoms ); /// Actually do the calculation - double compute(); -/// This returns the position of the central atom - Vector getCentralAtom(); + double compute( const unsigned& tindex, AtomValuePack& myatoms ); /// Is the variable periodic bool isPeriodic(){ return false; } }; @@ -124,14 +122,6 @@ MultiColvarFunction(ao) for(unsigned i=0;i<getNumberOfBaseMultiColvars();++i){ if( !getBaseMultiColvar(i)->hasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); } - - // Resize these ready for business - if( getBaseMultiColvar(0)->getNumberOfQuantities()==5 ){ - orient0.resize( 1 ); orient1.resize( 1 ); - } else { - orient0.resize( getBaseMultiColvar(0)->getNumberOfQuantities() - 5 ); - orient1.resize( getBaseMultiColvar(0)->getNumberOfQuantities() - 5 ); - } // Create holders for the collective variable readVesselKeywords(); @@ -140,36 +130,44 @@ MultiColvarFunction(ao) readVesselKeywords(); } -void NumberOfLinks::calculateWeight(){ - Vector distance = getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(1) ); +void NumberOfLinks::calculateWeight( AtomValuePack& myatoms ){ + Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc ); - addCentralAtomsDerivatives( 0, 1, (-dfunc)*distance ); - addCentralAtomsDerivatives( 1, 1, (dfunc)*distance ); - MultiColvarBase::addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); - setElementValue(1,sw); + myatoms.setValue(0,sw); + + if( !doNotCalculateDerivatives() ){ + CatomPack atom0=getCentralAtomPackFromInput( myatoms.getIndex(0) ); + myatoms.addComDerivatives( 0, (-dfunc)*distance, atom0 ); + CatomPack atom1=getCentralAtomPackFromInput( myatoms.getIndex(1) ); + myatoms.addComDerivatives( 0, (dfunc)*distance, atom1 ); + myatoms.addBoxDerivatives( 0, (-dfunc)*Tensor(distance,distance) ); + } } -double NumberOfLinks::compute(){ - getVectorForBaseTask( 0, orient0 ); - getVectorForBaseTask( 1, orient1 ); +double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ){ + if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; + + unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities(); + + std::vector<double> orient0( ncomp ), orient1( ncomp ); + getVectorForTask( myatoms.getIndex(0), true, orient0 ); + getVectorForTask( myatoms.getIndex(1), true, orient1 ); double dot=0; - for(unsigned k=0;k<orient0.size();++k){ + for(unsigned k=2;k<orient0.size();++k){ dot+=orient0[k]*orient1[k]; } -// for(unsigned k=0;k<orient0.size();++k){ -// orient0[k]*=dot_df; orient1[k]*=dot_df; -// } - addOrientationDerivatives( 0, orient1 ); - addOrientationDerivatives( 1, orient0 ); - return dot; -} + if( !doNotCalculateDerivatives() ){ + unsigned nder=getNumberOfDerivatives(); + vesselbase::MultiValue myder0(ncomp,nder), myder1(ncomp,nder); + getVectorDerivatives( myatoms.getIndex(0), true, myder0 ); + mergeVectorDerivatives( 1, 2, orient1.size(), myatoms.getIndex(0), orient1, myder0, myatoms ); + getVectorDerivatives( myatoms.getIndex(1), true, myder1 ); + mergeVectorDerivatives( 1, 2, orient0.size(), myatoms.getIndex(1), orient0, myder1, myatoms ); + } -Vector NumberOfLinks::getCentralAtom(){ - addDerivativeOfCentralAtomPos( 0, 0.5*Tensor::identity() ); - addDerivativeOfCentralAtomPos( 1, 0.5*Tensor::identity() ); - return 0.5*( getPositionOfCentralAtom(0) + getPositionOfCentralAtom(1) ); + return dot; } } diff --git a/src/multicolvar/Sprint.cpp b/src/multicolvar/Sprint.cpp index a8d9194eb07f9df2e99fda7578253f3773d8708f..c007ef84a4ecafcbef025aad55612eab2dd9a04d 100644 --- a/src/multicolvar/Sprint.cpp +++ b/src/multicolvar/Sprint.cpp @@ -169,17 +169,23 @@ void Sprint::completeCalculation(){ else { rank=comm.Get_rank(); stride=comm.Get_size(); } // Derivatives - Matrix<double> mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); - unsigned nval = getFullNumberOfBaseTasks(); mymat_ders=0; + vesselbase::MultiValue myvals( 2, getNumberOfDerivatives() ); + Matrix<double> mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); + std::vector<unsigned> catoms(2); unsigned nval = getFullNumberOfBaseTasks(); mymat_ders=0; for(unsigned i=rank;i<getNumberOfActiveMatrixElements();i+=stride){ - setMatrixIndexesForTask( i ); unsigned j=current_atoms[0], k=current_atoms[1]; + decodeIndexToAtoms( getTaskCode(getActiveMatrixElement(i)), catoms ); unsigned j=catoms[0], k=catoms[1]; double tmp1 = 2 * eigenvecs(nval-1,j)*eigenvecs(nval-1,k); for(unsigned icomp=0;icomp<getNumberOfComponents();++icomp){ double tmp2 = 0.; for(unsigned n=0;n<nval-1;++n){ // Need care on following line tmp2 += eigenvecs(n,maxeig[icomp].second) * ( eigenvecs(n,j)*eigenvecs(nval-1,k) + eigenvecs(n,k)*eigenvecs(nval-1,j) ) / ( lambda - eigvals[n] ); } - addDerivativesOnMatrixElement( i, icomp, sqrtn*( tmp1*maxeig[icomp].first + tmp2*lambda ), mymat_ders ); + double prefactor=sqrtn*( tmp1*maxeig[icomp].first + tmp2*lambda ); + getAdjacencyVessel()->retrieveDerivatives( getActiveMatrixElement(i), false, myvals ); + for(unsigned jd=0;jd<myvals.getNumberActive();++jd){ + unsigned ider=myvals.getActiveIndex(jd); + mymat_ders( icomp, ider ) += prefactor*myvals.getDerivative( 1, ider ); + } } } if( !serialCalculation() ) comm.Sum( mymat_ders ); diff --git a/src/multicolvar/StoreCentralAtomsVessel.cpp b/src/multicolvar/StoreCentralAtomsVessel.cpp deleted file mode 100644 index 1a762cff009affbd51fdec7a223136e3e267ce27..0000000000000000000000000000000000000000 --- a/src/multicolvar/StoreCentralAtomsVessel.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013,2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#include "vesselbase/VesselRegister.h" -#include "vesselbase/ActionWithVessel.h" -#include "tools/DynamicList.h" -#include "MultiColvar.h" -#include "MultiColvarFunction.h" -#include "StoreCentralAtomsVessel.h" - -namespace PLMD { -namespace multicolvar { - -StoreCentralAtomsVessel::StoreCentralAtomsVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da), -tmpdf(3) -{ - mycolv=dynamic_cast<MultiColvarBase*>( getAction() ); - plumed_assert( mycolv ); completeSetup( mycolv->getCentralAtomElementIndex(), 3 ); -} - -void StoreCentralAtomsVessel::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& aindexes ){ - plumed_dbg_assert( mycolv->derivativesAreRequired() ); - - aindexes[jstore]=3*mycolv->atomsWithCatomDer.getNumberActive(); - if( aindexes[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); - unsigned kder = ntotal + jstore*maxder; - for(unsigned jder=0;jder<mycolv->atomsWithCatomDer.getNumberActive();++jder){ - unsigned iatom = 3*mycolv->atomsWithCatomDer[jder]; - for(unsigned icomp=0;icomp<3;++icomp){ aindexes[ kder ] = iatom+icomp; kder++; } - } -} - -Vector StoreCentralAtomsVessel::getPosition( const unsigned& iatom ){ - Vector pos; for(unsigned i=0;i<3;++i) pos[i]=getComponent( iatom, i ); - return pos; -} - -void StoreCentralAtomsVessel::performTask( const unsigned& itask ){ - mycolv->atomsWithCatomDer.deactivateAll(); - bool check=mycolv->setupCurrentAtomList( mycolv->getCurrentTask() ); - plumed_dbg_assert( check ); - Vector ignore = mycolv->retrieveCentralAtomPos(); -} - -void StoreCentralAtomsVessel::finishTask( const unsigned& itask ){ - mycolv->atomsWithCatomDer.deactivateAll(); - Vector ignore = mycolv->retrieveCentralAtomPos(); -} - -void StoreCentralAtomsVessel::addAtomsDerivatives( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, - const Vector& df, MultiColvarFunction* funcout ){ - plumed_dbg_assert( mycolv->derivativesAreRequired() ); - - for(unsigned ider=0;ider<getNumberOfDerivatives(iatom);ider+=3){ - for(unsigned i=0;i<3;++i) tmpdf[i]=df[0]; - funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( iatom, ider+0 ), chainRule(iatom, ider+0, tmpdf) ); - for(unsigned i=0;i<3;++i) tmpdf[i]=df[1]; - funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( iatom, ider+1 ), chainRule(iatom, ider+1, tmpdf) ); - for(unsigned i=0;i<3;++i) tmpdf[i]=df[2]; - funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( iatom, ider+2 ), chainRule(iatom, ider+2, tmpdf) ); - } -} - -} -} diff --git a/src/multicolvar/StoreCentralAtomsVessel.h b/src/multicolvar/StoreCentralAtomsVessel.h deleted file mode 100644 index cb8421146987204f38857e982721d3034faa6dfa..0000000000000000000000000000000000000000 --- a/src/multicolvar/StoreCentralAtomsVessel.h +++ /dev/null @@ -1,58 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#ifndef __PLUMED_multicolvar_StoreCentralAtomsVessel_h -#define __PLUMED_multicolvar_StoreCentralAtomsVessel_h - -#include "vesselbase/StoreDataVessel.h" - -namespace PLMD { -namespace multicolvar { - -class MultiColvarBase; -class MultiColvarFunction; - -class StoreCentralAtomsVessel : public vesselbase::StoreDataVessel { -private: -/// The base multicolvar - MultiColvarBase* mycolv; -/// A vector that is used to store derivatives - std::vector<double> tmpdf; -public: -/// Constructor - StoreCentralAtomsVessel( const vesselbase::VesselOptions& ); -/// This does nothing - std::string description(){ return ""; } -/// Get the orientation of the ith vector - Vector getPosition( const unsigned& ); -/// Recalculate the central atom position - void performTask( const unsigned& ); - void finishTask( const unsigned& ); -/// Get the indices - void getIndexList( const unsigned& , const unsigned& , const unsigned& , std::vector<unsigned>& ); -/// Add derivatives to central atom position - void addAtomsDerivatives( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, const Vector& df, MultiColvarFunction* funcout ); -}; - -} -} -#endif - diff --git a/src/multicolvar/StoreColvarVessel.cpp b/src/multicolvar/StoreColvarVessel.cpp deleted file mode 100644 index 332aa0126bf8b7d0d1c773dd6953b813c3771831..0000000000000000000000000000000000000000 --- a/src/multicolvar/StoreColvarVessel.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#include "StoreColvarVessel.h" -#include "MultiColvarFunction.h" - -namespace PLMD { -namespace multicolvar { - -void StoreColvarVessel::registerKeywords( Keywords& keys ){ - StoreDataVessel::registerKeywords( keys ); -} - -StoreColvarVessel::StoreColvarVessel( const vesselbase::VesselOptions& da): -StoreDataVessel(da) -{ - completeSetup( 0, 1 ); -} - -void StoreColvarVessel::chainRuleForComponent( const unsigned& icolv, const unsigned& jout, const unsigned& base_cv_no, - const double& weight, MultiColvarFunction* funcout ){ - plumed_dbg_assert( getAction()->derivativesAreRequired() ); - - if( usingLowMem() ){ - unsigned ibuf = icolv*getAction()->getNumberOfDerivatives(); - for(unsigned ider=0;ider<getNumberOfDerivatives(icolv);++ider){ - funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( icolv, ider ), weight*getLocalDerivative(ibuf+ider) ); - } - } else { - unsigned ibuf = icolv*getNumberOfDerivativeSpacesPerComponent() + 1; - for(unsigned ider=0;ider<getNumberOfDerivatives(icolv);++ider){ -// funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( icolv, ider ), weight*getBufferElement(ibuf+ider) ); - } - } -} - -} -} diff --git a/src/multicolvar/StoreColvarVessel.h b/src/multicolvar/StoreColvarVessel.h deleted file mode 100644 index 751b51b19d802feaa367b8bed2fb74e2d6ea16c4..0000000000000000000000000000000000000000 --- a/src/multicolvar/StoreColvarVessel.h +++ /dev/null @@ -1,51 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#ifndef __PLUMED_multicolvar_StoreColvarVessel_h -#define __PLUMED_multicolvar_StoreColvarVessel_h - -#include <string> -#include <cstring> -#include <vector> -#include "vesselbase/StoreDataVessel.h" - -namespace PLMD { -namespace multicolvar { - -class MultiColvarFunction; - -class StoreColvarVessel : public vesselbase::StoreDataVessel { -public: - static void registerKeywords( Keywords& keys ); - StoreColvarVessel( const vesselbase::VesselOptions& ); - double getValue( const unsigned& ); - virtual std::string description(){ return ""; } - void chainRuleForComponent( const unsigned& , const unsigned& , const unsigned& , const double& , MultiColvarFunction* ); -}; - -inline -double StoreColvarVessel::getValue( const unsigned& ival ){ - return getComponent( ival, 0 ); -} - -} -} -#endif diff --git a/src/multicolvar/Torsions.cpp b/src/multicolvar/Torsions.cpp index 6a8a44fe458e23833344a708997d9e0791a23c2b..154547a4964784b28e9b37c1070e7077077f98c7 100644 --- a/src/multicolvar/Torsions.cpp +++ b/src/multicolvar/Torsions.cpp @@ -75,10 +75,9 @@ class Torsions : public MultiColvar { public: static void registerKeywords( Keywords& keys ); Torsions(const ActionOptions&); - virtual double compute(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); bool isPeriodic(){ return true; } void retrieveDomain( std::string& min, std::string& max ){ min="-pi"; max="pi"; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(Torsions,"TORSIONS") @@ -93,36 +92,33 @@ PLUMED_MULTICOLVAR_INIT(ao) { // Read in the atoms int natoms=4; readAtoms( natoms ); + std::vector<bool> catom_ind(4, false); + catom_ind[1]=catom_ind[2]=true; + setAtomsForCentralAtom( catom_ind ); // Read in the vessels readVesselKeywords(); // And check everything has been read in correctly checkRead(); } -double Torsions::compute(){ +double Torsions::compute( const unsigned& tindex, AtomValuePack& myatoms ){ Vector d0,d1,d2; - d0=getSeparation(getPosition(1),getPosition(0)); - d1=getSeparation(getPosition(2),getPosition(1)); - d2=getSeparation(getPosition(3),getPosition(2)); + d0=getSeparation(myatoms.getPosition(1),myatoms.getPosition(0)); + d1=getSeparation(myatoms.getPosition(2),myatoms.getPosition(1)); + d2=getSeparation(myatoms.getPosition(3),myatoms.getPosition(2)); Vector dd0,dd1,dd2; PLMD::Torsion t; double value = t.compute(d0,d1,d2,dd0,dd1,dd2); - addAtomsDerivatives(0,dd0); - addAtomsDerivatives(1,dd1-dd0); - addAtomsDerivatives(2,dd2-dd1); - addAtomsDerivatives(3,-dd2); + myatoms.addAtomsDerivatives(1,0,dd0); + myatoms.addAtomsDerivatives(1,1,dd1-dd0); + myatoms.addAtomsDerivatives(1,2,dd2-dd1); + myatoms.addAtomsDerivatives(1,3,-dd2); - addBoxDerivatives (-(extProduct(d0,dd0)+extProduct(d1,dd1)+extProduct(d2,dd2))); + myatoms.addBoxDerivatives (1, -(extProduct(d0,dd0)+extProduct(d1,dd1)+extProduct(d2,dd2))); return value; } -Vector Torsions::getCentralAtom(){ - addCentralAtomDerivatives( 1, 0.5*Tensor::identity() ); - addCentralAtomDerivatives( 2, 0.5*Tensor::identity() ); - return 0.5*( getPosition(1) + getPosition(2) ); -} - } } diff --git a/src/multicolvar/VolumeAround.cpp b/src/multicolvar/VolumeAround.cpp index 5440fb4284a2bbf21749256f45cd459c9e0c0f8b..1a70cabb8bea7f2f27f6b94b564236a4448adc0e 100644 --- a/src/multicolvar/VolumeAround.cpp +++ b/src/multicolvar/VolumeAround.cpp @@ -78,7 +78,7 @@ public: static void registerKeywords( Keywords& keys ); VolumeAround(const ActionOptions& ao); void setupRegions(); - double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives ); + double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ); }; PLUMED_REGISTER_ACTION(VolumeAround,"AROUND") @@ -116,7 +116,7 @@ ActionVolume(ao) void VolumeAround::setupRegions(){ } -double VolumeAround::calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives ){ +double VolumeAround::calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ){ // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); @@ -143,9 +143,9 @@ double VolumeAround::calculateNumberInside( const Vector& cpos, HistogramBead& b derivatives[1]=xcontr*yder*zcontr; derivatives[2]=xcontr*ycontr*zder; // Add derivatives wrt to position of origin atom - addReferenceAtomDerivatives( 0, -derivatives ); + refders[0] = -derivatives; // Add virial contribution - addBoxDerivatives( -Tensor(fpos,derivatives) ); + vir -= Tensor(fpos,derivatives); return xcontr*ycontr*zcontr; } diff --git a/src/multicolvar/VolumeCavity.cpp b/src/multicolvar/VolumeCavity.cpp index bc93f3dd1c65757588136aef62e6aa7ffcc76c07..d0f5b59a95560c9ccbcd4cf0013800394f5f7acd 100644 --- a/src/multicolvar/VolumeCavity.cpp +++ b/src/multicolvar/VolumeCavity.cpp @@ -122,7 +122,7 @@ public: ~VolumeCavity(); void setupRegions(); void update(); - double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives ); + double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ); }; PLUMED_REGISTER_ACTION(VolumeCavity,"CAVITY") @@ -340,7 +340,7 @@ void VolumeCavity::update(){ } } -double VolumeCavity::calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives ){ +double VolumeCavity::calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& rderiv ){ // Calculate distance of atom from origin of new coordinate frame Vector datom=pbcDistance( origin, cpos ); double ucontr, uder, vcontr, vder, wcontr, wder; @@ -373,7 +373,6 @@ double VolumeCavity::calculateNumberInside( const Vector& cpos, HistogramBead& b double tot = ucontr*vcontr*wcontr*jacob_det; // Add reference atom derivatives - std::vector<Vector> rderiv(4); dfd[0]=uder2*vcontr*wcontr; dfd[1]=ucontr*vder2*wcontr; dfd[2]=ucontr*vcontr*wder2; Vector dfld; dfld[0]=udlen*vcontr*wcontr; dfld[1]=ucontr*vdlen*wcontr; dfld[2]=ucontr*vcontr*wdlen; rderiv[0] = dfd[0]*matmul(datom,dbi[0]) + dfd[1]*matmul(datom,dcross[0]) + dfd[2]*matmul(datom,dperp[0]) + @@ -384,12 +383,10 @@ double VolumeCavity::calculateNumberInside( const Vector& cpos, HistogramBead& b dfld[0]*dlbi[2] + dfld[1]*dlcross[2] + dfld[2]*dlperp[2]; rderiv[3] = dfld[0]*dlbi[3] + dfld[1]*dlcross[3] + dfld[2]*dlperp[3]; - Tensor vir; vir.zero(); - vir-=Tensor( cpos,derivatives ); + vir.zero(); vir-=Tensor( cpos,derivatives ); for(unsigned i=0;i<4;++i){ - vir -= Tensor( getPosition(i), rderiv[i] ); addReferenceAtomDerivatives( i, rderiv[i] ); + vir -= Tensor( getPosition(i), rderiv[i] ); } - addBoxDerivatives( vir ); return tot; } diff --git a/src/multicolvar/VolumeGradientBase.cpp b/src/multicolvar/VolumeGradientBase.cpp index d2dcdb769573dcec347758d47c39ec924bd3ea29..3f08a5e63b9ff76f5276ae480829d26d7e0b65c2 100644 --- a/src/multicolvar/VolumeGradientBase.cpp +++ b/src/multicolvar/VolumeGradientBase.cpp @@ -20,6 +20,7 @@ along with plumed. If not, see <http://www.gnu.org/licenses/>. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "VolumeGradientBase.h" +#include "CatomPack.h" namespace PLMD { namespace multicolvar { @@ -46,50 +47,81 @@ void VolumeGradientBase::doJobsRequiredBeforeTaskList(){ ActionWithVessel::doJobsRequiredBeforeTaskList(); } -void VolumeGradientBase::completeTask(){ +void VolumeGradientBase::completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){ if( getPntrToMultiColvar()->isDensity() ){ - setElementValue( 0, 1.0 ); + outvals.setValue(0, 1.0); outvals.setValue(1, 1.0); } else { // Copy derivatives of the colvar and the value of the colvar - getPntrToMultiColvar()->copyElementsToBridgedColvar( this ); + invals.copyValues( outvals ); + if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); } - calculateAllVolumes(); + calculateAllVolumes( curr, outvals ); } -void VolumeGradientBase::setNumberInVolume( const unsigned& ivol, const double& weight, const Vector& wdf ){ - MultiColvarBase* mcolv=getPntrToMultiColvar(); +void VolumeGradientBase::setNumberInVolume( const unsigned& ivol, const unsigned& curr, const double& weight, + const Vector& wdf, const Tensor& virial, const std::vector<Vector>& refders, + vesselbase::MultiValue& outvals ){ + MultiColvarBase* mcolv=getPntrToMultiColvar(); if( !mcolv->weightHasDerivatives ){ - unsigned nstart=ivol*getNumberOfDerivatives(); - setElementValue( ivol, weight ); - for(unsigned i=0;i<mcolv->atomsWithCatomDer.getNumberActive();++i){ - unsigned n=mcolv->atomsWithCatomDer[i], nx=nstart + 3*n; - atoms_with_derivatives.activate(n); - addElementDerivative( nx+0, mcolv->getCentralAtomDerivative(n, 0, wdf ) ); - addElementDerivative( nx+1, mcolv->getCentralAtomDerivative(n, 1, wdf ) ); - addElementDerivative( nx+2, mcolv->getCentralAtomDerivative(n, 2, wdf ) ); - } + outvals.setValue(ivol, weight ); + if( derivativesAreRequired() ){ + CatomPack catom( mcolv->getCentralAtomPack( 0, curr ) ); + for(unsigned i=0;i<catom.getNumberOfAtomsWithDerivatives();++i){ + unsigned jatom=3*catom.getIndex(i); + outvals.addDerivative( ivol, jatom+0, catom.getDerivative(i,0,wdf) ); + outvals.addDerivative( ivol, jatom+1, catom.getDerivative(i,1,wdf) ); + outvals.addDerivative( ivol, jatom+2, catom.getDerivative(i,2,wdf) ); + } + unsigned nmder=getPntrToMultiColvar()->getNumberOfDerivatives(); + for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) outvals.addDerivative( ivol, nmder-9+3*i+j, virial(i,j) ); + for(unsigned i=0;i<refders.size();++i){ + unsigned iatom=nmder+3*i; + + outvals.addDerivative( ivol, iatom+0, refders[i][0] ); + outvals.addDerivative( ivol, iatom+1, refders[i][1] ); + outvals.addDerivative( ivol, iatom+2, refders[i][2] ); + } + } + } else if(ivol==0){ + double ww=outvals.get(0); outvals.setValue(ivol,ww*weight); + if( derivativesAreRequired() ){ + plumed_merror("This needs testing"); + CatomPack catom( mcolv->getCentralAtomPack( 0, curr ) ); + for(unsigned i=0;i<catom.getNumberOfAtomsWithDerivatives();++i){ + unsigned jatom=3*catom.getIndex(i); + outvals.addDerivative( ivol, jatom+0, weight*outvals.getDerivative(ivol,jatom+0) + ww*catom.getDerivative(i,0,wdf) ); + outvals.addDerivative( ivol, jatom+1, weight*outvals.getDerivative(ivol,jatom+1) + ww*catom.getDerivative(i,1,wdf) ); + outvals.addDerivative( ivol, jatom+2, weight*outvals.getDerivative(ivol,jatom+2) + ww*catom.getDerivative(i,2,wdf) ); + } + unsigned nmder=getPntrToMultiColvar()->getNumberOfDerivatives(); + for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) outvals.addDerivative( ivol, nmder-9+3*i+j, ww*virial(i,j) ); + for(unsigned i=0;i<refders.size();++i){ + unsigned iatom=nmder+3*i; + outvals.addDerivative( ivol, iatom+0, ww*refders[i][0] ); + outvals.addDerivative( ivol, iatom+1, ww*refders[i][1] ); + outvals.addDerivative( ivol, iatom+2, ww*refders[i][2] ); + } + } } else { - unsigned nstart=ivol*getNumberOfDerivatives(); - double ww=mcolv->getElementValue(1); setElementValue( ivol, ww*weight ); - for(unsigned i=0;i<mcolv->atomsWithCatomDer.getNumberActive();++i){ - unsigned n=mcolv->atomsWithCatomDer[i], nx=nstart + 3*n; - atoms_with_derivatives.activate(n); - addElementDerivative( nx+0, ww*mcolv->getCentralAtomDerivative(n, 0, wdf ) ); - addElementDerivative( nx+1, ww*mcolv->getCentralAtomDerivative(n, 1, wdf ) ); - addElementDerivative( nx+2, ww*mcolv->getCentralAtomDerivative(n, 2, wdf ) ); - } - unsigned nder=mcolv->getNumberOfDerivatives(); - for(unsigned i=0;i<mcolv->atoms_with_derivatives.getNumberActive();++i){ - unsigned n=mcolv->atoms_with_derivatives[i], nx=nder + 3*n, ny=nstart + 3*n; - atoms_with_derivatives.activate(n); - addElementDerivative( ny+0, weight*mcolv->getElementDerivative(nx+0) ); - addElementDerivative( ny+1, weight*mcolv->getElementDerivative(nx+1) ); - addElementDerivative( ny+2, weight*mcolv->getElementDerivative(nx+2) ); - } - unsigned nwvir=mcolv->getNumberOfDerivatives()-9, nwvir2=nstart + 3*mcolv->getNumberOfAtoms(); - for(unsigned i=0;i<9;++i){ - addElementDerivative( nwvir2, weight*mcolv->getElementDerivative(nwvir) ); nwvir++; nwvir2++; - } + double ww=outvals.get(0); outvals.setValue(ivol,ww*weight); + if( derivativesAreRequired() ){ + plumed_merror("This needs testing"); + CatomPack catom( mcolv->getCentralAtomPack( 0, curr ) ); + for(unsigned i=0;i<catom.getNumberOfAtomsWithDerivatives();++i){ + unsigned jatom=3*catom.getIndex(i); + outvals.addDerivative( ivol, jatom+0, ww*catom.getDerivative(i,0,wdf) ); + outvals.addDerivative( ivol, jatom+1, ww*catom.getDerivative(i,1,wdf) ); + outvals.addDerivative( ivol, jatom+2, ww*catom.getDerivative(i,2,wdf) ); + } + unsigned nmder=getPntrToMultiColvar()->getNumberOfDerivatives(); + for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) outvals.addDerivative( ivol, nmder-9+3*i+j, ww*virial(i,j) ); + for(unsigned i=0;i<refders.size();++i){ + unsigned iatom=nmder+3*i; + outvals.addDerivative( ivol, iatom+0, ww*refders[i][0] ); + outvals.addDerivative( ivol, iatom+1, ww*refders[i][1] ); + outvals.addDerivative( ivol, iatom+2, ww*refders[i][2] ); + } + } } } diff --git a/src/multicolvar/VolumeGradientBase.h b/src/multicolvar/VolumeGradientBase.h index fe85c12ae95b65e663094a37d0eaad5b4bd2d694..12a9c09344acd345b1118a94c3b79f5a0950fd6a 100644 --- a/src/multicolvar/VolumeGradientBase.h +++ b/src/multicolvar/VolumeGradientBase.h @@ -46,20 +46,16 @@ protected: /// Request the atoms void requestAtoms( const std::vector<AtomNumber>& atoms ); /// Set the number in the volume - void setNumberInVolume( const unsigned& ivol, const double& weight, const Vector& wdf ); -/// Add derivatinve to one of the reference atoms here - void addReferenceAtomDerivatives( const unsigned& jvol, const unsigned& iatom, const Vector& der ); -/// Add derivatives wrt to the virial - void addBoxDerivatives( const unsigned& jvol, const Tensor& vir ); + void setNumberInVolume( const unsigned& , const unsigned& , const double& , const Vector& , const Tensor& , const std::vector<Vector>& , vesselbase::MultiValue& ); public: static void registerKeywords( Keywords& keys ); VolumeGradientBase(const ActionOptions&); /// Do jobs required before tasks are undertaken void doJobsRequiredBeforeTaskList(); /// Actually do what we are asked - void completeTask(); + void completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ); /// Calculate what is in the volumes - virtual void calculateAllVolumes()=0; + virtual void calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals )=0; /// Setup the regions that this is based on virtual void setupRegions()=0; /// Forces here are applied through the bridge @@ -95,32 +91,6 @@ const Vector & VolumeGradientBase::getPosition( int iatom ){ return tmp_p; } -inline -void VolumeGradientBase::addReferenceAtomDerivatives( const unsigned& jvol, const unsigned& iatom, const Vector& der ){ - // This is used for storing the derivatives wrt to the - // positions of any additional reference atoms - double pref=getPntrToMultiColvar()->getElementValue(1); - unsigned nstart = jvol*getNumberOfDerivatives() + getPntrToMultiColvar()->getNumberOfDerivatives() + 3*iatom; - addElementDerivative( nstart + 0, pref*der[0] ); - addElementDerivative( nstart + 1, pref*der[1] ); - addElementDerivative( nstart + 2, pref*der[2] ); -} - -inline -void VolumeGradientBase::addBoxDerivatives( const unsigned& jvol, const Tensor& vir ){ - double pref=getPntrToMultiColvar()->getElementValue(1); - unsigned nstart = jvol*getNumberOfDerivatives() + getPntrToMultiColvar()->getNumberOfDerivatives() - 9; - addElementDerivative( nstart + 0, pref*vir(0,0) ); - addElementDerivative( nstart + 1, pref*vir(0,1) ); - addElementDerivative( nstart + 2, pref*vir(0,2) ); - addElementDerivative( nstart + 3, pref*vir(1,0) ); - addElementDerivative( nstart + 4, pref*vir(1,1) ); - addElementDerivative( nstart + 5, pref*vir(1,2) ); - addElementDerivative( nstart + 6, pref*vir(2,0) ); - addElementDerivative( nstart + 7, pref*vir(2,1) ); - addElementDerivative( nstart + 8, pref*vir(2,2) ); -} - } } #endif diff --git a/src/multicolvar/XDistances.cpp b/src/multicolvar/XDistances.cpp index 41e40524aa0eff48e2cad6177f877e5016170649..c6ac26e960b9ad975cb29837b61b8797e947ebae 100644 --- a/src/multicolvar/XDistances.cpp +++ b/src/multicolvar/XDistances.cpp @@ -115,10 +115,9 @@ public: static void registerKeywords( Keywords& keys ); XDistances(const ActionOptions&); // active methods: - virtual double compute(); + virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); /// Returns the number of coordinates of the field bool isPeriodic(){ return false; } - Vector getCentralAtom(); }; PLUMED_REGISTER_ACTION(XDistances,"XDISTANCES") @@ -151,25 +150,19 @@ PLUMED_MULTICOLVAR_INIT(ao) checkRead(); } -double XDistances::compute(){ +double XDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ){ Vector distance; - distance=getSeparation( getPosition(0), getPosition(1) ); + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); const double value=distance[myc]; Vector myvec; myvec.zero(); // And finish the calculation - myvec[myc]=+1; addAtomsDerivatives( 1,myvec ); - myvec[myc]=-1; addAtomsDerivatives( 0,myvec ); - addBoxDerivatives( Tensor(distance,myvec) ); + myvec[myc]=+1; myatoms.addAtomsDerivatives( 1, 1, myvec ); + myvec[myc]=-1; myatoms.addAtomsDerivatives( 1, 0, myvec ); + myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); return value; } -Vector XDistances::getCentralAtom(){ - addCentralAtomDerivatives( 0, 0.5*Tensor::identity() ); - addCentralAtomDerivatives( 1, 0.5*Tensor::identity() ); - return 0.5*( getPosition(0) + getPosition(1) ); -} - } } diff --git a/src/secondarystructure/SecondaryStructureRMSD.cpp b/src/secondarystructure/SecondaryStructureRMSD.cpp index 012c49bf92b4381be4793fd08c87e9f774247350..3eaa972e34cf7495484aa93a63db2682a90df4ce 100644 --- a/src/secondarystructure/SecondaryStructureRMSD.cpp +++ b/src/secondarystructure/SecondaryStructureRMSD.cpp @@ -205,15 +205,15 @@ void SecondaryStructureRMSD::calculate(){ runAllTasks(); } -void SecondaryStructureRMSD::performTask(){ +void SecondaryStructureRMSD::performTask( const unsigned& task_index, const unsigned& current, vesselbase::MultiValue& myvals ){ // Retrieve the positions - for(unsigned i=0;i<pos.size();++i) pos[i]=ActionAtomistic::getPosition( getAtomIndex(i) ); + for(unsigned i=0;i<pos.size();++i) pos[i]=ActionAtomistic::getPosition( getAtomIndex(current,i) ); // This does strands cutoff Vector distance=pbcDistance( pos[align_atom_1],pos[align_atom_2] ); if( s_cutoff>0 ){ if( distance.modulo()>s_cutoff ){ - setElementValue(1,0.0); + myvals.setValue( 0, 0.0 ); return; } } @@ -234,49 +234,40 @@ void SecondaryStructureRMSD::performTask(){ nr=references[i]->calculate( pos, pbc, false ); if( nr<r ){ closest=i; r=nr; } } - setElementValue(1,1.0); - setElementValue(0,r); - return; -} -void SecondaryStructureRMSD::mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ){ - plumed_dbg_assert( ider==0 ); - printf("MERGING \n"); - for(unsigned i=0;i<colvar_atoms[getCurrentTask()].size();++i){ - unsigned thisatom=getAtomIndex(i), thispos=3*thisatom; + // Transfer everything to the value + myvals.setValue( 0, 1.0 ); myvals.setValue( 1, r ); + for(unsigned i=0;i<colvar_atoms[current].size();++i){ + unsigned thisatom=3*getAtomIndex(current,i); Vector ader=references[closest]->getAtomDerivative(i); - buffer[start+stride*thispos] += df*ader[0]; thispos++; - buffer[start+stride*thispos] += df*ader[1]; thispos++; - buffer[start+stride*thispos] += df*ader[2]; + myvals.addDerivative( 1, thisatom, ader[0] ); thisatom++; + myvals.addDerivative( 1, thisatom, ader[1] ); thisatom++; + myvals.addDerivative( 1, thisatom, ader[2] ); } Tensor virial; - if( !references[closest]->getVirial( virial ) ){ + if( !references[closest]->getVirial( virial ) ){ virial.zero(); - for(unsigned i=0;i<colvar_atoms[getCurrentTask()].size();++i){ + for(unsigned i=0;i<colvar_atoms[current].size();++i){ virial+=(-1.0*Tensor( pos[i], references[closest]->getAtomDerivative(i) )); } - } - - // Easy to merge the virial + } unsigned outnat=3*getNumberOfAtoms(); - buffer[start+stride*outnat] += df*virial(0,0); outnat++; - buffer[start+stride*outnat] += df*virial(0,1); outnat++; - buffer[start+stride*outnat] += df*virial(0,2); outnat++; - buffer[start+stride*outnat] += df*virial(1,0); outnat++; - buffer[start+stride*outnat] += df*virial(1,1); outnat++; - buffer[start+stride*outnat] += df*virial(1,2); outnat++; - buffer[start+stride*outnat] += df*virial(2,0); outnat++; - buffer[start+stride*outnat] += df*virial(2,1); outnat++; - buffer[start+stride*outnat] += df*virial(2,2); + myvals.addDerivative( 1, outnat, virial(0,0) ); outnat++; + myvals.addDerivative( 1, outnat, virial(0,1) ); outnat++; + myvals.addDerivative( 1, outnat, virial(0,2) ); outnat++; + myvals.addDerivative( 1, outnat, virial(1,0) ); outnat++; + myvals.addDerivative( 1, outnat, virial(1,1) ); outnat++; + myvals.addDerivative( 1, outnat, virial(1,2) ); outnat++; + myvals.addDerivative( 1, outnat, virial(2,0) ); outnat++; + myvals.addDerivative( 1, outnat, virial(2,1) ); outnat++; + myvals.addDerivative( 1, outnat, virial(2,2) ); + + return; } void SecondaryStructureRMSD::apply(){ if( getForcesFromVessels( forcesToApply ) ) setForcesOnAtoms( forcesToApply ); } -void SecondaryStructureRMSD::clearDerivativesAfterTask( const unsigned& ival ){ - thisval_wasset[ival]=false; setElementValue( ival, 0.0 ); thisval_wasset[ival]=false; -} - } } diff --git a/src/secondarystructure/SecondaryStructureRMSD.h b/src/secondarystructure/SecondaryStructureRMSD.h index c953ba2b8da47d46ff0022e3fea389e23b9c14ae..141bedba76e5d309e966f272c2de08e4cb54019f 100644 --- a/src/secondarystructure/SecondaryStructureRMSD.h +++ b/src/secondarystructure/SecondaryStructureRMSD.h @@ -63,7 +63,7 @@ private: std::vector<Vector> pos; std::vector<double> forcesToApply; /// Get the index of an atom - unsigned getAtomIndex( const unsigned& iatom ); + unsigned getAtomIndex( const unsigned& current, const unsigned& iatom ); protected: /// Get the atoms in the backbone void readBackboneAtoms( const std::string& backnames, std::vector<unsigned>& chain_lengths ); @@ -83,10 +83,8 @@ public: void prepare(); void finishTaskListUpdate(); void calculate(); - void performTask(); - void clearDerivativesAfterTask( const unsigned& ); + void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ); void apply(); - void mergeDerivatives( const unsigned& , const double&, const unsigned, const unsigned, std::vector<double>& ); bool isPeriodic(){ return false; } }; @@ -101,8 +99,8 @@ unsigned SecondaryStructureRMSD::getNumberOfDerivatives(){ } inline -unsigned SecondaryStructureRMSD::getAtomIndex( const unsigned& iatom ){ - return all_atoms.linkIndex( colvar_atoms[getCurrentTask()][iatom] ); +unsigned SecondaryStructureRMSD::getAtomIndex( const unsigned& current, const unsigned& iatom ){ + return all_atoms.linkIndex( colvar_atoms[current][iatom] ); } } diff --git a/src/vesselbase/ActionWithVessel.cpp b/src/vesselbase/ActionWithVessel.cpp index 8e24d808eb6f26d134572da097c8116bbc96a6da..47529851960ac982eb8a39d9b39632ff2d9e6760 100644 --- a/src/vesselbase/ActionWithVessel.cpp +++ b/src/vesselbase/ActionWithVessel.cpp @@ -27,6 +27,7 @@ #include "VesselRegister.h" #include "BridgeVessel.h" #include "FunctionVessel.h" +#include "StoreDataVessel.h" using namespace std; namespace PLMD{ @@ -54,6 +55,7 @@ ActionWithVessel::ActionWithVessel(const ActionOptions&ao): serial(false), lowmem(false), noderiv(true), + actionIsBridged(false), contributorsAreUnlocked(false), weightHasDerivatives(false) { @@ -108,6 +110,7 @@ BridgeVessel* ActionWithVessel::addBridgingVessel( ActionWithVessel* tome ){ VesselOptions da("","",0,"",this); BridgeVessel* bv=new BridgeVessel(da); bv->setOutputAction( tome ); + tome->actionIsBridged=true; functions.push_back( dynamic_cast<Vessel*>(bv) ); resizeFunctions(); return bv; @@ -118,7 +121,16 @@ StoreDataVessel* ActionWithVessel::buildDataStashes( const bool& allow_wcutoff, StoreDataVessel* vsv=dynamic_cast<StoreDataVessel*>( functions[i] ); if( vsv ) return vsv; } - return NULL; + + VesselOptions da("","",0,"",this); + StoreDataVessel* mydata=new StoreDataVessel(da); + if( allow_wcutoff ) mydata->setHardCutoffOnWeight( wtol ); + addVessel(mydata); + + // Make sure resizing of vessels is done + resizeFunctions(); + + return mydata; } void ActionWithVessel::addTaskToList( const unsigned& taskCode ){ @@ -169,8 +181,6 @@ void ActionWithVessel::readVesselKeywords(){ void ActionWithVessel::resizeFunctions(){ for(unsigned i=0;i<functions.size();++i) functions[i]->resize(); - thisval.resize( getNumberOfQuantities() ); thisval_wasset.resize( getNumberOfQuantities(), false ); - derivatives.resize( getNumberOfQuantities()*getNumberOfDerivatives(), 0.0 ); } void ActionWithVessel::needsDerivatives(){ @@ -235,7 +245,7 @@ void ActionWithVessel::activateTheseTasks( std::vector<unsigned>& additionalTask contributorsAreUnlocked=false; } -void ActionWithVessel::deactivate_task(){ +void ActionWithVessel::deactivate_task( const unsigned & task_index ){ plumed_dbg_assert( contributorsAreUnlocked ); taskFlags[task_index]=1; } @@ -268,32 +278,34 @@ void ActionWithVessel::runAllTasks(){ // Get size for buffer unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); + // Build storage stuff for loop std::vector<double> buffer( bufsize, 0.0 ); + MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + myvals.clearAll(); bvals.clearAll(); + for(unsigned i=rank;i<nactive_tasks;i+=stride){ - // The index of the task in the full list - task_index=indexOfTaskInFullList[i]; - // Store the task we are currently working on - current=partialTaskList[i]; // Calculate the stuff in the loop for this action - performTask(); + performTask( indexOfTaskInFullList[i], partialTaskList[i], myvals ); // Weight should be between zero and one - plumed_dbg_assert( getValueForTolerance()>=0 && getValueForTolerance()<=1.0 ); + plumed_dbg_assert( myvals.get(0)>=0 && myvals.get(0)<=1.0 ); // Check for conditions that allow us to just to skip the calculation // the condition is that the weight of the contribution is low // N.B. Here weights are assumed to be between zero and one - if( getValueForTolerance()<tolerance ){ - // Clear the derivatives - clearAfterTask(); + if( myvals.get(0)<tolerance ){ // Deactivate task if it is less than the neighbor list tolerance - if( getValueForTolerance()<nl_tolerance && contributorsAreUnlocked ) deactivate_task(); + if( myvals.get(0)<nl_tolerance && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); + // Clear the derivatives + myvals.clearAll(); continue; } // Now calculate all the functions // If the contribution of this quantity is very small at neighbour list time ignore it // untill next neighbour list time - if( !calculateAllVessels( buffer ) && contributorsAreUnlocked ) deactivate_task(); + if( !calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer ) && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); + myvals.clearAll(); } // MPI Gather everything if( !serial && buffer.size()>0 ) comm.Sum( buffer ); @@ -304,35 +316,26 @@ void ActionWithVessel::runAllTasks(){ finishComputations( buffer ); } -void ActionWithVessel::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ - indices[jstore]=getNumberOfDerivatives(); - if( indices[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); - - unsigned kder = ntotal + jstore*getNumberOfDerivatives(); - for(unsigned jder=0;jder<getNumberOfDerivatives();++jder){ indices[ kder ] = jder; kder++; } -} - -void ActionWithVessel::clearAfterTask(){ - // Clear the derivatives from this step - for(unsigned k=0;k<thisval.size();++k) clearDerivativesAfterTask(k); +void ActionWithVessel::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ){ + plumed_error(); } -void ActionWithVessel::clearDerivativesAfterTask( const unsigned& ider ){ - thisval[ider]=0.0; thisval_wasset[ider]=false; - if( !noderiv ){ - unsigned kstart=ider*getNumberOfDerivatives(); - for(unsigned j=0;j<getNumberOfDerivatives();++j) derivatives[ kstart+j ]=0.0; - } -} +// void ActionWithVessel::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ +// indices[jstore]=getNumberOfDerivatives(); +// if( indices[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); +// +// unsigned kder = ntotal + jstore*getNumberOfDerivatives(); +// for(unsigned jder=0;jder<getNumberOfDerivatives();++jder){ indices[ kder ] = jder; kder++; } +// } -bool ActionWithVessel::calculateAllVessels( std::vector<double>& buffer ){ - bool keep=false; +bool ActionWithVessel::calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector<double>& buffer ){ + bool keep=false; for(unsigned j=0;j<functions.size();++j){ // Calculate returns a bool that tells us if this particular // quantity is contributing more than the tolerance - if( functions[j]->calculate( buffer ) ) keep=true; + if( functions[j]->calculate( taskCode, functions[j]->transformDerivatives(taskCode, myvals, bvals), buffer ) ) keep=true; + if( !actionIsBridged ) bvals.clearAll(); } - clearAfterTask(); return keep; } @@ -341,25 +344,6 @@ void ActionWithVessel::finishComputations( const std::vector<double>& buffer ){ for(unsigned j=0;j<functions.size();++j) functions[j]->finish( buffer ); } -void ActionWithVessel::chainRuleForElementDerivatives( const unsigned& ider, const unsigned& iout, const double& df, const unsigned& buffer_start, std::vector<double>& buffer ){ - if( noderiv ) return; - mergeDerivatives( ider, df, buffer_start + (getNumberOfDerivatives()+1)*iout + 1 , 1, buffer ); -} - -void ActionWithVessel::chainRuleForElementDerivatives( const unsigned& ider, const unsigned& iout, const unsigned& stride, - const unsigned& off, const double& df, const unsigned& bufstart, - std::vector<double>& buffer ){ - if( noderiv ) return; - plumed_dbg_assert( off<stride ); - unsigned buffer_start=bufstart + stride*(getNumberOfDerivatives()+1)*iout + stride + off; - mergeDerivatives( ider, df, buffer_start, stride, buffer ); -} - -void ActionWithVessel::mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ){ - unsigned nder=getNumberOfDerivatives(), vstart=nder*ider; - for(unsigned i=0;i<getNumberOfDerivatives();++i) buffer[start+stride*i] += df*derivatives[vstart+i]; -} - bool ActionWithVessel::getForcesFromVessels( std::vector<double>& forcesToApply ){ #ifndef DNDEBUG if( forcesToApply.size()>0 ) plumed_dbg_assert( forcesToApply.size()==getNumberOfDerivatives() ); diff --git a/src/vesselbase/ActionWithVessel.h b/src/vesselbase/ActionWithVessel.h index b5442c63b17310e458b175760281d9fe3e2c25c6..e57a93ce18aec3e4ac413c30e9cb412c5036292e 100644 --- a/src/vesselbase/ActionWithVessel.h +++ b/src/vesselbase/ActionWithVessel.h @@ -26,6 +26,7 @@ #include "core/ActionAtomistic.h" #include "tools/Exception.h" #include "tools/DynamicList.h" +#include "MultiValue.h" #include <vector> namespace PLMD{ @@ -57,16 +58,14 @@ private: bool lowmem; /// Are we skipping the calculation of the derivatives bool noderiv; +/// This tells plumed that this is used in a bridge + bool actionIsBridged; /// The maximum number of derivatives we can use before we need to invoke lowmem unsigned maxderivatives; /// The tolerance on the accumulators double tolerance; /// Tolerance for quantities being put in neighbor lists double nl_tolerance; -/// The value of the current element in the sum - std::vector<double> thisval; -/// Vector of derivatives for the object - std::vector<double> derivatives; /// Pointers to the functions we are using on each value std::vector<Vessel*> functions; /// Tempory storage for forces @@ -74,7 +73,7 @@ private: /// Ths full list of tasks we have to perform std::vector<unsigned> fullTaskList; /// The current number of active tasks - unsigned nactive_tasks, task_index, current; + unsigned nactive_tasks; /// The indices of the tasks in the full list of tasks std::vector<unsigned> indexOfTaskInFullList; /// The list of currently active tasks @@ -82,16 +81,12 @@ private: /// This list is used to update the neighbor list std::vector<unsigned> taskFlags; protected: -/// A boolean that makes sure we don't accumulate very wrong derivatives - std::vector<bool> thisval_wasset; /// The terms in the series are locked bool contributorsAreUnlocked; /// Does the weight have derivatives bool weightHasDerivatives; /// This is used for numerical derivatives of bridge variables unsigned bridgeVariable; -/// Set the maximum number of derivatives - void setMaximumNumberOfDerivatives( const unsigned& ); /// Add a vessel to the list of vessels void addVessel( const std::string& name, const std::string& input, const int numlab=0 ); void addVessel( Vessel* vv ); @@ -115,11 +110,9 @@ protected: void resizeFunctions(); /// This loops over all the vessels calculating them and also /// sets all the element derivatives equal to zero - bool calculateAllVessels( std::vector<double>& buffer ); + bool calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector<double>& buffer ); /// Retrieve the forces from all the vessels (used in apply) bool getForcesFromVessels( std::vector<double>& forcesToApply ); -/// Clear tempory data that is calculated for each task - void clearAfterTask(); /// Is the calculation being done in serial bool serialCalculation() const; /// Are we using low memory @@ -130,12 +123,6 @@ protected: unsigned getCurrentNumberOfActiveTasks() const ; /// Get the ith of the currently active tasks unsigned getActiveTask( const unsigned& ii ) const ; -/// Get the position of the ith active task in the full list - unsigned getPositionInFullTaskList( const unsigned& ii ) const ; -/// Get the current task's position in the task list - unsigned getCurrentPositionInTaskList() const ; -/// Return the number that provides instructions for the current task - unsigned getCurrentTask() const ; /// Deactivate all the tasks in the task list void deactivateAllTasks(); /// Deactivate all tasks with i in lower \f$\le\f$ i < upper @@ -153,12 +140,7 @@ public: virtual void finishTaskListUpdate(){}; /// Activate the jth colvar /// Deactivate the current task in future loops - virtual void deactivate_task(); -/// Merge the derivatives - void chainRuleForElementDerivatives( const unsigned&, const unsigned&, const double& , const unsigned& , std::vector<double>& ); - void chainRuleForElementDerivatives( const unsigned&, const unsigned& , const unsigned& , const unsigned& , const double& , const unsigned& , std::vector<double>& ); - virtual void mergeDerivatives( const unsigned& ider, const double& df, const unsigned start, const unsigned stride, std::vector<double>& buffer ); - virtual void clearDerivativesAfterTask( const unsigned& ); + virtual void deactivate_task( const unsigned & task_index ); /// Are derivatives required for this quantity bool derivativesAreRequired() const ; /// Finish running all the calculations @@ -172,43 +154,31 @@ public: /// Get the number of quantities that are calculated during each task virtual unsigned getNumberOfQuantities(); /// Get the list of indices that have derivatives - virtual void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ); -/// This returns the value on which we apply the tolerance - by default this is element 1 - the weight - virtual double getValueForTolerance(); -/// Get the index of the element in which we are storing the weight - virtual unsigned getIndexOfWeight(); +// virtual void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ); /// Switch on additional tasks void activateTheseTasks( std::vector<unsigned>& addtionalTasks ); /// Do any jobs that are required before the task list is undertaken virtual void doJobsRequiredBeforeTaskList(); /// Get the full size of the taskList dynamic list unsigned getFullNumberOfTasks() const ; +/// Get the position of the ith active task in the full list + unsigned getPositionInFullTaskList( const unsigned& ii ) const ; /// Get the code for the ii th task in the list unsigned getTaskCode( const unsigned& ii ) const ; -/// Set the indices for computing a task - void setTaskIndexToCompute( const unsigned& itask ); /// Calculate one of the functions in the distribution - virtual void performTask()=0; -/// Set the derivative of the jth element wrt to a numbered element - void setElementDerivative( const unsigned&, const double& ); -/// Add some derivative of the quantity in the sum wrt to a numbered element - void addElementDerivative( const unsigned&, const double& ); -/// Set the value of the element - void setElementValue( const unsigned& , const double& ); -/// Add to an element value - void addElementValue( const unsigned&, const double& ); -/// Get the value of this element - double getElementValue( const unsigned& ival ) const ; -/// Retrieve the derivative of the quantity in the sum wrt to a numbered element - double getElementDerivative( const unsigned& ) const ; + virtual void performTask( const unsigned& , const unsigned& , MultiValue& )=0; +/// Do the task if we have a bridge + virtual void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ); /// Ensure that data required in other vessels is stored - virtual StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol ); + StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol ); /// Apply forces from bridge vessel - this is rarely used - currently only in ActionVolume virtual void applyBridgeForces( const std::vector<double>& bb ){ plumed_error(); } /// These are overwritten in MultiColvarFunction virtual void activateIndexes( const unsigned&, const unsigned&, const std::vector<unsigned>& ){} /// Return a particular named vessel Vessel* getVesselWithName( const std::string& mynam ); +/// Does the weight have derivatives + bool weightWithDerivatives() const ; }; inline @@ -237,48 +207,6 @@ Vessel* ActionWithVessel::getPntrToVessel( const unsigned& i ){ return functions[i]; } -inline -double ActionWithVessel::getElementValue(const unsigned& ival) const { - return thisval[ival]; -} - -inline -void ActionWithVessel::setElementValue( const unsigned& ival, const double& val ){ - // Element 0 is reserved for the value we are accumulating - // Element 1 is reserved for the normalization constant for calculating AVERAGES, normalized HISTOGRAMS - // plumed_dbg_massert( !thisval_wasset[ival], "In action named " + getName() + " with label " + getLabel() ); - thisval[ival]=val; - thisval_wasset[ival]=true; -} - -inline -void ActionWithVessel::addElementValue( const unsigned& ival, const double& val ){ - thisval[ival]+=val; - thisval_wasset[ival]=true; -} - -inline -double ActionWithVessel::getElementDerivative( const unsigned& ider ) const { - plumed_dbg_assert( ider<derivatives.size() ); - return derivatives[ider]; -} - -inline -void ActionWithVessel::addElementDerivative( const unsigned& ider, const double& der ){ -#ifndef NDEBUG - unsigned ndertmp=getNumberOfDerivatives(); - if( ider>=ndertmp && ider<2*ndertmp ) plumed_dbg_massert( weightHasDerivatives, "In " + getLabel() ); -#endif - plumed_dbg_assert( ider<derivatives.size() ); - derivatives[ider] += der; -} - -inline -void ActionWithVessel::setElementDerivative( const unsigned& ider, const double& der ){ - plumed_dbg_assert( ider<derivatives.size() ); - derivatives[ider] = der; -} - inline unsigned ActionWithVessel::getFullNumberOfTasks() const { return fullTaskList.size(); @@ -322,34 +250,14 @@ void ActionWithVessel::setLowMemOption(const bool& l){ lowmem=l; } -inline -unsigned ActionWithVessel::getCurrentTask() const { - return current; -} - -inline -unsigned ActionWithVessel::getCurrentPositionInTaskList() const { - return task_index; -} - inline bool ActionWithVessel::derivativesAreRequired() const { return !noderiv; } inline -double ActionWithVessel::getValueForTolerance(){ - return thisval[1]; -} - -inline -unsigned ActionWithVessel::getIndexOfWeight(){ - return 1; -} - -inline -void ActionWithVessel::setTaskIndexToCompute( const unsigned& itask ){ - current=fullTaskList[itask]; task_index=itask; +bool ActionWithVessel::weightWithDerivatives() const { + return weightHasDerivatives; } } diff --git a/src/vesselbase/Between.cpp b/src/vesselbase/Between.cpp index d167f6ae2f35bd7a210e13511f5d73a68a98b862..2a3dabea53d84ca2f8aed576de6b59c915c36045 100644 --- a/src/vesselbase/Between.cpp +++ b/src/vesselbase/Between.cpp @@ -67,10 +67,8 @@ std::string Between::function_description(){ return "the number of values " + hist.description(); } -bool Between::calculate( std::vector<double>& buffer ){ - double val=getAction()->getElementValue(0); - double dval, f = hist.calculate(val, dval); - return addToBuffers( f, dval, buffer ); +double Between::calcTransform( const double& val, double& dv ){ + double f = hist.calculate(val, dv); return f; } double Between::getCutoff(){ diff --git a/src/vesselbase/Between.h b/src/vesselbase/Between.h index 2d8aa9488455a86850bc708bbeca3a010a414669..593f1993d17378f5331fde6bc429b0f15eb32560 100644 --- a/src/vesselbase/Between.h +++ b/src/vesselbase/Between.h @@ -36,7 +36,7 @@ public: static void reserveKeyword( Keywords& keys ); Between( const VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); double getCutoff(); }; diff --git a/src/vesselbase/BridgeVessel.cpp b/src/vesselbase/BridgeVessel.cpp index 572d2d786680ee4f809ce7246017f53dd4b5b901..dceec770437191c5a221de5ccb4349c59eaf7fcb 100644 --- a/src/vesselbase/BridgeVessel.cpp +++ b/src/vesselbase/BridgeVessel.cpp @@ -62,16 +62,21 @@ void BridgeVessel::setBufferStart( unsigned& start ){ unsigned tmp=myOutputAction->getSizeOfBuffer( start ); } -bool BridgeVessel::calculate( std::vector<double>& buffer ){ +MultiValue& BridgeVessel::transformDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ){ + if( outvals.getNumberOfValues()!=myOutputAction->getNumberOfQuantities() || + outvals.getNumberOfDerivatives()!=myOutputAction->getNumberOfDerivatives() ){ + outvals.resize( myOutputAction->getNumberOfQuantities(), myOutputAction->getNumberOfDerivatives() ); + } + myOutputAction->transformBridgedDerivatives( current, invals, outvals ); + return outvals; +} + +bool BridgeVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer ){ in_normal_calculate=true; - myOutputAction->task_index = getAction()->task_index; - myOutputAction->current = getAction()->current; - myOutputAction->performTask(); - if( myOutputAction->getValueForTolerance()<myOutputAction->getTolerance() ){ - myOutputAction->clearAfterTask(); - return ( !myOutputAction->contributorsAreUnlocked || myOutputAction->getValueForTolerance()>=myOutputAction->getNLTolerance() ); + if( myvals.get(0)<myOutputAction->getTolerance() ){ + return ( !myOutputAction->contributorsAreUnlocked || myvals.get(0)>=myOutputAction->getNLTolerance() ); } - bool keep=myOutputAction->calculateAllVessels( buffer ); + bool keep=myOutputAction->calculateAllVessels( current, myvals, myvals, buffer ); in_normal_calculate=false; return ( !myOutputAction->contributorsAreUnlocked || keep ); } diff --git a/src/vesselbase/BridgeVessel.h b/src/vesselbase/BridgeVessel.h index 71216676689af6112d23db0504bb79ea0428dbc3..fc6c914bd3dc06a01a70b4029c504552c393d768 100644 --- a/src/vesselbase/BridgeVessel.h +++ b/src/vesselbase/BridgeVessel.h @@ -60,8 +60,10 @@ public: void prepare(); /// Set the start of the buffer void setBufferStart( unsigned& start ); +/// This transforms the derivatives using the output value + MultiValue& transformDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ); /// Actually do the calculation - bool calculate( std::vector<double>& buffer ); + bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer ); /// Finish the calculation void finish( const std::vector<double>& buffer ); /// Calculate numerical derivatives diff --git a/src/vesselbase/FunctionVessel.cpp b/src/vesselbase/FunctionVessel.cpp index a195da74e28f4a4cc3c5221f57c93ed011f1afe5..5aad279d770862235bd21d97e04e6c03faac9acf 100644 --- a/src/vesselbase/FunctionVessel.cpp +++ b/src/vesselbase/FunctionVessel.cpp @@ -48,7 +48,6 @@ usetol(false) } final_value=a->copyOutput( a->getNumberOfComponents()-1 ); diffweight=getAction()->weightHasDerivatives; - wnum=getAction()->getIndexOfWeight(); } std::string FunctionVessel::description(){ @@ -61,9 +60,11 @@ void FunctionVessel::resize(){ nderivatives=getAction()->getNumberOfDerivatives(); resizeBuffer( (1+nderivatives)*2 ); final_value->resizeDerivatives( nderivatives ); + diffweight=getAction()->weightHasDerivatives; } else { nderivatives=0; resizeBuffer(2); + diffweight=false; // Don't need to worry about differentiable weights if no derivatives } } @@ -72,26 +73,33 @@ void FunctionVessel::setNumberOfDerivatives( const unsigned& nder ){ final_value->resizeDerivatives( nder ); } -bool FunctionVessel::addToBuffers( const double& f, const double& dval, std::vector<double>& buffer ){ - double weight=getAction()->getElementValue(wnum); +bool FunctionVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer ){ + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); + // This deals with the value + double dval, f=calcTransform( myvals.get(1), dval ); + if( norm ){ if( usetol && weight<getTolerance() ) return false; buffer[bufstart+1+nderivatives] += weight; - if( diffweight ) getAction()->chainRuleForElementDerivatives( wnum, 1, 1.0, bufstart, buffer ); + if( diffweight ) myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); } double contr=weight*f; if( usetol && contr<getTolerance() ) return false; buffer[bufstart] += contr; - if( diffweight ) getAction()->chainRuleForElementDerivatives( wnum, 0, f, bufstart, buffer ); - if(fabs(dval)>0.0) getAction()->chainRuleForElementDerivatives( 0, 0, weight*dval, bufstart, buffer ); + if( diffweight ) myvals.chainRule( 0, 0, 1, 0, f, bufstart, buffer ); + if( getAction()->derivativesAreRequired() && fabs(dval)>0.0 ) myvals.chainRule( 1, 0, 1, 0, weight*dval, bufstart, buffer ); return true; } +double FunctionVessel::calcTransform( const double& , double& ){ + plumed_error(); return 1.0; +} + void FunctionVessel::finish( const std::vector<double>& buffer ){ if( norm && diffweight ){ double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; diff --git a/src/vesselbase/FunctionVessel.h b/src/vesselbase/FunctionVessel.h index 064dfedaf8784d71661ec1bebe926f06d11c3842..08157928f0ac309db713e91edeb979bad261d34a 100644 --- a/src/vesselbase/FunctionVessel.h +++ b/src/vesselbase/FunctionVessel.h @@ -42,8 +42,6 @@ class FunctionVessel : public Vessel { private: /// The number of derivatives unsigned nderivatives; -/// The index of the weight - unsigned wnum; /// This is the pointer to the value we are creating Value* final_value; protected: @@ -61,8 +59,6 @@ protected: void setNumberOfDerivatives( const unsigned& nder ); /// Return a pointer to the final value void addDerivativeToFinalValue( const unsigned& j, const double& der ); -/// Add some value to the buffers - bool addToBuffers( const double& f, const double& dval, std::vector<double>& buffer ); public: static void registerKeywords( Keywords& keys ); FunctionVessel( const VesselOptions& ); @@ -74,6 +70,10 @@ public: std::string description(); /// The rest of the description of what we are calculating virtual std::string function_description()=0; +/// Do the calcualtion + virtual bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer ); +/// Do any transformations of the value that are required + virtual double calcTransform( const double& val, double& df ); /// Finish the calculation of the quantity virtual void finish( const std::vector<double>& buffer ); /// Finish with any transforms required diff --git a/src/vesselbase/LessThan.cpp b/src/vesselbase/LessThan.cpp index 2b30c7c0cc204a4ce2a6983c221cd535a7b5037f..479f3afac78e3c101afd4942af97c5f67b09e2ff 100644 --- a/src/vesselbase/LessThan.cpp +++ b/src/vesselbase/LessThan.cpp @@ -54,10 +54,8 @@ std::string LessThan::function_description(){ return "the number of values less than " + sf.description(); } -bool LessThan::calculate( std::vector<double>& buffer ){ - double val=getAction()->getElementValue(0); - double dval, f = sf.calculate(val, dval); dval*=val; - return addToBuffers( f, dval, buffer ); +double LessThan::calcTransform( const double& val, double& dv ){ + double f = sf.calculate(val, dv); dv*=val; return f; } double LessThan::getCutoff(){ diff --git a/src/vesselbase/LessThan.h b/src/vesselbase/LessThan.h index a7f6616f1677bd19103587f1ce8a304b1d2ad359..24bf15148f2c37e5da16ecb28025f2a318467428 100644 --- a/src/vesselbase/LessThan.h +++ b/src/vesselbase/LessThan.h @@ -37,7 +37,7 @@ public: static void reserveKeyword( Keywords& keys ); LessThan( const VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); double getCutoff(); }; diff --git a/src/vesselbase/Max.cpp b/src/vesselbase/Max.cpp index d81cb1a306ce5ac63a97f0606decd44973ce1549..13b5a995ce6770dffcadaad33e84569f225a283c 100644 --- a/src/vesselbase/Max.cpp +++ b/src/vesselbase/Max.cpp @@ -34,7 +34,7 @@ public: static void reserveKeyword( Keywords& keys ); Max( const VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); double finalTransform( const double& val, double& dv ); }; @@ -69,10 +69,8 @@ std::string Max::function_description(){ return "the maximum value. Beta is equal to " + str_beta; } -bool Max::calculate( std::vector<double>& buffer ){ - double val=getAction()->getElementValue(0); - double dval, f = exp(val/beta); dval=f/beta; - return addToBuffers( f, dval, buffer ); +double Max::calcTransform( const double& val, double& dv ){ + double f = exp(val/beta); dv=f/beta; return f; } double Max::finalTransform( const double& val, double& dv ){ diff --git a/src/vesselbase/Mean.cpp b/src/vesselbase/Mean.cpp index ebc79b8c69e42c19b9e904e72cc9c3544f951a65..529788360d4ecf1a270300ed77e00cd42d6a48de 100644 --- a/src/vesselbase/Mean.cpp +++ b/src/vesselbase/Mean.cpp @@ -32,7 +32,7 @@ public: static void reserveKeyword( Keywords& keys ); Mean( const vesselbase::VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); }; PLUMED_REGISTER_VESSEL(Mean,"MEAN") @@ -58,9 +58,8 @@ std::string Mean::function_description(){ return "the mean value"; } -bool Mean::calculate( std::vector<double>& buffer ){ - double colvar=getAction()->getElementValue(0); - return addToBuffers( colvar, 1.0, buffer ); +double Mean::calcTransform( const double& val, double& dv ){ + dv=1.0; return val; } } diff --git a/src/vesselbase/Min.cpp b/src/vesselbase/Min.cpp index f91372bff9b16d99b9e9eb6b14111e5208c6c784..a14c1f6bb8fc51c021100a3be15ed926105bcac7 100644 --- a/src/vesselbase/Min.cpp +++ b/src/vesselbase/Min.cpp @@ -34,7 +34,7 @@ public: static void reserveKeyword( Keywords& keys ); Min( const VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); double finalTransform( const double& val, double& dv ); }; @@ -68,10 +68,9 @@ std::string Min::function_description(){ return "the minimum value. Beta is equal to " + str_beta; } -bool Min::calculate( std::vector<double>& buffer ){ - double val=getAction()->getElementValue(0); - double dval, f = exp(beta/val); dval=f/(val*val); - return addToBuffers( f, dval, buffer ); +double Min::calcTransform( const double& val, double& dv ){ + double f = exp(beta/val); dv=f/(val*val); + return f; } double Min::finalTransform( const double& val, double& dv ){ diff --git a/src/vesselbase/Moments.cpp b/src/vesselbase/Moments.cpp index 83b23db2cd59997f5bbdcc8ee6a9978b129633ee..89264c0bcb631efdbceb8ad0a16cd634c1d319e4 100644 --- a/src/vesselbase/Moments.cpp +++ b/src/vesselbase/Moments.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see <http://www.gnu.org/licenses/>. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "VesselRegister.h" -#include "StoreValueVessel.h" +#include "StoreDataVessel.h" #include "ActionWithVessel.h" namespace PLMD { @@ -30,7 +30,7 @@ namespace vesselbase{ // The calculation of all the colvars is parallelized // but the loops for calculating moments are not // Feel free to reimplement this if you know how -class Moments : public StoreValueVessel { +class Moments : public StoreDataVessel { private: std::vector<unsigned> powers; std::vector<Value*> value_out; @@ -47,7 +47,7 @@ public: PLUMED_REGISTER_VESSEL(Moments,"MOMENTS") void Moments::registerKeywords( Keywords& keys ){ - StoreValueVessel::registerKeywords( keys ); + StoreDataVessel::registerKeywords( keys ); } void Moments::reserveKeyword( Keywords& keys ){ @@ -61,7 +61,7 @@ void Moments::reserveKeyword( Keywords& keys ){ } Moments::Moments( const vesselbase::VesselOptions& da) : -StoreValueVessel(da) +StoreDataVessel(da) { ActionWithValue* a=dynamic_cast<ActionWithValue*>( getAction() ); plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); @@ -80,9 +80,6 @@ StoreValueVessel(da) void Moments::resize(){ StoreDataVessel::resize(); - if( value_out[0]->getNumberOfDerivatives()>0 ){ - unsigned nder=getAction()->getNumberOfDerivatives(); - } } std::string Moments::description(){ @@ -108,33 +105,34 @@ void Moments::finish( const std::vector<double>& buffer ){ double pfactor, min, max; Tools::convert(str_min,min); Tools::convert(str_max,max); pfactor = 2*pi / ( max-min ); myvalue.setDomain( str_min, str_max ); double sinsum=0, cossum=0, val; - for(unsigned i=0;i<nvals;++i){ val=pfactor*( getValue(i) - min ); sinsum+=sin(val); cossum+=cos(val); } + for(unsigned i=0;i<nvals;++i){ val=pfactor*( buffer[i*nspace*vecsize+nspace] - min ); sinsum+=sin(val); cossum+=cos(val); } mean = 0.5 + atan2( sinsum / static_cast<double>( nvals ) , cossum / static_cast<double>( nvals ) ) / (2*pi); mean = min + (max-min)*mean; } else { - for(unsigned i=0;i<nvals;++i) mean+=getValue(i); + for(unsigned i=0;i<nvals;++i) mean+=buffer[i*nspace*vecsize+nspace]; mean/=static_cast<double>( nvals ); myvalue.setNotPeriodic(); } for(unsigned npow=0;npow<powers.size();++npow){ double dev1=0; if( value_out[0]->getNumberOfDerivatives()>0 ){ - for(unsigned i=0;i<nvals;++i) dev1+=pow( myvalue.difference( mean, getValue(i) ), powers[npow] - 1 ); + for(unsigned i=0;i<nvals;++i) dev1+=pow( myvalue.difference( mean, buffer[i*nspace*vecsize+nspace] ), powers[npow] - 1 ); dev1/=static_cast<double>( nvals ); } - std::vector<double> pref(1); double tmp, moment=0; + double moment=0; + MultiValue myvals( getNumberOfComponents(), getAction()->getNumberOfDerivatives() ); myvals.clearAll(); for(unsigned i=0;i<nvals;++i){ - tmp=myvalue.difference( mean, getValue(i) ); + double tmp=myvalue.difference( mean, buffer[i*nspace*vecsize+nspace] ); moment+=pow( tmp, powers[npow] ); if( value_out[npow]->getNumberOfDerivatives() ){ - pref[0]=pow( tmp, powers[npow] - 1 ) - dev1; - if( usingLowMem() ){ - recompute( i, 0 ); // Not very efficient - chainRule( 0, pref, value_out[npow] ); - } else { - chainRule( i, pref, value_out[npow] ); - } + double pref=pow( tmp, powers[npow] - 1 ) - dev1; + retrieveDerivatives( i, false, myvals ); + for(unsigned j=0;j<myvals.getNumberActive();++j){ + unsigned jatom=myvals.getActiveIndex(j); + value_out[npow]->addDerivative(jatom, pref*myvals.getDerivative( 1, jatom ) ); + } + myvals.clearAll(); } } if( value_out[npow]->getNumberOfDerivatives()>0 ) value_out[npow]->chainRule( powers[npow] / static_cast<double>( nvals ) ); diff --git a/src/vesselbase/MoreThan.cpp b/src/vesselbase/MoreThan.cpp index d1abe6fa30c810537233f09a7925c18d7100d5eb..8012481550d10fc9bfd80a11f75385ceeb151c37 100644 --- a/src/vesselbase/MoreThan.cpp +++ b/src/vesselbase/MoreThan.cpp @@ -36,7 +36,7 @@ public: static void reserveKeyword( Keywords& keys ); MoreThan( const VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); }; PLUMED_REGISTER_VESSEL(MoreThan,"MORE_THAN") @@ -68,10 +68,8 @@ std::string MoreThan::function_description(){ return "the number of values more than " + sf.description(); } -bool MoreThan::calculate( std::vector<double>& buffer ){ - double val=getAction()->getElementValue(0); - double dval, f = 1.0 - sf.calculate(val, dval); dval*=-val; - return addToBuffers( f, dval, buffer ); +double MoreThan::calcTransform( const double& val, double& dv ){ + double f = 1.0 - sf.calculate(val, dv); dv*=-val; return f; } } diff --git a/src/vesselbase/MultiValue.cpp b/src/vesselbase/MultiValue.cpp index 2d117db28f0ef494ab028c513f2b8ae7293b6ef9..3a7823e3fbf1f1a2e7bbbd859e5f292ec86be746 100644 --- a/src/vesselbase/MultiValue.cpp +++ b/src/vesselbase/MultiValue.cpp @@ -33,6 +33,13 @@ derivatives(nvals,nder) hasDerivatives.deactivateAll(); } +void MultiValue::resize( const unsigned& nvals, const unsigned& nder ){ + values.resize(nvals); derivatives.resize( nvals, nder ); + hasDerivatives.clear(); + for(unsigned i=0;i<nder;++i) hasDerivatives.addIndexToList( i ); + hasDerivatives.deactivateAll(); +} + void MultiValue::clearAll(){ if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); for(unsigned i=0;i<values.size();++i) clear(i); @@ -58,5 +65,37 @@ void MultiValue::chainRule( const unsigned& ival, const unsigned& iout, const un } } +void MultiValue::copyValues( MultiValue& outvals ) const { + plumed_dbg_assert( values.size()<=outvals.getNumberOfValues() ); + for(unsigned i=0;i<values.size();++i) outvals.setValue( i, values[i] ); + +} + +void MultiValue::copyDerivatives( MultiValue& outvals ){ + plumed_dbg_assert( values.size()<=outvals.getNumberOfValues() && derivatives.ncols()<=outvals.getNumberOfDerivatives() ); + + if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); + + for(unsigned i=0;i<values.size();++i){ + for(unsigned j=0;j<hasDerivatives.getNumberActive();++j){ + unsigned jder=hasDerivatives[j]; + outvals.addDerivative( i, jder, derivatives(i,jder) ); + } + } +} + +void MultiValue::quotientRule( const unsigned& nder, const unsigned& dder, const unsigned& oder ){ + plumed_dbg_assert( nder<values.size() && dder<values.size() && oder<values.size() ); + + if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); + + double weight = values[dder], pref = values[nder] / (weight*weight); + for(unsigned j=0;j<hasDerivatives.getNumberActive();++j){ + unsigned jder=hasDerivatives[j]; + derivatives(oder,jder) = derivatives(nder,jder) / weight - pref*derivatives(dder,jder); + } + values[oder] = values[nder] / values[dder]; +} + } } diff --git a/src/vesselbase/MultiValue.h b/src/vesselbase/MultiValue.h index 051abbb063a38b9716afa24f3062a975ca004dbf..57203c3231e61cf1987ac0e1c0d3ab99c91f6fab 100644 --- a/src/vesselbase/MultiValue.h +++ b/src/vesselbase/MultiValue.h @@ -40,20 +40,57 @@ private: Matrix<double> derivatives; public: MultiValue( const unsigned& , const unsigned& ); + void resize( const unsigned& , const unsigned& ); +/// Get the number of values in the stash + unsigned getNumberOfValues() const ; +/// Get the number of derivatives in the stash + unsigned getNumberOfDerivatives() const ; /// Set value numbered void setValue( const unsigned&, const double& ); +/// Add value numbered + void addValue( const unsigned&, const double& ); /// Add derivative void addDerivative( const unsigned& , const unsigned& , const double& ); +/// Set the value of the derivative + void setDerivative( const unsigned& ival, const unsigned& jder, const double& der); /// Return the ith value double get( const unsigned& ) const ; +/// Return a derivative value + double getDerivative( const unsigned&, const unsigned& ) const ; /// Clear all values void clearAll(); /// Clear a value void clear( const unsigned& ); +/// Functions for accessing active list + bool updateComplete(); + void emptyActiveMembers(); + void updateIndex( const unsigned & ); + void sortActiveList(); + void updateDynamicList(); +/// + unsigned getNumberActive(); +/// + unsigned getActiveIndex( const unsigned& ) const ; /// Transfer derivatives to buffer void chainRule( const unsigned& , const unsigned& , const unsigned&, const unsigned& , const double& , const unsigned& , std::vector<double>& buffer ); +/// + void copyValues( MultiValue& ) const ; +/// + void copyDerivatives( MultiValue& ); +/// + void quotientRule( const unsigned& nder, const unsigned& dder, const unsigned& oder ); }; +inline +unsigned MultiValue::getNumberOfValues() const { + return values.size(); +} + +inline +unsigned MultiValue::getNumberOfDerivatives() const { + return derivatives.ncols(); +} + inline double MultiValue::get( const unsigned& ival ) const { plumed_dbg_assert( ival<=values.size() ); @@ -66,12 +103,67 @@ void MultiValue::setValue( const unsigned& ival, const double& val){ values[ival]=val; } +inline +void MultiValue::addValue( const unsigned& ival, const double& val){ + plumed_dbg_assert( ival<=values.size() ); + values[ival]+=val; +} + inline void MultiValue::addDerivative( const unsigned& ival, const unsigned& jder, const double& der){ plumed_dbg_assert( ival<=values.size() ); hasDerivatives.activate(jder); derivatives(ival,jder) += der; } +inline +void MultiValue::setDerivative( const unsigned& ival, const unsigned& jder, const double& der){ + plumed_dbg_assert( ival<=values.size() ); + hasDerivatives.activate(jder); derivatives(ival,jder)=der; +} + + +inline +double MultiValue::getDerivative( const unsigned& ival, const unsigned& jder ) const { + plumed_dbg_assert( jder<derivatives.ncols() && hasDerivatives.isActive(jder) ); + return derivatives(ival,jder); +} + +inline +bool MultiValue::updateComplete(){ + return hasDerivatives.updateComplete(); +} + +inline +void MultiValue::emptyActiveMembers(){ + hasDerivatives.emptyActiveMembers(); +} + +inline +void MultiValue::updateIndex( const unsigned& ind ){ + hasDerivatives.updateIndex( ind ); +} + +inline +void MultiValue::sortActiveList(){ + hasDerivatives.sortActiveList(); +} + +inline +unsigned MultiValue::getNumberActive(){ + return hasDerivatives.getNumberActive(); +} + +inline +unsigned MultiValue::getActiveIndex( const unsigned& ind ) const { + plumed_dbg_assert( ind<hasDerivatives.getNumberActive() ); + return hasDerivatives[ind]; +} + +inline +void MultiValue::updateDynamicList(){ + hasDerivatives.updateActiveMembers(); +} + } } #endif diff --git a/src/vesselbase/ShortcutVessel.h b/src/vesselbase/ShortcutVessel.h index 90b6a7d942b0dec132666de769db9a2edefec1fe..b1a2d88f2fd8d274a9aa8fb5157120d53f1775ce 100644 --- a/src/vesselbase/ShortcutVessel.h +++ b/src/vesselbase/ShortcutVessel.h @@ -39,7 +39,7 @@ public: ShortcutVessel( const VesselOptions& ); std::string description(){ return ""; } void resize(){ plumed_error(); } - bool calculate( std::vector<double>& buffer ){ plumed_error(); } + bool calculate( const unsigned& taskCode, MultiValue& myvals, std::vector<double>& buffer ){ plumed_error(); } void finish( const std::vector<double>& buffer ){ plumed_error(); } bool applyForce( std::vector<double>& forces ){ plumed_error(); } }; diff --git a/src/vesselbase/StoreDataVessel.cpp b/src/vesselbase/StoreDataVessel.cpp index baa132d40d2177e48e9e232f00f8f2e8fd8dd7f5..b1b35f484c82eccc8a58083873f9a84b035a7406 100644 --- a/src/vesselbase/StoreDataVessel.cpp +++ b/src/vesselbase/StoreDataVessel.cpp @@ -37,6 +37,8 @@ hard_cut(false) ActionWithValue* myval=dynamic_cast<ActionWithValue*>( getAction() ); if( !myval ) hasderiv=false; else hasderiv=!myval->doNotCalculateDerivatives(); + + vecsize=getAction()->getNumberOfQuantities(); } void StoreDataVessel::setHardCutoffOnWeight( const double& mytol ){ @@ -47,19 +49,19 @@ bool StoreDataVessel::weightCutoffIsOn() const { return hard_cut; } -void StoreDataVessel::completeSetup( const unsigned& dstart, const unsigned& nvec ){ - if( (dstart+nvec)>getAction()->getNumberOfQuantities() ) error("this vessel can not be used with this action"); - data_start=dstart; vecsize = nvec; fvec.resize( vecsize ); -} +// void StoreDataVessel::completeSetup( const unsigned& dstart, const unsigned& nvec ){ +// if( (dstart+nvec)>getAction()->getNumberOfQuantities() ) error("this vessel can not be used with this action"); +// data_start=dstart; vecsize = nvec; // fvec.resize( vecsize ); +// } void StoreDataVessel::resize(){ plumed_dbg_assert( vecsize>0 ); - if( getAction()->derivativesAreRequired() ) final_derivatives.resize( getAction()->getNumberOfDerivatives() ); +// if( getAction()->derivativesAreRequired() ) final_derivatives.resize( getAction()->getNumberOfDerivatives() ); if( getAction()->lowmem || !getAction()->derivativesAreRequired() ){ nspace = 1; active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); - local_derivatives.resize( max_lowmem_stash * vecsize * getAction()->getNumberOfDerivatives() ); +// local_derivatives.resize( max_lowmem_stash * vecsize * getAction()->getNumberOfDerivatives() ); } else { nspace = 1 + getAction()->maxderivatives; active_der.resize( getAction()->getFullNumberOfTasks() * ( 1 + getAction()->maxderivatives ) ); @@ -75,89 +77,173 @@ void StoreDataVessel::prepare(){ active_val.assign(active_val.size(),0); } -void StoreDataVessel::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ - getAction()->getIndexList( ntotal, jstore, maxder, indices ); -} - -void StoreDataVessel::setTaskToRecompute( const unsigned& ivec ){ - getAction()->current = getAction()->fullTaskList[ivec]; - getAction()->task_index = ivec; -} - -void StoreDataVessel::recompute( const unsigned& ivec, const unsigned& jstore ){ - plumed_dbg_assert( getAction()->derivativesAreRequired() && getAction()->lowmem && jstore<max_lowmem_stash ); - // Set the task we want to reperform - setTaskToRecompute( ivec ); - // Reperform the task - performTask( jstore ); - // Store the derivatives - storeDerivativesLowMem( jstore ); - - // Clear up afterwards - getAction()->clearAfterTask(); -} - -void StoreDataVessel::storeValues( const unsigned& myelem, std::vector<double>& buffer ){ - ActionWithVessel* act = getAction(); active_val[myelem]=1; // Keeps track of which values are stashed - unsigned ibuf = bufstart + myelem * vecsize * nspace; - for(unsigned icomp=data_start;icomp<data_start + vecsize;++icomp){ - buffer[ibuf] = act->getElementValue( icomp ); ibuf+=nspace; - //setBufferElement( ibuf, act->getElementValue( icomp ) ); ibuf+=nspace; +// void StoreDataVessel::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ +// // getAction()->getIndexList( ntotal, jstore, maxder, indices ); +// } +// +// void StoreDataVessel::setTaskToRecompute( const unsigned& ivec ){ +// // getAction()->current = getAction()->fullTaskList[ivec]; +// // getAction()->task_index = ivec; +// } +// +// void StoreDataVessel::recompute( const unsigned& ivec, const unsigned& jstore ){ +// plumed_dbg_assert( getAction()->derivativesAreRequired() && getAction()->lowmem && jstore<max_lowmem_stash ); +// // Set the task we want to reperform +// setTaskToRecompute( ivec ); +// // Reperform the task +// performTask( jstore ); +// // Store the derivatives +// storeDerivativesLowMem( jstore ); +// +// // Clear up afterwards +// // getAction()->clearAfterTask(); +// } + +void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer ){ + unsigned ibuf = bufstart + myelem * vecsize * nspace; active_val[myelem]=1; + for(unsigned icomp=0;icomp<vecsize;++icomp){ + buffer[ibuf] = myvals.get(icomp); ibuf+=nspace; } } -void StoreDataVessel::storeDerivativesHighMem( const unsigned& myelem, std::vector<double>& buffer ){ +void StoreDataVessel::storeDerivatives( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer ){ plumed_dbg_assert( getAction()->derivativesAreRequired() && myelem<getAction()->getFullNumberOfTasks() ); - ActionWithVessel* act=getAction(); - getIndexList( act->getFullNumberOfTasks(), myelem, nspace-1, active_der ); + active_der[myelem]=myvals.getNumberActive(); + // getIndexList( act->getFullNumberOfTasks(), myelem, nspace-1, active_der ); // Store the values of the components and the derivatives if - unsigned nder = act->getNumberOfDerivatives(); - for(unsigned icomp=data_start;icomp<data_start + vecsize;++icomp){ - unsigned ibuf = bufstart + myelem * ( vecsize*nspace ) + (icomp-data_start)*nspace + 1; - unsigned kder = act->getFullNumberOfTasks() + myelem * ( nspace - 1 ); - for(unsigned jder=0;jder<active_der[myelem];++jder){ - buffer[ibuf] += act->getElementDerivative(nder*icomp + active_der[ kder ]); + // unsigned nder =getAction()->getNumberOfDerivatives(); + for(unsigned icomp=0;icomp<vecsize;++icomp){ + unsigned ibuf = bufstart + myelem * ( vecsize*nspace ) + icomp*nspace + 1; + unsigned kder = getAction()->getFullNumberOfTasks() + myelem * ( nspace - 1 ); + for(unsigned j=0;j<myvals.getNumberActive();++j){ + unsigned jder=myvals.getActiveIndex(j); + buffer[ibuf] = myvals.getDerivative( icomp, jder ); + active_der[kder] = jder; + // act->getElementDerivative(nder*icomp + active_der[ kder ]); //addToBufferElement( ibuf, act->getElementDerivative(nder*icomp + active_der[ kder ]) ); - kder++; ibuf++; + ibuf++; kder++; } } } -void StoreDataVessel::storeDerivativesLowMem( const unsigned& jstore ){ - plumed_dbg_assert( getAction()->derivativesAreRequired() ); - // Store the indexes that have derivatives - ActionWithVessel* act=getAction(); - unsigned nder = act->getNumberOfDerivatives(); - getIndexList( max_lowmem_stash, jstore, nder, active_der ); - - // Stash the derivatives - for(unsigned icomp=data_start;icomp<data_start + vecsize;++icomp){ - unsigned ibuf = jstore * vecsize * nder + (icomp-data_start)*nder; - unsigned kder = max_lowmem_stash + jstore*nder; - for(unsigned jder=0;jder<active_der[jstore];++jder){ - local_derivatives[ibuf] = act->getElementDerivative( nder*icomp + active_der[ kder ] ); - ibuf++; kder++; - } +void StoreDataVessel::retrieveValue( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const { + plumed_dbg_assert( values.size()==vecsize ); + if( normed && values.size()>2 ){ + unsigned ibuf = myelem * vecsize * nspace; + values[0]=local_buffer[ibuf]; ibuf+=nspace; + values[1]=local_buffer[ibuf]; ibuf+=nspace; // Element 1 contains the norm of the vector + for(unsigned i=2;i<vecsize;++i){ values[i]=local_buffer[ibuf]/values[1]; ibuf+=nspace; } + } else { + unsigned ibuf = myelem * vecsize * nspace; + for(unsigned i=0;i<vecsize;++i){ values[i]=local_buffer[ibuf]; ibuf+=nspace; } } } -bool StoreDataVessel::calculate( std::vector<double>& buffer ){ - unsigned myelem = getAction()->getCurrentPositionInTaskList(); +void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ){ + plumed_dbg_assert( myvals.getNumberOfValues()==vecsize && myvals.getNumberOfDerivatives()==getAction()->getNumberOfDerivatives() ); + + myvals.clearAll(); + if( getAction()->lowmem ){ + getAction()->performTask( getAction()->getPositionInFullTaskList(myelem), getAction()->getTaskCode(myelem), myvals ); + if( normed ){ + plumed_dbg_assert( myvals.getNumberOfValues()>2 ); + double v = myvals.get(1), weight = 1.0 / v, wdf = 1.0 / ( v*v*v ); + for(unsigned j=0;j<myvals.getNumberActive();++j){ + double comp2=0.0; unsigned jder=myvals.getActiveIndex(j); + for(unsigned jcomp=2;jcomp<vecsize;++jcomp) comp2 += myvals.get(jcomp)*myvals.getDerivative( jcomp, jder ); + for(unsigned jcomp=2;jcomp<vecsize;++jcomp) myvals.setDerivative( jcomp, jder, weight*myvals.getDerivative( jcomp, jder ) - wdf*comp2*myvals.get(jcomp) ); + } + } + } else { + // Retrieve the derivatives for elements 0 and 1 - weight and norm + for(unsigned icomp=0;icomp<2;++icomp){ + unsigned ibuf = myelem * ( vecsize*nspace ) + icomp*nspace + 1; + unsigned kder = getAction()->getFullNumberOfTasks() + myelem * ( nspace - 1 ); + for(unsigned j=0;j<active_der[myelem];++j){ + myvals.addDerivative( icomp, active_der[kder], local_buffer[ibuf] ); + kder++; ibuf++; + } + } + + // Retrieve the derivatives for the vector + if( vecsize>2 && normed ){ + plumed_dbg_assert( myvals.getNumberOfValues()>2 ); + unsigned kder = getAction()->getFullNumberOfTasks() + myelem * ( nspace - 1 ); + double v = local_buffer[myelem*vecsize*nspace + nspace], weight = 1.0 / v, wdf = 1.0 / ( v*v*v ); + for(unsigned ider=0;ider<active_der[myelem];++ider){ + unsigned ibuf = myelem * vecsize * nspace + 2 * nspace + 1 + ider; double comp2=0.0; + for(unsigned jcomp=2;jcomp<vecsize;++jcomp){ comp2 += local_buffer[ibuf-ider-1]*local_buffer[ibuf]; ibuf+=nspace; } + ibuf = myelem * vecsize * nspace + 2 * nspace + 1 + ider; + for(unsigned jcomp=2;jcomp<vecsize;++jcomp){ + myvals.addDerivative( jcomp, active_der[kder], weight*local_buffer[ibuf] - wdf*comp2*local_buffer[ibuf-ider-1] ); + ibuf+=nspace; + } + kder++; + } + } else if( vecsize>2 ){ + for(unsigned icomp=2;icomp<vecsize;++icomp){ + unsigned ibuf = myelem * ( vecsize*nspace ) + icomp*nspace + 1; + unsigned kder = getAction()->getFullNumberOfTasks() + myelem * ( nspace - 1 ); + for(unsigned j=0;j<active_der[myelem];++j){ + myvals.addDerivative( icomp, active_der[kder], local_buffer[ibuf] ); + kder++; ibuf++; + } + } + } + // Now ensure appropriate parts of list are activated + myvals.emptyActiveMembers(); + unsigned kder = getAction()->getFullNumberOfTasks() + myelem * ( nspace - 1 ); + for(unsigned j=0;j<active_der[myelem];++j){ myvals.updateIndex( active_der[kder] ); kder++; } + myvals.sortActiveList(); + } +} + + +// +// void StoreDataVessel::storeDerivativesLowMem( const unsigned& jstore ){ +// plumed_dbg_assert( getAction()->derivativesAreRequired() ); +// // Store the indexes that have derivatives +// ActionWithVessel* act=getAction(); +// unsigned nder = act->getNumberOfDerivatives(); +// getIndexList( max_lowmem_stash, jstore, nder, active_der ); +// +// // Stash the derivatives +// for(unsigned icomp=data_start;icomp<data_start + vecsize;++icomp){ +// unsigned ibuf = jstore * vecsize * nder + (icomp-data_start)*nder; +// unsigned kder = max_lowmem_stash + jstore*nder; +// for(unsigned jder=0;jder<active_der[jstore];++jder){ +// // local_derivatives[ibuf] = act->getElementDerivative( nder*icomp + active_der[ kder ] ); +// ibuf++; kder++; +// } +// } +// } + +bool StoreDataVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer ){ + + if( !hard_cut ){ + storeValues( current, myvals, buffer ); + if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer ); + } else if( myvals.get(0)>wtol ){ + storeValues( current, myvals, buffer ); + if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer ); + } + +// unsigned myelem = getAction()->getCurrentPositionInTaskList(); // Normalize vector if it is required - finishTask( myelem ); +// unsigned myelem; finishTask( myelem ); // Store the values - if( !hard_cut ){ - storeValues( myelem, buffer ); - // Store the derivatives if we are not using low memory - if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivativesHighMem( myelem, buffer ); - } else if( getAction()->getElementValue(getAction()->getIndexOfWeight())>wtol ){ - storeValues( myelem, buffer ); - // Store the derivatives if we are not using low memory - if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivativesHighMem( myelem, buffer ); - } - +// if( !hard_cut ){ +// storeValues( myelem, buffer ); +// // Store the derivatives if we are not using low memory +// if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivativesHighMem( myelem, buffer ); +// } else if( getAction()->getElementValue(0)>wtol ){ +// storeValues( myelem, buffer ); +// // Store the derivatives if we are not using low memory +// if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivativesHighMem( myelem, buffer ); +// } +// return true; } @@ -172,71 +258,71 @@ void StoreDataVessel::finish( const std::vector<double>& buffer ){ if(!getAction()->lowmem && getAction()->derivativesAreRequired() ) comm.Sum( &active_der[0], active_der.size() ); } -double StoreDataVessel::chainRule( const unsigned& ival, const unsigned& ider, const std::vector<double>& df ){ - plumed_dbg_assert( getAction()->derivativesAreRequired() && df.size()==vecsize ); - // Clear final derivatives array - final_derivatives.assign( final_derivatives.size(), 0.0 ); - - double dfout = 0.0; - if(getAction()->lowmem){ - plumed_dbg_assert( ival<max_lowmem_stash ); - unsigned maxder = getAction()->getNumberOfDerivatives(); - unsigned ibuf=ival*(vecsize*maxder) + ider; - for(unsigned icomp=0;icomp<vecsize;++icomp){ - dfout+=df[icomp]*local_derivatives[ibuf]; - ibuf+=maxder; - } - } else { - plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() ); - unsigned ibuf=ival*(vecsize*nspace) + 1 + ider; - for(unsigned icomp=0;icomp<vecsize;++icomp){ - dfout+=df[icomp]*local_buffer[ibuf]; //getBufferElement(ibuf); - ibuf+=nspace; - } - } - return dfout; -} - -void StoreDataVessel::chainRule( const unsigned& ival, const std::vector<double>& df ){ - plumed_dbg_assert( getAction()->derivativesAreRequired() && df.size()==vecsize ); - // Clear final derivatives array - final_derivatives.assign( final_derivatives.size(), 0.0 ); - - if(getAction()->lowmem){ - plumed_dbg_assert( ival<max_lowmem_stash ); - unsigned maxder = getAction()->getNumberOfDerivatives(); - for(unsigned ider=0;ider<active_der[ival];++ider){ - final_derivatives[ider]=0.0; - unsigned ibuf=ival*(vecsize*maxder) + ider; - for(unsigned jcomp=0;jcomp<vecsize;++jcomp){ - final_derivatives[ider]+=df[jcomp]*local_derivatives[ibuf]; - ibuf+=maxder; - } - } - } else { - plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() ); - for(unsigned ider=0;ider<active_der[ival];++ider){ - final_derivatives[ider]=0.0; - unsigned ibuf=ival*(vecsize*nspace) + 1 + ider; - for(unsigned jcomp=0;jcomp<vecsize;++jcomp){ - final_derivatives[ider]+=df[jcomp]*local_buffer[ibuf]; - //final_derivatives[ider]+=df[jcomp]*getBufferElement(ibuf); - ibuf+=nspace; - } - } - } -} - -void StoreDataVessel::chainRule( const unsigned& ival, const std::vector<double>& df, Value* val ){ - plumed_dbg_assert( getAction()->derivativesAreRequired() && val->getNumberOfDerivatives()==final_derivatives.size() ); - chainRule( ival, df ); - - unsigned kder; - if( getAction()->lowmem ) kder = max_lowmem_stash + ival*getAction()->getNumberOfDerivatives(); - else kder = getAction()->getFullNumberOfTasks() + ival*(nspace-1); - - for(unsigned i=0;i<active_der[ival];++i) val->addDerivative( active_der[kder+i] , final_derivatives[i] ); -} +// double StoreDataVessel::chainRule( const unsigned& ival, const unsigned& ider, const std::vector<double>& df ){ +// plumed_dbg_assert( getAction()->derivativesAreRequired() && df.size()==vecsize ); +// // Clear final derivatives array +// final_derivatives.assign( final_derivatives.size(), 0.0 ); +// +// double dfout = 0.0; +// if(getAction()->lowmem){ +// plumed_dbg_assert( ival<max_lowmem_stash ); +// unsigned maxder = getAction()->getNumberOfDerivatives(); +// unsigned ibuf=ival*(vecsize*maxder) + ider; +// for(unsigned icomp=0;icomp<vecsize;++icomp){ +// dfout+=df[icomp]*local_derivatives[ibuf]; +// ibuf+=maxder; +// } +// } else { +// plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() ); +// unsigned ibuf=ival*(vecsize*nspace) + 1 + ider; +// for(unsigned icomp=0;icomp<vecsize;++icomp){ +// dfout+=df[icomp]*local_buffer[ibuf]; //getBufferElement(ibuf); +// ibuf+=nspace; +// } +// } +// return dfout; +// } + +// void StoreDataVessel::chainRule( const unsigned& ival, const std::vector<double>& df ){ +// plumed_dbg_assert( getAction()->derivativesAreRequired() && df.size()==vecsize ); +// // Clear final derivatives array +// final_derivatives.assign( final_derivatives.size(), 0.0 ); +// +// if(getAction()->lowmem){ +// plumed_dbg_assert( ival<max_lowmem_stash ); +// unsigned maxder = getAction()->getNumberOfDerivatives(); +// for(unsigned ider=0;ider<active_der[ival];++ider){ +// final_derivatives[ider]=0.0; +// unsigned ibuf=ival*(vecsize*maxder) + ider; +// for(unsigned jcomp=0;jcomp<vecsize;++jcomp){ +// final_derivatives[ider]+=df[jcomp]*local_derivatives[ibuf]; +// ibuf+=maxder; +// } +// } +// } else { +// plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() ); +// for(unsigned ider=0;ider<active_der[ival];++ider){ +// final_derivatives[ider]=0.0; +// unsigned ibuf=ival*(vecsize*nspace) + 1 + ider; +// for(unsigned jcomp=0;jcomp<vecsize;++jcomp){ +// final_derivatives[ider]+=df[jcomp]*local_buffer[ibuf]; +// //final_derivatives[ider]+=df[jcomp]*getBufferElement(ibuf); +// ibuf+=nspace; +// } +// } +// } +// } + +// void StoreDataVessel::chainRule( const unsigned& ival, const std::vector<double>& df, Value* val ){ +// plumed_dbg_assert( getAction()->derivativesAreRequired() && val->getNumberOfDerivatives()==final_derivatives.size() ); +// chainRule( ival, df ); +// +// unsigned kder; +// if( getAction()->lowmem ) kder = max_lowmem_stash + ival*getAction()->getNumberOfDerivatives(); +// else kder = getAction()->getFullNumberOfTasks() + ival*(nspace-1); +// +// for(unsigned i=0;i<active_der[ival];++i) val->addDerivative( active_der[kder+i] , final_derivatives[i] ); +// } } } diff --git a/src/vesselbase/StoreDataVessel.h b/src/vesselbase/StoreDataVessel.h index 36375648ffe67839b26c92858b2fcbcc15b2fad0..02a0f7f93147938b5fda421c216003b3d8438564 100644 --- a/src/vesselbase/StoreDataVessel.h +++ b/src/vesselbase/StoreDataVessel.h @@ -39,14 +39,13 @@ second step. */ class StoreDataVessel : public Vessel { +friend class Moments; private: /// Do the quantities being stored in here need derivatives bool hasderiv; /// What is the maximum number of vectors we are going to /// have to store when using lowmem option unsigned max_lowmem_stash; -/// The start point for the data we are storing in this particular object - unsigned data_start; /// The size of the vector we are computing unsigned vecsize; /// The amount of data per vector element @@ -56,13 +55,13 @@ private: /// The active derivative elements std::vector<unsigned> active_der; /// This is a tempory vector that is used to store data - std::vector<double> fvec; +// std::vector<double> fvec; /// The buffer - std::vector<double> local_buffer; -/// The local derivatives - std::vector<double> local_derivatives; -/// The final derivatives - std::vector<double> final_derivatives; + std::vector<double> local_buffer; +// /// The local derivatives +// std::vector<double> local_derivatives; +// /// The final derivatives +// std::vector<double> final_derivatives; protected: /// Apply a hard cutoff on the weight bool hard_cut; @@ -78,15 +77,15 @@ protected: /// Return value of nspace unsigned getNumberOfDerivativeSpacesPerComponent() const ; /// Retrieve the values from the underlying ActionWithVessel - void storeValues( const unsigned& , std::vector<double>& ); + void storeValues( const unsigned& , MultiValue& , std::vector<double>& ); /// Set the Task that needs redoing - void setTaskToRecompute( const unsigned& ivec ); +// void setTaskToRecompute( const unsigned& ivec ); /// Set a component of one of the vectors - void setComponent( const unsigned& , const unsigned& , const double& ); +// void setComponent( const unsigned& , const unsigned& , const double& ); /// This is the proper chain rule for vectors - double chainRule( const unsigned&, const unsigned&, const std::vector<double>& ); -/// Chain rule the vector and output derivatives to a value - void chainRule( const unsigned& , const std::vector<double>&, Value* ); +// double chainRule( const unsigned&, const unsigned&, const std::vector<double>& ); +// /// Chain rule the vector and output derivatives to a value +// void chainRule( const unsigned& , const std::vector<double>&, Value* ); /// Get the ibuf'th local derivative value double getLocalDerivative( const unsigned& ibuf ); /// Set the ibuf'th local derivative value @@ -100,33 +99,39 @@ public: bool weightCutoffIsOn() const ; /// Return the number of components in the vector unsigned getNumberOfComponents() const { return vecsize; } +/// Get the values of all the components in the vector + void retrieveValue( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const ; +/// Get the derivatives for one of the components in the vector + void retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ); /// Do all resizing of data virtual void resize(); /// Clear certain data before start of main loop virtual void prepare(); +/// + virtual std::string description(){ return ""; } /// Get the number of derivatives for the ith value unsigned getNumberOfDerivatives( const unsigned& ); /// Get one of the stored indexes - unsigned getStoredIndex( const unsigned& , const unsigned& ); +// unsigned getStoredIndex( const unsigned& , const unsigned& ); /// Get a component of the stored vector - double getComponent( const unsigned& , const unsigned& ); +// double getComponent( const unsigned& , const unsigned& ); /// Recalculate a vector - used in lowmem mode - virtual void recompute( const unsigned& , const unsigned& ); +// virtual void recompute( const unsigned& , const unsigned& ); /// This reperforms the task in the underlying action - virtual void performTask( const unsigned& ); +// virtual void performTask( const unsigned& ); /// This reperforms the task - virtual void finishTask( const unsigned& ){}; +// virtual void finishTask( const unsigned& ){}; /// Chain rule and store output in local array called final_derivatives /// with vectors this does chain rule for dot products - void chainRule( const unsigned& , const std::vector<double>& ); +// void chainRule( const unsigned& , const std::vector<double>& ); /// Get the ider'th final derivative value - double getFinalDerivative( const unsigned& ider ) const ; +// double getFinalDerivative( const unsigned& ider ) const ; /// This stores the data when not using lowmem - bool calculate( std::vector<double>& buffer ); + bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer ); /// This stores the data we get from the calculation - void storeDerivativesLowMem( const unsigned& ); +// void storeDerivativesLowMem( const unsigned& ); /// This stores the data we get from the calculation - void storeDerivativesHighMem( const unsigned& , std::vector<double>& ); + void storeDerivatives( const unsigned& , MultiValue& myvals, std::vector<double>& ); /// Final step in gathering data virtual void finish( const std::vector<double>& buffer ); /// Is a particular stored value active at the present time @@ -134,7 +139,7 @@ public: /// Activate indexes (this is used at end of chain rule) virtual void activateIndices( ActionWithVessel* ){} /// Get the list of indices that we are storing data for - virtual void getIndexList( const unsigned& , const unsigned& , const unsigned& , std::vector<unsigned>& ); +// virtual void getIndexList( const unsigned& , const unsigned& , const unsigned& , std::vector<unsigned>& ); /// Forces on vectors should always be applied elsewhere virtual bool applyForce(std::vector<double>&){ return false; } }; @@ -149,63 +154,63 @@ bool StoreDataVessel::usingLowMem(){ return getAction()->lowmem; } -inline -void StoreDataVessel::performTask( const unsigned& ivec ){ - if( usingLowMem() ) getAction()->performTask(); -} - -inline -double StoreDataVessel::getComponent( const unsigned& ival, const unsigned& jcomp ){ - plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() && jcomp<vecsize ); - return 0.0; // GAT Broken -// return getBufferElement( ival*(vecsize*nspace) + jcomp*nspace ); -} - -inline -void StoreDataVessel::setComponent( const unsigned& ival, const unsigned& jcomp, const double& val ){ - plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() && jcomp<vecsize ); -// setBufferElement( ival*(vecsize*nspace) + jcomp*nspace, val ); -} +// inline +// void StoreDataVessel::performTask( const unsigned& ivec ){ +// // if( usingLowMem() ) getAction()->performTask(); +// } + +// inline +// double StoreDataVessel::getComponent( const unsigned& ival, const unsigned& jcomp ){ +// plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() && jcomp<vecsize ); +// return 0.0; // GAT Broken +// // return getBufferElement( ival*(vecsize*nspace) + jcomp*nspace ); +// } +// +// inline +// void StoreDataVessel::setComponent( const unsigned& ival, const unsigned& jcomp, const double& val ){ +// plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() && jcomp<vecsize ); +// // setBufferElement( ival*(vecsize*nspace) + jcomp*nspace, val ); +// } inline unsigned StoreDataVessel::getNumberOfDerivativeSpacesPerComponent() const { return nspace; } -inline -unsigned StoreDataVessel::getNumberOfDerivatives( const unsigned& ival ){ - plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() ); - return active_der[ival]; -} - -inline -unsigned StoreDataVessel::getStoredIndex( const unsigned& ival, const unsigned& jindex ){ - plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() && jindex<active_der[ival] ); - - unsigned kder; - if( getAction()->lowmem ) kder = max_lowmem_stash + ival*getAction()->getNumberOfDerivatives(); - else kder = getAction()->getFullNumberOfTasks() + ival*(nspace-1); - - return active_der[kder + jindex]; -} - -inline -double StoreDataVessel::getLocalDerivative( const unsigned& ibuf ){ - plumed_dbg_assert( getAction()->lowmem && ibuf<local_derivatives.size() ); - return local_derivatives[ibuf]; -} - -inline -double StoreDataVessel::getFinalDerivative( const unsigned& ider ) const { - plumed_dbg_assert( ider<final_derivatives.size() ); - return final_derivatives[ider]; -} - -inline -void StoreDataVessel::setLocalDerivative( const unsigned& ibuf, const double& val ){ - plumed_dbg_assert( getAction()->lowmem && ibuf<local_derivatives.size() ); - local_derivatives[ibuf]=val; -} +// inline +// unsigned StoreDataVessel::getNumberOfDerivatives( const unsigned& ival ){ +// plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() ); +// return active_der[ival]; +// } + +// inline +// unsigned StoreDataVessel::getStoredIndex( const unsigned& ival, const unsigned& jindex ){ +// plumed_dbg_assert( ival<getAction()->getFullNumberOfTasks() && jindex<active_der[ival] ); +// +// unsigned kder; +// if( getAction()->lowmem ) kder = max_lowmem_stash + ival*getAction()->getNumberOfDerivatives(); +// else kder = getAction()->getFullNumberOfTasks() + ival*(nspace-1); +// +// return active_der[kder + jindex]; +// } + +// inline +// double StoreDataVessel::getLocalDerivative( const unsigned& ibuf ){ +// plumed_dbg_assert( getAction()->lowmem && ibuf<local_derivatives.size() ); +// return local_derivatives[ibuf]; +// } +// +// inline +// double StoreDataVessel::getFinalDerivative( const unsigned& ider ) const { +// plumed_dbg_assert( ider<final_derivatives.size() ); +// return final_derivatives[ider]; +// } +// +// inline +// void StoreDataVessel::setLocalDerivative( const unsigned& ibuf, const double& val ){ +// plumed_dbg_assert( getAction()->lowmem && ibuf<local_derivatives.size() ); +// local_derivatives[ibuf]=val; +// } inline bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ){ diff --git a/src/vesselbase/StoreValueAndWeightVessel.h b/src/vesselbase/StoreValueAndWeightVessel.h deleted file mode 100644 index 3dbf5563884761c4a94f80d9d147252856b1dd62..0000000000000000000000000000000000000000 --- a/src/vesselbase/StoreValueAndWeightVessel.h +++ /dev/null @@ -1,54 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#ifndef __PLUMED_vesselbase_StoreValueAndWeightVessel_h -#define __PLUMED_vesselbase_StoreValueAndWeightVessel_h - -#include <string> -#include <cstring> -#include <vector> -#include "StoreDataVessel.h" - -namespace PLMD { -namespace vesselbase { - -class StoreValueAndWeightVessel : public StoreDataVessel { -public: - static void registerKeywords( Keywords& keys ); - StoreValueAndWeightVessel( const VesselOptions& ); - double getValue( const unsigned& ); - double getWeight( const unsigned& ); -}; - -inline -double StoreValueAndWeightVessel::getValue( const unsigned& ival ){ - return getComponent( ival, 0 ); -} - -inline -double StoreValueAndWeightVessel::getWeight( const unsigned& ival ){ - return getComponent( ival, 1 ); -} - - -} -} -#endif diff --git a/src/vesselbase/StoreValueVessel.cpp b/src/vesselbase/StoreValueVessel.cpp deleted file mode 100644 index 38af097c541c8602a7685fd43b3508ce5bc482d9..0000000000000000000000000000000000000000 --- a/src/vesselbase/StoreValueVessel.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#include "StoreValueVessel.h" - -namespace PLMD { -namespace vesselbase { - -void StoreValueVessel::registerKeywords( Keywords& keys ){ - StoreDataVessel::registerKeywords( keys ); -} - -StoreValueVessel::StoreValueVessel( const VesselOptions& da): -StoreDataVessel(da) -{ - if( weightHasDerivatives() ) error("this quantity cannot be calculated if weights have derivatives"); - completeSetup( 0, 1 ); -} - -} -} diff --git a/src/vesselbase/StoreValueVessel.h b/src/vesselbase/StoreValueVessel.h deleted file mode 100644 index ccd3de4df879165a348b65eebf1c8ae7458426f8..0000000000000000000000000000000000000000 --- a/src/vesselbase/StoreValueVessel.h +++ /dev/null @@ -1,48 +0,0 @@ -/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2014 The plumed team - (see the PEOPLE file at the root of the distribution for a list of names) - - See http://www.plumed-code.org for more information. - - This file is part of plumed, version 2. - - plumed is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - plumed is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with plumed. If not, see <http://www.gnu.org/licenses/>. -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#ifndef __PLUMED_vesselbase_StoreValueVessel_h -#define __PLUMED_vesselbase_StoreValueVessel_h - -#include <string> -#include <cstring> -#include <vector> -#include "StoreDataVessel.h" - -namespace PLMD { -namespace vesselbase { - -class StoreValueVessel : public StoreDataVessel { -public: - static void registerKeywords( Keywords& keys ); - StoreValueVessel( const VesselOptions& ); - double getValue( const unsigned& ); - virtual std::string description(){ return ""; } -}; - -inline -double StoreValueVessel::getValue( const unsigned& ival ){ - return getComponent( ival, 0 ); -} - -} -} -#endif diff --git a/src/vesselbase/Sum.cpp b/src/vesselbase/Sum.cpp index 7fc58422c840dae9c757a55d7c442cd8b1daa4e2..08ce670bece4c78d4c9c4a034d6c8711156062c9 100644 --- a/src/vesselbase/Sum.cpp +++ b/src/vesselbase/Sum.cpp @@ -31,7 +31,7 @@ public: static void reserveKeyword( Keywords& keys ); Sum( const VesselOptions& da ); std::string function_description(); - bool calculate( std::vector<double>& buffer ); + double calcTransform( const double& val, double& dv ); }; PLUMED_REGISTER_VESSEL(Sum,"SUM") @@ -54,9 +54,8 @@ std::string Sum::function_description(){ return "the sum of all the values"; } -bool Sum::calculate( std::vector<double>& buffer ){ - double val=getAction()->getElementValue(0); - return addToBuffers( val, 1.0, buffer ); +double Sum::calcTransform( const double& val, double& dv ){ + dv=1.0; return val; } } diff --git a/src/vesselbase/Vessel.h b/src/vesselbase/Vessel.h index 2ed69e4f18df43e472aaead141eb1aac1289a3f8..8ff117e6ac33981467b31d4737a403e22ad16928 100644 --- a/src/vesselbase/Vessel.h +++ b/src/vesselbase/Vessel.h @@ -143,8 +143,10 @@ public: virtual void setBufferStart( unsigned& start ); /// Do something before the loop virtual void prepare(){} +/// This is replaced in bridges so we can transform the derivatives + virtual MultiValue& transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ); /// Calculate the part of the vessel that is done in the loop - virtual bool calculate( std::vector<double>& buffer )=0; + virtual bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer )=0; /// Complete the calculation once the loop is finished virtual void finish( const std::vector<double>& )=0; /// Reset the size of the buffers @@ -210,6 +212,11 @@ void Vessel::setBufferStart( unsigned& start ){ bufstart=start; start+=bufsize; } +inline +MultiValue& Vessel::transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ){ + return myvals; +} + inline void Vessel::resizeBuffer( const unsigned& n ){ bufsize=n;