diff --git a/src/adjmat/ActionWithInputMatrix.cpp b/src/adjmat/ActionWithInputMatrix.cpp index c0acb31959..5aed42c85b 100644 --- a/src/adjmat/ActionWithInputMatrix.cpp +++ b/src/adjmat/ActionWithInputMatrix.cpp @@ -29,43 +29,43 @@ namespace PLMD { namespace adjmat { -void ActionWithInputMatrix::registerKeywords( Keywords& keys ){ - MultiColvarBase::registerKeywords( keys ); - keys.add("compulsory","MATRIX","the action that calcualtes the adjacency matrix vessel we would like to analyse"); +void ActionWithInputMatrix::registerKeywords( Keywords& keys ) { + MultiColvarBase::registerKeywords( keys ); + keys.add("compulsory","MATRIX","the action that calcualtes the adjacency matrix vessel we would like to analyse"); } ActionWithInputMatrix::ActionWithInputMatrix(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao), -mymatrix(NULL) + Action(ao), + MultiColvarBase(ao), + mymatrix(NULL) { - matsums=true; - if( keywords.exists("MATRIX") ){ - std::vector fake_atoms; - if( !parseMultiColvarAtomList("MATRIX",-1,fake_atoms ) ) error("unable to interpret input matrix"); - if( mybasemulticolvars.size()!=1 ) error("should be exactly one matrix input"); - - // Retrieve the adjacency matrix of interest - for(unsigned i=0;igetNumberOfVessels();++i){ - mymatrix = dynamic_cast( mybasemulticolvars[0]->getPntrToVessel(i) ); - if( mymatrix ) break ; - } - if( !mymatrix ) error( mybasemulticolvars[0]->getLabel() + " does not calculate an adjacency matrix"); - - atom_lab.resize(0); unsigned nnodes; // Delete all the atom labels that have been created - if( mymatrix->undirectedGraph() ) nnodes = (mymatrix->function)->ablocks[0].size(); - else nnodes = (mymatrix->function)->ablocks[0].size() + (mymatrix->function)->ablocks[1].size(); - for(unsigned i=0;i( 1, i ) ); + matsums=true; + if( keywords.exists("MATRIX") ) { + std::vector fake_atoms; + if( !parseMultiColvarAtomList("MATRIX",-1,fake_atoms ) ) error("unable to interpret input matrix"); + if( mybasemulticolvars.size()!=1 ) error("should be exactly one matrix input"); + + // Retrieve the adjacency matrix of interest + for(unsigned i=0; igetNumberOfVessels(); ++i) { + mymatrix = dynamic_cast( mybasemulticolvars[0]->getPntrToVessel(i) ); + if( mymatrix ) break ; + } + if( !mymatrix ) error( mybasemulticolvars[0]->getLabel() + " does not calculate an adjacency matrix"); + + atom_lab.resize(0); unsigned nnodes; // Delete all the atom labels that have been created + if( mymatrix->undirectedGraph() ) nnodes = (mymatrix->function)->ablocks[0].size(); + else nnodes = (mymatrix->function)->ablocks[0].size() + (mymatrix->function)->ablocks[1].size(); + for(unsigned i=0; i( 1, i ) ); } } unsigned ActionWithInputMatrix::getNumberOfDerivatives() { - return (mymatrix->function)->getNumberOfDerivatives(); + return (mymatrix->function)->getNumberOfDerivatives(); } unsigned ActionWithInputMatrix::getNumberOfNodes() const { - return (mymatrix->function)->ablocks[0].size(); + return (mymatrix->function)->ablocks[0].size(); } AdjacencyMatrixVessel* ActionWithInputMatrix::getAdjacencyVessel() const { @@ -73,27 +73,27 @@ AdjacencyMatrixVessel* ActionWithInputMatrix::getAdjacencyVessel() const { } AtomNumber ActionWithInputMatrix::getAbsoluteIndexOfCentralAtom(const unsigned& i) const { - return (mymatrix->function)->getAbsoluteIndexOfCentralAtom(i); + return (mymatrix->function)->getAbsoluteIndexOfCentralAtom(i); } double ActionWithInputMatrix::retrieveConnectionValue( const unsigned& i, const unsigned& j, std::vector& vals ) const { if( !mymatrix->matrixElementIsActive( i, j ) ) return 0; unsigned myelem = mymatrix->getStoreIndexFromMatrixIndices( i, j ); - + unsigned vi; double df; - mymatrix->retrieveValueWithIndex( myelem, false, vals ); + mymatrix->retrieveValueWithIndex( myelem, false, vals ); return vals[0]*vals[1]; // (mymatrix->function)->transformStoredValues( vals, vi, df ); } void ActionWithInputMatrix::getInputData( const unsigned& ind, const bool& normed, const multicolvar::AtomValuePack& myatoms, std::vector& orient0 ) const { - if( (mymatrix->function)->mybasemulticolvars.size()==0 ){ - std::vector tvals( mymatrix->getNumberOfComponents() ); orient0.assign(orient0.size(),0); - for(unsigned i=0;igetNumberOfColumns();++i){ - if( mymatrix->undirectedGraph() && ind==i ) continue; - orient0[1]+=retrieveConnectionValue( ind, i, tvals ); - } - orient0[0]=1.0; return; - } + if( (mymatrix->function)->mybasemulticolvars.size()==0 ) { + std::vector tvals( mymatrix->getNumberOfComponents() ); orient0.assign(orient0.size(),0); + for(unsigned i=0; igetNumberOfColumns(); ++i) { + if( mymatrix->undirectedGraph() && ind==i ) continue; + orient0[1]+=retrieveConnectionValue( ind, i, tvals ); + } + orient0[0]=1.0; return; + } (mymatrix->function)->getInputData( ind, normed, myatoms, orient0 ); } @@ -102,33 +102,33 @@ void ActionWithInputMatrix::addConnectionDerivatives( const unsigned& i, const u unsigned myelem = mymatrix->getStoreIndexFromMatrixIndices( i, j ); // Get derivatives and add mymatrix->retrieveDerivatives( myelem, false, myvals ); - for(unsigned jd=0;jdfunction)->mybasemulticolvars.size()==0 ){ - MultiValue& myder=mymatrix->getTemporyMultiValue(0); - if( myder.getNumberOfValues()!=2 || myder.getNumberOfDerivatives()!=(mymatrix->function)->getNumberOfDerivatives() ){ - myder.resize( 2, (mymatrix->function)->getNumberOfDerivatives() ); - } - myder.clearAll(); - MultiValue myvals( (mymatrix->function)->getNumberOfQuantities(), (mymatrix->function)->getNumberOfDerivatives() ); - for(unsigned i=0;igetNumberOfColumns();++i){ - if( mymatrix->undirectedGraph() && ind==i ) continue; - addConnectionDerivatives( ind, i, myvals, myder ); - } - myder.updateDynamicList(); return myder; - } - return (mymatrix->function)->getInputDerivatives( ind, normed, myatoms ); + if( (mymatrix->function)->mybasemulticolvars.size()==0 ) { + MultiValue& myder=mymatrix->getTemporyMultiValue(0); + if( myder.getNumberOfValues()!=2 || myder.getNumberOfDerivatives()!=(mymatrix->function)->getNumberOfDerivatives() ) { + myder.resize( 2, (mymatrix->function)->getNumberOfDerivatives() ); + } + myder.clearAll(); + MultiValue myvals( (mymatrix->function)->getNumberOfQuantities(), (mymatrix->function)->getNumberOfDerivatives() ); + for(unsigned i=0; igetNumberOfColumns(); ++i) { + if( mymatrix->undirectedGraph() && ind==i ) continue; + addConnectionDerivatives( ind, i, myvals, myder ); + } + myder.updateDynamicList(); return myder; + } + return (mymatrix->function)->getInputDerivatives( ind, normed, myatoms ); } unsigned ActionWithInputMatrix::getNumberOfNodeTypes() const { unsigned size = (mymatrix->function)->mybasemulticolvars.size(); if( size==0 ) return 1; - return size; + return size; } unsigned ActionWithInputMatrix::getNumberOfQuantities() const { @@ -137,13 +137,13 @@ unsigned ActionWithInputMatrix::getNumberOfQuantities() const { } unsigned ActionWithInputMatrix::getNumberOfAtomsInGroup( const unsigned& igrp ) const { - plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); - return (mymatrix->function)->mybasemulticolvars[igrp]->getFullNumberOfTasks(); + plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); + return (mymatrix->function)->mybasemulticolvars[igrp]->getFullNumberOfTasks(); } multicolvar::MultiColvarBase* ActionWithInputMatrix::getBaseMultiColvar( const unsigned& igrp ) const { - plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); - return (mymatrix->function)->mybasemulticolvars[igrp]; + plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); + return (mymatrix->function)->mybasemulticolvars[igrp]; } Vector ActionWithInputMatrix::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { diff --git a/src/adjmat/ActionWithInputMatrix.h b/src/adjmat/ActionWithInputMatrix.h index 55c2567eaa..994f5ff240 100644 --- a/src/adjmat/ActionWithInputMatrix.h +++ b/src/adjmat/ActionWithInputMatrix.h @@ -57,7 +57,7 @@ class ActionWithInputMatrix : public multicolvar::MultiColvarBase { virtual unsigned getNumberOfDerivatives(); /// Get the number of rows/cols in the adjacency matrix vessel virtual unsigned getNumberOfNodes() const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } virtual unsigned getNumberOfQuantities() const ; /// virtual AtomNumber getAbsoluteIndexOfCentralAtom(const unsigned& i) const ; diff --git a/src/adjmat/AdjacencyMatrixBase.cpp b/src/adjmat/AdjacencyMatrixBase.cpp index 4f9844f9bc..9f6cc8de7d 100644 --- a/src/adjmat/AdjacencyMatrixBase.cpp +++ b/src/adjmat/AdjacencyMatrixBase.cpp @@ -29,73 +29,73 @@ namespace PLMD { namespace adjmat { -void AdjacencyMatrixBase::registerKeywords( Keywords& keys ){ +void AdjacencyMatrixBase::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); keys.remove("LOWMEM"); keys.use("HIGHMEM"); } AdjacencyMatrixBase::AdjacencyMatrixBase(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao), -connect_id(0), -no_third_dim_accum(true), -mat(NULL) + Action(ao), + MultiColvarBase(ao), + connect_id(0), + no_third_dim_accum(true), + mat(NULL) { log<<" Bibliography "< sw; - if( !multiple ){ - sw.resize(1); parse(key,sw[0]); - if(sw[0].length()==0) error("could not find " + key + " keyword"); - } else { - std::string input; - for(int i=1;;i++){ - if( !parseNumbered(key, i, input ) ) break; - sw.push_back( input ); - } +void AdjacencyMatrixBase::parseConnectionDescriptions( const std::string& key, const bool& multiple, const unsigned& nrow_t ) { + if( getNumberOfNodeTypes()==1 || (getNumberOfNodeTypes()==2 && nrow_t==1) ) { + std::vector sw; + if( !multiple ) { + sw.resize(1); parse(key,sw[0]); + if(sw[0].length()==0) error("could not find " + key + " keyword"); + } else { + std::string input; + for(int i=1;; i++) { + if( !parseNumbered(key, i, input ) ) break; + sw.push_back( input ); } - setupConnector( connect_id, 0, 0, sw ); + } + setupConnector( connect_id, 0, 0, sw ); } else { - if( multiple ) error("keyword " + key + " does not work with multiple input strings"); - unsigned nr, nc; - if( nrow_t==0 ){ - nr=nc=getNumberOfNodeTypes(); - } else{ - nr=nrow_t; nc = getNumberOfNodeTypes() - nr; + if( multiple ) error("keyword " + key + " does not work with multiple input strings"); + unsigned nr, nc; + if( nrow_t==0 ) { + nr=nc=getNumberOfNodeTypes(); + } else { + nr=nrow_t; nc = getNumberOfNodeTypes() - nr; + } + for(unsigned i=0; i sw(1); parseNumbered(key,ibase+j+1,sw[0]); - if(sw[0].length()==0){ - std::string num; Tools::convert(ibase+j+1,num); - error("could not find " + key + num + " keyword. Need one " + key + " keyword for each distinct base-multicolvar-pair type"); - } - setupConnector( connect_id, i, j, sw ); - } + + for(unsigned j=i; j sw(1); parseNumbered(key,ibase+j+1,sw[0]); + if(sw[0].length()==0) { + std::string num; Tools::convert(ibase+j+1,num); + error("could not find " + key + num + " keyword. Need one " + key + " keyword for each distinct base-multicolvar-pair type"); + } + setupConnector( connect_id, i, j, sw ); } + } } connect_id++; } unsigned AdjacencyMatrixBase::getSizeOfInputVectors() const { - if( mybasemulticolvars.size()==0 ) return 2; + if( mybasemulticolvars.size()==0 ) return 2; unsigned nq = mybasemulticolvars[0]->getNumberOfQuantities(); - for(unsigned i=1;igetNumberOfQuantities()!=nq ) error("mismatch between vectors in base colvars"); + for(unsigned i=1; igetNumberOfQuantities()!=nq ) error("mismatch between vectors in base colvars"); } return nq; } @@ -108,69 +108,69 @@ unsigned AdjacencyMatrixBase::getNumberOfNodeTypes() const { void AdjacencyMatrixBase::retrieveTypeDimensions( unsigned& nrows, unsigned& ncols, unsigned& ntype ) const { bool allsame=(ablocks[0].size()==ablocks[1].size()); - if( allsame ){ - for(unsigned i=0;i types(1); types[0]=atom_lab[ablocks[0][0]].first; - for(unsigned i=1;i types(1); types[0]=atom_lab[ablocks[0][0]].first; + for(unsigned i=1; i types(1); types[0]=atom_lab[ablocks[0][0]].first; - for(unsigned i=1;i types(1); types[0]=atom_lab[ablocks[0][0]].first; + for(unsigned i=1; i& all_atoms ){ +void AdjacencyMatrixBase::finishMatrixSetup( const bool& symmetric, const std::vector& all_atoms ) { std::string param; if( symmetric && ablocks[0].size()==ablocks[1].size() ) param="SYMMETRIC"; - if( !symmetric ){ - bool usehbonds=( ablocks[0].size()==ablocks[1].size() ); - if( usehbonds ){ - for(unsigned i=0;i all_atoms; readTwoGroups( key0, key1, key2, all_atoms ); finishMatrixSetup( symmetric, all_atoms ); } -void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& keym, const bool& symmetric ){ +void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& keym, const bool& symmetric ) { std::vector all_atoms; readGroupKeywords( key0, key1, key2, keym, true, symmetric, all_atoms ); finishMatrixSetup( symmetric, all_atoms ); } @@ -180,14 +180,14 @@ void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, co // AtomNumber AdjacencyMatrixBase::getAbsoluteIndexOfCentralAtom(const unsigned& i) const { // plumed_dbg_assert( i myatoms; decodeIndexToAtoms( getTaskCode( myelem ), myatoms ); unsigned i=myatoms[0], j=myatoms[1]; - for(unsigned k=bookeeping(i,j).first;k& desc ) = 0; /// None of these things are allowed - bool isPeriodic(){ return false; } - Vector getCentralAtom(){ plumed_merror("cannot find central atoms for adjacency matrix actions"); Vector dum; return dum; } + bool isPeriodic() { return false; } + Vector getCentralAtom() { plumed_merror("cannot find central atoms for adjacency matrix actions"); Vector dum; return dum; } /// Get the atom number - AtomNumber getAbsoluteIndexOfCentralAtom( const unsigned& i ) const ; + AtomNumber getAbsoluteIndexOfCentralAtom( const unsigned& i ) const ; }; inline -AdjacencyMatrixVessel* AdjacencyMatrixBase::getAdjacencyVessel(){ +AdjacencyMatrixVessel* AdjacencyMatrixBase::getAdjacencyVessel() { return mat; } inline unsigned AdjacencyMatrixBase::getBaseColvarNumber( const unsigned& inum ) const { - if( atom_lab[inum].first>0 ) return atom_lab[inum].first-1; + if( atom_lab[inum].first>0 ) return atom_lab[inum].first-1; return 0; } inline AtomNumber AdjacencyMatrixBase::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const { - if( atom_lab[iatom].first>0 ){ - unsigned mmc=atom_lab[ iatom ].first - 1; - return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); + if( atom_lab[iatom].first>0 ) { + unsigned mmc=atom_lab[ iatom ].first - 1; + return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); } return ActionAtomistic::getAbsoluteIndex( atom_lab[iatom].second ); } diff --git a/src/adjmat/AdjacencyMatrixVessel.cpp b/src/adjmat/AdjacencyMatrixVessel.cpp index 6d07fc40e1..f4a62bb6db 100644 --- a/src/adjmat/AdjacencyMatrixVessel.cpp +++ b/src/adjmat/AdjacencyMatrixVessel.cpp @@ -20,20 +20,20 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "AdjacencyMatrixVessel.h" -#include "AdjacencyMatrixBase.h" +#include "AdjacencyMatrixBase.h" #include "vesselbase/ActionWithVessel.h" namespace PLMD { namespace adjmat { -void AdjacencyMatrixVessel::registerKeywords( Keywords& keys ){ +void AdjacencyMatrixVessel::registerKeywords( Keywords& keys ) { StoreDataVessel::registerKeywords(keys); keys.addFlag("SYMMETRIC",false,"is the matrix symmetric"); keys.addFlag("HBONDS",false,"can we think of the matrix as a undirected graph"); } AdjacencyMatrixVessel::AdjacencyMatrixVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da) + StoreDataVessel(da) { function=dynamic_cast( getAction() ); plumed_assert( function ); @@ -65,13 +65,13 @@ bool AdjacencyMatrixVessel::matrixElementIsActive( const unsigned& ielem, const unsigned AdjacencyMatrixVessel::getStoreIndexFromMatrixIndices( const unsigned& ielem, const unsigned& jelem ) const { if( !symmetric && !hbonds ) return (function->ablocks[1].size())*ielem + jelem; - if( !symmetric ){ - plumed_dbg_assert( ielem!=jelem ); - if( jelemablocks[1].size()-1)*ielem + jelem; - return (function->ablocks[1].size()-1)*ielem + jelem - 1; + if( !symmetric ) { + plumed_dbg_assert( ielem!=jelem ); + if( jelemablocks[1].size()-1)*ielem + jelem; + return (function->ablocks[1].size()-1)*ielem + jelem - 1; } if( ielem>jelem ) return 0.5*ielem*(ielem-1)+jelem; - return 0.5*jelem*(jelem-1) + ielem; + return 0.5*jelem*(jelem-1) + ielem; } AdjacencyMatrixBase* AdjacencyMatrixVessel::getMatrixAction() { @@ -79,61 +79,61 @@ AdjacencyMatrixBase* AdjacencyMatrixVessel::getMatrixAction() { } void AdjacencyMatrixVessel::getMatrixIndices( const unsigned& code, unsigned& i, unsigned& j ) const { - std::vector myatoms; function->decodeIndexToAtoms( function->getTaskCode(code), myatoms ); - i=myatoms[0]; j=myatoms[1]; - if( !undirectedGraph() ) j -= function->ablocks[0].size(); // Have to remove number of columns as returns number in ablocks[1] + std::vector myatoms; function->decodeIndexToAtoms( function->getTaskCode(code), myatoms ); + i=myatoms[0]; j=myatoms[1]; + if( !undirectedGraph() ) j -= function->ablocks[0].size(); // Have to remove number of columns as returns number in ablocks[1] } -void AdjacencyMatrixVessel::retrieveMatrix( DynamicList& myactive_elements, Matrix& mymatrix ){ +void AdjacencyMatrixVessel::retrieveMatrix( DynamicList& myactive_elements, Matrix& mymatrix ) { unsigned vin; double df; - myactive_elements.deactivateAll(); std::vector vals( getNumberOfComponents() ); - for(unsigned i=0;i vals( getNumberOfComponents() ); + for(unsigned i=0; igetPositionInFullTaskList(i), k, j ); + myactive_elements.activate(i); + unsigned j, k; getMatrixIndices( function->getPositionInFullTaskList(i), k, j ); - if( symmetric ) mymatrix(k,j)=mymatrix(j,k)=vals[0]*vals[1]; - else mymatrix(k,j)=vals[0]*vals[1]; + if( symmetric ) mymatrix(k,j)=mymatrix(j,k)=vals[0]*vals[1]; + else mymatrix(k,j)=vals[0]*vals[1]; } - myactive_elements.updateActiveMembers(); + myactive_elements.updateActiveMembers(); } -void AdjacencyMatrixVessel::retrieveAdjacencyLists( std::vector& nneigh, Matrix& adj_list ){ +void AdjacencyMatrixVessel::retrieveAdjacencyLists( std::vector& nneigh, Matrix& adj_list ) { plumed_dbg_assert( undirectedGraph() ); // Currently everything has zero neighbors - for(unsigned i=0;i myvals( getNumberOfComponents() ); - for(unsigned i=0;igetPositionInFullTaskList(i), k, j ); - - if( nneigh[j]>=adj_list.ncols() || nneigh[k]>=adj_list.ncols() ) error("adjacency lists are not large enough, increase maxconnections"); - // Store if atoms are connected - // unsigned j, k; getMatrixIndices( i, k, j ); - adj_list(k,nneigh[k])=j; nneigh[k]++; - adj_list(j,nneigh[j])=k; nneigh[j]++; + for(unsigned i=0; igetPositionInFullTaskList(i), k, j ); + + if( nneigh[j]>=adj_list.ncols() || nneigh[k]>=adj_list.ncols() ) error("adjacency lists are not large enough, increase maxconnections"); + // Store if atoms are connected + // unsigned j, k; getMatrixIndices( i, k, j ); + adj_list(k,nneigh[k])=j; nneigh[k]++; + adj_list(j,nneigh[j])=k; nneigh[j]++; } } -void AdjacencyMatrixVessel::retrieveEdgeList( unsigned& nedge, std::vector >& edge_list ){ +void AdjacencyMatrixVessel::retrieveEdgeList( unsigned& nedge, std::vector >& edge_list ) { plumed_dbg_assert( undirectedGraph() ); nedge=0; std::vector myvals( getNumberOfComponents() ); if( getNumberOfStoredValues()>edge_list.size() ) error("adjacency lists are not large enough, increase maxconnections"); - for(unsigned i=0;igetPositionInFullTaskList(i), edge_list[nedge].first, edge_list[nedge].second ); - nedge++; + getMatrixIndices( function->getPositionInFullTaskList(i), edge_list[nedge].first, edge_list[nedge].second ); + nedge++; } } @@ -141,7 +141,7 @@ bool AdjacencyMatrixVessel::nodesAreConnected( const unsigned& iatom, const unsi if( !matrixElementIsActive( iatom, jatom ) ) return false; unsigned ind=getStoreIndexFromMatrixIndices( iatom, jatom ); - std::vector myvals( getNumberOfComponents() ); + std::vector myvals( getNumberOfComponents() ); retrieveValueWithIndex( ind, false, myvals ); return ( myvals[0]>epsilon && myvals[1]>epsilon ); } diff --git a/src/adjmat/AdjacencyMatrixVessel.h b/src/adjmat/AdjacencyMatrixVessel.h index 637208bd4e..7e1ef1586c 100644 --- a/src/adjmat/AdjacencyMatrixVessel.h +++ b/src/adjmat/AdjacencyMatrixVessel.h @@ -22,7 +22,7 @@ #ifndef __PLUMED_adjmat_AdjacencyMatrixVessel_h #define __PLUMED_adjmat_AdjacencyMatrixVessel_h -#include "vesselbase/StoreDataVessel.h" +#include "vesselbase/StoreDataVessel.h" #include "multicolvar/MultiColvarBase.h" namespace PLMD { @@ -30,15 +30,15 @@ namespace adjmat { class AdjacencyMatrixBase; -// One school of thought would have it that it makes more sense to +// One school of thought would have it that it makes more sense to // have the functionality contained within this class in AdjacencyMatrixBase // I have not done this as I can inherit many useful things from StoreDataVessel // If I put this functionality within AdjacencyMatrixBase I would have to reimplement // these features. class AdjacencyMatrixVessel : public vesselbase::StoreDataVessel { -friend class AdjacencyMatrixBase; -friend class ActionWithInputMatrix; + friend class AdjacencyMatrixBase; + friend class ActionWithInputMatrix; private: /// Pointer to underlying action AdjacencyMatrixBase* function; @@ -63,7 +63,7 @@ friend class ActionWithInputMatrix; /// void getMatrixIndices( const unsigned& code, unsigned& i, unsigned& j ) const ; /// Can we think of the matrix as an undirected graph - bool undirectedGraph() const ; + bool undirectedGraph() const ; /// Is the matrix symmetric bool isSymmetric() const ; /// Get the number of rows diff --git a/src/adjmat/AlignedMatrixBase.cpp b/src/adjmat/AlignedMatrixBase.cpp index 28fd47c936..408cf8c736 100644 --- a/src/adjmat/AlignedMatrixBase.cpp +++ b/src/adjmat/AlignedMatrixBase.cpp @@ -27,59 +27,59 @@ namespace PLMD { namespace adjmat { -void AlignedMatrixBase::registerKeywords( Keywords& keys ){ +void AlignedMatrixBase::registerKeywords( Keywords& keys ) { AdjacencyMatrixBase::registerKeywords( keys ); keys.add("atoms","ATOMS","The list of molecules for which you would like to calculate the contact matrix. The molecules involved must " - "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " - "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " - "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); + "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " + "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " + "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); keys.add("atoms-1","ATOMSA","The list of molecules that you would like to use for the rows of the contact matrix. The molecules involved must " - "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " - "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " - "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); + "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " + "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " + "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); keys.add("atoms-1","ATOMSB","The list of molecules that you would like to use for the columns of the contact matrix. The molecules involved must " - "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " - "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " - "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); + "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " + "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " + "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); keys.add("numbered","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); } AlignedMatrixBase::AlignedMatrixBase( const ActionOptions& ao ): -Action(ao), -AdjacencyMatrixBase(ao) + Action(ao), + AdjacencyMatrixBase(ao) { // Read in the atomic positions readMaxTwoSpeciesMatrix( "ATOMS", "ATOMSA", "ATOMSB", true ); - unsigned nrows, ncols; retrieveTypeDimensions( nrows, ncols, ncol_t ); + unsigned nrows, ncols; retrieveTypeDimensions( nrows, ncols, ncol_t ); if( mybasemulticolvars.size()==0 ) error("cannot use atom indices as input to this variable / input was not specified"); if( getSizeOfInputVectors()<3 ) error("base multicolvars do not calculate an orientation"); // Read in the switching function switchingFunction.resize( nrows, ncols ); - parseConnectionDescriptions("SWITCH",false,ncol_t); + parseConnectionDescriptions("SWITCH",false,ncol_t); // Find the largest sf cutoff double sfmax=switchingFunction(0,0).get_dmax(); - for(unsigned i=0;isfmax ) sfmax=tsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + } } // And set the link cell cutoff setLinkCellCutoff( sfmax ); } -void AlignedMatrixBase::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ - plumed_assert( id<2 ); - if( id==0 ){ - plumed_assert( desc.size()==1 ); std::string errors; switchingFunction(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function in SWITCH keywrd description " + errors); - if( j!=i) switchingFunction(i,j).set(desc[0],errors); - log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); - } else if( id==1 ){ - readOrientationConnector( i, j, desc ); +void AlignedMatrixBase::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { + plumed_assert( id<2 ); + if( id==0 ) { + plumed_assert( desc.size()==1 ); std::string errors; switchingFunction(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function in SWITCH keywrd description " + errors); + if( j!=i) switchingFunction(i,j).set(desc[0],errors); + log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); + } else if( id==1 ) { + readOrientationConnector( i, j, desc ); } } @@ -94,21 +94,21 @@ double AlignedMatrixBase::compute( const unsigned& tindex, multicolvar::AtomValu std::vector orient0(ncomp), orient1(ncomp), dorient0(ncomp), dorient1(ncomp); Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); getInputData( 0, true, myatoms, orient0 ); getInputData( 1, true, myatoms, orient1 ); - double f_dot = computeVectorFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t, + double f_dot = computeVectorFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t, distance, orient0, orient1, ddistance, dorient0, dorient1 ); // Retrieve the weight of the connection - double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t ).calculate( distance.modulo(), dfunc ); + double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t ).calculate( distance.modulo(), dfunc ); - if( !doNotCalculateDerivatives() ){ - addAtomDerivatives( 1, 0, (-dfunc)*f_dot*distance - sw*ddistance, myatoms ); - addAtomDerivatives( 1, 1, (+dfunc)*f_dot*distance + sw*ddistance, myatoms ); - myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) - sw*extProduct( distance, ddistance ) ); + if( !doNotCalculateDerivatives() ) { + addAtomDerivatives( 1, 0, (-dfunc)*f_dot*distance - sw*ddistance, myatoms ); + addAtomDerivatives( 1, 1, (+dfunc)*f_dot*distance + sw*ddistance, myatoms ); + myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) - sw*extProduct( distance, ddistance ) ); - // Add derivatives of orientation - for(unsigned k=2;k fake_atoms; @@ -46,14 +46,14 @@ myclusters(NULL) // Setup the atom pack myfatoms.setNumberOfAtoms( myclusters->getNumberOfNodes() ); myfvals.getIndices().resize( myclusters->getNumberOfNodes() ); - for(unsigned i=0;igetNumberOfNodes();++i) myfatoms.setAtomIndex( i, i ); + for(unsigned i=0; igetNumberOfNodes(); ++i) myfatoms.setAtomIndex( i, i ); } -void ClusterAnalysisBase::turnOnDerivatives(){ +void ClusterAnalysisBase::turnOnDerivatives() { // Check for dubious vessels - for(unsigned i=0;igetName()=="MEAN" ) error("MEAN of cluster is not differentiable"); - if( getPntrToVessel(i)->getName()=="VMEAN" ) error("VMEAN of cluster is not differentiable"); + for(unsigned i=0; igetName()=="MEAN" ) error("MEAN of cluster is not differentiable"); + if( getPntrToVessel(i)->getName()=="VMEAN" ) error("VMEAN of cluster is not differentiable"); } MultiColvarBase::turnOnDerivatives(); } @@ -70,7 +70,7 @@ unsigned ClusterAnalysisBase::getNumberOfClusters() const { return myclusters->getNumberOfClusters(); } -bool ClusterAnalysisBase::isPeriodic(){ +bool ClusterAnalysisBase::isPeriodic() { return mybasemulticolvars[0]->isPeriodic(); } diff --git a/src/adjmat/ClusterAnalysisBase.h b/src/adjmat/ClusterAnalysisBase.h index 58d4b91e73..24a1b80aee 100644 --- a/src/adjmat/ClusterAnalysisBase.h +++ b/src/adjmat/ClusterAnalysisBase.h @@ -48,7 +48,7 @@ class ClusterAnalysisBase : public multicolvar::MultiColvarBase { unsigned getNumberOfQuantities() const ; bool isPeriodic(); void turnOnDerivatives(); - void setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ){} + void setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ) {} Vector getPositionOfAtomForLinkCells( const unsigned& ) const ; double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { plumed_error(); } }; diff --git a/src/adjmat/ClusterDiameter.cpp b/src/adjmat/ClusterDiameter.cpp index c1a6fa54ab..ec26f2eeb9 100644 --- a/src/adjmat/ClusterDiameter.cpp +++ b/src/adjmat/ClusterDiameter.cpp @@ -26,11 +26,11 @@ /* Print out the diameter of one of the connected components -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. When analysing these matrix we can treat them as a graph and find connected components using some clustering algorithm. This action is used in tandem with this form of analysis -to output the largest of the distances between the paris of atoms that are connected together in a particular connected component. It is important to +to output the largest of the distances between the paris of atoms that are connected together in a particular connected component. It is important to note that the quantity that is output by this action is not differentiable. As such it cannot be used as a collective variable in a biased simulation. \par Examples @@ -79,51 +79,51 @@ class ClusterDiameter : public ClusterAnalysisBase { PLUMED_REGISTER_ACTION(ClusterDiameter,"CLUSTER_DIAMETER") -void ClusterDiameter::registerKeywords( Keywords& keys ){ +void ClusterDiameter::registerKeywords( Keywords& keys ) { ClusterAnalysisBase::registerKeywords( keys ); keys.add("compulsory","CLUSTER","1","which cluster would you like to look at 1 is the largest cluster, 2 is the second largest, 3 is the the third largest and so on."); } ClusterDiameter::ClusterDiameter(const ActionOptions&ao): -Action(ao), -ClusterAnalysisBase(ao) + Action(ao), + ClusterAnalysisBase(ao) { - // Find out which cluster we want - parse("CLUSTER",clustr); - - if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); - if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); - - // Create the task list - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); + // Find out which cluster we want + parse("CLUSTER",clustr); + + if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); + if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); + + // Create the task list + for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); } -void ClusterDiameter::turnOnDerivatives(){ - error("cannot calculate derivatives of cluster radius. This quantity is not differentiable"); +void ClusterDiameter::turnOnDerivatives() { + error("cannot calculate derivatives of cluster radius. This quantity is not differentiable"); } -void ClusterDiameter::calculate(){ - // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); - // Activate the relevant tasks - deactivateAllTasks(); - for(unsigned i=1;i myatoms; retrieveAtomsInCluster( clustr, myatoms ); + // Activate the relevant tasks + deactivateAllTasks(); + for(unsigned i=1; i fake_atoms; setupMultiColvarBase( fake_atoms ); + use_switch=false; + std::string input, errors; parse("TRANSFORM",input); + if( input!="none" ) { + use_switch=true; sf.set( input, errors ); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } + parseFlag("INVERSE_TRANSFORM",inverse); + if( inverse && !use_switch ) error("INVERSE_TRANSFORM option was specified but no TRANSOFRM switching function was given"); + + // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) + for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); } -void ClusterDistribution::calculate(){ - // Activate the relevant tasks - nderivatives = getNumberOfDerivatives(); - deactivateAllTasks(); - for(unsigned i=0;i vals( getNumberOfQuantities() ); + std::vector vals( getNumberOfQuantities() ); MultiValue tvals( getNumberOfQuantities(), nderivatives ); // And this builds everything for this particular atom - double vv, df, tval=0; - for(unsigned j=0;jgetNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); + if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); + if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); - // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); + // And now finish the setup of everything in the base + std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); } -void ClusterProperties::calculate(){ - // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); - // Activate the relevant tasks - deactivateAllTasks(); - for(unsigned i=0;i myatoms; retrieveAtomsInCluster( clustr, myatoms ); + // Activate the relevant tasks + deactivateAllTasks(); + for(unsigned i=0; i vals( myvals.getNumberOfValues() ); getPropertiesOfNode( current, vals ); - if( !doNotCalculateDerivatives() ) getNodePropertyDerivatives( current, myvals ); - for(unsigned k=0;k vals( myvals.getNumberOfValues() ); getPropertiesOfNode( current, vals ); + if( !doNotCalculateDerivatives() ) getNodePropertyDerivatives( current, myvals ); + for(unsigned k=0; kgetNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); + if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); + if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); - // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); - addValue(); setNotPeriodic(); + // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) + for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); + addValue(); setNotPeriodic(); } -void ClusterSize::turnOnDerivatives(){ - error("cannot calculate derivatives of number of atoms in cluster. This quantity is not differentiable"); +void ClusterSize::turnOnDerivatives() { + error("cannot calculate derivatives of number of atoms in cluster. This quantity is not differentiable"); } -void ClusterSize::calculate(){ - // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); setValue( myatoms.size() ); +void ClusterSize::calculate() { + // Retrieve the atoms in the largest cluster + std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); setValue( myatoms.size() ); } } diff --git a/src/adjmat/ClusterWithSurface.cpp b/src/adjmat/ClusterWithSurface.cpp index 21c2e3a5cd..ab472eee50 100644 --- a/src/adjmat/ClusterWithSurface.cpp +++ b/src/adjmat/ClusterWithSurface.cpp @@ -24,24 +24,24 @@ #include "AdjacencyMatrixBase.h" #include "core/ActionRegister.h" -//+PLUMEDOC MATRIXF CLUSTER_WITHSURFACE +//+PLUMEDOC MATRIXF CLUSTER_WITHSURFACE /* Take a connected component that was found using a clustering algorithm and create a new cluster that contains those atoms that are in the cluster together with those atoms that are within a certain cutoff of the cluster. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. When analysing these matrix we can treat them as a graph and find connected components using some clustering algorithm. This action is used in tandem with this form of analysis -and takes one of the connected components that was found during this analysis and creates a new cluster that includes all the atoms within the +and takes one of the connected components that was found during this analysis and creates a new cluster that includes all the atoms within the connected component that was found together that were within a certain cutoff distance of the atoms in the connected component. This form of analysis has been used sucessfully in the forward flux sampling simulations described in this paper \cite gab-ice-kaolinite \par Examples -The following input uses PLUMED to calculate a adjacency matrix that connects a pair of atoms if they both have a coordination number that is less +The following input uses PLUMED to calculate a adjacency matrix that connects a pair of atoms if they both have a coordination number that is less than 13.5 and if they are within 0.38 nm of each other. Depth first search clustering is used to find the connected components in this matrix. The -number of atoms with indices that are between 1 and 1996 and that are either in the second largest cluster or that are within within 0.3 nm of one of the -atoms within the the second largest cluster are then counted and this number of atoms is output to a file called size. In addition the indices of the atoms +number of atoms with indices that are between 1 and 1996 and that are either in the second largest cluster or that are within within 0.3 nm of one of the +atoms within the the second largest cluster are then counted and this number of atoms is output to a file called size. In addition the indices of the atoms that were counted are output to a file called dfs2.dat. \verbatim @@ -88,45 +88,45 @@ class ClusterWithSurface : public ClusteringBase { /// unsigned getNumberOfQuantities() const ; /// Do the calculation - void performClustering(){}; + void performClustering() {}; /// - double getCutoffForConnection() const ; + double getCutoffForConnection() const ; /// Vector getPositionOfAtomForLinkCells( const unsigned& taskIndex ) const ; }; PLUMED_REGISTER_ACTION(ClusterWithSurface,"CLUSTER_WITHSURFACE") -void ClusterWithSurface::registerKeywords( Keywords& keys ){ +void ClusterWithSurface::registerKeywords( Keywords& keys ) { ClusteringBase::registerKeywords( keys ); keys.remove("MATRIX"); keys.add("compulsory","CLUSTERS","the label of the action that does the clustering"); keys.add("compulsory","RCUT_SURF","you also have the option to find the atoms on the surface of the cluster. An atom must be within this distance of one of the atoms " - "of the cluster in order to be considered a surface atom"); + "of the cluster in order to be considered a surface atom"); } ClusterWithSurface::ClusterWithSurface(const ActionOptions&ao): -Action(ao), -ClusteringBase(ao) + Action(ao), + ClusteringBase(ao) { - std::vector fake_atoms; - if( !parseMultiColvarAtomList("CLUSTERS",-1,fake_atoms ) ) error("unable to find CLUSTERS input"); - if( mybasemulticolvars.size()!=1 ) error("should be exactly one multicolvar input"); + std::vector fake_atoms; + if( !parseMultiColvarAtomList("CLUSTERS",-1,fake_atoms ) ) error("unable to find CLUSTERS input"); + if( mybasemulticolvars.size()!=1 ) error("should be exactly one multicolvar input"); - // Retrieve the adjacency matrix of interest - atom_lab.resize(0); myclusters = dynamic_cast( mybasemulticolvars[0] ); - if( !myclusters ) error( mybasemulticolvars[0]->getLabel() + " does not calculate clusters"); + // Retrieve the adjacency matrix of interest + atom_lab.resize(0); myclusters = dynamic_cast( mybasemulticolvars[0] ); + if( !myclusters ) error( mybasemulticolvars[0]->getLabel() + " does not calculate clusters"); - // Setup switching function for surface atoms - double rcut_surf; parse("RCUT_SURF",rcut_surf); - if( rcut_surf>0 ) log.printf(" counting surface atoms that are within %f of the cluster atoms \n",rcut_surf); - rcut_surf2=rcut_surf*rcut_surf; + // Setup switching function for surface atoms + double rcut_surf; parse("RCUT_SURF",rcut_surf); + if( rcut_surf>0 ) log.printf(" counting surface atoms that are within %f of the cluster atoms \n",rcut_surf); + rcut_surf2=rcut_surf*rcut_surf; - // And now finish the setup of everything in the base - setupMultiColvarBase( fake_atoms ); + // And now finish the setup of everything in the base + setupMultiColvarBase( fake_atoms ); } -unsigned ClusterWithSurface::getNumberOfDerivatives(){ +unsigned ClusterWithSurface::getNumberOfDerivatives() { return myclusters->getNumberOfDerivatives(); } @@ -161,26 +161,26 @@ void ClusterWithSurface::retrieveAtomsInCluster( const unsigned& clust, std::vec // Prevent double counting std::vector incluster( getNumberOfNodes(), false ); - for(unsigned i=0;i surface_atom( getNumberOfNodes(), false ); - for(unsigned i=0;i surface_atom( getNumberOfNodes(), false ); + for(unsigned i=0; iundirectedGraph() ) error("input contact matrix is incompatible with clustering"); - } - if( keywords.exists("MATRIX") ){ - std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); - } + if( getAdjacencyVessel() ) { + cluster_sizes.resize(getNumberOfNodes()); which_cluster.resize(getNumberOfNodes()); + if( getNumberOfNodeTypes()!=1 ) error("should only be running clustering with one base multicolvar in function"); + if( !getAdjacencyVessel()->undirectedGraph() ) error("input contact matrix is incompatible with clustering"); + } + if( keywords.exists("MATRIX") ) { + std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); + } } -void ClusteringBase::turnOnDerivatives(){ - // Check base multicolvar isn't density probably other things shouldn't be allowed here as well - if( (getAdjacencyVessel()->getMatrixAction())->getNumberOfBaseMultiColvars()>0 ){ - if( getBaseMultiColvar(0)->isDensity() ) error("DFS clustering cannot be differentiated if base multicolvar is DENSITY"); - } +void ClusteringBase::turnOnDerivatives() { + // Check base multicolvar isn't density probably other things shouldn't be allowed here as well + if( (getAdjacencyVessel()->getMatrixAction())->getNumberOfBaseMultiColvars()>0 ) { + if( getBaseMultiColvar(0)->isDensity() ) error("DFS clustering cannot be differentiated if base multicolvar is DENSITY"); + } - // Ensure that derivatives are turned on in base classes - ActionWithInputMatrix::turnOnDerivatives(); + // Ensure that derivatives are turned on in base classes + ActionWithInputMatrix::turnOnDerivatives(); } -void ClusteringBase::calculate(){ - // All the clusters have zero size initially - for(unsigned i=0;i& myatoms ) const { - unsigned n=0; myatoms.resize( cluster_sizes[cluster_sizes.size() - clust].first ); - for(unsigned i=0;inodesAreConnected( iatom, jatom ); + return getAdjacencyVessel()->nodesAreConnected( iatom, jatom ); } double ClusteringBase::getCutoffForConnection() const { diff --git a/src/adjmat/ClusteringBase.h b/src/adjmat/ClusteringBase.h index 11c0bc14cc..741ac9046e 100644 --- a/src/adjmat/ClusteringBase.h +++ b/src/adjmat/ClusteringBase.h @@ -32,7 +32,7 @@ class ClusteringBase : public ActionWithInputMatrix { protected: /// Vector that stores the sizes of the current set of clusters std::vector< std::pair > cluster_sizes; -/// Used to identify the cluster we are working on +/// Used to identify the cluster we are working on int number_of_cluster; /// Vector that identifies the cluster each atom belongs to std::vector which_cluster; @@ -47,15 +47,15 @@ class ClusteringBase : public ActionWithInputMatrix { bool areConnected( const unsigned& iatom, const unsigned& jatom ) const ; /// Do the calculation void calculate(); -/// Do the clustering +/// Do the clustering virtual void performClustering()=0; /// Get the number of clusters that have been found unsigned getNumberOfClusters() const ; /// Get the atoms in one of the clusters virtual void retrieveAtomsInCluster( const unsigned& clust, std::vector& myatoms ) const ; /// Do nothing for apply here - void apply(){} -/// Get the cutoff + void apply() {} +/// Get the cutoff virtual double getCutoffForConnection() const ; }; diff --git a/src/adjmat/ContactAlignedMatrix.cpp b/src/adjmat/ContactAlignedMatrix.cpp index e1343f5a35..e1bdfcdba0 100644 --- a/src/adjmat/ContactAlignedMatrix.cpp +++ b/src/adjmat/ContactAlignedMatrix.cpp @@ -23,12 +23,12 @@ #include "core/ActionRegister.h" #include "tools/Matrix.h" -//+PLUMEDOC MATRIX ALIGNED_MATRIX +//+PLUMEDOC MATRIX ALIGNED_MATRIX /* Adjacency matrix in which two molecule are adjacent if they are within a certain cutoff and if they have the same orientation. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. These matrices can then be further analysed using a number of other algorithms as is detailed in \cite tribello-clustering. @@ -38,29 +38,29 @@ For this action the elements of the adjacency matrix are calculated using: a_{ij} = \sigma_1( |\mathbf{r}_{ij}| ) \sigma_2( \mathbf{v}_i . \mathbf{v}_j ) \f] -This form of adjacency matrix can only be used if the input species are objects that lie at a point in space and that have an orientation, \f$\mathbf{v}\f$. -These orientations might represent the -orientation of a molecule, which could be calculated using \ref MOLECULES or \ref PLANES, or it might be the complex vectors calculated using the +This form of adjacency matrix can only be used if the input species are objects that lie at a point in space and that have an orientation, \f$\mathbf{v}\f$. +These orientations might represent the +orientation of a molecule, which could be calculated using \ref MOLECULES or \ref PLANES, or it might be the complex vectors calculated using the Steinhardt parameters \ref Q3, \ref Q4 or \ref Q6. In the expression above \f$\mathbf{r}_{ij}\f$ is the vector connecting the points in space where objects \f$i\f$ and \f$j\f$ find themselves and \f$\sigma_1\f$ is a \ref switchingfunction that acts upon the magnitude of this vector. -\f$\sigma_2\f$ is a second \ref switchingfunction that acts on the dot product of the directors of the vectors that define the orientations of -objects \f$i\f$ and \f$j\f$. +\f$\sigma_2\f$ is a second \ref switchingfunction that acts on the dot product of the directors of the vectors that define the orientations of +objects \f$i\f$ and \f$j\f$. \par Examples The example input below is necessarily but gives you an idea of what can be achieved using this action. -The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the +The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the centeres of mass of the two atoms specified and the direction of the vector connecting the two atoms that were specified. -A \f$4 \times 4\f$ matrix is then computed using the formula above. The \f$ij\f$-element of this matrix tells us whether +A \f$4 \times 4\f$ matrix is then computed using the formula above. The \f$ij\f$-element of this matrix tells us whether or not atoms \f$i\f$ and \f$j\f$ are within 0.1 nm of each other and whether or not the dot-product of their orientation vectors -is greater than 0.5. The sum of the rows of this matrix are then computed. The sums of the \f$i\f$th row of this matrix tells us how -many of the molecules that are within the first coordination sphere of molecule \f$i\f$ have an orientation that is similar to that of -molecule \f$i\f$. We thus calculate the number of these "coordination numbers" that are greater than 1.0 and output this quantity to a file. +is greater than 0.5. The sum of the rows of this matrix are then computed. The sums of the \f$i\f$th row of this matrix tells us how +many of the molecules that are within the first coordination sphere of molecule \f$i\f$ have an orientation that is similar to that of +molecule \f$i\f$. We thus calculate the number of these "coordination numbers" that are greater than 1.0 and output this quantity to a file. \verbatim m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 mat: ALIGNED_MATRIX ATOMS=m1 SWITCH={RATIONAL R_0=0.1} ORIENTATION_SWITCH={RATIONAL R_0=0.1 D_MAX=0.5} -rr: ROWSUMS MATRIX=mat MORE_THAN={RATIONAL D_0=1.0 R_0=0.1} +rr: ROWSUMS MATRIX=mat MORE_THAN={RATIONAL D_0=1.0 R_0=0.1} PRINT ARG=rr.* FILE=colvar \endverbatim @@ -72,48 +72,48 @@ namespace adjmat { class ContactAlignedMatrix : public AlignedMatrixBase { private: - Matrix sf; + Matrix sf; public: - /// - static void registerKeywords( Keywords& keys ); - /// - explicit ContactAlignedMatrix(const ActionOptions&); - void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); - double computeVectorFunction( const unsigned& iv, const unsigned& jv, - const Vector& conn, const std::vector& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; + /// + static void registerKeywords( Keywords& keys ); + /// + explicit ContactAlignedMatrix(const ActionOptions&); + void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); + double computeVectorFunction( const unsigned& iv, const unsigned& jv, + const Vector& conn, const std::vector& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; }; PLUMED_REGISTER_ACTION(ContactAlignedMatrix,"ALIGNED_MATRIX") -void ContactAlignedMatrix::registerKeywords( Keywords& keys ){ - AlignedMatrixBase::registerKeywords( keys ); - keys.add("numbered","ORIENTATION_SWITCH","A switching function that transforms the dot product of the input vectors."); +void ContactAlignedMatrix::registerKeywords( Keywords& keys ) { + AlignedMatrixBase::registerKeywords( keys ); + keys.add("numbered","ORIENTATION_SWITCH","A switching function that transforms the dot product of the input vectors."); } ContactAlignedMatrix::ContactAlignedMatrix( const ActionOptions& ao ): -Action(ao), -AlignedMatrixBase(ao) + Action(ao), + AlignedMatrixBase(ao) { - unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); - sf.resize( nrows, ncols ); - parseConnectionDescriptions("ORIENTATION_SWITCH",false,0); + unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); + sf.resize( nrows, ncols ); + parseConnectionDescriptions("ORIENTATION_SWITCH",false,0); } -void ContactAlignedMatrix::readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ){ - plumed_assert( desc.size()==1 ); std::string errors; sf(j,i).set(desc[0],errors); - if( j!=i ) sf(i,j).set(desc[0],errors); - log.printf(" vectors in %u th and %u th groups must have a dot product that is greater than %s \n",i+1,j+1,(sf(i,j).description()).c_str() ); +void ContactAlignedMatrix::readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ) { + plumed_assert( desc.size()==1 ); std::string errors; sf(j,i).set(desc[0],errors); + if( j!=i ) sf(i,j).set(desc[0],errors); + log.printf(" vectors in %u th and %u th groups must have a dot product that is greater than %s \n",i+1,j+1,(sf(i,j).description()).c_str() ); } -double ContactAlignedMatrix::computeVectorFunction( const unsigned& iv, const unsigned& jv, - const Vector& conn, const std::vector& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { - double dot_df, dot=0; dconn.zero(); - for(unsigned k=2;k& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { + double dot_df, dot=0; dconn.zero(); + for(unsigned k=2; ksfmax ) sfmax=tsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + } } // And set the link cell cutoff setLinkCellCutoff( sfmax ); } -void ContactMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ +void ContactMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { plumed_assert( id==0 && desc.size()==1 ); std::string errors; switchingFunction(j,i).set(desc[0],errors); if( errors.length()!=0 ) error("problem reading switching function description " + errors); if( j!=i) switchingFunction(i,j).set(desc[0],errors); @@ -137,12 +137,12 @@ double ContactMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePac Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); - if( !doNotCalculateDerivatives() ){ - Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); - addAtomDerivatives( 1, 0, (-dfunc)*distance, myatoms ); - addAtomDerivatives( 1, 1, (+dfunc)*distance, myatoms ); - myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); + if( !doNotCalculateDerivatives() ) { + Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); + addAtomDerivatives( 1, 0, (-dfunc)*distance, myatoms ); + addAtomDerivatives( 1, 1, (+dfunc)*distance, myatoms ); + myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); } return sw; } diff --git a/src/adjmat/DFSClustering.cpp b/src/adjmat/DFSClustering.cpp index 596641849f..af0dc327e8 100644 --- a/src/adjmat/DFSClustering.cpp +++ b/src/adjmat/DFSClustering.cpp @@ -24,8 +24,8 @@ #include "core/ActionRegister.h" #ifdef __PLUMED_HAS_BOOST_GRAPH -#include -#include +#include +#include #include #endif @@ -33,8 +33,8 @@ /* Find the connected components of the matrix using the depth first search clustering algorithm. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. As detailed in \cite tribello-clustering these matrices provide a representation of a graph and can thus can be analysed using tools from graph theory. This particular action performs a depth first search clustering to find the connected components of this graph. You can read more about depth first search here: @@ -44,7 +44,7 @@ a depth first search clustering to find the connected components of this graph. This action is useful if you are looking at a phenomenon such as nucleation where the aim is to detect the sizes of the crystalline nuclei that have formed in your simulation cell. -\par Examples +\par Examples The input below calculates the coordination numbers of atoms 1-100 and then computes the an adjacency matrix whose elements measures whether atoms \f$i\f$ and \f$j\f$ are within 0.55 nm of each other. The action @@ -54,15 +54,15 @@ numbers for the atoms in this largest connected component are then computed and file. The way this input can be used is described in detail in \cite tribello-clustering. \verbatim -lq: COORDINATIONNUMBER SPECIES=1-100 SWITCH={CUBIC D_0=0.45 D_MAX=0.55} LOWMEM -cm: CONTACT_MATRIX ATOMS=lq SWITCH={CUBIC D_0=0.45 D_MAX=0.55} -dfs: DFSCLUSTERING MATRIX=cm -clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM +lq: COORDINATIONNUMBER SPECIES=1-100 SWITCH={CUBIC D_0=0.45 D_MAX=0.55} LOWMEM +cm: CONTACT_MATRIX ATOMS=lq SWITCH={CUBIC D_0=0.45 D_MAX=0.55} +dfs: DFSCLUSTERING MATRIX=cm +clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM PRINT ARG=clust1.* FILE=colvar \endverbatim */ -//+ENDPLUMEDOC +//+ENDPLUMEDOC namespace PLMD { namespace adjmat { @@ -93,67 +93,67 @@ class DFSClustering : public ClusteringBase { PLUMED_REGISTER_ACTION(DFSClustering,"DFSCLUSTERING") -void DFSClustering::registerKeywords( Keywords& keys ){ +void DFSClustering::registerKeywords( Keywords& keys ) { ClusteringBase::registerKeywords( keys ); keys.add("compulsory","MAXCONNECT","0","maximum number of connections that can be formed by any given node in the graph. " - "By default this is set equal to zero and the number of connections is set equal to the number " - "of nodes. You only really need to set this if you are working with a very large system and " - "memory is at a premium"); + "By default this is set equal to zero and the number of connections is set equal to the number " + "of nodes. You only really need to set this if you are working with a very large system and " + "memory is at a premium"); } DFSClustering::DFSClustering(const ActionOptions&ao): -Action(ao), -ClusteringBase(ao) + Action(ao), + ClusteringBase(ao) { - unsigned maxconnections; parse("MAXCONNECT",maxconnections); -#ifdef __PLUMED_HAS_BOOST_GRAPH - if( maxconnections>0 ) edge_list.resize( getNumberOfNodes()*maxconnections ); - else edge_list.resize(0.5*getNumberOfNodes()*(getNumberOfNodes()-1)); + unsigned maxconnections; parse("MAXCONNECT",maxconnections); +#ifdef __PLUMED_HAS_BOOST_GRAPH + if( maxconnections>0 ) edge_list.resize( getNumberOfNodes()*maxconnections ); + else edge_list.resize(0.5*getNumberOfNodes()*(getNumberOfNodes()-1)); #else - nneigh.resize( getNumberOfNodes() ); color.resize(getNumberOfNodes()); - if( maxconnections>0 ) adj_list.resize(getNumberOfNodes(),maxconnections); - else adj_list.resize(getNumberOfNodes(),getNumberOfNodes()); + nneigh.resize( getNumberOfNodes() ); color.resize(getNumberOfNodes()); + if( maxconnections>0 ) adj_list.resize(getNumberOfNodes(),maxconnections); + else adj_list.resize(getNumberOfNodes(),getNumberOfNodes()); #endif } -void DFSClustering::performClustering(){ +void DFSClustering::performClustering() { #ifdef __PLUMED_HAS_BOOST_GRAPH - // Get the list of edges - unsigned nedges=0; getAdjacencyVessel()->retrieveEdgeList( nedges, edge_list ); + // Get the list of edges + unsigned nedges=0; getAdjacencyVessel()->retrieveEdgeList( nedges, edge_list ); - // Build the graph using boost - boost::adjacency_list sg(&edge_list[0],&edge_list[nedges],getNumberOfNodes()); + // Build the graph using boost + boost::adjacency_list sg(&edge_list[0],&edge_list[nedges],getNumberOfNodes()); - // Find the connected components using boost (-1 here for compatibility with non-boost version) - number_of_cluster=boost::connected_components(sg,&which_cluster[0]) - 1; + // Find the connected components using boost (-1 here for compatibility with non-boost version) + number_of_cluster=boost::connected_components(sg,&which_cluster[0]) - 1; - // And work out the size of each cluster - for(unsigned i=0;iretrieveAdjacencyLists( nneigh, adj_list ); - - // Perform clustering - number_of_cluster=-1; color.assign(color.size(),0); - for(unsigned i=0;iretrieveAdjacencyLists( nneigh, adj_list ); + + // Perform clustering + number_of_cluster=-1; color.assign(color.size(),0); + for(unsigned i=0; i( mstring ); - if( !mm ) error("found no action in set with label " + mstring + " that calculates matrix"); - log.printf(" printing graph for matrix calculated by action %s\n", mm->getLabel().c_str() ); - - // Retrieve the adjacency matrix of interest - for(unsigned i=0;igetNumberOfVessels();++i){ - mymatrix = dynamic_cast( mm->getPntrToVessel(i) ); - if( mymatrix ) break ; - } - if( !mymatrix ) error( mm->getLabel() + " does not calculate an adjacency matrix"); - if( !mymatrix->isSymmetric() ) error("input contact matrix must be symmetric"); - if( maxconnections==0 ) maxconnections=mymatrix->getNumberOfRows(); - parse("FILE",filename); - log.printf(" printing graph to file named %s \n",filename.c_str() ); - checkRead(); + parse("MAXCONNECT",maxconnections); std::string mstring; parse("MATRIX",mstring); + AdjacencyMatrixBase* mm = plumed.getActionSet().selectWithLabel( mstring ); + if( !mm ) error("found no action in set with label " + mstring + " that calculates matrix"); + log.printf(" printing graph for matrix calculated by action %s\n", mm->getLabel().c_str() ); + + // Retrieve the adjacency matrix of interest + for(unsigned i=0; igetNumberOfVessels(); ++i) { + mymatrix = dynamic_cast( mm->getPntrToVessel(i) ); + if( mymatrix ) break ; + } + if( !mymatrix ) error( mm->getLabel() + " does not calculate an adjacency matrix"); + if( !mymatrix->isSymmetric() ) error("input contact matrix must be symmetric"); + if( maxconnections==0 ) maxconnections=mymatrix->getNumberOfRows(); + parse("FILE",filename); + log.printf(" printing graph to file named %s \n",filename.c_str() ); + checkRead(); } -void DumpGraph::update(){ - OFile ofile; ofile.link(*this); ofile.setBackupString("graph"); - ofile.open( filename ); ofile.printf("graph G { \n"); - // Print all nodes - for(unsigned i=0;igetNumberOfRows();++i) ofile.printf("%u [label=\"%u\"];\n",i,i); - // Now retrieve connectivitives - unsigned nedge; std::vector > edge_list( mymatrix->getNumberOfRows()*maxconnections ); - mymatrix->retrieveEdgeList( nedge, edge_list ); - for(unsigned i=0;igetNumberOfRows(); ++i) ofile.printf("%u [label=\"%u\"];\n",i,i); + // Now retrieve connectivitives + unsigned nedge; std::vector > edge_list( mymatrix->getNumberOfRows()*maxconnections ); + mymatrix->retrieveEdgeList( nedge, edge_list ); + for(unsigned i=0; isfmax ) sfmax=tsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + } } // Set the link cell cutoff setLinkCellCutoff( sfmax ); } -void HBondMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ +void HBondMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { plumed_assert( id<3 && desc.size()==1 ); - if( id==0 ){ - std::string errors; distanceOOSwitch(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) distanceOOSwitch(i,j).set(desc[0],errors); - log.printf(" atoms of type %u and %u must be within %s\n",i+1,j+1,(distanceOOSwitch(i,j).description()).c_str() ); - } else if( id==1 ){ - std::string errors; distanceOHSwitch(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) distanceOHSwitch(i,j).set(desc[0],errors); - log.printf(" for atoms of type %u and %u the OH distance must be less than %s \n",i+1,j+1,(distanceOHSwitch(i,j).description()).c_str() ); - } else if( id==2 ){ - std::string errors; angleSwitch(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) angleSwitch(i,j).set(desc[0],errors); - log.printf(" for atoms of type %u and %u the OOH angle must be less than %s \n",i+1,j+1,(angleSwitch(i,j).description()).c_str() ); - } + if( id==0 ) { + std::string errors; distanceOOSwitch(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) distanceOOSwitch(i,j).set(desc[0],errors); + log.printf(" atoms of type %u and %u must be within %s\n",i+1,j+1,(distanceOOSwitch(i,j).description()).c_str() ); + } else if( id==1 ) { + std::string errors; distanceOHSwitch(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) distanceOHSwitch(i,j).set(desc[0],errors); + log.printf(" for atoms of type %u and %u the OH distance must be less than %s \n",i+1,j+1,(distanceOHSwitch(i,j).description()).c_str() ); + } else if( id==2 ) { + std::string errors; angleSwitch(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) angleSwitch(i,j).set(desc[0],errors); + log.printf(" for atoms of type %u and %u the OOH angle must be less than %s \n",i+1,j+1,(angleSwitch(i,j).description()).c_str() ); + } } double HBondMatrix::calculateWeight( const unsigned& taskCode, const double& weight, multicolvar::AtomValuePack& myatoms ) const { // Ensure we skip diagonal elements of square matrix - if( myatoms.getIndex(0)==myatoms.getIndex(1) ) return 0.0; + if( myatoms.getIndex(0)==myatoms.getIndex(1) ) return 0.0; Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); if( distance.modulo2()3 ){ - for(unsigned i=2;i3 ) { + for(unsigned i=2; igetMatrixAction())->mybasemulticolvars.size()>0 ) error("matrix row sums should only be calculated when inputs are atoms"); // Setup the tasks - unsigned ncols = mymatrix->getNumberOfColumns(); + unsigned ncols = mymatrix->getNumberOfColumns(); ablocks.resize(1); ablocks[0].resize( ncols ); - for(unsigned i=0;iundirectedGraph() ){ - for(unsigned i=0;iundirectedGraph() ) { + for(unsigned i=0; igetNumberOfRows() + i; + for(unsigned i=0; igetNumberOfRows() + i; } std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); } double MatrixColumnSums::compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const { double sum=0.0; std::vector tvals( mymatrix->getNumberOfComponents() ); - unsigned nrows = mymatrix->getNumberOfRows(); - for(unsigned i=0;iundirectedGraph() && tinded==i ) continue; - sum+=retrieveConnectionValue( i, tinded, tvals ); + unsigned nrows = mymatrix->getNumberOfRows(); + for(unsigned i=0; iundirectedGraph() && tinded==i ) continue; + sum+=retrieveConnectionValue( i, tinded, tvals ); } - if( !doNotCalculateDerivatives() ){ - MultiValue myvals( mymatrix->getNumberOfComponents(), myatoms.getNumberOfDerivatives() ); - MultiValue& myvout=myatoms.getUnderlyingMultiValue(); - for(unsigned i=0;iisSymmetric() && tinded==i ) continue ; - addConnectionDerivatives( i, tinded, myvals, myvout ); - } + if( !doNotCalculateDerivatives() ) { + MultiValue myvals( mymatrix->getNumberOfComponents(), myatoms.getNumberOfDerivatives() ); + MultiValue& myvout=myatoms.getUnderlyingMultiValue(); + for(unsigned i=0; iisSymmetric() && tinded==i ) continue ; + addConnectionDerivatives( i, tinded, myvals, myvout ); + } } return sum; } diff --git a/src/adjmat/MatrixRowSums.cpp b/src/adjmat/MatrixRowSums.cpp index 1b7da9cf09..038aa89a71 100644 --- a/src/adjmat/MatrixRowSums.cpp +++ b/src/adjmat/MatrixRowSums.cpp @@ -27,36 +27,36 @@ #include "core/PlumedMain.h" #include "core/ActionSet.h" -//+PLUMEDOC MATRIXF ROWSUMS +//+PLUMEDOC MATRIXF ROWSUMS /* Sum the rows of a adjacency matrix. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether -or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. This action allows you to calculate +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. This action allows you to calculate the sum of the rows in this adjacency matrix and to then calculate further functions of these quantities. \par Examples The first instruction in the following input file tells PLUMED to compute a \f$10 \times 10\f$ matrix in which the \f$ij\f$-element tells you whether atoms \f$i\f$ and \f$j\f$ are within 1.0 nm of each other. The numbers in each of this rows are then added together -and the average value is computed. As such the following input provides an alternative method for calculating the coordination numbers -of atoms 1 to 10. +and the average value is computed. As such the following input provides an alternative method for calculating the coordination numbers +of atoms 1 to 10. \verbatim -mat: CONTACT_MATRIX ATOMS=1-10 SWITCH={RATIONAL R_0=1.0} -rsums: ROWSUMS MATRIX=mat MEAN -PRINT ARG=rsums.* FILE=colvar +mat: CONTACT_MATRIX ATOMS=1-10 SWITCH={RATIONAL R_0=1.0} +rsums: ROWSUMS MATRIX=mat MEAN +PRINT ARG=rsums.* FILE=colvar \endverbatim -The following input demonstrates another way that an average coordination number can be computed. This input calculates the number of atoms +The following input demonstrates another way that an average coordination number can be computed. This input calculates the number of atoms with indices between 6 and 15 that are within the first coordination spheres of each of the atoms within indices between 1 and 5. The average coordination number is then calculated from these five coordination numbers and this quantity is output to a file. \verbatim -mat2: CONTACT_MATRIX ATOMSA=1-5 ATOMSB=6-15 SWITCH={RATIONAL R_0=1.0} -rsums: ROWSUMS MATRIX=mat2 MEAN -PRINT ARG=rsums.* FILE=colvar +mat2: CONTACT_MATRIX ATOMSA=1-5 ATOMSB=6-15 SWITCH={RATIONAL R_0=1.0} +rsums: ROWSUMS MATRIX=mat2 MEAN +PRINT ARG=rsums.* FILE=colvar \endverbatim */ @@ -69,12 +69,12 @@ class MatrixRowSums : public ActionWithInputMatrix { public: static void registerKeywords( Keywords& keys ); explicit MatrixRowSums(const ActionOptions&); - double compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const ; + double compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const ; }; PLUMED_REGISTER_ACTION(MatrixRowSums,"ROWSUMS") -void MatrixRowSums::registerKeywords( Keywords& keys ){ +void MatrixRowSums::registerKeywords( Keywords& keys ) { ActionWithInputMatrix::registerKeywords( keys ); keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MEAN"); keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); @@ -82,24 +82,24 @@ void MatrixRowSums::registerKeywords( Keywords& keys ){ } MatrixRowSums::MatrixRowSums(const ActionOptions& ao): -Action(ao), -ActionWithInputMatrix(ao) + Action(ao), + ActionWithInputMatrix(ao) { if( (mymatrix->getMatrixAction())->mybasemulticolvars.size()>0 ) error("matrix row sums should only be calculated when inputs are atoms"); // Setup the tasks - unsigned nrows = mymatrix->getNumberOfRows(); + unsigned nrows = mymatrix->getNumberOfRows(); ablocks.resize(1); ablocks[0].resize( nrows ); - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); } double MatrixRowSums::compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const { - std::vector tvals( mymatrix->getNumberOfComponents() ); + std::vector tvals( mymatrix->getNumberOfComponents() ); getInputData( tinded, false, myatoms, tvals ); double fval=tvals[1]; - if( !doNotCalculateDerivatives() ){ - tvals.assign( tvals.size(), 0 ); tvals[1]=1.0; - mergeInputDerivatives( 1, 1, 2, tinded, tvals, getInputDerivatives( tinded, false, myatoms ), myatoms ); + if( !doNotCalculateDerivatives() ) { + tvals.assign( tvals.size(), 0 ); tvals[1]=1.0; + mergeInputDerivatives( 1, 1, 2, tinded, tvals, getInputDerivatives( tinded, false, myatoms ), myatoms ); } return fval; } diff --git a/src/adjmat/OutputCluster.cpp b/src/adjmat/OutputCluster.cpp index d4bba925ba..c2b752f0d0 100644 --- a/src/adjmat/OutputCluster.cpp +++ b/src/adjmat/OutputCluster.cpp @@ -36,16 +36,16 @@ The output in question here is either - a file that contains a list of the atom indices that form part of one of the clusters that was identified using \ref DFSCLUSTERING - an xyz file containing the positions of the atoms in one of the the clusters that was identified using \ref DFSCLUSTERING -Notice also that if you choose to output an xyz file you can ask PLUMED to try to reconstruct the cluster +Notice also that if you choose to output an xyz file you can ask PLUMED to try to reconstruct the cluster taking the periodic boundary conditions into account by using the MAKE_WHOLE flag. \par Examples -The input shown below identifies those atoms with a coordination number less than 13 +The input shown below identifies those atoms with a coordination number less than 13 and then constructs a contact matrix that describes the connectivity between the atoms -that satisfy this criteria. The DFS algorithm is then used to find the connected components +that satisfy this criteria. The DFS algorithm is then used to find the connected components in this matrix and the indices of the atoms in the largest connected component are then output -to a file. +to a file. \verbatim c1: COORDINATIONNUMBER SPECIES=1-1996 SWITCH={CUBIC D_0=0.34 D_MAX=0.38} @@ -81,14 +81,14 @@ class OutputCluster : public ActionPilot { public: static void registerKeywords( Keywords& keys ); explicit OutputCluster(const ActionOptions&); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void update(); }; PLUMED_REGISTER_ACTION(OutputCluster,"OUTPUT_CLUSTER") -void OutputCluster::registerKeywords( Keywords& keys ){ +void OutputCluster::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); keys.add("compulsory","CLUSTERS","the action that performed the clustering"); @@ -101,125 +101,125 @@ void OutputCluster::registerKeywords( Keywords& keys ){ } OutputCluster::OutputCluster(const ActionOptions& ao): -Action(ao), -ActionPilot(ao), -myclusters(NULL) + Action(ao), + ActionPilot(ao), + myclusters(NULL) { // Setup output file ofile.link(*this); std::string file; parse("FILE",file); if( file.length()==0 ) error("output file name was not specified"); // Search for xyz extension output_xyz=false; - if( file.find(".")!=std::string::npos ){ - std::size_t dot=file.find_first_of('.'); - if( file.substr(dot+1)=="xyz" ) output_xyz=true; + if( file.find(".")!=std::string::npos ) { + std::size_t dot=file.find_first_of('.'); + if( file.substr(dot+1)=="xyz" ) output_xyz=true; } - ofile.open(file); log.printf(" on file %s \n",file.c_str()); + ofile.open(file); log.printf(" on file %s \n",file.c_str()); parseFlag("MAKE_WHOLE",makewhole); parse("MAXDEPTH",maxdepth); parse("MAXGOES",maxgoes); if( makewhole && !output_xyz) error("MAKE_WHOLE flag is not compatible with output of non-xyz files"); // Find what action we are taking the clusters from std::vector matname(1); parse("CLUSTERS",matname[0]); myclusters = plumed.getActionSet().selectWithLabel( matname[0] ); - if( !myclusters ) error( matname[0] + " does not calculate perform a clustering of the atomic positions"); + if( !myclusters ) error( matname[0] + " does not calculate perform a clustering of the atomic positions"); // N.B. the +0.3 is a fudge factor. Reconstrucing PBC doesnt work without this GAT addDependency( myclusters ); double rcut=myclusters->getCutoffForConnection() + 0.3; rcut2=rcut*rcut; // Read in the cluster we are calculating - parse("CLUSTER",clustr); + parse("CLUSTER",clustr); if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); if( clustr>myclusters->getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); log.printf(" outputting atoms in %u th largest cluster found by %s \n",clustr,matname[0].c_str() ); } -void OutputCluster::update(){ +void OutputCluster::update() { myclusters->retrieveAtomsInCluster( clustr, myatoms ); - if( output_xyz ){ - ofile.printf("%u \n",static_cast(myatoms.size())); - ofile.printf("atoms in %u th largest cluster \n",clustr ); - if( makewhole ){ - // Retrieve the atom positions - atomsin.resize( myatoms.size() ); - for(unsigned i=0;igetPositionOfAtomForLinkCells( myatoms[i] ); - // Build a connectivity matrix neglecting the pbc - nneigh.resize( myatoms.size(), 0 ); adj_list.resize( myatoms.size(), myatoms.size() ); - for(unsigned i=1;i(myatoms.size())); + ofile.printf("atoms in %u th largest cluster \n",clustr ); + if( makewhole ) { + // Retrieve the atom positions + atomsin.resize( myatoms.size() ); + for(unsigned i=0; igetPositionOfAtomForLinkCells( myatoms[i] ); + // Build a connectivity matrix neglecting the pbc + nneigh.resize( myatoms.size(), 0 ); adj_list.resize( myatoms.size(), myatoms.size() ); + for(unsigned i=1; iareConnected( myatoms[i], myatoms[j] ) ) { adj_list(i,nneigh[i])=j; adj_list(j,nneigh[j])=i; nneigh[i]++; nneigh[j]++; } } - std::sort( cluster_sizes.begin(), cluster_sizes.end() ); + } - // Now set visited so that only those atoms in largest cluster will be start points for PBCing - visited.assign( visited.size(), false ); - for(unsigned i=0;iareConnected( myatoms[i], myatoms[j] ) ){ adj_list(i,nneigh[i])=j; adj_list(j,nneigh[j])=i; nneigh[i]++; nneigh[j]++; } - } - } + // Now find broken bonds and run iterative deepening depth first search to reconstruct + for(unsigned jj=0; jjrcut2 ){ - visited[j]=true; - for(unsigned depth=0;depth<=maxdepth;++depth) explore( j, depth ); - } - } + for(unsigned k=0; krcut2 ) { + visited[j]=true; + for(unsigned depth=0; depth<=maxdepth; ++depth) explore( j, depth ); } + } } - // And print final positions - for(unsigned i=0;igetPositionOfAtomForLinkCells( myatoms[i] ); - ofile.printf( "X %f %f %f \n", pos[0], pos[1], pos[2] ); - } - } + } + // And print final positions + for(unsigned i=0; igetPositionOfAtomForLinkCells( myatoms[i] ); + ofile.printf( "X %f %f %f \n", pos[0], pos[1], pos[2] ); + } + } } else { - ofile.printf("CLUSTERING RESULTS AT TIME %f : NUMBER OF ATOMS IN %u TH LARGEST CLUSTER EQUALS %u \n",getTime(),clustr,static_cast(myatoms.size()) ); - ofile.printf("INDICES OF ATOMS : "); - for(unsigned i=0;igetAbsoluteIndexOfCentralAtom(myatoms[i])).index()); - ofile.printf("\n"); + ofile.printf("CLUSTERING RESULTS AT TIME %f : NUMBER OF ATOMS IN %u TH LARGEST CLUSTER EQUALS %u \n",getTime(),clustr,static_cast(myatoms.size()) ); + ofile.printf("INDICES OF ATOMS : "); + for(unsigned i=0; igetAbsoluteIndexOfCentralAtom(myatoms[i])).index()); + ofile.printf("\n"); } } -void OutputCluster::explore( const unsigned& index, const unsigned& depth ){ +void OutputCluster::explore( const unsigned& index, const unsigned& depth ) { if( depth==0 ) return ; - for(unsigned i=0;ipbcDistance( atomsin[index], atomsin[j] ); - atomsin[j] = atomsin[index] + svec; - explore( j, depth-1 ); - } + for(unsigned i=0; ipbcDistance( atomsin[index], atomsin[j] ); + atomsin[j] = atomsin[index] + svec; + explore( j, depth-1 ); + } } -bool OutputCluster::explore_dfs( const unsigned& index ){ +bool OutputCluster::explore_dfs( const unsigned& index ) { visited[index]=true; - for(unsigned i=0;i > kernels; + Matrix > kernels; public: - /// - static void registerKeywords( Keywords& keys ); - /// - explicit SMACMatrix(const ActionOptions&); - void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); - double computeVectorFunction( const unsigned& iv, const unsigned& jv, - const Vector& conn, const std::vector& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; + /// + static void registerKeywords( Keywords& keys ); + /// + explicit SMACMatrix(const ActionOptions&); + void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); + double computeVectorFunction( const unsigned& iv, const unsigned& jv, + const Vector& conn, const std::vector& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; }; PLUMED_REGISTER_ACTION(SMACMatrix,"SMAC_MATRIX") -void SMACMatrix::registerKeywords( Keywords& keys ){ - AlignedMatrixBase::registerKeywords( keys ); - keys.add("numbered","KERNEL","The various kernels that are used to determine whether or not the molecules are aligned"); +void SMACMatrix::registerKeywords( Keywords& keys ) { + AlignedMatrixBase::registerKeywords( keys ); + keys.add("numbered","KERNEL","The various kernels that are used to determine whether or not the molecules are aligned"); } SMACMatrix::SMACMatrix( const ActionOptions& ao ): -Action(ao), -AlignedMatrixBase(ao) + Action(ao), + AlignedMatrixBase(ao) { - unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); - kernels.resize( nrows, ncols ); parseConnectionDescriptions("KERNEL",true,0); + unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); + kernels.resize( nrows, ncols ); parseConnectionDescriptions("KERNEL",true,0); } -void SMACMatrix::readOrientationConnector( const unsigned& iv, const unsigned& jv, const std::vector& desc ){ - for(int i=0;i& desc ) { + for(int i=0; i& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { + const Vector& conn, const std::vector& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { unsigned nvectors = ( vec1.size() - 2 ) / 3; plumed_assert( (vec1.size()-2)%3==0 ); std::vector dv1(nvectors), dv2(nvectors), tdconn(nvectors); Torsion t; std::vector v1(nvectors), v2(nvectors); - std::vector pos; for(unsigned i=0;isetDomain( "-pi", "pi" ); } - - for(unsigned j=0;jset( angle ); + std::vector pos; for(unsigned i=0; isetDomain( "-pi", "pi" ); } + + for(unsigned j=0; jset( angle ); } - - double ans=0; std::vector deriv( nvectors ), df( nvectors, 0 ); - for(unsigned i=0;i deriv( nvectors ), df( nvectors, 0 ); + for(unsigned i=0; ilabel.coord-1, " - "the second smallest will be labelleled label.coord-1 and so on"); + "the smallest sprint coordinate will be labelled label.coord-1, " + "the second smallest will be labelleled label.coord-1 and so on"); } Sprint::Sprint(const ActionOptions&ao): -Action(ao), -ActionWithInputMatrix(ao), -eigvals( getNumberOfNodes() ), -maxeig( getNumberOfNodes() ), -thematrix( getNumberOfNodes(), getNumberOfNodes() ), -eigenvecs( getNumberOfNodes(), getNumberOfNodes() ) + Action(ao), + ActionWithInputMatrix(ao), + eigvals( getNumberOfNodes() ), + maxeig( getNumberOfNodes() ), + thematrix( getNumberOfNodes(), getNumberOfNodes() ), + eigenvecs( getNumberOfNodes(), getNumberOfNodes() ) { - // Check on setup - // if( getNumberOfVessels()!=1 ) error("there should be no vessel keywords"); - // Check for bad colvar input ( we are going to get rid of this because we are going to have input adjacency matrix in future ) - // for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); - // } - - if( !getAdjacencyVessel()->isSymmetric() ) error("input contact matrix is not symmetric"); - std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); - - // Create all the values - sqrtn = sqrt( static_cast( getNumberOfNodes() ) ); - for(unsigned i=0;iresizeDerivatives( getNumberOfDerivatives() ); - } - - // Setup the dynamic list to hold all the tasks - unsigned ntriangle = 0.5*getNumberOfNodes()*(getNumberOfNodes()-1); - for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); + // } + + if( !getAdjacencyVessel()->isSymmetric() ) error("input contact matrix is not symmetric"); + std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); + + // Create all the values + sqrtn = sqrt( static_cast( getNumberOfNodes() ) ); + for(unsigned i=0; iresizeDerivatives( getNumberOfDerivatives() ); + } + + // Setup the dynamic list to hold all the tasks + unsigned ntriangle = 0.5*getNumberOfNodes()*(getNumberOfNodes()-1); + for(unsigned i=0; iretrieveMatrix( active_elements, thematrix ); - // Diagonalize it - diagMat( thematrix, eigvals, eigenvecs ); - // Get the maximum eigevalue - double lambda = eigvals[ getNumberOfNodes()-1 ]; - // Get the corresponding eigenvector - for(unsigned j=0;jset( sqrtn*lambda*maxeig[icomp].first ); - } - - // Parallelism - unsigned rank, stride; - if( serialCalculation() ){ stride=1; rank=0; } - else { rank=comm.Get_rank(); stride=comm.Get_size(); } - - // Derivatives - MultiValue myvals( 2, getNumberOfDerivatives() ); - Matrix mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); - // std::vector catoms(2); - unsigned nval = getNumberOfNodes(); mymat_ders=0; - for(unsigned i=rank;igetMatrixIndices( active_elements[i], j, k ); - double tmp1 = 2 * eigenvecs(nval-1,j)*eigenvecs(nval-1,k); - for(unsigned icomp=0;icompretrieveDerivatives( active_elements[i], false, myvals ); - for(unsigned jd=0;jdretrieveMatrix( active_elements, thematrix ); + // Diagonalize it + diagMat( thematrix, eigvals, eigenvecs ); + // Get the maximum eigevalue + double lambda = eigvals[ getNumberOfNodes()-1 ]; + // Get the corresponding eigenvector + for(unsigned j=0; jset( sqrtn*lambda*maxeig[icomp].first ); + } + + // Parallelism + unsigned rank, stride; + if( serialCalculation() ) { stride=1; rank=0; } + else { rank=comm.Get_rank(); stride=comm.Get_size(); } + + // Derivatives + MultiValue myvals( 2, getNumberOfDerivatives() ); + Matrix mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); + // std::vector catoms(2); + unsigned nval = getNumberOfNodes(); mymat_ders=0; + for(unsigned i=rank; igetMatrixIndices( active_elements[i], j, k ); + double tmp1 = 2 * eigenvecs(nval-1,j)*eigenvecs(nval-1,k); + for(unsigned icomp=0; icompretrieveDerivatives( active_elements[i], false, myvals ); + for(unsigned jd=0; jdaddDerivative( i, mymat_ders(j,i) ); - } + for(unsigned j=0; jaddDerivative( i, mymat_ders(j,i) ); + } } -void Sprint::apply(){ +void Sprint::apply() { std::vector& f(modifyForces()); Tensor& v(modifyVirial()); unsigned nat=getNumberOfAtoms(); std::vector forces( 3*getNumberOfAtoms() + 9 ); - for(unsigned i=0;iapplyForce( forces ) ){ - for(unsigned j=0;japplyForce( forces ) ) { + for(unsigned j=0; j0 ) error("errors in DENSITY_THRESHOLD switching function : " + errors ); + if( errors.length()>0 ) error("errors in DENSITY_THRESHOLD switching function : " + errors ); log.printf(" threshold on density of atoms in cylinder equals %s\n",threshold_switch.description().c_str() ); - for(unsigned i=0;isfmax ) sfmax=tsf; - double rsf=cylinder_sw(i,j).get_dmax(); - if( rsf>rfmax ) rfmax=rsf; - double lsf=low_sf(i,j).get_dmax(); - if( lsf>lsfmax ) lsfmax=lsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + double rsf=cylinder_sw(i,j).get_dmax(); + if( rsf>rfmax ) rfmax=rsf; + double lsf=low_sf(i,j).get_dmax(); + if( lsf>lsfmax ) lsfmax=lsf; + } } // Get the width of the bead - HistogramBead bead; bead.isNotPeriodic(); + HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype ); bead.set( 0.0, 1.0, sigma ); - beadrad = bead.getCutoff(); + beadrad = bead.getCutoff(); // Set the link cell cutoff log.printf(" setting cutoff %f \n", sfmax ); - setLinkCellCutoff( sfmax, std::numeric_limits::max() ); + setLinkCellCutoff( sfmax, std::numeric_limits::max() ); double maxsize=0; - for(unsigned i=0;imaxsize ) maxsize=binw_mat(i,j); - } + for(unsigned i=0; imaxsize ) maxsize=binw_mat(i,j); + } } // Set the maximum number of bins that we will need to compute - maxbins = std::floor( sfmax / maxsize ) + 1; + maxbins = std::floor( sfmax / maxsize ) + 1; // Need to resize functions again here to ensure that vector sizes // are set correctly in AdjacencyMatrixVessel resizeFunctions(); @@ -164,27 +164,27 @@ unsigned TopologyMatrix::getNumberOfQuantities() const { return maxbins+3; } -void TopologyMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ +void TopologyMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { plumed_assert( id<4 ); - if( id==0 ){ - std::string errors; switchingFunction(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) switchingFunction(i,j).set(desc[0],errors); - log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); - } else if( id==1 ){ - std::string errors; cylinder_sw(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) cylinder_sw(i,j).set(desc[0],errors); - log.printf(" there must be not atoms within the cylinder connections atoms of multicolvar groups %u th and %u th. This cylinder has radius %s \n",i+1,j+1,(cylinder_sw(i,j).description()).c_str() ); - } else if( id==2 ){ - std::string errors; low_sf(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i ) low_sf(i,j).set(desc[0],errors); - log.printf(" %u th and %u th multicolvar groups must be further apart than %s\n",i+1,j+1,(low_sf(j,i).description()).c_str() ); - } else if( id==3 ){ - Tools::convert( desc[0], binw_mat(j,i) ); - if( i!=j ) binw_mat(i,j)=binw_mat(j,i); - log.printf(" cylinder for %u th and %u th multicolvar groups is split into bins of length %f \n",i,j,binw_mat(i,j) ); + if( id==0 ) { + std::string errors; switchingFunction(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) switchingFunction(i,j).set(desc[0],errors); + log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); + } else if( id==1 ) { + std::string errors; cylinder_sw(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) cylinder_sw(i,j).set(desc[0],errors); + log.printf(" there must be not atoms within the cylinder connections atoms of multicolvar groups %u th and %u th. This cylinder has radius %s \n",i+1,j+1,(cylinder_sw(i,j).description()).c_str() ); + } else if( id==2 ) { + std::string errors; low_sf(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i ) low_sf(i,j).set(desc[0],errors); + log.printf(" %u th and %u th multicolvar groups must be further apart than %s\n",i+1,j+1,(low_sf(j,i).description()).c_str() ); + } else if( id==3 ) { + Tools::convert( desc[0], binw_mat(j,i) ); + if( i!=j ) binw_mat(i,j)=binw_mat(j,i); + log.printf(" cylinder for %u th and %u th multicolvar groups is split into bins of length %f \n",i,j,binw_mat(i,j) ); } } @@ -198,15 +198,15 @@ double TopologyMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePa HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype ); // Initialise to zero density on all bins - for(unsigned bin=0;bin binvals( 1+maxbins ); for(unsigned i=1;imax ){ max=myatoms.getValue(i); vout=i; } + for(unsigned i=3; imax ) { max=myatoms.getValue(i); vout=i; } } // Calculate value and derivative of switching function between atoms 1 and 2 double dfuncl, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( d1_len, dfuncl ); // Transform the density double df, tsw = threshold_switch.calculate( max, df ); - if( !doNotCalculateDerivatives() ){ - // Factor of d1_len is required here because d1 is normalized - d1 *= d1_len; - addAtomDerivatives( 2+maxbins, 0, -dfuncl*d1, myatoms ); - addAtomDerivatives( 2+maxbins, 1, dfuncl*d1, myatoms ); - myatoms.addBoxDerivatives( 2+maxbins, (-dfuncl)*Tensor(d1,d1) ); - // Update active atoms so that next bit works - updateActiveAtoms( myatoms ); - // Now finish caclulation of derivatives - MultiValue& myvals=myatoms.getUnderlyingMultiValue(); - for(unsigned jd=0;jd(lcylinder+bead.getCutoff()) ) return; - // Calculate the excess swiching function + // Calculate the excess swiching function double edf, eval = low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( excess, edf ); // Calculate the projection on the perpendicular distance from the center of the tube double cm = d2.modulo2() - proj*proj; // Now calculate the density in the cylinder - if( cmbinw*(bin+1)+bead.getCutoff() ) continue; - double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; der /= cellv; - myatoms.addValue( 2+bin, contr*val*eval ); - - if( !doNotCalculateDerivatives() ){ - g1derivf=contr*eval*dc1 + val*eval*der*dd1 + contr*val*de1; - addAtomDerivatives( 2+bin, 0, g1derivf, myatoms ); - g2derivf=contr*eval*dc2 + val*eval*der*dd2 + contr*val*de2; - addAtomDerivatives( 2+bin, 1, g2derivf, myatoms ); - lderivf=contr*eval*dc3 + val*eval*der*dd3 + contr*val*de3; - addAtomDerivatives( 2+bin, iat, lderivf, myatoms ); - // Virial - vir = -Tensor( myatoms.getPosition(0), g1derivf ) - Tensor( pos1, g2derivf ) - Tensor( pos2, lderivf ); - myatoms.addBoxDerivatives( 2+bin, vir ); - } + if( cmbinw*(bin+1)+bead.getCutoff() ) continue; + double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; der /= cellv; + myatoms.addValue( 2+bin, contr*val*eval ); + + if( !doNotCalculateDerivatives() ) { + g1derivf=contr*eval*dc1 + val*eval*der*dd1 + contr*val*de1; + addAtomDerivatives( 2+bin, 0, g1derivf, myatoms ); + g2derivf=contr*eval*dc2 + val*eval*der*dd2 + contr*val*de2; + addAtomDerivatives( 2+bin, 1, g2derivf, myatoms ); + lderivf=contr*eval*dc3 + val*eval*der*dd3 + contr*val*de3; + addAtomDerivatives( 2+bin, iat, lderivf, myatoms ); + // Virial + vir = -Tensor( myatoms.getPosition(0), g1derivf ) - Tensor( pos1, g2derivf ) - Tensor( pos2, lderivf ); + myatoms.addBoxDerivatives( 2+bin, vir ); } + } } } diff --git a/src/analysis/Analysis.cpp b/src/analysis/Analysis.cpp index 4d76df935a..989981ab6b 100644 --- a/src/analysis/Analysis.cpp +++ b/src/analysis/Analysis.cpp @@ -34,7 +34,7 @@ namespace PLMD { namespace analysis { -void Analysis::registerKeywords( Keywords& keys ){ +void Analysis::registerKeywords( Keywords& keys ) { vesselbase::ActionWithAveraging::registerKeywords( keys ); keys.use("ARG"); keys.reset_style("ARG","optional"); keys.add("atoms","ATOMS","the atoms whose positions we are tracking for the purpose of analysing the data"); @@ -44,36 +44,36 @@ void Analysis::registerKeywords( Keywords& keys ){ keys.addFlag("WRITE_CHECKPOINT",false,"write out a checkpoint so that the analysis can be restarted in a later run"); keys.add("hidden","REUSE_DATA_FROM","eventually this will allow you to analyse the same set of data multiple times"); keys.add("hidden","IGNORE_REWEIGHTING","this allows you to ignore any reweighting factors"); - keys.use("RESTART"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); keys.remove("TOL"); + keys.use("RESTART"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); keys.remove("TOL"); } Analysis::Analysis(const ActionOptions&ao): -Action(ao), -ActionWithAveraging(ao), -nomemory(true), -write_chq(false), -reusing_data(false), -ignore_reweight(false), -idata(0), + Action(ao), + ActionWithAveraging(ao), + nomemory(true), + write_chq(false), + reusing_data(false), + ignore_reweight(false), + idata(0), //firstAnalysisDone(false), //old_norm(0.0), -ofmt("%f"), -current_args(getNumberOfArguments()), -argument_names(getNumberOfArguments()) + ofmt("%f"), + current_args(getNumberOfArguments()), + argument_names(getNumberOfArguments()) { parse("FMT",ofmt); // Read the format for output files // Make a vector containing all the argument names - for(unsigned i=0;igetName(); + for(unsigned i=0; igetName(); // Read in the metric style parse("METRIC",metricname); std::vector atom_numbers; ReferenceConfiguration* checkref=metricRegister().create( metricname ); // Check if we should read atoms ReferenceAtoms* hasatoms=dynamic_cast( checkref ); - if( hasatoms ){ - parseAtomList("ATOMS",atom_numbers); requestAtoms(atom_numbers); - log.printf(" monitoring positions of atoms "); - for(unsigned i=0;i( checkref ); @@ -83,174 +83,174 @@ argument_names(getNumberOfArguments()) delete checkref; std::string prev_analysis; parse("REUSE_DATA_FROM",prev_analysis); - if( prev_analysis.length()>0 ){ - reusing_data=true; - mydatastash=plumed.getActionSet().selectWithLabel( prev_analysis ); - if( !mydatastash ) error("could not find analysis action named " + prev_analysis ); - parseFlag("IGNORE_REWEIGHTING",ignore_reweight); - if( ignore_reweight ) log.printf(" reusing data stored by %s but ignoring all reweighting\n",prev_analysis.c_str() ); - else log.printf(" reusing data stored by %s\n",prev_analysis.c_str() ); - } else { - parse("RUN",freq); - if( freq==0 ){ - log.printf(" analyzing all data in trajectory\n"); - } else { - if( freq%getStride()!=0 ) error("frequncy of running is not a multiple of the stride"); - log.printf(" running analysis every %u steps\n",freq); - ndata=freq/getStride(); data.resize( ndata ); logweights.resize( ndata ); - for(unsigned i=0;i( metricname ); - data[i]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); - } - } - parseFlag("WRITE_CHECKPOINT",write_chq); - if( write_chq ){ - write_chq=false; - warning("ignoring WRITE_CHECKPOINT flag because we are analyzing all data"); - } - - // We need no restart file if we are just collecting data and analyzing all of it - std::string filename = getName() + "_" + getLabel() + ".chkpnt"; - if( write_chq ) rfile.link(*this); - if( getRestart() ){ - if( !write_chq ) warning("restarting without writing a checkpoint file is somewhat strange"); - // Read in data from input file - readDataFromFile( filename ); - // Setup the restart file (append mode) - if( write_chq ) rfile.open( filename.c_str() ); // In append mode automatically because of restart - // Run the analysis if we stoped in the middle of it last time - log.printf(" restarting analysis with %u points read from restart file\n",idata); - } else if( write_chq ){ - // Setup the restart file (delete any old one) - rfile.open( filename.c_str() ); // In overwrite mode automatically because there is no restart - } - if( write_chq ){ - //rfile.addConstantField("old_normalization"); - for(unsigned i=0;i0 ) { + reusing_data=true; + mydatastash=plumed.getActionSet().selectWithLabel( prev_analysis ); + if( !mydatastash ) error("could not find analysis action named " + prev_analysis ); + parseFlag("IGNORE_REWEIGHTING",ignore_reweight); + if( ignore_reweight ) log.printf(" reusing data stored by %s but ignoring all reweighting\n",prev_analysis.c_str() ); + else log.printf(" reusing data stored by %s\n",prev_analysis.c_str() ); + } else { + parse("RUN",freq); + if( freq==0 ) { + log.printf(" analyzing all data in trajectory\n"); + } else { + if( freq%getStride()!=0 ) error("frequncy of running is not a multiple of the stride"); + log.printf(" running analysis every %u steps\n",freq); + ndata=freq/getStride(); data.resize( ndata ); logweights.resize( ndata ); + for(unsigned i=0; i( metricname ); + data[i]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); } + } + parseFlag("WRITE_CHECKPOINT",write_chq); + if( write_chq ) { + write_chq=false; + warning("ignoring WRITE_CHECKPOINT flag because we are analyzing all data"); + } + + // We need no restart file if we are just collecting data and analyzing all of it + std::string filename = getName() + "_" + getLabel() + ".chkpnt"; + if( write_chq ) rfile.link(*this); + if( getRestart() ) { + if( !write_chq ) warning("restarting without writing a checkpoint file is somewhat strange"); + // Read in data from input file + readDataFromFile( filename ); + // Setup the restart file (append mode) + if( write_chq ) rfile.open( filename.c_str() ); // In append mode automatically because of restart + // Run the analysis if we stoped in the middle of it last time + log.printf(" restarting analysis with %u points read from restart file\n",idata); + } else if( write_chq ) { + // Setup the restart file (delete any old one) + rfile.open( filename.c_str() ); // In overwrite mode automatically because there is no restart + } + if( write_chq ) { + //rfile.addConstantField("old_normalization"); + for(unsigned i=0; iset( mypdb ); - data[idata]->parse("TIME",tstep); - if( !first && ((tstep-oldtstep) - getStride()*plumed.getAtoms().getTimeStep())>plumed.getAtoms().getTimeStep() ){ - error("frequency of data storage in " + filename + " is not equal to frequency of data storage plumed.dat file"); - } - data[idata]->parse("LOG_WEIGHT",logweights[idata]); - //data[idata]->parse("OLD_NORM",old_norm); - data[idata]->checkRead(); - idata++; first=false; oldtstep=tstep; - } else{ - break; - } - } + if(fp!=NULL) { + double tstep, oldtstep; + bool do_read=true, first=true; + while (do_read) { + PDB mypdb; + do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); + if(do_read) { + data[idata]->set( mypdb ); + data[idata]->parse("TIME",tstep); + if( !first && ((tstep-oldtstep) - getStride()*plumed.getAtoms().getTimeStep())>plumed.getAtoms().getTimeStep() ) { + error("frequency of data storage in " + filename + " is not equal to frequency of data storage plumed.dat file"); + } + data[idata]->parse("LOG_WEIGHT",logweights[idata]); + //data[idata]->parse("OLD_NORM",old_norm); + data[idata]->checkRead(); + idata++; first=false; oldtstep=tstep; + } else { + break; + } + } fclose(fp); } // if(old_norm>0) firstAnalysisDone=true; } -void Analysis::parseOutputFile( const std::string& key, std::string& filename ){ +void Analysis::parseOutputFile( const std::string& key, std::string& filename ) { parse(key,filename); if(filename=="dont output") return; - if( !getRestart() ){ - OFile ofile; ofile.link(*this); - ofile.setBackupString("analysis"); - ofile.backupAllFiles(filename); - } + if( !getRestart() ) { + OFile ofile; ofile.link(*this); + ofile.setBackupString("analysis"); + ofile.backupAllFiles(filename); + } } -void Analysis::accumulate(){ +void Analysis::accumulate() { // Don't store the first step (also don't store if we are getting data from elsewhere) if( getStep()==0 || reusing_data ) return; // This is used when we have a full quota of data from the first run - if( freq>0 && idata==logweights.size() ) return; + if( freq>0 && idata==logweights.size() ) return; // Get the arguments ready to transfer to reference configuration - for(unsigned i=0;i0){ - // Get the arguments and store them in a vector of vectors - data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); - logweights[idata] = lweight; + if( freq>0) { + // Get the arguments and store them in a vector of vectors + data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); + logweights[idata] = lweight; } else { - data.push_back( metricRegister().create( metricname ) ); - plumed_dbg_assert( data.size()==idata+1 ); - data[idata]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); - data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); - logweights.push_back(lweight); - } + data.push_back( metricRegister().create( metricname ) ); + plumed_dbg_assert( data.size()==idata+1 ); + data[idata]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); + data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); + logweights.push_back(lweight); + } // Write data to checkpoint file - if( write_chq ){ - rfile.rewind(); - data[idata]->print( rfile, getTime(), logweights[idata], atoms.getUnits().getLength()/0.1, 1.0 ); //old_norm ); - rfile.flush(); + if( write_chq ) { + rfile.rewind(); + data[idata]->print( rfile, getTime(), logweights[idata], atoms.getUnits().getLength()/0.1, 1.0 ); //old_norm ); + rfile.flush(); } // Increment data counter idata++; } -Analysis::~Analysis(){ - for(unsigned i=0;i Analysis::getMetric() const { // Add more exotic metrics in here -- FlexibleHill for instance std::vector empty; - if( metricname=="EUCLIDEAN" ){ - empty.resize( getNumberOfArguments(), 1.0 ); + if( metricname=="EUCLIDEAN" ) { + empty.resize( getNumberOfArguments(), 1.0 ); } return empty; } double Analysis::getWeight( const unsigned& idata ) const { - if( !reusing_data ){ - plumed_dbg_assert( idatagetWeight(); + if( !reusing_data ) { + plumed_dbg_assert( idatagetWeight(); } else { - return mydatastash->getWeight(idata); + return mydatastash->getWeight(idata); } } -void Analysis::finalizeWeights( const bool& ignore_weights ){ +void Analysis::finalizeWeights( const bool& ignore_weights ) { // Check that we have the correct ammount of data if( !reusing_data && idata!=logweights.size() ) error("something has gone wrong. Am trying to run analysis but I don't have sufficient data"); double norm=0; // Reset normalization constant - if( ignore_weights ){ - for(unsigned i=0;isetWeight(1.0); norm+=1.0; - } - } else if( nomemory ){ - // Find the maximum weight - double maxweight=logweights[0]; - for(unsigned i=1;imaxweight) maxweight=logweights[i]; - } - // Calculate normalization constant - for(unsigned i=0;isetWeight( exp( logweights[i]-maxweight ) ); - } - // Calculate normalized weights (with memory) + if( ignore_weights ) { + for(unsigned i=0; isetWeight(1.0); norm+=1.0; + } + } else if( nomemory ) { + // Find the maximum weight + double maxweight=logweights[0]; + for(unsigned i=1; imaxweight) maxweight=logweights[i]; + } + // Calculate normalization constant + for(unsigned i=0; isetWeight( exp( logweights[i]-maxweight ) ); + } + // Calculate normalized weights (with memory) } else { - plumed_merror("analysis can now only support block averages"); - // if( !firstAnalysisDone ) - // finalizeWeightsNoLogSums( 1.0 ); - // else finalizeWeightsNoLogSums( old_norm ); + plumed_merror("analysis can now only support block averages"); + // if( !firstAnalysisDone ) + // finalizeWeightsNoLogSums( 1.0 ); + // else finalizeWeightsNoLogSums( old_norm ); } } @@ -264,26 +264,26 @@ void Analysis::finalizeWeights( const bool& ignore_weights ){ void Analysis::getDataPoint( const unsigned& idata, std::vector& point, double& weight ) const { plumed_dbg_assert( getNumberOfAtoms()==0 ); - if( !reusing_data ){ - plumed_dbg_assert( idatagetReferenceArgument(i); - weight=data[idata]->getWeight(); + if( !reusing_data ) { + plumed_dbg_assert( idatagetReferenceArgument(i); + weight=data[idata]->getWeight(); } else { - return mydatastash->getDataPoint( idata, point, weight ); + return mydatastash->getDataPoint( idata, point, weight ); } } -void Analysis::runAnalysis(){ +void Analysis::runAnalysis() { // Note : could add multiple walkers here - simply read in the data from all // other walkers here if we are writing the check points. - // Calculate the final weights from the log weights - if( !reusing_data ){ - finalizeWeights( ignore_reweight ); + // Calculate the final weights from the log weights + if( !reusing_data ) { + finalizeWeights( ignore_reweight ); } else { - mydatastash->finalizeWeights( ignore_reweight ); - // norm=mydatastash->retrieveNorm(); + mydatastash->finalizeWeights( ignore_reweight ); + // norm=mydatastash->retrieveNorm(); } // This ensures everything is set up to run the calculation // if( single_run ) setAnalysisStride( single_run, freq ); @@ -294,15 +294,15 @@ void Analysis::runAnalysis(){ } -void Analysis::performOperations( const bool& from_update ){ +void Analysis::performOperations( const bool& from_update ) { accumulate(); - if( freq>0 ){ - if( getStep()>0 && getStep()%freq==0 ) runAnalysis(); - else if( idata==logweights.size() ) error("something has gone wrong. Probably a wrong initial time on restart"); + if( freq>0 ) { + if( getStep()>0 && getStep()%freq==0 ) runAnalysis(); + else if( idata==logweights.size() ) error("something has gone wrong. Probably a wrong initial time on restart"); } } -bool Analysis::getPeriodicityInformation(const unsigned& i, std::string& dmin, std::string& dmax){ +bool Analysis::getPeriodicityInformation(const unsigned& i, std::string& dmin, std::string& dmax) { bool isperiodic=getPntrToArgument(i)->isPeriodic(); if(isperiodic) getPntrToArgument(i)->getDomain(dmin,dmax); return isperiodic; @@ -311,7 +311,7 @@ bool Analysis::getPeriodicityInformation(const unsigned& i, std::string& dmin, s void Analysis::runFinalJobs() { if( freq>0 ) return; if( getNumberOfDataPoints()==0 ) error("no data is available for analysis"); - runAnalysis(); + runAnalysis(); } } diff --git a/src/analysis/Analysis.h b/src/analysis/Analysis.h index 2a6c371afb..44b6082777 100644 --- a/src/analysis/Analysis.h +++ b/src/analysis/Analysis.h @@ -34,7 +34,7 @@ namespace analysis { /** \ingroup INHERIT -This is the abstract base class to use for implementing new methods for analyzing the trajectory, within it there +This is the abstract base class to use for implementing new methods for analyzing the trajectory, within it there is information as to how to go about implementing a new analysis method. */ @@ -82,7 +82,7 @@ class Analysis : public vesselbase::ActionWithAveraging { /// Get the metric if we are using malonobius distance and flexible hill std::vector getMetric() const ; protected: -/// List of argument names +/// List of argument names std::vector argument_names; /// This is used to read in output file names for analysis methods. When /// this method is used and the calculation is not restarted old analysis @@ -98,10 +98,10 @@ class Analysis : public vesselbase::ActionWithAveraging { double getWeight( const unsigned& idata ) const ; /// Retrieve the ith point void getDataPoint( const unsigned& idata, std::vector& point, double& weight ) const ; -/// Returns true if argument i is periodic together with the domain +/// Returns true if argument i is periodic together with the domain bool getPeriodicityInformation(const unsigned& i, std::string& dmin, std::string& dmax); /// Are we analyzing each data block separately (if we are not this also returns the old normalization ) - bool usingMemory() const; + bool usingMemory() const; /// Return the format to use for numbers in output files std::string getOutputFormat() const ; /// Finalize the weights without using the log sums @@ -110,14 +110,14 @@ class Analysis : public vesselbase::ActionWithAveraging { static void registerKeywords( Keywords& keys ); explicit Analysis(const ActionOptions&); ~Analysis(); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void accumulate(); void performOperations( const bool& from_update ); virtual void performAnalysis()=0; void runFinalJobs(); void runAnalysis(); - bool isPeriodic(){ plumed_error(); return false; } + bool isPeriodic() { plumed_error(); return false; } /// Convert the stored log weights to proper weights virtual void finalizeWeights( const bool& ignore_weights ); }; @@ -129,20 +129,20 @@ std::string Analysis::getMetricName() const { inline unsigned Analysis::getNumberOfDataPoints() const { - if( !reusing_data ){ - plumed_dbg_assert( data.size()==logweights.size() ); - return data.size(); + if( !reusing_data ) { + plumed_dbg_assert( data.size()==logweights.size() ); + return data.size(); } else { - return mydatastash->getNumberOfDataPoints(); + return mydatastash->getNumberOfDataPoints(); } } inline bool Analysis::usingMemory() const { - if( !reusing_data ){ - return !nomemory; + if( !reusing_data ) { + return !nomemory; } else { - return mydatastash->usingMemory(); + return mydatastash->usingMemory(); } } diff --git a/src/analysis/AnalysisWithLandmarks.cpp b/src/analysis/AnalysisWithLandmarks.cpp index 4ff419e922..9cd67c52f4 100644 --- a/src/analysis/AnalysisWithLandmarks.cpp +++ b/src/analysis/AnalysisWithLandmarks.cpp @@ -25,7 +25,7 @@ //+PLUMEDOC INTERNAL landmarkselection /* -This is currently a filler page. +This is currently a filler page. Just use LANDMARKS=ALL. More complex versions will appear in later versions. @@ -35,37 +35,37 @@ Just use LANDMARKS=ALL. More complex versions will appear in later versions. namespace PLMD { namespace analysis { -void AnalysisWithLandmarks::registerKeywords( Keywords& keys ){ +void AnalysisWithLandmarks::registerKeywords( Keywords& keys ) { Analysis::registerKeywords( keys ); keys.add("compulsory","LANDMARKS","ALL","only use a subset of the data that was collected. " - "For more information on the landmark selection algorithms that are available in " - "plumed see \\ref landmarkselection."); + "For more information on the landmark selection algorithms that are available in " + "plumed see \\ref landmarkselection."); } AnalysisWithLandmarks::AnalysisWithLandmarks( const ActionOptions& ao): -Action(ao), -Analysis(ao), -data_to_analyze(NULL) + Action(ao), + Analysis(ao), + data_to_analyze(NULL) { - std::string linput; parse("LANDMARKS",linput); - std::vector words=Tools::getWords(linput); - landmarkSelector=landmarkRegister().create( LandmarkSelectionOptions(words,this) ); - log.printf(" %s\n", landmarkSelector->description().c_str() ); + std::string linput; parse("LANDMARKS",linput); + std::vector words=Tools::getWords(linput); + landmarkSelector=landmarkRegister().create( LandmarkSelectionOptions(words,this) ); + log.printf(" %s\n", landmarkSelector->description().c_str() ); } -AnalysisWithLandmarks::~AnalysisWithLandmarks(){ - delete landmarkSelector; +AnalysisWithLandmarks::~AnalysisWithLandmarks() { + delete landmarkSelector; } -void AnalysisWithLandmarks::setDataToAnalyze( MultiReferenceBase* mydata ){ - data_to_analyze=mydata; +void AnalysisWithLandmarks::setDataToAnalyze( MultiReferenceBase* mydata ) { + data_to_analyze=mydata; } unsigned AnalysisWithLandmarks::getNumberOfLandmarks() const { return landmarkSelector->getNumberOfLandmarks(); } -void AnalysisWithLandmarks::performAnalysis(){ +void AnalysisWithLandmarks::performAnalysis() { plumed_assert( data_to_analyze ); landmarkSelector->selectLandmarks( data_to_analyze ); analyzeLandmarks(); diff --git a/src/analysis/AnalysisWithLandmarks.h b/src/analysis/AnalysisWithLandmarks.h index 3eb2c6a023..b129a4d01e 100644 --- a/src/analysis/AnalysisWithLandmarks.h +++ b/src/analysis/AnalysisWithLandmarks.h @@ -33,12 +33,12 @@ namespace analysis { class LandmarkSelectionBase; class AnalysisWithLandmarks : public Analysis { -friend class LandmarkSelectionBase; -friend class CopyAllFrames; + friend class LandmarkSelectionBase; + friend class CopyAllFrames; private: /// This object selects landmarks from the data LandmarkSelectionBase* landmarkSelector; -/// A pointer to the data we are analyzing +/// A pointer to the data we are analyzing MultiReferenceBase* data_to_analyze; protected: /// Set the data that needs to be analyzed @@ -53,7 +53,7 @@ friend class CopyAllFrames; void performAnalysis(); virtual void analyzeLandmarks()=0; /// This does nothing - void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; + void performTask( const unsigned&, const unsigned&, MultiValue& ) const ; }; } diff --git a/src/analysis/Average.cpp b/src/analysis/Average.cpp index ec2da2ad28..c96b2556bb 100644 --- a/src/analysis/Average.cpp +++ b/src/analysis/Average.cpp @@ -23,8 +23,8 @@ #include "core/ActionRegister.h" #include "AverageVessel.h" -//+PLUMEDOC GRIDCALC AVERAGE -/* +//+PLUMEDOC GRIDCALC AVERAGE +/* Calculate the ensemble average of a collective variable The ensemble average for a non-periodic, collective variable, \f$s\f$ is given by the following expression: @@ -34,8 +34,8 @@ The ensemble average for a non-periodic, collective variable, \f$s\f$ is given b \f] Here the sum runs over a the trajectory and \f$s(t')\f$ is used to denote the value of the collective variable -at time \f$t'\f$. The final quantity evalulated is a weighted -average as the weights, \f$w(t')\f$, allow us to negate the effect any bias might have on the region of phase space +at time \f$t'\f$. The final quantity evalulated is a weighted +average as the weights, \f$w(t')\f$, allow us to negate the effect any bias might have on the region of phase space sampled by the system. This is discussed in the section of the manual on \ref Analysis. When the variable is periodic (e.g. \ref TORSION) and has a value, \f$s\f$, in \f$a \le s \le b\f$ the ensemble average is evaluated using: @@ -47,12 +47,12 @@ When the variable is periodic (e.g. \ref TORSION) and has a value, \f$s\f$, in \ \par Examples The following example calculates the ensemble average for the distance between atoms 1 and 2 -and output this to a file called COLVAR. In this example it is assumed that no bias is acting -on the system and that the weights, \f$w(t')\f$ in the formulae above can thus all be set equal -to one. +and output this to a file called COLVAR. In this example it is assumed that no bias is acting +on the system and that the weights, \f$w(t')\f$ in the formulae above can thus all be set equal +to one. \verbatim -d1: DISTANCE ATOMS=1,2 +d1: DISTANCE ATOMS=1,2 d1a: AVERAGE ARG=d1 PRINT ARG=d1a FILE=colvar STRIDE=100 \endverbatim @@ -60,23 +60,23 @@ PRINT ARG=d1a FILE=colvar STRIDE=100 The following example calculates the ensemble average for the torsional angle involving atoms 1, 2, 3 and 4. At variance with the previous example this quantity is periodic so the second formula in the above introduction is used to calculate the average. Furthermore, by using the CLEAR keyword we have specified that block averages -are to be calculated. Consequently, after 100 steps all the information aquired thus far in the simulation is -forgotten and the process of averaging is begun again. The quantities output in the colvar file are thus the +are to be calculated. Consequently, after 100 steps all the information aquired thus far in the simulation is +forgotten and the process of averaging is begun again. The quantities output in the colvar file are thus the block averages taken over the first 100 frames of the trajectory, the block average over the second 100 frames of trajectory and so on. \verbatim -t1: TORSION ATOMS=1,2,3,4 +t1: TORSION ATOMS=1,2,3,4 t1a: AVERAGE ARG=t1 CLEAR=100 PRINT ARG=t1a FILE=colvar STRIDE=100 \endverbatim This third example incorporates a bias. Notice that the effect the bias has on the ensemble average is removed by taking advantage of the \ref REWEIGHT_BIAS method. The final ensemble averages output to the file are thus block ensemble averages for the -unbiased canononical ensemble at a temperature of 300 K. +unbiased canononical ensemble at a temperature of 300 K. \verbatim -t1: TORSION ATOMS=1,2,3,4 +t1: TORSION ATOMS=1,2,3,4 RESTRAINT ARG=t1 AT=pi KAPPA=100. ww: REWEIGHT_BIAS TEMP=300 t1a: AVERAGE ARG=t1 LOGWEIGHTS=ww CLEAR=100 @@ -95,47 +95,47 @@ class Average : public vesselbase::ActionWithAveraging { public: static void registerKeywords( Keywords& keys ); explicit Average( const ActionOptions& ); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void performOperations( const bool& from_update ); void finishAveraging(); - bool isPeriodic(){ return false; } - void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); } + bool isPeriodic() { return false; } + void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); } }; PLUMED_REGISTER_ACTION(Average,"AVERAGE") -void Average::registerKeywords( Keywords& keys ){ +void Average::registerKeywords( Keywords& keys ) { vesselbase::ActionWithAveraging::registerKeywords( keys ); keys.use("ARG"); - keys.remove("SERIAL"); keys.remove("LOWMEM"); + keys.remove("SERIAL"); keys.remove("LOWMEM"); } Average::Average( const ActionOptions& ao ): -Action(ao), -ActionWithAveraging(ao) + Action(ao), + ActionWithAveraging(ao) { - addValue(); // Create a value so that we can output the average - if( getNumberOfArguments()!=1 ) error("only one quantity can be averaged at a time"); - std::string instring; - if( getPntrToArgument(0)->isPeriodic() ){ - std::string min, max; getPntrToArgument(0)->getDomain(min,max); - instring = "PERIODIC=" + min + "," + max; setPeriodic( min, max ); - } else { - setNotPeriodic(); - } - // Create a vessel to hold the average - vesselbase::VesselOptions da("myaverage","",-1,instring,this); - Keywords keys; AverageVessel::registerKeywords( keys ); - vesselbase::VesselOptions dar( da, keys ); - myaverage = new AverageVessel(dar); setAveragingAction( myaverage, false ); + addValue(); // Create a value so that we can output the average + if( getNumberOfArguments()!=1 ) error("only one quantity can be averaged at a time"); + std::string instring; + if( getPntrToArgument(0)->isPeriodic() ) { + std::string min, max; getPntrToArgument(0)->getDomain(min,max); + instring = "PERIODIC=" + min + "," + max; setPeriodic( min, max ); + } else { + setNotPeriodic(); + } + // Create a vessel to hold the average + vesselbase::VesselOptions da("myaverage","",-1,instring,this); + Keywords keys; AverageVessel::registerKeywords( keys ); + vesselbase::VesselOptions dar( da, keys ); + myaverage = new AverageVessel(dar); setAveragingAction( myaverage, false ); } -void Average::performOperations( const bool& from_update ){ - myaverage->accumulate( cweight, getArgument(0) ); +void Average::performOperations( const bool& from_update ) { + myaverage->accumulate( cweight, getArgument(0) ); } -void Average::finishAveraging(){ - setValue( myaverage->getAverage() ); +void Average::finishAveraging() { + setValue( myaverage->getAverage() ); } } diff --git a/src/analysis/AverageVessel.cpp b/src/analysis/AverageVessel.cpp index 1361696539..96e4a72fe0 100644 --- a/src/analysis/AverageVessel.cpp +++ b/src/analysis/AverageVessel.cpp @@ -24,30 +24,30 @@ namespace PLMD { namespace analysis { -void AverageVessel::registerKeywords( Keywords& keys ){ +void AverageVessel::registerKeywords( Keywords& keys ) { vesselbase::AveragingVessel::registerKeywords( keys ); keys.add("optional","PERIODIC","is the quantity being averaged periodic and what is its domain"); } AverageVessel::AverageVessel( const vesselbase::VesselOptions& da): -AveragingVessel(da) + AveragingVessel(da) { parseVector("PERIODIC",domain); plumed_assert( domain.size()==2 || domain.size()==0 ); } -void AverageVessel::resize(){ - resizeBuffer(0); +void AverageVessel::resize() { + resizeBuffer(0); if( domain.size()==2 ) setDataSize(2); else setDataSize(1); } -void AverageVessel::accumulate( const double& weight, const double& val ){ - if( domain.size()==2 ){ - // Average with Berry Phase - double tval = 2*pi*( val - domain[0] ) / ( domain[1] - domain[0] ); - addDataElement( 0, weight*sin(tval) ); addDataElement( 1, weight*cos(tval) ); - } else addDataElement( 0, weight*val ); +void AverageVessel::accumulate( const double& weight, const double& val ) { + if( domain.size()==2 ) { + // Average with Berry Phase + double tval = 2*pi*( val - domain[0] ) / ( domain[1] - domain[0] ); + addDataElement( 0, weight*sin(tval) ); addDataElement( 1, weight*cos(tval) ); + } else addDataElement( 0, weight*val ); } double AverageVessel::getAverage() const { diff --git a/src/analysis/AverageVessel.h b/src/analysis/AverageVessel.h index 6b1f239712..3b056b8c48 100644 --- a/src/analysis/AverageVessel.h +++ b/src/analysis/AverageVessel.h @@ -29,21 +29,21 @@ namespace analysis { class AverageVessel : public vesselbase::AveragingVessel { private: - std::vector domain; + std::vector domain; public: /// keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Constructor - explicit AverageVessel( const vesselbase::VesselOptions& ); + explicit AverageVessel( const vesselbase::VesselOptions& ); /// Set the size of the data vessel - void resize(); + void resize(); /// This does nothing - void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; - std::string description(){ return ""; } + void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; + std::string description() { return ""; } /// Accumulate the average - void accumulate( const double& weight, const double& val ); + void accumulate( const double& weight, const double& val ); /// Get the average value - double getAverage() const ; + double getAverage() const ; }; } diff --git a/src/analysis/ClassicalMultiDimensionalScaling.cpp b/src/analysis/ClassicalMultiDimensionalScaling.cpp index 6326dab170..93bb25f1d4 100644 --- a/src/analysis/ClassicalMultiDimensionalScaling.cpp +++ b/src/analysis/ClassicalMultiDimensionalScaling.cpp @@ -29,26 +29,26 @@ namespace analysis { //+PLUMEDOC DIMRED CLASSICAL_MDS /* -Create a low-dimensional projection of a trajectory using the classical multidimensional +Create a low-dimensional projection of a trajectory using the classical multidimensional scaling algorithm. -Multidimensional scaling (MDS) is similar to what is done when you make a map. You start with distances -between London, Belfast, Paris and Dublin and then you try to arrange points on a piece of paper so that the (suitably scaled) -distances between the points in your map representing each of those cities are related to the true distances between the cities. -Stating this more mathematically MDS endeavors to find an isometry -between points distributed in a high-dimensional space and a set of points distributed in a low-dimensional plane. -In other words, if we have \f$M\f$ \f$D\f$-dimensional points, \f$\mathbf{X}\f$, -and we can calculate dissimilarities between pairs them, \f$D_{ij}\f$, we can, with an MDS calculation, try to create \f$M\f$ projections, -\f$\mathbf{x}\f$, of the high dimensionality points in a \f$d\f$-dimensional linear space by trying to arrange the projections so that the +Multidimensional scaling (MDS) is similar to what is done when you make a map. You start with distances +between London, Belfast, Paris and Dublin and then you try to arrange points on a piece of paper so that the (suitably scaled) +distances between the points in your map representing each of those cities are related to the true distances between the cities. +Stating this more mathematically MDS endeavors to find an isometry +between points distributed in a high-dimensional space and a set of points distributed in a low-dimensional plane. +In other words, if we have \f$M\f$ \f$D\f$-dimensional points, \f$\mathbf{X}\f$, +and we can calculate dissimilarities between pairs them, \f$D_{ij}\f$, we can, with an MDS calculation, try to create \f$M\f$ projections, +\f$\mathbf{x}\f$, of the high dimensionality points in a \f$d\f$-dimensional linear space by trying to arrange the projections so that the Euclidean distances between pairs of them, \f$d_{ij}\f$, resemble the dissimilarities between the high dimensional points. In short we minimize: \f[ \chi^2 = \sum_{i \ne j} \left( D_{ij} - d_{ij} \right)^2 \f] -where \f$D_{ij}\f$ is the distance between point \f$X^{i}\f$ and point \f$X^{j}\f$ and \f$d_{ij}\f$ is the distance between the projection -of \f$X^{i}\f$, \f$x^i\f$, and the projection of \f$X^{j}\f$, \f$x^j\f$. A tutorial on this approach can be used to analyse simulations -can be found in the tutorial \ref belfast-3 and in the following short video. +where \f$D_{ij}\f$ is the distance between point \f$X^{i}\f$ and point \f$X^{j}\f$ and \f$d_{ij}\f$ is the distance between the projection +of \f$X^{i}\f$, \f$x^i\f$, and the projection of \f$X^{j}\f$, \f$x^j\f$. A tutorial on this approach can be used to analyse simulations +can be found in the tutorial \ref belfast-3 and in the following short video. \par Examples @@ -58,34 +58,34 @@ The RMSD distance between atoms 1-256 have moved is used to measure the distance \verbatim CLASSICAL_MDS ... ATOMS=1-256 - METRIC=OPTIMAL-FAST + METRIC=OPTIMAL-FAST USE_ALL_DATA NLOW_DIM=2 OUTPUT_FILE=rmsd-embed ... CLASSICAL_MDS \endverbatim -The following section is for people who are interested in how this method works in detail. A solid understanding of this material is -not necessary to use MDS. +The following section is for people who are interested in how this method works in detail. A solid understanding of this material is +not necessary to use MDS. \section dim-sec Method of optimisation -The stress function can be minimized using a standard optimization algorithm such as conjugate gradients or steepest descent. -However, it is more common to do this minimization using a technique known as classical scaling. Classical scaling works by +The stress function can be minimized using a standard optimization algorithm such as conjugate gradients or steepest descent. +However, it is more common to do this minimization using a technique known as classical scaling. Classical scaling works by recognizing that each of the distances $D_{ij}$ in the above sum can be written as: \f[ -D_{ij}^2 = \sum_{\alpha} (X^i_\alpha - X^j_\alpha)^2 = \sum_\alpha (X^i_\alpha)^2 + (X^j_\alpha)^2 - 2X^i_\alpha X^j_\alpha +D_{ij}^2 = \sum_{\alpha} (X^i_\alpha - X^j_\alpha)^2 = \sum_\alpha (X^i_\alpha)^2 + (X^j_\alpha)^2 - 2X^i_\alpha X^j_\alpha \f] -We can use this expression and matrix algebra to calculate multiple distances at once. For instance if we have three points, +We can use this expression and matrix algebra to calculate multiple distances at once. For instance if we have three points, \f$\mathbf{X}\f$, we can write distances between them as: \f{eqnarray*}{ D^2(\mathbf{X}) &=& \left[ \begin{array}{ccc} 0 & d_{12}^2 & d_{13}^2 \\ d_{12}^2 & 0 & d_{23}^2 \\ -d_{13}^2 & d_{23}^2 & 0 +d_{13}^2 & d_{23}^2 & 0 \end{array}\right] \\ &=& \sum_\alpha \left[ \begin{array}{ccc} @@ -103,19 +103,19 @@ X^1_\alpha X^1_\alpha & X^1_\alpha X^2_\alpha & X^1_\alpha X^3_\alpha \\ X^2_\alpha X^1_\alpha & X^2_\alpha X^2_\alpha & X^2_\alpha X^3_\alpha \\ X^1_\alpha X^3_\alpha & X^3_\alpha X^2_\alpha & X^3_\alpha X^3_\alpha \end{array}\right] \nonumber \\ -&=& \mathbf{c 1^T} + \mathbf{1 c^T} - 2 \sum_\alpha \mathbf{x}_a \mathbf{x}^T_a = \mathbf{c 1^T} + \mathbf{1 c^T} - 2\mathbf{X X^T} +&=& \mathbf{c 1^T} + \mathbf{1 c^T} - 2 \sum_\alpha \mathbf{x}_a \mathbf{x}^T_a = \mathbf{c 1^T} + \mathbf{1 c^T} - 2\mathbf{X X^T} \f} -This last equation can be extended to situations when we have more than three points. In it \f$\mathbf{X}\f$ is a matrix that has -one high-dimensional point on each of its rows and \f$\mathbf{X^T}\f$ is its transpose. \f$\mathbf{1}\f$ is an \f$M \times 1\f$ vector +This last equation can be extended to situations when we have more than three points. In it \f$\mathbf{X}\f$ is a matrix that has +one high-dimensional point on each of its rows and \f$\mathbf{X^T}\f$ is its transpose. \f$\mathbf{1}\f$ is an \f$M \times 1\f$ vector of ones and \f$\mathbf{c}\f$ is a vector with components given by: \f[ c_i = \sum_\alpha (x_\alpha^i)^2 \f] -These quantities are the diagonal elements of \f$\mathbf{X X^T}\f$, which is a dot product or Gram Matrix that contains the -dot product of the vector \f$X_i\f$ with the vector \f$X_j\f$ in element \f$i,j\f$. +These quantities are the diagonal elements of \f$\mathbf{X X^T}\f$, which is a dot product or Gram Matrix that contains the +dot product of the vector \f$X_i\f$ with the vector \f$X_j\f$ in element \f$i,j\f$. In classical scaling we introduce a centering matrix \f$\mathbf{J}\f$ that is given by: @@ -130,36 +130,36 @@ where \f$\mathbf{I}\f$ is the identity. Multiplying the equations above from th &=& -\frac{1}{2}\mathbf{J c 1^T J} - \frac{1}{2} \mathbf{J 1 c^T J} + \frac{1}{2} \mathbf{J}(2\mathbf{X X^T})\mathbf{J} \\ &=& \mathbf{ J X X^T J } = \mathbf{X X^T } \label{eqn:scaling} \f} - -The fist two terms in this expression disappear because \f$\mathbf{1^T J}=\mathbf{J 1} =\mathbf{0}\f$, where \f$\mathbf{0}\f$ -is a matrix containing all zeros. In the final step meanwhile we use the fact that the matrix of squared distances will not + +The fist two terms in this expression disappear because \f$\mathbf{1^T J}=\mathbf{J 1} =\mathbf{0}\f$, where \f$\mathbf{0}\f$ +is a matrix containing all zeros. In the final step meanwhile we use the fact that the matrix of squared distances will not change when we translate all the points. We can thus assume that the mean value, \f$\mu\f$, for each of the components, \f$\alpha\f$: \f[ \mu_\alpha = \frac{1}{M} \sum_{i=1}^N \mathbf{X}^i_\alpha \f] -is equal to 0 so the columns of \f$\mathbf{X}\f$ add up to 0. This in turn means that each of the columns of -\f$\mathbf{X X^T}\f$ adds up to zero, which is what allows us to write \f$\mathbf{ J X X^T J } = \mathbf{X X^T }\f$. +is equal to 0 so the columns of \f$\mathbf{X}\f$ add up to 0. This in turn means that each of the columns of +\f$\mathbf{X X^T}\f$ adds up to zero, which is what allows us to write \f$\mathbf{ J X X^T J } = \mathbf{X X^T }\f$. -The matrix of squared distances is symmetric and positive-definite we can thus use the spectral decomposition to decompose it as: +The matrix of squared distances is symmetric and positive-definite we can thus use the spectral decomposition to decompose it as: \f[ \Phi= \mathbf{V} \Lambda \mathbf{V}^T \f] -Furthermore, because the matrix we are diagonalizing, \f$\mathbf{X X^T}\f$, is the product of a matrix and its transpose +Furthermore, because the matrix we are diagonalizing, \f$\mathbf{X X^T}\f$, is the product of a matrix and its transpose we can use this decomposition to write: \f[ -\mathbf{X} =\mathbf{V} \Lambda^\frac{1}{2} +\mathbf{X} =\mathbf{V} \Lambda^\frac{1}{2} \f] -Much as in PCA there are generally a small number of large eigenvalues in \f$\Lambda\f$ and many small eigenvalues. -We can safely use only the large eigenvalues and their corresponding eigenvectors to express the relationship between -the coordinates \f$\mathbf{X}\f$. This gives us our set of low-dimensional projections. +Much as in PCA there are generally a small number of large eigenvalues in \f$\Lambda\f$ and many small eigenvalues. +We can safely use only the large eigenvalues and their corresponding eigenvectors to express the relationship between +the coordinates \f$\mathbf{X}\f$. This gives us our set of low-dimensional projections. This derivation makes a number of assumptions about the how the low dimensional points should best be arranged to minimise -the stress. If you use an interative optimization algorithm such as SMACOF you may thus be able to find a better -(lower-stress) projection of the points. For more details on the assumptions made +the stress. If you use an interative optimization algorithm such as SMACOF you may thus be able to find a better +(lower-stress) projection of the points. For more details on the assumptions made see this website. */ //+ENDPLUMEDOC @@ -179,7 +179,7 @@ class ClassicalMultiDimensionalScaling : public AnalysisWithLandmarks { PLUMED_REGISTER_ACTION(ClassicalMultiDimensionalScaling,"CLASSICAL_MDS") -void ClassicalMultiDimensionalScaling::registerKeywords( Keywords& keys ){ +void ClassicalMultiDimensionalScaling::registerKeywords( Keywords& keys ) { AnalysisWithLandmarks::registerKeywords( keys ); keys.add("compulsory","NLOW_DIM","number of low-dimensional coordinates required"); keys.add("compulsory","OUTPUT_FILE","file on which to output the final embedding coordinates"); @@ -187,8 +187,8 @@ void ClassicalMultiDimensionalScaling::registerKeywords( Keywords& keys ){ } ClassicalMultiDimensionalScaling::ClassicalMultiDimensionalScaling( const ActionOptions& ao ): -Action(ao), -AnalysisWithLandmarks(ao) + Action(ao), + AnalysisWithLandmarks(ao) { myembedding = new PointWiseMapping( getMetricName(), false ); setDataToAnalyze( dynamic_cast(myembedding) ); @@ -196,10 +196,10 @@ AnalysisWithLandmarks(ao) parse("NLOW_DIM",nlow); if( nlow<1 ) error("dimensionality of low dimensional space must be at least one"); std::vector propnames( nlow ); std::string num; - for(unsigned i=0;isetPropertyNames( propnames, false ); @@ -207,11 +207,11 @@ AnalysisWithLandmarks(ao) parseOutputFile("OUTPUT_FILE",ofilename); } -ClassicalMultiDimensionalScaling::~ClassicalMultiDimensionalScaling(){ +ClassicalMultiDimensionalScaling::~ClassicalMultiDimensionalScaling() { delete myembedding; } -void ClassicalMultiDimensionalScaling::analyzeLandmarks(){ +void ClassicalMultiDimensionalScaling::analyzeLandmarks() { // Calculate all pairwise diatances myembedding->calculateAllDistances( getPbc(), getArguments(), comm, myembedding->modifyDmat(), true ); @@ -220,27 +220,27 @@ void ClassicalMultiDimensionalScaling::analyzeLandmarks(){ // Output the embedding as long lists of data // std::string gfname=saveResultsFromPreviousAnalyses( ofilename ); - OFile gfile; gfile.link(*this); + OFile gfile; gfile.link(*this); gfile.setBackupString("analysis"); gfile.fmtField(getOutputFormat()+" "); gfile.open( ofilename.c_str() ); - + // Print embedding coordinates - for(unsigned i=0;igetNumberOfReferenceFrames();++i){ - for(unsigned j=0;jgetProjectionCoordinate(i,j) ); - } - gfile.printField(); - } + for(unsigned i=0; igetNumberOfReferenceFrames(); ++i) { + for(unsigned j=0; jgetProjectionCoordinate(i,j) ); + } + gfile.printField(); + } gfile.close(); // Output the embedding in plumed format - if( efilename!="dont output"){ - OFile afile; afile.link(*this); afile.setBackupString("analysis"); - afile.open( efilename.c_str() ); - myembedding->print( "classical mds", getTime(), afile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); - afile.close(); + if( efilename!="dont output") { + OFile afile; afile.link(*this); afile.setBackupString("analysis"); + afile.open( efilename.c_str() ); + myembedding->print( "classical mds", getTime(), afile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); + afile.close(); } } diff --git a/src/analysis/ClassicalScaling.cpp b/src/analysis/ClassicalScaling.cpp index f7e9890c9c..e7c911eeef 100644 --- a/src/analysis/ClassicalScaling.cpp +++ b/src/analysis/ClassicalScaling.cpp @@ -25,31 +25,31 @@ namespace PLMD { namespace analysis { -void ClassicalScaling::run( PointWiseMapping* mymap ){ - // Retrieve the distances from the dimensionality reduction object - double half=(-0.5); Matrix distances( half*mymap->modifyDmat() ); - - // Apply centering transtion - unsigned n=distances.nrows(); double sum; - // First HM - for(unsigned i=0;i eigval(n); Matrix eigvec(n,n); - diagMat( distances, eigval, eigvec ); - - // Pass final projections to map object - for(unsigned i=0;igetNumberOfProperties();++j) mymap->setProjectionCoordinate( i, j, sqrt(eigval[n-1-j])*eigvec(n-1-j,i) ); - } +void ClassicalScaling::run( PointWiseMapping* mymap ) { + // Retrieve the distances from the dimensionality reduction object + double half=(-0.5); Matrix distances( half*mymap->modifyDmat() ); + + // Apply centering transtion + unsigned n=distances.nrows(); double sum; + // First HM + for(unsigned i=0; i eigval(n); Matrix eigvec(n,n); + diagMat( distances, eigval, eigvec ); + + // Pass final projections to map object + for(unsigned i=0; igetNumberOfProperties(); ++j) mymap->setProjectionCoordinate( i, j, sqrt(eigval[n-1-j])*eigvec(n-1-j,i) ); + } } } diff --git a/src/analysis/Commit.cpp b/src/analysis/Commit.cpp index 6c9bf69c85..5cbacf4db1 100644 --- a/src/analysis/Commit.cpp +++ b/src/analysis/Commit.cpp @@ -28,52 +28,52 @@ namespace PLMD { namespace analysis { -//+PLUMEDOC PRINTANALYSIS COMMITTOR +//+PLUMEDOC PRINTANALYSIS COMMITTOR /* Does a committor analysis. \par Examples The following input monitors two torsional angles during a simulation, -defines two basins (A and B) as a function of the two torsions and +defines two basins (A and B) as a function of the two torsions and stops the simulation when it falls in one of the two. In the log -file will be shown the latest values for the CVs and the basin reached. +file will be shown the latest values for the CVs and the basin reached. \verbatim TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 COMMITTOR ... - ARG=r1,r2 + ARG=r1,r2 STRIDE=10 - BASIN_LL1=0.15,0.20 - BASIN_UL1=0.25,0.40 - BASIN_LL2=-0.15,-0.20 - BASIN_UL2=-0.25,-0.40 -... COMMITTOR + BASIN_LL1=0.15,0.20 + BASIN_UL1=0.25,0.40 + BASIN_LL2=-0.15,-0.20 + BASIN_UL2=-0.25,-0.40 +... COMMITTOR \endverbatim */ //+ENDPLUMEDOC -class Committor : -public ActionPilot, -public ActionWithArguments +class Committor : + public ActionPilot, + public ActionWithArguments { private: std::string file; OFile ofile; std::string fmt; - std::vector< std::vector > lowerlimits; + std::vector< std::vector > lowerlimits; std::vector< std::vector > upperlimits; unsigned nbasins; public: static void registerKeywords( Keywords& keys ); explicit Committor(const ActionOptions&ao); void calculate(); - void apply(){} + void apply() {} }; PLUMED_REGISTER_ACTION(Committor,"COMMITTOR") -void Committor::registerKeywords( Keywords& keys ){ +void Committor::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -87,14 +87,14 @@ void Committor::registerKeywords( Keywords& keys ){ } Committor::Committor(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -fmt("%f") + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + fmt("%f") { ofile.link(*this); parse("FILE",file); - if(file.length()>0){ + if(file.length()>0) { ofile.open(file); log.printf(" on file %s\n",file.c_str()); } else { @@ -105,53 +105,53 @@ fmt("%f") fmt=" "+fmt; log.printf(" with format %s\n",fmt.c_str()); - for(unsigned i=0;i tmpl, tmpu; - parseNumberedVector("BASIN_LL", b, tmpl ); - parseNumberedVector("BASIN_UL", b, tmpu ); - if( tmpl.empty() && tmpu.empty() ) break; - if( tmpl.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_LL: they should be equal to the number of arguments"); - if( tmpu.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_UL: they should be equal to the number of arguments"); - lowerlimits.push_back(tmpl); - upperlimits.push_back(tmpu); - nbasins=b; + std::vector tmpl, tmpu; + parseNumberedVector("BASIN_LL", b, tmpl ); + parseNumberedVector("BASIN_UL", b, tmpu ); + if( tmpl.empty() && tmpu.empty() ) break; + if( tmpl.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_LL: they should be equal to the number of arguments"); + if( tmpu.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_UL: they should be equal to the number of arguments"); + lowerlimits.push_back(tmpl); + upperlimits.push_back(tmpu); + nbasins=b; } checkRead(); - for(unsigned b=0;bupperlimits[b][i]) error("COMMITTOR: UPPER bounds must always be greater than LOWER bounds"); log.printf(" %f - %f\n", lowerlimits[b][i], upperlimits[b][i]); } } } -void Committor::calculate(){ +void Committor::calculate() { std::vector inbasin; inbasin.assign (nbasins,1); - for(unsigned b=0;blowerlimits[b][i]&&getArgument(i)lowerlimits[b][i]&&getArgument(i) forcesToApply, finalForces; std::vector myvessels; std::vector stashes; - gridtools::HistogramOnGrid* myhist; + gridtools::HistogramOnGrid* myhist; public: static void registerKeywords( Keywords& keys ); explicit Histogram(const ActionOptions&ao); @@ -174,16 +174,16 @@ class Histogram : public gridtools::ActionWithGrid { void prepareForAveraging(); void performOperations( const bool& from_update ); void finishAveraging(); - bool isPeriodic(){ return false; } - unsigned getNumberOfDerivatives(); + bool isPeriodic() { return false; } + unsigned getNumberOfDerivatives(); void turnOnDerivatives(); - void compute( const unsigned& , MultiValue& ) const ; + void compute( const unsigned&, MultiValue& ) const ; void apply(); }; PLUMED_REGISTER_ACTION(Histogram,"HISTOGRAM") -void Histogram::registerKeywords( Keywords& keys ){ +void Histogram::registerKeywords( Keywords& keys ) { gridtools::ActionWithGrid::registerKeywords( keys ); keys.use("ARG"); keys.add("optional","DATA","input data from action with vessel and compute histogram"); keys.add("optional","VECTORS","input three dimsnional vectors for computing histogram"); @@ -195,137 +195,137 @@ void Histogram::registerKeywords( Keywords& keys ){ } Histogram::Histogram(const ActionOptions&ao): -Action(ao), -ActionWithGrid(ao), -ww(0.0), -in_apply(false), -mvectors(false), -kernel(NULL) + Action(ao), + ActionWithGrid(ao), + ww(0.0), + in_apply(false), + mvectors(false), + kernel(NULL) { - // Read in arguments + // Read in arguments std::string vlab; parse("VECTORS",vlab); - if( vlab.length()>0 ){ - ActionWithVessel* myv = plumed.getActionSet().selectWithLabel( vlab ); - if( !myv ) error("action labelled " + vlab + " does not exist or is not an ActionWithVessel"); - myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); - addDependency( myv ); mvectors=true; - if( myv->getNumberOfQuantities()!=5 ) error("can only compute histograms for three dimensional vectors"); - log.printf(" for vector quantities calculated by %s \n", vlab.c_str() ); + if( vlab.length()>0 ) { + ActionWithVessel* myv = plumed.getActionSet().selectWithLabel( vlab ); + if( !myv ) error("action labelled " + vlab + " does not exist or is not an ActionWithVessel"); + myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); + addDependency( myv ); mvectors=true; + if( myv->getNumberOfQuantities()!=5 ) error("can only compute histograms for three dimensional vectors"); + log.printf(" for vector quantities calculated by %s \n", vlab.c_str() ); } else { - std::vector mlab; parseVector("DATA",mlab); - if( mlab.size()>0 ){ - for(unsigned i=0;i( mlab[i] ); - if( !myv ) error("action labelled " + mlab[i] + " does not exist or is not an ActionWithVessel"); - myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); - // log.printf(" for all base quantities calculated by %s \n",myvessel->getLabel().c_str() ); - // Add the dependency - addDependency( myv ); - } - unsigned nvals = myvessels[0]->getFullNumberOfTasks(); - for(unsigned i=1;igetFullNumberOfTasks() ) error("mismatched number of quantities calculated by actions input to histogram"); - } - log.printf(" for all base quantities calculated by %s ", myvessels[0]->getLabel().c_str() ); - for(unsigned i=1;igetLabel().c_str() ); + std::vector mlab; parseVector("DATA",mlab); + if( mlab.size()>0 ) { + for(unsigned i=0; i( mlab[i] ); + if( !myv ) error("action labelled " + mlab[i] + " does not exist or is not an ActionWithVessel"); + myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); + // log.printf(" for all base quantities calculated by %s \n",myvessel->getLabel().c_str() ); + // Add the dependency + addDependency( myv ); + } + unsigned nvals = myvessels[0]->getFullNumberOfTasks(); + for(unsigned i=1; igetFullNumberOfTasks() ) error("mismatched number of quantities calculated by actions input to histogram"); + } + log.printf(" for all base quantities calculated by %s ", myvessels[0]->getLabel().c_str() ); + for(unsigned i=1; igetLabel().c_str() ); + log.printf("\n"); + } else { + std::vector arg; parseArgumentList("ARG",arg); + if(!arg.empty()) { + log.printf(" with arguments"); + for(unsigned i=0; igetName().c_str()); log.printf("\n"); - } else { - std::vector arg; parseArgumentList("ARG",arg); - if(!arg.empty()){ - log.printf(" with arguments"); - for(unsigned i=0;igetName().c_str()); - log.printf("\n"); - // Retrieve the bias acting and make sure we request this also - std::vector bias( ActionWithArguments::getArguments() ); - for(unsigned i=0;i bias( ActionWithArguments::getArguments() ); + for(unsigned i=0; i0 ) narg=myvessels.size(); // Input of name and labels std::string vstring="COMPONENTS=" + getLabel(); - if( mvectors ){ - vstring += " COORDINATES=x,y,z PBC=F,F,F"; - } else if( myvessels.size()>0 ){ - vstring += " COORDINATES=" + myvessels[0]->getLabel(); - for(unsigned i=1;igetLabel(); - // Input for PBC - if( myvessels[0]->isPeriodic() ) vstring+=" PBC=T"; - else vstring+=" PBC=F"; - for(unsigned i=1;iisPeriodic() ) vstring+=",T"; - else vstring+=",F"; - } + if( mvectors ) { + vstring += " COORDINATES=x,y,z PBC=F,F,F"; + } else if( myvessels.size()>0 ) { + vstring += " COORDINATES=" + myvessels[0]->getLabel(); + for(unsigned i=1; igetLabel(); + // Input for PBC + if( myvessels[0]->isPeriodic() ) vstring+=" PBC=T"; + else vstring+=" PBC=F"; + for(unsigned i=1; iisPeriodic() ) vstring+=",T"; + else vstring+=",F"; + } } else { - vstring += " COORDINATES=" + getPntrToArgument(0)->getName(); - for(unsigned i=1;igetName(); - // Input for PBC - if( getPntrToArgument(0)->isPeriodic() ) vstring+=" PBC=T"; - else vstring+=" PBC=F"; - for(unsigned i=1;iisPeriodic() ) vstring+=",T"; - else vstring+=",F"; - } + vstring += " COORDINATES=" + getPntrToArgument(0)->getName(); + for(unsigned i=1; igetName(); + // Input for PBC + if( getPntrToArgument(0)->isPeriodic() ) vstring+=" PBC=T"; + else vstring+=" PBC=F"; + for(unsigned i=1; iisPeriodic() ) vstring+=",T"; + else vstring+=",F"; + } } // And create the grid - createGrid( "histogram", vstring ); - if( mygrid->getType()=="flat" ){ - if( mvectors ) error("computing histogram for three dimensional vectors but grid is not of fibonacci type - use CONCENTRATION"); - std::vector gmin( narg ), gmax( narg ); - parseVector("GRID_MIN",gmin); parseVector("GRID_MAX",gmax); - std::vector nbin; parseVector("GRID_BIN",nbin); - std::vector gspacing; parseVector("GRID_SPACING",gspacing); - if( nbin.size()!=narg && gspacing.size()!=narg ){ - error("GRID_BIN or GRID_SPACING must be set"); - } - mygrid->setBounds( gmin, gmax, nbin, gspacing ); + createGrid( "histogram", vstring ); + if( mygrid->getType()=="flat" ) { + if( mvectors ) error("computing histogram for three dimensional vectors but grid is not of fibonacci type - use CONCENTRATION"); + std::vector gmin( narg ), gmax( narg ); + parseVector("GRID_MIN",gmin); parseVector("GRID_MAX",gmax); + std::vector nbin; parseVector("GRID_BIN",nbin); + std::vector gspacing; parseVector("GRID_SPACING",gspacing); + if( nbin.size()!=narg && gspacing.size()!=narg ) { + error("GRID_BIN or GRID_SPACING must be set"); + } + mygrid->setBounds( gmin, gmax, nbin, gspacing ); } else { - std::vector nbin; parseVector("GRID_BIN",nbin); - if( nbin.size()!=1 ) error("should only be one index for number of bins with spherical grid"); - if( mygrid->getType()=="fibonacci" ) mygrid->setupFibonacciGrid( nbin[0] ); + std::vector nbin; parseVector("GRID_BIN",nbin); + if( nbin.size()!=1 ) error("should only be one index for number of bins with spherical grid"); + if( mygrid->getType()=="fibonacci" ) mygrid->setupFibonacciGrid( nbin[0] ); } - myhist = dynamic_cast( mygrid ); - plumed_assert( myhist ); - if( myvessels.size()>0 ){ - // Create a task list - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList(i); - setAveragingAction( mygrid, true ); + myhist = dynamic_cast( mygrid ); + plumed_assert( myhist ); + if( myvessels.size()>0 ) { + // Create a task list + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList(i); + setAveragingAction( mygrid, true ); } else { - // Create a task list - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); - myhist->addOneKernelEachTimeOnly(); - setAveragingAction( mygrid, myhist->noDiscreteKernels() ); + // Create a task list + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); + myhist->addOneKernelEachTimeOnly(); + setAveragingAction( mygrid, myhist->noDiscreteKernels() ); } checkRead(); } -void Histogram::turnOnDerivatives(){ +void Histogram::turnOnDerivatives() { ActionWithGrid::turnOnDerivatives(); std::vector all_atoms, tmp_atoms; - for(unsigned i=0;i( myvessels[i] ); - if( !mbase ) error("do not know how to get histogram derivatives for actions of type " + myvessels[i]->getName() ); - tmp_atoms = mbase->getAbsoluteIndexes(); - for(unsigned j=0;j( myvessels[i] ); + if( !mbase ) error("do not know how to get histogram derivatives for actions of type " + myvessels[i]->getName() ); + tmp_atoms = mbase->getAbsoluteIndexes(); + for(unsigned j=0; jresize(); in_apply=false; } -unsigned Histogram::getNumberOfDerivatives(){ - if( in_apply ){ - unsigned nder=0; - for(unsigned i=0;igetNumberOfDerivatives(); - return nder; +unsigned Histogram::getNumberOfDerivatives() { + if( in_apply ) { + unsigned nder=0; + for(unsigned i=0; igetNumberOfDerivatives(); + return nder; } return getNumberOfArguments(); } @@ -336,152 +336,152 @@ unsigned Histogram::getNumberOfQuantities() const { return 2; } -void Histogram::prepareForAveraging(){ - if( myvessels.size()>0 ){ - deactivateAllTasks(); double norm=0; - for(unsigned i=0;igetNumberOfStoredValues();++i){ - std::vector cvals( myvessels[0]->getNumberOfQuantities() ); - stashes[0]->retrieveSequentialValue( i, false, cvals ); - unsigned itask=myvessels[0]->getActiveTask(i); double tnorm = cvals[0]; - for(unsigned j=1;jgetActiveTask(i)!=itask ) error("mismatched task identities in histogram suggests histogram is meaningless"); - if( cvals.size()!=myvessels[j]->getNumberOfQuantities() ) cvals.resize( myvessels[j]->getNumberOfQuantities() ); - stashes[j]->retrieveSequentialValue( i, false, cvals ); tnorm *= cvals[0]; - } - norm += tnorm; taskFlags[i]=1; +void Histogram::prepareForAveraging() { + if( myvessels.size()>0 ) { + deactivateAllTasks(); double norm=0; + for(unsigned i=0; igetNumberOfStoredValues(); ++i) { + std::vector cvals( myvessels[0]->getNumberOfQuantities() ); + stashes[0]->retrieveSequentialValue( i, false, cvals ); + unsigned itask=myvessels[0]->getActiveTask(i); double tnorm = cvals[0]; + for(unsigned j=1; jgetActiveTask(i)!=itask ) error("mismatched task identities in histogram suggests histogram is meaningless"); + if( cvals.size()!=myvessels[j]->getNumberOfQuantities() ) cvals.resize( myvessels[j]->getNumberOfQuantities() ); + stashes[j]->retrieveSequentialValue( i, false, cvals ); tnorm *= cvals[0]; } - lockContributors(); - // Sort out normalization of histogram - if( !noNormalization() ) ww = cweight / norm; - else ww = cweight; + norm += tnorm; taskFlags[i]=1; + } + lockContributors(); + // Sort out normalization of histogram + if( !noNormalization() ) ww = cweight / norm; + else ww = cweight; } else { - // Now fetch the kernel and the active points - std::vector point( getNumberOfArguments() ); - for(unsigned i=0;i neighbors(1); - kernel = myhist->getKernelAndNeighbors( point, num_neigh, neighbors ); - - if( num_neigh>1 ){ - // Activate relevant tasks - deactivateAllTasks(); - for(unsigned i=0;iaddToGridElement( neighbors[0], 0, cweight ); - } + // Now fetch the kernel and the active points + std::vector point( getNumberOfArguments() ); + for(unsigned i=0; i neighbors(1); + kernel = myhist->getKernelAndNeighbors( point, num_neigh, neighbors ); + + if( num_neigh>1 ) { + // Activate relevant tasks + deactivateAllTasks(); + for(unsigned i=0; iaddToGridElement( neighbors[0], 0, cweight ); + } } } -void Histogram::performOperations( const bool& from_update ){ if( myvessels.size()==0 ) plumed_dbg_assert( !myhist->noDiscreteKernels() ); } +void Histogram::performOperations( const bool& from_update ) { if( myvessels.size()==0 ) plumed_dbg_assert( !myhist->noDiscreteKernels() ); } -void Histogram::finishAveraging(){ +void Histogram::finishAveraging() { if( myvessels.size()==0 ) delete kernel; } -void Histogram::compute( const unsigned& current, MultiValue& myvals ) const { - if( mvectors ){ - std::vector cvals( myvessels[0]->getNumberOfQuantities() ); - stashes[0]->retrieveSequentialValue( current, true, cvals ); - for(unsigned i=2;igetNumberOfQuantities();++i) myvals.setValue( i-1, cvals[i] ); - myvals.setValue( 0, cvals[0] ); myvals.setValue( myvessels[0]->getNumberOfQuantities() - 1, ww ); - if( in_apply ){ - MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); - stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), true, tmpval ); - for(unsigned j=0;jgetNumberOfQuantities();++i) myvals.addDerivative( i-1, jder, tmpval.getDerivative(i, jder) ); - } - myvals.updateDynamicList(); +void Histogram::compute( const unsigned& current, MultiValue& myvals ) const { + if( mvectors ) { + std::vector cvals( myvessels[0]->getNumberOfQuantities() ); + stashes[0]->retrieveSequentialValue( current, true, cvals ); + for(unsigned i=2; igetNumberOfQuantities(); ++i) myvals.setValue( i-1, cvals[i] ); + myvals.setValue( 0, cvals[0] ); myvals.setValue( myvessels[0]->getNumberOfQuantities() - 1, ww ); + if( in_apply ) { + MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); + stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), true, tmpval ); + for(unsigned j=0; jgetNumberOfQuantities(); ++i) myvals.addDerivative( i-1, jder, tmpval.getDerivative(i, jder) ); } - } else if( myvessels.size()>0 ){ - std::vector cvals( myvessels[0]->getNumberOfQuantities() ); - stashes[0]->retrieveSequentialValue( current, false, cvals ); - unsigned derbase; double totweight=cvals[0], tnorm = cvals[0]; myvals.setValue( 1, cvals[1] ); - // Get the derivatives as well if we are in apply - if( in_apply ){ - // This bit gets the total weight - double weight0 = cvals[0]; // Store the current weight - for(unsigned j=1;jretrieveSequentialValue( current, false, cvals ); totweight *= cvals[0]; - } - // And this bit the derivatives - MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); - stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), false, tmpval ); - for(unsigned j=0;jgetNumberOfDerivatives(); + myvals.updateDynamicList(); + } + } else if( myvessels.size()>0 ) { + std::vector cvals( myvessels[0]->getNumberOfQuantities() ); + stashes[0]->retrieveSequentialValue( current, false, cvals ); + unsigned derbase; double totweight=cvals[0], tnorm = cvals[0]; myvals.setValue( 1, cvals[1] ); + // Get the derivatives as well if we are in apply + if( in_apply ) { + // This bit gets the total weight + double weight0 = cvals[0]; // Store the current weight + for(unsigned j=1; jretrieveSequentialValue( current, false, cvals ); totweight *= cvals[0]; } - for(unsigned i=1;igetNumberOfQuantities() ) cvals.resize( myvessels[i]->getNumberOfQuantities() ); - stashes[i]->retrieveSequentialValue( current, false, cvals ); - tnorm *= cvals[0]; myvals.setValue( 1+i, cvals[1] ); - // Get the derivatives as well if we are in apply - if( in_apply ){ - MultiValue tmpval( myvessels[i]->getNumberOfQuantities(), myvessels[i]->getNumberOfDerivatives() ); - stashes[i]->retrieveDerivatives( stashes[i]->getTrueIndex(current), false, tmpval ); - for(unsigned j=0;jgetNumberOfDerivatives(); - } + // And this bit the derivatives + MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); + stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), false, tmpval ); + for(unsigned j=0; j vv( myhist->getVectorOfValues() ); - std::vector val( getNumberOfArguments() ), der( getNumberOfArguments() ); - // Retrieve the location of the grid point at which we are evaluating the kernel - mygrid->getGridPointCoordinates( current, val ); - if( kernel ){ - for(unsigned i=0;iset( val[i] ); - // Evaluate the histogram at the relevant grid point and set the values - double vvh = kernel->evaluate( vv, der ,true); myvals.setValue( 1, vvh ); - } else { - plumed_merror("normalisation of vectors does not work with arguments and spherical grids"); - // Evalulate dot product - double dot=0; for(unsigned j=0;jvon_misses_norm)*exp( (myhist->von_misses_concentration)*dot ); myvals.setValue( 1, newval ); - // And final derivatives - for(unsigned j=0;jvon_misses_concentration)*newval; + derbase = myvessels[0]->getNumberOfDerivatives(); + } + for(unsigned i=1; igetNumberOfQuantities() ) cvals.resize( myvessels[i]->getNumberOfQuantities() ); + stashes[i]->retrieveSequentialValue( current, false, cvals ); + tnorm *= cvals[0]; myvals.setValue( 1+i, cvals[1] ); + // Get the derivatives as well if we are in apply + if( in_apply ) { + MultiValue tmpval( myvessels[i]->getNumberOfQuantities(), myvessels[i]->getNumberOfDerivatives() ); + stashes[i]->retrieveDerivatives( stashes[i]->getTrueIndex(current), false, tmpval ); + for(unsigned j=0; jgetNumberOfDerivatives(); } - // Set the derivatives and delete the vector of values - for(unsigned i=0;i vv( myhist->getVectorOfValues() ); + std::vector val( getNumberOfArguments() ), der( getNumberOfArguments() ); + // Retrieve the location of the grid point at which we are evaluating the kernel + mygrid->getGridPointCoordinates( current, val ); + if( kernel ) { + for(unsigned i=0; iset( val[i] ); + // Evaluate the histogram at the relevant grid point and set the values + double vvh = kernel->evaluate( vv, der,true); myvals.setValue( 1, vvh ); + } else { + plumed_merror("normalisation of vectors does not work with arguments and spherical grids"); + // Evalulate dot product + double dot=0; for(unsigned j=0; jvon_misses_norm)*exp( (myhist->von_misses_concentration)*dot ); myvals.setValue( 1, newval ); + // And final derivatives + for(unsigned j=0; jvon_misses_concentration)*newval; + } + // Set the derivatives and delete the vector of values + for(unsigned i=0; iwasForced() ) return ; - in_apply=true; + in_apply=true; // Run the loop to calculate the forces - runAllTasks(); finishAveraging(); + runAllTasks(); finishAveraging(); // We now need to retrieve the buffer and set the forces on the atoms - myhist->applyForce( forcesToApply ); + myhist->applyForce( forcesToApply ); // Now make the forces make sense for the virial unsigned fbase=0, tbase=0, vbase = getNumberOfDerivatives() - myvessels.size()*9; - for(unsigned i=vbase;igetNumberOfDerivatives()-9;++j){ - finalForces[fbase + j] = forcesToApply[tbase + j]; - } - unsigned k=0; - for(unsigned j=myvessels[i]->getNumberOfDerivatives()-9;jgetNumberOfDerivatives();++j){ - finalForces[vbase + k] += forcesToApply[tbase + j]; k++; - } - fbase += myvessels[i]->getNumberOfDerivatives() - 9; - tbase += myvessels[i]->getNumberOfDerivatives(); + for(unsigned i=vbase; igetNumberOfDerivatives()-9; ++j) { + finalForces[fbase + j] = forcesToApply[tbase + j]; + } + unsigned k=0; + for(unsigned j=myvessels[i]->getNumberOfDerivatives()-9; jgetNumberOfDerivatives(); ++j) { + finalForces[vbase + k] += forcesToApply[tbase + j]; k++; + } + fbase += myvessels[i]->getNumberOfDerivatives() - 9; + tbase += myvessels[i]->getNumberOfDerivatives(); } // And set the final forces on the atoms setForcesOnAtoms( finalForces ); // Reset everything for next regular loop - in_apply=false; + in_apply=false; } } diff --git a/src/analysis/LandmarkRegister.cpp b/src/analysis/LandmarkRegister.cpp index 32cc946d5d..0b3a6e4f7a 100644 --- a/src/analysis/LandmarkRegister.cpp +++ b/src/analysis/LandmarkRegister.cpp @@ -22,45 +22,45 @@ #include "LandmarkRegister.h" #include -namespace PLMD{ -namespace analysis{ +namespace PLMD { +namespace analysis { -LandmarkRegister::~LandmarkRegister(){ - if(m.size()>0){ +LandmarkRegister::~LandmarkRegister() { + if(m.size()>0) { std::string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: ReferenceConfiguration "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -LandmarkRegister& landmarkRegister(){ +LandmarkRegister& landmarkRegister() { static LandmarkRegister ans; return ans; } -void LandmarkRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void LandmarkRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void LandmarkRegister::add( std::string type, creator_pointer f ){ +void LandmarkRegister::add( std::string type, creator_pointer f ) { plumed_massert(m.count(type)==0,"type has already been registered"); m.insert(std::pair(type,f)); } -bool LandmarkRegister::check(std::string type){ +bool LandmarkRegister::check(std::string type) { if( m.count(type)>0 ) return true; return false; } -LandmarkSelectionBase* LandmarkRegister::create( const LandmarkSelectionOptions& lo ){ +LandmarkSelectionBase* LandmarkRegister::create( const LandmarkSelectionOptions& lo ) { LandmarkSelectionBase* lselect; - if( check(lo.words[0]) ){ - lselect=m[lo.words[0]](lo); - lselect->checkRead(); + if( check(lo.words[0]) ) { + lselect=m[lo.words[0]](lo); + lselect->checkRead(); } else lselect=NULL; return lselect; } diff --git a/src/analysis/LandmarkRegister.h b/src/analysis/LandmarkRegister.h index e17c9b2abd..dd4c5d38d9 100644 --- a/src/analysis/LandmarkRegister.h +++ b/src/analysis/LandmarkRegister.h @@ -28,13 +28,13 @@ #include #include "LandmarkSelectionBase.h" -namespace PLMD{ +namespace PLMD { class PDB; -namespace analysis{ +namespace analysis { -class LandmarkRegister{ +class LandmarkRegister { private: /// Pointer to a function which, given the type for a ReferenceConfiguration, creates it typedef LandmarkSelectionBase*(*creator_pointer)(const LandmarkSelectionOptions&); diff --git a/src/analysis/LandmarkSelectionBase.cpp b/src/analysis/LandmarkSelectionBase.cpp index 24df3c1d1e..5bd8f7e60f 100644 --- a/src/analysis/LandmarkSelectionBase.cpp +++ b/src/analysis/LandmarkSelectionBase.cpp @@ -26,88 +26,88 @@ namespace PLMD { namespace analysis { LandmarkSelectionOptions::LandmarkSelectionOptions( const std::vector& input, AnalysisWithLandmarks* myanalysis ): -words(input), -action(myanalysis) + words(input), + action(myanalysis) { } LandmarkSelectionBase::LandmarkSelectionBase( const LandmarkSelectionOptions& lo ): -style(lo.words[0]), -input(lo.words), -action(lo.action) + style(lo.words[0]), + input(lo.words), + action(lo.action) { input.erase( input.begin() ); - if( style=="ALL" ){ - novoronoi=true; + if( style=="ALL" ) { + novoronoi=true; } else { - parse("N",nlandmarks); - parseFlag("NOVORONOI",novoronoi); + parse("N",nlandmarks); + parseFlag("NOVORONOI",novoronoi); } parseFlag("IGNORE_WEIGHTS",noweights); } -LandmarkSelectionBase::~LandmarkSelectionBase(){ +LandmarkSelectionBase::~LandmarkSelectionBase() { } -void LandmarkSelectionBase::parseFlag(const std::string& key, bool& t){ +void LandmarkSelectionBase::parseFlag(const std::string& key, bool& t) { Tools::parseFlag(input,key,t); } void LandmarkSelectionBase::checkRead() const { - if(!input.empty()){ - std::string msg="cannot understand the following words from landmark selection input : "; - for(unsigned i=0;igetWeight(iframe); } -double LandmarkSelectionBase::getDistanceBetweenFrames( const unsigned& iframe, const unsigned& jframe ){ +double LandmarkSelectionBase::getDistanceBetweenFrames( const unsigned& iframe, const unsigned& jframe ) { return distance( action->getPbc(), action->getArguments(), action->data[iframe], action->data[jframe], false ); } -void LandmarkSelectionBase::selectFrame( const unsigned& iframe, MultiReferenceBase* myframes){ +void LandmarkSelectionBase::selectFrame( const unsigned& iframe, MultiReferenceBase* myframes) { plumed_assert( myframes->getNumberOfReferenceFrames()copyFrame( action->data[iframe] ); } -void LandmarkSelectionBase::selectLandmarks( MultiReferenceBase* myframes ){ +void LandmarkSelectionBase::selectLandmarks( MultiReferenceBase* myframes ) { // Select landmarks myframes->clearFrames(); select( myframes ); plumed_assert( myframes->getNumberOfReferenceFrames()==nlandmarks ); - // Now calculate voronoi weights - if( !novoronoi ){ - unsigned rank=action->comm.Get_rank(); - unsigned size=action->comm.Get_size(); - std::vector weights( nlandmarks, 0.0 ); - for(unsigned i=rank;idata.size();i+=size){ - unsigned closest=0; - double mindist=distance( action->getPbc(), action->getArguments(), action->data[i], myframes->getFrame(0), false ); - for(unsigned j=1;jgetPbc(), action->getArguments(), action->data[i], myframes->getFrame(j), false ); - if( distcomm.Get_rank(); + unsigned size=action->comm.Get_size(); + std::vector weights( nlandmarks, 0.0 ); + for(unsigned i=rank; idata.size(); i+=size) { + unsigned closest=0; + double mindist=distance( action->getPbc(), action->getArguments(), action->data[i], myframes->getFrame(0), false ); + for(unsigned j=1; jgetPbc(), action->getArguments(), action->data[i], myframes->getFrame(j), false ); + if( distcomm.Sum( &weights[0], weights.size() ); - myframes->setWeights( weights ); + weights[closest] += getWeightOfFrame(i); + } + action->comm.Sum( &weights[0], weights.size() ); + myframes->setWeights( weights ); } } diff --git a/src/analysis/LandmarkSelectionBase.h b/src/analysis/LandmarkSelectionBase.h index b2deb5c578..a8300ff107 100644 --- a/src/analysis/LandmarkSelectionBase.h +++ b/src/analysis/LandmarkSelectionBase.h @@ -28,9 +28,9 @@ namespace PLMD { namespace analysis { -class LandmarkSelectionOptions{ -friend class LandmarkRegister; -friend class LandmarkSelectionBase; +class LandmarkSelectionOptions { + friend class LandmarkRegister; + friend class LandmarkSelectionBase; private: std::vector words; AnalysisWithLandmarks* action; @@ -39,8 +39,8 @@ friend class LandmarkSelectionBase; }; class LandmarkSelectionBase { -friend class AnalysisWithLandmarks; -friend class CopyAllFrames; + friend class AnalysisWithLandmarks; + friend class CopyAllFrames; private: /// Name of the method we are using for landmark selection std::string style; @@ -57,9 +57,9 @@ friend class CopyAllFrames; unsigned getNumberOfLandmarks() const ; /// Return the communicator Communicator& getCommunicator(); -/// Read a keywords from the input +/// Read a keywords from the input template - void parse(const std::string& ,T& ); + void parse(const std::string&,T& ); /// Read a flag from the input void parseFlag(const std::string& key, bool& t); /// Get the number of frames in the underlying action @@ -67,9 +67,9 @@ friend class CopyAllFrames; /// Get the weight of the ith frame double getWeightOfFrame( const unsigned& ); /// Calculate the distance between the ith and jth frames - double getDistanceBetweenFrames( const unsigned& , const unsigned& ); + double getDistanceBetweenFrames( const unsigned&, const unsigned& ); /// Transfer frame i in the underlying action to the object we are going to analyze - void selectFrame( const unsigned& , MultiReferenceBase* ); + void selectFrame( const unsigned&, MultiReferenceBase* ); public: explicit LandmarkSelectionBase( const LandmarkSelectionOptions& lo ); virtual ~LandmarkSelectionBase(); @@ -78,7 +78,7 @@ friend class CopyAllFrames; /// Return a description of the landmark selection protocol std::string description(); /// Overwrite this to have a more descriptive output - virtual std::string rest_of_description(){ return ""; }; + virtual std::string rest_of_description() { return ""; }; /// Actually do landmark selection void selectLandmarks( MultiReferenceBase* ); virtual void select( MultiReferenceBase* )=0; @@ -90,7 +90,7 @@ unsigned LandmarkSelectionBase::getNumberOfLandmarks() const { } inline -Communicator& LandmarkSelectionBase::getCommunicator(){ +Communicator& LandmarkSelectionBase::getCommunicator() { return action->comm; } @@ -100,7 +100,7 @@ unsigned LandmarkSelectionBase::getNumberOfFrames() const { } template -void LandmarkSelectionBase::parse( const std::string& key, T& t ){ +void LandmarkSelectionBase::parse( const std::string& key, T& t ) { bool found=Tools::parse(input,key,t); if(!found) plumed_merror("landmark seleciton style " + style + " requires " + key + " keyword"); } diff --git a/src/analysis/PCA.cpp b/src/analysis/PCA.cpp index d338b5b8a9..5b31a04faa 100644 --- a/src/analysis/PCA.cpp +++ b/src/analysis/PCA.cpp @@ -28,32 +28,32 @@ #include "core/ActionRegister.h" //+PLUMEDOC DIMRED PCA -/* +/* Perform principal component analysis (PCA) using either the positions of the atoms a large number of collective variables as input. -Principal component analysis is a statistical technique that uses an orthogonal transformation to convert a set of observations of +Principal component analysis is a statistical technique that uses an orthogonal transformation to convert a set of observations of poorly correlated variables into a set of linearly uncorrelated variables. You can read more about the specifics of this technique here: https://en.wikipedia.org/wiki/Principal_component_analysis -When used with molecular dynamics simulations a set of frames taken from the trajectory, \f$\{X_i\}\f$, or the values of -a number of collective variables which are calculated from the trajectory frames are used as input. In this second instance your +When used with molecular dynamics simulations a set of frames taken from the trajectory, \f$\{X_i\}\f$, or the values of +a number of collective variables which are calculated from the trajectory frames are used as input. In this second instance your input to the PCA analysis algorithm is thus a set of high-dimensional vectors of collective variables. However, if -collective variables are calculated from the positions of the atoms or if the positions are used directly the assumption is that -this input trajectory is a set of poorly correlated (high-dimensional) vectors. After principal component analysis has been -performed the output is a set of orthogonal vectors that describe the directions in which the largest motions have been seen. +collective variables are calculated from the positions of the atoms or if the positions are used directly the assumption is that +this input trajectory is a set of poorly correlated (high-dimensional) vectors. After principal component analysis has been +performed the output is a set of orthogonal vectors that describe the directions in which the largest motions have been seen. In other words, principal component analysis provides a method for lowering the dimensionality of the data contained in a trajectory. -These output directions are some linear combination of the \f$x\f$, \f$y\f$ and \f$z\f$ positions if the positions were used as input +These output directions are some linear combination of the \f$x\f$, \f$y\f$ and \f$z\f$ positions if the positions were used as input or some linear combination of the input collective variables if a high-dimensional vector of collective variables was used as input. -As explained on the Wikipedia page you must calculate the average and covariance for each of the input coordinates. In other words, you must -calculate the average structure and the amount the system fluctuates around this average structure. The problem in doing so when the -\f$x\f$, \f$y\f$ and \f$z\f$ coordinates of a molecule are used as input is that the majority of the changes in the positions of the +As explained on the Wikipedia page you must calculate the average and covariance for each of the input coordinates. In other words, you must +calculate the average structure and the amount the system fluctuates around this average structure. The problem in doing so when the +\f$x\f$, \f$y\f$ and \f$z\f$ coordinates of a molecule are used as input is that the majority of the changes in the positions of the atoms comes from the translational and rotational degrees of freedom of the molecule. The first six principal components will thus, most likely, -be uninteresting. Consequently, to remedy this problem PLUMED provides the functionality to perform an RMSD alignment of the all the structures -to be analysed to the first frame in the trajectory. This can be used to effectively remove translational and/or rotational motions from -consideration. The resulting principal components thus describe vibrational motions of the molecule. +be uninteresting. Consequently, to remedy this problem PLUMED provides the functionality to perform an RMSD alignment of the all the structures +to be analysed to the first frame in the trajectory. This can be used to effectively remove translational and/or rotational motions from +consideration. The resulting principal components thus describe vibrational motions of the molecule. -If you wish to calculate the projection of a trajectory on a set of principal components calculated from this PCA action then the output can be +If you wish to calculate the projection of a trajectory on a set of principal components calculated from this PCA action then the output can be used as input for the \ref PCAVARS action. \par Examples @@ -70,10 +70,10 @@ PCA METRIC=OPTIMAL ATOMS=1-22 STRIDE=1 USE_ALL_DATA NLOW_DIM=2 OFILE=pca-comp.pd The following input instructs PLUMED to perform a principal component analysis in which the covariance matrix is calculated from chnages in the six distances seen in the previous lines. Notice that here the TYPE=EUCLIDEAN keyword is used to indicate that no alighment has to be done when calculating the various elements of the covariance matrix from the input vectors. In this calculation the first two principal components will be output to a file called pca-comp.pdb. -Trajectory frames will be collected every five steps and the PCA calculation is performed every 1000 steps. Consequently, if you run a 2000 step simulation the +Trajectory frames will be collected every five steps and the PCA calculation is performed every 1000 steps. Consequently, if you run a 2000 step simulation the PCA analysis will be performed twice. The REWEIGHT_BIAS keyword in this input tells PLUMED that rather that ascribing a weight of one to each of the frames -when calculating averages and covariances a reweighting should be performed based and each frames' weight in these calculations should be determined based on -the current value of the instantaneous bias (see \ref REWEIGHT_BIAS). +when calculating averages and covariances a reweighting should be performed based and each frames' weight in these calculations should be determined based on +the current value of the instantaneous bias (see \ref REWEIGHT_BIAS). \verbatim d1: DISTANCE ATOMS=1,2 @@ -107,27 +107,27 @@ class PCA : public Analysis { explicit PCA(const ActionOptions&ao); ~PCA(); void performAnalysis(); - void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); } + void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); } }; PLUMED_REGISTER_ACTION(PCA,"PCA") -void PCA::registerKeywords( Keywords& keys ){ +void PCA::registerKeywords( Keywords& keys ) { Analysis::registerKeywords( keys ); keys.add("compulsory","NLOW_DIM","number of PCA coordinates required"); keys.add("compulsory","OFILE","the file on which to output the eigenvectors"); } PCA::PCA(const ActionOptions&ao): -PLUMED_ANALYSIS_INIT(ao) + PLUMED_ANALYSIS_INIT(ao) { // Setup reference configuration log.printf(" performing PCA analysis using %s metric \n", getMetricName().c_str() ); myref = metricRegister().create( getMetricName() ); std::vector argnames( getNumberOfArguments() ); - for(unsigned i=0;iisPeriodic() ) error("cannot run PCA with periodic variables"); - argnames[i] = getArguments()[i]->getName(); + for(unsigned i=0; iisPeriodic() ) error("cannot run PCA with periodic variables"); + argnames[i] = getArguments()[i]->getName(); } myref->setNamesAndAtomNumbers( getAbsoluteIndexes(), argnames ); @@ -136,74 +136,74 @@ PLUMED_ANALYSIS_INIT(ao) if( getNumberOfArguments()>0 ) arg_eigv.resize( ndim, getNumberOfArguments() ); // Read stuff for output file - parseOutputFile("OFILE",ofilename); + parseOutputFile("OFILE",ofilename); checkRead(); } -PCA::~PCA(){ +PCA::~PCA() { delete myref; } -void PCA::performAnalysis(){ +void PCA::performAnalysis() { // Align everything to the first frame MultiValue myval( 1, getNumberOfArguments() + 3*getNumberOfAtoms() + 9 ); ReferenceValuePack mypack( getNumberOfArguments(), getNumberOfAtoms(), myval ); - for(unsigned i=0;isetupPCAStorage ( mypack ); // Create some arrays to store the average position std::vector sarg( getNumberOfArguments(), 0 ); std::vector spos( getNumberOfAtoms() ); - for(unsigned i=0;icalc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); - // Accumulate average displacement of arguments (Here PBC could do fucked up things - really needs Berry Phase ) GAT - for(unsigned j=0;jcalc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); + // Accumulate average displacement of arguments (Here PBC could do fucked up things - really needs Berry Phase ) GAT + for(unsigned j=0; jgetReferenceArguments()[j]; - for(unsigned j=0;jgetReferencePositions()[j]; + double inorm = 1.0 / norm ; + for(unsigned j=0; jgetReferenceArguments()[j]; + for(unsigned j=0; jgetReferencePositions()[j]; // And set the reference configuration - std::vector empty( getNumberOfArguments(), 1.0 ); myref->setReferenceConfig( spos, sarg, empty ); + std::vector empty( getNumberOfArguments(), 1.0 ); myref->setReferenceConfig( spos, sarg, empty ); // Now accumulate the covariance unsigned narg=getNumberOfArguments(); Matrix covar( getNumberOfArguments()+3*getNumberOfAtoms(), getNumberOfArguments()+3*getNumberOfAtoms() ); covar=0; - for(unsigned i=0;icalc( spos, getPbc(), getArguments(), sarg, mypack, true ); - double d = data[0]->calc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); - for(unsigned jarg=0;jarggetReferenceArguments()[jarg] - sarg[jarg]; - for(unsigned karg=0;karggetReferenceArguments()[karg] - sarg[karg]; - covar( jarg, karg ) += 0.25*getWeight(i)*jarg_d*karg_d; // mypack.getArgumentDerivative(jarg)*mypack.getArgumentDerivative(karg); - } + for(unsigned i=0; icalc( spos, getPbc(), getArguments(), sarg, mypack, true ); + double d = data[0]->calc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); + for(unsigned jarg=0; jarggetReferenceArguments()[jarg] - sarg[jarg]; + for(unsigned karg=0; karggetReferenceArguments()[karg] - sarg[karg]; + covar( jarg, karg ) += 0.25*getWeight(i)*jarg_d*karg_d; // mypack.getArgumentDerivative(jarg)*mypack.getArgumentDerivative(karg); } - for(unsigned jat=0;jatgetReferencePositions()[jat][jc] - spos[jat][jc]; - for(unsigned kat=0;katgetReferencePositions()[kat][kc] - spos[kat][kc]; - covar( narg+3*jat + jc, narg+3*kat + kc ) += getWeight(i)*jdisplace*kdisplace; - } - } - } + } + for(unsigned jat=0; jatgetReferencePositions()[jat][jc] - spos[jat][jc]; + for(unsigned kat=0; katgetReferencePositions()[kat][kc] - spos[kat][kc]; + covar( narg+3*jat + jc, narg+3*kat + kc ) += getWeight(i)*jdisplace*kdisplace; + } + } } + } } // Normalise - for(unsigned i=0;iprint( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); + myref->print( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); // Store and print the eigenvectors std::vector tmp_atoms( getNumberOfAtoms() ); std::vector tmp_args( getNumberOfArguments() ); Direction* tref = metricRegister().create( "DIRECTION" ); tref->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); - for(unsigned dim=0;dimsetDirection( tmp_atoms, tmp_args ); - tref->print( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); - } - // Close the output file + for(unsigned dim=0; dimsetDirection( tmp_atoms, tmp_args ); + tref->print( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); + } + // Close the output file delete tref; ofile.close(); } diff --git a/src/analysis/SelectAllFrames.cpp b/src/analysis/SelectAllFrames.cpp index 56ea3751fc..8f61b7305d 100644 --- a/src/analysis/SelectAllFrames.cpp +++ b/src/analysis/SelectAllFrames.cpp @@ -34,13 +34,13 @@ class CopyAllFrames : public LandmarkSelectionBase { PLUMED_REGISTER_LANDMARKS(CopyAllFrames,"ALL") CopyAllFrames::CopyAllFrames( const LandmarkSelectionOptions& lo ): -LandmarkSelectionBase(lo) + LandmarkSelectionBase(lo) { } -void CopyAllFrames::select( MultiReferenceBase* myframes ){ +void CopyAllFrames::select( MultiReferenceBase* myframes ) { nlandmarks = action->getNumberOfDataPoints(); - for(unsigned i=0;i to; std::vector min; std::vector kappa; @@ -96,7 +96,7 @@ class ABMD : public Bias{ PLUMED_REGISTER_ACTION(ABMD,"ABMD") -void ABMD::registerKeywords(Keywords& keys){ +void ABMD::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","TO","The array of target values"); @@ -106,18 +106,18 @@ void ABMD::registerKeywords(Keywords& keys){ keys.add("optional","SEED","Array of seeds for the white noise (add a temperature to the ABMD)"); keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); keys.addOutputComponent("_min","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - " These quantities will be named with the arguments of the bias followed by " - "the character string _min. These quantities tell the user the minimum value assumed by rho_m(t)."); + " These quantities will be named with the arguments of the bias followed by " + "the character string _min. These quantities tell the user the minimum value assumed by rho_m(t)."); } ABMD::ABMD(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -to(getNumberOfArguments(),0.0), -min(getNumberOfArguments(),-1.0), -kappa(getNumberOfArguments(),0.0), -temp(getNumberOfArguments(),0.0), -seed(getNumberOfArguments(),time(0)), -random(getNumberOfArguments()) + PLUMED_BIAS_INIT(ao), + to(getNumberOfArguments(),0.0), + min(getNumberOfArguments(),-1.0), + kappa(getNumberOfArguments(),0.0), + temp(getNumberOfArguments(),0.0), + seed(getNumberOfArguments(),time(0)), + random(getNumberOfArguments()) { // Note : parseVector will check that number of arguments is correct parseVector("KAPPA",kappa); @@ -130,35 +130,35 @@ random(getNumberOfArguments()) checkRead(); log.printf(" min"); - for(unsigned i=0;igetName()+"_min"; - addComponent(str_min); componentIsNotPeriodic(str_min); - if(min[i]!=-1.0) getPntrToComponent(str_min)->set(min[i]); + for(unsigned i=0; igetName()+"_min"; + addComponent(str_min); componentIsNotPeriodic(str_min); + if(min[i]!=-1.0) getPntrToComponent(str_min)->set(min[i]); } - for(unsigned i=0;i0) { + if(diff>0) { noise = 2.*random[i].Gaussian()*diff; if(cv2<=diff) { diff=0.; temp[i]=0.; } } @@ -166,11 +166,11 @@ void ABMD::calculate(){ // min < 0 means that the variable has not been used in the input file, so the current position of the CV is used // cv2 < min means that the collective variable is nearer to the target value than at any other previous time so // min is set to the CV value - if(min[i]<0.||cv21){ + if(getStride()>1) { log<<" multiple time step "<getPntrToAction())->turnOnDerivatives(); + for(unsigned i=0; igetPntrToAction())->turnOnDerivatives(); } turnOnDerivatives(); } -void Bias::registerKeywords( Keywords& keys ){ +void Bias::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithValue::registerKeywords(keys); @@ -57,13 +57,13 @@ void Bias::registerKeywords( Keywords& keys ){ keys.addOutputComponent("bias","default","the instantaneous value of the bias potential"); } -void Bias::apply(){ +void Bias::apply() { const unsigned noa=getNumberOfArguments(); const unsigned ncp=getNumberOfComponents(); - if(onStep()) { + if(onStep()) { double gstr = static_cast(getStride()); - for(unsigned i=0;iaddForce(gstr*outputForces[i]); } } @@ -73,18 +73,18 @@ void Bias::apply(){ std::vector forces(noa); bool at_least_one_forced=false; - for(unsigned i=0;iapplyForce(forces)){ - at_least_one_forced=true; - for(unsigned j=0;japplyForce(forces)) { + at_least_one_forced=true; + for(unsigned j=0; jaddForce(f[i]); - } + if(at_least_one_forced) for(unsigned i=0; iaddForce(f[i]); + } } diff --git a/src/bias/Bias.h b/src/bias/Bias.h index 551372dec8..25776466f4 100644 --- a/src/bias/Bias.h +++ b/src/bias/Bias.h @@ -28,12 +28,12 @@ #define PLUMED_BIAS_INIT(ao) Action(ao),Bias(ao) -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { /** \ingroup INHERIT -This is the abstract base class to use for implementing new simulation biases, within it there is +This is the abstract base class to use for implementing new simulation biases, within it there is information as to how to go about implementing a new bias. */ @@ -59,18 +59,18 @@ class Bias : }; inline -void Bias::setOutputForce(int i,double f){ +void Bias::setOutputForce(int i,double f) { outputForces[i]=f; valueBias->addDerivative(i,-f); } inline -void Bias::setBias(double bias){ - valueBias->set(bias); +void Bias::setBias(double bias) { + valueBias->set(bias); } inline -unsigned Bias::getNumberOfDerivatives(){ +unsigned Bias::getNumberOfDerivatives() { return getNumberOfArguments(); } diff --git a/src/bias/BiasValue.cpp b/src/bias/BiasValue.cpp index 4d5e3e25b5..3e77621a55 100644 --- a/src/bias/BiasValue.cpp +++ b/src/bias/BiasValue.cpp @@ -26,10 +26,10 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { -//+PLUMEDOC BIAS BIASVALUE +//+PLUMEDOC BIAS BIASVALUE /* Takes the value of one variable and use it as a bias @@ -40,7 +40,7 @@ to some collective variable then using the value of this function directly as a \par Examples The following input tells plumed to use the value of the distance between atoms 3 and 5 -and the value of the distance between atoms 2 and 4 as biases. +and the value of the distance between atoms 2 and 4 as biases. It then tells plumed to print the energy of the restraint \verbatim DISTANCE ATOMS=3,5 LABEL=d1 @@ -50,13 +50,13 @@ PRINT ARG=d1,d2,b.d1,b.d2 \endverbatim (See also \ref DISTANCE and \ref PRINT). -Another thing one can do is asking one system to follow +Another thing one can do is asking one system to follow a circle in sin/cos according a time dependence \verbatim t: TIME # this just print cos and sin of time -cos: MATHEVAL ARG=t VAR=t FUNC=cos(t) PERIODIC=NO +cos: MATHEVAL ARG=t VAR=t FUNC=cos(t) PERIODIC=NO sin: MATHEVAL ARG=t VAR=t FUNC=sin(t) PERIODIC=NO c1: COM ATOMS=1,2 c2: COM ATOMS=3,4 @@ -65,11 +65,11 @@ PRINT ARG=t,cos,sin,d.x,d.y,d.z STRIDE=1 FILE=colvar FMT=%8.4f # this calculates sine and cosine of a projected component of distance mycos: MATHEVAL ARG=d.x,d.y VAR=x,y FUNC=x/sqrt(x*x+y*y) PERIODIC=NO mysin: MATHEVAL ARG=d.x,d.y VAR=x,y FUNC=y/sqrt(x*x+y*y) PERIODIC=NO -# this creates a moving spring so that the system follows a circle-like dynamics +# this creates a moving spring so that the system follows a circle-like dynamics # but it is not a bias, it is a simple value now vv1: MATHEVAL ARG=mycos,mysin,cos,sin VAR=mc,ms,c,s FUNC=100*((mc-c)^2+(ms-s)^2) PERIODIC=NO -# this takes the value calculated with matheval and uses as a bias -cc: BIASVALUE ARG=vv1 +# this takes the value calculated with matheval and uses as a bias +cc: BIASVALUE ARG=vv1 # some printout PRINT ARG=t,cos,sin,d.x,d.y,d.z,mycos,mysin,cc.bias.vv1 STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim @@ -79,7 +79,7 @@ PRINT ARG=t,cos,sin,d.x,d.y,d.z,mycos,mysin,cc.bias.vv1 STRIDE=1 FILE=colvar FMT */ //+ENDPLUMEDOC -class BiasValue : public Bias{ +class BiasValue : public Bias { public: explicit BiasValue(const ActionOptions&); void calculate(); @@ -88,31 +88,31 @@ class BiasValue : public Bias{ PLUMED_REGISTER_ACTION(BiasValue,"BIASVALUE") -void BiasValue::registerKeywords(Keywords& keys){ +void BiasValue::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); // Should be _bias below keys.addOutputComponent("_bias","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "these quantities will named with the arguments of the bias followed by " - "the character string _bias. These quantities tell the user how much the bias is " - "due to each of the colvars."); + "these quantities will named with the arguments of the bias followed by " + "the character string _bias. These quantities tell the user how much the bias is " + "due to each of the colvars."); } BiasValue::BiasValue(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao) + PLUMED_BIAS_INIT(ao) { checkRead(); - // add one bias for each argument - for(unsigned i=0;igetName()+"_bias"; addComponent(ss); componentIsNotPeriodic(ss); } } -void BiasValue::calculate(){ +void BiasValue::calculate() { double bias=0.0; - for(unsigned i=0;iset(val); setOutputForce(i,-1.); bias+=val; diff --git a/src/bias/ExtendedLagrangian.cpp b/src/bias/ExtendedLagrangian.cpp index 1b89116a20..85de570dd5 100644 --- a/src/bias/ExtendedLagrangian.cpp +++ b/src/bias/ExtendedLagrangian.cpp @@ -31,8 +31,8 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS EXTENDED_LAGRANGIAN /* @@ -114,7 +114,7 @@ PRINT STRIDE=10 ARG=phi,psi,ex.phi_fict,ex.psi_fict FILE=COLVAR */ //+ENDPLUMEDOC -class ExtendedLagrangian : public Bias{ +class ExtendedLagrangian : public Bias { bool firsttime; std::vector fict; std::vector vfict; @@ -136,35 +136,35 @@ class ExtendedLagrangian : public Bias{ PLUMED_REGISTER_ACTION(ExtendedLagrangian,"EXTENDED_LAGRANGIAN") -void ExtendedLagrangian::registerKeywords(Keywords& keys){ - Bias::registerKeywords(keys); - keys.use("ARG"); - keys.add("compulsory","KAPPA","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); - keys.add("compulsory","TAU","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); - keys.add("compulsory","FRICTION","0.0","add a friction to the variable"); - keys.add("optional","TEMP","the system temperature - needed when FRICTION is present. If not provided will be taken from MD code (if available)"); - componentsAreNotOptional(keys); - keys.addOutputComponent("_fict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _tilde. It is possible to add forces on these variable."); - keys.addOutputComponent("_vfict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _tilde. It is NOT possible to add forces on these variable."); +void ExtendedLagrangian::registerKeywords(Keywords& keys) { + Bias::registerKeywords(keys); + keys.use("ARG"); + keys.add("compulsory","KAPPA","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); + keys.add("compulsory","TAU","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); + keys.add("compulsory","FRICTION","0.0","add a friction to the variable"); + keys.add("optional","TEMP","the system temperature - needed when FRICTION is present. If not provided will be taken from MD code (if available)"); + componentsAreNotOptional(keys); + keys.addOutputComponent("_fict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " + "These quantities will named with the arguments of the bias followed by " + "the character string _tilde. It is possible to add forces on these variable."); + keys.addOutputComponent("_vfict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " + "These quantities will named with the arguments of the bias followed by " + "the character string _tilde. It is NOT possible to add forces on these variable."); } ExtendedLagrangian::ExtendedLagrangian(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -firsttime(true), -fict(getNumberOfArguments(),0.0), -vfict(getNumberOfArguments(),0.0), -vfict_laststep(getNumberOfArguments(),0.0), -ffict(getNumberOfArguments(),0.0), -kappa(getNumberOfArguments(),0.0), -tau(getNumberOfArguments(),0.0), -friction(getNumberOfArguments(),0.0), -fictValue(getNumberOfArguments(),NULL), -vfictValue(getNumberOfArguments(),NULL), -kbt(0.0) + PLUMED_BIAS_INIT(ao), + firsttime(true), + fict(getNumberOfArguments(),0.0), + vfict(getNumberOfArguments(),0.0), + vfict_laststep(getNumberOfArguments(),0.0), + ffict(getNumberOfArguments(),0.0), + kappa(getNumberOfArguments(),0.0), + tau(getNumberOfArguments(),0.0), + friction(getNumberOfArguments(),0.0), + fictValue(getNumberOfArguments(),NULL), + vfictValue(getNumberOfArguments(),NULL), + kbt(0.0) { parseVector("TAU",tau); parseVector("FRICTION",friction); @@ -176,19 +176,19 @@ kbt(0.0) checkRead(); log.printf(" with harmonic force constant"); - for(unsigned i=0;i0.0) hasFriction=true; + for(unsigned i=0; i0.0) hasFriction=true; - if(hasFriction){ + if(hasFriction) { log.printf(" with friction"); - for(unsigned i=0;igetName()+"_fict"; addComponentWithDerivatives(comp); - if(getPntrToArgument(i)->isPeriodic()){ + if(getPntrToArgument(i)->isPeriodic()) { std::string a,b; getPntrToArgument(i)->getDomain(a,b); componentIsPeriodic(comp,a,b); @@ -212,7 +212,7 @@ kbt(0.0) } log<<" Bibliography "<bringBackInPbc(fict[i]); fictValue[i]->set(fict[i]); vfictValue[i]->set(vfict_laststep[i]); } } -void ExtendedLagrangian::update(){ +void ExtendedLagrangian::update() { double dt=getTimeStep()*getStride(); - for(unsigned i=0;igetDimension()!=getNumberOfArguments()) error("mismatch between dimensionality of input grid and number of arguments"); - for(unsigned i=0;iisPeriodic()!=BiasGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); - } + for(unsigned i=0; iisPeriodic()!=BiasGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); + } } void External::calculate() @@ -154,13 +154,13 @@ void External::calculate() unsigned ncv=getNumberOfArguments(); vector cv(ncv), der(ncv); - for(unsigned i=0;igetValueAndDerivatives(cv,der); setBias(ene); - for(unsigned i=0;i at; std::vector kappa; std::vector exp; @@ -78,7 +78,7 @@ class LWalls : public Bias{ PLUMED_REGISTER_ACTION(LWalls,"LOWER_WALLS") -void LWalls::registerKeywords(Keywords& keys){ +void LWalls::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall."); @@ -90,12 +90,12 @@ void LWalls::registerKeywords(Keywords& keys){ } LWalls::LWalls(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -at(getNumberOfArguments(),0), -kappa(getNumberOfArguments(),0.0), -exp(getNumberOfArguments(),2.0), -eps(getNumberOfArguments(),1.0), -offset(getNumberOfArguments(),0.0) + PLUMED_BIAS_INIT(ao), + at(getNumberOfArguments(),0), + kappa(getNumberOfArguments(),0.0), + exp(getNumberOfArguments(),2.0), + eps(getNumberOfArguments(),1.0), + offset(getNumberOfArguments(),0.0) { // Note sizes of these vectors are automatically checked by parseVector :-) parseVector("OFFSET",offset); @@ -106,28 +106,28 @@ offset(getNumberOfArguments(),0.0) checkRead(); log.printf(" at"); - for(unsigned i=0;iset(totf2); + getPntrToComponent("force2")->set(totf2); } } diff --git a/src/bias/MetaD.cpp b/src/bias/MetaD.cpp index 6e9923aaa1..b586185705 100644 --- a/src/bias/MetaD.cpp +++ b/src/bias/MetaD.cpp @@ -41,14 +41,14 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { -//+PLUMEDOC BIAS METAD +//+PLUMEDOC BIAS METAD /* Used to performed MetaDynamics on one or more collective variables. -In a metadynamics simulations a history dependent bias composed of +In a metadynamics simulations a history dependent bias composed of intermittently added Gaussian functions is added to the potential \cite metad. \f[ @@ -60,10 +60,10 @@ V(\vec{s},t) = \sum_{ k \tau < t} W(k \tau) This potential forces the system away from the kinetic traps in the potential energy surface and out into the unexplored parts of the energy landscape. Information on the Gaussian -functions from which this potential is composed is output to a file called HILLS, which -is used both the restart the calculation and to reconstruct the free energy as a function of the CVs. +functions from which this potential is composed is output to a file called HILLS, which +is used both the restart the calculation and to reconstruct the free energy as a function of the CVs. The free energy can be reconstructed from a metadynamics calculation because the final bias is given -by: +by: \f[ V(\vec{s}) = -F(\vec(s)) @@ -72,10 +72,10 @@ V(\vec{s}) = -F(\vec(s)) During post processing the free energy can be calculated in this way using the \ref sum_hills utility. -In the simplest possible implementation of a metadynamics calculation the expense of a metadynamics -calculation increases with the length of the simulation as one has to, at every step, evaluate +In the simplest possible implementation of a metadynamics calculation the expense of a metadynamics +calculation increases with the length of the simulation as one has to, at every step, evaluate the values of a larger and larger number of Gaussians. To avoid this issue you can -store the bias on a grid. This approach is similar to that proposed in \cite babi08jcp but has the +store the bias on a grid. This approach is similar to that proposed in \cite babi08jcp but has the advantage that the grid spacing is independent on the Gaussian width. Notice that you should provide either the number of bins for every collective variable (GRID_BIN) or @@ -112,19 +112,19 @@ gaussian potential is denoted by one value only that is a Cartesian space (ADAPT (ADAPTIVE=DIFF). Note that a specific integration technique for the deposited gaussians should be used in this case. Check the documentation for utility sum_hills. -With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero -outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only +With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero +outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only to the free energy for s > sw, the history dependent potential is still updated according to the above -equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also -if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the -force on the system in the region s > sw comes from both metadynamics and the force field, in the region -s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that -fluctuates around a stable estimator, equal to the negative of the free energy far enough from the +equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also +if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the +force on the system in the region s > sw comes from both metadynamics and the force field, in the region +s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that +fluctuates around a stable estimator, equal to the negative of the free energy far enough from the boundaries. Note that: - It works only for one-dimensional biases; - It works both with and without GRID; - The interval limit sw in a region where the free energy derivative is not large; -- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should +- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should be used together with a \ref UPPER_WALLS or \ref LOWER_WALLS at sw. As a final note, since version 2.0.2 when the system is outside of the selected interval the force @@ -134,21 +134,21 @@ for replica exchange methods to be computed correctly. Multiple walkers \cite multiplewalkers can also be used. See below the examples. -The c(t) reweighting factor can also be calculated on the fly using the equations -presented in \cite Tiwary_jp504920s. -The expression used to calculate c(t) follows directly from using Eq. 12 in -Eq. 3 in \cite Tiwary_jp504920s and gives smoother results than equivalent Eqs. 13 -and Eqs. 14 in that paper. The c(t) is given by the rct component while the bias -normalized by c(t) is given by the rbias component (rbias=bias-ct) which can be used +The c(t) reweighting factor can also be calculated on the fly using the equations +presented in \cite Tiwary_jp504920s. +The expression used to calculate c(t) follows directly from using Eq. 12 in +Eq. 3 in \cite Tiwary_jp504920s and gives smoother results than equivalent Eqs. 13 +and Eqs. 14 in that paper. The c(t) is given by the rct component while the bias +normalized by c(t) is given by the rbias component (rbias=bias-ct) which can be used to obtain a reweighted histogram. -The calculation of c(t) is enabled by using the keyword REWEIGHTING_NGRID where the grid used for the +The calculation of c(t) is enabled by using the keyword REWEIGHTING_NGRID where the grid used for the calculation is specified. This grid should have a size that is equal or larger than the grid given in GRID_BIN./ -By default c(t) is updated every 50 Gaussian hills but this -can be changed by using the REWEIGHTING_NHILLS keyword. -This option can only be employed together with Well-Tempered Metadynamics and requires that +By default c(t) is updated every 50 Gaussian hills but this +can be changed by using the REWEIGHTING_NHILLS keyword. +This option can only be employed together with Well-Tempered Metadynamics and requires that a grid is used. -Additional material and examples can be also found in the tutorials: +Additional material and examples can be also found in the tutorials: - \ref belfast-6 - \ref belfast-7 @@ -174,7 +174,7 @@ PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \par If you use adaptive Gaussians, with diffusion scheme where you use a Gaussian that should cover the space of 20 timesteps in collective variables. -Note that in this case the histogram correction is needed when summing up hills. +Note that in this case the histogram correction is needed when summing up hills. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 @@ -185,7 +185,7 @@ PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \par If you use adaptive Gaussians, with geometrical scheme where you use a Gaussian that should cover the space of 0.05 nm in Cartesian space. -Note that in this case the histogram correction is needed when summing up hills. +Note that in this case the histogram correction is needed when summing up hills. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 @@ -194,40 +194,40 @@ PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \endverbatim \par -When using adaptive Gaussians you might want to limit how the hills width can change. +When using adaptive Gaussians you might want to limit how the hills width can change. You can use SIGMA_MIN and SIGMA_MAX keywords. -The sigmas should specified in terms of CV so you should use the CV units. +The sigmas should specified in terms of CV so you should use the CV units. Note that if you use a negative number, this means that the limit is not set. -Note also that in this case the histogram correction is needed when summing up hills. +Note also that in this case the histogram correction is needed when summing up hills. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 METAD ... ARG=d1,d2 SIGMA=0.05 HEIGHT=0.3 PACE=500 LABEL=restraint ADAPTIVE=GEOM - SIGMA_MIN=0.2,0.1 SIGMA_MAX=0.5,1.0 -... METAD + SIGMA_MIN=0.2,0.1 SIGMA_MAX=0.5,1.0 +... METAD PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \endverbatim \par -Multiple walkers can be also use as in \cite multiplewalkers -These are enabled by setting the number of walker used, the id of the -current walker which interprets the input file, the directory where the +Multiple walkers can be also use as in \cite multiplewalkers +These are enabled by setting the number of walker used, the id of the +current walker which interprets the input file, the directory where the hills containing files resides, and the frequency to read the other walkers. Here is an example \verbatim DISTANCE ATOMS=3,5 LABEL=d1 METAD ... - ARG=d1 SIGMA=0.05 HEIGHT=0.3 PACE=500 LABEL=restraint + ARG=d1 SIGMA=0.05 HEIGHT=0.3 PACE=500 LABEL=restraint WALKERS_N=10 WALKERS_ID=3 WALKERS_DIR=../ WALKERS_RSTRIDE=100 ... METAD \endverbatim -where WALKERS_N is the total number of walkers, WALKERS_ID is the -id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory -where all the walkers are located. WALKERS_RSTRIDE is the number of step between +where WALKERS_N is the total number of walkers, WALKERS_ID is the +id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory +where all the walkers are located. WALKERS_RSTRIDE is the number of step between one update and the other. Since version 2.2.5, hills files are automatically flushed every WALKERS_RSTRIDE steps. @@ -331,20 +331,20 @@ The number of elements in the RECT array should be equal to the number of replic */ //+ENDPLUMEDOC -class MetaD : public Bias{ +class MetaD : public Bias { private: struct Gaussian { - vector center; - vector sigma; - double height; - bool multivariate; // this is required to discriminate the one dimensional case - vector invsigma; - Gaussian(const vector & center,const vector & sigma,double height, bool multivariate ): - center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma){ - // to avoid troubles from zero element in flexible hills - for(unsigned i=0;i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; - } + vector center; + vector sigma; + double height; + bool multivariate; // this is required to discriminate the one dimensional case + vector invsigma; + Gaussian(const vector & center,const vector & sigma,double height, bool multivariate ): + center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma) { + // to avoid troubles from zero element in flexible hills + for(unsigned i=0; i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; + } }; vector sigma0_; vector sigma0min_; @@ -354,7 +354,7 @@ class MetaD : public Bias{ OFile gridfile_; Grid* BiasGrid_; bool storeOldGrids_; - int wgridstride_; + int wgridstride_; bool grid_; double height0_; double biasf_; @@ -383,11 +383,11 @@ class MetaD : public Bias{ bool doInt_; bool isFirstStep; double reweight_factor; - vector rewf_grid_; + vector rewf_grid_; unsigned rewf_ustride_; double work_; long int last_step_warn_grid; - + void readGaussians(IFile*); bool readChunkOfGaussians(IFile *ifile, unsigned n); void writeGaussian(const Gaussian&,OFile&); @@ -407,15 +407,15 @@ class MetaD : public Bias{ void calculate(); void update(); static void registerKeywords(Keywords& keys); - bool checkNeedsGradients()const{if(adaptive_==FlexibleBin::geometry){return true;}else{return false;}} + bool checkNeedsGradients()const {if(adaptive_==FlexibleBin::geometry) {return true;} else {return false;}} }; PLUMED_REGISTER_ACTION(MetaD,"METAD") -void MetaD::registerKeywords(Keywords& keys){ +void MetaD::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.addOutputComponent("rbias","REWEIGHTING_NGRID","the instantaneous value of the bias normalized using the \\f$c(t)\\f$ reweighting factor [rbias=bias-c(t)]." - "This component can be used to obtain a reweighted histogram."); + "This component can be used to obtain a reweighted histogram."); keys.addOutputComponent("rct","REWEIGHTING_NGRID","the reweighting factor \\f$c(t)\\f$."); keys.addOutputComponent("work","default","accumulator for work"); keys.addOutputComponent("acc","ACCELERATION","the metadynamics acceleration factor"); @@ -436,11 +436,11 @@ void MetaD::registerKeywords(Keywords& keys){ keys.add("optional","GRID_BIN","the number of bins for the grid"); keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); keys.add("optional","REWEIGHTING_NGRID","calculate the c(t) reweighting factor and use that to obtain the normalized bias [rbias=bias-c(t)]." - "Here you should specify the number of grid points required in each dimension." - "The number of grid points should be equal or larger to the number of grid points given in GRID_BIN." - "This method is not compatible with metadynamics not on a grid."); + "Here you should specify the number of grid points required in each dimension." + "The number of grid points should be equal or larger to the number of grid points given in GRID_BIN." + "This method is not compatible with metadynamics not on a grid."); keys.add("optional","REWEIGHTING_NHILLS","how many Gaussian hills should be deposited between calculating the c(t) reweighting factor." - "The default is to do this every 50 hills."); + "The default is to do this every 50 hills."); keys.addFlag("GRID_SPARSE",false,"use a sparse grid to store hills"); keys.addFlag("GRID_NOSPLINE",false,"don't use spline interpolation with grids"); keys.add("optional","GRID_WSTRIDE","write the grid to a file every N steps"); @@ -456,13 +456,13 @@ void MetaD::registerKeywords(Keywords& keys){ keys.add("optional","SIGMA_MAX","the upper bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds "); keys.add("optional","SIGMA_MIN","the lower bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds "); keys.addFlag("WALKERS_MPI",false,"Switch on MPI version of multiple walkers - not compatible with WALKERS_* options other than WALKERS_DIR"); - keys.addFlag("ACCELERATION",false,"Set to TRUE if you want to compute the metadynamics acceleration factor."); + keys.addFlag("ACCELERATION",false,"Set to TRUE if you want to compute the metadynamics acceleration factor."); keys.use("RESTART"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); } -MetaD::~MetaD(){ +MetaD::~MetaD() { if(flexbin) delete flexbin; if(BiasGrid_) delete BiasGrid_; if(TargetGrid_) delete TargetGrid_; @@ -470,86 +470,86 @@ MetaD::~MetaD(){ if(wgridstride_>0) gridfile_.close(); delete [] dp_; // close files - for(int i=0;iisOpen()) ifiles[i]->close(); - delete ifiles[i]; + for(int i=0; iisOpen()) ifiles[i]->close(); + delete ifiles[i]; } } MetaD::MetaD(const ActionOptions& ao): -PLUMED_BIAS_INIT(ao), + PLUMED_BIAS_INIT(ao), // Grid stuff initialization -BiasGrid_(NULL), wgridstride_(0), grid_(false), + BiasGrid_(NULL), wgridstride_(0), grid_(false), // Metadynamics basic parameters -height0_(std::numeric_limits::max()), biasf_(-1.0), dampfactor_(0.0), TargetGrid_(NULL), -kbt_(0.0), -stride_(0), welltemp_(false), + height0_(std::numeric_limits::max()), biasf_(-1.0), dampfactor_(0.0), TargetGrid_(NULL), + kbt_(0.0), + stride_(0), welltemp_(false), // Other stuff -dp_(NULL), adaptive_(FlexibleBin::none), -flexbin(NULL), + dp_(NULL), adaptive_(FlexibleBin::none), + flexbin(NULL), // Multiple walkers initialization -mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), -walkers_mpi(false), mpi_nw_(0), mpi_mw_(0), -acceleration(false), acc(0.0), + mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), + walkers_mpi(false), mpi_nw_(0), mpi_mw_(0), + acceleration(false), acc(0.0), // Interval initialization -uppI_(-1), lowI_(-1), doInt_(false), -isFirstStep(true), -reweight_factor(0.0), -rewf_ustride_(1), -work_(0), -last_step_warn_grid(0) + uppI_(-1), lowI_(-1), doInt_(false), + isFirstStep(true), + reweight_factor(0.0), + rewf_ustride_(1), + work_(0), + last_step_warn_grid(0) { // parse the flexible hills string adaptiveoption; adaptiveoption="NONE"; parse("ADAPTIVE",adaptiveoption); - if(adaptiveoption=="GEOM"){ + if(adaptiveoption=="GEOM") { log.printf(" Uses Geometry-based hills width: sigma must be in distance units and only one sigma is needed\n"); - adaptive_=FlexibleBin::geometry; - } else if(adaptiveoption=="DIFF"){ + adaptive_=FlexibleBin::geometry; + } else if(adaptiveoption=="DIFF") { log.printf(" Uses Diffusion-based hills width: sigma must be in timesteps and only one sigma is needed\n"); - adaptive_=FlexibleBin::diffusion; - } else if(adaptiveoption=="NONE"){ - adaptive_=FlexibleBin::none; + adaptive_=FlexibleBin::diffusion; + } else if(adaptiveoption=="NONE") { + adaptive_=FlexibleBin::none; } else { - error("I do not know this type of adaptive scheme"); + error("I do not know this type of adaptive scheme"); } parse("FMT",fmt); // parse the sigma parseVector("SIGMA",sigma0_); - if(adaptive_==FlexibleBin::none){ - // if you use normal sigma you need one sigma per argument + if(adaptive_==FlexibleBin::none) { + // if you use normal sigma you need one sigma per argument if( sigma0_.size()!=getNumberOfArguments() ) error("number of arguments does not match number of SIGMA parameters"); } else { - // if you use flexible hills you need one sigma - if(sigma0_.size()!=1){ + // if you use flexible hills you need one sigma + if(sigma0_.size()!=1) { error("If you choose ADAPTIVE you need only one sigma according to your choice of type (GEOM/DIFF)"); - } + } // if adaptive then the number must be an integer - if(adaptive_==FlexibleBin::diffusion){ - if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ){ - error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); - } - } + if(adaptive_==FlexibleBin::diffusion) { + if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ) { + error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); + } + } // here evtl parse the sigma min and max values parseVector("SIGMA_MIN",sigma0min_); if(sigma0min_.size()>0 && sigma0min_.size()!=getNumberOfArguments()) { error("the number of SIGMA_MIN values be the same of the number of the arguments"); - } else if(sigma0min_.size()==0) { + } else if(sigma0min_.size()==0) { sigma0min_.resize(getNumberOfArguments()); - for(unsigned i=0;i0 && sigma0max_.size()!=getNumberOfArguments()) { - error("the number of SIGMA_MAX values be the same of the number of the arguments"); - } else if(sigma0max_.size()==0) { + error("the number of SIGMA_MAX values be the same of the number of the arguments"); + } else if(sigma0max_.size()==0) { sigma0max_.resize(getNumberOfArguments()); - for(unsigned i=0;i rect_biasf_; parseVector("RECT",rect_biasf_); - if(rect_biasf_.size()>0){ + if(rect_biasf_.size()>0) { int r=0; if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); @@ -575,32 +575,32 @@ last_step_warn_grid(0) parse("TEMP",temp); if(temp>0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; else kbt_=plumed.getAtoms().getKbT(); - if(biasf_>=1.0){ + if(biasf_>=1.0) { if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with well-tempered metad you must specify it using TEMP"); welltemp_=true; } - if(dampfactor_>0.0){ + if(dampfactor_>0.0) { if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with damped metad you must specify it using TEMP"); } parse("TARGET",targetfilename_); if(targetfilename_.length()>0 && kbt_==0.0) error("with TARGET temperature must be specified"); double tau=0.0; parse("TAU",tau); - if(tau==0.0){ + if(tau==0.0) { if(height0_==std::numeric_limits::max()) error("At least one between HEIGHT and TAU should be specified"); // if tau is not set, we compute it here from the other input parameters if(welltemp_) tau=(kbt_*(biasf_-1.0))/height0_*getTimeStep()*stride_; else if(dampfactor_>0.0) tau=(kbt_*dampfactor_)/height0_*getTimeStep()*stride_; } else { if(height0_!=std::numeric_limits::max()) error("At most one between HEIGHT and TAU should be specified"); - if(welltemp_){ + if(welltemp_) { if(biasf_!=1.0) height0_=(kbt_*(biasf_-1.0))/tau*getTimeStep()*stride_; else height0_=kbt_/tau*getTimeStep()*stride_; // special case for gamma=1 } else if(dampfactor_>0.0) height0_=(kbt_*dampfactor_)/tau*getTimeStep()*stride_; else error("TAU only makes sense in well-tempered or damped metadynamics"); } - + // Grid Stuff vector gmin(getNumberOfArguments()); parseVector("GRID_MIN",gmin); @@ -617,71 +617,71 @@ last_step_warn_grid(0) if(gmin.size()!=gmax.size()) error("GRID_MAX and GRID_MIN should be either present or absent"); if(gspacing.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); if(gbin.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); - if(gmin.size()!=0){ - if(gbin.size()==0 && gspacing.size()==0){ - if(adaptive_==FlexibleBin::none){ + if(gmin.size()!=0) { + if(gbin.size()==0 && gspacing.size()==0) { + if(adaptive_==FlexibleBin::none) { log<<" Binsize not specified, 1/5 of sigma will be be used\n"; plumed_assert(sigma0_.size()==getNumberOfArguments()); gspacing.resize(getNumberOfArguments()); - for(unsigned i=0;i0){grid_=true;} + if(gbin.size()>0) {grid_=true;} parse("GRID_WSTRIDE",wgridstride_); string gridfilename_; - parse("GRID_WFILE",gridfilename_); + parse("GRID_WFILE",gridfilename_); parseFlag("STORE_GRIDS",storeOldGrids_); - if(grid_ && gridfilename_.length()>0){ + if(grid_ && gridfilename_.length()>0) { if(wgridstride_==0 ) error("frequency with which to output grid not specified use GRID_WSTRIDE"); } - if(grid_ && wgridstride_>0){ - if(gridfilename_.length()==0) error("grid filename not specified use GRID_WFILE"); + if(grid_ && wgridstride_>0) { + if(gridfilename_.length()==0) error("grid filename not specified use GRID_WFILE"); } string gridreadfilename_; parse("GRID_RFILE",gridreadfilename_); if(!grid_&&gridfilename_.length()> 0) error("To write a grid you need first to define it!"); if(!grid_&&gridreadfilename_.length()>0) error("To read a grid you need first to define it!"); - - if(grid_){ - parseVector("REWEIGHTING_NGRID",rewf_grid_); - if(rewf_grid_.size()>0 && rewf_grid_.size()!=getNumberOfArguments()){ + + if(grid_) { + parseVector("REWEIGHTING_NGRID",rewf_grid_); + if(rewf_grid_.size()>0 && rewf_grid_.size()!=getNumberOfArguments()) { error("size mismatch for REWEIGHTING_NGRID keyword"); - } else if(rewf_grid_.size()==getNumberOfArguments()){ - for(unsigned j=0;jisPeriodic() ) rewf_grid_[j] += 1; + } else if(rewf_grid_.size()==getNumberOfArguments()) { + for(unsigned j=0; jisPeriodic() ) rewf_grid_[j] += 1; } } if(adaptive_==FlexibleBin::diffusion || adaptive_==FlexibleBin::geometry) warning("reweighting has not been proven to work with adaptive Gaussians"); rewf_ustride_=50; parse("REWEIGHTING_NHILLS",rewf_ustride_); } - if(dampfactor_>0.0){ + if(dampfactor_>0.0) { if(!grid_) error("With DAMPFACTOR you should use grids"); } @@ -716,32 +716,32 @@ last_step_warn_grid(0) log.printf(" Gaussian width "); if (adaptive_==FlexibleBin::diffusion)log.printf(" (Note: The units of sigma are in timesteps) "); if (adaptive_==FlexibleBin::geometry)log.printf(" (Note: The units of sigma are in dist units) "); - for(unsigned i=0;i0){log.printf(" Grid is written on file %s with stride %d\n",gridfilename_.c_str(),wgridstride_);} + if(spline) {log.printf(" Grid uses spline interpolation\n");} + if(sparsegrid) {log.printf(" Grid uses sparse grid\n");} + if(wgridstride_>0) {log.printf(" Grid is written on file %s with stride %d\n",gridfilename_.c_str(),wgridstride_);} } - if(mw_n_>1){ + if(mw_n_>1) { if(walkers_mpi) error("MPI version of multiple walkers is not compatible with filesystem version of multiple walkers"); log.printf(" %d multiple walkers active\n",mw_n_); log.printf(" walker id %d\n",mw_id_); @@ -749,9 +749,9 @@ last_step_warn_grid(0) if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); } else { if(walkers_mpi) { - log.printf(" Multiple walkers active using MPI communnication\n"); + log.printf(" Multiple walkers active using MPI communnication\n"); if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { // Only root of group can communicate with other walkers mpi_nw_=multi_sim_comm.Get_size(); mpi_mw_=multi_sim_comm.Get_rank(); @@ -763,16 +763,16 @@ last_step_warn_grid(0) } } - if( rewf_grid_.size()>0 ){ + if( rewf_grid_.size()>0 ) { addComponent("rbias"); componentIsNotPeriodic("rbias"); - addComponent("rct"); componentIsNotPeriodic("rct"); + addComponent("rct"); componentIsNotPeriodic("rct"); log.printf(" the c(t) reweighting factor will be calculated every %u hills\n",rewf_ustride_); getPntrToComponent("rct")->set(reweight_factor); } addComponent("work"); componentIsNotPeriodic("work"); if(acceleration) { - if(!welltemp_) error("The calculation of the acceleration works only if Well-Tempered Metadynamics is on"); + if(!welltemp_) error("The calculation of the acceleration works only if Well-Tempered Metadynamics is on"); log.printf(" calculation on the fly of the acceleration factor"); addComponent("acc"); componentIsNotPeriodic("acc"); } @@ -781,37 +781,37 @@ last_step_warn_grid(0) dp_ = new double[getNumberOfArguments()]; // initializing and checking grid - if(grid_){ - // check for mesh and sigma size - for(unsigned i=0;i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; - } else { - if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; - } - } - std::string funcl=getLabel() + ".bias"; - if(!sparsegrid){BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} - else{BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} - std::vector actualmin=BiasGrid_->getMin(); - std::vector actualmax=BiasGrid_->getMax(); - for(unsigned i=0;i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; + } else { + if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; + } + } + std::string funcl=getLabel() + ".bias"; + if(!sparsegrid) {BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + else {BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + std::vector actualmin=BiasGrid_->getMin(); + std::vector actualmax=BiasGrid_->getMax(); + for(unsigned i=0; i0){ + if(gridreadfilename_.length()>0) { // read the grid in input, find the keys - IFile gridfile; + IFile gridfile; gridfile.link(*this); - if(gridfile.FileExist(gridreadfilename_)){ + if(gridfile.FileExist(gridreadfilename_)) { gridfile.open(gridreadfilename_); } else { error("The GRID file you want to read: " + gridreadfilename_ + ", cannot be found!"); @@ -820,7 +820,7 @@ last_step_warn_grid(0) BiasGrid_=Grid::create(funcl, getArguments(), gridfile, gmin, gmax, gbin, sparsegrid, spline, true); gridfile.close(); if(BiasGrid_->getDimension()!=getNumberOfArguments()) error("mismatch between dimensionality of input grid and number of arguments"); - for(unsigned i=0;iisPeriodic()!=BiasGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); double a, b; Tools::convert(gmin[i],a); @@ -828,16 +828,16 @@ last_step_warn_grid(0) double mesh=(b-a)/((double)gbin[i]); if(mesh>0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; } - log.printf(" Restarting from %s:",gridreadfilename_.c_str()); + log.printf(" Restarting from %s:",gridreadfilename_.c_str()); if(getRestart()) restartedFromGrid=true; } // initializing and checking grid - if(grid_&&!(gridreadfilename_.length()>0)){ + if(grid_&&!(gridreadfilename_.length()>0)) { // check for adaptive and sigma_min if(sigma0min_.size()==0&&adaptive_!=FlexibleBin::none) error("When using Adaptive Gaussians on a grid SIGMA_MIN must be specified"); // check for mesh and sigma size - for(unsigned i=0;i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; } std::string funcl=getLabel() + ".bias"; - if(!sparsegrid){BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} - else{BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + if(!sparsegrid) {BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + else {BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} std::vector actualmin=BiasGrid_->getMin(); std::vector actualmax=BiasGrid_->getMax(); - for(unsigned i=0;i1) { @@ -878,13 +878,13 @@ last_step_warn_grid(0) } IFile *ifile = new IFile(); ifile->link(*this); - ifiles.push_back(ifile); + ifiles.push_back(ifile); ifilesnames.push_back(fname); - if(ifile->FileExist(fname)){ + if(ifile->FileExist(fname)) { ifile->open(fname); - if(getRestart()&&!restartedFromGrid){ - log.printf(" Restarting from %s:",ifilesnames[i].c_str()); - readGaussians(ifiles[i]); + if(getRestart()&&!restartedFromGrid) { + log.printf(" Restarting from %s:",ifilesnames[i].c_str()); + readGaussians(ifiles[i]); } ifiles[i]->reset(false); // close only the walker own hills file for later writing @@ -901,13 +901,13 @@ last_step_warn_grid(0) // (e.g. in bias exchange with a neutral replica) // see issue #168 on github if(comm.Get_rank()==0 && walkers_mpi) multi_sim_comm.Barrier(); - if(targetfilename_.length()>0){ + if(targetfilename_.length()>0) { IFile gridfile; gridfile.open(targetfilename_); std::string funcl=getLabel() + ".target"; TargetGrid_=Grid::create(funcl,getArguments(),gridfile,false,false,true); gridfile.close(); if(TargetGrid_->getDimension()!=getNumberOfArguments()) error("mismatch between dimensionality of input grid and number of arguments"); - for(unsigned i=0;iisPeriodic()!=TargetGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); } } @@ -916,9 +916,9 @@ last_step_warn_grid(0) if(getRestart() && rewf_grid_.size()>0 ) computeReweightingFactor(); // open grid file for writing - if(wgridstride_>0){ + if(wgridstride_>0) { gridfile_.link(*this); - if(walkers_mpi){ + if(walkers_mpi) { int r=0; if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); @@ -931,7 +931,7 @@ last_step_warn_grid(0) // open hills file for writing hillsOfile_.link(*this); - if(walkers_mpi){ + if(walkers_mpi) { int r=0; if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); @@ -948,14 +948,14 @@ last_step_warn_grid(0) } hillsOfile_.setHeavyFlush(); // output periodicities of variables - for(unsigned i=0;i(p)){ concurrent=true; break; } + for(const auto & p : actionSet) if(dynamic_cast(p)) { concurrent=true; break; } if(concurrent) log<<" You are using concurrent metadynamics\n"; - if(rect_biasf_.size()>0){ - if(walkers_mpi){ + if(rect_biasf_.size()>0) { + if(walkers_mpi) { log<<" You are using RECT in its 'altruistic' implementation\n"; }{ log<<" You are using RECT\n"; @@ -964,22 +964,22 @@ last_step_warn_grid(0) log<<" Bibliography "<1||walkers_mpi) log<0) log<0) log<0 && walkers_mpi) log<0){ + "Hosek, Toulcova, Bortolato, and Spiwok, J. Phys. Chem. B 120, 2209 (2016)"); + if(targetfilename_.length()>0) { log< center(ncv); vector sigma(ncv); double height; - int nhills=0; + int nhills=0; bool multivariate=false; - + std::vector tmpvalues; - for(unsigned j=0;jgetName(), false ) ); - - while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)){; + for(unsigned j=0; jgetName(), false ) ); + + while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)) { + ; nhills++; // note that for gamma=1 we store directly -F - if(welltemp_ && biasf_>1.0){height*=(biasf_-1.0)/biasf_;} + if(welltemp_ && biasf_>1.0) {height*=(biasf_-1.0)/biasf_;} addGaussian(Gaussian(center,sigma,height,multivariate)); - } + } log.printf(" %d Gaussians read\n",nhills); } @@ -1017,18 +1018,19 @@ bool MetaD::readChunkOfGaussians(IFile *ifile, unsigned n) unsigned nhills=0; bool multivariate=false; std::vector tmpvalues; - for(unsigned j=0;jgetName(), false ) ); - - while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)){; + for(unsigned j=0; jgetName(), false ) ); + + while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)) { + ; // note that for gamma=1 we store directly -F - if(welltemp_ && biasf_>1.0) height*=(biasf_-1.0)/biasf_; + if(welltemp_ && biasf_>1.0) height*=(biasf_-1.0)/biasf_; addGaussian(Gaussian(center,sigma,height,multivariate)); - if(nhills==n){ + if(nhills==n) { log.printf(" %u Gaussians read\n",nhills); return true; } nhills++; - } + } log.printf(" %u Gaussians read\n",nhills); return false; } @@ -1037,26 +1039,26 @@ void MetaD::writeGaussian(const Gaussian& hill, OFile&file) { unsigned ncv=getNumberOfArguments(); file.printField("time",getTimeStep()*getStep()); - for(unsigned i=0;i mymatrix(ncv,ncv); unsigned k=0; - for(unsigned i=0;i invmatrix(ncv,ncv); Invert(mymatrix,invmatrix); // enforce symmetry - for(unsigned i=0;i lower(ncv,ncv); cholesky(invmatrix,lower); - // loop in band form - for(unsigned i=0;igetName()+"_"+getPntrToArgument(j)->getName(),lower(j+i,j)); } } } else { hillsOfile_.printField("multivariate","false"); - for(unsigned i=0;igetName(),hill.sigma[i]); } double height=hill.height; // note that for gamma=1 we store directly -F - if(welltemp_ && biasf_>1.0) height*=biasf_/(biasf_-1.0); + if(welltemp_ && biasf_>1.0) height*=biasf_/(biasf_-1.0); file.printField("height",height).printField("biasf",biasf_); if(mw_n_>1) file.printField("clock",int(std::time(0))); file.printField(); @@ -1085,36 +1087,36 @@ void MetaD::writeGaussian(const Gaussian& hill, OFile&file) void MetaD::addGaussian(const Gaussian& hill) { - if(!grid_) hills_.push_back(hill); + if(!grid_) hills_.push_back(hill); else { unsigned ncv=getNumberOfArguments(); vector nneighb=getGaussianSupport(hill); vector neighbors=BiasGrid_->getNeighbors(hill.center,nneighb); vector der(ncv); vector xx(ncv); - if(comm.Get_size()==1){ - for(unsigned i=0;igetPoint(ineigh,xx); double bias=evaluateGaussian(xx,hill,&der[0]); BiasGrid_->addValueAndDerivatives(ineigh,bias,der); - } + } } else { unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); vector allder(ncv*neighbors.size(),0.0); vector allbias(neighbors.size(),0.0); - for(unsigned i=rank;igetPoint(ineigh,xx); allbias[i]=evaluateGaussian(xx,hill,&allder[ncv*i]); } comm.Sum(allbias); comm.Sum(allder); - for(unsigned i=0;iaddValueAndDerivatives(ineigh,allbias[i],der); } } @@ -1124,42 +1126,42 @@ void MetaD::addGaussian(const Gaussian& hill) vector MetaD::getGaussianSupport(const Gaussian& hill) { vector nneigh; - vector cutoff; + vector cutoff; unsigned ncv=getNumberOfArguments(); - // traditional or flexible hill? - if(hill.multivariate){ + // traditional or flexible hill? + if(hill.multivariate) { unsigned k=0; Matrix mymatrix(ncv,ncv); - for(unsigned i=0;i myinv(ncv,ncv); Invert(mymatrix,myinv); Matrix myautovec(ncv,ncv); - vector myautoval(ncv); //should I take this or their square root? + vector myautoval(ncv); //should I take this or their square root? diagMat(myinv,myautoval,myautovec); double maxautoval=0.; - unsigned ind_maxautoval;ind_maxautoval=ncv; - for(unsigned i=0;imaxautoval){maxautoval=myautoval[i];ind_maxautoval=i;} - } - for(unsigned i=0;imaxautoval) {maxautoval=myautoval[i]; ind_maxautoval=i;} + } + for(unsigned i=0; i uppI_ || hill.center[0]-cutoff[0] < lowI_) { + if(doInt_) { + if(hill.center[0]+cutoff[0] > uppI_ || hill.center[0]-cutoff[0] < lowI_) { // in this case, we updated the entire grid to avoid problems return BiasGrid_->getNbin(); } else { @@ -1167,19 +1169,19 @@ vector MetaD::getGaussianSupport(const Gaussian& hill) return nneigh; } } else { - for(unsigned i=0;i(ceil(cutoff[i]/BiasGrid_->getDx()[i])) ); } } - + return nneigh; } double MetaD::getBiasAndDerivatives(const vector& cv, double* der) { double bias=0.0; - if(!grid_){ - if(hills_.size()>10000 && (getStep()-last_step_warn_grid)>10000){ + if(!grid_) { + if(hills_.size()>10000 && (getStep()-last_step_warn_grid)>10000) { std::string msg; Tools::convert(hills_.size(),msg); msg="You have accumulated "+msg+" hills, you should enable GRIDs to avoid serious performance hits"; @@ -1188,19 +1190,19 @@ double MetaD::getBiasAndDerivatives(const vector& cv, double* der) } unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); - for(unsigned i=rank;i vder(getNumberOfArguments()); - bias=BiasGrid_->getValueAndDerivatives(cv,vder); - for(unsigned i=0;i vder(getNumberOfArguments()); + bias=BiasGrid_->getValueAndDerivatives(cv,vder); + for(unsigned i=0; igetValue(cv); - } + } } return bias; @@ -1208,15 +1210,15 @@ double MetaD::getBiasAndDerivatives(const vector& cv, double* der) double MetaD::getGaussianNormalization( const Gaussian& hill ) { - double norm=1; + double norm=1; unsigned ncv=hill.center.size(); - if(hill.multivariate){ - // recompose the full sigma from the upper diag cholesky - unsigned k=0; + if(hill.multivariate) { + // recompose the full sigma from the upper diag cholesky + unsigned k=0; Matrix mymatrix(ncv,ncv); - for(unsigned i=0;i(ncv)/2.0); @@ -1240,65 +1242,65 @@ double MetaD::evaluateGaussian(const vector& cv, const Gaussian& hill, d const double *pcv=NULL; // pointer to cv double tmpcv[1]; // tmp array with cv (to be used with doInt_) if(cv.size()>0) pcv=&cv[0]; - if(doInt_){ + if(doInt_) { plumed_assert(cv.size()==1); tmpcv[0]=cv[0]; if(cv[0]uppI_) tmpcv[0]=uppI_; pcv=&(tmpcv[0]); } - if(hill.multivariate){ + if(hill.multivariate) { unsigned k=0; - unsigned ncv=cv.size(); - // recompose the full sigma from the upper diag cholesky + unsigned ncv=cv.size(); + // recompose the full sigma from the upper diag cholesky Matrix mymatrix(ncv,ncv); - for(unsigned i=0;iuppI_) for(unsigned i=0;iuppI_) for(unsigned i=0; i& cv, const Gaussian& hill, d double MetaD::getHeight(const vector& cv) { double height=height0_; - if(welltemp_){ + if(welltemp_) { double vbias = getBiasAndDerivatives(cv); - if(biasf_>1.0){ + if(biasf_>1.0) { height = height0_*exp(-vbias/(kbt_*(biasf_-1.0))); } else { // notice that if gamma=1 we store directly -F height = height0_*exp(-vbias/kbt_); } - } - if(dampfactor_>0.0){ + } + if(dampfactor_>0.0) { plumed_assert(BiasGrid_); double m=BiasGrid_->getMaxValue(); height*=exp(-m/(kbt_*(dampfactor_))); } - if(TargetGrid_){ + if(TargetGrid_) { double f=TargetGrid_->getValue(cv)-TargetGrid_->getMaxValue(); height*=exp(f/kbt_); } @@ -1337,15 +1339,15 @@ void MetaD::calculate() const unsigned ncv=getNumberOfArguments(); vector cv(ncv); double* der = new double[ncv]; - for(unsigned i=0;iset(mean_acc); } getPntrToComponent("work")->set(work_); - // set Forces - for(unsigned i=0;i cv(getNumberOfArguments()); vector thissigma; bool multivariate; // adding hills criteria (could be more complex though) - bool nowAddAHill; + bool nowAddAHill; if(getStep()%stride_==0 && !isFirstStep )nowAddAHill=true; else { nowAddAHill=false; isFirstStep=false; } - for(unsigned i=0;iupdate(nowAddAHill); multivariate=true; } else { multivariate=false; } - if(nowAddAHill){ + if(nowAddAHill) { // add a Gaussian double height=getHeight(cv); - // returns upper diagonal inverse + // returns upper diagonal inverse if(adaptive_!=FlexibleBin::none) thissigma=flexbin->getInverseMatrix(); // returns normal sigma else thissigma=sigma0_; // In case we use walkers_mpi, it is now necessary to communicate with other replicas. - if(walkers_mpi){ + if(walkers_mpi) { // Allocate arrays to store all walkers hills std::vector all_cv(mpi_nw_*cv.size(),0.0); std::vector all_sigma(mpi_nw_*thissigma.size(),0.0); std::vector all_height(mpi_nw_,0.0); std::vector all_multivariate(mpi_nw_,0); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { // Communicate (only root) multi_sim_comm.Allgather(cv,all_cv); multi_sim_comm.Allgather(thissigma,all_sigma); @@ -1417,12 +1419,12 @@ void MetaD::update(){ comm.Bcast(all_sigma,0); comm.Bcast(all_height,0); comm.Bcast(all_multivariate,0); - for(unsigned i=0;i cv_now(cv.size()); std::vector sigma_now(thissigma.size()); - for(unsigned j=0;j1.0?(biasf_-1.0)/biasf_:1.0),all_multivariate[i]); addGaussian(newhill); @@ -1438,7 +1440,7 @@ void MetaD::update(){ // this should be outside of the if block in case // mw_rstride_ is not a multiple of stride_ - if(mw_n_>1 && getStep()%mw_rstride_==0){ + if(mw_n_>1 && getStep()%mw_rstride_==0) { hillsOfile_.flush(); } @@ -1446,7 +1448,7 @@ void MetaD::update(){ work_+=vbias1-vbias; // dump grid on file - if(wgridstride_>0&&(getStep()%wgridstride_==0||getCPT())){ + if(wgridstride_>0&&(getStep()%wgridstride_==0||getCPT())) { // in case old grids are stored, a sequence of grids should appear // this call results in a repetition of the header: if(storeOldGrids_) gridfile_.clearFields(); @@ -1457,10 +1459,10 @@ void MetaD::update(){ if(walkers_mpi) { if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); - } + } if(r==0) gridfile_.rewind(); } - BiasGrid_->writeToFile(gridfile_); + BiasGrid_->writeToFile(gridfile_); // if a single grid is stored, it is necessary to flush it, otherwise // the file might stay empty forever (when a single grid is not large enough to // trigger flushing from the operating system). @@ -1471,83 +1473,83 @@ void MetaD::update(){ } // if multiple walkers and time to read Gaussians - if(mw_n_>1 && getStep()%mw_rstride_==0){ - for(int i=0;i1 && getStep()%mw_rstride_==0) { + for(int i=0; iisOpen())){ + // if the file is not open yet + if(!(ifiles[i]->isOpen())) { // check if it exists now and open it! if(ifiles[i]->FileExist(ifilesnames[i])) { ifiles[i]->open(ifilesnames[i]); ifiles[i]->reset(false); } - // otherwise read the new Gaussians + // otherwise read the new Gaussians } else { log.printf(" Reading hills from %s:",ifilesnames[i].c_str()); readGaussians(ifiles[i]); ifiles[i]->reset(false); } } - } + } if(getStep()%(stride_*rewf_ustride_)==0 && nowAddAHill && rewf_grid_.size()>0 ) computeReweightingFactor(); } -/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height -bool MetaD::scanOneHill(IFile *ifile, vector &tmpvalues, vector ¢er, vector &sigma, double &height , bool &multivariate) +/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height +bool MetaD::scanOneHill(IFile *ifile, vector &tmpvalues, vector ¢er, vector &sigma, double &height, bool &multivariate) { double dummy; multivariate=false; - if(ifile->scanField("time",dummy)){ + if(ifile->scanField("time",dummy)) { unsigned ncv; ncv=tmpvalues.size(); - for(unsigned i=0;iscanField( &tmpvalues[i] ); - if( tmpvalues[i].isPeriodic() && ! getPntrToArgument(i)->isPeriodic() ){ + if( tmpvalues[i].isPeriodic() && ! getPntrToArgument(i)->isPeriodic() ) { error("in hills file periodicity for variable " + tmpvalues[i].getName() + " does not match periodicity in input"); - } else if( tmpvalues[i].isPeriodic() ){ + } else if( tmpvalues[i].isPeriodic() ) { std::string imin, imax; tmpvalues[i].getDomain( imin, imax ); std::string rmin, rmax; getPntrToArgument(i)->getDomain( rmin, rmax ); - if( imin!=rmin || imax!=rmax ){ + if( imin!=rmin || imax!=rmax ) { error("in hills file periodicity for variable " + tmpvalues[i].getName() + " does not match periodicity in input"); } } center[i]=tmpvalues[i].get(); } - // scan for multivariate label: record the actual file position so to eventually rewind + // scan for multivariate label: record the actual file position so to eventually rewind std::string sss; ifile->scanField("multivariate",sss); if(sss=="true") multivariate=true; else if(sss=="false") multivariate=false; else plumed_merror("cannot parse multivariate = "+ sss); - if(multivariate){ + if(multivariate) { sigma.resize(ncv*(ncv+1)/2); Matrix upper(ncv,ncv); Matrix lower(ncv,ncv); - for(unsigned i=0;iscanField("sigma_"+getPntrToArgument(j+i)->getName()+"_"+getPntrToArgument(j)->getName(),lower(j+i,j)); upper(j,j+i)=lower(j+i,j); } } - Matrix mymult(ncv,ncv); - Matrix invmatrix(ncv,ncv); - mult(lower,upper,mymult); + Matrix mymult(ncv,ncv); + Matrix invmatrix(ncv,ncv); + mult(lower,upper,mymult); // now invert and get the sigmas Invert(mymult,invmatrix); - // put the sigmas in the usual order: upper diagonal (this time in normal form and not in band form) + // put the sigmas in the usual order: upper diagonal (this time in normal form and not in band form) unsigned k=0; - for(unsigned i=0;iscanField("sigma_"+getPntrToArgument(i)->getName(),sigma[i]); } } - + ifile->scanField("height",height); ifile->scanField("biasf",dummy); if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy); @@ -1555,8 +1557,8 @@ bool MetaD::scanOneHill(IFile *ifile, vector &tmpvalues, vector if(ifile->FieldExist("upper_int")) ifile->scanField("upper_int",dummy); ifile->scanField(); return true; - } else { - return false; + } else { + return false; } } @@ -1564,36 +1566,36 @@ void MetaD::computeReweightingFactor() { if( !welltemp_ ) error("cannot compute the c(t) reweighting factors for non well-tempered metadynamics"); - if(biasf_==1.0){ + if(biasf_==1.0) { // in this case we have no bias, so reweight factor is 1.0 - getPntrToComponent("rct")->set(1.0); - return; + getPntrToComponent("rct")->set(1.0); + return; } // Recover the minimum values for the grid unsigned ncv=getNumberOfArguments(); unsigned ntotgrid=1; - std::vector dmin( ncv ),dmax( ncv ), grid_spacing( ncv ), vals( ncv ); - for(unsigned j=0;j dmin( ncv ),dmax( ncv ), grid_spacing( ncv ), vals( ncv ); + for(unsigned j=0; jgetMin()[j], dmin[j] ); Tools::convert( BiasGrid_->getMax()[j], dmax[j] ); grid_spacing[j] = ( dmax[j] - dmin[j] ) / static_cast( rewf_grid_[j] ); - if( !getPntrToArgument(j)->isPeriodic() ) dmax[j] += grid_spacing[j]; + if( !getPntrToArgument(j)->isPeriodic() ) dmax[j] += grid_spacing[j]; ntotgrid *= rewf_grid_[j]; } - + // Now sum over whole grid reweight_factor=0.0; double* der=new double[ncv]; std::vector t_index( ncv ); double sum1=0.0; double sum2=0.0; double afactor = biasf_ / (kbt_*(biasf_-1.0)); double afactor2 = 1.0 / (kbt_*(biasf_-1.0)); - unsigned rank=comm.Get_rank(), stride=comm.Get_size(); - for(unsigned i=rank;i=2 ) t_index[ncv-1]=((kk-t_index[ncv-1])/rewf_grid_[ncv-2]); - - for(unsigned j=0;j(getNumberOfArguments())&&!parameters.empty()) @@ -206,21 +206,21 @@ MCfirst_(-1) if(!arg2.empty()) { if(parameters.size()>0) error("It is not possible to use PARARG and PARAMETERS together"); if(arg2.size()!=getNumberOfArguments()) error("Size of PARARG array should be the same as number for arguments in ARG"); - for(unsigned i=0;iget()); + for(unsigned i=0; iget()); if(arg2[i]->hasDerivatives()==true) error("PARARG can only accept arguments without derivatives"); } } - if(parameters.size()!=getNumberOfArguments()) + if(parameters.size()!=getNumberOfArguments()) error("PARARG or PARAMETERS arrays should include the same number of elements as the arguments in ARG"); string stringa_noise; parse("NOISETYPE",stringa_noise); - if(stringa_noise=="GAUSS") noise_type_ = GAUSS; + if(stringa_noise=="GAUSS") noise_type_ = GAUSS; else if(stringa_noise=="MGAUSS") noise_type_ = MGAUSS; else if(stringa_noise=="OUTLIERS") noise_type_ = OUTLIERS; - else error("Unkwnow noise type"); + else error("Unkwnow noise type"); parseFlag("SCALEDATA", doscale_); if(doscale_) { @@ -243,7 +243,7 @@ MCfirst_(-1) sigma_.resize(getNumberOfArguments(),readsigma[0]); } else { error("SIGMA0 can accept either one single value or as many values as the number of arguments (with NOISETYPE=MGAUSS)"); - } + } } else sigma_.resize(1, readsigma[0]); parse("SIGMA_MIN",sigma_min_); @@ -279,15 +279,15 @@ MCfirst_(-1) MCstride_ *= getStride(); switch(noise_type_) { - case GAUSS: - log.printf(" with gaussian noise and a single noise parameter for all the data\n"); - break; - case MGAUSS: - log.printf(" with gaussian noise and a noise parameter for each data point\n"); - break; - case OUTLIERS: - log.printf(" with long tailed gaussian noise and a single noise parameter for all the data\n"); - break; + case GAUSS: + log.printf(" with gaussian noise and a single noise parameter for all the data\n"); + break; + case MGAUSS: + log.printf(" with gaussian noise and a noise parameter for each data point\n"); + break; + case OUTLIERS: + log.printf(" with long tailed gaussian noise and a single noise parameter for all the data\n"); + break; } if(doscale_) { @@ -301,7 +301,7 @@ MCfirst_(-1) if(readsigma.size()==1) log.printf(" initial data uncertainty %f\n",sigma_[0]); else { log.printf(" initial data uncertainties"); - for(unsigned i=0;i &sigma, const double scale){ +double Metainference::getEnergySPE(const vector &sigma, const double scale) { // calculate effective sigma const double smean2 = sigma_mean_*sigma_mean_; const double s = sqrt( sigma[0]*sigma[0] + smean2 ); // cycle on arguments double ene = 0.0; - for(unsigned i=0;i &sigma, const double sca return kbt_ * ene; } -double Metainference::getEnergyGJE(const vector &sigma, const double scale){ +double Metainference::getEnergyGJE(const vector &sigma, const double scale) { // cycle on arguments double ene = 0.0; const double smean2 = sigma_mean_*sigma_mean_; - double ss = sigma[0]*sigma[0] + smean2; - for(unsigned i=0;i &sigma, const double sca return kbt_ * ene; } -void Metainference::doMonteCarlo(){ +void Metainference::doMonteCarlo() { double old_energy; switch(noise_type_) { - case GAUSS: - case MGAUSS: - old_energy = getEnergyGJE(sigma_,scale_); - break; - case OUTLIERS: - old_energy = getEnergySPE(sigma_,scale_); - break; + case GAUSS: + case MGAUSS: + old_energy = getEnergyGJE(sigma_,scale_); + break; + case OUTLIERS: + old_energy = getEnergySPE(sigma_,scale_); + break; } - - // cycle on MC steps - for(unsigned i=0;i scale_max_){new_scale = 2.0 * scale_max_ - new_scale;} - if(new_scale < scale_min_){new_scale = 2.0 * scale_min_ - new_scale;} + if(new_scale > scale_max_) {new_scale = 2.0 * scale_max_ - new_scale;} + if(new_scale < scale_min_) {new_scale = 2.0 * scale_min_ - new_scale;} // the scaling factor should be the same for all the replicas if(comm.Get_rank()==0) multi_sim_comm.Bcast(new_scale,0); comm.Bcast(new_scale,0); } - + // propose move for sigma vector new_sigma(sigma_.size()); - for(unsigned j=0;j(rand()) / RAND_MAX; const double ds2 = -Dsigma_ + r2 * 2.0 * Dsigma_; new_sigma[j] = sigma_[j] + ds2; // check boundaries - if(new_sigma[j] > sigma_max_){new_sigma[j] = 2.0 * sigma_max_ - new_sigma[j];} - if(new_sigma[j] < sigma_min_){new_sigma[j] = 2.0 * sigma_min_ - new_sigma[j];} + if(new_sigma[j] > sigma_max_) {new_sigma[j] = 2.0 * sigma_max_ - new_sigma[j];} + if(new_sigma[j] < sigma_min_) {new_sigma[j] = 2.0 * sigma_min_ - new_sigma[j];} } - + // calculate new energy double new_energy=0; switch(noise_type_) { - case GAUSS: - case MGAUSS: - new_energy = getEnergyGJE(new_sigma,new_scale); - break; - case OUTLIERS: - new_energy = getEnergySPE(new_sigma,new_scale); - break; + case GAUSS: + case MGAUSS: + new_energy = getEnergyGJE(new_sigma,new_scale); + break; + case OUTLIERS: + new_energy = getEnergySPE(new_sigma,new_scale); + break; } // accept or reject const double delta = ( new_energy - old_energy ) / kbt_; // if delta is negative always accept move - if( delta <= 0.0 ){ + if( delta <= 0.0 ) { old_energy = new_energy; scale_ = new_scale; sigma_ = new_sigma; MCaccept_++; - // otherwise extract random number + // otherwise extract random number } else { const double s = static_cast(rand()) / RAND_MAX; - if( s < exp(-delta) ){ + if( s < exp(-delta) ) { old_energy = new_energy; scale_ = new_scale; sigma_ = new_sigma; MCaccept_++; } } - + if(doscale_) { // the scaling factor should be the same for all the replicas if(comm.Get_rank()==0) multi_sim_comm.Bcast(scale_,0); @@ -466,26 +466,26 @@ double Metainference::getEnergyForceSPE() double ene = 0.0; const unsigned narg=getNumberOfArguments(); - const double smean2 = sigma_mean_*sigma_mean_; + const double smean2 = sigma_mean_*sigma_mean_; const double s = sqrt( sigma_[0]*sigma_[0] + smean2 ); vector f(narg,0); - - if(comm.Get_rank()==0){ - for(unsigned i=0;i(ndata_)*std::log(sqrt2_div_pi*s); + + if(comm.Get_rank()==0) { + for(unsigned i=0; i(ndata_)*std::log(sqrt2_div_pi*s); } // intra-replica summation comm.Sum(&f[0],narg); @@ -504,19 +504,19 @@ double Metainference::getEnergyForceGJE() vector inv_s2(ssize, 0.); const double smean2 = sigma_mean_*sigma_mean_; - for(unsigned i=0;iset(accept); // calculate bias and forces - double ene = 0; + double ene = 0; switch(noise_type_) { - case GAUSS: - case MGAUSS: - ene = getEnergyForceGJE(); - break; - case OUTLIERS: - ene = getEnergyForceSPE(); - break; + case GAUSS: + case MGAUSS: + ene = getEnergyForceGJE(); + break; + case OUTLIERS: + ene = getEnergyForceSPE(); + break; } // set value of the bias setBias(kbt_*ene); diff --git a/src/bias/MovingRestraint.cpp b/src/bias/MovingRestraint.cpp index 02c08fb4e9..13cafce97e 100644 --- a/src/bias/MovingRestraint.cpp +++ b/src/bias/MovingRestraint.cpp @@ -26,8 +26,8 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS MOVINGRESTRAINT /* @@ -39,7 +39,7 @@ and Jarzynski sampling \cite jarzynski. The harmonic restraint on your system is given by: \f[ -V(\vec{s},t) = \frac{1}{2} \kappa(t) ( \vec{s} - \vec{s}_0(t) )^2 +V(\vec{s},t) = \frac{1}{2} \kappa(t) ( \vec{s} - \vec{s}_0(t) )^2 \f] The time dependence of \f$\kappa\f$ and \f$\vec{s}_0\f$ are specified by a list of @@ -47,7 +47,7 @@ STEP, KAPPA and AT keywords. These keywords tell plumed what values \f$\kappa\f should have at the time specified by the corresponding STEP keyword. Inbetween these times the values of \f$\kappa\f$ and \f$\vec{s}_0\f$ are linearly interpolated. -Additional material and examples can be also found in the tutorial \ref belfast-5 +Additional material and examples can be also found in the tutorial \ref belfast-5 \par Examples The following input is dragging the distance between atoms 2 and 4 @@ -71,7 +71,7 @@ static. DISTANCE ATOMS=1,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 MOVINGRESTRAINT ... - ARG=d1,d2 + ARG=d1,d2 STEP0=0 AT0=1.0,1.5 KAPPA0=0.0,0.0 STEP1=1000 AT1=1.0,1.5 KAPPA1=1.0,1.0 ... MOVINGRESTRAINT @@ -88,9 +88,9 @@ MOVINGRESTRAINT ... ... MOVINGRESTRAINT \endverbatim -By default the Action is issuing some values which are +By default the Action is issuing some values which are the work on each degree of freedom, the center of the harmonic potential, -the total bias deposited +the total bias deposited (See also \ref DISTANCE). @@ -100,7 +100,7 @@ the total bias deposited //+ENDPLUMEDOC -class MovingRestraint : public Bias{ +class MovingRestraint : public Bias { std::vector > at; std::vector > kappa; std::vector step; @@ -119,54 +119,54 @@ class MovingRestraint : public Bias{ PLUMED_REGISTER_ACTION(MovingRestraint,"MOVINGRESTRAINT") -void MovingRestraint::registerKeywords( Keywords& keys ){ +void MovingRestraint::registerKeywords( Keywords& keys ) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","VERSE","B","Tells plumed whether the restraint is only acting for CV larger (U) or smaller (L) than " - "the restraint or whether it is acting on both sides (B)"); + "the restraint or whether it is acting on both sides (B)"); keys.add("numbered","STEP","This keyword appears multiple times as STEPx with x=0,1,2,...,n. Each value given represents " - "the MD step at which the restraint parameters take the values KAPPAx and ATx."); + "the MD step at which the restraint parameters take the values KAPPAx and ATx."); keys.reset_style("STEP","compulsory"); keys.add("numbered","AT","ATx is equal to the position of the restraint at time STEPx. For intermediate times this parameter " - "is linearly interpolated. If no ATx is specified for STEPx then the values of AT are kept constant " - "during the interval of time between STEPx-1 and STEPx."); - keys.reset_style("AT","compulsory"); + "is linearly interpolated. If no ATx is specified for STEPx then the values of AT are kept constant " + "during the interval of time between STEPx-1 and STEPx."); + keys.reset_style("AT","compulsory"); keys.add("numbered","KAPPA","KAPPAx is equal to the value of the force constants at time STEPx. For intermediate times this " - "parameter is linearly interpolated. If no KAPPAx is specified for STEPx then the values of KAPPAx " - "are kept constant during the interval of time between STEPx-1 and STEPx."); + "parameter is linearly interpolated. If no KAPPAx is specified for STEPx then the values of KAPPAx " + "are kept constant during the interval of time between STEPx-1 and STEPx."); keys.reset_style("KAPPA","compulsory"); keys.addOutputComponent("work","default","the total work performed changing this restraint"); keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); keys.addOutputComponent("_cntr","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "these quantities will named with the arguments of the bias followed by " - "the character string _cntr. These quantities give the instantaneous position " - "of the center of the harmonic potential."); + "these quantities will named with the arguments of the bias followed by " + "the character string _cntr. These quantities give the instantaneous position " + "of the center of the harmonic potential."); keys.addOutputComponent("_work","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _work. These quantities tell the user how much work has " - "been done by the potential in dragging the system along the various colvar axis."); + "These quantities will named with the arguments of the bias followed by " + "the character string _work. These quantities tell the user how much work has " + "been done by the potential in dragging the system along the various colvar axis."); keys.addOutputComponent("_kappa","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _kappa. These quantities tell the user the time dependent value of kappa."); + "These quantities will named with the arguments of the bias followed by " + "the character string _kappa. These quantities tell the user the time dependent value of kappa."); } MovingRestraint::MovingRestraint(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -verse(getNumberOfArguments()) + PLUMED_BIAS_INIT(ao), + verse(getNumberOfArguments()) { parseVector("VERSE",verse); vector ss(1); ss[0]=-1; std::vector kk( getNumberOfArguments() ), aa( getNumberOfArguments() ); - for(int i=0;;i++){ - // Read in step + for(int i=0;; i++) { + // Read in step if( !parseNumberedVector("STEP",i,ss) ) break; - for(unsigned j=0;jgetName()+"_cntr"; // each spring has its own center - addComponent(comp); componentIsNotPeriodic(comp); - comp=getPntrToArgument(i)->getName()+"_work"; // each spring has its own work - addComponent(comp); componentIsNotPeriodic(comp); - comp=getPntrToArgument(i)->getName()+"_kappa"; // each spring has its own kappa - addComponent(comp); componentIsNotPeriodic(comp); - work.push_back(0.); // initialize the work value + for(unsigned i=0; i< getNumberOfArguments() ; i++) { + comp=getPntrToArgument(i)->getName()+"_cntr"; // each spring has its own center + addComponent(comp); componentIsNotPeriodic(comp); + comp=getPntrToArgument(i)->getName()+"_work"; // each spring has its own work + addComponent(comp); componentIsNotPeriodic(comp); + comp=getPntrToArgument(i)->getName()+"_kappa"; // each spring has its own kappa + addComponent(comp); componentIsNotPeriodic(comp); + work.push_back(0.); // initialize the work value } addComponent("work"); componentIsNotPeriodic("work"); tot_work=0.0; @@ -208,38 +208,38 @@ verse(getNumberOfArguments()) } -void MovingRestraint::calculate(){ +void MovingRestraint::calculate() { double ene=0.0; double totf2=0.0; unsigned narg=getNumberOfArguments(); long int now=getStep(); std::vector kk(narg),aa(narg),f(narg),dpotdk(narg); - if(now<=step[0]){ + if(now<=step[0]) { kk=kappa[0]; aa=at[0]; oldaa=at[0]; oldk=kappa[0]; - olddpotdk.resize(narg); + olddpotdk.resize(narg); oldf.resize(narg); - } else if(now>=step[step.size()-1]){ + } else if(now>=step[step.size()-1]) { kk=kappa[step.size()-1]; aa=at[step.size()-1]; } else { unsigned i=0; - for(i=1;igetName()+"_cntr")->set(aa[i]); + getPntrToComponent(getPntrToArgument(i)->getName()+"_cntr")->set(aa[i]); const double k=kk[i]; f[i]=-k*cv; if(verse[i]=="U" && cv<0) continue; @@ -247,8 +247,8 @@ void MovingRestraint::calculate(){ plumed_assert(verse[i]=="U" || verse[i]=="L" || verse[i]=="B"); dpotdk[i]=0.5*cv*cv; if(oldaa.size()==aa.size() && oldf.size()==f.size()) work[i]+=0.5*(oldf[i]+f[i])*(aa[i]-oldaa[i]) + 0.5*( dpotdk[i]+olddpotdk[i] )*(kk[i]-oldk[i]); - getPntrToComponent(getPntrToArgument(i)->getName()+"_work")->set(work[i]); - getPntrToComponent(getPntrToArgument(i)->getName()+"_kappa")->set(kk[i]); + getPntrToComponent(getPntrToArgument(i)->getName()+"_work")->set(work[i]); + getPntrToComponent(getPntrToArgument(i)->getName()+"_kappa")->set(kk[i]); tot_work+=work[i]; ene+=0.5*k*cv*cv; setOutputForce(i,f[i]); diff --git a/src/bias/PBMetaD.cpp b/src/bias/PBMetaD.cpp index a129ffb9c5..b50557f7d2 100644 --- a/src/bias/PBMetaD.cpp +++ b/src/bias/PBMetaD.cpp @@ -41,14 +41,14 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { -//+PLUMEDOC BIAS PBMETAD +//+PLUMEDOC BIAS PBMETAD /* Used to performed Parallel Bias MetaDynamics. -This action activate Parallel Bias MetaDynamics (PBMetaD) \cite pbmetad, a version of MetaDynamics \cite metad in which +This action activate Parallel Bias MetaDynamics (PBMetaD) \cite pbmetad, a version of MetaDynamics \cite metad in which multiple low-dimensional bias potentials are applied in parallel. In the current implementation, these have the form of mono-dimensional MetaDynamics bias potentials: @@ -72,7 +72,7 @@ at each deposition step the Gaussian heights are multiplied by the so-called con \f[ W_i(k \tau)=W_0 \frac{\exp\left( - \frac{V(s_i,k \tau)}{k_B T} -\right)}{\sum_{i=1}^N +\right)}{\sum_{i=1}^N \exp\left( - \frac{V(s_i,k \tau)}{k_B T} \right)} @@ -83,19 +83,19 @@ where \f$W_0\f$ is the initial Gaussian height. The PBMetaD bias potential is defined by: \f[ -V_{PB}(\vec{s},t) = -k_B T \log{\sum_{i=1}^N +V_{PB}(\vec{s},t) = -k_B T \log{\sum_{i=1}^N \exp\left( - \frac{V(s_i,t)}{k_B T} \right)}. \f] -Information on the Gaussian functions that build each bias potential are printed to -multiple HILLS files, which -are used both to restart the calculation and to reconstruct the mono-dimensional -free energies as a function of the corresponding CVs. +Information on the Gaussian functions that build each bias potential are printed to +multiple HILLS files, which +are used both to restart the calculation and to reconstruct the mono-dimensional +free energies as a function of the corresponding CVs. These can be reconstructed using the \ref sum_hills utility because the final bias is given -by: +by: \f[ V(s_i) = -F(s_i) @@ -113,7 +113,7 @@ and if Gaussian width is fixed PLUMED will use 1/5 of the Gaussian width as grid This default choice should be reasonable for most applications. Another option that is available is well-tempered metadynamics \cite Barducci:2008. In this -variant of PBMetaD the heights of the Gaussian hills are rescaled at each step by the +variant of PBMetaD the heights of the Gaussian hills are rescaled at each step by the additional well-tempered metadynamics term. This ensures that each bias converges more smoothly. It should be noted that, in the case of well-tempered metadynamics, in the output printed the Gaussian height is re-scaled using the bias factor. @@ -128,21 +128,21 @@ gaussian potential is denoted by one value only that is a Cartesian space (ADAPT (ADAPTIVE=DIFF). Note that a specific integration technique for the deposited gaussians should be used in this case. Check the documentation for utility sum_hills. -With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero -outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only +With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero +outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only to the free energy for s > sw, the history dependent potential is still updated according to the above -equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also -if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the -force on the system in the region s > sw comes from both metadynamics and the force field, in the region -s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that -fluctuates around a stable estimator, equal to the negative of the free energy far enough from the +equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also +if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the +force on the system in the region s > sw comes from both metadynamics and the force field, in the region +s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that +fluctuates around a stable estimator, equal to the negative of the free energy far enough from the boundaries. Note that: - It works only for one-dimensional biases; - It works both with and without GRID; - The interval limit sw in a region where the free energy derivative is not large; -- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should +- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should be used together with a \ref UPPER_WALLS or \ref LOWER_WALLS at sw. - + Multiple walkers \cite multiplewalkers can also be used. See below the examples. \par Examples @@ -160,26 +160,26 @@ PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \par If you use well-tempered metadynamics, you should specify a single biasfactor and initial -Gaussian height. +Gaussian height. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 PBMETAD ... -ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 -PACE=500 BIASFACTOR=8 LABEL=pb +ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 +PACE=500 BIASFACTOR=8 LABEL=pb FILE=HILLS_d1,HILLS_d2 ... PBMETAD PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \endverbatim -\par +\par The following input enables the MPI version of multiple-walkers. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 PBMETAD ... -ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 -PACE=500 BIASFACTOR=8 LABEL=pb +ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 +PACE=500 BIASFACTOR=8 LABEL=pb FILE=HILLS_d1,HILLS_d2 WALKERS_MPI ... PBMETAD @@ -187,17 +187,17 @@ PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \endverbatim \par -The disk version of multiple-walkers can be -enabled by setting the number of walker used, the id of the -current walker which interprets the input file, the directory where the +The disk version of multiple-walkers can be +enabled by setting the number of walker used, the id of the +current walker which interprets the input file, the directory where the hills containing files resides, and the frequency to read the other walkers. Here is an example \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 PBMETAD ... -ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 -PACE=500 BIASFACTOR=8 LABEL=pb +ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 +PACE=500 BIASFACTOR=8 LABEL=pb FILE=HILLS_d1,HILLS_d2 WALKERS_N=10 WALKERS_ID=3 @@ -206,28 +206,28 @@ WALKERS_RSTRIDE=100 ... PBMETAD PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \endverbatim -where WALKERS_N is the total number of walkers, WALKERS_ID is the -id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory -where all the walkers are located. WALKERS_RSTRIDE is the number of step between -one update and the other. +where WALKERS_N is the total number of walkers, WALKERS_ID is the +id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory +where all the walkers are located. WALKERS_RSTRIDE is the number of step between +one update and the other. */ //+ENDPLUMEDOC -class PBMetaD : public Bias{ +class PBMetaD : public Bias { private: struct Gaussian { - vector center; - vector sigma; - double height; - bool multivariate; // this is required to discriminate the one dimensional case - vector invsigma; - Gaussian(const vector & center,const vector & sigma, double height, bool multivariate): - center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma){ - // to avoid troubles from zero element in flexible hills - for(unsigned i=0;i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; - } + vector center; + vector sigma; + double height; + bool multivariate; // this is required to discriminate the one dimensional case + vector invsigma; + Gaussian(const vector & center,const vector & sigma, double height, bool multivariate): + center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma) { + // to avoid troubles from zero element in flexible hills + for(unsigned i=0; i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; + } }; vector sigma0_; vector sigma0min_; @@ -276,12 +276,12 @@ class PBMetaD : public Bias{ void calculate(); void update(); static void registerKeywords(Keywords& keys); - bool checkNeedsGradients()const{if(adaptive_==FlexibleBin::geometry){return true;}else{return false;}} + bool checkNeedsGradients()const {if(adaptive_==FlexibleBin::geometry) {return true;} else {return false;}} }; PLUMED_REGISTER_ACTION(PBMetaD,"PBMETAD") -void PBMetaD::registerKeywords(Keywords& keys){ +void PBMetaD::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","SIGMA","the widths of the Gaussian hills"); @@ -316,102 +316,102 @@ void PBMetaD::registerKeywords(Keywords& keys){ keys.use("UPDATE_UNTIL"); } -PBMetaD::~PBMetaD(){ +PBMetaD::~PBMetaD() { for(unsigned i=0; iclose(); - delete hillsOfiles_[i]; + for(unsigned i=0; iclose(); + delete hillsOfiles_[i]; } if(wgridstride_ > 0) { - for(unsigned i=0; iclose(); - delete gridfiles_[i]; - } + for(unsigned i=0; iclose(); + delete gridfiles_[i]; + } } // close files - for(unsigned i=0;iisOpen()) ifiles[i]->close(); - delete ifiles[i]; + for(unsigned i=0; iisOpen()) ifiles[i]->close(); + delete ifiles[i]; } } PBMetaD::PBMetaD(const ActionOptions& ao): -PLUMED_BIAS_INIT(ao), -grid_(false), height0_(std::numeric_limits::max()), -biasf_(1.0), kbt_(0.0), stride_(0), wgridstride_(0), welltemp_(false), -mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), -walkers_mpi(false), mpi_nw_(0), -adaptive_(FlexibleBin::none), -isFirstStep(true) + PLUMED_BIAS_INIT(ao), + grid_(false), height0_(std::numeric_limits::max()), + biasf_(1.0), kbt_(0.0), stride_(0), wgridstride_(0), welltemp_(false), + mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), + walkers_mpi(false), mpi_nw_(0), + adaptive_(FlexibleBin::none), + isFirstStep(true) { // parse the flexible hills string adaptiveoption; adaptiveoption="NONE"; parse("ADAPTIVE",adaptiveoption); - if(adaptiveoption=="GEOM"){ + if(adaptiveoption=="GEOM") { log.printf(" Uses Geometry-based hills width: sigma must be in distance units and only one sigma is needed\n"); - adaptive_=FlexibleBin::geometry; - } else if(adaptiveoption=="DIFF"){ + adaptive_=FlexibleBin::geometry; + } else if(adaptiveoption=="DIFF") { log.printf(" Uses Diffusion-based hills width: sigma must be in timesteps and only one sigma is needed\n"); - adaptive_=FlexibleBin::diffusion; - } else if(adaptiveoption=="NONE"){ - adaptive_=FlexibleBin::none; + adaptive_=FlexibleBin::diffusion; + } else if(adaptiveoption=="NONE") { + adaptive_=FlexibleBin::none; } else { - error("I do not know this type of adaptive scheme"); + error("I do not know this type of adaptive scheme"); } parse("FMT",fmt); // parse the sigma parseVector("SIGMA",sigma0_); - if(adaptive_==FlexibleBin::none){ - // if you use normal sigma you need one sigma per argument + if(adaptive_==FlexibleBin::none) { + // if you use normal sigma you need one sigma per argument if( sigma0_.size()!=getNumberOfArguments() ) error("number of arguments does not match number of SIGMA parameters"); } else { - // if you use flexible hills you need one sigma - if(sigma0_.size()!=1){ + // if you use flexible hills you need one sigma + if(sigma0_.size()!=1) { error("If you choose ADAPTIVE you need only one sigma according to your choice of type (GEOM/DIFF)"); - } + } // if adaptive then the number must be an integer - if(adaptive_==FlexibleBin::diffusion){ - if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ){ - error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); - } - } + if(adaptive_==FlexibleBin::diffusion) { + if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ) { + error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); + } + } // here evtl parse the sigma min and max values parseVector("SIGMA_MIN",sigma0min_); if(sigma0min_.size()>0 && sigma0min_.size()!=getNumberOfArguments()) { error("the number of SIGMA_MIN values be the same of the number of the arguments"); - } else if(sigma0min_.size()==0) { + } else if(sigma0min_.size()==0) { sigma0min_.resize(getNumberOfArguments()); - for(unsigned i=0;i0 && sigma0max_.size()!=getNumberOfArguments()) { - error("the number of SIGMA_MAX values be the same of the number of the arguments"); - } else if(sigma0max_.size()==0) { + error("the number of SIGMA_MAX values be the same of the number of the arguments"); + } else if(sigma0max_.size()==0) { sigma0max_.resize(getNumberOfArguments()); - for(unsigned i=0;i tmp_smin, tmp_smax; tmp_smin.resize(1,sigma0min_[i]); tmp_smax.resize(1,sigma0max_[i]); flexbin.push_back(FlexibleBin(adaptive_,this,i,sigma0_[0],tmp_smin,tmp_smax)); } } - + // note: HEIGHT is not compulsory, since one could use the TAU keyword, see below parse("HEIGHT",height0_); parse("PACE",stride_); if(stride_<=0) error("frequency for hill addition is nonsensical"); - + parseVector("FILE",hillsfname); if(hillsfname.size()==0) { - for(unsigned i=0;igetName()); - } + for(unsigned i=0; igetName()); + } if( hillsfname.size()!=getNumberOfArguments() ) { error("number of FILE arguments does not match number of HILLS files"); } @@ -422,13 +422,13 @@ isFirstStep(true) parse("TEMP",temp); if(temp>0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; else kbt_=plumed.getAtoms().getKbT(); - if(biasf_>1.0){ + if(biasf_>1.0) { if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with well-tempered metad you must specify it using TEMP"); welltemp_=true; } double tau=0.0; parse("TAU",tau); - if(tau==0.0){ + if(tau==0.0) { if(height0_==std::numeric_limits::max()) error("At least one between HEIGHT and TAU should be specified"); // if tau is not set, we compute it here from the other input parameters if(welltemp_) tau=(kbt_*(biasf_-1.0))/height0_*getTimeStep()*stride_; @@ -437,7 +437,7 @@ isFirstStep(true) if(height0_!=std::numeric_limits::max()) error("At most one between HEIGHT and TAU should be specified"); height0_=(kbt_*(biasf_-1.0))/tau*getTimeStep()*stride_; } - + // Multiple walkers parse("WALKERS_N",mw_n_); parse("WALKERS_ID",mw_id_); @@ -456,15 +456,15 @@ isFirstStep(true) error("frequency with which to output grid not specified use GRID_WSTRIDE"); } if(gridfilenames_.size()==0 && wgridstride_ > 0) { - for(unsigned i=0;igetName()); - } - if(gridfilenames_.size() > 0 && hillsfname.size() > 0 && gridfilenames_.size() != hillsfname.size()) + for(unsigned i=0; igetName()); + } + if(gridfilenames_.size() > 0 && hillsfname.size() > 0 && gridfilenames_.size() != hillsfname.size()) error("number of GRID_WFILES arguments does not match number of HILLS files"); // Read grid vector gridreadfilenames_; parseVector("GRID_RFILES",gridreadfilenames_); - + // Grid Stuff vector gmin(getNumberOfArguments()); parseVector("GRID_MIN",gmin); @@ -481,45 +481,45 @@ isFirstStep(true) if(gmin.size()!=gmax.size()) error("GRID_MAX and GRID_MIN should be either present or absent"); if(gspacing.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); if(gbin.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); - if(gmin.size()!=0){ - if(gbin.size()==0 && gspacing.size()==0){ - if(adaptive_==FlexibleBin::none){ + if(gmin.size()!=0) { + if(gbin.size()==0 && gspacing.size()==0) { + if(adaptive_==FlexibleBin::none) { log<<" Binsize not specified, 1/10 of sigma will be be used\n"; plumed_assert(sigma0_.size()==getNumberOfArguments()); gspacing.resize(getNumberOfArguments()); - for(unsigned i=0;i0){grid_=true;} + if(gbin.size()>0) {grid_=true;} if(!grid_&&gridfilenames_.size() > 0) error("To write a grid you need first to define it!"); if(!grid_&&gridreadfilenames_.size() > 0) error("To read a grid you need first to define it!"); - doInt_.resize(getNumberOfArguments(),false); + doInt_.resize(getNumberOfArguments(),false); // Interval keyword parseVector("INTERVAL_MIN",lowI_); parseVector("INTERVAL_MAX",uppI_); @@ -531,26 +531,26 @@ isFirstStep(true) if(getPntrToArgument(i)->isPeriodic()) warning("INTERVAL is not used for periodic variables"); else doInt_[i]=true; } - + checkRead(); log.printf(" Gaussian width "); if (adaptive_==FlexibleBin::diffusion)log.printf(" (Note: The units of sigma are in timesteps) "); if (adaptive_==FlexibleBin::geometry)log.printf(" (Note: The units of sigma are in dist units) "); - for(unsigned i=0;i1){ + if(mw_n_>1) { if(walkers_mpi) error("MPI version of multiple walkers is not compatible with filesystem version of multiple walkers"); log.printf(" %d multiple walkers active\n",mw_n_); log.printf(" walker id %d\n",mw_id_); @@ -558,9 +558,9 @@ isFirstStep(true) if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); } else { if(walkers_mpi) { - log.printf(" Multiple walkers active using MPI communnication\n"); + log.printf(" Multiple walkers active using MPI communnication\n"); if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { // Only root of group can communicate with other walkers mpi_nw_ = multi_sim_comm.Get_size(); mpi_id_ = multi_sim_comm.Get_rank(); @@ -572,31 +572,31 @@ isFirstStep(true) } } - for(unsigned i=0; i0) { - for(unsigned i=0; i0) { + for(unsigned i=0; i0) { - for(unsigned i=0; i0) { + for(unsigned i=0; i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; - } else { - if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; - } - } - std::string funcl=getLabel() + ".bias"; - for(unsigned i=0; i args(1); - args[0] = getPntrToArgument(i); - vector gmin_t(1); - vector gmax_t(1); - vector gbin_t(1); - gmin_t[0] = gmin[i]; - gmax_t[0] = gmax[i]; - gbin_t[0] = gbin[i]; - Grid* BiasGrid_; - // Read grid from file - if(gridreadfilenames_.size()>0) { - IFile gridfile; - gridfile.link(*this); - if(gridfile.FileExist(gridreadfilenames_[i])){ - gridfile.open(gridreadfilenames_[i]); - } else { - error("The GRID file you want to read: " + gridreadfilenames_[i] + ", cannot be found!"); - } - string funcl = getLabel() + ".bias"; - BiasGrid_ = Grid::create(funcl, args, gridfile, gmin_t, gmax_t, gbin_t, sparsegrid, spline, true); - gridfile.close(); - if(BiasGrid_->getDimension() != args.size()) { - error("mismatch between dimensionality of input grid and number of arguments"); - } - if(getPntrToArgument(i)->isPeriodic() != BiasGrid_->getIsPeriodic()[0]) { - error("periodicity mismatch between arguments and input bias"); - } - log.printf(" Restarting from %s:",gridreadfilenames_[i].c_str()); - if(getRestart()) restartedFromGrid=true; - } else { - if(!sparsegrid){BiasGrid_=new Grid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} - else {BiasGrid_=new SparseGrid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} - std::vector actualmin=BiasGrid_->getMin(); - std::vector actualmax=BiasGrid_->getMax(); - if(gmin_t[0]!=actualmin[0]) log<<" WARNING: GRID_MIN["<0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; + } else { + if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; + } + } + std::string funcl=getLabel() + ".bias"; + for(unsigned i=0; i args(1); + args[0] = getPntrToArgument(i); + vector gmin_t(1); + vector gmax_t(1); + vector gbin_t(1); + gmin_t[0] = gmin[i]; + gmax_t[0] = gmax[i]; + gbin_t[0] = gbin[i]; + Grid* BiasGrid_; + // Read grid from file + if(gridreadfilenames_.size()>0) { + IFile gridfile; + gridfile.link(*this); + if(gridfile.FileExist(gridreadfilenames_[i])) { + gridfile.open(gridreadfilenames_[i]); + } else { + error("The GRID file you want to read: " + gridreadfilenames_[i] + ", cannot be found!"); + } + string funcl = getLabel() + ".bias"; + BiasGrid_ = Grid::create(funcl, args, gridfile, gmin_t, gmax_t, gbin_t, sparsegrid, spline, true); + gridfile.close(); + if(BiasGrid_->getDimension() != args.size()) { + error("mismatch between dimensionality of input grid and number of arguments"); + } + if(getPntrToArgument(i)->isPeriodic() != BiasGrid_->getIsPeriodic()[0]) { + error("periodicity mismatch between arguments and input bias"); + } + log.printf(" Restarting from %s:",gridreadfilenames_[i].c_str()); + if(getRestart()) restartedFromGrid=true; + } else { + if(!sparsegrid) {BiasGrid_=new Grid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} + else {BiasGrid_=new SparseGrid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} + std::vector actualmin=BiasGrid_->getMin(); + std::vector actualmax=BiasGrid_->getMax(); + if(gmin_t[0]!=actualmin[0]) log<<" WARNING: GRID_MIN["<link(*this); ifiles.push_back(ifile); ifilesnames.push_back(fname); - if(ifile->FileExist(fname)){ + if(ifile->FileExist(fname)) { ifile->open(fname); - if(getRestart()&&!restartedFromGrid){ + if(getRestart()&&!restartedFromGrid) { log.printf(" Restarting from %s:",ifilesnames[k].c_str()); readGaussians(i,ifiles[k]); } @@ -707,106 +707,108 @@ isFirstStep(true) if(comm.Get_rank()==0 && walkers_mpi) multi_sim_comm.Barrier(); // open hills files for writing - for(unsigned i=0;ilink(*this); - // if MPI multiple walkers, only rank 0 will write to file - if(walkers_mpi){ - int r=0; - if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); - comm.Bcast(r,0); - if(r>0) ifilesnames[mw_id_*hillsfname.size()+i]="/dev/null"; - ofile->enforceSuffix(""); - } - if(mw_n_>1) ofile->enforceSuffix(""); - ofile->open(ifilesnames[mw_id_*hillsfname.size()+i]); - if(fmt.length()>0) ofile->fmtField(fmt); - ofile->addConstantField("multivariate"); - if(doInt_[i]) { - ofile->addConstantField("lower_int").printField("lower_int",lowI_[i]); - ofile->addConstantField("upper_int").printField("upper_int",uppI_[i]); - } - ofile->setHeavyFlush(); - // output periodicities of variables - ofile->setupPrintValue( getPntrToArgument(i) ); - // push back - hillsOfiles_.push_back(ofile); - } - - // Dump grid to files - if(wgridstride_ > 0) { - for(unsigned i = 0; i < gridfilenames_.size(); ++i) { + for(unsigned i=0; ilink(*this); - string gridfname_tmp = gridfilenames_[i]; + // if MPI multiple walkers, only rank 0 will write to file if(walkers_mpi) { - int r = 0; - if(comm.Get_rank() == 0) { - r = multi_sim_comm.Get_rank(); - } - comm.Bcast(r, 0); - if(r>0) { - gridfname_tmp = "/dev/null"; - } - ofile->enforceSuffix(""); + int r=0; + if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); + comm.Bcast(r,0); + if(r>0) ifilesnames[mw_id_*hillsfname.size()+i]="/dev/null"; + ofile->enforceSuffix(""); } if(mw_n_>1) ofile->enforceSuffix(""); - ofile->open(gridfname_tmp); + ofile->open(ifilesnames[mw_id_*hillsfname.size()+i]); + if(fmt.length()>0) ofile->fmtField(fmt); + ofile->addConstantField("multivariate"); + if(doInt_[i]) { + ofile->addConstantField("lower_int").printField("lower_int",lowI_[i]); + ofile->addConstantField("upper_int").printField("upper_int",uppI_[i]); + } ofile->setHeavyFlush(); - gridfiles_.push_back(ofile); - } + // output periodicities of variables + ofile->setupPrintValue( getPntrToArgument(i) ); + // push back + hillsOfiles_.push_back(ofile); + } + + // Dump grid to files + if(wgridstride_ > 0) { + for(unsigned i = 0; i < gridfilenames_.size(); ++i) { + OFile *ofile = new OFile(); + ofile->link(*this); + string gridfname_tmp = gridfilenames_[i]; + if(walkers_mpi) { + int r = 0; + if(comm.Get_rank() == 0) { + r = multi_sim_comm.Get_rank(); + } + comm.Bcast(r, 0); + if(r>0) { + gridfname_tmp = "/dev/null"; + } + ofile->enforceSuffix(""); + } + if(mw_n_>1) ofile->enforceSuffix(""); + ofile->open(gridfname_tmp); + ofile->setHeavyFlush(); + gridfiles_.push_back(ofile); + } } log<<" Bibliography "<1||walkers_mpi) log< center(1); - vector sigma(1); - double height; - int nhills=0; - bool multivariate=false; - - std::vector tmpvalues; - tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); - - while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)){; - nhills++; - if(welltemp_){height*=(biasf_-1.0)/biasf_;} - addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); - } - log.printf(" %d Gaussians read\n",nhills); + vector center(1); + vector sigma(1); + double height; + int nhills=0; + bool multivariate=false; + + std::vector tmpvalues; + tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); + + while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)) { + ; + nhills++; + if(welltemp_) {height*=(biasf_-1.0)/biasf_;} + addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); + } + log.printf(" %d Gaussians read\n",nhills); } bool PBMetaD::readChunkOfGaussians(unsigned iarg, IFile *ifile, unsigned n) { - vector center(1); - vector sigma(1); - double height; - unsigned nhills=0; - bool multivariate=false; - std::vector tmpvalues; - tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); - - while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)){; - if(welltemp_){height*=(biasf_-1.0)/biasf_;} - addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); - if(nhills==n){ + vector center(1); + vector sigma(1); + double height; + unsigned nhills=0; + bool multivariate=false; + std::vector tmpvalues; + tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); + + while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)) { + ; + if(welltemp_) {height*=(biasf_-1.0)/biasf_;} + addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); + if(nhills==n) { log.printf(" %u Gaussians read\n",nhills); return true; + } + nhills++; } - nhills++; - } - log.printf(" %u Gaussians read\n",nhills); - return false; + log.printf(" %u Gaussians read\n",nhills); + return false; } void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile) @@ -814,17 +816,17 @@ void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile) ofile->printField("time",getTimeStep()*getStep()); ofile->printField(getPntrToArgument(iarg),hill.center[0]); - if(hill.multivariate){ + if(hill.multivariate) { ofile->printField("multivariate","true"); double lower = sqrt(1./hill.sigma[0]); ofile->printField("sigma_"+getPntrToArgument(iarg)->getName()+"_"+ - getPntrToArgument(iarg)->getName(),lower); + getPntrToArgument(iarg)->getName(),lower); } else { ofile->printField("multivariate","false"); ofile->printField("sigma_"+getPntrToArgument(iarg)->getName(),hill.sigma[0]); } double height=hill.height; - if(welltemp_) height *= biasf_/(biasf_-1.0); + if(welltemp_) height *= biasf_/(biasf_-1.0); ofile->printField("height",height); ofile->printField("biasf",biasf_); if(mw_n_>1) ofile->printField("clock",int(std::time(0))); @@ -833,128 +835,128 @@ void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile) void PBMetaD::addGaussian(unsigned iarg, const Gaussian& hill) { - if(!grid_){hills_[iarg].push_back(hill);} - else{ - vector nneighb=getGaussianSupport(iarg, hill); - vector neighbors=BiasGrids_[iarg]->getNeighbors(hill.center,nneighb); - vector der(1); - vector xx(1); - if(comm.Get_size()==1){ - for(unsigned i=0;igetPoint(ineigh,xx); - double bias=evaluateGaussian(iarg,xx,hill,&der[0]); - BiasGrids_[iarg]->addValueAndDerivatives(ineigh,bias,der); - } - } else { - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - vector allder(neighbors.size(),0.0); - vector allbias(neighbors.size(),0.0); - for(unsigned i=rank;igetPoint(ineigh,xx); - allbias[i]=evaluateGaussian(iarg,xx,hill,&allder[i]); - } - comm.Sum(allbias); - comm.Sum(allder); - for(unsigned i=0;iaddValueAndDerivatives(ineigh,allbias[i],der); + if(!grid_) {hills_[iarg].push_back(hill);} + else { + vector nneighb=getGaussianSupport(iarg, hill); + vector neighbors=BiasGrids_[iarg]->getNeighbors(hill.center,nneighb); + vector der(1); + vector xx(1); + if(comm.Get_size()==1) { + for(unsigned i=0; igetPoint(ineigh,xx); + double bias=evaluateGaussian(iarg,xx,hill,&der[0]); + BiasGrids_[iarg]->addValueAndDerivatives(ineigh,bias,der); + } + } else { + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + vector allder(neighbors.size(),0.0); + vector allbias(neighbors.size(),0.0); + for(unsigned i=rank; igetPoint(ineigh,xx); + allbias[i]=evaluateGaussian(iarg,xx,hill,&allder[i]); + } + comm.Sum(allbias); + comm.Sum(allder); + for(unsigned i=0; iaddValueAndDerivatives(ineigh,allbias[i],der); + } } } - } } vector PBMetaD::getGaussianSupport(unsigned iarg, const Gaussian& hill) { - vector nneigh; - double cutoff; - if(hill.multivariate){ - double maxautoval=1./hill.sigma[0]; - cutoff=sqrt(2.0*DP2CUTOFF*maxautoval); - } else { - cutoff=sqrt(2.0*DP2CUTOFF)*hill.sigma[0]; - } - - if(doInt_[iarg]){ - if(hill.center[0]+cutoff > uppI_[iarg] || hill.center[0]-cutoff < lowI_[iarg]) { - // in this case, we updated the entire grid to avoid problems - return BiasGrids_[iarg]->getNbin(); - } else { - nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0]))); - return nneigh; - } - } - - nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0])) ); - - return nneigh; + vector nneigh; + double cutoff; + if(hill.multivariate) { + double maxautoval=1./hill.sigma[0]; + cutoff=sqrt(2.0*DP2CUTOFF*maxautoval); + } else { + cutoff=sqrt(2.0*DP2CUTOFF)*hill.sigma[0]; + } + + if(doInt_[iarg]) { + if(hill.center[0]+cutoff > uppI_[iarg] || hill.center[0]-cutoff < lowI_[iarg]) { + // in this case, we updated the entire grid to avoid problems + return BiasGrids_[iarg]->getNbin(); + } else { + nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0]))); + return nneigh; + } + } + + nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0])) ); + + return nneigh; } double PBMetaD::getBiasAndDerivatives(unsigned iarg, const vector& cv, double* der) { - double bias=0.0; - if(!grid_){ - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - for(unsigned i=rank;i vder(1); - bias = BiasGrids_[iarg]->getValueAndDerivatives(cv,vder); - der[0] = vder[0]; - }else{ - bias = BiasGrids_[iarg]->getValue(cv); - } - } - - return bias; + double bias=0.0; + if(!grid_) { + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + for(unsigned i=rank; i vder(1); + bias = BiasGrids_[iarg]->getValueAndDerivatives(cv,vder); + der[0] = vder[0]; + } else { + bias = BiasGrids_[iarg]->getValue(cv); + } + } + + return bias; } double PBMetaD::evaluateGaussian(unsigned iarg, const vector& cv, const Gaussian& hill, double* der) { - double bias=0.0; - // I use a pointer here because cv is const (and should be const) - // but when using doInt it is easier to locally replace cv[0] with - // the upper/lower limit in case it is out of range - const double *pcv=NULL; - double tmpcv[1]; // tmp array with cv (to be used with doInt_) - tmpcv[0]=cv[0]; - bool isOutOfInt = false; - if(doInt_[iarg]){ - if(cv[0]uppI_[iarg]) { tmpcv[0]=uppI_[iarg]; isOutOfInt = true; } - } - pcv=&(tmpcv[0]); - - if(hill.multivariate){ - double dp = difference(iarg, hill.center[0], pcv[0]); - double dp2 = 0.5 * dp * dp * hill.sigma[0]; - if(dp2uppI_[iarg]) { tmpcv[0]=uppI_[iarg]; isOutOfInt = true; } + } + pcv=&(tmpcv[0]); + + if(hill.multivariate) { + double dp = difference(iarg, hill.center[0], pcv[0]); + double dp2 = 0.5 * dp * dp * hill.sigma[0]; + if(dp2 cv(getNumberOfArguments()); - vector bias(getNumberOfArguments()); - vector thissigma(getNumberOfArguments()); - vector height(getNumberOfArguments()); - vector cv_tmp(1); - vector sigma_tmp(1); - double norm = 0.0; - double bmin = 1.0e+19; - for(unsigned i=0; i all_cv(mpi_nw_*cv.size(), 0.0); - std::vector all_sigma(mpi_nw_*getNumberOfArguments(), 0.0); - std::vector all_height(mpi_nw_*height.size(), 0.0); - if(comm.Get_rank()==0){ - // fill in value - for(unsigned i=0; i cv(getNumberOfArguments()); + vector bias(getNumberOfArguments()); + vector thissigma(getNumberOfArguments()); + vector height(getNumberOfArguments()); + vector cv_tmp(1); + vector sigma_tmp(1); + double norm = 0.0; + double bmin = 1.0e+19; + for(unsigned i=0; i all_cv(mpi_nw_*cv.size(), 0.0); + std::vector all_sigma(mpi_nw_*getNumberOfArguments(), 0.0); + std::vector all_height(mpi_nw_*height.size(), 0.0); + if(comm.Get_rank()==0) { + // fill in value + for(unsigned i=0; i0 && (getStep()%wgridstride_==0 || getCPT())) { - int r = 0; - if(walkers_mpi) { - if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); - comm.Bcast(r,0); - } - if(r==0) { - for(unsigned i=0; irewind(); - BiasGrids_[i]->writeToFile(*gridfiles_[i]); - gridfiles_[i]->flush(); - } - } - } + // write grid files + if(wgridstride_>0 && (getStep()%wgridstride_==0 || getCPT())) { + int r = 0; + if(walkers_mpi) { + if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); + comm.Bcast(r,0); + } + if(r==0) { + for(unsigned i=0; irewind(); + BiasGrids_[i]->writeToFile(*gridfiles_[i]); + gridfiles_[i]->flush(); + } + } + } // if multiple walkers and time to read Gaussians - if(mw_n_>1 && getStep()%mw_rstride_==0){ - for(int j=0;j1 && getStep()%mw_rstride_==0) { + for(int j=0; jisOpen())){ + // if the file is not open yet + if(!(ifiles[k]->isOpen())) { // check if it exists now and open it! if(ifiles[k]->FileExist(ifilesnames[k])) { ifiles[k]->open(ifilesnames[k]); ifiles[k]->reset(false); } - // otherwise read the new Gaussians + // otherwise read the new Gaussians } else { log.printf(" Reading hills from %s:",ifilesnames[k].c_str()); readGaussians(i,ifiles[k]); @@ -1131,21 +1133,21 @@ void PBMetaD::update() } -/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height +/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector &tmpvalues, vector ¢er, vector &sigma, double &height, bool &multivariate) { double dummy; multivariate=false; - if(ifile->scanField("time",dummy)){ + if(ifile->scanField("time",dummy)) { ifile->scanField( &tmpvalues[0] ); - if( tmpvalues[0].isPeriodic() && ! getPntrToArgument(iarg)->isPeriodic() ){ - error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); - } else if( tmpvalues[0].isPeriodic() ){ - std::string imin, imax; tmpvalues[0].getDomain( imin, imax ); - std::string rmin, rmax; getPntrToArgument(iarg)->getDomain( rmin, rmax ); - if( imin!=rmin || imax!=rmax ){ - error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); - } + if( tmpvalues[0].isPeriodic() && ! getPntrToArgument(iarg)->isPeriodic() ) { + error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); + } else if( tmpvalues[0].isPeriodic() ) { + std::string imin, imax; tmpvalues[0].getDomain( imin, imax ); + std::string rmin, rmax; getPntrToArgument(iarg)->getDomain( rmin, rmax ); + if( imin!=rmin || imax!=rmax ) { + error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); + } } center[0]=tmpvalues[0].get(); std::string sss; @@ -1154,9 +1156,9 @@ bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector &tmpvalues, else if(sss=="false") multivariate=false; else plumed_merror("cannot parse multivariate = "+ sss); - if(multivariate){ + if(multivariate) { ifile->scanField("sigma_"+getPntrToArgument(iarg)->getName()+"_"+ - getPntrToArgument(iarg)->getName(),sigma[0]); + getPntrToArgument(iarg)->getName(),sigma[0]); sigma[0] = 1./(sigma[0]*sigma[0]); } else { ifile->scanField("sigma_"+getPntrToArgument(iarg)->getName(),sigma[0]); @@ -1168,9 +1170,9 @@ bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector &tmpvalues, if(ifile->FieldExist("upper_int")) ifile->scanField("upper_int",dummy); ifile->scanField(); return true; - } else { - return false; - } + } else { + return false; + } } } diff --git a/src/bias/Restraint.cpp b/src/bias/Restraint.cpp index fc36068209..8bb3df2027 100644 --- a/src/bias/Restraint.cpp +++ b/src/bias/Restraint.cpp @@ -26,16 +26,16 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS RESTRAINT /* -Adds harmonic and/or linear restraints on one or more variables. +Adds harmonic and/or linear restraints on one or more variables. Either or both of SLOPE and KAPPA must be present to specify the linear and harmonic force constants -respectively. The resulting potential is given by: +respectively. The resulting potential is given by: \f[ \sum_i \frac{k_i}{2} (x_i-a_i)^2 + m_i*(x_i-a_i) \f]. @@ -43,7 +43,7 @@ respectively. The resulting potential is given by: The number of components for any vector of force constants must be equal to the number of arguments to the action. -Additional material and examples can be also found in the tutorial \ref belfast-4 +Additional material and examples can be also found in the tutorial \ref belfast-4 \par Examples The following input tells plumed to restrain the distance between atoms 3 and 5 @@ -60,7 +60,7 @@ PRINT ARG=restraint.bias */ //+ENDPLUMEDOC -class Restraint : public Bias{ +class Restraint : public Bias { std::vector at; std::vector kappa; std::vector slope; @@ -73,20 +73,20 @@ class Restraint : public Bias{ PLUMED_REGISTER_ACTION(Restraint,"RESTRAINT") -void Restraint::registerKeywords(Keywords& keys){ - Bias::registerKeywords(keys); - keys.use("ARG"); - keys.add("compulsory","SLOPE","0.0","specifies that the restraint is linear and what the values of the force constants on each of the variables are"); - keys.add("compulsory","KAPPA","0.0","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); - keys.add("compulsory","AT","the position of the restraint"); - keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); +void Restraint::registerKeywords(Keywords& keys) { + Bias::registerKeywords(keys); + keys.use("ARG"); + keys.add("compulsory","SLOPE","0.0","specifies that the restraint is linear and what the values of the force constants on each of the variables are"); + keys.add("compulsory","KAPPA","0.0","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); + keys.add("compulsory","AT","the position of the restraint"); + keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); } Restraint::Restraint(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -at(getNumberOfArguments()), -kappa(getNumberOfArguments(),0.0), -slope(getNumberOfArguments(),0.0) + PLUMED_BIAS_INIT(ao), + at(getNumberOfArguments()), + kappa(getNumberOfArguments(),0.0), + slope(getNumberOfArguments(),0.0) { parseVector("SLOPE",slope); parseVector("KAPPA",kappa); @@ -94,13 +94,13 @@ slope(getNumberOfArguments(),0.0) checkRead(); log.printf(" at"); - for(unsigned i=0;i0) simtemp*=plumed.getAtoms().getKBoltzmann(); - else simtemp=plumed.getAtoms().getKbT(); - if(simtemp==0) error("The MD engine does not pass the temperature to plumed so you have to specify it using TEMP"); - // Create something to hold the weight - addValue(); setNotPeriodic(); + simtemp=0.; parse("TEMP",simtemp); + if(simtemp>0) simtemp*=plumed.getAtoms().getKBoltzmann(); + else simtemp=plumed.getAtoms().getKbT(); + if(simtemp==0) error("The MD engine does not pass the temperature to plumed so you have to specify it using TEMP"); + // Create something to hold the weight + addValue(); setNotPeriodic(); } -void ReweightBase::calculate(){ +void ReweightBase::calculate() { double weight = getLogWeight(); setValue( weight ); } diff --git a/src/bias/ReweightBase.h b/src/bias/ReweightBase.h index e3dfd35adb..f39e94d705 100644 --- a/src/bias/ReweightBase.h +++ b/src/bias/ReweightBase.h @@ -28,9 +28,9 @@ namespace PLMD { namespace bias { -class ReweightBase : -public ActionWithValue, -public ActionWithArguments +class ReweightBase : + public ActionWithValue, + public ActionWithArguments { protected: /// The temperature at which you are running the simulation @@ -38,11 +38,11 @@ public ActionWithArguments public: static void registerKeywords(Keywords&); explicit ReweightBase(const ActionOptions&ao); - unsigned getNumberOfDerivatives(){ return 0; } + unsigned getNumberOfDerivatives() { return 0; } void calculate(); virtual double getLogWeight() const = 0; - void apply(){} -}; + void apply() {} +}; } } diff --git a/src/bias/ReweightBias.cpp b/src/bias/ReweightBias.cpp index d5459df962..d0b2d90a3e 100644 --- a/src/bias/ReweightBias.cpp +++ b/src/bias/ReweightBias.cpp @@ -26,24 +26,24 @@ /* Calculate weights for ensemble averages that negate the effect the bias has on the region of phase space explored -If a static or pseudo-static bias \f$V(x,t')\f$ is acting on +If a static or pseudo-static bias \f$V(x,t')\f$ is acting on the system we can remove the bias and get the unbiased probability distribution using: \f[ -\langle P(s',t) \rangle = \frac{ \sum_{t'}^t \delta( s(x) - s' ) \exp\left( +\frac{V(x,t')}{k_B T} \right) }{ \sum_t'^t \exp\left( +\frac{V(x,t')}{k_B T} \right) } +\langle P(s',t) \rangle = \frac{ \sum_{t'}^t \delta( s(x) - s' ) \exp\left( +\frac{V(x,t')}{k_B T} \right) }{ \sum_t'^t \exp\left( +\frac{V(x,t')}{k_B T} \right) } \f] -The weights calculated by this action are equal to \f$\exp\left( +\frac{V(x,t')}{k_B T} \right)\f$ these weights can then be used in any action -that computes ensemble averages. For example this action can be used in tandem with \ref HISTOGRAM or \ref AVERAGE. +The weights calculated by this action are equal to \f$\exp\left( +\frac{V(x,t')}{k_B T} \right)\f$ these weights can then be used in any action +that computes ensemble averages. For example this action can be used in tandem with \ref HISTOGRAM or \ref AVERAGE. \par Examples -In the following example there is a fixed restraint on the distance between atoms 1 and 2. Clearly, this +In the following example there is a fixed restraint on the distance between atoms 1 and 2. Clearly, this restraint will have an effect on the region of phase space that will be sampled when an MD simulation is run using this variable. Consequently, when the histogram as a function of the distance, \f$x\f$, is accumulated, we use reweighting into order to discount the effect of the bias from our final histogram. -\verbatim +\verbatim x: DISTANCE ATOMS=1,2 RESTRAINT ARG=x SLOPE=1.0 AT=0.0 as: REWEIGHT_BIAS TEMP=300 @@ -77,21 +77,21 @@ class ReweightBias : public ReweightBase { PLUMED_REGISTER_ACTION(ReweightBias,"REWEIGHT_BIAS") -void ReweightBias::registerKeywords(Keywords& keys ){ +void ReweightBias::registerKeywords(Keywords& keys ) { ReweightBase::registerKeywords( keys ); keys.remove("ARG"); keys.add("compulsory","ARG","*.bias","the biases that must be taken into account when reweighting"); } ReweightBias::ReweightBias(const ActionOptions&ao): -Action(ao), -ReweightBase(ao) + Action(ao), + ReweightBase(ao) { } double ReweightBias::getLogWeight() const { - // Retrieve the bias - double bias=0.0; for(unsigned i=0;i all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - log.printf(" using the following biases in reweighting "); - for(unsigned j=0;jgetLabel() + ".bias"; - if( all[j]->exists(flab) ){ - biases.push_back( all[j]->copyOutput(flab) ); - log.printf(" %s", flab.c_str()); - } - } - log.printf("\n"); + parse("REWEIGHT_TEMP",rtemp); + log.printf(" reweighting simulation to probabilities at temperature %f\n",rtemp); + rtemp*=plumed.getAtoms().getKBoltzmann(); + + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + log.printf(" using the following biases in reweighting "); + for(unsigned j=0; jgetLabel() + ".bias"; + if( all[j]->exists(flab) ) { + biases.push_back( all[j]->copyOutput(flab) ); + log.printf(" %s", flab.c_str()); + } + } + log.printf("\n"); } -void ReweightTemperature::prepare(){ - plumed.getAtoms().setCollectEnergy(true); +void ReweightTemperature::prepare() { + plumed.getAtoms().setCollectEnergy(true); } double ReweightTemperature::getLogWeight() const { - // Retrieve the bias - double bias=0.0; for(unsigned i=0;iget(); - double energy=plumed.getAtoms().getEnergy()+bias; - return -( (1.0/rtemp) - (1.0/simtemp) )*(energy+bias); + // Retrieve the bias + double bias=0.0; for(unsigned i=0; iget(); + double energy=plumed.getAtoms().getEnergy()+bias; + return -( (1.0/rtemp) - (1.0/simtemp) )*(energy+bias); } } diff --git a/src/bias/UWalls.cpp b/src/bias/UWalls.cpp index 04626b5db6..0f096f11b1 100644 --- a/src/bias/UWalls.cpp +++ b/src/bias/UWalls.cpp @@ -26,16 +26,16 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS UPPER_WALLS /* Defines a wall for the value of one or more collective variables, - which limits the region of the phase space accessible during the simulation. + which limits the region of the phase space accessible during the simulation. -The restraining potential starts acting on the system when the value of the CV is greater -(in the case of UPPER_WALLS) or lower (in the case of LOWER_WALLS) than a certain limit \f$a_i\f$ (AT) +The restraining potential starts acting on the system when the value of the CV is greater +(in the case of UPPER_WALLS) or lower (in the case of LOWER_WALLS) than a certain limit \f$a_i\f$ (AT) minus an offset \f$o_i\f$ (OFFSET). The expression for the bias due to the wall is given by: @@ -43,15 +43,15 @@ The expression for the bias due to the wall is given by: \sum_i {k_i}((x_i-a_i+o_i)/s_i)^e_i \f$ -\f$k_i\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s_i\f$ (EPS) a rescaling factor and +\f$k_i\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s_i\f$ (EPS) a rescaling factor and \f$e_i\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFFSET = 0. \par Examples -The following input tells plumed to add both a lower and an upper walls on the distance +The following input tells plumed to add both a lower and an upper walls on the distance between atoms 3 and 5 and the distance between atoms 2 and 4. The lower and upper limits -are defined at different values. The strength of the walls is the same for the four cases. -It also tells plumed to print the energy of the walls. +are defined at different values. The strength of the walls is the same for the four cases. +It also tells plumed to print the energy of the walls. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 @@ -64,7 +64,7 @@ PRINT ARG=uwall.bias,lwall.bias */ //+ENDPLUMEDOC -class UWalls : public Bias{ +class UWalls : public Bias { std::vector at; std::vector kappa; std::vector exp; @@ -78,7 +78,7 @@ class UWalls : public Bias{ PLUMED_REGISTER_ACTION(UWalls,"UPPER_WALLS") -void UWalls::registerKeywords(Keywords& keys){ +void UWalls::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall."); @@ -90,12 +90,12 @@ void UWalls::registerKeywords(Keywords& keys){ } UWalls::UWalls(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -at(getNumberOfArguments(),0), -kappa(getNumberOfArguments(),0.0), -exp(getNumberOfArguments(),2.0), -eps(getNumberOfArguments(),1.0), -offset(getNumberOfArguments(),0.0) + PLUMED_BIAS_INIT(ao), + at(getNumberOfArguments(),0), + kappa(getNumberOfArguments(),0.0), + exp(getNumberOfArguments(),2.0), + eps(getNumberOfArguments(),1.0), + offset(getNumberOfArguments(),0.0) { // Note : the sizes of these vectors are checked automatically by parseVector parseVector("OFFSET",offset); @@ -106,28 +106,28 @@ offset(getNumberOfArguments(),0.0) checkRead(); log.printf(" at"); - for(unsigned i=0;i plugins; static map pluginmap; -static int register_cb(void *v, vmdplugin_t *p){ +static int register_cb(void *v, vmdplugin_t *p) { //const char *key = p->name; const auto ret = pluginmap.insert ( std::pair(string(p->name),plugins.size()) ); - if (ret.second==false) { - //cerr<<"MOLFILE: found duplicate plugin for "<(p)); - } + if (ret.second==false) { + //cerr<<"MOLFILE: found duplicate plugin for "<(p)); + } return VMDPLUGIN_SUCCESS; } #endif @@ -195,15 +195,15 @@ class Driver : public CLTool { }; template -void Driver::registerKeywords( Keywords& keys ){ +void Driver::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.isDriver(); keys.addFlag("--help-debug",false,"print special options that can be used to create regtests"); keys.add("compulsory","--plumed","plumed.dat","specify the name of the plumed input file"); keys.add("compulsory","--timestep","1.0","the timestep that was used in the calculation that produced this trajectory in picoseconds"); keys.add("compulsory","--trajectory-stride","1","the frequency with which frames were output to this trajectory during the simulation" #ifdef __PLUMED_HAS_XDRFILE - " (0 means that the number of the step is read from the trajectory file," - " currently working only for xtc/trr files read with --ixtc/--trr)" + " (0 means that the number of the step is read from the trajectory file," + " currently working only for xtc/trr files read with --ixtc/--trr)" #endif ); keys.add("compulsory","--multi","0","set number of replicas for multi environment (needs mpi)"); @@ -225,7 +225,7 @@ void Driver::registerKeywords( Keywords& keys ){ keys.add("optional","--box","comma-separated box dimensions (3 for orthorombic, 9 for generic)"); keys.add("optional","--natoms","provides number of atoms - only used if file format does not contain number of atoms"); keys.add("optional","--debug-forces","output a file containing the forces due to the bias evaluated using numerical derivatives " - "and using the analytical derivatives implemented in plumed"); + "and using the analytical derivatives implemented in plumed"); keys.add("hidden","--debug-float","turns on the single precision version (to check float interface)"); keys.add("hidden","--debug-dd","use a fake domain decomposition"); keys.add("hidden","--debug-pd","use a fake particle decomposition"); @@ -234,56 +234,56 @@ void Driver::registerKeywords( Keywords& keys ){ #ifdef __PLUMED_HAS_MOLFILE_PLUGINS MOLFILE_INIT_ALL MOLFILE_REGISTER_ALL(NULL, register_cb) - for(int i=0;iname); - string mm=" molfile: the trajectory in "+string(plugins[i]->name)+" format " ; - //cerr<<"REGISTERING "<name); + string mm=" molfile: the trajectory in "+string(plugins[i]->name)+" format " ; + //cerr<<"REGISTERING "< Driver::Driver(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { - inputdata=commandline; + inputdata=commandline; } template -string Driver::description()const{ return "analyze trajectories with plumed"; } +string Driver::description()const { return "analyze trajectories with plumed"; } template -int Driver::main(FILE* in,FILE*out,Communicator& pc){ +int Driver::main(FILE* in,FILE*out,Communicator& pc) { Units units; PDB pdb; // Parse everything bool printhelpdebug; parseFlag("--help-debug",printhelpdebug); - if( printhelpdebug ){ - fprintf(out,"%s", - "Additional options for debug (only to be used in regtest):\n" - " [--debug-float] : turns on the single precision version (to check float interface)\n" - " [--debug-dd] : use a fake domain decomposition\n" - " [--debug-pd] : use a fake particle decomposition\n" - ); - return 0; + if( printhelpdebug ) { + fprintf(out,"%s", + "Additional options for debug (only to be used in regtest):\n" + " [--debug-float] : turns on the single precision version (to check float interface)\n" + " [--debug-dd] : use a fake domain decomposition\n" + " [--debug-pd] : use a fake particle decomposition\n" + ); + return 0; } // Are we reading trajectory data bool noatoms; parseFlag("--noatoms",noatoms); - std::string fakein; + std::string fakein; bool debugfloat=parse("--debug-float",fakein); - if(debugfloat && sizeof(real)!=sizeof(float)){ - CLTool* cl=cltoolRegister().create(CLToolOptions("driver-float")); //new Driver(*this); - cl->setInputData(this->getInputData()); - int ret=cl->main(in,out,pc); - delete cl; - return ret; + if(debugfloat && sizeof(real)!=sizeof(float)) { + CLTool* cl=cltoolRegister().create(CLToolOptions("driver-float")); //new Driver(*this); + cl->setInputData(this->getInputData()); + int ret=cl->main(in,out,pc); + delete cl; + return ret; } bool debug_pd=parse("--debug-pd",fakein); bool debug_dd=parse("--debug-dd",fakein); - if( debug_pd || debug_dd ){ + if( debug_pd || debug_dd ) { if(noatoms) error("cannot debug without atoms"); } @@ -292,7 +292,7 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ parse("--multi",multi); Communicator intracomm; Communicator intercomm; - if(multi){ + if(multi) { int ntot=pc.Get_size(); int nintra=ntot/multi; if(multi*nintra!=ntot) error("invalid number of processes for multi environment"); @@ -306,20 +306,20 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ bool debug_grex=parse("--debug-grex",fakein); int grex_stride=0; FILE*grex_log=NULL; - if(debug_grex){ + if(debug_grex) { if(noatoms) error("must have atoms to debug_grex"); if(multi<2) error("--debug_grex needs --multi with at least two replicas"); Tools::convert(fakein,grex_stride); string n; Tools::convert(intercomm.Get_rank(),n); string file; parse("--debug-grex-log",file); - if(file.length()>0){ + if(file.length()>0) { file+="."+n; grex_log=fopen(file.c_str(),"w"); } } -// Read the plumed input file name +// Read the plumed input file name string plumedFile; parse("--plumed",plumedFile); // the timestep double t; parse("--timestep",t); @@ -327,11 +327,11 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ // the stride unsigned stride; parse("--trajectory-stride",stride); // are we writing forces - string dumpforces(""), debugforces(""), dumpforcesFmt("%f");; + string dumpforces(""), debugforces(""), dumpforcesFmt("%f");; bool dumpfullvirial=false; - if(!noatoms){ - parse("--dump-forces",dumpforces); - parse("--debug-forces",debugforces); + if(!noatoms) { + parse("--dump-forces",dumpforces); + parse("--debug-forces",debugforces); } if(dumpforces!="" || debugforces!="" ) parse("--dump-forces-fmt",dumpforcesFmt); if(dumpforces!="") parseFlag("--dump-full-virial",dumpfullvirial); @@ -340,11 +340,11 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ string trajectory_fmt; - bool use_molfile=false; + bool use_molfile=false; #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - molfile_plugin_t *api=NULL; + molfile_plugin_t *api=NULL; void *h_in=NULL; - molfile_timestep_t ts_in; // this is the structure that has the timestep + molfile_timestep_t ts_in; // this is the structure that has the timestep ts_in.coords=NULL; ts_in.A=-1; // we use this to check whether cell is provided or not #endif @@ -354,99 +354,99 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ bool pbc_cli_given=false; vector pbc_cli_box(9,0.0); int command_line_natoms=-1; - if(!noatoms){ - std::string traj_xyz; parse("--ixyz",traj_xyz); - std::string traj_gro; parse("--igro",traj_gro); - std::string traj_xtc; - std::string traj_trr; + if(!noatoms) { + std::string traj_xyz; parse("--ixyz",traj_xyz); + std::string traj_gro; parse("--igro",traj_gro); + std::string traj_xtc; + std::string traj_trr; #ifdef __PLUMED_HAS_XDRFILE - parse("--ixtc",traj_xtc); - parse("--itrr",traj_trr); + parse("--ixtc",traj_xtc); + parse("--itrr",traj_trr); #endif #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - for(int i=0;iname); - string traj_molfile; - parse(molfile_key,traj_molfile); - if(traj_molfile.length()>0){ - fprintf(out,"\nDRIVER: Found molfile format trajectory %s with name %s\n",plugins[i]->name,traj_molfile.c_str()); - trajectoryFile=traj_molfile; - trajectory_fmt=string(plugins[i]->name); - use_molfile=true; - api = plugins[i]; - } - } + for(int i=0; iname); + string traj_molfile; + parse(molfile_key,traj_molfile); + if(traj_molfile.length()>0) { + fprintf(out,"\nDRIVER: Found molfile format trajectory %s with name %s\n",plugins[i]->name,traj_molfile.c_str()); + trajectoryFile=traj_molfile; + trajectory_fmt=string(plugins[i]->name); + use_molfile=true; + api = plugins[i]; + } + } #endif - { // check that only one fmt is specified - int nn=0; - if(traj_xyz.length()>0) nn++; - if(traj_gro.length()>0) nn++; - if(traj_xtc.length()>0) nn++; - if(traj_trr.length()>0) nn++; - if(nn>1){ - fprintf(stderr,"ERROR: cannot provide more than one trajectory file\n"); - if(grex_log)fclose(grex_log); - return 1; - } - } - if(traj_xyz.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_xyz; - trajectory_fmt="xyz"; - } - if(traj_gro.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_gro; - trajectory_fmt="gro"; - } - if(traj_xtc.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_xtc; - trajectory_fmt="xdr-xtc"; - } - if(traj_trr.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_trr; - trajectory_fmt="xdr-trr"; - } - if(trajectoryFile.length()==0){ - fprintf(stderr,"ERROR: missing trajectory data\n"); - if(grex_log)fclose(grex_log); - return 1; - } - string lengthUnits(""); parse("--length-units",lengthUnits); - if(lengthUnits.length()>0) units.setLength(lengthUnits); - string chargeUnits(""); parse("--charge-units",chargeUnits); - if(chargeUnits.length()>0) units.setCharge(chargeUnits); - string massUnits(""); parse("--mass-units",massUnits); - if(massUnits.length()>0) units.setMass(massUnits); - - parse("--pdb",pdbfile); - if(pdbfile.length()>0){ - bool check=pdb.read(pdbfile,false,1.0); - if(!check) error("error reading pdb file"); - } - - parse("--mc",mcfile); - - string pbc_cli_list; parse("--box",pbc_cli_list); - if(pbc_cli_list.length()>0) { - pbc_cli_given=true; - vector words=Tools::getWords(pbc_cli_list,","); - if(words.size()==3){ - for(int i=0;i<3;i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[4*i])); - } else if(words.size()==9) { - for(int i=0;i<9;i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[i])); - } else { - string msg="ERROR: cannot parse command-line box "+pbc_cli_list; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } - - } - - parse("--natoms",command_line_natoms); - + { // check that only one fmt is specified + int nn=0; + if(traj_xyz.length()>0) nn++; + if(traj_gro.length()>0) nn++; + if(traj_xtc.length()>0) nn++; + if(traj_trr.length()>0) nn++; + if(nn>1) { + fprintf(stderr,"ERROR: cannot provide more than one trajectory file\n"); + if(grex_log)fclose(grex_log); + return 1; + } + } + if(traj_xyz.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_xyz; + trajectory_fmt="xyz"; + } + if(traj_gro.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_gro; + trajectory_fmt="gro"; + } + if(traj_xtc.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_xtc; + trajectory_fmt="xdr-xtc"; + } + if(traj_trr.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_trr; + trajectory_fmt="xdr-trr"; + } + if(trajectoryFile.length()==0) { + fprintf(stderr,"ERROR: missing trajectory data\n"); + if(grex_log)fclose(grex_log); + return 1; + } + string lengthUnits(""); parse("--length-units",lengthUnits); + if(lengthUnits.length()>0) units.setLength(lengthUnits); + string chargeUnits(""); parse("--charge-units",chargeUnits); + if(chargeUnits.length()>0) units.setCharge(chargeUnits); + string massUnits(""); parse("--mass-units",massUnits); + if(massUnits.length()>0) units.setMass(massUnits); + + parse("--pdb",pdbfile); + if(pdbfile.length()>0) { + bool check=pdb.read(pdbfile,false,1.0); + if(!check) error("error reading pdb file"); + } + + parse("--mc",mcfile); + + string pbc_cli_list; parse("--box",pbc_cli_list); + if(pbc_cli_list.length()>0) { + pbc_cli_given=true; + vector words=Tools::getWords(pbc_cli_list,","); + if(words.size()==3) { + for(int i=0; i<3; i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[4*i])); + } else if(words.size()==9) { + for(int i=0; i<9; i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[i])); + } else { + string msg="ERROR: cannot parse command-line box "+pbc_cli_list; + fprintf(stderr,"%s\n",msg.c_str()); + return 1; + } + + } + + parse("--natoms",command_line_natoms); + } if( debug_dd && debug_pd ) error("cannot use debug-dd and debug-pd at the same time"); - if(debug_pd || debug_dd){ + if(debug_pd || debug_dd) { if( !Communicator::initialized() ) error("needs mpi for debug-pd"); } @@ -455,14 +455,14 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ p.cmd("setRealPrecision",&rr); int checknatoms=-1; long int step=0; - if(Communicator::initialized()){ - if(multi){ + if(Communicator::initialized()) { + if(multi) { if(intracomm.Get_rank()==0) p.cmd("GREX setMPIIntercomm",&intercomm.Get_comm()); p.cmd("GREX setMPIIntracomm",&intracomm.Get_comm()); p.cmd("GREX init"); - } + } p.cmd("setMPIComm",&intracomm.Get_comm()); - } + } p.cmd("setMDLengthUnits",&units.getLength()); p.cmd("setMDChargeUnits",&units.getCharge()); p.cmd("setMDMassUnits",&units.getMass()); @@ -471,7 +471,7 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ p.cmd("setPlumedDat",plumedFile.c_str()); p.cmd("setLog",out); - if(multi){ + if(multi) { string n; Tools::convert(intercomm.Get_rank(),n); trajectoryFile=FileBase::appendSuffix(trajectoryFile,"."+n); @@ -484,57 +484,57 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ #ifdef __PLUMED_HAS_XDRFILE XDRFILE* xd=NULL; #endif - if(!noatoms){ - if (trajectoryFile=="-") - fp=in; - else { - if(use_molfile==true){ + if(!noatoms) { + if (trajectoryFile=="-") + fp=in; + else { + if(use_molfile==true) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS h_in = api->open_file_read(trajectoryFile.c_str(), trajectory_fmt.c_str(), &natoms); - if(natoms==MOLFILE_NUMATOMS_UNKNOWN){ + if(natoms==MOLFILE_NUMATOMS_UNKNOWN) { if(command_line_natoms>=0) natoms=command_line_natoms; else error("this file format does not provide number of atoms; use --natoms on the command line"); } ts_in.coords = new float [3*natoms]; #endif - }else if(trajectory_fmt=="xdr-xtc" || trajectory_fmt=="xdr-trr"){ + } else if(trajectory_fmt=="xdr-xtc" || trajectory_fmt=="xdr-trr") { #ifdef __PLUMED_HAS_XDRFILE - xd=xdrfile_open(trajectoryFile.c_str(),"r"); - if(!xd){ - string msg="ERROR: Error opening trajectory file "+trajectoryFile; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } - if(trajectory_fmt=="xdr-xtc") read_xtc_natoms(&trajectoryFile[0],&natoms); - if(trajectory_fmt=="xdr-trr") read_trr_natoms(&trajectoryFile[0],&natoms); + xd=xdrfile_open(trajectoryFile.c_str(),"r"); + if(!xd) { + string msg="ERROR: Error opening trajectory file "+trajectoryFile; + fprintf(stderr,"%s\n",msg.c_str()); + return 1; + } + if(trajectory_fmt=="xdr-xtc") read_xtc_natoms(&trajectoryFile[0],&natoms); + if(trajectory_fmt=="xdr-trr") read_trr_natoms(&trajectoryFile[0],&natoms); #endif - }else{ - fp=fopen(trajectoryFile.c_str(),"r"); - if(!fp){ - string msg="ERROR: Error opening trajectory file "+trajectoryFile; - fprintf(stderr,"%s\n",msg.c_str()); + } else { + fp=fopen(trajectoryFile.c_str(),"r"); + if(!fp) { + string msg="ERROR: Error opening trajectory file "+trajectoryFile; + fprintf(stderr,"%s\n",msg.c_str()); // cppcheck detects a false positive here. I suppress it: // cppcheck-suppress memleak - return 1; - } - } - } - if(dumpforces.length()>0){ - if(Communicator::initialized() && pc.Get_size()>1){ - string n; - Tools::convert(pc.Get_rank(),n); - dumpforces+="."+n; - } - fp_forces=fopen(dumpforces.c_str(),"w"); - } - if(debugforces.length()>0){ - if(Communicator::initialized() && pc.Get_size()>1){ - string n; - Tools::convert(pc.Get_rank(),n); - debugforces+="."+n; - } - fp_dforces.open(debugforces); - } + return 1; + } + } + } + if(dumpforces.length()>0) { + if(Communicator::initialized() && pc.Get_size()>1) { + string n; + Tools::convert(pc.Get_rank(),n); + dumpforces+="."+n; + } + fp_forces=fopen(dumpforces.c_str(),"w"); + } + if(debugforces.length()>0) { + if(Communicator::initialized() && pc.Get_size()>1) { + string n; + Tools::convert(pc.Get_rank(),n); + debugforces+="."+n; + } + fp_dforces.open(debugforces); + } } std::string line; @@ -560,41 +560,41 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ // random stream to choose decompositions Random rnd; - while(true){ - if(!noatoms){ - if(use_molfile==true){ + while(true) { + if(!noatoms) { + if(use_molfile==true) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - int rc; - rc = api->read_next_timestep(h_in, natoms, &ts_in); - //if(rc==MOLFILE_SUCCESS){ - // printf(" read this one :success \n"); - //} - if(rc==MOLFILE_EOF){ - //printf(" read this one :eof or error \n"); - break; - } + int rc; + rc = api->read_next_timestep(h_in, natoms, &ts_in); + //if(rc==MOLFILE_SUCCESS){ + // printf(" read this one :success \n"); + //} + if(rc==MOLFILE_EOF) { + //printf(" read this one :eof or error \n"); + break; + } #endif - }else if(trajectory_fmt=="xyz" || trajectory_fmt=="gro"){ - if(!Tools::getline(fp,line)) break; - } + } else if(trajectory_fmt=="xyz" || trajectory_fmt=="gro") { + if(!Tools::getline(fp,line)) break; + } } bool first_step=false; - if(!noatoms){ - if(use_molfile==false && (trajectory_fmt=="xyz" || trajectory_fmt=="gro")){ + if(!noatoms) { + if(use_molfile==false && (trajectory_fmt=="xyz" || trajectory_fmt=="gro")) { if(trajectory_fmt=="gro") if(!Tools::getline(fp,line)) error("premature end of trajectory file"); sscanf(line.c_str(),"%100d",&natoms); } } - if(checknatoms<0 && !noatoms){ + if(checknatoms<0 && !noatoms) { pd_nlocal=natoms; pd_start=0; first_step=true; masses.assign(natoms,NAN); charges.assign(natoms,NAN); //case pdb: structure - if(pdbfile.length()>0){ - for(unsigned i=0;i0) { + for(unsigned i=0; i=unsigned(natoms) ) error("atom index in pdb exceeds the number of atoms in trajectory"); @@ -602,26 +602,26 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ charges[index]=pdb.getBeta()[i]; } } - if(mcfile.length()>0){ + if(mcfile.length()>0) { IFile ifile; ifile.open(mcfile); int index; double mass; double charge; - while(ifile.scanField("index",index).scanField("mass",mass).scanField("charge",charge).scanField()){ + while(ifile.scanField("index",index).scanField("mass",mass).scanField("charge",charge).scanField()) { masses[index]=mass; charges[index]=charge; } } - } else if( checknatoms<0 && noatoms ){ - natoms=0; + } else if( checknatoms<0 && noatoms ) { + natoms=0; } - if( checknatoms<0 ){ + if( checknatoms<0 ) { checknatoms=natoms; p.cmd("setNatoms",&natoms); p.cmd("init"); } - if(checknatoms!=natoms){ - std::string stepstr; Tools::convert(step,stepstr); - error("number of atoms in frame " + stepstr + " does not match number of atoms in first frame"); + if(checknatoms!=natoms) { + std::string stepstr; Tools::convert(step,stepstr); + error("number of atoms in frame " + stepstr + " does not match number of atoms in first frame"); } coordinates.assign(3*natoms,real(0.0)); @@ -629,12 +629,12 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ cell.assign(9,real(0.0)); virial.assign(9,real(0.0)); - if( first_step || rnd.U01()>0.5){ - if(debug_pd){ + if( first_step || rnd.U01()>0.5) { + if(debug_pd) { int npe=intracomm.Get_size(); vector loc(npe,0); vector start(npe,0); - for(int i=0;inatoms) cc=natoms-start[i]; loc[i]=cc; @@ -645,14 +645,14 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ intracomm.Bcast(start,0); pd_nlocal=loc[intracomm.Get_rank()]; pd_start=start[intracomm.Get_rank()]; - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { fprintf(out,"\nDRIVER: Reassigning particle decomposition\n"); - fprintf(out,"DRIVER: "); for(int i=0;i::main(FILE* in,FILE*out,Communicator& pc){ dd_coordinates.assign(3*natoms,0.0); dd_forces.assign(3*natoms,0.0); dd_nlocal=0; - for(int i=0;ir)break; + int n; for(n=0; nr)break; plumed_assert(n::main(FILE* in,FILE*out,Communicator& pc){ dd_nlocal++; } } - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { fprintf(out,"\nDRIVER: Reassigning particle decomposition\n"); } p.cmd("setAtomsNlocal",&dd_nlocal); @@ -683,232 +683,232 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ } int plumedStopCondition=0; - if(!noatoms){ - if(use_molfile){ + if(!noatoms) { + if(use_molfile) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - if(pbc_cli_given==false) { - if(ts_in.A>0.0){ // this is negative if molfile does not provide box - // info on the cell: convert using pbcset.tcl from pbctools in vmd distribution - real cosBC=cos(ts_in.alpha*pi/180.); - //double sinBC=sin(ts_in.alpha*pi/180.); - real cosAC=cos(ts_in.beta*pi/180.); - real cosAB=cos(ts_in.gamma*pi/180.); - real sinAB=sin(ts_in.gamma*pi/180.); - real Ax=ts_in.A; - real Bx=ts_in.B*cosAB; - real By=ts_in.B*sinAB; - real Cx=ts_in.C*cosAC; - real Cy=(ts_in.C*ts_in.B*cosBC-Cx*Bx)/By; - real Cz=sqrt(ts_in.C*ts_in.C-Cx*Cx-Cy*Cy); - cell[0]=Ax/10.;cell[1]=0.;cell[2]=0.; - cell[3]=Bx/10.;cell[4]=By/10.;cell[5]=0.; - cell[6]=Cx/10.;cell[7]=Cy/10.;cell[8]=Cz/10.; - } else { - cell[0]=0.0; cell[1]=0.0; cell[2]=0.0; - cell[3]=0.0; cell[4]=0.0; cell[5]=0.0; - cell[6]=0.0; cell[7]=0.0; cell[8]=0.0; - } - }else{ - for(unsigned i=0;i<9;i++)cell[i]=pbc_cli_box[i]; - } - // info on coords - // the order is xyzxyz... - for(unsigned i=0;i<3*natoms;i++){ - coordinates[i]=real(ts_in.coords[i]/10.); //convert to nm - //cerr<<"COOR "<0.0) { // this is negative if molfile does not provide box + // info on the cell: convert using pbcset.tcl from pbctools in vmd distribution + real cosBC=cos(ts_in.alpha*pi/180.); + //double sinBC=sin(ts_in.alpha*pi/180.); + real cosAC=cos(ts_in.beta*pi/180.); + real cosAB=cos(ts_in.gamma*pi/180.); + real sinAB=sin(ts_in.gamma*pi/180.); + real Ax=ts_in.A; + real Bx=ts_in.B*cosAB; + real By=ts_in.B*sinAB; + real Cx=ts_in.C*cosAC; + real Cy=(ts_in.C*ts_in.B*cosBC-Cx*Bx)/By; + real Cz=sqrt(ts_in.C*ts_in.C-Cx*Cx-Cy*Cy); + cell[0]=Ax/10.; cell[1]=0.; cell[2]=0.; + cell[3]=Bx/10.; cell[4]=By/10.; cell[5]=0.; + cell[6]=Cx/10.; cell[7]=Cy/10.; cell[8]=Cz/10.; + } else { + cell[0]=0.0; cell[1]=0.0; cell[2]=0.0; + cell[3]=0.0; cell[4]=0.0; cell[5]=0.0; + cell[6]=0.0; cell[7]=0.0; cell[8]=0.0; + } + } else { + for(unsigned i=0; i<9; i++)cell[i]=pbc_cli_box[i]; + } + // info on coords + // the order is xyzxyz... + for(unsigned i=0; i<3*natoms; i++) { + coordinates[i]=real(ts_in.coords[i]/10.); //convert to nm + //cerr<<"COOR "< celld(9,0.0); - if(pbc_cli_given==false) { - std::vector words; - words=Tools::getWords(line); - if(words.size()==3){ - sscanf(line.c_str(),"%100lf %100lf %100lf",&celld[0],&celld[4],&celld[8]); - } else if(words.size()==9){ - sscanf(line.c_str(),"%100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf", - &celld[0], &celld[1], &celld[2], - &celld[3], &celld[4], &celld[5], - &celld[6], &celld[7], &celld[8]); - } else error("needed box in second line of xyz file"); - } else { // from command line - celld=pbc_cli_box; - } - for(unsigned i=0;i<9;i++)cell[i]=real(celld[i]); - } - int ddist=0; - // Read coordinates - for(int i=0;i=pd_start && i words=Tools::getWords(line); - if(words.size()<3) error("cannot understand box format"); - Tools::convert(words[0],cell[0]); - Tools::convert(words[1],cell[4]); - Tools::convert(words[2],cell[8]); - if(words.size()>3) Tools::convert(words[3],cell[1]); - if(words.size()>4) Tools::convert(words[4],cell[2]); - if(words.size()>5) Tools::convert(words[5],cell[3]); - if(words.size()>6) Tools::convert(words[6],cell[5]); - if(words.size()>7) Tools::convert(words[7],cell[6]); - if(words.size()>8) Tools::convert(words[8],cell[7]); - } - - } - - p.cmd("setStepLong",&step); - p.cmd("setStopFlag",&plumedStopCondition); - - if(debug_dd){ - for(int i=0;i celld(9,0.0); + if(pbc_cli_given==false) { + std::vector words; + words=Tools::getWords(line); + if(words.size()==3) { + sscanf(line.c_str(),"%100lf %100lf %100lf",&celld[0],&celld[4],&celld[8]); + } else if(words.size()==9) { + sscanf(line.c_str(),"%100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf", + &celld[0], &celld[1], &celld[2], + &celld[3], &celld[4], &celld[5], + &celld[6], &celld[7], &celld[8]); + } else error("needed box in second line of xyz file"); + } else { // from command line + celld=pbc_cli_box; + } + for(unsigned i=0; i<9; i++)cell[i]=real(celld[i]); + } + int ddist=0; + // Read coordinates + for(int i=0; i=pd_start && i words=Tools::getWords(line); + if(words.size()<3) error("cannot understand box format"); + Tools::convert(words[0],cell[0]); + Tools::convert(words[1],cell[4]); + Tools::convert(words[2],cell[8]); + if(words.size()>3) Tools::convert(words[3],cell[1]); + if(words.size()>4) Tools::convert(words[4],cell[2]); + if(words.size()>5) Tools::convert(words[5],cell[3]); + if(words.size()>6) Tools::convert(words[6],cell[5]); + if(words.size()>7) Tools::convert(words[7],cell[6]); + if(words.size()>8) Tools::convert(words[8],cell[7]); + } + + } + + p.cmd("setStepLong",&step); + p.cmd("setStopFlag",&plumedStopCondition); + + if(debug_dd) { + for(int i=0; i0){ - p.cmd("GREX prepare"); - } else { - int r=intercomm.Get_rank(); - int n=intercomm.Get_size(); - int partner=r+(2*((r+step/grex_stride)%2))-1; - if(partner<0)partner=0; - if(partner>=n) partner=n-1; - p.cmd("GREX setPartner",&partner); - p.cmd("GREX calculate"); - p.cmd("GREX shareAllDeltaBias"); - for(int i=0;i0){ + intracomm.Bcast(virial,0); + if(debug_pd) intracomm.Sum(forces); + if(debug_dd) { + for(int i=0; i0) { + p.cmd("GREX prepare"); + } else { + int r=intercomm.Get_rank(); + int n=intercomm.Get_size(); + int partner=r+(2*((r+step/grex_stride)%2))-1; + if(partner<0)partner=0; + if(partner>=n) partner=n-1; + p.cmd("GREX setPartner",&partner); + p.cmd("GREX calculate"); + p.cmd("GREX shareAllDeltaBias"); + for(int i=0; i0) { // Now call the routine to work out the derivatives numerically numder.assign(3*natoms+9,real(0.0)); real base=0; p.cmd("getBias",&base); if( fabs(base)::main(FILE* in,FILE*out,Communicator& pc){ template void Driver::evaluateNumericalDerivatives( const long int& step, Plumed& p, const std::vector& coordinates, - const std::vector& masses, const std::vector& charges, - std::vector& cell, const double& base, std::vector& numder ){ + const std::vector& masses, const std::vector& charges, + std::vector& cell, const double& base, std::vector& numder ) { int natoms = coordinates.size() / 3; real delta = sqrt(epsilon); - std::vector pos(natoms); real bias=0; + std::vector pos(natoms); real bias=0; std::vector fake_forces( 3*natoms ), fake_virial(9); - for(int i=0;i DriverFloat; /// Specialized version template<> -string Driver::description()const{ return "analyze trajectories with plumed (single precision version)"; } +string Driver::description()const { return "analyze trajectories with plumed (single precision version)"; } PLUMED_REGISTER_CLTOOL(DriverFloat,"driver-float") diff --git a/src/cltools/GenTemplate.cpp b/src/cltools/GenTemplate.cpp index 7ac49aa374..bce33af848 100644 --- a/src/cltools/GenTemplate.cpp +++ b/src/cltools/GenTemplate.cpp @@ -32,7 +32,7 @@ using namespace std; namespace PLMD { -namespace cltools{ +namespace cltools { //+PLUMEDOC TOOLS gentemplate /* @@ -48,26 +48,26 @@ The following generates template input for the action DISTANCE. \verbatim plumed gentemplate --action DISTANCE \endverbatim - + */ //+ENDPLUMEDOC class GenTemplate: -public CLTool + public CLTool { public: static void registerKeywords( Keywords& keys ); explicit GenTemplate(const CLToolOptions& co ); int main(FILE* in, FILE*out,Communicator& pc); - string description()const{ + string description()const { return "print out a template input for a particular action"; } }; PLUMED_REGISTER_CLTOOL(GenTemplate,"gentemplate") -void GenTemplate::registerKeywords( Keywords& keys ){ +void GenTemplate::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.add("optional","--action","print the template for this particular action"); keys.addFlag("--list",false,"print a list of the available actions"); @@ -75,32 +75,32 @@ void GenTemplate::registerKeywords( Keywords& keys ){ } GenTemplate::GenTemplate(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { inputdata=commandline; } -int GenTemplate::main(FILE* in, FILE*out,Communicator& pc){ +int GenTemplate::main(FILE* in, FILE*out,Communicator& pc) { - std::string action; - bool list_templates=false; - parseFlag("--list",list_templates); + std::string action; + bool list_templates=false; + parseFlag("--list",list_templates); - if(list_templates) { - std::cerr<3){ + } + parse("ndim",ndim); + if(ndim<1 || ndim>3) { fprintf(stderr,"ndim should be 1,2 or 3\n"); exit(1); + } + std::string w; + parse("wrapatoms",w); + wrapatoms=false; + if(w.length()>0 && (w[0]=='T' || w[0]=='t')) wrapatoms=true; } - std::string w; - parse("wrapatoms",w); - wrapatoms=false; - if(w.length()>0 && (w[0]=='T' || w[0]=='t')) wrapatoms=true; -} -void read_natoms(const string & inputfile,int & natoms){ + void read_natoms(const string & inputfile,int & natoms) { // read the number of atoms in file "input.xyz" - FILE* fp=fopen(inputfile.c_str(),"r"); - if(!fp){ - fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str()); - exit(1); + FILE* fp=fopen(inputfile.c_str(),"r"); + if(!fp) { + fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str()); + exit(1); + } + fscanf(fp,"%1000d",&natoms); + fclose(fp); } - fscanf(fp,"%1000d",&natoms); - fclose(fp); -} -void read_positions(const string& inputfile,int natoms,vector& positions,double cell[3]){ + void read_positions(const string& inputfile,int natoms,vector& positions,double cell[3]) { // read positions and cell from a file called inputfile // natoms (input variable) and number of atoms in the file should be consistent - FILE* fp=fopen(inputfile.c_str(),"r"); - if(!fp){ - fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str()); - exit(1); - } - char buffer[256]; - char atomname[256]; - fgets(buffer,256,fp); - fscanf(fp,"%1000lf %1000lf %1000lf",&cell[0],&cell[1],&cell[2]); - for(int i=0;i&masses,vector& velocities,Random&random){ + void randomize_velocities(const int natoms,const int ndim,const double temperature,const vector&masses,vector& velocities,Random&random) { // randomize the velocities according to the temperature - for(int iatom=0;iatom& positions,const vector&positions0,const double listcutoff, - const double forcecutoff,bool & recompute) -{ + void check_list(const int natoms,const vector& positions,const vector&positions0,const double listcutoff, + const double forcecutoff,bool & recompute) + { // check if the neighbour list have to be recomputed - Vector displacement; // displacement from positions0 to positions - double delta2; // square of the 'skin' thickness - recompute=false; - delta2=(0.5*(listcutoff-forcecutoff))*(0.5*(listcutoff-forcecutoff)); + Vector displacement; // displacement from positions0 to positions + double delta2; // square of the 'skin' thickness + recompute=false; + delta2=(0.5*(listcutoff-forcecutoff))*(0.5*(listcutoff-forcecutoff)); // if ANY atom moved more than half of the skin thickness, recompute is set to .true. - for(int iatom=0;iatomdelta2) recompute=true; + for(int iatom=0; iatomdelta2) recompute=true; + } } -} -void compute_list(const int natoms,const int listsize,const vector& positions,const double cell[3],const double listcutoff, - vector& point,vector& list){ + void compute_list(const int natoms,const int listsize,const vector& positions,const double cell[3],const double listcutoff, + vector& point,vector& list) { // see Allen-Tildesey for a definition of point and list - Vector distance; // distance of the two atoms - Vector distance_pbc; // minimum-image distance of the two atoms - double listcutoff2; // squared list cutoff - listcutoff2=listcutoff*listcutoff; - point[0]=0; - for(int iatom=0;iatomlistcutoff2)continue; - if(point[iatom+1]>listsize){ + double d2=0; for(int k=0; k<3; k++) d2+=distance_pbc[k]*distance_pbc[k]; + if(d2>listcutoff2)continue; + if(point[iatom+1]>listsize) { // too many neighbours - fprintf(stderr,"%s","Verlet list size exceeded\n"); - fprintf(stderr,"%s","Increase maxneighbours\n"); - exit(1); + fprintf(stderr,"%s","Verlet list size exceeded\n"); + fprintf(stderr,"%s","Increase maxneighbours\n"); + exit(1); + } + list[point[iatom+1]]=jatom; + point[iatom+1]++; } - list[point[iatom+1]]=jatom; - point[iatom+1]++; } } -} -void compute_forces(const int natoms,const int listsize,const vector& positions,const double cell[3], - double forcecutoff,const vector& point,const vector& list,vector& forces,double & engconf) -{ - Vector distance; // distance of the two atoms - Vector distance_pbc; // minimum-image distance of the two atoms - double distance_pbc2; // squared minimum-image distance - double forcecutoff2; // squared force cutoff - Vector f; // force - double engcorrection; // energy necessary shift the potential avoiding discontinuities - - forcecutoff2=forcecutoff*forcecutoff; - engconf=0.0; - for(int i=0;i& positions,const double cell[3], + double forcecutoff,const vector& point,const vector& list,vector& forces,double & engconf) + { + Vector distance; // distance of the two atoms + Vector distance_pbc; // minimum-image distance of the two atoms + double distance_pbc2; // squared minimum-image distance + double forcecutoff2; // squared force cutoff + Vector f; // force + double engcorrection; // energy necessary shift the potential avoiding discontinuities + + forcecutoff2=forcecutoff*forcecutoff; + engconf=0.0; + for(int i=0; iforcecutoff2) continue; - double distance_pbc6=distance_pbc2*distance_pbc2*distance_pbc2; - double distance_pbc8=distance_pbc6*distance_pbc2; - double distance_pbc12=distance_pbc6*distance_pbc6; - double distance_pbc14=distance_pbc12*distance_pbc2; - engconf+=4.0*(1.0/distance_pbc12 - 1.0/distance_pbc6) - engcorrection; - for(int k=0;k<3;k++) f[k]=2.0*distance_pbc[k]*4.0*(6.0/distance_pbc14-3.0/distance_pbc8); + if(distance_pbc2>forcecutoff2) continue; + double distance_pbc6=distance_pbc2*distance_pbc2*distance_pbc2; + double distance_pbc8=distance_pbc6*distance_pbc2; + double distance_pbc12=distance_pbc6*distance_pbc6; + double distance_pbc14=distance_pbc12*distance_pbc2; + engconf+=4.0*(1.0/distance_pbc12 - 1.0/distance_pbc6) - engcorrection; + for(int k=0; k<3; k++) f[k]=2.0*distance_pbc[k]*4.0*(6.0/distance_pbc14-3.0/distance_pbc8); // same force on the two atoms, with opposite sign: - for(int k=0;k<3;k++) forces[iatom][k]+=f[k]; - for(int k=0;k<3;k++) forces[jatom][k]-=f[k]; + for(int k=0; k<3; k++) forces[iatom][k]+=f[k]; + for(int k=0; k<3; k++) forces[jatom][k]-=f[k]; + } } } -} -void compute_engkin(const int natoms,const vector& masses,const vector& velocities,double & engkin) -{ + void compute_engkin(const int natoms,const vector& masses,const vector& velocities,double & engkin) + { // calculate the kinetic energy from the velocities - engkin=0.0; - for(int iatom=0;iatom& masses,const double dt,const double friction, - const double temperature,vector& velocities,double & engint,Random & random){ + void thermostat(const int natoms,const int ndim,const vector& masses,const double dt,const double friction, + const double temperature,vector& velocities,double & engint,Random & random) { // Langevin thermostat, implemented as decribed in Bussi and Parrinello, Phys. Rev. E (2007) // it is a linear combination of old velocities and new, randomly chosen, velocity, // with proper coefficients - double c1=exp(-friction*dt); - for(int iatom=0;iatom& positions,const double cell[3],const bool wrapatoms) -{ + void write_positions(const string& trajfile,int natoms,const vector& positions,const double cell[3],const bool wrapatoms) + { // write positions on file trajfile // positions are appended at the end of the file - Vector pos; - FILE*fp; - if(write_positions_first){ - fp=fopen(trajfile.c_str(),"w"); - write_positions_first=false; - } else { - fp=fopen(trajfile.c_str(),"a"); - } - fprintf(fp,"%d\n",natoms); - fprintf(fp,"%f %f %f\n",cell[0],cell[1],cell[2]); - for(int iatom=0;iatom& positions,const double cell[3],const bool wrapatoms) -{ + void write_final_positions(const string& outputfile,int natoms,const vector& positions,const double cell[3],const bool wrapatoms) + { // write positions on file outputfile - Vector pos; - FILE*fp; - fp=fopen(outputfile.c_str(),"w"); - fprintf(fp,"%d\n",natoms); - fprintf(fp,"%f %f %f\n",cell[0],cell[1],cell[2]); - for(int iatom=0;iatom100){ + write_statistics_fp=fopen(statfile.c_str(),"w"); + write_statistics_first=false; + } + if(istep-write_statistics_last_time_reopened>100) { // every 100 steps, reopen the file to flush the buffer - fclose(write_statistics_fp); - write_statistics_fp=fopen(statfile.c_str(),"a"); - write_statistics_last_time_reopened=istep; + fclose(write_statistics_fp); + write_statistics_fp=fopen(statfile.c_str(),"a"); + write_statistics_last_time_reopened=istep; + } + fprintf(write_statistics_fp,"%d %f %f %f %f %f\n",istep,istep*tstep,2.0*engkin/double(ndim*natoms),engconf,engkin+engconf,engkin+engconf+engint); } - fprintf(write_statistics_fp,"%d %f %f %f %f %f\n",istep,istep*tstep,2.0*engkin/double(ndim*natoms),engconf,engkin+engconf,engkin+engconf+engint); -} -virtual int main(FILE* in,FILE*out,PLMD::Communicator& pc){ - int natoms; // number of atoms - vector positions; // atomic positions - vector velocities; // velocities - vector masses; // masses - vector forces; // forces - double cell[3]; // cell size - double cell9[3][3]; // cell size + virtual int main(FILE* in,FILE*out,PLMD::Communicator& pc) { + int natoms; // number of atoms + vector positions; // atomic positions + vector velocities; // velocities + vector masses; // masses + vector forces; // forces + double cell[3]; // cell size + double cell9[3][3]; // cell size // neighbour list variables // see Allen and Tildesey book for details - int listsize; // size of the list array - vector list; // neighbour list - vector point; // pointer to neighbour list - vector positions0; // reference atomic positions, i.e. positions when the neighbour list + int listsize; // size of the list array + vector list; // neighbour list + vector point; // pointer to neighbour list + vector positions0; // reference atomic positions, i.e. positions when the neighbour list // input parameters // all of them have a reasonable default value, set in read_input() - double tstep; // simulation timestep - double temperature; // temperature - double friction; // friction for Langevin dynamics (for NVE, use 0) - double listcutoff; // cutoff for neighbour list - double forcecutoff; // cutoff for forces - int nstep; // number of steps - int nconfig; // stride for output of configurations - int nstat; // stride for output of statistics - int maxneighbour; // maximum average number of neighbours per atom - int ndim; // dimensionality of the system (1, 2, or 3) - int idum; // seed - int plumedWantsToStop; // stop flag - bool wrapatoms; // if true, atomic coordinates are written wrapped in minimal cell - string inputfile; // name of file with starting configuration (xyz) - string outputfile; // name of file with final configuration (xyz) - string trajfile; // name of the trajectory file (xyz) - string statfile; // name of the file with statistics - - double engkin; // kinetic energy - double engconf; // configurational energy - double engint; // integral for conserved energy in Langevin dynamics - - bool recompute_list; // control if the neighbour list have to be recomputed - - Random random; // random numbers stream - - PLMD::Plumed* plumed=NULL; + double tstep; // simulation timestep + double temperature; // temperature + double friction; // friction for Langevin dynamics (for NVE, use 0) + double listcutoff; // cutoff for neighbour list + double forcecutoff; // cutoff for forces + int nstep; // number of steps + int nconfig; // stride for output of configurations + int nstat; // stride for output of statistics + int maxneighbour; // maximum average number of neighbours per atom + int ndim; // dimensionality of the system (1, 2, or 3) + int idum; // seed + int plumedWantsToStop; // stop flag + bool wrapatoms; // if true, atomic coordinates are written wrapped in minimal cell + string inputfile; // name of file with starting configuration (xyz) + string outputfile; // name of file with final configuration (xyz) + string trajfile; // name of the trajectory file (xyz) + string statfile; // name of the file with statistics + + double engkin; // kinetic energy + double engconf; // configurational energy + double engint; // integral for conserved energy in Langevin dynamics + + bool recompute_list; // control if the neighbour list have to be recomputed + + Random random; // random numbers stream + + PLMD::Plumed* plumed=NULL; // Commenting the next line it is possible to switch-off plumed - plumed=new PLMD::Plumed; + plumed=new PLMD::Plumed; - if(plumed){ - int s=sizeof(double); - plumed->cmd("setRealPrecision",&s); - } + if(plumed) { + int s=sizeof(double); + plumed->cmd("setRealPrecision",&s); + } - read_input(temperature,tstep,friction,forcecutoff, - listcutoff,nstep,nconfig,nstat, - wrapatoms,inputfile,outputfile,trajfile,statfile, - maxneighbour,ndim,idum); + read_input(temperature,tstep,friction,forcecutoff, + listcutoff,nstep,nconfig,nstat, + wrapatoms,inputfile,outputfile,trajfile,statfile, + maxneighbour,ndim,idum); // number of atoms is read from file inputfile - read_natoms(inputfile,natoms); + read_natoms(inputfile,natoms); // write the parameters in output so they can be checked - fprintf(out,"%s %s\n","Starting configuration :",inputfile.c_str()); - fprintf(out,"%s %s\n","Final configuration :",outputfile.c_str()); - fprintf(out,"%s %d\n","Number of atoms :",natoms); - fprintf(out,"%s %f\n","Temperature :",temperature); - fprintf(out,"%s %f\n","Time step :",tstep); - fprintf(out,"%s %f\n","Friction :",friction); - fprintf(out,"%s %f\n","Cutoff for forces :",forcecutoff); - fprintf(out,"%s %f\n","Cutoff for neighbour list :",listcutoff); - fprintf(out,"%s %d\n","Number of steps :",nstep); - fprintf(out,"%s %d\n","Stride for trajectory :",nconfig); - fprintf(out,"%s %s\n","Trajectory file :",trajfile.c_str()); - fprintf(out,"%s %d\n","Stride for statistics :",nstat); - fprintf(out,"%s %s\n","Statistics file :",statfile.c_str()); - fprintf(out,"%s %d\n","Max average number of neighbours :",maxneighbour); - fprintf(out,"%s %d\n","Dimensionality :",ndim); - fprintf(out,"%s %d\n","Seed :",idum); - fprintf(out,"%s %s\n","Are atoms wrapped on output? :",(wrapatoms?"T":"F")); + fprintf(out,"%s %s\n","Starting configuration :",inputfile.c_str()); + fprintf(out,"%s %s\n","Final configuration :",outputfile.c_str()); + fprintf(out,"%s %d\n","Number of atoms :",natoms); + fprintf(out,"%s %f\n","Temperature :",temperature); + fprintf(out,"%s %f\n","Time step :",tstep); + fprintf(out,"%s %f\n","Friction :",friction); + fprintf(out,"%s %f\n","Cutoff for forces :",forcecutoff); + fprintf(out,"%s %f\n","Cutoff for neighbour list :",listcutoff); + fprintf(out,"%s %d\n","Number of steps :",nstep); + fprintf(out,"%s %d\n","Stride for trajectory :",nconfig); + fprintf(out,"%s %s\n","Trajectory file :",trajfile.c_str()); + fprintf(out,"%s %d\n","Stride for statistics :",nstat); + fprintf(out,"%s %s\n","Statistics file :",statfile.c_str()); + fprintf(out,"%s %d\n","Max average number of neighbours :",maxneighbour); + fprintf(out,"%s %d\n","Dimensionality :",ndim); + fprintf(out,"%s %d\n","Seed :",idum); + fprintf(out,"%s %s\n","Are atoms wrapped on output? :",(wrapatoms?"T":"F")); // Setting the seed - random.setSeed(idum); + random.setSeed(idum); // Since each atom pair is counted once, the total number of pairs // will be half of the number of neighbours times the number of atoms - listsize=maxneighbour*natoms/2; + listsize=maxneighbour*natoms/2; // allocation of dynamical arrays - positions.resize(natoms); - positions0.resize(natoms); - velocities.resize(natoms); - forces.resize(natoms); - masses.resize(natoms); - point.resize(natoms); - list.resize(listsize); + positions.resize(natoms); + positions0.resize(natoms); + velocities.resize(natoms); + forces.resize(natoms); + masses.resize(natoms); + point.resize(natoms); + list.resize(listsize); // masses are hard-coded to 1 - for(int i=0;icmd("setNoVirial"); - plumed->cmd("setNatoms",&natoms); - plumed->cmd("setMDEngine","simpleMD"); - plumed->cmd("setTimestep",&tstep); - plumed->cmd("setPlumedDat","plumed.dat"); - int pversion=0; - plumed->cmd("getApiVersion",&pversion); + randomize_velocities(natoms,ndim,temperature,masses,velocities,random); + + if(plumed) { + plumed->cmd("setNoVirial"); + plumed->cmd("setNatoms",&natoms); + plumed->cmd("setMDEngine","simpleMD"); + plumed->cmd("setTimestep",&tstep); + plumed->cmd("setPlumedDat","plumed.dat"); + int pversion=0; + plumed->cmd("getApiVersion",&pversion); // setting kbT is only implemented with api>1 // even if not necessary in principle in SimpleMD (which is part of plumed) // we leave the check here as a reference - if(pversion>1){ + if(pversion>1) { plumed->cmd("setKbT",&temperature); } - plumed->cmd("init"); - } + plumed->cmd("init"); + } // neighbour list are computed, and reference positions are saved - compute_list(natoms,listsize,positions,cell,listcutoff,point,list); + compute_list(natoms,listsize,positions,cell,listcutoff,point,list); - fprintf(out,"List size: %d\n",point[natoms-1]); - for(int iatom=0;iatomcmd("setStep",&istepplusone); - plumed->cmd("setMasses",&masses[0]); - plumed->cmd("setForces",&forces[0]); - plumed->cmd("setEnergy",&engconf); - plumed->cmd("setPositions",&positions[0]); - plumed->cmd("setBox",cell9); - plumed->cmd("setStopFlag",&plumedWantsToStop); - plumed->cmd("calc"); - if(plumedWantsToStop) nstep=istep; - } + compute_forces(natoms,listsize,positions,cell,forcecutoff,point,list,forces,engconf); + + if(plumed) { + int istepplusone=istep+1; + plumedWantsToStop=0; + for(int i=0; i<3; i++)for(int k=0; k<3; k++) cell9[i][k]=0.0; + for(int i=0; i<3; i++) cell9[i][i]=cell[i]; + plumed->cmd("setStep",&istepplusone); + plumed->cmd("setMasses",&masses[0]); + plumed->cmd("setForces",&forces[0]); + plumed->cmd("setEnergy",&engconf); + plumed->cmd("setPositions",&positions[0]); + plumed->cmd("setBox",cell9); + plumed->cmd("setStopFlag",&plumedWantsToStop); + plumed->cmd("calc"); + if(plumedWantsToStop) nstep=istep; + } // remove forces if ndim<3 - if(ndim<3) - for(int iatom=0;iatom > &cvs,std::vector &pmin,std::vector &pmax, bool &multivariate, string &lowI_, string &uppI_); }; -void CLToolSumHills::registerKeywords( Keywords& keys ){ +void CLToolSumHills::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.addFlag("--help-debug",false,"print special options that can be used to create regtests"); keys.add("optional","--hills","specify the name of the hills file"); @@ -219,21 +219,21 @@ void CLToolSumHills::registerKeywords( Keywords& keys ){ } CLToolSumHills::CLToolSumHills(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { - inputdata=commandline; + inputdata=commandline; } -string CLToolSumHills::description()const{ return "sum the hills with plumed"; } +string CLToolSumHills::description()const { return "sum the hills with plumed"; } + +int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc) { -int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ - -// Read the hills input file name - vector hillsFiles; +// Read the hills input file name + vector hillsFiles; bool dohills; dohills=parseVector("--hills",hillsFiles); // Read the histogram file - vector histoFiles; + vector histoFiles; bool dohisto; dohisto=parseVector("--histo",histoFiles); @@ -243,44 +243,44 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ vector vpmin; vector vpmax; string lowI_, uppI_; - if(dohills){ - // parse it as it was a restart - bool vmultivariate; - findCvsAndPeriodic(hillsFiles[0], vcvs, vpmin, vpmax, vmultivariate, lowI_, uppI_); + if(dohills) { + // parse it as it was a restart + bool vmultivariate; + findCvsAndPeriodic(hillsFiles[0], vcvs, vpmin, vpmax, vmultivariate, lowI_, uppI_); } vector< vector > hcvs; vector hpmin; vector hpmax; - - vector sigma; - if(dohisto){ - bool hmultivariate; - findCvsAndPeriodic(histoFiles[0], hcvs, hpmin, hpmax, hmultivariate, lowI_, uppI_); - // here need also the vector of sigmas - parseVector("--sigma",sigma); - if(sigma.size()==0)plumed_merror("you should define --sigma vector when using histogram"); - lowI_=uppI_="-1."; // Interval is not use for histograms + + vector sigma; + if(dohisto) { + bool hmultivariate; + findCvsAndPeriodic(histoFiles[0], hcvs, hpmin, hpmax, hmultivariate, lowI_, uppI_); + // here need also the vector of sigmas + parseVector("--sigma",sigma); + if(sigma.size()==0)plumed_merror("you should define --sigma vector when using histogram"); + lowI_=uppI_="-1."; // Interval is not use for histograms } - if(dohisto && dohills){ - plumed_massert(vcvs==hcvs,"variables for histogram and bias should have the same labels"); - plumed_massert(hpmin==vpmin,"variables for histogram and bias should have the same min for periodicity"); - plumed_massert(hpmax==vpmax,"variables for histogram and bias should have the same max for periodicity"); + if(dohisto && dohills) { + plumed_massert(vcvs==hcvs,"variables for histogram and bias should have the same labels"); + plumed_massert(hpmin==vpmin,"variables for histogram and bias should have the same min for periodicity"); + plumed_massert(hpmax==vpmax,"variables for histogram and bias should have the same max for periodicity"); } - // now put into a neutral vector - + // now put into a neutral vector + vector< vector > cvs; vector pmin; vector pmax; - if(dohills){ + if(dohills) { cvs=vcvs; pmin=vpmin; pmax=vpmax; } - if(dohisto){ + if(dohisto) { cvs=hcvs; pmin=hpmin; pmax=hpmax; @@ -288,32 +288,32 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ // setup grids - unsigned grid_check=0; + unsigned grid_check=0; vector gmin(cvs.size()); - if(parseVector("--min",gmin)){ - if(gmin.size()!=cvs.size() && gmin.size()!=0) plumed_merror("not enough values for --min"); - grid_check++; + if(parseVector("--min",gmin)) { + if(gmin.size()!=cvs.size() && gmin.size()!=0) plumed_merror("not enough values for --min"); + grid_check++; } vector gmax(cvs.size() ); - if(parseVector("--max",gmax)){ - if(gmax.size()!=cvs.size() && gmax.size()!=0) plumed_merror("not enough values for --max"); - grid_check++; + if(parseVector("--max",gmax)) { + if(gmax.size()!=cvs.size() && gmax.size()!=0) plumed_merror("not enough values for --max"); + grid_check++; } vector gbin(cvs.size()); - bool grid_has_bin; grid_has_bin=false; - if(parseVector("--bin",gbin)){ - if(gbin.size()!=cvs.size() && gbin.size()!=0) plumed_merror("not enough values for --bin"); - grid_has_bin=true; + bool grid_has_bin; grid_has_bin=false; + if(parseVector("--bin",gbin)) { + if(gbin.size()!=cvs.size() && gbin.size()!=0) plumed_merror("not enough values for --bin"); + grid_has_bin=true; } vector gspacing(cvs.size()); - bool grid_has_spacing; grid_has_spacing=false; - if(parseVector("--spacing",gspacing)){ - if(gspacing.size()!=cvs.size() && gspacing.size()!=0) plumed_merror("not enough values for --spacing"); - grid_has_spacing=true; + bool grid_has_spacing; grid_has_spacing=false; + if(parseVector("--spacing",gspacing)) { + if(gspacing.size()!=cvs.size() && gspacing.size()!=0) plumed_merror("not enough values for --spacing"); + grid_has_spacing=true; } // allowed: no grids only bin - // not allowed: partial grid definition - plumed_massert( gmin.size()==gmax.size() && (gmin.size()==0 || gmin.size()==cvs.size() ) ,"you should specify --min and --max together with same number of components"); + // not allowed: partial grid definition + plumed_massert( gmin.size()==gmax.size() && (gmin.size()==0 || gmin.size()==cvs.size() ),"you should specify --min and --max together with same number of components"); @@ -321,99 +321,99 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ std::string ss; unsigned nn=1; ss="setNatoms"; - plumed.cmd(ss,&nn); - if(Communicator::initialized()) plumed.cmd("setMPIComm",&pc.Get_comm()); - plumed.cmd("init",&nn); - vector isdone(cvs.size(),false); - for(unsigned i=0;i actioninput; - std::vector inds; - actioninput.push_back("FAKE"); - actioninput.push_back("ATOMS=1"); - actioninput.push_back("LABEL="+cvs[i][0]); - std::vector comps, periods; - if(cvs[i].size()>1){comps.push_back(cvs[i][1]);inds.push_back(i);} - periods.push_back(pmin[i]);periods.push_back(pmax[i]); - for(unsigned j=i+1;j1){ - comps.push_back(cvs[j][1]); - periods.push_back(pmin[j]);periods.push_back(pmax[j]); - isdone[j]=true; inds.push_back(j); - } - } - - } - // drain all the components - std::string addme; - if(comps.size()>0){ - addme="COMPONENTS="; - for(unsigned i=0;ipm ){ - plumed_merror("Periodicity issue : GRID_MAX value ( "+gmax[jj]+" ) is more than periodicity in HILLS file in "+cvs[jj][0]+ " ( "+pmax[jj]+" ) "); - } - } - } - } + plumed.cmd(ss,&nn); + if(Communicator::initialized()) plumed.cmd("setMPIComm",&pc.Get_comm()); + plumed.cmd("init",&nn); + vector isdone(cvs.size(),false); + for(unsigned i=0; i actioninput; + std::vector inds; + actioninput.push_back("FAKE"); + actioninput.push_back("ATOMS=1"); + actioninput.push_back("LABEL="+cvs[i][0]); + std::vector comps, periods; + if(cvs[i].size()>1) {comps.push_back(cvs[i][1]); inds.push_back(i);} + periods.push_back(pmin[i]); periods.push_back(pmax[i]); + for(unsigned j=i+1; j1) { + comps.push_back(cvs[j][1]); + periods.push_back(pmin[j]); periods.push_back(pmax[j]); + isdone[j]=true; inds.push_back(j); + } + } + + } + // drain all the components + std::string addme; + if(comps.size()>0) { + addme="COMPONENTS="; + for(unsigned i=0; ipm ) { + plumed_merror("Periodicity issue : GRID_MAX value ( "+gmax[jj]+" ) is more than periodicity in HILLS file in "+cvs[jj][0]+ " ( "+pmax[jj]+" ) "); + } + } + } + } // for(unsigned i=0;i< actioninput.size();i++){ -// cerr<<"AA "< actioninput; vector idw; - // check if the variables to be used are correct - if(parseVector("--idw",idw)){ - for(unsigned i=0;i1){ - if(idw[i]==cvs[j][0]+"."+cvs[j][1])found=true; - }else{ - if(idw[i]==cvs[j][0])found=true; - } - } - if(!found)plumed_merror("variable "+idw[i]+" is not found in the bunch of cvs: revise your --idw option" ); - } - plumed_massert( idw.size()<=cvs.size() ,"the number of variables to be integrated should be at most equal to the total number of cvs "); - // in this case you neeed a beta factor! - } + // check if the variables to be used are correct + if(parseVector("--idw",idw)) { + for(unsigned i=0; i1) { + if(idw[i]==cvs[j][0]+"."+cvs[j][1])found=true; + } else { + if(idw[i]==cvs[j][0])found=true; + } + } + if(!found)plumed_merror("variable "+idw[i]+" is not found in the bunch of cvs: revise your --idw option" ); + } + plumed_massert( idw.size()<=cvs.size(),"the number of variables to be integrated should be at most equal to the total number of cvs "); + // in this case you neeed a beta factor! + } - std::string kt; kt=std::string("1.");// assign an arbitrary value just in case that idw.size()==cvs.size() + std::string kt; kt=std::string("1.");// assign an arbitrary value just in case that idw.size()==cvs.size() if ( dohisto || idw.size()!=0 ) { - plumed_massert(parse("--kt",kt),"if you make a dimensionality reduction (--idw) or a histogram (--histo) then you need to define --kt "); + plumed_massert(parse("--kt",kt),"if you make a dimensionality reduction (--idw) or a histogram (--histo) then you need to define --kt "); } std::string addme; @@ -423,70 +423,70 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ // set names std::string outfile; - if(parse("--outfile",outfile)){ - actioninput.push_back("OUTHILLS="+outfile); - } + if(parse("--outfile",outfile)) { + actioninput.push_back("OUTHILLS="+outfile); + } std::string outhisto; - if(parse("--outhisto",outhisto)){ - actioninput.push_back("OUTHISTO="+outhisto); - } + if(parse("--outhisto",outhisto)) { + actioninput.push_back("OUTHISTO="+outhisto); + } addme="ARG="; - for(unsigned i=0;i<(ncv-1);i++){ - if(cvs[i].size()==1){ - addme+=std::string(cvs[i][0])+","; - }else{ - addme+=std::string(cvs[i][0])+"."+std::string(cvs[i][1])+","; - } + for(unsigned i=0; i<(ncv-1); i++) { + if(cvs[i].size()==1) { + addme+=std::string(cvs[i][0])+","; + } else { + addme+=std::string(cvs[i][0])+"."+std::string(cvs[i][1])+","; + } } - if(cvs[ncv-1].size()==1){ - addme+=std::string(cvs[ncv-1][0]); - }else{ - addme+=std::string(cvs[ncv-1][0])+"."+std::string(cvs[ncv-1][1]); + if(cvs[ncv-1].size()==1) { + addme+=std::string(cvs[ncv-1][0]); + } else { + addme+=std::string(cvs[ncv-1][0])+"."+std::string(cvs[ncv-1][1]); } actioninput.push_back(addme); //for(unsigned i=0;i< actioninput.size();i++){ - // cerr<<"AA "< > &cvs, std::vector &pmin,std::vector &pmax, bool &multivariate, string &lowI_, string &uppI_){ - IFile ifile; - ifile.allowIgnoredFields(); - std::vector fields; - if(ifile.FileExist(filename)){ - cvs.clear(); pmin.clear(); pmax.clear(); - ifile.open(filename); - ifile.scanFieldList(fields); - bool before_sigma=true; - for(unsigned i=0;i ss; - // this loop does not take into account repetitions - if(dot!=std::string::npos){ - std::string a=fields[i].substr(0,dot); - std::string name=fields[i].substr(dot+1); - ss.push_back(a); - ss.push_back(name); - cvs.push_back(ss); - }else{ - std::vector ss; - ss.push_back(fields[i]); - cvs.push_back(ss); - } - //std::cerr<<"found variable number "<1){mm=cvs.back()[0]+"."+cvs.back()[1];}else{mm=cvs.back()[0];} - if(ifile.FieldExist("min_"+mm)){ - std::string val; - ifile.scanField("min_"+mm,val); - pmin[pmin.size()-1]=val; - // std::cerr<<"found min : "< > &cvs, std::vector &pmin,std::vector &pmax, bool &multivariate, string &lowI_, string &uppI_) { + IFile ifile; + ifile.allowIgnoredFields(); + std::vector fields; + if(ifile.FileExist(filename)) { + cvs.clear(); pmin.clear(); pmax.clear(); + ifile.open(filename); + ifile.scanFieldList(fields); + bool before_sigma=true; + for(unsigned i=0; i ss; + // this loop does not take into account repetitions + if(dot!=std::string::npos) { + std::string a=fields[i].substr(0,dot); + std::string name=fields[i].substr(dot+1); + ss.push_back(a); + ss.push_back(name); + cvs.push_back(ss); + } else { + std::vector ss; + ss.push_back(fields[i]); + cvs.push_back(ss); + } + //std::cerr<<"found variable number "<1) {mm=cvs.back()[0]+"."+cvs.back()[1];} else {mm=cvs.back()[0];} + if(ifile.FieldExist("min_"+mm)) { + std::string val; + ifile.scanField("min_"+mm,val); + pmin[pmin.size()-1]=val; + // std::cerr<<"found min : "< atoms; parseAtomList("ATOMS",atoms); @@ -111,14 +111,14 @@ pbc(true) parseFlag("NOPBC",nopbc); pbc=!nopbc; - if(atoms.size()==3){ + if(atoms.size()==3) { log.printf(" between atoms %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial()); atoms.resize(4); atoms[3]=atoms[2]; atoms[2]=atoms[1]; - }else if(atoms.size()==4){ + } else if(atoms.size()==4) { log.printf(" between lines %d-%d and %d-%d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial()); - }else error("Number of specified atoms should be either 3 or 4"); + } else error("Number of specified atoms should be either 3 or 4"); if(pbc) log.printf(" using periodic boundary conditions\n"); else log.printf(" without periodic boundary conditions\n"); @@ -129,7 +129,7 @@ pbc(true) } // calculator -void Angle::calculate(){ +void Angle::calculate() { if(pbc) makeWhole(); diff --git a/src/colvar/CS2Backbone.cpp b/src/colvar/CS2Backbone.cpp index 617a5d621a..040e0dfad8 100644 --- a/src/colvar/CS2Backbone.cpp +++ b/src/colvar/CS2Backbone.cpp @@ -25,10 +25,10 @@ #define cutOnDist 0.32 // cut off distance for non-bonded pairwise forces #define cutOffNB2 cutOffNB*cutOffNB // squared buffer distance for neighbour-lists #define cutOffDist2 cutOffDist*cutOffDist -#define cutOnDist2 cutOnDist*cutOnDist +#define cutOnDist2 cutOnDist*cutOnDist #define invswitch 1.0/((cutOffDist2-cutOnDist2)*(cutOffDist2-cutOnDist2)*(cutOffDist2-cutOnDist2)) -#define cutOffDist4 cutOffDist2*cutOffDist2 -#define cutMixed cutOffDist2*cutOffDist2*cutOffDist2 -3.*cutOffDist2*cutOffDist2*cutOnDist2 +#define cutOffDist4 cutOffDist2*cutOffDist2 +#define cutMixed cutOffDist2*cutOffDist2*cutOffDist2 -3.*cutOffDist2*cutOffDist2*cutOnDist2 #include #include @@ -46,11 +46,11 @@ using namespace std; namespace PLMD { -namespace colvar{ +namespace colvar { -//+PLUMEDOC COLVAR CS2BACKBONE +//+PLUMEDOC COLVAR CS2BACKBONE /* -This collective variable calculates the backbone chemical shifts for a protein. +This collective variable calculates the backbone chemical shifts for a protein. The functional form is that of CamShift \cite Kohlhoff:2009us. The chemical shifts of the selected nuclei/residues are saved as components. Reference experimental values @@ -63,18 +63,18 @@ shift as in \cite Camilloni:2012je \cite Camilloni:2013hs (see \ref STATS and CamShift calculation is relatively heavy because it often uses a large number of atoms, in order to make it faster it is currently parallelised with \ref Openmp. -As a general rule, when using \ref CS2BACKBONE or other experimental restraints it is better to -increase the accuracy of the constraint algorithm due to the increased strain on the bonded structure. +As a general rule, when using \ref CS2BACKBONE or other experimental restraints it is better to +increase the accuracy of the constraint algorithm due to the increased strain on the bonded structure. In the case of GROMACS it is safer to use lincs-iter=2 and lincs-order=6. In general the system for which chemical shifts are calculated must be completly included in -ATOMS and a TEMPLATE pdb file for the same atoms should be provided as well in the folder DATA. -The atoms are made automatically whole unless NOPBC is used, in particular if the system is made of +ATOMS and a TEMPLATE pdb file for the same atoms should be provided as well in the folder DATA. +The atoms are made automatically whole unless NOPBC is used, in particular if the system is made of by multiple chains it is usually better to use NOPBC and make the molecule whole \ref WHOLEMOLECULES selecting an appropriate order. - + In addition to a pdb file one needs to provide a list of chemical shifts to be calculated using one -file per nucleus type (CAshifts.dat, CBshifts.dat, Cshifts.dat, Hshifts.dat, HAshifts.dat, Nshifts.dat), +file per nucleus type (CAshifts.dat, CBshifts.dat, Cshifts.dat, Hshifts.dat, HAshifts.dat, Nshifts.dat), all the six files should always be present. A chemical shift for a nucleus is calculated if a value greater than 0 is provided. For practical purposes the value can correspond to the experimental value. Residues numbers should go from 1 to N irrespectively of the numbers used in the pdb file. The first and @@ -97,19 +97,19 @@ CAshifts.dat: The default behaviour is to store the values for the active nuclei in components (ca_#, cb_#, co_#, ha_#, hn_#, nh_# and expca_#, expcb_#, expco_#, expha_#, exphn_#, exp_nh#) with NOEXP it is possible to only store the backcalculated values. - -A pdb file is needed to the generate a simple topology of the protein. For histidines in protonation -states different from D the HIE/HSE HIP/HSP name should be used. GLH and ASH can be used for the alternative + +A pdb file is needed to the generate a simple topology of the protein. For histidines in protonation +states different from D the HIE/HSE HIP/HSP name should be used. GLH and ASH can be used for the alternative protonation of GLU and ASP. Non-standard amino acids and other molecules are not yet supported, but in principle -they can be named UNK. If multiple chains are present the chain identifier must be in the standard PDB format, -together with the TER keyword at the end of each chain. +they can be named UNK. If multiple chains are present the chain identifier must be in the standard PDB format, +together with the TER keyword at the end of each chain. One more standard file is also needed in the folder DATA: camshift.db. This file includes all the CamShift parameters -and can be found in regtest/basic/rt45/data/ . +and can be found in regtest/basic/rt45/data/ . -All the above files must be in a single folder that must be specified with the keyword DATA. +All the above files must be in a single folder that must be specified with the keyword DATA. -Additional material and examples can be also found in the tutorial \ref belfast-9 +Additional material and examples can be also found in the tutorial \ref belfast-9 \par Examples @@ -119,15 +119,15 @@ in NMR driven Metadynamics \cite Granata:2013dk : \verbatim whole: GROUP ATOMS=2612-2514:-1,961-1:-1,2466-962:-1,2513-2467:-1 WHOLEMOLECULES ENTITY0=whole -cs: CS2BACKBONE ATOMS=1-2612 NRES=176 DATA=../data/ TEMPLATE=template.pdb CAMSHIFT NOPBC +cs: CS2BACKBONE ATOMS=1-2612 NRES=176 DATA=../data/ TEMPLATE=template.pdb CAMSHIFT NOPBC metad: METAD ARG=cs HEIGHT=0.5 SIGMA=0.1 PACE=200 BIASFACTOR=10 -PRINT ARG=cs,metad.bias FILE=COLVAR STRIDE=100 +PRINT ARG=cs,metad.bias FILE=COLVAR STRIDE=100 \endverbatim -In this second example the chemical shifts are used as replica-averaged restrained as in \cite Camilloni:2012je \cite Camilloni:2013hs. - +In this second example the chemical shifts are used as replica-averaged restrained as in \cite Camilloni:2012je \cite Camilloni:2013hs. + \verbatim -cs: CS2BACKBONE ATOMS=1-174 DATA=data/ NRES=13 +cs: CS2BACKBONE ATOMS=1-174 DATA=data/ NRES=13 encs: ENSEMBLE ARG=(cs\.hn_.*),(cs\.nh_.*) stcs: STATS ARG=encs.* SQDEVSUM PARARG=(cs\.exphn_.*),(cs\.expnh_.*) RESTRAINT ARG=stcs.sqdevsum AT=0 KAPPA=0 SLOPE=24 @@ -166,13 +166,13 @@ class CS2BackboneDB { public: - inline unsigned kind(const string &s){ + inline unsigned kind(const string &s) { if(s=="GLY") return GLY; - else if(s=="PRO") return PRO; + else if(s=="PRO") return PRO; return STD; } - inline unsigned atom_kind(const string &s){ + inline unsigned atom_kind(const string &s) { if(s=="HA")return HA_ATOM; else if(s=="H") return H_ATOM; else if(s=="N") return N_ATOM; @@ -188,17 +188,17 @@ class CS2BackboneDB { inline double * CONSTAACURR(const unsigned a_kind, const unsigned at_kind) {return c_aa[a_kind][at_kind];} inline double * CONSTAANEXT(const unsigned a_kind, const unsigned at_kind) {return c_aa_succ[a_kind][at_kind];} inline double * CONSTAAPREV(const unsigned a_kind, const unsigned at_kind) {return c_aa_prev[a_kind][at_kind];} - inline double * CONST_BB2_PREV(const unsigned a_kind, const unsigned at_kind){return co_bb[a_kind][at_kind];} - inline double * CONST_BB2_CURR(const unsigned a_kind, const unsigned at_kind){return co_bb[a_kind][at_kind]+5;} - inline double * CONST_BB2_NEXT(const unsigned a_kind, const unsigned at_kind){return co_bb[a_kind][at_kind]+11;} - inline double * CONST_SC2(const unsigned a_kind, const unsigned at_kind, unsigned res_type){ return co_sc_[a_kind][at_kind][res_type];} - inline double * CONST_XD(const unsigned a_kind, const unsigned at_kind){ return co_xd[a_kind][at_kind];} - inline double * CO_SPHERE(const unsigned a_kind, const unsigned at_kind, unsigned exp_type){ return co_sphere[a_kind][at_kind][exp_type];} - inline double * CO_RING(const unsigned a_kind, const unsigned at_kind){ return co_ring[a_kind][at_kind];} - inline double * CO_DA(const unsigned a_kind, const unsigned at_kind){ return co_da[a_kind][at_kind];} - inline double * PARS_DA(const unsigned a_kind, const unsigned at_kind, const unsigned ang_kind){ return pars_da[a_kind][at_kind][ang_kind];} - - void parse(const string &file, const double dscale){ + inline double * CONST_BB2_PREV(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind];} + inline double * CONST_BB2_CURR(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind]+5;} + inline double * CONST_BB2_NEXT(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind]+11;} + inline double * CONST_SC2(const unsigned a_kind, const unsigned at_kind, unsigned res_type) { return co_sc_[a_kind][at_kind][res_type];} + inline double * CONST_XD(const unsigned a_kind, const unsigned at_kind) { return co_xd[a_kind][at_kind];} + inline double * CO_SPHERE(const unsigned a_kind, const unsigned at_kind, unsigned exp_type) { return co_sphere[a_kind][at_kind][exp_type];} + inline double * CO_RING(const unsigned a_kind, const unsigned at_kind) { return co_ring[a_kind][at_kind];} + inline double * CO_DA(const unsigned a_kind, const unsigned at_kind) { return co_da[a_kind][at_kind];} + inline double * PARS_DA(const unsigned a_kind, const unsigned at_kind, const unsigned ang_kind) { return pars_da[a_kind][at_kind][ang_kind];} + + void parse(const string &file, const double dscale) { ifstream in; in.open(file.c_str()); if(!in) plumed_merror("Unable to open CS2Backbone DB file " +file); @@ -207,24 +207,24 @@ class CS2BackboneDB { unsigned c_atom = 0; unsigned nline = 0; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<6;j++) { - for(unsigned k=0;k<20;k++) { - c_aa[i][j][k]=0.; - c_aa_prev[i][j][k]=0.; - c_aa_succ[i][j][k]=0.; - for(unsigned m=0;m<20;m++) co_sc_[i][j][k][m]=0.; - } - for(unsigned k=0;k<16;k++) {co_bb[i][j][k]=0.; } - for(unsigned k=0;k<8;k++) { co_sphere[i][j][0][k]=0.; co_sphere[i][j][1][k]=0.; } - for(unsigned k=0;k<3;k++) { - co_da[i][j][k]=0.; - for(unsigned l=0;l<5;l++) pars_da[i][j][k][l]=0.; + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<6; j++) { + for(unsigned k=0; k<20; k++) { + c_aa[i][j][k]=0.; + c_aa_prev[i][j][k]=0.; + c_aa_succ[i][j][k]=0.; + for(unsigned m=0; m<20; m++) co_sc_[i][j][k][m]=0.; + } + for(unsigned k=0; k<16; k++) {co_bb[i][j][k]=0.; } + for(unsigned k=0; k<8; k++) { co_sphere[i][j][0][k]=0.; co_sphere[i][j][1][k]=0.; } + for(unsigned k=0; k<3; k++) { + co_da[i][j][k]=0.; + for(unsigned l=0; l<5; l++) pars_da[i][j][k][l]=0.; + } + for(unsigned k=0; k<5; k++) co_ring[i][j][k]=0.; + for(unsigned k=0; k tok; vector tmp; tok = split(line,' '); - for(unsigned q=0;q & v, const double scale){ - for(unsigned i=1;i & v, const double scale) { + for(unsigned i=1; i dd0, dd10, dd21, dd2; - Fragment() { + Fragment() { comp.resize(6); exp_cs.resize(6,0); res_type_prev = res_type_curr = res_type_next = 0; res_kind = 0; fd = 0; - res_name = ""; + res_name = ""; pos.resize(6,-1); prev.reserve(5); curr.reserve(6); next.reserve(5); side_chain.reserve(20); - xd1.reserve(27); - xd2.reserve(27); + xd1.reserve(27); + xd2.reserve(27); box_nb.reserve(250); phi.reserve(4); psi.reserve(4); chi1.reserve(4); t_phi = t_psi = t_chi1 = 0; - dd0.resize(3); - dd10.resize(3); - dd21.resize(3); - dd2.resize(3); + dd0.resize(3); + dd10.resize(3); + dd21.resize(3); + dd2.resize(3); } }; - struct RingInfo{ + struct RingInfo { enum {R_PHE, R_TYR, R_TRP1, R_TRP2, R_HIS}; unsigned rtype; // one out of five different types unsigned atom[6]; // up to six member per ring @@ -451,7 +453,7 @@ class CS2Backbone : public Colvar { RingInfo(): rtype(0),numAtoms(0), lengthN2(NAN),lengthNV(NAN) - {for(unsigned i=0;i<6;i++) atom[i]=0;} + {for(unsigned i=0; i<6; i++) atom[i]=0;} }; enum aa_t {ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, UNK}; @@ -496,7 +498,7 @@ class CS2Backbone : public Colvar { PLUMED_REGISTER_ACTION(CS2Backbone,"CS2BACKBONE") -void CS2Backbone::registerKeywords( Keywords& keys ){ +void CS2Backbone::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); useCustomisableComponents(keys); @@ -505,26 +507,26 @@ void CS2Backbone::registerKeywords( Keywords& keys ){ keys.add("compulsory","TEMPLATE","template.pdb","A PDB file of the protein system to initialise ALMOST."); keys.add("compulsory","NEIGH_FREQ","20","Period in step for neighbour list update."); keys.add("compulsory","NRES","Number of residues, corresponding to the number of chemical shifts."); - keys.addFlag("CAMSHIFT",false,"Set to TRUE if you to calculate a single CamShift score."); - keys.addFlag("NOEXP",false,"Set to TRUE if you don't want to have fixed components with the experimetnal values."); - keys.addOutputComponent("ha","default","the calculated Ha hydrogen chemical shifts"); - keys.addOutputComponent("hn","default","the calculated H hydrogen chemical shifts"); - keys.addOutputComponent("nh","default","the calculated N nitrogen chemical shifts"); - keys.addOutputComponent("ca","default","the calculated Ca carbon chemical shifts"); - keys.addOutputComponent("cb","default","the calculated Cb carbon chemical shifts"); - keys.addOutputComponent("co","default","the calculated C' carbon chemical shifts"); - keys.addOutputComponent("expha","default","the experimental Ha hydrogen chemical shifts"); - keys.addOutputComponent("exphn","default","the experimental H hydrogen chemical shifts"); - keys.addOutputComponent("expnh","default","the experimental N nitrogen chemical shifts"); - keys.addOutputComponent("expca","default","the experimental Ca carbon chemical shifts"); - keys.addOutputComponent("expcb","default","the experimental Cb carbon chemical shifts"); - keys.addOutputComponent("expco","default","the experimental C' carbon chemical shifts"); + keys.addFlag("CAMSHIFT",false,"Set to TRUE if you to calculate a single CamShift score."); + keys.addFlag("NOEXP",false,"Set to TRUE if you don't want to have fixed components with the experimetnal values."); + keys.addOutputComponent("ha","default","the calculated Ha hydrogen chemical shifts"); + keys.addOutputComponent("hn","default","the calculated H hydrogen chemical shifts"); + keys.addOutputComponent("nh","default","the calculated N nitrogen chemical shifts"); + keys.addOutputComponent("ca","default","the calculated Ca carbon chemical shifts"); + keys.addOutputComponent("cb","default","the calculated Cb carbon chemical shifts"); + keys.addOutputComponent("co","default","the calculated C' carbon chemical shifts"); + keys.addOutputComponent("expha","default","the experimental Ha hydrogen chemical shifts"); + keys.addOutputComponent("exphn","default","the experimental H hydrogen chemical shifts"); + keys.addOutputComponent("expnh","default","the experimental N nitrogen chemical shifts"); + keys.addOutputComponent("expca","default","the experimental Ca carbon chemical shifts"); + keys.addOutputComponent("expcb","default","the experimental Cb carbon chemical shifts"); + keys.addOutputComponent("expco","default","the experimental C' carbon chemical shifts"); } CS2Backbone::CS2Backbone(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -camshift(false), -pbc(true) + PLUMED_COLVAR_INIT(ao), + camshift(false), + pbc(true) { string stringadb; string stringapdb; @@ -561,7 +563,7 @@ pbc(true) } log.printf(" Initialization of the predictor ...\n"); log.flush(); - db.parse(stringadb,scale); + db.parse(stringadb,scale); PDB pdb; if( !pdb.read(stringapdb,plumed.getAtoms().usingNaturalUnits(),1./scale) ) error("missing input file " + stringapdb); init_backbone(pdb); @@ -595,18 +597,18 @@ pbc(true) /* this is a workaround for those chemical shifts that can result in too large forces */ remove_problematic("GLN", "CB"); remove_problematic("ILE", "CB"); - remove_problematic("PRO", "N"); + remove_problematic("PRO", "N"); remove_problematic("PRO", "H"); remove_problematic("PRO", "CB"); remove_problematic("GLY", "HA"); remove_problematic("GLY", "CB"); /* this is a workaround for those chemical shifts that are not parameterized */ remove_problematic("HIE", "HA"); remove_problematic("HIP", "HA"); remove_problematic("HSP", "HA"); - remove_problematic("HIE", "H"); remove_problematic("HIP", "H"); remove_problematic("HSP", "H"); - remove_problematic("HIE", "N"); remove_problematic("HIP", "N"); remove_problematic("HSP", "N"); + remove_problematic("HIE", "H"); remove_problematic("HIP", "H"); remove_problematic("HSP", "H"); + remove_problematic("HIE", "N"); remove_problematic("HIP", "N"); remove_problematic("HSP", "N"); remove_problematic("HIE", "CA"); remove_problematic("HIP", "CA"); remove_problematic("HSP", "CA"); remove_problematic("HIE", "CB"); remove_problematic("HIP", "CB"); remove_problematic("HSP", "CB"); - remove_problematic("HIE", "C"); remove_problematic("HIP", "C"); remove_problematic("HSP", "C"); + remove_problematic("HIE", "C"); remove_problematic("HIP", "C"); remove_problematic("HSP", "C"); remove_problematic("GLH", "HA"); remove_problematic("ASH", "HA"); remove_problematic("HSE", "HA"); remove_problematic("GLH", "H"); remove_problematic("ASH", "H"); remove_problematic("HSE", "H"); remove_problematic("GLH", "N"); remove_problematic("ASH", "N"); remove_problematic("HSE", "N"); @@ -646,11 +648,11 @@ pbc(true) unsigned index=0; if(camshift) noexp = true; if(!camshift) { - for(unsigned i=0;iset(atom[i][a].exp_cs[at_kind]); @@ -689,7 +691,7 @@ pbc(true) /* temporary check, the idea is that I can remove NRES completely */ if(index!=numResidues) error("NRES and the number of residues in the PDB do not match!"); - + requestAtoms(atoms); } @@ -703,8 +705,8 @@ void CS2Backbone::remove_problematic(const string &res, const string &nucl) { else if(nucl=="C") n=5; else return; - for(unsigned i=0;i camshift_sigma2(6); - camshift_sigma2[0] = 0.08; // HA + camshift_sigma2[0] = 0.08; // HA camshift_sigma2[1] = 0.30; // HN camshift_sigma2[2] = 9.00; // NH camshift_sigma2[3] = 1.30; // CA @@ -777,13 +779,13 @@ void CS2Backbone::calculate() // CYCLE OVER MULTIPLE CHAINS #pragma omp parallel num_threads(OpenMP::getNumThreads()) - for(unsigned s=0;s omp_deriv; if(camshift) omp_deriv.resize(getNumberOfAtoms(), Vector(0,0,0)); #pragma omp for reduction(+:score) // SKIP FIRST AND LAST RESIDUE OF EACH CHAIN - for(unsigned a=1;ares_kind; @@ -796,7 +798,7 @@ void CS2Backbone::calculate() const unsigned xdsize=myfrag->xd1.size(); vector ext_distances(xdsize); vector ext_d(xdsize); - for(unsigned q=0;qxd1[q]==-1||myfrag->xd2[q]==-1) continue; const Vector distance = delta(getPosition(myfrag->xd1[q]),getPosition(myfrag->xd2[q])); ext_d[q] = distance.modulo(); @@ -804,30 +806,30 @@ void CS2Backbone::calculate() } // CYCLE OVER THE SIX BACKBONE CHEMICAL SHIFTS - for(unsigned at_kind=0;at_kind<6;at_kind++){ - if(atom[s][a].exp_cs[at_kind]!=0){ + for(unsigned at_kind=0; at_kind<6; at_kind++) { + if(atom[s][a].exp_cs[at_kind]!=0) { // Common constant and AATYPE const double * CONSTAACURR = db.CONSTAACURR(aa_kind,at_kind); const double * CONSTAANEXT = db.CONSTAANEXT(aa_kind,at_kind); const double * CONSTAAPREV = db.CONSTAAPREV(aa_kind,at_kind); - double cs = CONSTAACURR[res_type_curr] + - CONSTAANEXT[res_type_next] + + double cs = CONSTAACURR[res_type_curr] + + CONSTAANEXT[res_type_next] + CONSTAAPREV[res_type_prev]; - // this is the atom for which we are calculating the chemical shift + // this is the atom for which we are calculating the chemical shift const unsigned ipos = myfrag->pos[at_kind]; vector list; list.reserve(needed_atoms); list.push_back(ipos); vector ff; - ff.reserve(needed_atoms); + ff.reserve(needed_atoms); ff.push_back(Vector(0,0,0)); //PREV const double * CONST_BB2_PREV = db.CONST_BB2_PREV(aa_kind,at_kind); const unsigned presize = myfrag->prev.size(); - for(unsigned q=0;qprev[q]; @@ -845,7 +847,7 @@ void CS2Backbone::calculate() //CURR const double * CONST_BB2_CURR = db.CONST_BB2_CURR(aa_kind,at_kind); const unsigned cursize = myfrag->curr.size(); - for(unsigned q=0;qcurr[q]; @@ -864,8 +866,8 @@ void CS2Backbone::calculate() //NEXT const double * CONST_BB2_NEXT = db.CONST_BB2_NEXT(aa_kind,at_kind); const unsigned nexsize = myfrag->next.size(); - for(unsigned q=0;qnext[q]; list.push_back(jpos); @@ -882,8 +884,8 @@ void CS2Backbone::calculate() //SIDE CHAIN const double * CONST_SC2 = db.CONST_SC2(aa_kind,at_kind,res_type_curr); const unsigned sidsize = myfrag->side_chain.size(); - for(unsigned q=0;qside_chain[q]; if(ipos==jpos) continue; @@ -897,10 +899,10 @@ void CS2Backbone::calculate() ff[0] += der; ff.push_back(-der); } - + //EXTRA DIST const double * CONST_XD = db.CONST_XD(aa_kind,at_kind); - for(unsigned q=0;qxd1[q]==-1||myfrag->xd2[q]==-1) continue; @@ -911,7 +913,7 @@ void CS2Backbone::calculate() ff.push_back( der); ff.push_back(-der); } - + //NON BOND { const double * CONST_CO_SPHERE3 = db.CO_SPHERE(aa_kind,at_kind,0); @@ -921,22 +923,22 @@ void CS2Backbone::calculate() const unsigned jpos = myfrag->box_nb[bat]; const Vector distance = delta(getPosition(jpos),getPosition(ipos)); const double d2 = distance.modulo2(); - + if(d2cutOnDist2) { const double af = cutOffDist2 - d2; const double bf = cutOffDist2 - 3.*cutOnDist2 + 2.*d2; - const double cf = invswitch*af; + const double cf = invswitch*af; const double df = cf*af*bf; - factor1 *= df; + factor1 *= df; factor3 *= df; - const double d4 = d2*d2; + const double d4 = d2*d2; const double af1 = 15.*cutOnDist2*d2; const double bf1 = -14.*d4; const double cf1 = -3.*cutOffDist2*cutOnDist2 + cutOffDist2*d2; @@ -950,14 +952,14 @@ void CS2Backbone::calculate() dfactor3 *= invswitch*(cutMixed+df3); } - const unsigned t = type[jpos]; + const unsigned t = type[jpos]; cs += factor1*CONST_CO_SPHERE[t] + factor3*CONST_CO_SPHERE3[t] ; - const double fact = dfactor1*CONST_CO_SPHERE[t]+dfactor3*CONST_CO_SPHERE3[t]; + const double fact = dfactor1*CONST_CO_SPHERE[t]+dfactor3*CONST_CO_SPHERE3[t]; const Vector der = fact*distance; list.push_back(jpos); ff[0] += der; - ff.push_back(-der); + ff.push_back(-der); } } } @@ -967,64 +969,64 @@ void CS2Backbone::calculate() { const double *rc = db.CO_RING(aa_kind,at_kind); const unsigned rsize = ringInfo.size(); - for(unsigned i=0; iphi.size()==4){ - const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,0); + if(myfrag->phi.size()==4) { + const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,0); const double val1 = 3.*myfrag->t_phi+PARS_DA[3]; const double val2 = myfrag->t_phi+PARS_DA[4]; - cs += CO_DA[0]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); + cs += CO_DA[0]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); const double fact = -CO_DA[0]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2)); ff.push_back(fact*myfrag->dd0[0]); @@ -1054,11 +1056,11 @@ void CS2Backbone::calculate() list.push_back(myfrag->phi[3]); } - if(myfrag->psi.size()==4){ - const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,1); + if(myfrag->psi.size()==4) { + const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,1); const double val1 = 3.*myfrag->t_psi+PARS_DA[3]; const double val2 = myfrag->t_psi+PARS_DA[4]; - cs += CO_DA[1]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); + cs += CO_DA[1]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); const double fact = -CO_DA[1]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2)); ff.push_back(fact*myfrag->dd0[1]); @@ -1072,11 +1074,11 @@ void CS2Backbone::calculate() } //Chi - if(myfrag->chi1.size()==4){ - const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,2); + if(myfrag->chi1.size()==4) { + const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,2); const double val1 = 3.*myfrag->t_chi1+PARS_DA[3]; const double val2 = myfrag->t_chi1+PARS_DA[4]; - cs += CO_DA[2]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); + cs += CO_DA[2]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); const double fact = -CO_DA[2]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2)); ff.push_back(fact*myfrag->dd0[2]); @@ -1093,13 +1095,13 @@ void CS2Backbone::calculate() Value * comp; double fact = 1.0; - if(!camshift) { + if(!camshift) { comp = atom[s][a].comp[at_kind]; comp->set(cs); Tensor virial; - for(unsigned i=0;i(res_curr-res_num[bat])); if(res_dist<2) continue; - for(unsigned at_kind=0;at_kind<6; at_kind++) { + for(unsigned at_kind=0; at_kind<6; at_kind++) { if(atom[s][a].exp_cs[at_kind]==0.) continue; - const unsigned ipos = atom[s][a].pos[at_kind]; + const unsigned ipos = atom[s][a].pos[at_kind]; const Vector distance = delta(getPosition(bat),getPosition(ipos)); const double d2=distance.modulo2(); - if(d2phi.size()==4){ + if(myfrag->phi.size()==4) { const Vector d0 = delta(getPosition(myfrag->phi[1]), getPosition(myfrag->phi[0])); const Vector d1 = delta(getPosition(myfrag->phi[2]), getPosition(myfrag->phi[1])); const Vector d2 = delta(getPosition(myfrag->phi[3]), getPosition(myfrag->phi[2])); @@ -1223,7 +1225,7 @@ void CS2Backbone::compute_dihedrals(){ atom[s][a].dd21[0] = dd2-dd1; atom[s][a].dd2[0] = dd2; } - if(myfrag->psi.size()==4){ + if(myfrag->psi.size()==4) { const Vector d0 = delta(getPosition(myfrag->psi[1]), getPosition(myfrag->psi[0])); const Vector d1 = delta(getPosition(myfrag->psi[2]), getPosition(myfrag->psi[1])); const Vector d2 = delta(getPosition(myfrag->psi[3]), getPosition(myfrag->psi[2])); @@ -1235,7 +1237,7 @@ void CS2Backbone::compute_dihedrals(){ atom[s][a].dd21[1] = dd2-dd1; atom[s][a].dd2[1] = dd2; } - if(myfrag->chi1.size()==4){ + if(myfrag->chi1.size()==4) { const Vector d0 = delta(getPosition(myfrag->chi1[1]), getPosition(myfrag->chi1[0])); const Vector d1 = delta(getPosition(myfrag->chi1[2]), getPosition(myfrag->chi1[1])); const Vector d2 = delta(getPosition(myfrag->chi1[3]), getPosition(myfrag->chi1[2])); @@ -1251,14 +1253,14 @@ void CS2Backbone::compute_dihedrals(){ } } -void CS2Backbone::init_backbone(const PDB &pdb){ +void CS2Backbone::init_backbone(const PDB &pdb) { // number of chains vector chains; pdb.getChainNames( chains ); seg_last.resize(chains.size()); unsigned old_size=0; - for(unsigned i=0;i allatoms = pdb.getAtomsInChain(chains[i]); // cycle over all the atoms in the chain - for(unsigned a=0;a atm_; - // cycle over all residues in the chain - for(unsigned a=start;a<=end;a++){ + // cycle over all residues in the chain + for(unsigned a=start; a<=end; a++) { unsigned f_idx = a - res_offset; Fragment at; at.pos[0] = HA_[f_idx]; @@ -1319,17 +1321,17 @@ void CS2Backbone::init_backbone(const PDB &pdb){ at.pos[4] = CB_[f_idx]; at.pos[5] = C_[f_idx]; at.res_type_prev = at.res_type_curr = at.res_type_next = 0; - at.res_name = pdb.getResidueName(a, chains[i]); + at.res_name = pdb.getResidueName(a, chains[i]); at.res_kind = db.kind(at.res_name); at.fd = a; //REGISTER PREV CURR NEXT { - if(a>start){ + if(a>start) { at.prev.push_back( N_[f_idx-1]); at.prev.push_back(CA_[f_idx-1]); at.prev.push_back(HA_[f_idx-1]); at.prev.push_back( C_[f_idx-1]); - at.prev.push_back( O_[f_idx-1]); + at.prev.push_back( O_[f_idx-1]); at.res_type_prev = frag2enum(pdb.getResidueName(a-1, chains[i])); } @@ -1338,10 +1340,10 @@ void CS2Backbone::init_backbone(const PDB &pdb){ at.curr.push_back(CA_[f_idx]); at.curr.push_back(HA_[f_idx]); at.curr.push_back( C_[f_idx]); - at.curr.push_back( O_[f_idx]); + at.curr.push_back( O_[f_idx]); at.res_type_curr = frag2enum(pdb.getResidueName(a, chains[i])); - if(astart){ + if(a>start) { at.phi.push_back( C_[f_idx-1]); at.phi.push_back( N_[f_idx]); at.phi.push_back(CA_[f_idx]); at.phi.push_back( C_[f_idx]); } - - if(a chains; +void CS2Backbone::init_sidechain(const PDB &pdb) { + vector chains; pdb.getChainNames( chains ); unsigned old_size=0; // cycle over chains - for(unsigned s=0; s atm = pdb.getAtomsInResidue(atom[s][a].fd, chains[s]); vector sc_atm = side_chain_atoms(atom[s][a].res_name); - for(unsigned sc=0;sc chains; + vector chains; pdb.getChainNames( chains ); unsigned old_size=0; - for(unsigned s=0; s atm_curr = pdb.getAtomsInResidue(atom[s][a].fd,chains[s]); vector atm_prev = pdb.getAtomsInResidue(atom[s][a].fd-1,chains[s]); vector atm_next = pdb.getAtomsInResidue(atom[s][a].fd+1,chains[s]); - for(unsigned q=0;q::iterator at1, at1_end; vector::iterator at2, at2_end; @@ -1449,37 +1454,37 @@ void CS2Backbone::init_xdist(const PDB &pdb){ bool init_p2=false; AtomNumber p2; - if(resOffsetP1[q]== 0){ at1 = atm_curr.begin(); at1_end = atm_curr.end();} - if(resOffsetP1[q]==-1){ at1 = atm_prev.begin(); at1_end = atm_prev.end();} - if(resOffsetP1[q]==+1){ at1 = atm_next.begin(); at1_end = atm_next.end();} - while(at1!=at1_end){ + if(resOffsetP1[q]== 0) { at1 = atm_curr.begin(); at1_end = atm_curr.end();} + if(resOffsetP1[q]==-1) { at1 = atm_prev.begin(); at1_end = atm_prev.end();} + if(resOffsetP1[q]==+1) { at1 = atm_next.begin(); at1_end = atm_next.end();} + while(at1!=at1_end) { AtomNumber aa = *at1; ++at1; string name = pdb.getAtomName(aa); xdist_name_map(name); - if(name==atomsP1[q]){ - p1 = aa; + if(name==atomsP1[q]) { + p1 = aa; init_p1=true; - break; + break; } } - if(resOffsetP2[q]== 0){ at2 = atm_curr.begin(); at2_end = atm_curr.end();} - if(resOffsetP2[q]==-1){ at2 = atm_prev.begin(); at2_end = atm_prev.end();} - if(resOffsetP2[q]==+1){ at2 = atm_next.begin(); at2_end = atm_next.end();} - while(at2!=at2_end){ + if(resOffsetP2[q]== 0) { at2 = atm_curr.begin(); at2_end = atm_curr.end();} + if(resOffsetP2[q]==-1) { at2 = atm_prev.begin(); at2_end = atm_prev.end();} + if(resOffsetP2[q]==+1) { at2 = atm_next.begin(); at2_end = atm_next.end();} + while(at2!=at2_end) { AtomNumber aa = *at2; ++at2; string name = pdb.getAtomName(aa); xdist_name_map(name); - if(name==atomsP2[q]){ - p2 = aa; + if(name==atomsP2[q]) { + p2 = aa; init_p2=true; - break; + break; } } int add1 = -1; @@ -1490,13 +1495,13 @@ void CS2Backbone::init_xdist(const PDB &pdb){ atom[s][a].xd2.push_back(add2); } } - old_size += aend.index()+1; + old_size += aend.index()+1; } } -void CS2Backbone::init_types(const PDB &pdb){ +void CS2Backbone::init_types(const PDB &pdb) { vector aa = pdb.getAtomNumbers(); - for(unsigned i=0;i chains; + vector chains; pdb.getChainNames( chains ); vector allatoms = pdb.getAtomNumbers(); unsigned old_size=0; - for(unsigned s=0; s frg_atoms = pdb.getAtomsInResidue(atom[s][r].fd,chains[s]); - if(frg=="PHE"||frg=="TYR"){ + if(frg=="PHE"||frg=="TYR") { RingInfo ri; - for(unsigned a=0;a CS2Backbone::side_chain_atoms(const string &s){ +vector CS2Backbone::side_chain_atoms(const string &s) { vector sc; - if(s=="ALA"){ + if(s=="ALA") { sc.push_back( "CB" ); sc.push_back( "HB1" ); sc.push_back( "HB2" ); sc.push_back( "HB3" ); return sc; - } else if(s=="ARG"){ + } else if(s=="ARG") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1691,7 +1696,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "1HH2" ); sc.push_back( "2HH2" ); return sc; - } else if(s=="ASN"){ + } else if(s=="ASN") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "OD1" ); @@ -1704,7 +1709,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "1HD2" ); sc.push_back( "2HD2" ); return sc; - } else if(s=="ASP"||s=="ASH"){ + } else if(s=="ASP"||s=="ASH") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "OD1" ); @@ -1713,7 +1718,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HB2" ); sc.push_back( "HB3" ); return sc; - } else if(s=="CYS"||s=="CYM"){ + } else if(s=="CYS"||s=="CYM") { sc.push_back( "CB" ); sc.push_back( "SG" ); sc.push_back( "HB1" ); @@ -1722,7 +1727,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HG1" ); sc.push_back( "HG" ); return sc; - } else if(s=="GLN"){ + } else if(s=="GLN") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1739,7 +1744,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "1HE2" ); sc.push_back( "2HE2" ); return sc; - } else if(s=="GLU"||s=="GLH"){ + } else if(s=="GLU"||s=="GLH") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1752,10 +1757,10 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HG2" ); sc.push_back( "HG3" ); return sc; - } else if(s=="GLY"){ + } else if(s=="GLY") { sc.push_back( "HA2" ); return sc; - } else if(s=="HIS"||s=="HSE"||s=="HIE"||s=="HSD"||s=="HID"||s=="HIP"||s=="HSP"){ + } else if(s=="HIS"||s=="HSE"||s=="HIE"||s=="HSD"||s=="HID"||s=="HIP"||s=="HSP") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "ND1" ); @@ -1770,7 +1775,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE1" ); sc.push_back( "HE2" ); return sc; - } else if(s=="ILE"){ + } else if(s=="ILE") { sc.push_back( "CB" ); sc.push_back( "CG1" ); sc.push_back( "CG2" ); @@ -1790,7 +1795,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HD2" ); sc.push_back( "HD3" ); return sc; - } else if(s=="LEU"){ + } else if(s=="LEU") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1812,7 +1817,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "2HD2" ); sc.push_back( "3HD2" ); return sc; - } else if(s=="LYS"){ + } else if(s=="LYS") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1834,7 +1839,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HZ2" ); sc.push_back( "HZ3" ); return sc; - } else if(s=="MET"){ + } else if(s=="MET") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "SD" ); @@ -1849,7 +1854,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE2" ); sc.push_back( "HE3" ); return sc; - } else if(s=="PHE"){ + } else if(s=="PHE") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1868,7 +1873,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE3" ); sc.push_back( "HZ" ); return sc; - } else if(s=="PRO"){ + } else if(s=="PRO") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1882,7 +1887,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HD2" ); sc.push_back( "HD3" ); return sc; - } else if(s=="SER"){ + } else if(s=="SER") { sc.push_back( "CB" ); sc.push_back( "OG" ); sc.push_back( "HB1" ); @@ -1891,7 +1896,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HG1" ); sc.push_back( "HG" ); return sc; - } else if(s=="THR"){ + } else if(s=="THR") { sc.push_back( "CB" ); sc.push_back( "OG1" ); sc.push_back( "CG2" ); @@ -1904,7 +1909,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "2HG2" ); sc.push_back( "3HG2" ); return sc; - } else if(s=="TRP"){ + } else if(s=="TRP") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1925,7 +1930,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HZ3" ); sc.push_back( "HH2" ); return sc; - } else if(s=="TYR"){ + } else if(s=="TYR") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1945,7 +1950,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE3" ); sc.push_back( "HH" ); return sc; - } else if(s=="VAL"){ + } else if(s=="VAL") { sc.push_back( "CB" ); sc.push_back( "CG1" ); sc.push_back( "CG2" ); @@ -2023,7 +2028,7 @@ bool CS2Backbone::isSP2(const string & resType, const string & atomName) { else if (atomName == "CE1") sp2 = true; else if (atomName == "CE2") sp2 = true; else if (atomName == "CZ") sp2 = true; - + } else if (resType == "ASN") { if (atomName == "CG") sp2 = true; @@ -2039,7 +2044,7 @@ bool CS2Backbone::isSP2(const string & resType, const string & atomName) { return sp2; } -bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm){ +bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm) { if(atm=="CG") return true; if((frg == "CYS")&&(atm =="SG")) return true; if(((frg == "ILE")||(frg == "VAL"))&&(atm == "CG1")) return true; @@ -2049,52 +2054,52 @@ bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm){ return false; } -unsigned CS2Backbone::frag_segment(const unsigned p){ +unsigned CS2Backbone::frag_segment(const unsigned p) { unsigned s = 0; - for(unsigned i=0;iseg_last[i]) s = i+1; else break; } return s; } -unsigned CS2Backbone::frag_relitive_index(const unsigned p, const unsigned s){ +unsigned CS2Backbone::frag_relitive_index(const unsigned p, const unsigned s) { if(s==0) return p; return p-seg_last[s-1]; } -void CS2Backbone::debug_report(){ +void CS2Backbone::debug_report() { printf("\t CS2Backbone Initialization report: \n"); printf("\t -------------------------------\n"); printf("\t Number of segments: %u\n", static_cast(atom.size())); printf("\t Segments size: "); - for(unsigned i=0;i(atom[i].size())); printf("\n"); + for(unsigned i=0; i(atom[i].size())); printf("\n"); printf("\t%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s \n", - "Seg","N","AA","Prev","Curr","Next","SC","XD1","XD2","Phi","Psi","Chi1"); - for(unsigned i=0;i(ringInfo.size())); printf("\t%8s %8s %8s %8s\n", "Num","Type","RType","N.atoms"); - for(unsigned i=0;i atoms; checkRead(); @@ -80,7 +80,7 @@ PLUMED_COLVAR_INIT(ao) requestAtoms(atoms); } -void Cell::registerKeywords( Keywords& keys ){ +void Cell::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -98,13 +98,13 @@ void Cell::registerKeywords( Keywords& keys ){ // calculator -void Cell::calculate(){ +void Cell::calculate() { - for(int i=0;i<3;i++) for(int j=0;j<3;j++) components[i][j]->set(getBox()[i][j]); - for(int l=0;l<3;l++) for(int m=0;m<3;m++){ - Tensor der; for(int i=0;i<3;i++) der[i][m]=getBox()[l][i]; - setBoxDerivatives(components[l][m],-der); - } + for(int i=0; i<3; i++) for(int j=0; j<3; j++) components[i][j]->set(getBox()[i][j]); + for(int l=0; l<3; l++) for(int m=0; m<3; m++) { + Tensor der; for(int i=0; i<3; i++) der[i][m]=getBox()[l][i]; + setBoxDerivatives(components[l][m],-der); + } } } diff --git a/src/colvar/Colvar.h b/src/colvar/Colvar.h index aead24e9bd..2d8904d64d 100644 --- a/src/colvar/Colvar.h +++ b/src/colvar/Colvar.h @@ -22,11 +22,11 @@ #ifndef __PLUMED_colvar_Colvar_h #define __PLUMED_colvar_Colvar_h #include "core/Colvar.h" -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { // Ideally core/Colvar.h should be moved to this directory and Colvar should stay in namespace PLMD::colvar // With this trick, PLMD::Colvar is visible as PLMD::colvar::Colvar - using PLMD::Colvar; +using PLMD::Colvar; } } #endif diff --git a/src/colvar/Constant.cpp b/src/colvar/Constant.cpp index 15bdab0dfb..49423413df 100644 --- a/src/colvar/Constant.cpp +++ b/src/colvar/Constant.cpp @@ -27,8 +27,8 @@ #include #include -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR CONSTANT /* @@ -76,16 +76,16 @@ class Constant : public Colvar { PLUMED_REGISTER_ACTION(Constant,"CONSTANT") Constant::Constant(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { bool noderiv=false; parseFlag("NODERIV",noderiv); parseVector("VALUES",values); - if(values.size()==0){ + if(values.size()==0) { double v; parse("VALUE",v); // this checks if v is different from NAN - if(v*2!=v || v==0.0){ + if(v*2!=v || v==0.0) { values.resize(1); values[0]=v; } @@ -98,7 +98,7 @@ PLUMED_COLVAR_INIT(ao) setNotPeriodic(); setValue(values[0]); } else if(values.size()>1) { - for(unsigned i=0;iset(values[i]); } diff --git a/src/colvar/ContactMap.cpp b/src/colvar/ContactMap.cpp index 4cb1c84b93..9405f172f4 100644 --- a/src/colvar/ContactMap.cpp +++ b/src/colvar/ContactMap.cpp @@ -53,15 +53,15 @@ PRINT ARG=f1.* FILE=colvar The following example calculates the difference of the current contact map with respect to a reference provided. In this case REFERENCE is the fraction of contact that is formed (i.e. the distance between two atoms transformed with the SWITH), while R_0 is the contact -distance. WEIGHT gives the relative weight of each contact to the final distance measure. +distance. WEIGHT gives the relative weight of each contact to the final distance measure. \verbatim CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=0.1 WEIGHT1=0.5 -ATOMS2=3,4 REFERENCE2=0.5 WEIGHT2=1.0 -ATOMS3=4,5 REFERENCE3=0.25 WEIGHT3=1.0 -ATOMS4=5,6 REFERENCE4=0.0 WEIGHT4=0.5 -SWITCH={RATIONAL R_0=1.5} +ATOMS1=1,2 REFERENCE1=0.1 WEIGHT1=0.5 +ATOMS2=3,4 REFERENCE2=0.5 WEIGHT2=1.0 +ATOMS3=4,5 REFERENCE3=0.25 WEIGHT3=1.0 +ATOMS4=5,6 REFERENCE4=0.0 WEIGHT4=0.5 +SWITCH={RATIONAL R_0=1.5} LABEL=cmap CMDIST ... CONTACTMAP @@ -69,14 +69,14 @@ CMDIST PRINT ARG=cmap FILE=colvar \endverbatim -The next example calculates calculates fraction of native contacts (Q) -for Trp-cage mini-protein. R_0 is the distance at which the switch function is guaranteed to -be 1.0 – it doesn't really matter for Q and should be something very small, like 1 A. -REF is the reference distance for the contact, e.g. the distance from a crystal structure. -LAMBDA is the tolerance for the distance – if set to 1.0, the contact would have to have exactly -the reference value to be formed; instead for lambda values of 1.5–1.8 are usually used to allow some slack. -BETA is the softness of the switch function, default is 50nm. -WEIGHT is the 1/(number of contacts) giving equal weight to each contact. +The next example calculates calculates fraction of native contacts (Q) +for Trp-cage mini-protein. R_0 is the distance at which the switch function is guaranteed to +be 1.0 – it doesn't really matter for Q and should be something very small, like 1 A. +REF is the reference distance for the contact, e.g. the distance from a crystal structure. +LAMBDA is the tolerance for the distance – if set to 1.0, the contact would have to have exactly +the reference value to be formed; instead for lambda values of 1.5–1.8 are usually used to allow some slack. +BETA is the softness of the switch function, default is 50nm. +WEIGHT is the 1/(number of contacts) giving equal weight to each contact. When using native contact Q switch function, please cite \cite best2013 @@ -87,7 +87,7 @@ CONTACTMAP ... ATOMS1=1,67 SWITCH1={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.4059} WEIGHT1=0.003597 ATOMS2=1,68 SWITCH2={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.4039} WEIGHT2=0.003597 ATOMS3=1,69 SWITCH3={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.3215} WEIGHT3=0.003597 -[snip] +[snip] ATOMS275=183,213 SWITCH275={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.355} WEIGHT275=0.003597 ATOMS276=183,234 SWITCH276={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.428} WEIGHT276=0.003597 ATOMS277=183,250 SWITCH277={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.3832} WEIGHT277=0.003597 @@ -104,7 +104,7 @@ PRINT ARG=cmap FILE=colvar */ //+ENDPLUMEDOC -class ContactMap : public Colvar { +class ContactMap : public Colvar { private: bool pbc, serial, docomp, dosum, docmdist; NeighborList *nl; @@ -116,28 +116,28 @@ class ContactMap : public Colvar { ~ContactMap(); // active methods: virtual void calculate(); - void checkFieldsAllowed(){} + void checkFieldsAllowed() {} }; PLUMED_REGISTER_ACTION(ContactMap,"CONTACTMAP") -void ContactMap::registerKeywords( Keywords& keys ){ +void ContactMap::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("numbered","ATOMS","the atoms involved in each of the contacts you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one contact will be " - "calculated for each ATOM keyword you specify."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one contact will be " + "calculated for each ATOM keyword you specify."); keys.reset_style("ATOMS","atoms"); keys.add("numbered","SWITCH","The switching functions to use for each of the contacts in your map. " - "You can either specify a global switching function using SWITCH or one " - "switching function for each contact. Details of the various switching " - "functions you can use are provided on \\ref switchingfunction."); + "You can either specify a global switching function using SWITCH or one " + "switching function for each contact. Details of the various switching " + "functions you can use are provided on \\ref switchingfunction."); keys.add("numbered","REFERENCE","A reference value for a given contact, by default is 0.0 " - "You can either specify a global reference value using REFERENCE or one " - "reference value for each contact."); + "You can either specify a global reference value using REFERENCE or one " + "reference value for each contact."); keys.add("numbered","WEIGHT","A weight value for a given contact, by default is 1.0 " - "You can either specify a global weight value using WEIGHT or one " - "weight value for each contact."); - keys.reset_style("SWITCH","compulsory"); + "You can either specify a global weight value using WEIGHT or one " + "weight value for each contact."); + keys.reset_style("SWITCH","compulsory"); keys.addFlag("SUM",false,"calculate the sum of all the contacts in the input"); keys.addFlag("CMDIST",false,"calculate the distance with respect to the provided reference contant map"); keys.addFlag("SERIAL",false,"Perform the calculation in serial - for debug purpose"); @@ -145,12 +145,12 @@ void ContactMap::registerKeywords( Keywords& keys ){ } ContactMap::ContactMap(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true), -serial(false), -docomp(true), -dosum(false), -docmdist(false) + PLUMED_COLVAR_INIT(ao), + pbc(true), + serial(false), + docomp(true), + dosum(false), + docmdist(false) { parseFlag("SERIAL",serial); parseFlag("SUM",dosum); @@ -158,96 +158,96 @@ docmdist(false) if(docmdist==true&&dosum==true) error("You cannot use SUM and CMDIST together"); bool nopbc=!pbc; parseFlag("NOPBC",nopbc); - pbc=!nopbc; + pbc=!nopbc; // Read in the atoms std::vector t, ga_lista, gb_lista; - for(int i=1;;++i ){ - parseAtomList("ATOMS", i, t ); - if( t.empty() ) break; - - if( t.size()!=2 ){ - std::string ss; Tools::convert(i,ss); - error("ATOMS" + ss + " keyword has the wrong number of atoms"); - } - ga_lista.push_back(t[0]); gb_lista.push_back(t[1]); - t.resize(0); - - // Add a value for this contact - std::string num; Tools::convert(i,num); - if(!dosum&&!docmdist) {addComponentWithDerivatives("contact-"+num); componentIsNotPeriodic("contact-"+num);} + for(int i=1;; ++i ) { + parseAtomList("ATOMS", i, t ); + if( t.empty() ) break; + + if( t.size()!=2 ) { + std::string ss; Tools::convert(i,ss); + error("ATOMS" + ss + " keyword has the wrong number of atoms"); + } + ga_lista.push_back(t[0]); gb_lista.push_back(t[1]); + t.resize(0); + + // Add a value for this contact + std::string num; Tools::convert(i,num); + if(!dosum&&!docmdist) {addComponentWithDerivatives("contact-"+num); componentIsNotPeriodic("contact-"+num);} } // Create neighbour lists nl= new NeighborList(ga_lista,gb_lista,true,pbc,getPbc()); // Read in switching functions std::string errors; sfs.resize( ga_lista.size() ); unsigned nswitch=0; - for(unsigned i=0;i deriv(getNumberOfAtoms()); - - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if(serial){ - // when using components the parallelisation do not work - stride=1; - rank=0; - }else{ - stride=comm.Get_size(); - rank=comm.Get_rank(); - } - - // sum over close pairs - for(unsigned i=rank;isize();i+=stride) { +void ContactMap::calculate() { + + double ncoord=0.; + Tensor virial; + std::vector deriv(getNumberOfAtoms()); + + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if(serial) { + // when using components the parallelisation do not work + stride=1; + rank=0; + } else { + stride=comm.Get_size(); + rank=comm.Get_rank(); + } + +// sum over close pairs + for(unsigned i=rank; isize(); i+=stride) { Vector distance; unsigned i0=nl->getClosePair(i).first; unsigned i1=nl->getClosePair(i).second; - if(pbc){ + if(pbc) { distance=pbcDistance(getPosition(i0),getPosition(i1)); } else { distance=delta(getPosition(i0),getPosition(i1)); @@ -294,40 +294,40 @@ void ContactMap::calculate(){ double coord = weight[i]*(sfs[i].calculate(distance.modulo(), dfunc) - reference[i]); Vector tmpder = weight[i]*dfunc*distance; Tensor tmpvir = weight[i]*dfunc*Tensor(distance,distance); - if(!docmdist) { - deriv[i0] -= tmpder; - deriv[i1] += tmpder; - virial -= tmpvir; - ncoord += coord; + if(!docmdist) { + deriv[i0] -= tmpder; + deriv[i1] += tmpder; + virial -= tmpvir; + ncoord += coord; } else { - tmpder *= 2.*coord; - tmpvir *= 2.*coord; - deriv[i0] -= tmpder; - deriv[i1] += tmpder; - virial -= tmpvir; - ncoord += coord*coord; + tmpder *= 2.*coord; + tmpvir *= 2.*coord; + deriv[i0] -= tmpder; + deriv[i1] += tmpder; + virial -= tmpvir; + ncoord += coord*coord; } if(docomp) { - Value* val=getPntrToComponent( i ); - setAtomsDerivatives( val, i0, deriv[i0] ); - setAtomsDerivatives( val, i1, deriv[i1] ); - setBoxDerivatives( val, -tmpvir ); - val->set(coord); + Value* val=getPntrToComponent( i ); + setAtomsDerivatives( val, i0, deriv[i0] ); + setAtomsDerivatives( val, i1, deriv[i1] ); + setBoxDerivatives( val, -tmpvir ); + val->set(coord); } - } - - if(!serial){ - comm.Sum(&ncoord,1); - if(!deriv.empty()) comm.Sum(&deriv[0][0],3*deriv.size()); - comm.Sum(&virial[0][0],9); - } - - if( !docomp ){ - for(unsigned i=0;i0){ + if(sw.length()>0) { switchingFunction.set(sw,errors); if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); } else { @@ -135,13 +135,13 @@ CoordinationBase(ao) parse("MM",mm); switchingFunction.set(nn,mm,r0,d0); } - + checkRead(); log<<" contacts are counted with cutoff "<0){ + if(gb_lista.size()>0) { if(doneigh) nl= new NeighborList(ga_lista,gb_lista,dopair,pbc,getPbc(),nl_cut,nl_st); else nl= new NeighborList(ga_lista,gb_lista,dopair,pbc,getPbc()); } else { if(doneigh) nl= new NeighborList(ga_lista,pbc,getPbc(),nl_cut,nl_st); else nl= new NeighborList(ga_lista,pbc,getPbc()); } - + requestAtoms(nl->getFullAtomList()); - + log.printf(" between two groups of %u and %u atoms\n",static_cast(ga_lista.size()),static_cast(gb_lista.size())); log.printf(" first group:\n"); - for(unsigned int i=0;igetStride()>0){ - if(firsttime || (getStep()%nl->getStride()==0)){ +void CoordinationBase::prepare() { + if(nl->getStride()>0) { + if(firsttime || (getStep()%nl->getStride()==0)) { requestAtoms(nl->getFullAtomList()); invalidateList=true; firsttime=false; - }else{ + } else { requestAtoms(nl->getReducedAtomList()); invalidateList=false; if(getExchangeStep()) error("Neighbor lists should be updated on exchange steps - choose a NL_STRIDE which divides the exchange stride!"); @@ -131,84 +131,84 @@ void CoordinationBase::prepare(){ void CoordinationBase::calculate() { - double ncoord=0.; - Tensor virial; - vector deriv(getNumberOfAtoms()); + double ncoord=0.; + Tensor virial; + vector deriv(getNumberOfAtoms()); // deriv.resize(getPositions().size()); - if(nl->getStride()>0 && invalidateList){ - nl->update(getPositions()); - } + if(nl->getStride()>0 && invalidateList) { + nl->update(getPositions()); + } - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if(serial){ - stride=1; - rank=0; - }else{ - stride=comm.Get_size(); - rank=comm.Get_rank(); - } + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if(serial) { + stride=1; + rank=0; + } else { + stride=comm.Get_size(); + rank=comm.Get_rank(); + } -unsigned nt=OpenMP::getNumThreads(); + unsigned nt=OpenMP::getNumThreads(); -const unsigned nn=nl->size(); + const unsigned nn=nl->size(); -if(nt*stride*10>nn) nt=nn/stride/10; -if(nt==0)nt=1; + if(nt*stride*10>nn) nt=nn/stride/10; + if(nt==0)nt=1; -#pragma omp parallel num_threads(nt) -{ - std::vector omp_deriv(getPositions().size()); - Tensor omp_virial; + #pragma omp parallel num_threads(nt) + { + std::vector omp_deriv(getPositions().size()); + Tensor omp_virial; -#pragma omp for reduction(+:ncoord) nowait - for(unsigned int i=rank;igetClosePair(i).first; - unsigned i1=nl->getClosePair(i).second; + #pragma omp for reduction(+:ncoord) nowait + for(unsigned int i=rank; igetClosePair(i).first; + unsigned i1=nl->getClosePair(i).second; - if(pbc){ - distance=pbcDistance(getPosition(i0),getPosition(i1)); - } else { - distance=delta(getPosition(i0),getPosition(i1)); - } + if(getAbsoluteIndex(i0)==getAbsoluteIndex(i1)) continue; - double dfunc=0.; - ncoord += pairing(distance.modulo2(), dfunc,i0,i1); + if(pbc) { + distance=pbcDistance(getPosition(i0),getPosition(i1)); + } else { + distance=delta(getPosition(i0),getPosition(i1)); + } - Vector dd(dfunc*distance); - Tensor vv(dd,distance); - if(nt>1){ - omp_deriv[i0]-=dd; - omp_deriv[i1]+=dd; - omp_virial-=vv; - } else { - deriv[i0]-=dd; - deriv[i1]+=dd; - virial-=vv; - } + double dfunc=0.; + ncoord += pairing(distance.modulo2(), dfunc,i0,i1); - } -#pragma omp critical - if(nt>1){ - for(int i=0;i1) { + omp_deriv[i0]-=dd; + omp_deriv[i1]+=dd; + omp_virial-=vv; + } else { + deriv[i0]-=dd; + deriv[i1]+=dd; + virial-=vv; + } + + } + #pragma omp critical + if(nt>1) { + for(int i=0; iset( pdb ); checkRead(); - std::vector atoms; + std::vector atoms; drmsd_->getAtomRequests( atoms ); // drmsd_->setNumberOfAtoms( atoms.size() ); requestAtoms( atoms ); // Setup the derivative pack myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() ); - for(unsigned i=0;icalculate(getPositions(), getPbc(), mypack, false); + double drmsd; Tensor virial; mypack.clear(); + drmsd=drmsd_->calculate(getPositions(), getPbc(), mypack, false); - setValue(drmsd); - for(unsigned i=0;i dsigmas; - private: - void consistencyCheck(); - vector usedatoms; +public: + static void registerKeywords( Keywords& keys); + Dimer(const ActionOptions&); + virtual void calculate(); +protected: + bool trimer,useall; + int myrank, nranks, natoms; + double qexp,temperature,beta,dsigma; + vector dsigmas; +private: + void consistencyCheck(); + vector usedatoms; }; PLUMED_REGISTER_ACTION(Dimer, "DIMER") -void Dimer::registerKeywords( Keywords& keys){ - Colvar::registerKeywords(keys); - - keys.add("compulsory","DSIGMA","The interaction strength of the dimer bond."); - keys.add("compulsory", "Q", "The exponent of the dimer potential."); - keys.add("compulsory", "TEMP", "The temperature (in Kelvin) of the simulation."); - keys.add("atoms", "ATOMS", "The list of atoms being considered by this CV. Used if ALLATOMS flag is missing"); - keys.add("atoms","NATOMS","The number of dimerized atoms. Used in combination with ATOMS list"); - keys.addFlag("ALLATOMS", false, "Use EVERY atom of the system. Overrides ATOMS keyword."); - keys.addFlag("NOVSITES", false, "If present the configuration is without virtual sites at the centroids."); - +void Dimer::registerKeywords( Keywords& keys) { + Colvar::registerKeywords(keys); + + keys.add("compulsory","DSIGMA","The interaction strength of the dimer bond."); + keys.add("compulsory", "Q", "The exponent of the dimer potential."); + keys.add("compulsory", "TEMP", "The temperature (in Kelvin) of the simulation."); + keys.add("atoms", "ATOMS", "The list of atoms being considered by this CV. Used if ALLATOMS flag is missing"); + keys.add("atoms","NATOMS","The number of dimerized atoms. Used in combination with ATOMS list"); + keys.addFlag("ALLATOMS", false, "Use EVERY atom of the system. Overrides ATOMS keyword."); + keys.addFlag("NOVSITES", false, "If present the configuration is without virtual sites at the centroids."); + } Dimer::Dimer(const ActionOptions& ao): - PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { - - log<<" Bibliography "< atoms; - parseFlag("ALLATOMS",useall); - trimer=true; - bool notrim; - parseFlag("NOVSITES",notrim); - trimer=!notrim; - - nranks=multi_sim_comm.Get_size(); - myrank=multi_sim_comm.Get_rank(); - if(dsigmas.size()==1) - dsigma=dsigmas[0]; - else - dsigma=dsigmas[myrank]; - - - - - if(useall) - { - // go with every atom in the system but not the virtuals... - if(trimer) - natoms= 2*getTotAtoms()/3; - else - natoms=getTotAtoms()/2; - - for(unsigned int i=0;i<((unsigned int)natoms);i++) - { - AtomNumber ati; - ati.setIndex(i); - atoms.push_back(ati); - } - } - else // serials for the first beads of each dimer are given - { - parseVector("ATOMS",usedatoms); - double ntm; - parse("NATOMS",ntm); - natoms=ntm; - - int isz = usedatoms.size(); - - for(unsigned int i=0;inatoms) - error("The Dimer CV requires that when choosing atoms you refere only to the first beads."); - atoms.push_back(atip2); - } - - } - consistencyCheck(); - checkRead(); - beta = 1./(kBoltzmann*temperature); - - addValueWithDerivatives(); // allocate - - requestAtoms(atoms); - - setNotPeriodic(); - + + log<<" Bibliography "< atoms; + parseFlag("ALLATOMS",useall); + trimer=true; + bool notrim; + parseFlag("NOVSITES",notrim); + trimer=!notrim; + + nranks=multi_sim_comm.Get_size(); + myrank=multi_sim_comm.Get_rank(); + if(dsigmas.size()==1) + dsigma=dsigmas[0]; + else + dsigma=dsigmas[myrank]; + + + + + if(useall) + { + // go with every atom in the system but not the virtuals... + if(trimer) + natoms= 2*getTotAtoms()/3; + else + natoms=getTotAtoms()/2; + + for(unsigned int i=0; i<((unsigned int)natoms); i++) + { + AtomNumber ati; + ati.setIndex(i); + atoms.push_back(ati); + } + } + else // serials for the first beads of each dimer are given + { + parseVector("ATOMS",usedatoms); + double ntm; + parse("NATOMS",ntm); + natoms=ntm; + + int isz = usedatoms.size(); + + for(unsigned int i=0; inatoms) + error("The Dimer CV requires that when choosing atoms you refere only to the first beads."); + atoms.push_back(atip2); + } + + } + consistencyCheck(); + checkRead(); + beta = 1./(kBoltzmann*temperature); + + addValueWithDerivatives(); // allocate + + requestAtoms(atoms); + + setNotPeriodic(); + } void Dimer::calculate() { - double cv_val=0; - Tensor virial; - vector derivatives; - vector my_pos=getPositions(); - int atms = my_pos.size(); - vector der_b2; - for(int i=0;i derivatives; + vector my_pos=getPositions(); + int atms = my_pos.size(); + vector der_b2; + for(int i=0; i1) - warning("Dimer CV is meant to be used with q-exponents between 0.5 and 1. We are not responsible for any black hole. :-)"); - if(dsigma<0) - error("Please use positive sigma values for the Dimer strength constant"); - if(temperature<0) - error("Please, use a positive value for the temperature..."); - - // if dsigmas has only one element means that either - // you are using different plumed.x.dat files or a plumed.dat with a single replica - if(dsigmas.size()!=nranks && dsigmas.size()!=1) - error("Mismatch between provided sigmas and number of replicas"); + if(useall==false && natoms==0) + error("Either NATOMS or ATOMS are required to specify the number of dimerized atoms."); + + if(qexp<0.5 || qexp>1) + warning("Dimer CV is meant to be used with q-exponents between 0.5 and 1. We are not responsible for any black hole. :-)"); + if(dsigma<0) + error("Please use positive sigma values for the Dimer strength constant"); + if(temperature<0) + error("Please, use a positive value for the temperature..."); + + // if dsigmas has only one element means that either + // you are using different plumed.x.dat files or a plumed.dat with a single replica + if(dsigmas.size()!=nranks && dsigmas.size()!=1) + error("Mismatch between provided sigmas and number of replicas"); } -}} +} +} diff --git a/src/colvar/Dipole.cpp b/src/colvar/Dipole.cpp index 4f0bed0308..09a4a65800 100644 --- a/src/colvar/Dipole.cpp +++ b/src/colvar/Dipole.cpp @@ -27,10 +27,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR DIPOLE +//+PLUMEDOC COLVAR DIPOLE /* Calculate the dipole moment for a group of atoms. @@ -43,7 +43,7 @@ PRINT FILE=output STRIDE=5 ARG=5 \endverbatim (see also \ref PRINT) -\attention +\attention If the total charge Q of the group in non zero, then a charge Q/N will be subtracted to every atom, where N is the number of atoms. This implies that the dipole (which for a charged system depends on the position) is computed on the geometric center of the group. @@ -51,7 +51,7 @@ on the position) is computed on the geometric center of the group. */ //+ENDPLUMEDOC - + class Dipole : public Colvar { vector ga_lista; bool components; @@ -63,7 +63,7 @@ class Dipole : public Colvar { PLUMED_REGISTER_ACTION(Dipole,"DIPOLE") -void Dipole::registerKeywords(Keywords& keys){ +void Dipole::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("atoms","GROUP","the group of atoms we are calculating the dipole moment for"); keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the dipole separately and store them as label.x, label.y and label.z"); @@ -74,13 +74,13 @@ void Dipole::registerKeywords(Keywords& keys){ } Dipole::Dipole(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -components(false) + PLUMED_COLVAR_INIT(ao), + components(false) { parseAtomList("GROUP",ga_lista); parseFlag("COMPONENTS",components); checkRead(); - if(components){ + if(components) { addComponentWithDerivatives("x"); componentIsNotPeriodic("x"); addComponentWithDerivatives("y"); componentIsNotPeriodic("y"); addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); @@ -89,7 +89,7 @@ components(false) } log.printf(" of %u atoms\n",static_cast(ga_lista.size())); - for(unsigned int i=0;i charges(N); - Vector dipje; - - for(unsigned i=0;iset(dipje[0]); - valuey->set(dipje[1]); - valuez->set(dipje[2]); - } + double ctot=0.; + unsigned N=getNumberOfAtoms(); + vector charges(N); + Vector dipje; + + for(unsigned i=0; iset(dipje[0]); + valuey->set(dipje[1]); + valuez->set(dipje[2]); + } } } diff --git a/src/colvar/Distance.cpp b/src/colvar/Distance.cpp index 8ef7c08055..c3a9817715 100644 --- a/src/colvar/Distance.cpp +++ b/src/colvar/Distance.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR DISTANCE /* @@ -110,7 +110,7 @@ with domain (-0.5,+0.5). */ //+ENDPLUMEDOC - + class Distance : public Colvar { bool components; bool scaled_components; @@ -125,11 +125,11 @@ class Distance : public Colvar { PLUMED_REGISTER_ACTION(Distance,"DISTANCE") -void Distance::registerKeywords( Keywords& keys ){ +void Distance::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("atoms","ATOMS","the pair of atom that we are calculating the distance between"); - keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the distance separately and store them as label.x, label.y and label.z"); - keys.addFlag("SCALED_COMPONENTS",false,"calculate the a, b and c scaled components of the distance separately and store them as label.a, label.b and label.c"); + keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the distance separately and store them as label.x, label.y and label.z"); + keys.addFlag("SCALED_COMPONENTS",false,"calculate the a, b and c scaled components of the distance separately and store them as label.a, label.b and label.c"); keys.addOutputComponent("x","COMPONENTS","the x-component of the vector connecting the two atoms"); keys.addOutputComponent("y","COMPONENTS","the y-component of the vector connecting the two atoms"); keys.addOutputComponent("z","COMPONENTS","the z-component of the vector connecting the two atoms"); @@ -139,10 +139,10 @@ void Distance::registerKeywords( Keywords& keys ){ } Distance::Distance(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -components(false), -scaled_components(false), -pbc(true) + PLUMED_COLVAR_INIT(ao), + components(false), + scaled_components(false), + pbc(true) { vector atoms; parseAtomList("ATOMS",atoms); @@ -161,12 +161,12 @@ pbc(true) if(components && scaled_components) error("COMPONENTS and SCALED_COMPONENTS are not compatible"); - if(components){ + if(components) { addComponentWithDerivatives("x"); componentIsNotPeriodic("x"); addComponentWithDerivatives("y"); componentIsNotPeriodic("y"); addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); log<<" WARNING: components will not have the proper periodicity - see manual\n"; - } else if(scaled_components){ + } else if(scaled_components) { addComponentWithDerivatives("a"); componentIsPeriodic("a","-0.5","+0.5"); addComponentWithDerivatives("b"); componentIsPeriodic("b","-0.5","+0.5"); addComponentWithDerivatives("c"); componentIsPeriodic("c","-0.5","+0.5"); @@ -180,7 +180,7 @@ pbc(true) // calculator -void Distance::calculate(){ +void Distance::calculate() { if(pbc) makeWhole(); @@ -188,7 +188,7 @@ void Distance::calculate(){ const double value=distance.modulo(); const double invvalue=1.0/value; - if(components){ + if(components) { Value* valuex=getPntrToComponent("x"); Value* valuey=getPntrToComponent("y"); Value* valuez=getPntrToComponent("z"); @@ -207,7 +207,7 @@ void Distance::calculate(){ setAtomsDerivatives (valuez,1,Vector(0,0,+1)); setBoxDerivativesNoPbc(valuez); valuez->set(distance[2]); - } else if(scaled_components){ + } else if(scaled_components) { Value* valuea=getPntrToComponent("a"); Value* valueb=getPntrToComponent("b"); Value* valuec=getPntrToComponent("c"); diff --git a/src/colvar/ERMSD.cpp b/src/colvar/ERMSD.cpp index 29ce5de510..3602df0868 100644 --- a/src/colvar/ERMSD.cpp +++ b/src/colvar/ERMSD.cpp @@ -35,35 +35,35 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR ERMSD /* -Calculate eRMSD with respect to a reference structure. +Calculate eRMSD with respect to a reference structure. -eRMSD is a metric developed for measuring distances between three-dimensional RNA structures. -The standard RMSD measure is highly inaccurate when measuring distances among three-dimensional -structures of nucleic acids. -It is not unusual, for example, that two RNA structures with low RMSD (i.e. less than 0.4nm) display a completely different network of base-base interactions. +eRMSD is a metric developed for measuring distances between three-dimensional RNA structures. +The standard RMSD measure is highly inaccurate when measuring distances among three-dimensional +structures of nucleic acids. +It is not unusual, for example, that two RNA structures with low RMSD (i.e. less than 0.4nm) display a completely different network of base-base interactions. eRMSD measures the distance between structures by considering only the relative positions and orientations of nucleobases. The eRMSD can be considered as a vectorial version of contact maps and it is calculated as follows: -1. Set up a local reference system in the center of the six-membered ring of each nucleobase in a molecule. - The xy plane lies on the plane of the nucleobase, and it is oriented such that the Watson-Crick interaction is always at \f$ \theta \approx 60^{\circ} \f$. +1. Set up a local reference system in the center of the six-membered ring of each nucleobase in a molecule. + The xy plane lies on the plane of the nucleobase, and it is oriented such that the Watson-Crick interaction is always at \f$ \theta \approx 60^{\circ} \f$. -2. Calculate all pairwise distance vectors \f$ \vec{r}_{i,j} \f$ among base centers. +2. Calculate all pairwise distance vectors \f$ \vec{r}_{i,j} \f$ among base centers. 3. Rescale distance vectors as \f$ \tilde{\vec{r}}_{i,j} = (r_x/a,r_y/a,r_z/b) \f$, where \f$ a=b=5 \AA, c= 3 \AA\f$. This rescaling has the effect of weghting more deviations on the z-axis with respect to the x/y directions. -4. Calculate the G vectors +4. Calculate the G vectors \f[ \vec{G}(\tilde{\vec{r}}) = (\sin(\gamma \tilde{r}) \tilde{r}_x/\tilde{r},\sin(\gamma \tilde{r}) \tilde{r}_y/\tilde{r},\sin(\gamma \tilde{r}) \tilde{r}_z/\tilde{r}, 1+\cos(\gamma \tilde{r})) \times \Theta(\tilde{r}_{cutoff}-\tilde{r}) \f] -Here, \f$ \gamma = \pi/\tilde{r}_{cutoff}\f$ and \f$ \Theta \f$ is the Heaviside step function. The default cutoff is set to 2.4. +Here, \f$ \gamma = \pi/\tilde{r}_{cutoff}\f$ and \f$ \Theta \f$ is the Heaviside step function. The default cutoff is set to 2.4. 5. The eRMSD between two structures \f$ \alpha \f$ and \f$ \beta \f$ reads @@ -81,7 +81,7 @@ for a multi molecular system. \par Examples -Calculate the eRMSD from reference structure reference.pdb using the default cutoff (2.4). The list of residues involved in the calculation has to be specified. In this example, the eRMSD is calculated +Calculate the eRMSD from reference structure reference.pdb using the default cutoff (2.4). The list of residues involved in the calculation has to be specified. In this example, the eRMSD is calculated considering residues 1,2,3,4,5,6. \verbatim @@ -91,13 +91,13 @@ eRMSD1: ERMSD REFERENCE=reference.pdb ATOMS=@lcs-1,@lcs-2,@lcs-3,@lcs-4,@lcs-5,@ */ //+ENDPLUMEDOC - + class ERMSD : public Colvar { - - vector derivs; - PLMD::ERMSD ermsd; - bool pbc; + + vector derivs; + PLMD::ERMSD ermsd; + bool pbc; public: explicit ERMSD(const ActionOptions&); @@ -107,7 +107,7 @@ class ERMSD : public Colvar { PLUMED_REGISTER_ACTION(ERMSD,"ERMSD") -void ERMSD::registerKeywords(Keywords& keys){ +void ERMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV."); @@ -118,7 +118,7 @@ void ERMSD::registerKeywords(Keywords& keys){ } ERMSD::ERMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), pbc(true) + PLUMED_COLVAR_INIT(ao), pbc(true) { string reference; parse("REFERENCE",reference); @@ -137,13 +137,13 @@ PLUMED_COLVAR_INIT(ao), pbc(true) parseVector("PAIRS",pairs_); checkRead(); - addValueWithDerivatives(); setNotPeriodic(); + addValueWithDerivatives(); setNotPeriodic(); if(atoms_.size()<6) error("at least six atoms should be specified"); if(atoms_.size()%3!=0) error("Atoms are not multiple of 3"); if(pairs_.size()%2!=0) error("pairs are not multiple of 2"); - + //checkRead(); //log.printf(" of atoms"); //for(unsigned i=0;i reference_positions; unsigned natoms = atoms_.size(); log.printf("Read %u atoms\n",natoms); reference_positions.resize(natoms); - for(unsigned i=0;i #include -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR ENERGY /* @@ -42,7 +42,7 @@ metadynamics applied to ENERGY can be used to decrease the number of required replicas. \bug Acceptance for replica exchange when \ref ENERGY is biased -is computed correctly only of all the replicas has the same +is computed correctly only of all the replicas has the same potential energy function. This is for instance not true when using GROMACS with lambda replica exchange of with plumed-hrex branch. @@ -76,7 +76,7 @@ using namespace std; PLUMED_REGISTER_ACTION(Energy,"ENERGY") Energy::Energy(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { // if(checkNumericalDerivatives()) // error("Cannot use NUMERICAL_DERIVATIVES with ENERGY"); @@ -89,23 +89,23 @@ PLUMED_COLVAR_INIT(ao) log<<"\n"; } -void Energy::registerKeywords( Keywords& keys ){ +void Energy::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); - keys.remove("NUMERICAL_DERIVATIVES"); + keys.remove("NUMERICAL_DERIVATIVES"); } -unsigned Energy::getNumberOfDerivatives(){ +unsigned Energy::getNumberOfDerivatives() { return 1; } -void Energy::prepare(){ +void Energy::prepare() { plumed.getAtoms().setCollectEnergy(true); } // calculator -void Energy::calculate(){ +void Energy::calculate() { setValue( getEnergy() ); getPntrToComponent(0)->addDerivative(0,1.0); } diff --git a/src/colvar/Fake.cpp b/src/colvar/Fake.cpp index 4a28cbf38d..70bd7f2789 100644 --- a/src/colvar/Fake.cpp +++ b/src/colvar/Fake.cpp @@ -29,10 +29,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR FAKE +//+PLUMEDOC COLVAR FAKE /* This is a fake colvar container used by cltools or various other actions and just support input and period definition @@ -46,7 +46,7 @@ FAKE ATOMS=1 PERIODIC=-3.14,3.14 LABEL=d2 */ //+ENDPLUMEDOC - + class ColvarFake : public Colvar { public: @@ -58,7 +58,7 @@ class ColvarFake : public Colvar { PLUMED_REGISTER_ACTION(ColvarFake,"FAKE") -void ColvarFake::registerKeywords( Keywords& keys ){ +void ColvarFake::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("atoms","ATOMS","the fake atom index, a number is enough"); keys.reserve("compulsory","PERIODIC","if the output of your function is periodic then you should specify the periodicity of the function. If the output is not periodic you must state this using PERIODIC=NO,NO (one for the lower and the other for the upper boundary). For multicomponents then it is PERIODIC=mincomp1,maxcomp1,mincomp2,maxcomp2 etc "); @@ -67,61 +67,61 @@ void ColvarFake::registerKeywords( Keywords& keys ){ } ColvarFake::ColvarFake(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { vector atoms; parseAtomList("ATOMS",atoms); - vector comps; - // multiple components for this variable + vector comps; + // multiple components for this variable parseVector("COMPONENTS",comps); - if(comps.size()!=0){ - for(unsigned i=0;i period; parseVector("PERIODIC",period); - if(period.size()!=0){ - plumed_massert(getNumberOfComponents()*2==period.size(),"the periodicty should coincide with the number of components"); - if(comps.size()!=0){ - for(int i=0;igetName()); - } - } else { - setNotPeriodic(); - } + if(period.size()!=0) { + plumed_massert(getNumberOfComponents()*2==period.size(),"the periodicty should coincide with the number of components"); + if(comps.size()!=0) { + for(int i=0; igetName()); + } + } else { + setNotPeriodic(); + } } - checkRead(); - requestAtoms(atoms); + checkRead(); + requestAtoms(atoms); } // calculator -void ColvarFake::calculate(){ - plumed_merror("you should never have got here"); +void ColvarFake::calculate() { + plumed_merror("you should never have got here"); } } diff --git a/src/colvar/FretEfficiency.cpp b/src/colvar/FretEfficiency.cpp index 9840c749de..02600e1057 100644 --- a/src/colvar/FretEfficiency.cpp +++ b/src/colvar/FretEfficiency.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR FRET /* @@ -48,7 +48,7 @@ boundary conditions. This behavior can be changed with the NOPBC flag. \par Examples -The following input tells plumed to print the FRET efficiencies +The following input tells plumed to print the FRET efficiencies calculated as a function of the distance between atoms 3 and 5 and the distance between atoms 2 and 4. \verbatim @@ -73,7 +73,7 @@ to be sure that if the distance is larger than half the simulation box the distance is compute properly. Also notice that, since many MD codes break molecules across cell boundary, it might be necessary to use the \ref WHOLEMOLECULES keyword (also notice that it should be -_before_ FRET). +_before_ FRET). Just be sure that the ordered list provide to WHOLEMOLECULES has the following properties: - Consecutive atoms should be closer than half-cell throughout the entire simulation. @@ -81,7 +81,7 @@ Just be sure that the ordered list provide to WHOLEMOLECULES has the following */ //+ENDPLUMEDOC - + class FretEfficiency : public Colvar { bool pbc; double R0_; @@ -95,21 +95,21 @@ class FretEfficiency : public Colvar { PLUMED_REGISTER_ACTION(FretEfficiency,"FRET") -void FretEfficiency::registerKeywords( Keywords& keys ){ +void FretEfficiency::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("atoms","ATOMS","the pair of atom that we are calculating the distance between"); keys.add("compulsory","R0","The value of the Forster radius."); } FretEfficiency::FretEfficiency(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true) + PLUMED_COLVAR_INIT(ao), + pbc(true) { vector atoms; parseAtomList("ATOMS",atoms); if(atoms.size()!=2) error("Number of specified atoms should be 2"); - parse("R0",R0_); + parse("R0",R0_); bool nopbc=!pbc; parseFlag("NOPBC",nopbc); pbc=!nopbc; @@ -129,14 +129,14 @@ pbc(true) // calculator -void FretEfficiency::calculate(){ +void FretEfficiency::calculate() { if(pbc) makeWhole(); Vector distance=delta(getPosition(0),getPosition(1)); const double dist_mod=distance.modulo(); const double inv_dist_mod=1.0/dist_mod; - + const double ratiosix=pow(dist_mod/R0_,6); const double fret_eff = 1.0/(1.0+ratiosix); diff --git a/src/colvar/Gyration.cpp b/src/colvar/Gyration.cpp index 9471593e9f..5cf35aea06 100644 --- a/src/colvar/Gyration.cpp +++ b/src/colvar/Gyration.cpp @@ -29,26 +29,26 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR GYRATION /* Calculate the radius of gyration, or other properties related to it. The different properties can be calculated and selected by the TYPE keyword: -the Radius of Gyration (RADIUS); the Trace of the Gyration Tensor (TRACE); +the Radius of Gyration (RADIUS); the Trace of the Gyration Tensor (TRACE); the Largest Principal Moment of the Gyration Tensor (GTPC_1); the middle Principal Moment of the Gyration Tensor (GTPC_2); the Smallest Principal Moment of the Gyration Tensor (GTPC_3); the Asphericiry (ASPHERICITY); the Acylindricity (ACYLINDRICITY); -the Relative Shape Anisotropy (KAPPA2); the Smallest Principal Radius Of Gyration (GYRATION_3); +the Relative Shape Anisotropy (KAPPA2); the Smallest Principal Radius Of Gyration (GYRATION_3); the Middle Principal Radius of Gyration (GYRATION_2); the Largest Principal Radius of Gyration (GYRATION_1). A derivation of all these different variants can be found in \cite Vymetal:2011gv The radius of gyration is calculated using: \f[ -s_{\rm Gyr}=\Big ( \frac{\sum_i^{n} - m_i \vert {r}_i -{r}_{\rm COM} \vert ^2 }{\sum_i^{n} m_i} \Big)^{1/2} +s_{\rm Gyr}=\Big ( \frac{\sum_i^{n} + m_i \vert {r}_i -{r}_{\rm COM} \vert ^2 }{\sum_i^{n} m_i} \Big)^{1/2} \f] with the position of the center of mass \f${r}_{\rm COM}\f$ given by: @@ -57,14 +57,14 @@ with the position of the center of mass \f${r}_{\rm COM}\f$ given by: {r}_{\rm COM}=\frac{\sum_i^{n} {r}_i\ m_i }{\sum_i^{n} m_i} \f] -The radius of gyration usually makes sense when atoms used for the calculation +The radius of gyration usually makes sense when atoms used for the calculation are all part of the same molecule. -When running with periodic boundary conditions, the atoms should be +When running with periodic boundary conditions, the atoms should be in the proper periodic image. This is done automatically since PLUMED 2.2, by considering the ordered list of atoms and rebuilding PBCs with a procedure that is equivalent to that done in \ref WHOLEMOLECULES . Notice that rebuilding is local to this action. This is different from \ref WHOLEMOLECULES -which actually modifies the coordinates stored in PLUMED. +which actually modifies the coordinates stored in PLUMED. In case you want to recover the old behavior you should use the NOPBC flag. In that case you need to take care that atoms are in the correct @@ -73,11 +73,11 @@ periodic image. \par Examples -The following input tells plumed to print the radius of gyration of the +The following input tells plumed to print the radius of gyration of the chain containing atoms 10 to 20. \verbatim GYRATION TYPE=RADIUS ATOMS=10-20 LABEL=rg -PRINT ARG=rg STRIDE=1 FILE=colvar +PRINT ARG=rg STRIDE=1 FILE=colvar \endverbatim (See also \ref PRINT) @@ -98,7 +98,7 @@ class Gyration : public Colvar { PLUMED_REGISTER_ACTION(Gyration,"GYRATION") -void Gyration::registerKeywords(Keywords& keys){ +void Gyration::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("atoms","ATOMS","the group of atoms that you are calculating the Gyration Tensor for"); keys.add("compulsory","TYPE","RADIUS","The type of calculation relative to the Gyration Tensor you want to perform"); @@ -106,9 +106,9 @@ void Gyration::registerKeywords(Keywords& keys){ } Gyration::Gyration(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -use_masses(false), -nopbc(false) + PLUMED_COLVAR_INIT(ao), + use_masses(false), + nopbc(false) { std::vector atoms; parseAtomList("ATOMS",atoms); @@ -134,25 +134,25 @@ nopbc(false) switch(rg_type) { - case RADIUS: log.printf(" GYRATION RADIUS (Rg);"); break; - case TRACE: log.printf(" TRACE OF THE GYRATION TENSOR;"); break; - case GTPC_1: log.printf(" THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);"); break; - case GTPC_2: log.printf(" THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);"); break; - case GTPC_3: log.printf(" THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);"); break; - case ASPHERICITY: log.printf(" THE ASPHERICITY (b');"); break; - case ACYLINDRICITY: log.printf(" THE ACYLINDRICITY (c');"); break; - case KAPPA2: log.printf(" THE RELATIVE SHAPE ANISOTROPY (kappa^2);"); break; - case GYRATION_3: log.printf(" THE SMALLEST PRINCIPAL RADIUS OF GYRATION (r_g3);"); break; - case GYRATION_2: log.printf(" THE MIDDLE PRINCIPAL RADIUS OF GYRATION (r_g2);"); break; - case GYRATION_1: log.printf(" THE LARGEST PRINCIPAL RADIUS OF GYRATION (r_g1);"); break; + case RADIUS: log.printf(" GYRATION RADIUS (Rg);"); break; + case TRACE: log.printf(" TRACE OF THE GYRATION TENSOR;"); break; + case GTPC_1: log.printf(" THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);"); break; + case GTPC_2: log.printf(" THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);"); break; + case GTPC_3: log.printf(" THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);"); break; + case ASPHERICITY: log.printf(" THE ASPHERICITY (b');"); break; + case ACYLINDRICITY: log.printf(" THE ACYLINDRICITY (c');"); break; + case KAPPA2: log.printf(" THE RELATIVE SHAPE ANISOTROPY (kappa^2);"); break; + case GYRATION_3: log.printf(" THE SMALLEST PRINCIPAL RADIUS OF GYRATION (r_g3);"); break; + case GYRATION_2: log.printf(" THE MIDDLE PRINCIPAL RADIUS OF GYRATION (r_g2);"); break; + case GYRATION_1: log.printf(" THE LARGEST PRINCIPAL RADIUS OF GYRATION (r_g1);"); break; } if(rg_type>TRACE) log<<" Bibliography "<(getNumberOfAtoms()); - for(unsigned i=0;i gyr_tens(3,3); - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) gyr_tens(i,j)=0.; + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) gyr_tens(i,j)=0.; //calculate gyration tensor if( use_masses ) { - for(unsigned i=0;i0.0001) error("Plumed Error: Cannot diagonalize gyration tensor\n"); switch(rg_type) { - case GTPC_1: - case GTPC_2: - case GTPC_3: - { - int pc_index = rg_type-2; //index of principal component - rgyr=sqrt(princ_comp[pc_index]/totmass); - double rm = rgyr*totmass; - if(rm>1e-6) prefactor[pc_index]=1.0/rm; //some parts of derivate - break; - } - case GYRATION_3: //the smallest principal radius of gyration - { - rgyr=sqrt((princ_comp[1]+princ_comp[2])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[1]=1.0/rm; - prefactor[2]=1.0/rm; - } - break; + case GTPC_1: + case GTPC_2: + case GTPC_3: + { + int pc_index = rg_type-2; //index of principal component + rgyr=sqrt(princ_comp[pc_index]/totmass); + double rm = rgyr*totmass; + if(rm>1e-6) prefactor[pc_index]=1.0/rm; //some parts of derivate + break; + } + case GYRATION_3: //the smallest principal radius of gyration + { + rgyr=sqrt((princ_comp[1]+princ_comp[2])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[1]=1.0/rm; + prefactor[2]=1.0/rm; } - case GYRATION_2: //the midle principal radius of gyration - { - rgyr=sqrt((princ_comp[0]+princ_comp[2])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[0]=1.0/rm; - prefactor[2]=1.0/rm; - } - break; + break; + } + case GYRATION_2: //the midle principal radius of gyration + { + rgyr=sqrt((princ_comp[0]+princ_comp[2])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[0]=1.0/rm; + prefactor[2]=1.0/rm; } - case GYRATION_1: //the largest principal radius of gyration - { - rgyr=sqrt((princ_comp[0]+princ_comp[1])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[0]=1.0/rm; - prefactor[1]=1.0/rm; - } - break; + break; + } + case GYRATION_1: //the largest principal radius of gyration + { + rgyr=sqrt((princ_comp[0]+princ_comp[1])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[0]=1.0/rm; + prefactor[1]=1.0/rm; } - case ASPHERICITY: - { - rgyr=sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[0]= 1.0/rm; - prefactor[1]=-0.5/rm; - prefactor[2]=-0.5/rm; - } - break; + break; + } + case ASPHERICITY: + { + rgyr=sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[0]= 1.0/rm; + prefactor[1]=-0.5/rm; + prefactor[2]=-0.5/rm; } - case ACYLINDRICITY: - { - rgyr=sqrt((princ_comp[1]-princ_comp[2])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ //avoid division by zero - prefactor[1]= 1.0/rm; - prefactor[2]=-1.0/rm; - } - break; + break; + } + case ACYLINDRICITY: + { + rgyr=sqrt((princ_comp[1]-princ_comp[2])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { //avoid division by zero + prefactor[1]= 1.0/rm; + prefactor[2]=-1.0/rm; } - case KAPPA2: // relative shape anisotropy - { - double trace = princ_comp[0]+princ_comp[1]+princ_comp[2]; - double tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2]; - rgyr=1.0-3*(tmp/(trace*trace)); - if (rgyr>1e-6){ - prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; - prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; - prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2; - } - break; + break; + } + case KAPPA2: // relative shape anisotropy + { + double trace = princ_comp[0]+princ_comp[1]+princ_comp[2]; + double tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2]; + rgyr=1.0-3*(tmp/(trace*trace)); + if (rgyr>1e-6) { + prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; + prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; + prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2; } + break; + } } - if(use_masses) { - for(unsigned i=0;i > nl; - vector > nlexpo; - vector > parameter; - void setupConstants(const vector &atoms, vector > ¶meter, bool tcorr); - map > setupTypeMap(); - map > setupValueMap(); - void update_neighb(); +private: + bool pbc; + double buffer; + double delta_g_ref; + unsigned stride; + unsigned nl_update; + vector > nl; + vector > nlexpo; + vector > parameter; + void setupConstants(const vector &atoms, vector > ¶meter, bool tcorr); + map > setupTypeMap(); + map > setupValueMap(); + void update_neighb(); - public: - static void registerKeywords(Keywords& keys); - explicit Implicit(const ActionOptions&); - virtual void calculate(); +public: + static void registerKeywords(Keywords& keys); + explicit Implicit(const ActionOptions&); + virtual void calculate(); }; PLUMED_REGISTER_ACTION(Implicit,"IMPLICIT") void Implicit::registerKeywords(Keywords& keys) { - Colvar::registerKeywords(keys); - componentsAreNotOptional(keys); - useCustomisableComponents(keys); - keys.add("atoms", "ATOMS", "The atoms to be included in the calculation, e.g. the whole protein."); - keys.add("compulsory", "NL_BUFFER", "The buffer to the intrinsic cutoff used when calculating pairwise interactions."); - keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbourlist is updated."); - keys.addFlag("TEMP_CORRECTION", false, "Correct free energy of solvation constants for temperatures different from 298.15 K"); + Colvar::registerKeywords(keys); + componentsAreNotOptional(keys); + useCustomisableComponents(keys); + keys.add("atoms", "ATOMS", "The atoms to be included in the calculation, e.g. the whole protein."); + keys.add("compulsory", "NL_BUFFER", "The buffer to the intrinsic cutoff used when calculating pairwise interactions."); + keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbourlist is updated."); + keys.addFlag("TEMP_CORRECTION", false, "Correct free energy of solvation constants for temperatures different from 298.15 K"); } Implicit::Implicit(const ActionOptions&ao): - PLUMED_COLVAR_INIT(ao), - pbc(true), - buffer(0.1), - delta_g_ref(0.), - stride(10), - nl_update(0) + PLUMED_COLVAR_INIT(ao), + pbc(true), + buffer(0.1), + delta_g_ref(0.), + stride(10), + nl_update(0) { - vector atoms; - parseAtomList("ATOMS", atoms); - const unsigned size = atoms.size(); - bool tcorr = false; - parseFlag("TEMP_CORRECTION", tcorr); - parse("NL_BUFFER", buffer); - parse("NL_STRIDE", stride); + vector atoms; + parseAtomList("ATOMS", atoms); + const unsigned size = atoms.size(); + bool tcorr = false; + parseFlag("TEMP_CORRECTION", tcorr); + parse("NL_BUFFER", buffer); + parse("NL_STRIDE", stride); - bool nopbc = !pbc; - parseFlag("NOPBC", nopbc); - pbc = !nopbc; + bool nopbc = !pbc; + parseFlag("NOPBC", nopbc); + pbc = !nopbc; - checkRead(); + checkRead(); - log << " Bibliography " << plumed.cite("Bottaro S, Lindorff-Larsen K, Best R, J. Chem. Theory Comput. 9, 5641 (2013)") - << plumed.cite("Lazaridis T, Karplus M, Proteins Struct. Funct. Genet. 35, 133 (1999)"); log << "\n"; + log << " Bibliography " << plumed.cite("Bottaro S, Lindorff-Larsen K, Best R, J. Chem. Theory Comput. 9, 5641 (2013)") + << plumed.cite("Lazaridis T, Karplus M, Proteins Struct. Funct. Genet. 35, 133 (1999)"); log << "\n"; - nl.resize(size); - nlexpo.resize(size); - parameter.resize(size, vector(4, 0)); - setupConstants(atoms, parameter, tcorr); + nl.resize(size); + nlexpo.resize(size); + parameter.resize(size, vector(4, 0)); + setupConstants(atoms, parameter, tcorr); - addValueWithDerivatives(); - setNotPeriodic(); - requestAtoms(atoms); + addValueWithDerivatives(); + setNotPeriodic(); + requestAtoms(atoms); } void Implicit::update_neighb() { - const double lower_c2 = 0.24 * 0.24; // this is the cut-off for bonded atoms - const unsigned size = getNumberOfAtoms(); - for (unsigned i=0; i mlambda) mlambda = 1./parameter[j][2]; - const double c2 = (4. * mlambda + buffer) * (4. * mlambda + buffer); - if (d2 < c2 ) { - nl[i].push_back(j); - if(parameter[i][2] == parameter[j][2] && parameter[i][3] == parameter[j][3]) { - nlexpo[i].push_back(true); - } else nlexpo[i].push_back(false); - } - } + const double lower_c2 = 0.24 * 0.24; // this is the cut-off for bonded atoms + const unsigned size = getNumberOfAtoms(); + for (unsigned i=0; i mlambda) mlambda = 1./parameter[j][2]; + const double c2 = (4. * mlambda + buffer) * (4. * mlambda + buffer); + if (d2 < c2 ) { + nl[i].push_back(j); + if(parameter[i][2] == parameter[j][2] && parameter[i][3] == parameter[j][3]) { + nlexpo[i].push_back(true); + } else nlexpo[i].push_back(false); + } } + } } void Implicit::calculate() { - if(pbc) makeWhole(); - if(getExchangeStep()) nl_update = 0; - if (nl_update == 0) { - update_neighb(); - } + if(pbc) makeWhole(); + if(getExchangeStep()) nl_update = 0; + if (nl_update == 0) { + update_neighb(); + } - const unsigned size=getNumberOfAtoms(); - double bias = 0.0; - Tensor deriv_box; - unsigned nt=OpenMP::getNumThreads(); - const unsigned nn=nl.size(); - if(nt*10>nn) nt=nn/10; - if(nt==0)nt=1; - #pragma omp parallel num_threads(nt) - { - vector deriv_omp(size); - #pragma omp for reduction(+:bias) - for (unsigned i=0; inn) nt=nn/10; + if(nt==0)nt=1; + #pragma omp parallel num_threads(nt) + { + vector deriv_omp(size); + #pragma omp for reduction(+:bias) + for (unsigned i=0; i 0.25*inv_lambda_i) - { - const double inv_lambda2_i = inv_lambda_i * inv_lambda_i; - const double rij_vdwr_diff = rij - vdw_radius_i; - const double expo = exp(-inv_lambda2_i * rij_vdwr_diff * rij_vdwr_diff); - const double fact = expo * fact_ij; - fedensity += fact; - deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_i); - } + const Vector dist = delta(posi, getPosition(j)); + const double rij = dist.modulo(); + const double inv_rij = 1.0 / rij; + const double inv_rij2 = inv_rij * inv_rij; + const double fact_ij = inv_rij2 * delta_g_free_i * vdw_volume_j * INV_PI_SQRT_PI* inv_lambda_i; + const double fact_ji = inv_rij2 * delta_g_free_j * vdw_volume_i * INV_PI_SQRT_PI* inv_lambda_j; + double deriv = 0.; - // j-i interaction - if(inv_rij > 0.25*inv_lambda_j) - { - const double inv_lambda2_j = inv_lambda_j * inv_lambda_j; - const double rij_vdwr_diff = rij - vdw_radius_j; - const double expo = exp(-inv_lambda2_j * rij_vdwr_diff * rij_vdwr_diff); - const double fact = expo * fact_ji; - fedensity += fact; - deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_j); - } - } else { - // i-j interaction - if(inv_rij > 0.25*inv_lambda_i) - { - const double inv_lambda2 = inv_lambda_i * inv_lambda_i; - const double rij_vdwr_diff = rij - vdw_radius_i; - const double expo = exp(-inv_lambda2 * rij_vdwr_diff * rij_vdwr_diff); - const double fact = expo*(fact_ij + fact_ji); - fedensity += fact; - deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2); - } - } + // in this case we can calculate a single exponential + if(!nlexpo[i][i_nl]) { + // i-j interaction + if(inv_rij > 0.25*inv_lambda_i) + { + const double inv_lambda2_i = inv_lambda_i * inv_lambda_i; + const double rij_vdwr_diff = rij - vdw_radius_i; + const double expo = exp(-inv_lambda2_i * rij_vdwr_diff * rij_vdwr_diff); + const double fact = expo * fact_ij; + fedensity += fact; + deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_i); + } - const Vector dd = deriv*dist; - deriv_i += dd; - deriv_omp[j] -= dd; - } - deriv_omp[i] += deriv_i; - bias += - 0.5 * fedensity; - } - #pragma omp critical - for(unsigned i=0;i 0.25*inv_lambda_j) + { + const double inv_lambda2_j = inv_lambda_j * inv_lambda_j; + const double rij_vdwr_diff = rij - vdw_radius_j; + const double expo = exp(-inv_lambda2_j * rij_vdwr_diff * rij_vdwr_diff); + const double fact = expo * fact_ji; + fedensity += fact; + deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_j); + } + } else { + // i-j interaction + if(inv_rij > 0.25*inv_lambda_i) + { + const double inv_lambda2 = inv_lambda_i * inv_lambda_i; + const double rij_vdwr_diff = rij - vdw_radius_i; + const double expo = exp(-inv_lambda2 * rij_vdwr_diff * rij_vdwr_diff); + const double fact = expo*(fact_ij + fact_ji); + fedensity += fact; + deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2); + } } + + const Vector dd = deriv*dist; + deriv_i += dd; + deriv_omp[j] -= dd; + } + deriv_omp[i] += deriv_i; + bias += - 0.5 * fedensity; } + #pragma omp critical + for(unsigned i=0; i &atoms, vector > ¶meter, bool tcorr) { - vector > parameter_temp; - parameter_temp.resize(atoms.size()); - map > valuemap; - map > typemap; - valuemap = setupValueMap(); - typemap = setupTypeMap(); - vector moldat = plumed.getActionSet().select(); - if (moldat.size() == 1) { - log << " MOLINFO DATA found, using proper atom names\n"; - for(unsigned i=0; i > parameter_temp; + parameter_temp.resize(atoms.size()); + map > valuemap; + map > typemap; + valuemap = setupValueMap(); + typemap = setupTypeMap(); + vector moldat = plumed.getActionSet().select(); + if (moldat.size() == 1) { + log << " MOLINFO DATA found, using proper atom names\n"; + for(unsigned i=0; igetAtomName(atoms[i]); - string Rname = moldat[0]->getResidueName(atoms[i]); - string Atype = typemap[Rname][Aname]; + // Get atom and residue names + string Aname = moldat[0]->getAtomName(atoms[i]); + string Rname = moldat[0]->getResidueName(atoms[i]); + string Atype = typemap[Rname][Aname]; - // Check for terminal COOH or COO- (different atomtypes & parameters!) - if (moldat[0]->getAtomName(atoms[i]) == "OT1") { - // We create a temporary AtomNumber object to access future atoms - unsigned ai = atoms[i].index(); - AtomNumber tmp_an; - tmp_an.setIndex(ai + 2); - if (moldat[0]->getAtomName(tmp_an) == "HT2") { - // COOH - Atype = "OB"; - } else { - // COO- - Atype = "OC"; - } - } - if (moldat[0]->getAtomName(atoms[i]) == "OT2") { - unsigned ai = atoms[i].index(); - AtomNumber tmp_an; - tmp_an.setIndex(ai + 1); - if (moldat[0]->getAtomName(tmp_an) == "HT2") { - // COOH - Atype = "OH1"; - } else { - // COO- - Atype = "OC"; - } - } + // Check for terminal COOH or COO- (different atomtypes & parameters!) + if (moldat[0]->getAtomName(atoms[i]) == "OT1") { + // We create a temporary AtomNumber object to access future atoms + unsigned ai = atoms[i].index(); + AtomNumber tmp_an; + tmp_an.setIndex(ai + 2); + if (moldat[0]->getAtomName(tmp_an) == "HT2") { + // COOH + Atype = "OB"; + } else { + // COO- + Atype = "OC"; + } + } + if (moldat[0]->getAtomName(atoms[i]) == "OT2") { + unsigned ai = atoms[i].index(); + AtomNumber tmp_an; + tmp_an.setIndex(ai + 1); + if (moldat[0]->getAtomName(tmp_an) == "HT2") { + // COOH + Atype = "OH1"; + } else { + // COO- + Atype = "OC"; + } + } - // Check for H-atoms - char type; - char first = Aname.at(0); + // Check for H-atoms + char type; + char first = Aname.at(0); - // GOLDEN RULE: type is first letter, if not a number - if (!isdigit(first)){ - type = first; - // otherwise is the second - } else { - type = Aname.at(1); - } + // GOLDEN RULE: type is first letter, if not a number + if (!isdigit(first)) { + type = first; + // otherwise is the second + } else { + type = Aname.at(1); + } - if (type == 'H') { - error("EEF1-SB does not allow the use of hydrogen atoms!\n"); - } + if (type == 'H') { + error("EEF1-SB does not allow the use of hydrogen atoms!\n"); + } - // Lookup atomtype in table or throw exception if its not there - try { - parameter_temp[i] = valuemap.at(Atype); - } catch (exception &e) { - log << "Type: " << Atype << " Name: " << Aname << " Residue: " << Rname << "\n"; - error("Invalid atom type!\n"); - } + // Lookup atomtype in table or throw exception if its not there + try { + parameter_temp[i] = valuemap.at(Atype); + } catch (exception &e) { + log << "Type: " << Atype << " Name: " << Aname << " Residue: " << Rname << "\n"; + error("Invalid atom type!\n"); + } - // Temperature correction - if (tcorr && parameter[i][1] > 0.0) { - const double t0 = 298.15; - const double delta_g_ref_t0 = parameter_temp[i][1]; - const double delta_h_ref_t0 = parameter_temp[i][3]; - const double delta_cp = parameter_temp[i][4]; - const double delta_s_ref_t0 = (delta_h_ref_t0 - delta_g_ref_t0) / t0; - const double t = plumed.getAtoms().getKbT() / plumed.getAtoms().getKBoltzmann(); - parameter_temp[i][1] -= delta_s_ref_t0 * (t - t0) - delta_cp * t * std::log(t / t0) + delta_cp * (t - t0); - parameter_temp[i][2] *= parameter_temp[i][1] / delta_g_ref_t0; - } - parameter[i][0] = parameter_temp[i][0]; - parameter[i][1] = parameter_temp[i][2]; - parameter[i][2] = parameter_temp[i][5]; - parameter[i][3] = parameter_temp[i][6]; - } - } else { - error("MOLINFO DATA not found\n"); + // Temperature correction + if (tcorr && parameter[i][1] > 0.0) { + const double t0 = 298.15; + const double delta_g_ref_t0 = parameter_temp[i][1]; + const double delta_h_ref_t0 = parameter_temp[i][3]; + const double delta_cp = parameter_temp[i][4]; + const double delta_s_ref_t0 = (delta_h_ref_t0 - delta_g_ref_t0) / t0; + const double t = plumed.getAtoms().getKbT() / plumed.getAtoms().getKBoltzmann(); + parameter_temp[i][1] -= delta_s_ref_t0 * (t - t0) - delta_cp * t * std::log(t / t0) + delta_cp * (t - t0); + parameter_temp[i][2] *= parameter_temp[i][1] / delta_g_ref_t0; + } + parameter[i][0] = parameter_temp[i][0]; + parameter[i][1] = parameter_temp[i][2]; + parameter[i][2] = parameter_temp[i][5]; + parameter[i][3] = parameter_temp[i][6]; } - for(unsigned i=0; i > Implicit::setupTypeMap() { - map > typemap; - typemap = { - {"ALA", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT3"}, - {"HB1", "HA3"}, - {"HB2", "HA3"}, - {"HB3", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"ARG", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CT2"}, - {"HD1", "HA2"}, - {"HD2", "HA2"}, - {"NE", "NC2"}, - {"HE", "HC" }, - {"CZ", "C" }, - {"NH1", "NC2"}, - {"HH11", "HC" }, - {"HH12", "HC" }, - {"NH2", "NC2"}, - {"HH21", "HC" }, - {"HH22", "HC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"ASN", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CC" }, - {"OD1", "O" }, - {"ND2", "NH2"}, - {"HD21", "H" }, - {"HD22", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"ASPP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CD" }, - {"OD1", "OB" }, - {"OD2", "OH1"}, - {"HD2", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"ASP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CC" }, - {"OD1", "OC" }, - {"OD2", "OC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"CYS", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"SG", "S" }, - {"HG1", "HS" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLN", { - {"N", "NH1" }, - {"HN", "H" }, - {"CA", "CT1" }, - {"HA", "HB1" }, - {"CB", "CT2" }, - {"HB1", "HA2" }, - {"HB2", "HA2" }, - {"CG", "CT2" }, - {"HG1", "HA2" }, - {"HG2", "HA2" }, - {"CD", "CC" }, - {"OE1", "O" }, - {"NE2", "NH2" }, - {"HE21", "H" }, - {"HE22", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLUP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CD" }, - {"OE1", "OB" }, - {"OE2", "OH1"}, - {"HE2", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLU", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CC" }, - {"OE1", "OC" }, - {"OE2", "OC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLY", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT2"}, - {"HA1", "HB2"}, - {"HA2", "HB2"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HSD", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"ND1", "NR1"}, - {"HD1", "H" }, - {"CG", "CPH1"}, - {"CE1", "CPH2"}, - {"HE1", "HR1"}, - {"NE2", "NR2"}, - {"CD2", "CPH1"}, - {"HD2", "HR3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HIS", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"ND1", "NR2"}, - {"CG", "CPH1"}, - {"CE1", "CPH2"}, - {"HE1", "HR1"}, - {"NE2", "NR1"}, - {"HE2", "H" }, - {"CD2", "CPH1"}, - {"HD2", "HR3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HSE", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"ND1", "NR2"}, - {"CG", "CPH1"}, - {"CE1", "CPH2"}, - {"HE1", "HR1"}, - {"NE2", "NR1"}, - {"HE2", "H" }, - {"CD2", "CPH1"}, - {"HD2", "HR3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HSP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CD2", "CPH1"}, - {"HD2", "HR1"}, - {"CG", "CPH1"}, - {"NE2", "NR3"}, - {"HE2", "H" }, - {"ND1", "NR3"}, - {"HD1", "H" }, - {"CE1", "CPH2"}, - {"HE1", "HR2"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"ILE", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT1"}, - {"HB", "HA1"}, - {"CG2", "CT3"}, - {"HG21", "HA3"}, - {"HG22", "HA3"}, - {"HG23", "HA3"}, - {"CG1", "CT2"}, - {"HG11", "HA2"}, - {"HG12", "HA2"}, - {"CD", "CT3"}, - {"HD1", "HA3"}, - {"HD2", "HA3"}, - {"HD3", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"LEU", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT1"}, - {"HG", "HA1"}, - {"CD1", "CT3"}, - {"HD11", "HA3"}, - {"HD12", "HA3"}, - {"HD13", "HA3"}, - {"CD2", "CT3"}, - {"HD21", "HA3"}, - {"HD22", "HA3"}, - {"HD23", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"LYS", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CT2"}, - {"HD1", "HA2"}, - {"HD2", "HA2"}, - {"CE", "CT2"}, - {"HE1", "HA2"}, - {"HE2", "HA2"}, - {"NZ", "NH3"}, - {"HZ1", "HC" }, - {"HZ2", "HC" }, - {"HZ3", "HC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"MET", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"SD", "S" }, - {"CE", "CT3"}, - {"HE1", "HA3"}, - {"HE2", "HA3"}, - {"HE3", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"PHE", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CA" }, - {"CD1", "CA" }, - {"HD1", "HP" }, - {"CE1", "CA" }, - {"HE1", "HP" }, - {"CZ", "CA" }, - {"HZ", "HP" }, - {"CD2", "CA" }, - {"HD2", "HP" }, - {"CE2", "CA" }, - {"HE2", "HP" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"PRO", { - {"N", "N" }, - {"CD", "CP3"}, - {"HD1", "HA2"}, - {"HD2", "HA2"}, - {"CA", "CP1"}, - {"HA", "HB1"}, - {"CB", "CP2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CP2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"SER", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"OG", "OH1"}, - {"HG1", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"THR", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT1"}, - {"HB", "HA1"}, - {"OG1", "OH1"}, - {"HG1", "H" }, - {"CG2", "CT3"}, - {"HG21", "HA3"}, - {"HG22", "HA3"}, - {"HG23", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"TRP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CY" }, - {"CD1", "CA" }, - {"HD1", "HP" }, - {"NE1", "NY" }, - {"HE1", "H" }, - {"CE2", "CPT"}, - {"CD2", "CPT"}, - {"CE3", "CAI"}, - {"HE3", "HP" }, - {"CZ3", "CA" }, - {"HZ3", "HP" }, - {"CZ2", "CAI"}, - {"HZ2", "HP" }, - {"CH2", "CA" }, - {"HH2", "HP" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"TYR", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CA" }, - {"CD1", "CA" }, - {"HD1", "HP" }, - {"CE1", "CA" }, - {"HE1", "HP" }, - {"CZ", "CA" }, - {"OH", "OH1"}, - {"HH", "H" }, - {"CD2", "CA" }, - {"HD2", "HP" }, - {"CE2", "CA" }, - {"HE2", "HP" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"VAL", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT1"}, - {"HB", "HA1"}, - {"CG1", "CT3"}, - {"HG11", "HA3"}, - {"HG12", "HA3"}, - {"HG13", "HA3"}, - {"CG2", "CT3"}, - {"HG21", "HA3"}, - {"HG22", "HA3"}, - {"HG23", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - } - }; - return typemap; + map > typemap; + typemap = { + { "ALA", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT3"}, + {"HB1", "HA3"}, + {"HB2", "HA3"}, + {"HB3", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "ARG", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CT2"}, + {"HD1", "HA2"}, + {"HD2", "HA2"}, + {"NE", "NC2"}, + {"HE", "HC" }, + {"CZ", "C" }, + {"NH1", "NC2"}, + {"HH11", "HC" }, + {"HH12", "HC" }, + {"NH2", "NC2"}, + {"HH21", "HC" }, + {"HH22", "HC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "ASN", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CC" }, + {"OD1", "O" }, + {"ND2", "NH2"}, + {"HD21", "H" }, + {"HD22", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "ASPP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CD" }, + {"OD1", "OB" }, + {"OD2", "OH1"}, + {"HD2", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "ASP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CC" }, + {"OD1", "OC" }, + {"OD2", "OC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "CYS", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"SG", "S" }, + {"HG1", "HS" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLN", { + {"N", "NH1" }, + {"HN", "H" }, + {"CA", "CT1" }, + {"HA", "HB1" }, + {"CB", "CT2" }, + {"HB1", "HA2" }, + {"HB2", "HA2" }, + {"CG", "CT2" }, + {"HG1", "HA2" }, + {"HG2", "HA2" }, + {"CD", "CC" }, + {"OE1", "O" }, + {"NE2", "NH2" }, + {"HE21", "H" }, + {"HE22", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLUP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CD" }, + {"OE1", "OB" }, + {"OE2", "OH1"}, + {"HE2", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLU", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CC" }, + {"OE1", "OC" }, + {"OE2", "OC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLY", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT2"}, + {"HA1", "HB2"}, + {"HA2", "HB2"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HSD", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"ND1", "NR1"}, + {"HD1", "H" }, + {"CG", "CPH1"}, + {"CE1", "CPH2"}, + {"HE1", "HR1"}, + {"NE2", "NR2"}, + {"CD2", "CPH1"}, + {"HD2", "HR3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HIS", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"ND1", "NR2"}, + {"CG", "CPH1"}, + {"CE1", "CPH2"}, + {"HE1", "HR1"}, + {"NE2", "NR1"}, + {"HE2", "H" }, + {"CD2", "CPH1"}, + {"HD2", "HR3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HSE", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"ND1", "NR2"}, + {"CG", "CPH1"}, + {"CE1", "CPH2"}, + {"HE1", "HR1"}, + {"NE2", "NR1"}, + {"HE2", "H" }, + {"CD2", "CPH1"}, + {"HD2", "HR3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HSP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CD2", "CPH1"}, + {"HD2", "HR1"}, + {"CG", "CPH1"}, + {"NE2", "NR3"}, + {"HE2", "H" }, + {"ND1", "NR3"}, + {"HD1", "H" }, + {"CE1", "CPH2"}, + {"HE1", "HR2"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "ILE", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT1"}, + {"HB", "HA1"}, + {"CG2", "CT3"}, + {"HG21", "HA3"}, + {"HG22", "HA3"}, + {"HG23", "HA3"}, + {"CG1", "CT2"}, + {"HG11", "HA2"}, + {"HG12", "HA2"}, + {"CD", "CT3"}, + {"HD1", "HA3"}, + {"HD2", "HA3"}, + {"HD3", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "LEU", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT1"}, + {"HG", "HA1"}, + {"CD1", "CT3"}, + {"HD11", "HA3"}, + {"HD12", "HA3"}, + {"HD13", "HA3"}, + {"CD2", "CT3"}, + {"HD21", "HA3"}, + {"HD22", "HA3"}, + {"HD23", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "LYS", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CT2"}, + {"HD1", "HA2"}, + {"HD2", "HA2"}, + {"CE", "CT2"}, + {"HE1", "HA2"}, + {"HE2", "HA2"}, + {"NZ", "NH3"}, + {"HZ1", "HC" }, + {"HZ2", "HC" }, + {"HZ3", "HC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "MET", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"SD", "S" }, + {"CE", "CT3"}, + {"HE1", "HA3"}, + {"HE2", "HA3"}, + {"HE3", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "PHE", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CA" }, + {"CD1", "CA" }, + {"HD1", "HP" }, + {"CE1", "CA" }, + {"HE1", "HP" }, + {"CZ", "CA" }, + {"HZ", "HP" }, + {"CD2", "CA" }, + {"HD2", "HP" }, + {"CE2", "CA" }, + {"HE2", "HP" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "PRO", { + {"N", "N" }, + {"CD", "CP3"}, + {"HD1", "HA2"}, + {"HD2", "HA2"}, + {"CA", "CP1"}, + {"HA", "HB1"}, + {"CB", "CP2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CP2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "SER", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"OG", "OH1"}, + {"HG1", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "THR", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT1"}, + {"HB", "HA1"}, + {"OG1", "OH1"}, + {"HG1", "H" }, + {"CG2", "CT3"}, + {"HG21", "HA3"}, + {"HG22", "HA3"}, + {"HG23", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "TRP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CY" }, + {"CD1", "CA" }, + {"HD1", "HP" }, + {"NE1", "NY" }, + {"HE1", "H" }, + {"CE2", "CPT"}, + {"CD2", "CPT"}, + {"CE3", "CAI"}, + {"HE3", "HP" }, + {"CZ3", "CA" }, + {"HZ3", "HP" }, + {"CZ2", "CAI"}, + {"HZ2", "HP" }, + {"CH2", "CA" }, + {"HH2", "HP" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "TYR", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CA" }, + {"CD1", "CA" }, + {"HD1", "HP" }, + {"CE1", "CA" }, + {"HE1", "HP" }, + {"CZ", "CA" }, + {"OH", "OH1"}, + {"HH", "H" }, + {"CD2", "CA" }, + {"HD2", "HP" }, + {"CE2", "CA" }, + {"HE2", "HP" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "VAL", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT1"}, + {"HB", "HA1"}, + {"CG1", "CT3"}, + {"HG11", "HA3"}, + {"HG12", "HA3"}, + {"HG13", "HA3"}, + {"CG2", "CT3"}, + {"HG21", "HA3"}, + {"HG22", "HA3"}, + {"HG23", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + } + }; + return typemap; } map > Implicit::setupValueMap() { - // Volume ∆Gref ∆Gfree ∆H ∆Cp λ vdw_radius - map > valuemap; - valuemap = { - {"C", { - ANG3_TO_NM3 * 14.720, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CD", { - ANG3_TO_NM3 * 14.720, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT1", { - ANG3_TO_NM3 * 11.507, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * 0.876, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT2", { - ANG3_TO_NM3 * 18.850, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT2A", { - ANG3_TO_NM3 * 18.666, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT3", { - ANG3_TO_NM3 * 27.941, - KCAL_TO_KJ * 1.089, - KCAL_TO_KJ * 1.089, - KCAL_TO_KJ * -1.779, - KCAL_TO_KJ * 35.6, - 1. / (ANG_TO_NM * 3.5), - 0.204, - } - }, - {"CPH1", { - ANG3_TO_NM3 * 5.275, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.080, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.18, - } - }, - {"CPH2", { - ANG3_TO_NM3 * 11.796, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.080, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.18, - } - }, - {"CPT", { - ANG3_TO_NM3 * 4.669, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * 2.220, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.186, - } - }, - {"CY", { - ANG3_TO_NM3 * 10.507, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * 2.220, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.199, - } - }, - {"CP1", { - ANG3_TO_NM3 * 25.458, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * 0.876, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.227, - } - }, - {"CP2", { - ANG3_TO_NM3 * 19.880, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.217, - } - }, - {"CP3", { - ANG3_TO_NM3 * 26.731, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.217, - } - }, - {"CC", { - ANG3_TO_NM3 * 16.539, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CAI", { - ANG3_TO_NM3 * 18.249, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.199, - } - }, - {"CA", { - ANG3_TO_NM3 * 18.249, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.199, - } - }, - {"N", { - ANG3_TO_NM3 * 0.000, - KCAL_TO_KJ * -1.000, - KCAL_TO_KJ * -1.000, - KCAL_TO_KJ * -1.250, - KCAL_TO_KJ * 8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NR1", { - ANG3_TO_NM3 * 15.273, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NR2", { - ANG3_TO_NM3 * 15.111, - KCAL_TO_KJ * -3.820, - KCAL_TO_KJ * -3.820, - KCAL_TO_KJ * -4.654, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NR3", { - ANG3_TO_NM3 * 15.071, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NH1", { - ANG3_TO_NM3 * 10.197, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NH2", { - ANG3_TO_NM3 * 18.182, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NH3", { - ANG3_TO_NM3 * 18.817, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -25.000, - KCAL_TO_KJ * -18.0, - 1. / (ANG_TO_NM * 6.0), - 0.185, - } - }, - {"NC2", { - ANG3_TO_NM3 * 18.215, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -12.000, - KCAL_TO_KJ * -7.0, - 1. / (ANG_TO_NM * 6.0), - 0.185, - } - }, - {"NY", { - ANG3_TO_NM3 * 12.001, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NP", { - ANG3_TO_NM3 * 4.993, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -25.000, - KCAL_TO_KJ * -18.0, - 1. / (ANG_TO_NM * 6.0), - 0.185, - } - }, - {"O", { - ANG3_TO_NM3 * 11.772, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.787, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.170, - } - }, - {"OB", { - ANG3_TO_NM3 * 11.694, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.787, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.170, - } - }, - {"OC", { - ANG3_TO_NM3 * 12.003, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -12.000, - KCAL_TO_KJ * -9.4, - 1. / (ANG_TO_NM * 6.0), - 0.170, - } - }, - {"OH1", { - ANG3_TO_NM3 * 15.528, - KCAL_TO_KJ * -5.920, - KCAL_TO_KJ * -5.920, - KCAL_TO_KJ * -9.264, - KCAL_TO_KJ * -11.2, - 1. / (ANG_TO_NM * 3.5), - 0.177, - } - }, - {"OS", { - ANG3_TO_NM3 * 6.774, - KCAL_TO_KJ * -2.900, - KCAL_TO_KJ * -2.900, - KCAL_TO_KJ * -3.150, - KCAL_TO_KJ * -4.8, - 1. / (ANG_TO_NM * 3.5), - 0.177, - } - }, - {"S", { - ANG3_TO_NM3 * 20.703, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -4.475, - KCAL_TO_KJ * -39.9, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"SM", { - ANG3_TO_NM3 * 21.306, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -4.475, - KCAL_TO_KJ * -39.9, - 1. / (ANG_TO_NM * 3.5), - 0.197, - } - } - }; - return valuemap; -} + // Volume ∆Gref ∆Gfree ∆H ∆Cp λ vdw_radius + map > valuemap; + valuemap = { + { "C", { + ANG3_TO_NM3 * 14.720, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CD", { + ANG3_TO_NM3 * 14.720, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT1", { + ANG3_TO_NM3 * 11.507, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * 0.876, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT2", { + ANG3_TO_NM3 * 18.850, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT2A", { + ANG3_TO_NM3 * 18.666, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT3", { + ANG3_TO_NM3 * 27.941, + KCAL_TO_KJ * 1.089, + KCAL_TO_KJ * 1.089, + KCAL_TO_KJ * -1.779, + KCAL_TO_KJ * 35.6, + 1. / (ANG_TO_NM * 3.5), + 0.204, + } + }, + { "CPH1", { + ANG3_TO_NM3 * 5.275, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.080, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.18, + } + }, + { "CPH2", { + ANG3_TO_NM3 * 11.796, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.080, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.18, + } + }, + { "CPT", { + ANG3_TO_NM3 * 4.669, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * 2.220, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.186, + } + }, + { "CY", { + ANG3_TO_NM3 * 10.507, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * 2.220, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.199, + } + }, + { "CP1", { + ANG3_TO_NM3 * 25.458, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * 0.876, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.227, + } + }, + { "CP2", { + ANG3_TO_NM3 * 19.880, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.217, + } + }, + { "CP3", { + ANG3_TO_NM3 * 26.731, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.217, + } + }, + { "CC", { + ANG3_TO_NM3 * 16.539, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CAI", { + ANG3_TO_NM3 * 18.249, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.199, + } + }, + { "CA", { + ANG3_TO_NM3 * 18.249, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.199, + } + }, + { "N", { + ANG3_TO_NM3 * 0.000, + KCAL_TO_KJ * -1.000, + KCAL_TO_KJ * -1.000, + KCAL_TO_KJ * -1.250, + KCAL_TO_KJ * 8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NR1", { + ANG3_TO_NM3 * 15.273, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NR2", { + ANG3_TO_NM3 * 15.111, + KCAL_TO_KJ * -3.820, + KCAL_TO_KJ * -3.820, + KCAL_TO_KJ * -4.654, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NR3", { + ANG3_TO_NM3 * 15.071, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NH1", { + ANG3_TO_NM3 * 10.197, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NH2", { + ANG3_TO_NM3 * 18.182, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NH3", { + ANG3_TO_NM3 * 18.817, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -25.000, + KCAL_TO_KJ * -18.0, + 1. / (ANG_TO_NM * 6.0), + 0.185, + } + }, + { "NC2", { + ANG3_TO_NM3 * 18.215, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -12.000, + KCAL_TO_KJ * -7.0, + 1. / (ANG_TO_NM * 6.0), + 0.185, + } + }, + { "NY", { + ANG3_TO_NM3 * 12.001, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NP", { + ANG3_TO_NM3 * 4.993, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -25.000, + KCAL_TO_KJ * -18.0, + 1. / (ANG_TO_NM * 6.0), + 0.185, + } + }, + { "O", { + ANG3_TO_NM3 * 11.772, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.787, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.170, + } + }, + { "OB", { + ANG3_TO_NM3 * 11.694, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.787, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.170, + } + }, + { "OC", { + ANG3_TO_NM3 * 12.003, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -12.000, + KCAL_TO_KJ * -9.4, + 1. / (ANG_TO_NM * 6.0), + 0.170, + } + }, + { "OH1", { + ANG3_TO_NM3 * 15.528, + KCAL_TO_KJ * -5.920, + KCAL_TO_KJ * -5.920, + KCAL_TO_KJ * -9.264, + KCAL_TO_KJ * -11.2, + 1. / (ANG_TO_NM * 3.5), + 0.177, + } + }, + { "OS", { + ANG3_TO_NM3 * 6.774, + KCAL_TO_KJ * -2.900, + KCAL_TO_KJ * -2.900, + KCAL_TO_KJ * -3.150, + KCAL_TO_KJ * -4.8, + 1. / (ANG_TO_NM * 3.5), + 0.177, + } + }, + { "S", { + ANG3_TO_NM3 * 20.703, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -4.475, + KCAL_TO_KJ * -39.9, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "SM", { + ANG3_TO_NM3 * 21.306, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -4.475, + KCAL_TO_KJ * -39.9, + 1. / (ANG_TO_NM * 3.5), + 0.197, + } } + }; + return valuemap; +} +} } diff --git a/src/colvar/Jcoupling.cpp b/src/colvar/Jcoupling.cpp index d7fda854c0..d192b8bbd6 100644 --- a/src/colvar/Jcoupling.cpp +++ b/src/colvar/Jcoupling.cpp @@ -29,8 +29,8 @@ using namespace std; -namespace PLMD{ - namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR JCOUPLING /* @@ -90,242 +90,242 @@ ENDPLUMED */ //+ENDPLUMEDOC - class JCoupling : public Colvar { - private: - bool pbc; - vector coupl; - unsigned ndata; - unsigned jtype_; - enum { HAN, HAHN, CCG, NCG, CUSTOM }; - double ka_; - double kb_; - double kc_; - double kshift_; - - public: - explicit JCoupling(const ActionOptions&); - virtual void calculate(); - static void registerKeywords(Keywords& keys); - }; - - PLUMED_REGISTER_ACTION(JCoupling, "JCOUPLING") - - void JCoupling::registerKeywords(Keywords& keys) { - Colvar::registerKeywords(keys); - componentsAreNotOptional(keys); - useCustomisableComponents(keys); - keys.add("numbered", "ATOMS", "the 4 atoms involved in each of the bonds for which you wish to calculate the J-coupling. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one J-coupling will be " - "calculated for each ATOMS keyword you specify."); - keys.reset_style("ATOMS", "atoms"); - keys.addFlag("ADDCOUPLINGS", false, "Set this flag if you want to have fixed components with the experimental values."); - keys.add("compulsory", "TYPE", "Type of J-coupling to compute (HAN,HAHN,CCG,NCG,CUSTOM)"); - keys.add("optional", "A", "Karplus parameter A"); - keys.add("optional", "B", "Karplus parameter B"); - keys.add("optional", "C", "Karplus parameter C"); - keys.add("optional", "SHIFT", "Angle shift in radians"); - keys.add("numbered", "COUPLING", "Add an experimental value for each coupling"); - keys.addOutputComponent("j", "default", "the calculated J-coupling"); - keys.addOutputComponent("exp", "ADDCOUPLINGS", "the experimental J-coupling"); - } - - JCoupling::JCoupling(const ActionOptions&ao): - PLUMED_COLVAR_INIT(ao), - pbc(true), - ndata(0) - { - bool nopbc = !pbc; - parseFlag("NOPBC", nopbc); - pbc =! nopbc; - - // Read in the atoms - vector t, atoms; - for (int i = 1; ; ++i) { - parseAtomList("ATOMS", i, t ); - if (t.empty()) { - break; - } - - if (t.size() != 4) { - std::string ss; - Tools::convert(i, ss); - error("ATOMS" + ss + " keyword has the wrong number of atoms"); - } - - // This makes the distance calculation easier later on (see Torsion implementation) - atoms.push_back(t[0]); - atoms.push_back(t[1]); - atoms.push_back(t[1]); - atoms.push_back(t[2]); - atoms.push_back(t[2]); - atoms.push_back(t[3]); - t.resize(0); - } - - // We now have 6 atoms per datapoint - ndata = atoms.size()/6; - - // Parse J-Coupling type, this will determine the Karplus parameters - string string_type; - parse("TYPE", string_type); - if(string_type == "HAN") { - jtype_ = HAN; - } else if(string_type == "HAHN") { - jtype_ = HAHN; - } else if(string_type == "CCG") { - jtype_ = CCG; - } else if(string_type == "NCG") { - jtype_ = NCG; - } else if(string_type == "CUSTOM") { - jtype_ = CUSTOM; - } else { - error("Unknown J-coupling type!"); - } - - // Optionally add an experimental value (like with RDCs) - bool addcoupling = false; - parseFlag("ADDCOUPLINGS", addcoupling); - if (addcoupling) { - coupl.resize(ndata); - unsigned ntarget = 0; - for (unsigned i = 0; i < ndata; ++i) { - if (!parseNumbered("COUPLING", i+1, coupl[i])){ - break; - } - ntarget++; - } - if (ntarget != ndata) { - error("found wrong number of COUPLING values"); - } - } - - // For custom types we allow use of custom Karplus parameters - if (jtype_ == CUSTOM) { - parse("A", ka_); - parse("B", kb_); - parse("C", kc_); - parse("SHIFT", kshift_); - } - - checkRead(); - - // Set Karplus parameters - switch (jtype_) { - case HAN: - ka_ = -0.88; - kb_ = -0.61; - kc_ = -0.27; - kshift_ = pi / 3.0; - log.printf("J-coupling type is HAN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Wang A C, Bax A, J. Am. Chem. Soc. 117, 1810 (1995)") << "\n"; - break; - case HAHN: - ka_ = 7.09; - kb_ = -1.42; - kc_ = 1.55; - kshift_ = -pi / 3.0; - log.printf("J-coupling type is HAHN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Hu J-S, Bax A, J. Am. Chem. Soc. 119, 6360 (1997)") << "\n"; - break; - case CCG: - ka_ = 2.31; - kb_ = -0.87; - kc_ = 0.55; - kshift_ = (2.0 * pi) / 3.0; - log.printf("J-coupling type is CCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; - break; - case NCG: - ka_ = 1.29; - kb_ = -0.49; - kc_ = 0.37; - kshift_ = 0.0; - log.printf("J-coupling type is NCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; - break; - case CUSTOM: - log.printf("J-coupling type is custom, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - break; - } - - for (unsigned i = 0; i < ndata; ++i) { - log.printf(" The %uth J-Coupling is calculated from atoms : %d %d %d %d.", - i+1, atoms[2*i].serial(), atoms[2*i+1].serial(), atoms[2*i+2].serial(), atoms[2*i+3].serial()); - if (addcoupling) { - log.printf(" Experimental J-Coupling is %f.", coupl[i]); - } - log.printf("\n"); - } - - if (pbc) { - log.printf(" using periodic boundary conditions\n"); - } else { - log.printf(" without periodic boundary conditions\n"); - } - - for (unsigned i = 0; i < ndata; i++) { - std::string num; Tools::convert(i, num); - addComponentWithDerivatives("j_" + num); - componentIsNotPeriodic("j_" + num); - } - - if (addcoupling) { - for (unsigned i = 0; i < ndata; i++) { - std::string num; Tools::convert(i, num); - addComponent("exp_" + num); - componentIsNotPeriodic("exp_" + num); - Value* comp = getPntrToComponent("exp_" + num); - comp->set(coupl[i]); - } - } - - requestAtoms(atoms); - } - - void JCoupling::calculate() { - if (pbc) { - makeWhole(); - } - - // Loop through atoms, with steps of 6 atoms (one iteration per datapoint) - for (unsigned r = 0; r < (ndata * 6); r += 6) { - // Index is the datapoint index - const unsigned index = r / 6; - - // 6 atoms -> 3 vectors - Vector d0, d1, d2; - d0 = delta(getPosition(r + 1), getPosition(r + 0)); - d1 = delta(getPosition(r + 3), getPosition(r + 2)); - d2 = delta(getPosition(r + 5), getPosition(r + 4)); - - // Calculate dihedral with 3 vectors, get the derivatives - Vector dd0, dd1, dd2; - PLMD::Torsion t; - const double torsion = t.compute(d0, d1, d2, dd0, dd1, dd2); - - // Calculate the Karplus relation and its derivative - const double theta = torsion + kshift_; - const double cos_theta = cos(theta); - const double j = ka_ * cos_theta * cos_theta + kb_ * cos_theta + kc_; - const double derj = sin(theta) * (-1.0 * (2.0 * ka_ * cos_theta + kb_)); - - Value* val = getPntrToComponent(index); - val->set(j); - - setAtomsDerivatives(val, r + 0, derj * dd0); - setAtomsDerivatives(val, r + 1, derj * -dd0); - setAtomsDerivatives(val, r + 2, derj * dd1); - setAtomsDerivatives(val, r + 3, derj * -dd1); - setAtomsDerivatives(val, r + 4, derj * dd2); - setAtomsDerivatives(val, r + 5, derj * -dd2); - setBoxDerivativesNoPbc(val); - } - } +class JCoupling : public Colvar { +private: + bool pbc; + vector coupl; + unsigned ndata; + unsigned jtype_; + enum { HAN, HAHN, CCG, NCG, CUSTOM }; + double ka_; + double kb_; + double kc_; + double kshift_; + +public: + explicit JCoupling(const ActionOptions&); + virtual void calculate(); + static void registerKeywords(Keywords& keys); +}; + +PLUMED_REGISTER_ACTION(JCoupling, "JCOUPLING") + +void JCoupling::registerKeywords(Keywords& keys) { + Colvar::registerKeywords(keys); + componentsAreNotOptional(keys); + useCustomisableComponents(keys); + keys.add("numbered", "ATOMS", "the 4 atoms involved in each of the bonds for which you wish to calculate the J-coupling. " + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one J-coupling will be " + "calculated for each ATOMS keyword you specify."); + keys.reset_style("ATOMS", "atoms"); + keys.addFlag("ADDCOUPLINGS", false, "Set this flag if you want to have fixed components with the experimental values."); + keys.add("compulsory", "TYPE", "Type of J-coupling to compute (HAN,HAHN,CCG,NCG,CUSTOM)"); + keys.add("optional", "A", "Karplus parameter A"); + keys.add("optional", "B", "Karplus parameter B"); + keys.add("optional", "C", "Karplus parameter C"); + keys.add("optional", "SHIFT", "Angle shift in radians"); + keys.add("numbered", "COUPLING", "Add an experimental value for each coupling"); + keys.addOutputComponent("j", "default", "the calculated J-coupling"); + keys.addOutputComponent("exp", "ADDCOUPLINGS", "the experimental J-coupling"); +} + +JCoupling::JCoupling(const ActionOptions&ao): + PLUMED_COLVAR_INIT(ao), + pbc(true), + ndata(0) +{ + bool nopbc = !pbc; + parseFlag("NOPBC", nopbc); + pbc =! nopbc; + + // Read in the atoms + vector t, atoms; + for (int i = 1; ; ++i) { + parseAtomList("ATOMS", i, t ); + if (t.empty()) { + break; + } + + if (t.size() != 4) { + std::string ss; + Tools::convert(i, ss); + error("ATOMS" + ss + " keyword has the wrong number of atoms"); + } + + // This makes the distance calculation easier later on (see Torsion implementation) + atoms.push_back(t[0]); + atoms.push_back(t[1]); + atoms.push_back(t[1]); + atoms.push_back(t[2]); + atoms.push_back(t[2]); + atoms.push_back(t[3]); + t.resize(0); + } + + // We now have 6 atoms per datapoint + ndata = atoms.size()/6; + + // Parse J-Coupling type, this will determine the Karplus parameters + string string_type; + parse("TYPE", string_type); + if(string_type == "HAN") { + jtype_ = HAN; + } else if(string_type == "HAHN") { + jtype_ = HAHN; + } else if(string_type == "CCG") { + jtype_ = CCG; + } else if(string_type == "NCG") { + jtype_ = NCG; + } else if(string_type == "CUSTOM") { + jtype_ = CUSTOM; + } else { + error("Unknown J-coupling type!"); + } + + // Optionally add an experimental value (like with RDCs) + bool addcoupling = false; + parseFlag("ADDCOUPLINGS", addcoupling); + if (addcoupling) { + coupl.resize(ndata); + unsigned ntarget = 0; + for (unsigned i = 0; i < ndata; ++i) { + if (!parseNumbered("COUPLING", i+1, coupl[i])) { + break; + } + ntarget++; + } + if (ntarget != ndata) { + error("found wrong number of COUPLING values"); } + } + + // For custom types we allow use of custom Karplus parameters + if (jtype_ == CUSTOM) { + parse("A", ka_); + parse("B", kb_); + parse("C", kc_); + parse("SHIFT", kshift_); + } + + checkRead(); + + // Set Karplus parameters + switch (jtype_) { + case HAN: + ka_ = -0.88; + kb_ = -0.61; + kc_ = -0.27; + kshift_ = pi / 3.0; + log.printf("J-coupling type is HAN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Wang A C, Bax A, J. Am. Chem. Soc. 117, 1810 (1995)") << "\n"; + break; + case HAHN: + ka_ = 7.09; + kb_ = -1.42; + kc_ = 1.55; + kshift_ = -pi / 3.0; + log.printf("J-coupling type is HAHN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Hu J-S, Bax A, J. Am. Chem. Soc. 119, 6360 (1997)") << "\n"; + break; + case CCG: + ka_ = 2.31; + kb_ = -0.87; + kc_ = 0.55; + kshift_ = (2.0 * pi) / 3.0; + log.printf("J-coupling type is CCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; + break; + case NCG: + ka_ = 1.29; + kb_ = -0.49; + kc_ = 0.37; + kshift_ = 0.0; + log.printf("J-coupling type is NCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; + break; + case CUSTOM: + log.printf("J-coupling type is custom, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + break; + } + + for (unsigned i = 0; i < ndata; ++i) { + log.printf(" The %uth J-Coupling is calculated from atoms : %d %d %d %d.", + i+1, atoms[2*i].serial(), atoms[2*i+1].serial(), atoms[2*i+2].serial(), atoms[2*i+3].serial()); + if (addcoupling) { + log.printf(" Experimental J-Coupling is %f.", coupl[i]); + } + log.printf("\n"); + } + + if (pbc) { + log.printf(" using periodic boundary conditions\n"); + } else { + log.printf(" without periodic boundary conditions\n"); + } + + for (unsigned i = 0; i < ndata; i++) { + std::string num; Tools::convert(i, num); + addComponentWithDerivatives("j_" + num); + componentIsNotPeriodic("j_" + num); + } + + if (addcoupling) { + for (unsigned i = 0; i < ndata; i++) { + std::string num; Tools::convert(i, num); + addComponent("exp_" + num); + componentIsNotPeriodic("exp_" + num); + Value* comp = getPntrToComponent("exp_" + num); + comp->set(coupl[i]); + } + } + + requestAtoms(atoms); +} + +void JCoupling::calculate() { + if (pbc) { + makeWhole(); + } + + // Loop through atoms, with steps of 6 atoms (one iteration per datapoint) + for (unsigned r = 0; r < (ndata * 6); r += 6) { + // Index is the datapoint index + const unsigned index = r / 6; + + // 6 atoms -> 3 vectors + Vector d0, d1, d2; + d0 = delta(getPosition(r + 1), getPosition(r + 0)); + d1 = delta(getPosition(r + 3), getPosition(r + 2)); + d2 = delta(getPosition(r + 5), getPosition(r + 4)); + + // Calculate dihedral with 3 vectors, get the derivatives + Vector dd0, dd1, dd2; + PLMD::Torsion t; + const double torsion = t.compute(d0, d1, d2, dd0, dd1, dd2); + + // Calculate the Karplus relation and its derivative + const double theta = torsion + kshift_; + const double cos_theta = cos(theta); + const double j = ka_ * cos_theta * cos_theta + kb_ * cos_theta + kc_; + const double derj = sin(theta) * (-1.0 * (2.0 * ka_ * cos_theta + kb_)); + + Value* val = getPntrToComponent(index); + val->set(j); + + setAtomsDerivatives(val, r + 0, derj * dd0); + setAtomsDerivatives(val, r + 1, derj * -dd0); + setAtomsDerivatives(val, r + 2, derj * dd1); + setAtomsDerivatives(val, r + 3, derj * -dd1); + setAtomsDerivatives(val, r + 4, derj * dd2); + setAtomsDerivatives(val, r + 5, derj * -dd2); + setBoxDerivativesNoPbc(val); + } +} +} } diff --git a/src/colvar/MultiRMSD.cpp b/src/colvar/MultiRMSD.cpp index 72e62b9456..7656c232be 100644 --- a/src/colvar/MultiRMSD.cpp +++ b/src/colvar/MultiRMSD.cpp @@ -30,13 +30,13 @@ using namespace std; -namespace PLMD{ -namespace colvar{ - +namespace PLMD { +namespace colvar { + class MultiRMSD : public Colvar { - + PLMD::MultiDomainRMSD* rmsd; - bool squared; + bool squared; MultiValue myvals; ReferenceValuePack mypack; @@ -52,11 +52,11 @@ using namespace std; //+PLUMEDOC DCOLVAR MULTI-RMSD /* -Calculate the RMSD distance moved by a number of separated domains from their positions in a reference structure. +Calculate the RMSD distance moved by a number of separated domains from their positions in a reference structure. When you have large proteins the calculation of the root mean squared deviation between all the atoms in a reference -structure and the instantaneous configuration becomes prohibitively expensive. You may thus instead want to calculate +structure and the instantaneous configuration becomes prohibitively expensive. You may thus instead want to calculate the RMSD between the atoms in a set of domains of your protein and your reference structure. That is to say: \f[ @@ -64,7 +64,7 @@ d(X,X_r) = \sqrt{ \sum_{i} w_i\vert X_i - X_i' \vert^2 } \f] where here the sum is over the domains of the protein, \f$X_i\f$ represents the positions of the atoms in domain \f$i\f$ -in the instantaneous configuration and \f$X_i'\f$ is the positions of the atoms in domain \f$i\f$ in the reference +in the instantaneous configuration and \f$X_i'\f$ is the positions of the atoms in domain \f$i\f$ in the reference configuration. \f$w_i\f$ is an optional weight. The distances for each of the domains in the above sum can be calculated using the \ref DRMSD or \ref RMSD measures or @@ -109,7 +109,7 @@ positions. Here distances are calculated using the \ref DRMSD measure. \verbatim MULTI-RMSD REFERENCE=file.pdb TYPE=MULTI-DRMSD -\endverbatim +\endverbatim in this case it is possible to use the following DRMSD options in the pdb file using the REMARK syntax: \verbatim @@ -117,7 +117,7 @@ NOPBC to calculate distances without PBC LOWER_CUTOFF=# only pairs of atoms further than LOWER_CUTOFF are considered in the calculation UPPER_CUTOFF=# only pairs of atoms further than UPPER_CUTOFF are considered in the calculation \endverbatim -as shown in the following example +as shown in the following example \verbatim REMARK NOPBC @@ -141,14 +141,14 @@ ATOM 21 HB2 ALA 2 2.556 -1.051 -0.295 1.00 1.00 DIA H ATOM 22 HB3 ALA 2 2.070 -2.314 -1.490 1.00 1.00 DIA H END \endverbatim - + */ //+ENDPLUMEDOC PLUMED_REGISTER_ACTION(MultiRMSD,"MULTI-RMSD") -void MultiRMSD::registerKeywords(Keywords& keys){ +void MultiRMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV."); keys.add("compulsory","TYPE","MULTI-SIMPLE","the manner in which RMSD alignment is performed. Should be MULTI-OPTIMAL, MULTI-OPTIMAL-FAST, MULTI-SIMPLE or MULTI-DRMSD."); @@ -157,11 +157,11 @@ void MultiRMSD::registerKeywords(Keywords& keys){ } MultiRMSD::MultiRMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals) + PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals) { string reference; parse("REFERENCE",reference); - string type; + string type; type.assign("SIMPLE"); parse("TYPE",type); parseFlag("SQUARED",squared); @@ -174,16 +174,16 @@ PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals) // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + reference ); + error("missing input file " + reference ); rmsd = metricRegister().create(type,pdb); - + std::vector atoms; rmsd->getAtomRequests( atoms ); requestAtoms( atoms ); myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() ); - for(unsigned i=0;icalculate( getPositions(), getPbc(), mypack, squared ); - setValue(r); - for(unsigned i=0;i nga; @@ -81,49 +81,49 @@ class NOE : public Colvar { PLUMED_REGISTER_ACTION(NOE,"NOE") -void NOE::registerKeywords( Keywords& keys ){ +void NOE::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); useCustomisableComponents(keys); keys.add("numbered","GROUPA","the atoms involved in each of the contacts you wish to calculate. " - "Keywords like GROUPA1, GROUPA2, GROUPA3,... should be listed and one contact will be " - "calculated for each ATOM keyword you specify."); + "Keywords like GROUPA1, GROUPA2, GROUPA3,... should be listed and one contact will be " + "calculated for each ATOM keyword you specify."); keys.add("numbered","GROUPB","the atoms involved in each of the contacts you wish to calculate. " - "Keywords like GROUPB1, GROUPB2, GROUPB3,... should be listed and one contact will be " - "calculated for each ATOM keyword you specify."); + "Keywords like GROUPB1, GROUPB2, GROUPB3,... should be listed and one contact will be " + "calculated for each ATOM keyword you specify."); keys.reset_style("GROUPA","atoms"); keys.reset_style("GROUPB","atoms"); - keys.addFlag("ADDEXP",false,"Set to TRUE if you want to have fixed components with the experimental reference values."); + keys.addFlag("ADDEXP",false,"Set to TRUE if you want to have fixed components with the experimental reference values."); keys.add("numbered","NOEDIST","Add an experimental value for each NOE."); keys.addOutputComponent("noe","default","the # NOE"); keys.addOutputComponent("exp","ADDEXP","the # NOE experimental distance"); } NOE::NOE(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true) + PLUMED_COLVAR_INIT(ao), + pbc(true) { bool nopbc=!pbc; parseFlag("NOPBC",nopbc); - pbc=!nopbc; + pbc=!nopbc; // Read in the atoms vector t, ga_lista, gb_lista; - for(int i=1;;++i ){ - parseAtomList("GROUPA", i, t ); - if( t.empty() ) break; - for(unsigned j=0;j ngb; - for(int i=1;;++i ){ - parseAtomList("GROUPB", i, t ); - if( t.empty() ) break; - for(unsigned j=0;j noedist; if(addexp) { - noedist.resize( nga.size() ); + noedist.resize( nga.size() ); unsigned ntarget=0; - for(unsigned i=0;i(nga[i]); Value* val=getPntrToComponent(i); - // cycle over equivalent atoms - for(unsigned j=0;jgetClosePair(index+j).first; const unsigned i1=nl->getClosePair(index+j).second; diff --git a/src/colvar/PCARMSD.cpp b/src/colvar/PCARMSD.cpp index 3e1688e90f..f5d1cf6f2c 100644 --- a/src/colvar/PCARMSD.cpp +++ b/src/colvar/PCARMSD.cpp @@ -29,13 +29,13 @@ using namespace std; -namespace PLMD{ -namespace colvar{ - +namespace PLMD { +namespace colvar { + class PCARMSD : public Colvar { - + PLMD::RMSD* rmsd; - bool squared; + bool squared; std::vector< std::vector > eigenvectors; std::vector pdbv; std::vector pca_names; @@ -49,7 +49,7 @@ class PCARMSD : public Colvar { using namespace std; -//+PLUMEDOC DCOLVAR PCARMSD +//+PLUMEDOC DCOLVAR PCARMSD /* Calculate the PCA components ( see \cite Sutto:2010 and \cite spiwok ) for a number of provided eigenvectors and an average structure. Performs optimal alignment at every step and reports the rmsd so you know if you are far or close from the average structure. It takes the average structure and eigenvectors in form of a pdb. @@ -58,17 +58,17 @@ Note that beta and occupancy values in the pdb are neglected and all the weights \par Examples \verbatim -PCARMSD AVERAGE=file.pdb EIGENVECTORS=eigenvectors.pdb +PCARMSD AVERAGE=file.pdb EIGENVECTORS=eigenvectors.pdb \endverbatim -The input is taken so to be compatible with the output you get from g_covar utility of gromacs (suitably adapted to have a pdb input format). +The input is taken so to be compatible with the output you get from g_covar utility of gromacs (suitably adapted to have a pdb input format). */ //+ENDPLUMEDOC PLUMED_REGISTER_ACTION(PCARMSD,"PCARMSD") -void PCARMSD::registerKeywords(Keywords& keys){ +void PCARMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","AVERAGE","a file in pdb format containing the reference structure and the atoms involved in the CV."); keys.add("compulsory","EIGENVECTORS","a file in pdb format containing the reference structure and the atoms involved in the CV."); @@ -79,35 +79,35 @@ void PCARMSD::registerKeywords(Keywords& keys){ } PCARMSD::PCARMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao),squared(true) + PLUMED_COLVAR_INIT(ao),squared(true) { string f_average; parse("AVERAGE",f_average); - string type; + string type; type.assign("OPTIMAL"); string f_eigenvectors; parse("EIGENVECTORS",f_eigenvectors); bool sq; parseFlag("SQUARED-ROOT",sq); - if (sq){ squared=false; } + if (sq) { squared=false; } checkRead(); PDB pdb; // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(f_average,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + f_average ); + error("missing input file " + f_average ); rmsd = new RMSD(); bool remove_com=true; bool normalize_weights=true; // here align and displace are a simple vector of ones - std::vector align; align=pdb.getOccupancy();for(unsigned i=0;i displace; displace=pdb.getBeta();for(unsigned i=0;i align; align=pdb.getOccupancy(); for(unsigned i=0; i displace; displace=pdb.getBeta(); for(unsigned i=0; iset(align,displace,pdb.getPositions(),type,remove_com,normalize_weights); requestAtoms( pdb.getAtomNumbers() ); - addComponentWithDerivatives("residual"); componentIsNotPeriodic("residual"); + addComponentWithDerivatives("residual"); componentIsNotPeriodic("residual"); log.printf(" average from file %s\n",f_average.c_str()); log.printf(" which contains %d atoms\n",getNumberOfAtoms()); @@ -116,7 +116,7 @@ PLUMED_COLVAR_INIT(ao),squared(true) log<<" Bibliography "< aaa; @@ -126,94 +126,94 @@ PLUMED_COLVAR_INIT(ao),squared(true) { log<<" Opening the eigenvectors file "< > drotdpos(3,3); - std::vector alignedpos; - std::vector centeredpos; - std::vector centeredref; - std::vector ddistdpos; - double r=rmsd->calc_PCAelements( getPositions(), ddistdpos, rotation , drotdpos , alignedpos ,centeredpos, centeredref ,squared); - invrotation=rotation.transpose(); - - Value* verr=getPntrToComponent("residual"); - verr->set(r); - for(unsigned iat=0;iat der; - der.resize(getNumberOfAtoms()); - - - for(unsigned i=0;iset(val); - // here the loop is reversed to better suit the structure of the derivative of the rotation matrix - double tmp1; - for(unsigned a=0;a<3;a++){ - for(unsigned b=0;b<3;b++){ - tmp1=0.; - for(unsigned n=0;n > drotdpos(3,3); + std::vector alignedpos; + std::vector centeredpos; + std::vector centeredref; + std::vector ddistdpos; + double r=rmsd->calc_PCAelements( getPositions(), ddistdpos, rotation, drotdpos, alignedpos,centeredpos, centeredref,squared); + invrotation=rotation.transpose(); + + Value* verr=getPntrToComponent("residual"); + verr->set(r); + for(unsigned iat=0; iat der; + der.resize(getNumberOfAtoms()); + + + for(unsigned i=0; iset(val); + // here the loop is reversed to better suit the structure of the derivative of the rotation matrix + double tmp1; + for(unsigned a=0; a<3; a++) { + for(unsigned b=0; b<3; b++) { + tmp1=0.; + for(unsigned n=0; n atom; parseAtomList("SPINLABEL",atom); @@ -118,24 +118,24 @@ pbc(true) // Read in the atoms vector t, ga_lista, gb_lista; - for(int i=1;;++i ){ - parseAtomList("GROUPA", i, t ); - if( t.empty() ) break; - for(unsigned j=0;j exppre; if(addexp) { - exppre.resize( nga.size() ); + exppre.resize( nga.size() ); unsigned ntarget=0; - for(unsigned i=0;iset(exppre[i]); } } @@ -213,22 +213,22 @@ pbc(true) checkRead(); } -PRE::~PRE(){ +PRE::~PRE() { delete nl; -} +} void PRE::calculate() { // cycle over the number of PRE -#pragma omp parallel for num_threads(OpenMP::getNumThreads()) - for(unsigned i=0;i deriv; + #pragma omp parallel for num_threads(OpenMP::getNumThreads()) + for(unsigned i=0; i deriv; Tensor dervir; double pre=0; unsigned index=0; - for(unsigned k=0; kgetClosePair(index+j).first; @@ -257,7 +257,7 @@ void PRE::calculate() val->set(ratio); setBoxDerivatives(val, fact*dervir); - for(unsigned j=0;jgetClosePair(index+j).first; const unsigned i1=nl->getClosePair(index+j).second; setAtomsDerivatives(val, i0, fact*deriv[j]); diff --git a/src/colvar/PathMSD.cpp b/src/colvar/PathMSD.cpp index 7d1cca0918..cdfd96ee1d 100644 --- a/src/colvar/PathMSD.cpp +++ b/src/colvar/PathMSD.cpp @@ -24,26 +24,26 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR PATHMSD /* -This Colvar calculates path collective variables. +This Colvar calculates path collective variables. -This is the Path Collective Variables implementation +This is the Path Collective Variables implementation ( see \cite brand07 ). -This variable computes the progress along a given set of frames that is provided -in input ("sss" component) and the distance from them ("zzz" component). +This variable computes the progress along a given set of frames that is provided +in input ("sss" component) and the distance from them ("zzz" component). (see below). \par Examples -Here below is a case where you have defined three frames and you want to +Here below is a case where you have defined three frames and you want to calculate the progress along the path and the distance from it in p1 \verbatim -p1: PATHMSD REFERENCE=file.pdb LAMBDA=500.0 NEIGH_STRIDE=4 NEIGH_SIZE=8 +p1: PATHMSD REFERENCE=file.pdb LAMBDA=500.0 NEIGH_STRIDE=4 NEIGH_SIZE=8 PRINT ARG=p1.sss,p1.zzz STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim @@ -60,7 +60,7 @@ is shared, as well as most input options. */ //+ENDPLUMEDOC - + class PathMSD : public PathMSDBase { public: explicit PathMSD(const ActionOptions&); @@ -69,7 +69,7 @@ class PathMSD : public PathMSDBase { PLUMED_REGISTER_ACTION(PathMSD,"PATHMSD") -void PathMSD::registerKeywords(Keywords& keys){ +void PathMSD::registerKeywords(Keywords& keys) { PathMSDBase::registerKeywords(keys); componentsAreNotOptional(keys); keys.addOutputComponent("sss","default","the position on the path"); @@ -77,7 +77,7 @@ void PathMSD::registerKeywords(Keywords& keys){ } PathMSD::PathMSD(const ActionOptions&ao): -Action(ao),PathMSDBase(ao) + Action(ao),PathMSDBase(ao) { checkRead(); @@ -87,12 +87,12 @@ Action(ao),PathMSDBase(ao) // no need to read anything addComponentWithDerivatives("sss"); componentIsNotPeriodic("sss"); addComponentWithDerivatives("zzz"); componentIsNotPeriodic("zzz"); - requestAtoms(pdbv[0].getAtomNumbers()); + requestAtoms(pdbv[0].getAtomNumbers()); double i=1.; - for(unsigned it=0 ;it v; v.push_back(i); - indexvec.push_back(v);i+=1.; + for(unsigned it=0 ; it v; v.push_back(i); + indexvec.push_back(v); i+=1.; } } diff --git a/src/colvar/PathMSDBase.cpp b/src/colvar/PathMSDBase.cpp index 6e283b27b8..cda02bdb98 100644 --- a/src/colvar/PathMSDBase.cpp +++ b/src/colvar/PathMSDBase.cpp @@ -31,10 +31,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -void PathMSDBase::registerKeywords(Keywords& keys){ +void PathMSDBase::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.remove("NOPBC"); keys.add("compulsory","LAMBDA","the lambda parameter is needed for smoothing, is in the units of plumed"); @@ -44,10 +44,10 @@ void PathMSDBase::registerKeywords(Keywords& keys){ } PathMSDBase::PathMSDBase(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -neigh_size(-1), -neigh_stride(-1), -nframes(0) + PLUMED_COLVAR_INIT(ao), + neigh_size(-1), + neigh_stride(-1), + nframes(0) { parse("LAMBDA",lambda); parse("NEIGH_SIZE",neigh_size); @@ -61,46 +61,46 @@ nframes(0) { log<<"Opening reference file "<0 || neigh_size>0){ - if(neigh_size>int(nframes)){ - log.printf(" List size required ( %d ) is too large: resizing to the maximum number of frames required: %u \n",neigh_size,nframes); - neigh_size=nframes; - } - log.printf(" Neighbor list enabled: \n"); - log.printf(" size : %d elements\n",neigh_size); - log.printf(" stride : %d timesteps \n",neigh_stride); - }else{ - log.printf(" Neighbor list NOT enabled \n"); + } + if(neigh_stride>0 || neigh_size>0) { + if(neigh_size>int(nframes)) { + log.printf(" List size required ( %d ) is too large: resizing to the maximum number of frames required: %u \n",neigh_size,nframes); + neigh_size=nframes; + } + log.printf(" Neighbor list enabled: \n"); + log.printf(" size : %d elements\n",neigh_size); + log.printf(" stride : %d timesteps \n",neigh_stride); + } else { + log.printf(" Neighbor list NOT enabled \n"); } } -void PathMSDBase::calculate(){ +void PathMSDBase::calculate() { if(neigh_size>0 && getExchangeStep()) error("Neighbor lists for this collective variable are not compatible with replica exchange, sorry for that!"); @@ -108,12 +108,12 @@ void PathMSDBase::calculate(){ // resize the list to full - if(imgVec.empty()){ // this is the signal that means: recalculate all - imgVec.resize(nframes); - for(unsigned i=0;i tmp_derivs2(imgVec.size()*nat); // if imgVec.size() is less than nframes, it means that only some msd will be calculated - for(unsigned i=rank;i val_s_path; - if(labels.size()>0){ - for(unsigned i=0;i0) { + for(unsigned i=0; i s_path(val_s_path.size());for(unsigned i=0;i s_path(val_s_path.size()); for(unsigned i=0; iset(s_path[i]) ;} + for(unsigned i=0; iset(s_path[i]) ;} val_z_path->set(-(1./lambda)*std::log(partition)); - for(unsigned j=0;j0){ - //if( int(getStep())%int(neigh_stride/getTimeStep())==0 ){ - // enforce consistency: the stride is in time steps - if( int(getStep())%int(neigh_stride)==0 ){ - - // next round do it all:empty the vector - imgVec.clear(); - } - // time to analyze the results: - if(imgVec.size()==nframes){ - //sort by msd - sort(imgVec.begin(), imgVec.end(), imgOrderByDist()); - //resize - imgVec.resize(neigh_size); - } + if (neigh_size>0) { + //if( int(getStep())%int(neigh_stride/getTimeStep())==0 ){ + // enforce consistency: the stride is in time steps + if( int(getStep())%int(neigh_stride)==0 ) { + + // next round do it all:empty the vector + imgVec.clear(); + } + // time to analyze the results: + if(imgVec.size()==nframes) { + //sort by msd + sort(imgVec.begin(), imgVec.end(), imgOrderByDist()); + //resize + imgVec.resize(neigh_size); + } } //log.printf("CALCULATION DONE! \n"); } diff --git a/src/colvar/PathMSDBase.h b/src/colvar/PathMSDBase.h index 4451bffc75..dae1603cb5 100644 --- a/src/colvar/PathMSDBase.h +++ b/src/colvar/PathMSDBase.h @@ -29,34 +29,34 @@ #include "tools/RMSD.h" #include "tools/Tools.h" -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { class PathMSDBase : public Colvar { -/// this class is a general container for path stuff +/// this class is a general container for path stuff class ImagePath { - public: - // cardinal indexing: needed to map over msd - unsigned index; - // spiwok indexing - std::vector property; - // distance - double distance; - // similarity (exp - lambda distance) or other - double similarity; - // derivatives of the distance - std::vector distder; - // here one can add a pointer to a value (hypothetically providing a distance from a point) + public: + // cardinal indexing: needed to map over msd + unsigned index; + // spiwok indexing + std::vector property; + // distance + double distance; + // similarity (exp - lambda distance) or other + double similarity; + // derivatives of the distance + std::vector distder; + // here one can add a pointer to a value (hypothetically providing a distance from a point) }; struct imgOrderByDist { - bool operator ()(ImagePath const& a, ImagePath const& b) { - return (a).distance < (b).distance; - } + bool operator ()(ImagePath const& a, ImagePath const& b) { + return (a).distance < (b).distance; + } }; struct imgOrderBySimilarity { - bool operator ()(ImagePath const& a, ImagePath const& b) { - return (a).similarity > (b).similarity; - } + bool operator ()(ImagePath const& a, ImagePath const& b) { + return (a).similarity > (b).similarity; + } }; double lambda; @@ -66,7 +66,7 @@ class PathMSDBase : public Colvar { std::string reference; std::vector derivs_s; std::vector derivs_z; - std::vector imgVec; // this can be used for doing neighlist + std::vector imgVec; // this can be used for doing neighlist protected: std::vector pdbv; std::vector labels; diff --git a/src/colvar/Position.cpp b/src/colvar/Position.cpp index ab34c3ae11..a381e039e0 100644 --- a/src/colvar/Position.cpp +++ b/src/colvar/Position.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR POSITION /* @@ -37,7 +37,7 @@ Calculate the components of the position of an atom. Notice that single components will not have the proper periodicity! If you need the values to be consistent through PBC you should use SCALED_COMPONENTS, -which defines values that by construction are in the -0.5,0.5 domain. This is +which defines values that by construction are in the -0.5,0.5 domain. This is similar to the equivalent flag for \ref DISTANCE. Also notice that by default the minimal image distance from the origin is considered (can be changed with NOPBC). @@ -45,7 +45,7 @@ origin is considered (can be changed with NOPBC). \attention This variable should be used with extreme care since it allows to easily go into troubles. See comments below. -This variable can be safely used only if +This variable can be safely used only if Hamiltonian is not invariant for translation (i.e. there are other absolute positions which are biased, e.g. by position restraints) and cell size and shapes are fixed through the simulation. @@ -65,7 +65,7 @@ PRINT ARG=p.x,p.y,p.z */ //+ENDPLUMEDOC - + class Position : public Colvar { bool scaled_components; bool pbc; @@ -79,7 +79,7 @@ class Position : public Colvar { PLUMED_REGISTER_ACTION(Position,"POSITION") -void Position::registerKeywords( Keywords& keys ){ +void Position::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); keys.add("atoms","ATOM","the atom number"); @@ -93,9 +93,9 @@ void Position::registerKeywords( Keywords& keys ){ } Position::Position(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -scaled_components(false), -pbc(true) + PLUMED_COLVAR_INIT(ao), + scaled_components(false), + pbc(true) { vector atoms; parseAtomList("ATOM",atoms); @@ -111,7 +111,7 @@ pbc(true) if(pbc) log.printf(" using periodic boundary conditions\n"); else log.printf(" without periodic boundary conditions\n"); - if(scaled_components){ + if(scaled_components) { addComponentWithDerivatives("a"); componentIsPeriodic("a","-0.5","+0.5"); addComponentWithDerivatives("b"); componentIsPeriodic("b","-0.5","+0.5"); addComponentWithDerivatives("c"); componentIsPeriodic("c","-0.5","+0.5"); @@ -127,16 +127,16 @@ pbc(true) // calculator -void Position::calculate(){ +void Position::calculate() { Vector distance; - if(pbc){ + if(pbc) { distance=pbcDistance(Vector(0.0,0.0,0.0),getPosition(0)); } else { distance=delta(Vector(0.0,0.0,0.0),getPosition(0)); } - if(scaled_components){ + if(scaled_components) { Value* valuea=getPntrToComponent("a"); Value* valueb=getPntrToComponent("b"); Value* valuec=getPntrToComponent("c"); diff --git a/src/colvar/PropertyMap.cpp b/src/colvar/PropertyMap.cpp index 89658cfad4..a8a21fef20 100644 --- a/src/colvar/PropertyMap.cpp +++ b/src/colvar/PropertyMap.cpp @@ -24,10 +24,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR PROPERTYMAP +//+PLUMEDOC COLVAR PROPERTYMAP /* Calculate generic property maps. @@ -42,7 +42,7 @@ Y=\frac{\sum_i Y_i*\exp(-\lambda D_i(x))}{\sum_i \exp(-\lambda D_i(x))} \\ zzz=-\frac{1}{\lambda}\log(\sum_i \exp(-\lambda D_i(x))) \f} -where the parameters \f$X_i\f$ and \f$Y_i\f$ are provided in the input pdb (allv.pdb in this case) and +where the parameters \f$X_i\f$ and \f$Y_i\f$ are provided in the input pdb (allv.pdb in this case) and \f$D_i(x)\f$ is the MSD after optimal alignment calculated on the pdb frames you input (see Kearsley). \par Examples @@ -55,17 +55,17 @@ note that NEIGH_STRIDE=4 NEIGH_SIZE=8 control the neighborlist parameter (option recommended for performance) and states that the neighbor list will be calculated every 4 timesteps and consider only the closest 8 member to the actual md snapshots. -In this case the input line instructs plumed to look for two properties X and Y with attached values in the REMARK +In this case the input line instructs plumed to look for two properties X and Y with attached values in the REMARK line of the reference pdb (Note: No spaces from X and = and 1 !!!!). e.g. \verbatim -REMARK X=1 Y=2 +REMARK X=1 Y=2 ATOM 1 CL ALA 1 -3.171 0.295 2.045 1.00 1.00 ATOM 5 CLP ALA 1 -1.819 -0.143 1.679 1.00 1.00 ....... END -REMARK X=2 Y=3 +REMARK X=2 Y=3 ATOM 1 CL ALA 1 -3.175 0.365 2.024 1.00 1.00 ATOM 5 CLP ALA 1 -1.814 -0.106 1.685 1.00 1.00 .... @@ -78,7 +78,7 @@ is shared, as well as most input options. */ //+ENDPLUMEDOC - + class PropertyMap : public PathMSDBase { public: explicit PropertyMap(const ActionOptions&); @@ -87,7 +87,7 @@ class PropertyMap : public PathMSDBase { PLUMED_REGISTER_ACTION(PropertyMap,"PROPERTYMAP") -void PropertyMap::registerKeywords(Keywords& keys){ +void PropertyMap::registerKeywords(Keywords& keys) { PathMSDBase::registerKeywords(keys); keys.add("compulsory","PROPERTY","the property to be used in the indexing: this goes in the REMARK field of the reference"); ActionWithValue::useCustomisableComponents(keys); @@ -95,45 +95,45 @@ void PropertyMap::registerKeywords(Keywords& keys){ } PropertyMap::PropertyMap(const ActionOptions&ao): -Action(ao), -PathMSDBase(ao) + Action(ao), + PathMSDBase(ao) { - // this is the only additional keyword needed + // this is the only additional keyword needed parseVector("PROPERTY",labels); checkRead(); log<<" Bibliography " - < myv(pdbv[i].getRemark()); - // now look for X=1.34555 Y=5.6677 - vector labelvals; - for(unsigned j=0;j myv(pdbv[i].getRemark()); + // now look for X=1.34555 Y=5.6677 + vector labelvals; + for(unsigned j=0; j atoms; parseAtomList("ATOMS",atoms); if(atoms.size()!=5 && atoms.size()!=6) error("only for 5 or 6-membered rings"); checkRead(); - - if(atoms.size()==5){ + + if(atoms.size()==5) { log.printf(" between atoms %d %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial(),atoms[4].serial()); - } else if(atoms.size()==6){ + } else if(atoms.size()==6) { log.printf(" between atoms %d %d %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial(),atoms[4].serial(),atoms[5].serial()); } else error("ATOMS should specify 5 atoms"); - - if(atoms.size()==5){ + + if(atoms.size()==5) { addComponentWithDerivatives("phs"); componentIsPeriodic("phs","-pi","pi"); addComponentWithDerivatives("amp"); componentIsNotPeriodic("amp"); addComponentWithDerivatives("Zx"); componentIsNotPeriodic("Zx"); addComponentWithDerivatives("Zy"); componentIsNotPeriodic("Zy"); - } else if(atoms.size()==6){ + } else if(atoms.size()==6) { addComponentWithDerivatives("qx"); componentIsNotPeriodic("qx"); addComponentWithDerivatives("qy"); componentIsNotPeriodic("qy"); addComponentWithDerivatives("qz"); componentIsNotPeriodic("qz"); @@ -134,27 +134,27 @@ PLUMED_COLVAR_INIT(ao) } // calculator -void Puckering::calculate(){ +void Puckering::calculate() { makeWhole(); if(getNumberOfAtoms()==5) calculate5m(); else calculate6m(); } -void Puckering::calculate5m(){ +void Puckering::calculate5m() { Vector d0,d1,d2,d3,d4,d5; - + d0=delta(getPosition(2),getPosition(1)); d1=delta(getPosition(3),getPosition(2)); d2=delta(getPosition(4),getPosition(3)); d3=delta(getPosition(4),getPosition(3)); d4=delta(getPosition(0),getPosition(4)); d5=delta(getPosition(1),getPosition(0)); - + Vector dd0,dd1,dd2,dd3,dd4,dd5; - + PLMD::Torsion t; - + double v1=t.compute(d0,d1,d2,dd0,dd1,dd2); double v3=t.compute(d3,d4,d5,dd3,dd4,dd5); @@ -162,31 +162,31 @@ void Puckering::calculate5m(){ double Zy=(v1-v3)/(2.0*sin(4.0*pi/5.0)); double phase=atan2(Zy,Zx); double amplitude=sqrt(Zx*Zx+Zy*Zy); - + Vector dZx_dR[5]; Vector dZy_dR[5]; - + dZx_dR[0]=(dd5-dd4); dZx_dR[1]=(dd0-dd5); dZx_dR[2]=(dd1-dd0); dZx_dR[3]=(dd2+dd3-dd1); dZx_dR[4]=(dd4-dd3-dd2); - + dZy_dR[0]=(dd4-dd5); dZy_dR[1]=(dd0+dd5); dZy_dR[2]=(dd1-dd0); dZy_dR[3]=(dd2-dd3-dd1); dZy_dR[4]=(dd3-dd4-dd2); - - for(unsigned j=0;j<5;j++) dZx_dR[j]*=(1.0/(2.0*cos(4.0*pi/5.0))); - for(unsigned j=0;j<5;j++) dZy_dR[j]*=(1.0/(2.0*sin(4.0*pi/5.0))); - + + for(unsigned j=0; j<5; j++) dZx_dR[j]*=(1.0/(2.0*cos(4.0*pi/5.0))); + for(unsigned j=0; j<5; j++) dZy_dR[j]*=(1.0/(2.0*sin(4.0*pi/5.0))); + Vector dphase_dR[5]; - for(unsigned j=0;j<5;j++) dphase_dR[j]=(1.0/(Zx*Zx+Zy*Zy))*(-Zy*dZx_dR[j] + Zx*dZy_dR[j]); - + for(unsigned j=0; j<5; j++) dphase_dR[j]=(1.0/(Zx*Zx+Zy*Zy))*(-Zy*dZx_dR[j] + Zx*dZy_dR[j]); + Vector damplitude_dR[5]; - for(unsigned j=0;j<5;j++) damplitude_dR[j]=(1.0/amplitude)*(Zx*dZx_dR[j] + Zy*dZy_dR[j]); - + for(unsigned j=0; j<5; j++) damplitude_dR[j]=(1.0/amplitude)*(Zx*dZx_dR[j] + Zy*dZy_dR[j]); + Value* vzx=getPntrToComponent("Zx"); vzx->set(Zx); setAtomsDerivatives (vzx,0, dZx_dR[0]); @@ -195,7 +195,7 @@ void Puckering::calculate5m(){ setAtomsDerivatives (vzx,3, dZx_dR[3]); setAtomsDerivatives (vzx,4, dZx_dR[4]); setBoxDerivativesNoPbc(vzx); - + Value* vzy=getPntrToComponent("Zy"); vzy->set(Zy); setAtomsDerivatives (vzy,0, dZy_dR[0]); @@ -214,7 +214,7 @@ void Puckering::calculate5m(){ setAtomsDerivatives (vph,3, dphase_dR[3]); setAtomsDerivatives (vph,4, dphase_dR[4]); setBoxDerivativesNoPbc(vph); - + Value* vam=getPntrToComponent("amp"); vam->set(amplitude); setAtomsDerivatives (vam,0, damplitude_dR[0]); @@ -224,22 +224,22 @@ void Puckering::calculate5m(){ setAtomsDerivatives (vam,4, damplitude_dR[4]); setBoxDerivativesNoPbc(vam); - + } -void Puckering::calculate6m(){ +void Puckering::calculate6m() { vector r(6); - for(unsigned i=0;i<6;i++) r[i]=getPosition(i); + for(unsigned i=0; i<6; i++) r[i]=getPosition(i); vector R(6); Vector center; - for(unsigned j=0;j<6;j++) center+=r[j]/6.0; - for(unsigned j=0;j<6;j++) R[j]=(r[j]-center); + for(unsigned j=0; j<6; j++) center+=r[j]/6.0; + for(unsigned j=0; j<6; j++) R[j]=(r[j]-center); Vector Rp,Rpp; - for(unsigned j=0;j<6;j++) Rp +=R[j]*sin(2.0/6.0*pi*j); - for(unsigned j=0;j<6;j++) Rpp+=R[j]*cos(2.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) Rp +=R[j]*sin(2.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) Rpp+=R[j]*cos(2.0/6.0*pi*j); Vector n=crossProduct(Rp,Rpp); Vector nhat=n/modulo(n); @@ -252,165 +252,165 @@ void Puckering::calculate6m(){ Tensor dnhat_dRpp=matmul(dnhat_dn,dn_dRpp); vector z(6); - for(unsigned j=0;j<6;j++) z[j]=dotProduct(R[j],nhat); + for(unsigned j=0; j<6; j++) z[j]=dotProduct(R[j],nhat); vector > dz_dR(6); - for(unsigned j=0;j<6;j++) dz_dR[j].resize(6); + for(unsigned j=0; j<6; j++) dz_dR[j].resize(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - if(i==j) dz_dR[i][j]+=nhat; - dz_dR[i][j]+=matmul(R[i],dnhat_dRp)*sin(2.0/6.0*pi*j); - dz_dR[i][j]+=matmul(R[i],dnhat_dRpp)*cos(2.0/6.0*pi*j); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + if(i==j) dz_dR[i][j]+=nhat; + dz_dR[i][j]+=matmul(R[i],dnhat_dRp)*sin(2.0/6.0*pi*j); + dz_dR[i][j]+=matmul(R[i],dnhat_dRpp)*cos(2.0/6.0*pi*j); + } double B=0.0; - for(unsigned j=0;j<6;j++) B+=z[j]*cos(4.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) B+=z[j]*cos(4.0/6.0*pi*j); vector dB_dR(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - dB_dR[i]+=dz_dR[j][i]*cos(4.0/6.0*pi*j); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + dB_dR[i]+=dz_dR[j][i]*cos(4.0/6.0*pi*j); + } Vector Bsum; - for(unsigned j=0;j<6;j++) Bsum+=dB_dR[j]; - for(unsigned j=0;j<6;j++) dB_dR[j]-=Bsum/6.0;; + for(unsigned j=0; j<6; j++) Bsum+=dB_dR[j]; + for(unsigned j=0; j<6; j++) dB_dR[j]-=Bsum/6.0;; double A=0.0; - for(unsigned j=0;j<6;j++) A+=z[j]*sin(4.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) A+=z[j]*sin(4.0/6.0*pi*j); vector dA_dR(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - dA_dR[i]+=dz_dR[j][i]*sin(4.0/6.0*pi*j); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + dA_dR[i]+=dz_dR[j][i]*sin(4.0/6.0*pi*j); + } Vector Asum; - for(unsigned j=0;j<6;j++) Asum+=dA_dR[j]; - for(unsigned j=0;j<6;j++) dA_dR[j]-=Asum/6.0;; + for(unsigned j=0; j<6; j++) Asum+=dA_dR[j]; + for(unsigned j=0; j<6; j++) dA_dR[j]-=Asum/6.0;; double C=0.0; - for(unsigned j=0;j<6;j++) C+=z[j]*Tools::fastpow(-1.0,(j)); + for(unsigned j=0; j<6; j++) C+=z[j]*Tools::fastpow(-1.0,(j)); vector dC_dR(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - dC_dR[i]+=dz_dR[j][i]*Tools::fastpow(-1.0,(j)); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + dC_dR[i]+=dz_dR[j][i]*Tools::fastpow(-1.0,(j)); + } Vector Csum; - for(unsigned j=0;j<6;j++) Csum+=dC_dR[j]; - for(unsigned j=0;j<6;j++) dC_dR[j]-=Csum/6.0;; + for(unsigned j=0; j<6; j++) Csum+=dC_dR[j]; + for(unsigned j=0; j<6; j++) dC_dR[j]-=Csum/6.0;; // qx - double qx = A/sqrt(3); + double qx = A/sqrt(3); // qx derivaties - vector dqx_dR(6); - for(unsigned j=0;j<6;j++){ - dqx_dR[j]=1/sqrt(3) * dA_dR[j]; - } + vector dqx_dR(6); + for(unsigned j=0; j<6; j++) { + dqx_dR[j]=1/sqrt(3) * dA_dR[j]; + } - Value* vqx=getPntrToComponent("qx"); - vqx->set(qx); - setAtomsDerivatives (vqx,0, dqx_dR[0] ); - setAtomsDerivatives (vqx,1, dqx_dR[1] ); - setAtomsDerivatives (vqx,2, dqx_dR[2] ); - setAtomsDerivatives (vqx,3, dqx_dR[3] ); - setAtomsDerivatives (vqx,4, dqx_dR[4] ); - setAtomsDerivatives (vqx,5, dqx_dR[5] ); - setBoxDerivativesNoPbc(vqx); + Value* vqx=getPntrToComponent("qx"); + vqx->set(qx); + setAtomsDerivatives (vqx,0, dqx_dR[0] ); + setAtomsDerivatives (vqx,1, dqx_dR[1] ); + setAtomsDerivatives (vqx,2, dqx_dR[2] ); + setAtomsDerivatives (vqx,3, dqx_dR[3] ); + setAtomsDerivatives (vqx,4, dqx_dR[4] ); + setAtomsDerivatives (vqx,5, dqx_dR[5] ); + setBoxDerivativesNoPbc(vqx); // qy - double qy = -B/sqrt(3); + double qy = -B/sqrt(3); // qy derivatives - vector dqy_dR(6); - for(unsigned j=0;j<6;j++){ - dqy_dR[j]=-1/sqrt(3) * dB_dR[j]; - } + vector dqy_dR(6); + for(unsigned j=0; j<6; j++) { + dqy_dR[j]=-1/sqrt(3) * dB_dR[j]; + } - Value* vqy=getPntrToComponent("qy"); - vqy->set(qy); - setAtomsDerivatives (vqy,0, dqy_dR[0] ); - setAtomsDerivatives (vqy,1, dqy_dR[1] ); - setAtomsDerivatives (vqy,2, dqy_dR[2] ); - setAtomsDerivatives (vqy,3, dqy_dR[3] ); - setAtomsDerivatives (vqy,4, dqy_dR[4] ); - setAtomsDerivatives (vqy,5, dqy_dR[5] ); - setBoxDerivativesNoPbc(vqy); + Value* vqy=getPntrToComponent("qy"); + vqy->set(qy); + setAtomsDerivatives (vqy,0, dqy_dR[0] ); + setAtomsDerivatives (vqy,1, dqy_dR[1] ); + setAtomsDerivatives (vqy,2, dqy_dR[2] ); + setAtomsDerivatives (vqy,3, dqy_dR[3] ); + setAtomsDerivatives (vqy,4, dqy_dR[4] ); + setAtomsDerivatives (vqy,5, dqy_dR[5] ); + setBoxDerivativesNoPbc(vqy); -// qz - double qz = C/sqrt(6); +// qz + double qz = C/sqrt(6); // qz derivatives - vector dqz_dR(6); - for(unsigned j=0;j<6;j++){ - dqz_dR[j]=1/sqrt(6) * dC_dR[j]; - } + vector dqz_dR(6); + for(unsigned j=0; j<6; j++) { + dqz_dR[j]=1/sqrt(6) * dC_dR[j]; + } - Value* vqz=getPntrToComponent("qz"); - vqz->set(qz); - setAtomsDerivatives (vqz,0, dqz_dR[0] ); - setAtomsDerivatives (vqz,1, dqz_dR[1] ); - setAtomsDerivatives (vqz,2, dqz_dR[2] ); - setAtomsDerivatives (vqz,3, dqz_dR[3] ); - setAtomsDerivatives (vqz,4, dqz_dR[4] ); - setAtomsDerivatives (vqz,5, dqz_dR[5] ); - setBoxDerivativesNoPbc(vqz); + Value* vqz=getPntrToComponent("qz"); + vqz->set(qz); + setAtomsDerivatives (vqz,0, dqz_dR[0] ); + setAtomsDerivatives (vqz,1, dqz_dR[1] ); + setAtomsDerivatives (vqz,2, dqz_dR[2] ); + setAtomsDerivatives (vqz,3, dqz_dR[3] ); + setAtomsDerivatives (vqz,4, dqz_dR[4] ); + setAtomsDerivatives (vqz,5, dqz_dR[5] ); + setBoxDerivativesNoPbc(vqz); // PHASE - double phi=atan2(-A,B); + double phi=atan2(-A,B); // PHASE DERIVATIVES - vector dphi_dR(6); - for(unsigned j=0;j<6;j++){ - dphi_dR[j]=1.0/(A*A+B*B) * (-B*dA_dR[j] + A*dB_dR[j]); - } + vector dphi_dR(6); + for(unsigned j=0; j<6; j++) { + dphi_dR[j]=1.0/(A*A+B*B) * (-B*dA_dR[j] + A*dB_dR[j]); + } - Value* vphi=getPntrToComponent("phi"); - vphi->set(phi); - setAtomsDerivatives (vphi,0, dphi_dR[0] ); - setAtomsDerivatives (vphi,1, dphi_dR[1] ); - setAtomsDerivatives (vphi,2, dphi_dR[2] ); - setAtomsDerivatives (vphi,3, dphi_dR[3] ); - setAtomsDerivatives (vphi,4, dphi_dR[4] ); - setAtomsDerivatives (vphi,5, dphi_dR[5] ); - setBoxDerivativesNoPbc(vphi); + Value* vphi=getPntrToComponent("phi"); + vphi->set(phi); + setAtomsDerivatives (vphi,0, dphi_dR[0] ); + setAtomsDerivatives (vphi,1, dphi_dR[1] ); + setAtomsDerivatives (vphi,2, dphi_dR[2] ); + setAtomsDerivatives (vphi,3, dphi_dR[3] ); + setAtomsDerivatives (vphi,4, dphi_dR[4] ); + setAtomsDerivatives (vphi,5, dphi_dR[5] ); + setBoxDerivativesNoPbc(vphi); // AMPLITUDE - double amplitude=sqrt((2*(A*A+B*B)+C*C)/6); + double amplitude=sqrt((2*(A*A+B*B)+C*C)/6); // AMPLITUDE DERIVATIES - vector damplitude_dR(6); - for (unsigned j=0;j<6;j++){ - damplitude_dR[j]=0.5*sqrt(2.0/6.0)/(sqrt(A*A+B*B+0.5*C*C)) * (2*A*dA_dR[j] + 2*B*dB_dR[j] + C*dC_dR[j]); - } + vector damplitude_dR(6); + for (unsigned j=0; j<6; j++) { + damplitude_dR[j]=0.5*sqrt(2.0/6.0)/(sqrt(A*A+B*B+0.5*C*C)) * (2*A*dA_dR[j] + 2*B*dB_dR[j] + C*dC_dR[j]); + } - Value* vamplitude=getPntrToComponent("amplitude"); - vamplitude->set(amplitude); - setAtomsDerivatives (vamplitude,0, damplitude_dR[0] ); - setAtomsDerivatives (vamplitude,1, damplitude_dR[1] ); - setAtomsDerivatives (vamplitude,2, damplitude_dR[2] ); - setAtomsDerivatives (vamplitude,3, damplitude_dR[3] ); - setAtomsDerivatives (vamplitude,4, damplitude_dR[4] ); - setAtomsDerivatives (vamplitude,5, damplitude_dR[5] ); - setBoxDerivativesNoPbc(vamplitude); + Value* vamplitude=getPntrToComponent("amplitude"); + vamplitude->set(amplitude); + setAtomsDerivatives (vamplitude,0, damplitude_dR[0] ); + setAtomsDerivatives (vamplitude,1, damplitude_dR[1] ); + setAtomsDerivatives (vamplitude,2, damplitude_dR[2] ); + setAtomsDerivatives (vamplitude,3, damplitude_dR[3] ); + setAtomsDerivatives (vamplitude,4, damplitude_dR[4] ); + setAtomsDerivatives (vamplitude,5, damplitude_dR[5] ); + setBoxDerivativesNoPbc(vamplitude); // THETA - double theta=acos( C / sqrt(2.*(A*A+B*B) +C*C ) ); + double theta=acos( C / sqrt(2.*(A*A+B*B) +C*C ) ); // THETA DERIVATIVES - vector dtheta_dR(6); - for(unsigned j=0;j<6;j++){ - dtheta_dR[j]=1.0/(3.0*sqrt(2)*amplitude*amplitude) * (C/(sqrt(A*A+B*B)) * (A*dA_dR[j] + B*dB_dR[j]) - sqrt(A*A+B*B)*dC_dR[j]); - } - Value* vtheta=getPntrToComponent("theta"); - vtheta->set(theta); - setAtomsDerivatives (vtheta,0, dtheta_dR[0] ); - setAtomsDerivatives (vtheta,1, dtheta_dR[1] ); - setAtomsDerivatives (vtheta,2, dtheta_dR[2] ); - setAtomsDerivatives (vtheta,3, dtheta_dR[3] ); - setAtomsDerivatives (vtheta,4, dtheta_dR[4] ); - setAtomsDerivatives (vtheta,5, dtheta_dR[5] ); - setBoxDerivativesNoPbc(vtheta); + vector dtheta_dR(6); + for(unsigned j=0; j<6; j++) { + dtheta_dR[j]=1.0/(3.0*sqrt(2)*amplitude*amplitude) * (C/(sqrt(A*A+B*B)) * (A*dA_dR[j] + B*dB_dR[j]) - sqrt(A*A+B*B)*dC_dR[j]); + } + Value* vtheta=getPntrToComponent("theta"); + vtheta->set(theta); + setAtomsDerivatives (vtheta,0, dtheta_dR[0] ); + setAtomsDerivatives (vtheta,1, dtheta_dR[1] ); + setAtomsDerivatives (vtheta,2, dtheta_dR[2] ); + setAtomsDerivatives (vtheta,3, dtheta_dR[3] ); + setAtomsDerivatives (vtheta,4, dtheta_dR[4] ); + setAtomsDerivatives (vtheta,5, dtheta_dR[5] ); + setBoxDerivativesNoPbc(vtheta); } diff --git a/src/colvar/RDC.cpp b/src/colvar/RDC.cpp index 124101b558..18db380141 100644 --- a/src/colvar/RDC.cpp +++ b/src/colvar/RDC.cpp @@ -33,16 +33,16 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR RDC +//+PLUMEDOC COLVAR RDC /* -Calculates the (Residual) Dipolar Coupling between two atoms. +Calculates the (Residual) Dipolar Coupling between two atoms. -The RDC between two atomic nuclei depends on the \f$\theta\f$ angle between -the inter-nuclear vector and the external magnetic field. In isotropic media RDCs average to zero because of the orientational -averaging, but when the rotational symmetry is broken, either through the introduction of an alignment medium or for molecules +The RDC between two atomic nuclei depends on the \f$\theta\f$ angle between +the inter-nuclear vector and the external magnetic field. In isotropic media RDCs average to zero because of the orientational +averaging, but when the rotational symmetry is broken, either through the introduction of an alignment medium or for molecules with highly anisotropic paramagnetic susceptibility, RDCs become measurable. \f[ @@ -55,8 +55,8 @@ where D_{max}=-\mu_0\gamma_1\gamma_2h/(8\pi^3r^3) \f] -that is the maximal value of the dipolar coupling for the two nuclear spins with gyromagnetic ratio \f$\gamma\f$. -\f$\mu\f$ is the magnetic constant and h is the Planck constant. +that is the maximal value of the dipolar coupling for the two nuclear spins with gyromagnetic ratio \f$\gamma\f$. +\f$\mu\f$ is the magnetic constant and h is the Planck constant. Common Gyromagnetic Ratios (C.G.S) - H(1) 26.7513 @@ -67,8 +67,8 @@ Common Gyromagnetic Ratios (C.G.S) - CN -18.2385 - CC 45.2404 -This collective variable calculates the Residual Dipolar Coupling for a set of couple of atoms using the above definition. -From the calculated RDCs and a set of experimental values it calculates either their correlation or the squared quality factor +This collective variable calculates the Residual Dipolar Coupling for a set of couple of atoms using the above definition. +From the calculated RDCs and a set of experimental values it calculates either their correlation or the squared quality factor \f[ Q^2=\frac{\sum_i(D_i-D^{exp}_i)^2}{\sum_i(D^{exp}_i)^2} @@ -76,7 +76,7 @@ Q^2=\frac{\sum_i(D_i-D^{exp}_i)^2}{\sum_i(D^{exp}_i)^2} RDCs report only on the fraction of molecules that is aligned, this means that comparing the RDCs from a single structure in a MD simulation to the experimental values is not particularly meaningfull, from this point of view it is better to compare -their correlation. The fraction of aligned molecules can be obtained by maximising the correlation between the calculated and +their correlation. The fraction of aligned molecules can be obtained by maximising the correlation between the calculated and the experimental RDCs. This fraction can be used as a scaling factor in the calculation of the RDCs in order to compare their values. The averaging of the RDCs calculated with the above definition from a standard MD should result to 0 because of the rotational diffusion, but this variable can be used to break the rotational symmetry. @@ -92,12 +92,12 @@ Additional material and examples can be also found in the tutorial \ref belfast- In the following example five N-H RDCs are defined and their correlation with respect to a set of experimental data is calculated and restrained. In addition, and only for analysis purposes, the same RDCs are calculated using a Single Value -Decomposition algorithm. +Decomposition algorithm. \verbatim RDC ... GYROM=-72.5388 -SCALE=1.0 +SCALE=1.0 ATOMS1=20,21 ATOMS2=37,38 ATOMS3=56,57 @@ -113,7 +113,7 @@ rdce: RESTRAINT ARG=nh.corr KAPPA=0. SLOPE=-25000.0 AT=1. RDC ... GYROM=-72.5388 SCALE=1.0 -SVD +SVD ATOMS1=20,21 COUPLING1=8.17 ATOMS2=37,38 COUPLING2=-8.271 ATOMS3=56,57 COUPLING3=-10.489 @@ -125,7 +125,7 @@ LABEL=svd PRINT ARG=nh.corr,rdce.bias FILE=colvar PRINT ARG=svd.* FILE=svd \endverbatim -(See also \ref PRINT, \ref RESTRAINT) +(See also \ref PRINT, \ref RESTRAINT) */ //+ENDPLUMEDOC @@ -146,55 +146,55 @@ class RDC : public Colvar { PLUMED_REGISTER_ACTION(RDC,"RDC") -void RDC::registerKeywords( Keywords& keys ){ +void RDC::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); useCustomisableComponents(keys); keys.add("numbered","ATOMS","the couple of atoms involved in each of the bonds for which you wish to calculate the RDC. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dipolar coupling will be " - "calculated for each ATOMS keyword you specify."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dipolar coupling will be " + "calculated for each ATOMS keyword you specify."); keys.reset_style("ATOMS","atoms"); keys.add("compulsory","GYROM","Add the product of the gyromagnetic constants for the bond. "); keys.add("compulsory","SCALE","Add the scaling factor to take into account concentration and other effects. "); - keys.addFlag("SVD",false,"Set to TRUE if you want to backcalculate using Single Value Decomposition (need GSL at compilation time)."); - keys.addFlag("ADDCOUPLINGS",false,"Set to TRUE if you want to have fixed components with the experimetnal values."); + keys.addFlag("SVD",false,"Set to TRUE if you want to backcalculate using Single Value Decomposition (need GSL at compilation time)."); + keys.addFlag("ADDCOUPLINGS",false,"Set to TRUE if you want to have fixed components with the experimetnal values."); keys.add("numbered","COUPLING","Add an experimental value for each coupling (needed by SVD and usefull for \ref STATS)."); keys.addOutputComponent("rdc","default","the calculated # RDC"); keys.addOutputComponent("exp","SVD/ADDCOUPLINGS","the experimental # RDC"); } RDC::RDC(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -Const(0.3356806), -mu_s(0), -scale(1), -pbc(true) + PLUMED_COLVAR_INIT(ao), + Const(0.3356806), + mu_s(0), + scale(1), + pbc(true) { bool nopbc=!pbc; parseFlag("NOPBC",nopbc); - pbc=!nopbc; + pbc=!nopbc; // Read in the atoms vector t, atoms; - for(int i=1;;++i ){ - parseAtomList("ATOMS", i, t ); - if( t.empty() ) break; - if( t.size()!=2 ){ - std::string ss; Tools::convert(i,ss); - error("ATOMS" + ss + " keyword has the wrong number of atoms"); - } - atoms.push_back(t[0]); - atoms.push_back(t[1]); - t.resize(0); + for(int i=1;; ++i ) { + parseAtomList("ATOMS", i, t ); + if( t.empty() ) break; + if( t.size()!=2 ) { + std::string ss; Tools::convert(i,ss); + error("ATOMS" + ss + " keyword has the wrong number of atoms"); + } + atoms.push_back(t[0]); + atoms.push_back(t[1]); + t.resize(0); } const unsigned ndata = atoms.size()/2; - + // Read in GYROMAGNETIC constants parse("GYROM", mu_s); if(mu_s==0.) error("GYROM must be set"); - // Read in SCALING factors + // Read in SCALING factors parse("SCALE", scale); if(scale==0.) error("SCALE must be different from 0"); @@ -208,19 +208,19 @@ pbc(true) parseFlag("ADDCOUPLINGS",addcoupling); if(svd||addcoupling) { - coupl.resize( ndata ); + coupl.resize( ndata ); unsigned ntarget=0; - for(unsigned i=0;iset(rdc); setBoxDerivatives(val, Tensor(distance,dRDC)); - setAtomsDerivatives(val, r , dRDC); - setAtomsDerivatives(val, r+1, -dRDC); + setAtomsDerivatives(val, r, dRDC); + setAtomsDerivatives(val, r+1, -dRDC); } } else { @@ -317,7 +317,7 @@ void RDC::calculate() double d = distance.modulo(); double d2 = d*d; double d3 = d2*d; - double id3 = 1./d3; + double id3 = 1./d3; double max = -Const*mu_s*scale; dmax[index] = id3*max; double mu_x = distance[0]/d; @@ -334,7 +334,7 @@ void RDC::calculate() gsl_matrix_memcpy(A,coef_mat); gsl_linalg_SV_decomp(A, V, Stmp, work); gsl_linalg_SV_solve(A, V, Stmp, rdc_vec, S); - /* tensor + /* tensor double Sxx = gsl_vector_get(S,0); double Syy = gsl_vector_get(S,1); double Szz = -Sxx-Syy; diff --git a/src/colvar/RMSD.cpp b/src/colvar/RMSD.cpp index 642433452b..8801dfeed2 100644 --- a/src/colvar/RMSD.cpp +++ b/src/colvar/RMSD.cpp @@ -30,15 +30,15 @@ using namespace std; -namespace PLMD{ -namespace colvar{ - +namespace PLMD { +namespace colvar { + class RMSD : public Colvar { - + MultiValue myvals; ReferenceValuePack mypack; PLMD::RMSDBase* rmsd; - bool squared; + bool squared; public: explicit RMSD(const ActionOptions&); @@ -52,30 +52,30 @@ using namespace std; //+PLUMEDOC DCOLVAR RMSD /* -Calculate the RMSD with respect to a reference structure. +Calculate the RMSD with respect to a reference structure. The aim with this colvar it to calculate something like: \f[ -d(X,X') = \vert X-X' \vert +d(X,X') = \vert X-X' \vert \f] -where \f$ X \f$ is the instantaneous position of all the atoms in the system and +where \f$ X \f$ is the instantaneous position of all the atoms in the system and \f$ X' \f$ is the positions of the atoms in some reference structure provided as input. \f$ d(X,X') \f$ thus measures the distance all the atoms have moved away from this reference configuration. -Oftentimes, it is only the internal motions of the structure - i.e. not the translations of the center of +Oftentimes, it is only the internal motions of the structure - i.e. not the translations of the center of mass or the rotations of the reference frame - that are interesting. Hence, when calculating the the root-mean-square deviation between the atoms in two configurations you must first superimpose the two structures in some way. At present PLUMED provides two distinct ways -of performing this superposition. The first method is applied when you use TYPE=SIMPLE in the input +of performing this superposition. The first method is applied when you use TYPE=SIMPLE in the input line. This instruction tells PLUMED that the root mean square deviation is to be calculated after the positions of the geometric centers in the reference and instantaneous configurations are aligned. In -other words \f$d(X,x')\f$ is to be calculated using: +other words \f$d(X,x')\f$ is to be calculated using: \f[ - d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}( X_{i,\alpha}-com_\alpha(X)-{X'}_{i,\alpha}+com_\alpha(X') )^2 } + d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}( X_{i,\alpha}-com_\alpha(X)-{X'}_{i,\alpha}+com_\alpha(X') )^2 } \f] -with +with \f[ com_\alpha(X)= \sum_i \frac{w'_{i}}{\sum_j w'_j}X_{i,\alpha} \f] @@ -86,42 +86,42 @@ com_\alpha(X')= \sum_i \frac{w'_{i}}{\sum_j w'_j}X'_{i,\alpha} Obviously, \f$ com_\alpha(X) \f$ and \f$ com_\alpha(X') \f$ represent the positions of the center of mass in the reference and instantaneous configurations if the weights $w'$ are set equal to the atomic masses. If the weights are all set equal to one, however, \f$com_\alpha(X) \f$ and \f$ com_\alpha(X') \f$ are the positions of the geometric centers. -Notice that there are sets of weights: \f$ w' \f$ and \f$ w \f$. The first is used to calculate the position of the center of mass +Notice that there are sets of weights: \f$ w' \f$ and \f$ w \f$. The first is used to calculate the position of the center of mass (so it determines how the atoms are \e aligned). Meanwhile, the second is used when calculating how far the atoms have actually been \e displaced. These weights are assigned in the reference configuration that you provide as input (i.e. the appear in the input file -to this action that you set using REFERENCE=whatever.pdb). This input reference configuration consists of a simple pdb file -containing the set of atoms for which you want to calculate the RMSD displacement and their positions in the reference configuration. -It is important to note that the indices in this pdb need to be set correctly. The indices in this file determine the indices of the +to this action that you set using REFERENCE=whatever.pdb). This input reference configuration consists of a simple pdb file +containing the set of atoms for which you want to calculate the RMSD displacement and their positions in the reference configuration. +It is important to note that the indices in this pdb need to be set correctly. The indices in this file determine the indices of the instantaneous atomic positions that are used by PLUMED when calculating this colvar. As such if you want to calculate the RMSD distance moved by the 1st, 4th, 6th and 28th atoms in the MD codes input file then the indices of the corresponding refernece positions in this pdb -file should be set equal to 1, 4, 6 and 28. +file should be set equal to 1, 4, 6 and 28. -The pdb input file should also contain the values of \f$w\f$ and \f$w'\f$. In particular, the OCCUPANCY column (the first column after the coordinates) +The pdb input file should also contain the values of \f$w\f$ and \f$w'\f$. In particular, the OCCUPANCY column (the first column after the coordinates) is used provides the values of \f$ w'\f$ that are used to calculate the position of the centre of mass. The BETA column (the second column -after the Cartesian coordinates) is used to provide the \f$ w \f$ values which are used in the the calculation of the displacement. -Please note that it is possible to use fractional values for beta and for the occupancy. However, we recommend you only do this when -you really know what you are doing however as the results can be rather strange. +after the Cartesian coordinates) is used to provide the \f$ w \f$ values which are used in the the calculation of the displacement. +Please note that it is possible to use fractional values for beta and for the occupancy. However, we recommend you only do this when +you really know what you are doing however as the results can be rather strange. -In PDB files the atomic coordinates and box lengths should be in Angstroms unless -you are working with natural units. If you are working with natural units then the coordinates +In PDB files the atomic coordinates and box lengths should be in Angstroms unless +you are working with natural units. If you are working with natural units then the coordinates should be in your natural length unit. For more details on the PDB file format visit http://www.wwpdb.org/docs.html. -A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line. In this case the root mean square +A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line. In this case the root mean square deviation is calculated after the positions of geometric centers in the reference and instantaneous configurations are aligned AND after an optimal alignment of the two frames is performed so that motion due to rotation of the reference frame between the two structures is removed. The equation for \f$d(X,X')\f$ in this case reads: \f[ -d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}[ X_{i,\alpha}-com_\alpha(X)- \sum_\beta M(X,X',w')_{\alpha,\beta}({X'}_{i,\beta}-com_\beta(X')) ]^2 } +d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}[ X_{i,\alpha}-com_\alpha(X)- \sum_\beta M(X,X',w')_{\alpha,\beta}({X'}_{i,\beta}-com_\beta(X')) ]^2 } \f] -where \f$ M(X,X',w') \f$ is the optimal alignment matrix which is calculated using the Kearsley \cite kearsley algorithm. Again different sets of +where \f$ M(X,X',w') \f$ is the optimal alignment matrix which is calculated using the Kearsley \cite kearsley algorithm. Again different sets of weights are used for the alignment (\f$w'\f$) and for the displacement calcuations (\f$w\f$). -This gives a great deal of flexibility as it allows you to use a different sets of atoms (which may or may not overlap) for the alignment and displacement +This gives a great deal of flexibility as it allows you to use a different sets of atoms (which may or may not overlap) for the alignment and displacement parts of the calculation. This may be very useful when you want to calculate how a ligand moves about in a protein cavity as you can use the protein as a reference -system and do no alignment of the ligand. +system and do no alignment of the ligand. -(Note: when this form of RMSD is used to calculate the secondary structure variables (\ref ALPHARMSD, \ref ANTIBETARMSD and \ref PARABETARMSD +(Note: when this form of RMSD is used to calculate the secondary structure variables (\ref ALPHARMSD, \ref ANTIBETARMSD and \ref PARABETARMSD all the atoms in the segment are assumed to be part of both the alignment and displacement sets and all weights are set equal to one) Please note that there are a number of other methods for calculating the distance between the instantaneous configuration and a reference configuration @@ -144,7 +144,7 @@ RMSD REFERENCE=file.pdb TYPE=OPTIMAL PLUMED_REGISTER_ACTION(RMSD,"RMSD") -void RMSD::registerKeywords(Keywords& keys){ +void RMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV."); keys.add("compulsory","TYPE","SIMPLE","the manner in which RMSD alignment is performed. Should be OPTIMAL or SIMPLE."); @@ -153,11 +153,11 @@ void RMSD::registerKeywords(Keywords& keys){ } RMSD::RMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) + PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) { string reference; parse("REFERENCE",reference); - string type; + string type; type.assign("SIMPLE"); parse("TYPE",type); parseFlag("SQUARED",squared); @@ -170,10 +170,10 @@ PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + reference ); + error("missing input file " + reference ); rmsd = metricRegister().create(type,pdb); - + std::vector atoms; rmsd->getAtomRequests( atoms ); // rmsd->setNumberOfAtoms( atoms.size() ); @@ -181,7 +181,7 @@ PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) // Setup the derivative pack myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() ); - for(unsigned i=0;icalculate( getPositions(), mypack, squared ); - setValue(r); - for(unsigned i=0;i \verbatim -# This should be a sample input. +# This should be a sample input. t: TEMPLATE ATOMS=1,2 PRINT ARG=t STRIDE=100 FILE=COLVAR \endverbatim @@ -50,7 +50,7 @@ PRINT ARG=t STRIDE=100 FILE=COLVAR */ //+ENDPLUMEDOC - + class Template : public Colvar { bool pbc; @@ -63,7 +63,7 @@ class Template : public Colvar { PLUMED_REGISTER_ACTION(Template,"TEMPLATE") -void Template::registerKeywords(Keywords& keys){ +void Template::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.addFlag("TEMPLATE_DEFAULT_OFF_FLAG",false,"flags that are by default not performed should be specified like this"); keys.addFlag("TEMPLATE_DEFAULT_ON_FLAG",true,"flags that are by default performed should be specified like this"); @@ -73,8 +73,8 @@ void Template::registerKeywords(Keywords& keys){ } Template::Template(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true) + PLUMED_COLVAR_INIT(ao), + pbc(true) { vector atoms; parseAtomList("ATOMS",atoms); @@ -96,10 +96,10 @@ pbc(true) // calculator -void Template::calculate(){ +void Template::calculate() { Vector distance; - if(pbc){ + if(pbc) { distance=pbcDistance(getPosition(0),getPosition(1)); } else { distance=delta(getPosition(0),getPosition(1)); diff --git a/src/colvar/Torsion.cpp b/src/colvar/Torsion.cpp index 7d885295f3..274d0565a4 100644 --- a/src/colvar/Torsion.cpp +++ b/src/colvar/Torsion.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR TORSION /* @@ -37,7 +37,7 @@ Calculate a torsional angle. This command can be used to compute the torsion between four atoms or alternatively to calculate the angle between two vectors projected on the plane -orthogonal to an axis. +orthogonal to an axis. \par Examples @@ -51,7 +51,7 @@ PRINT ARG=t FILE=COLVAR \endverbatim If you are working with a protein you can specify the special named torsion angles \f$\phi\f$, \f$\psi\f$, \f$\omega\f$ and \f$\chi_1\f$ -by using TORSION in combination with the \ref MOLINFO command. This can be done by using the following +by using TORSION in combination with the \ref MOLINFO command. This can be done by using the following syntax. \verbatim @@ -65,7 +65,7 @@ Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the 4th residue of the protein. */ //+ENDPLUMEDOC - + class Torsion : public Colvar { bool pbc; bool do_cosine; @@ -79,19 +79,19 @@ class Torsion : public Colvar { PLUMED_REGISTER_ACTION(Torsion,"TORSION") -void Torsion::registerKeywords(Keywords& keys){ - Colvar::registerKeywords( keys ); - keys.add("atoms-1","ATOMS","the four atoms involved in the torsional angle"); - keys.add("atoms-2","AXIS","two atoms that define an axis. You can use this to find the angle in the plane perpendicular to the axis between the vectors specified using the VECTOR1 and VECTOR2 keywords."); - keys.add("atoms-2","VECTOR1","two atoms that define a vector. You can use this in combination with VECTOR2 and AXIS"); - keys.add("atoms-2","VECTOR2","two atoms that define a vector. You can use this in combination with VECTOR1 and AXIS"); - keys.addFlag("COSINE",false,"calculate cosine instead of dihedral"); +void Torsion::registerKeywords(Keywords& keys) { + Colvar::registerKeywords( keys ); + keys.add("atoms-1","ATOMS","the four atoms involved in the torsional angle"); + keys.add("atoms-2","AXIS","two atoms that define an axis. You can use this to find the angle in the plane perpendicular to the axis between the vectors specified using the VECTOR1 and VECTOR2 keywords."); + keys.add("atoms-2","VECTOR1","two atoms that define a vector. You can use this in combination with VECTOR2 and AXIS"); + keys.add("atoms-2","VECTOR2","two atoms that define a vector. You can use this in combination with VECTOR1 and AXIS"); + keys.addFlag("COSINE",false,"calculate cosine instead of dihedral"); } Torsion::Torsion(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true), -do_cosine(false) + PLUMED_COLVAR_INIT(ao), + pbc(true), + do_cosine(false) { vector atoms,v1,v2,axis; parseAtomList("ATOMS",atoms); @@ -106,7 +106,7 @@ do_cosine(false) pbc=!nopbc; checkRead(); - if(atoms.size()==4){ + if(atoms.size()==4) { if(!(v1.empty() && v2.empty() && axis.empty())) error("ATOMS keyword is not compatible with VECTOR1, VECTOR2 and AXIS keywords"); log.printf(" between atoms %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial()); @@ -115,11 +115,11 @@ do_cosine(false) atoms[4]=atoms[2]; atoms[3]=atoms[2]; atoms[2]=atoms[1]; - }else if(atoms.empty()){ + } else if(atoms.empty()) { if(!(v1.size()==2 && v2.size()==2 && axis.size()==2)) error("VECTOR1, VECTOR2 and AXIS should specify 2 atoms each"); log.printf(" between lines %d-%d and %d-%d, projected on the plane orthogonal to line %d-%d\n", - v1[0].serial(),v1[1].serial(),v2[0].serial(),v2[1].serial(),axis[0].serial(),axis[1].serial()); + v1[0].serial(),v1[1].serial(),v2[0].serial(),v2[1].serial(),axis[0].serial(),axis[1].serial()); atoms.resize(6); atoms[0]=v1[1]; atoms[1]=v1[0]; @@ -127,7 +127,7 @@ do_cosine(false) atoms[3]=axis[1]; atoms[4]=v2[0]; atoms[5]=v2[1]; - }else error("ATOMS should specify 4 atoms"); + } else error("ATOMS should specify 4 atoms"); if(pbc) log.printf(" using periodic boundary conditions\n"); else log.printf(" without periodic boundary conditions\n"); @@ -141,7 +141,7 @@ do_cosine(false) } // calculator -void Torsion::calculate(){ +void Torsion::calculate() { Vector d0,d1,d2; if(pbc) makeWhole(); @@ -151,11 +151,11 @@ void Torsion::calculate(){ Vector dd0,dd1,dd2; PLMD::Torsion t; double torsion=t.compute(d0,d1,d2,dd0,dd1,dd2); - if(do_cosine){ - dd0 *= -sin(torsion); - dd1 *= -sin(torsion); - dd2 *= -sin(torsion); - torsion = cos(torsion); + if(do_cosine) { + dd0 *= -sin(torsion); + dd1 *= -sin(torsion); + dd2 *= -sin(torsion); + torsion = cos(torsion); } setAtomsDerivatives(0,dd0); setAtomsDerivatives(1,-dd0); diff --git a/src/colvar/Volume.cpp b/src/colvar/Volume.cpp index b33652d663..7b4fb9aacf 100644 --- a/src/colvar/Volume.cpp +++ b/src/colvar/Volume.cpp @@ -27,8 +27,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR VOLUME /* @@ -59,7 +59,7 @@ class Volume : public Colvar { PLUMED_REGISTER_ACTION(Volume,"VOLUME") Volume::Volume(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { std::vector atoms; checkRead(); @@ -68,7 +68,7 @@ PLUMED_COLVAR_INIT(ao) requestAtoms(atoms); } -void Volume::registerKeywords( Keywords& keys ){ +void Volume::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -76,7 +76,7 @@ void Volume::registerKeywords( Keywords& keys ){ // calculator -void Volume::calculate(){ +void Volume::calculate() { double v=getBox().determinant(); setBoxDerivatives(-v*Tensor::identity()); diff --git a/src/config/Config.h b/src/config/Config.h index 95501d9ef7..39c441e98d 100644 --- a/src/config/Config.h +++ b/src/config/Config.h @@ -24,8 +24,8 @@ #include -namespace PLMD{ -namespace config{ +namespace PLMD { +namespace config { /// Return the extension of shared libraries on this system. /// It is either "so" or "dylib". In case shared libraries are disabled, it returns an empty string. diff --git a/src/config/Config.inc.in b/src/config/Config.inc.in index 03eb4af418..6596895588 100644 --- a/src/config/Config.inc.in +++ b/src/config/Config.inc.in @@ -25,18 +25,18 @@ #include #include -namespace PLMD{ -namespace config{ +namespace PLMD { +namespace config { -std::string getSoExt(){ +std::string getSoExt() { return "@SOEXT@"; } -bool isInstalled(){ +bool isInstalled() { return @ISINSTALLED@; } -std::string getPlumedRoot(){ +std::string getPlumedRoot() { char *env = std::getenv("PLUMED_ROOT"); std::string ss; if( env == NULL) { @@ -47,7 +47,7 @@ std::string getPlumedRoot(){ return ss; } -std::string getPlumedHtmldir(){ +std::string getPlumedHtmldir() { if(!isInstalled()) return getPlumedRoot(); char *env = std::getenv("PLUMED_HTMLDIR"); std::string ss; @@ -59,7 +59,7 @@ std::string getPlumedHtmldir(){ return ss; } -std::string getPlumedIncludedir(){ +std::string getPlumedIncludedir() { if(!isInstalled()) return getPlumedRoot()+"/include"; char *env = std::getenv("PLUMED_INCLUDEDIR"); std::string ss; @@ -71,7 +71,7 @@ std::string getPlumedIncludedir(){ return ss; } -std::string getPlumedProgramName(){ +std::string getPlumedProgramName() { if(!isInstalled()) return "plumed"; char *env = std::getenv("PLUMED_PROGRAM_NAME"); std::string ss; @@ -83,86 +83,87 @@ std::string getPlumedProgramName(){ return ss; } -std::string getEnvCommand(){ +std::string getEnvCommand() { return "env PLUMED_ROOT=\""+getPlumedRoot()+"\""+ - " env PLUMED_HTMLDIR=\""+getPlumedHtmldir()+"\""+ - " env PLUMED_INCLUDEDIR=\""+getPlumedIncludedir()+"\""+ - " env PLUMED_PROGRAM_NAME=\""+getPlumedProgramName()+"\""+ - " env PLUMED_IS_INSTALLED=\""+(@ISINSTALLED@?"yes":"no")+"\""; + " env PLUMED_HTMLDIR=\""+getPlumedHtmldir()+"\""+ + " env PLUMED_INCLUDEDIR=\""+getPlumedIncludedir()+"\""+ + " env PLUMED_PROGRAM_NAME=\""+getPlumedProgramName()+"\""+ + " env PLUMED_IS_INSTALLED=\""+(@ISINSTALLED@?"yes":"no")+"\""; } -std::string getVersion(){ +std::string getVersion() { return PLUMED_VERSION_SHORT; } -std::string getVersionLong(){ +std::string getVersionLong() { return PLUMED_VERSION_LONG; } -std::string getVersionGit(){ +std::string getVersionGit() { return PLUMED_VERSION_GIT; } -std::string getMakefile(){ - static const char conf [] ={ +std::string getMakefile() { + static const char conf [] = { #include "Makefile.conf.xxd" - , 0x00 }; + , 0x00 + }; return std::string(conf,conf+std::strlen(conf)); } -bool hasMatheval(){ +bool hasMatheval() { #if __PLUMED_HAS_MATHEVAL - return true; + return true; #else - return false; + return false; #endif } -bool hasDlopen(){ +bool hasDlopen() { #if __PLUMED_HAS_DLOPEN - return true; + return true; #else - return false; + return false; #endif } -bool hasCregex(){ +bool hasCregex() { #if __PLUMED_HAS_CREGEX - return true; + return true; #else - return false; + return false; #endif } -bool hasMolfile(){ +bool hasMolfile() { #if __PLUMED_HAS_MOLFILE_PLUGINS - return true; + return true; #else - return false; + return false; #endif } -bool hasExternalMolfile(){ +bool hasExternalMolfile() { #if __PLUMED_HAS_EXTERNAL_MOLFILE_PLUGINS - return true; + return true; #else - return false; + return false; #endif } -bool hasZlib(){ +bool hasZlib() { #if __PLUMED_HAS_ZLIB - return true; + return true; #else - return false; + return false; #endif } -bool hasXdrfile(){ +bool hasXdrfile() { #if __PLUMED_HAS_XDRFILE - return true; + return true; #else - return false; + return false; #endif } diff --git a/src/core/Action.cpp b/src/core/Action.cpp index 1c47820095..a78c7c7300 100644 --- a/src/core/Action.cpp +++ b/src/core/Action.cpp @@ -28,25 +28,25 @@ #include "ActionSet.h" #include -namespace PLMD{ +namespace PLMD { Keywords ActionOptions::emptyKeys; ActionOptions::ActionOptions(PlumedMain&p,const std::vector&l): -plumed(p), -line(l), -keys(emptyKeys) + plumed(p), + line(l), + keys(emptyKeys) { } ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys): -plumed(ao.plumed), -line(ao.line), -keys(keys) + plumed(ao.plumed), + line(ao.line), + keys(keys) { } -void Action::registerKeywords( Keywords& keys ){ +void Action::registerKeywords( Keywords& keys ) { plumed_assert( keys.size()==0 ); keys.add( "hidden", "LABEL", "a label for the action so that its output can be referenced in the input to other actions. Actions with scalar output are referenced using their label only. Actions with vector output must have a separate label for every component. Individual componets are then refered to using label.component" ); keys.reserve("optional","UPDATE_FROM","Only update this action from this time"); @@ -71,14 +71,14 @@ Action::Action(const ActionOptions&ao): line.erase(line.begin()); log.printf("Action %s\n",name.c_str()); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { replica_index=multi_sim_comm.Get_rank(); } comm.Bcast(replica_index,0); - if ( keywords.exists("LABEL") ){ parse("LABEL",label); } + if ( keywords.exists("LABEL") ) { parse("LABEL",label); } - if(label.length()==0){ + if(label.length()==0) { std::string s; Tools::convert(plumed.getActionSet().size(),s); label="@"+s; } @@ -88,7 +88,7 @@ Action::Action(const ActionOptions&ao): if(update_from!=std::numeric_limits::max()) log.printf(" only update from time %f\n",update_from); if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until); if(update_until!=std::numeric_limits::max()) log.printf(" only update until time %f\n",update_until); - if ( keywords.exists("RESTART") ){ + if ( keywords.exists("RESTART") ) { std::string srestart="AUTO"; parse("RESTART",srestart); if(srestart=="YES") restart=true; @@ -98,15 +98,15 @@ Action::Action(const ActionOptions&ao): } } -Action::~Action(){ - if(files.size()!=0){ +Action::~Action() { + if(files.size()!=0) { std::cerr<<"WARNING: some files open in action "+getLabel()+" where not properly closed. This could lead to data loss!!\n"; } } -FILE* Action::fopen(const char *path, const char *mode){ +FILE* Action::fopen(const char *path, const char *mode) { bool write(false); - for(const char*p=mode;*p;p++) if(*p=='w' || *p=='a' || *p=='+') write=true; + for(const char*p=mode; *p; p++) if(*p=='w' || *p=='a' || *p=='+') write=true; FILE* fp; if(write && comm.Get_rank()!=0) fp=plumed.fopen("/dev/null",mode); else fp=plumed.fopen(path,mode); @@ -114,64 +114,64 @@ FILE* Action::fopen(const char *path, const char *mode){ return fp; } -int Action::fclose(FILE*fp){ +int Action::fclose(FILE*fp) { files.erase(fp); return plumed.fclose(fp); } -void Action::fflush(){ - for(const auto & p : files){ +void Action::fflush() { + for(const auto & p : files) { std::fflush(p); } } -std::string Action::getKeyword(const std::string& key){ - // Check keyword has been registered +std::string Action::getKeyword(const std::string& key) { + // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); std::string outkey; if( Tools::getKey(line,key,outkey ) ) return key + outkey; - if( keywords.style(key,"compulsory") ){ - if( keywords.getDefaultValue(key,outkey) ){ - if( outkey.length()==0 ) error("keyword " + key + " has weird default value"); - return key + "=" + outkey; - } else { - error("keyword " + key + " is compulsory for this action"); - } - } + if( keywords.style(key,"compulsory") ) { + if( keywords.getDefaultValue(key,outkey) ) { + if( outkey.length()==0 ) error("keyword " + key + " has weird default value"); + return key + "=" + outkey; + } else { + error("keyword " + key + " is compulsory for this action"); + } + } return ""; } -void Action::parseFlag(const std::string&key,bool & t){ +void Action::parseFlag(const std::string&key,bool & t) { // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); // Check keyword is a flag - if(!keywords.style(key,"nohtml")){ - plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag"); + if(!keywords.style(key,"nohtml")) { + plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag"); } // Read in the flag otherwise get the default value from the keywords object - if(!Tools::parseFlag(line,key,t)){ - if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ){ - t=false; - } else if ( !keywords.getLogicalDefault(key,t) ){ - log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() ); - plumed_error(); - } + if(!Tools::parseFlag(line,key,t)) { + if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) { + t=false; + } else if ( !keywords.getLogicalDefault(key,t) ) { + log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() ); + plumed_error(); + } } } -void Action::addDependency(Action*action){ +void Action::addDependency(Action*action) { after.push_back(action); } -void Action::activate(){ +void Action::activate() { // preparation step is called only the first time an Action is activated. // since it could change its dependences (e.g. in an ActionAtomistic which is // accessing to a virtual atom), this is done just before dependencies are // activated - if(!active){ + if(!active) { this->unlockRequests(); prepare(); this->lockRequests(); @@ -180,57 +180,57 @@ void Action::activate(){ active=true; } -void Action::setOption(const std::string &s){ -// This overloads the action and activate some options +void Action::setOption(const std::string &s) { +// This overloads the action and activate some options options.insert(s); for(const auto & p : after) p->setOption(s); } -void Action::clearOptions(){ -// This overloads the action and activate some options +void Action::clearOptions() { +// This overloads the action and activate some options options.clear(); } -void Action::clearDependencies(){ +void Action::clearDependencies() { after.clear(); } -std::string Action::getDocumentation()const{ +std::string Action::getDocumentation()const { return std::string("UNDOCUMENTED ACTION"); } -void Action::checkRead(){ - if(!line.empty()){ +void Action::checkRead() { + if(!line.empty()) { std::string msg="cannot understand the following words from the input line : "; - for(unsigned i=0;i(p); - if(av){ av->clearInputForces(); av->clearDerivatives(); } - p->readAtomsFromPDB( pdb ); - p->calculate(); + for(const auto & p : after) { + ActionWithValue*av=dynamic_cast(p); + if(av) { av->clearInputForces(); av->clearDerivatives(); } + p->readAtomsFromPDB( pdb ); + p->calculate(); } readAtomsFromPDB( pdb ); calculate(); } -bool Action::getExchangeStep()const{ +bool Action::getExchangeStep()const { return plumed.getExchangeStep(); } -std::string Action::cite(const std::string&s){ +std::string Action::cite(const std::string&s) { return plumed.cite(s); } /// Check if action should be updated. -bool Action::checkUpdate()const{ +bool Action::checkUpdate()const { double t=getTime(); if(t::max() || t>=update_from)) return true; else return false; diff --git a/src/core/Action.h b/src/core/Action.h index 43cd5d15ea..d65208bbcb 100644 --- a/src/core/Action.h +++ b/src/core/Action.h @@ -29,16 +29,16 @@ #include "tools/Tools.h" #include "tools/Log.h" -namespace PLMD{ +namespace PLMD { class PDB; class PlumedMain; class Communicator; /// This class is used to bring the relevant information to the Action constructor. -/// Only Action and ActionRegister class can access to its content, which is +/// Only Action and ActionRegister class can access to its content, which is /// kept private to other classes, and may change in the future. -class ActionOptions{ +class ActionOptions { friend class Action; friend class ActionRegister; /// Reference to main PlumedMain object @@ -88,12 +88,12 @@ class Action private: /// Actions on which this Action depends. Dependencies after; - + /// Switch to activate Action on this step. bool active; -/// Option that you might have enabled - std::set options; +/// Option that you might have enabled + std::set options; bool restart; @@ -114,7 +114,7 @@ class Action void clearDependencies(); /// Return the present timestep - long int getStep()const; + long int getStep()const; /// Return the present time double getTime()const; @@ -125,7 +125,7 @@ class Action /// Return true if we are doing a restart bool getRestart()const; -/// Return true if we are doing at a checkpoint step +/// Return true if we are doing at a checkpoint step bool getCPT()const; /// Just read one of the keywords and return the whole thing as a string @@ -151,8 +151,8 @@ class Action void parseFlag(const std::string&key,bool&t); /// Crash calculation and print documentation - void error( const std::string & msg ) const; - + void error( const std::string & msg ) const; + /// Issue a warning void warning( const std::string & msg ); @@ -190,11 +190,11 @@ class Action /// By default (if not overridden) does nothing. virtual void prepare(); -/// Register all the relevant keywords for the action +/// Register all the relevant keywords for the action static void registerKeywords( Keywords& keys ); - virtual void lockRequests(){} - virtual void unlockRequests(){} + virtual void lockRequests() {} + virtual void unlockRequests() {} /// Calculate an Action. /// This method is called one or more times per step. @@ -213,17 +213,17 @@ class Action /// of the fact that update() is active or not. /// In other words, this is *always* called, even when action /// is not active. - virtual void beforeUpdate(){} + virtual void beforeUpdate() {} /// Update. /// This method is called one time per step. /// The set of all Actions is updated in forward order. - virtual void update(){} + virtual void update() {} /// RunFinalJobs /// This method is called once at the very end of the calculation. /// The set of all Actions in run for the final time in forward order. - virtual void runFinalJobs(){} + virtual void runFinalJobs() {} /// Tell to the Action to flush open files void fflush(); @@ -254,16 +254,16 @@ class Action bool isOptionOn(const std::string &s)const; /// Return dependencies - const Dependencies & getDependencies()const{return after;} + const Dependencies & getDependencies()const {return after;} /// Check if numerical derivatives should be performed - virtual bool checkNumericalDerivatives()const{return false;} + virtual bool checkNumericalDerivatives()const {return false;} /// Check if the action needs gradient - virtual bool checkNeedsGradients()const{return false;} + virtual bool checkNeedsGradients()const {return false;} /// Perform calculation using numerical derivatives -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); @@ -278,10 +278,10 @@ class Action /// Calculate the action given a pdb file as input. This is used to initialize /// things like distance from a point in CV map space given a pdb as an input file void calculateFromPDB( const PDB& ); -/// This is overwritten in ActionAtomistic so that we can read -/// the atoms from the pdb input file rather than taking them from the +/// This is overwritten in ActionAtomistic so that we can read +/// the atoms from the pdb input file rather than taking them from the /// MD code - virtual void readAtomsFromPDB( const PDB& ){} + virtual void readAtomsFromPDB( const PDB& ) {} /// Check if we are on an exchange step bool getExchangeStep()const; @@ -293,17 +293,17 @@ class Action // FAST INLINE METHODS inline -const std::string & Action::getLabel()const{ +const std::string & Action::getLabel()const { return label; } inline -const std::string & Action::getName()const{ +const std::string & Action::getName()const { return name; } template -void Action::parse(const std::string&key,T&t){ +void Action::parse(const std::string&key,T&t) { // if(!Tools::parse(line,key,t)){ // log.printf("ERROR parsing keyword %s\n",key.c_str()); // log.printf("%s\n",getDocumentation().c_str()); @@ -313,26 +313,26 @@ void Action::parse(const std::string&key,T&t){ plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); // Now try to read the keyword - std::string def; + std::string def; bool present=Tools::findKeyword(line,key); bool found=Tools::parse(line,key,t,replica_index); if(present && !found) error("keyword " + key +" could not be read correctly"); - - // If it isn't read and it is compulsory see if a default value was specified - if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ){ - if( keywords.getDefaultValue(key,def) ){ - if( def.length()==0 || !Tools::convert(def,t) ){ - log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() ); - this->exit(1); - } - } else if( keywords.style(key,"compulsory") ){ - error("keyword " + key + " is compulsory for this action"); - } - } + + // If it isn't read and it is compulsory see if a default value was specified + if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) { + if( keywords.getDefaultValue(key,def) ) { + if( def.length()==0 || !Tools::convert(def,t) ) { + log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() ); + this->exit(1); + } + } else if( keywords.style(key,"compulsory") ) { + error("keyword " + key + " is compulsory for this action"); + } + } } template -bool Action::parseNumbered(const std::string&key, const int no, T&t){ +bool Action::parseNumbered(const std::string&key, const int no, T&t) { // Check keyword has been registered plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key ); @@ -343,7 +343,7 @@ bool Action::parseNumbered(const std::string&key, const int no, T&t){ } template -void Action::parseVector(const std::string&key,std::vector&t){ +void Action::parseVector(const std::string&key,std::vector&t) { // if(!Tools::parseVector(line,key,t)){ // log.printf("ERROR parsing keyword %s\n",key.c_str()); // log.printf("%s\n",getDocumentation().c_str()); @@ -362,31 +362,31 @@ void Action::parseVector(const std::string&key,std::vector&t){ if(present && !found) error("keyword " + key +" could not be read correctly"); // Check vectors size is correct (not if this is atoms or ARG) - if( !keywords.style(key,"atoms") && found ){ + if( !keywords.style(key,"atoms") && found ) { // bool skipcheck=false; // if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); } - if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); + if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); } - // If it isn't read and it is compulsory see if a default value was specified - if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ){ - if( keywords.getDefaultValue(key,def) ){ - if( def.length()==0 || !Tools::convert(def,val) ){ - log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() ); - this->exit(1); - } else { - for(unsigned i=0;iexit(1); + } else { + for(unsigned i=0; i -bool Action::parseNumberedVector(const std::string&key, const int no, std::vector&t){ +bool Action::parseNumberedVector(const std::string&key, const int no, std::vector&t) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key ); @@ -397,37 +397,37 @@ bool Action::parseNumberedVector(const std::string&key, const int no, std::vecto bool found=Tools::parseVector(line,key+num,t,replica_index); if(present && !found) error("keyword " + key +" could not be read correctly"); - if( keywords.style(key,"compulsory") ){ - if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size"); - } else if ( !found ){ + if( keywords.style(key,"compulsory") ) { + if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size"); + } else if ( !found ) { t.resize(0); } return found; } inline -void Action::deactivate(){ +void Action::deactivate() { options.clear(); active=false; } inline -bool Action::isActive()const{ +bool Action::isActive()const { return active; } inline -bool Action::isOptionOn(const std::string &s)const{ +bool Action::isOptionOn(const std::string &s)const { return options.count(s); } inline -bool Action::getRestart()const{ +bool Action::getRestart()const { return restart; } inline -bool Action::getCPT()const{ +bool Action::getCPT()const { return doCheckPoint; } diff --git a/src/core/ActionAtomistic.cpp b/src/core/ActionAtomistic.cpp index 288216266f..29ed09e3da 100644 --- a/src/core/ActionAtomistic.cpp +++ b/src/core/ActionAtomistic.cpp @@ -37,30 +37,30 @@ using namespace std; namespace PLMD { -ActionAtomistic::~ActionAtomistic(){ +ActionAtomistic::~ActionAtomistic() { // forget the pending request atoms.remove(this); delete(&pbc); } ActionAtomistic::ActionAtomistic(const ActionOptions&ao): -Action(ao), -pbc(*new(Pbc)), -lockRequestAtoms(false), -donotretrieve(false), -donotforce(false), -atoms(plumed.getAtoms()) + Action(ao), + pbc(*new(Pbc)), + lockRequestAtoms(false), + donotretrieve(false), + donotforce(false), + atoms(plumed.getAtoms()) { atoms.add(this); // if(atoms.getNatoms()==0) error("Cannot perform calculations involving atoms without atoms"); } -void ActionAtomistic::registerKeywords( Keywords& keys ){ +void ActionAtomistic::registerKeywords( Keywords& keys ) { (void) keys; // avoid warning } -void ActionAtomistic::requestAtoms(const vector & a){ +void ActionAtomistic::requestAtoms(const vector & a) { plumed_massert(!lockRequestAtoms,"requested atom list can only be changed in the prepare() method"); int nat=a.size(); indexes=a; @@ -71,7 +71,7 @@ void ActionAtomistic::requestAtoms(const vector & a){ int n=atoms.positions.size(); clearDependencies(); unique.clear(); - for(unsigned i=0;i=n) error("atom out of range"); if(atoms.isVirtualAtom(indexes[i])) addDependency(atoms.getVirtualAtomsAction(indexes[i])); // only real atoms are requested to lower level Atoms class @@ -80,24 +80,24 @@ void ActionAtomistic::requestAtoms(const vector & a){ } -Vector ActionAtomistic::pbcDistance(const Vector &v1,const Vector &v2)const{ +Vector ActionAtomistic::pbcDistance(const Vector &v1,const Vector &v2)const { return pbc.distance(v1,v2); } -void ActionAtomistic::pbcApply(std::vector& dlist, unsigned max_index)const{ +void ActionAtomistic::pbcApply(std::vector& dlist, unsigned max_index)const { pbc.apply(dlist, max_index); } -void ActionAtomistic::calculateNumericalDerivatives( ActionWithValue* a ){ +void ActionAtomistic::calculateNumericalDerivatives( ActionWithValue* a ) { calculateAtomicNumericalDerivatives( a, 0 ); } -void ActionAtomistic::changeBox( const Tensor& newbox ){ +void ActionAtomistic::changeBox( const Tensor& newbox ) { pbc.setBox( newbox ); } -void ActionAtomistic::calculateAtomicNumericalDerivatives( ActionWithValue* a, const unsigned& startnum ){ - if(!a){ +void ActionAtomistic::calculateAtomicNumericalDerivatives( ActionWithValue* a, const unsigned& startnum ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"only Actions with a value can be differentiated"); } @@ -109,109 +109,109 @@ void ActionAtomistic::calculateAtomicNumericalDerivatives( ActionWithValue* a, c std::vector savedPositions(natoms); const double delta=sqrt(epsilon); - for(int i=0;icalculate(); - positions[i][k]=savedPositions[i][k]; - for(int j=0;jgetOutputQuantity(j); + for(int i=0; icalculate(); + positions[i][k]=savedPositions[i][k]; + for(int j=0; jgetOutputQuantity(j); + } + } + Tensor box(pbc.getBox()); + for(int i=0; i<3; i++) for(int k=0; k<3; k++) { + double arg0=box(i,k); + for(int j=0; jcalculate(); + box(i,k)=arg0; + pbc.setBox(box); + for(int j=0; jgetOutputQuantity(j); } - } - Tensor box(pbc.getBox()); - for(int i=0;i<3;i++) for(int k=0;k<3;k++){ - double arg0=box(i,k); - for(int j=0;jcalculate(); - box(i,k)=arg0; - pbc.setBox(box); - for(int j=0;jgetOutputQuantity(j); - } a->calculate(); a->clearDerivatives(); - for(int j=0;jcopyOutput(j); double ref=v->get(); - if(v->hasDerivatives()){ - for(int i=0;iaddDerivative(startnum+3*i+k,d); - } + if(v->hasDerivatives()) { + for(int i=0; iaddDerivative(startnum+3*i+k,d); + } Tensor virial; - for(int i=0;i<3;i++) for(int k=0;k<3;k++)virial(i,k)= (valuebox[j](i,k)-ref)/delta; + for(int i=0; i<3; i++) for(int k=0; k<3; k++)virial(i,k)= (valuebox[j](i,k)-ref)/delta; // BE CAREFUL WITH NON ORTHOROMBIC CELL virial=-matmul(box.transpose(),virial); - for(int i=0;i<3;i++) for(int k=0;k<3;k++) v->addDerivative(startnum+3*natoms+3*k+i,virial(k,i)); + for(int i=0; i<3; i++) for(int k=0; k<3; k++) v->addDerivative(startnum+3*natoms+3*k+i,virial(k,i)); } } } -void ActionAtomistic::parseAtomList(const std::string&key, std::vector &t){ +void ActionAtomistic::parseAtomList(const std::string&key, std::vector &t) { parseAtomList(key,-1,t); } -void ActionAtomistic::parseAtomList(const std::string&key,const int num, std::vector &t){ +void ActionAtomistic::parseAtomList(const std::string&key,const int num, std::vector &t) { plumed_massert( keywords.style(key,"atoms") || keywords.style(key,"hidden"), "keyword " + key + " should be registered as atoms"); vector strings; - if( num<0 ){ - parseVector(key,strings); - if(strings.empty()) return; + if( num<0 ) { + parseVector(key,strings); + if(strings.empty()) return; } else { - if ( !parseNumberedVector(key,num,strings) ) return; + if ( !parseNumberedVector(key,num,strings) ) return; } interpretAtomList( strings, t ); } -void ActionAtomistic::interpretAtomList( std::vector& strings, std::vector &t){ +void ActionAtomistic::interpretAtomList( std::vector& strings, std::vector &t) { Tools::interpretRanges(strings); t.resize(0); - for(unsigned i=0;i moldat=plumed.getActionSet().select(); - if( moldat.size()>0 ){ - vector atom_list; moldat[0]->interpretSymbol( symbol, atom_list ); - if( atom_list.size()>0 ){ ok=true; t.insert(t.end(),atom_list.begin(),atom_list.end()); } - else { error(strings[i] + " is not a label plumed knows"); } + if( moldat.size()>0 ) { + vector atom_list; moldat[0]->interpretSymbol( symbol, atom_list ); + if( atom_list.size()>0 ) { ok=true; t.insert(t.end(),atom_list.begin(),atom_list.end()); } + else { error(strings[i] + " is not a label plumed knows"); } } else { - error("atoms specified using @ symbol but no MOLINFO was available"); + error("atoms specified using @ symbol but no MOLINFO was available"); } - } + } // here we check if the atom name is the name of a group - if(!ok){ - if(atoms.groups.count(strings[i])){ - const auto m=atoms.groups.find(strings[i]); - t.insert(t.end(),m->second.begin(),m->second.end()); - ok=true; - } - } + if(!ok) { + if(atoms.groups.count(strings[i])) { + const auto m=atoms.groups.find(strings[i]); + t.insert(t.end(),m->second.begin(),m->second.end()); + ok=true; + } + } // here we check if the atom name is the name of an added virtual atom - if(!ok){ - const ActionSet&actionSet(plumed.getActionSet()); - for(const auto & a : actionSet){ - ActionWithVirtualAtom* c=dynamic_cast(a); - if(c) if(c->getLabel()==strings[i]){ - ok=true; - t.push_back(c->getIndex()); - break; - } - } - } - if(!ok) error("it was not possible to interpret atom name " + strings[i]); - // plumed_massert(ok,"it was not possible to interpret atom name " + strings[i]); + if(!ok) { + const ActionSet&actionSet(plumed.getActionSet()); + for(const auto & a : actionSet) { + ActionWithVirtualAtom* c=dynamic_cast(a); + if(c) if(c->getLabel()==strings[i]) { + ok=true; + t.push_back(c->getIndex()); + break; + } + } + } + if(!ok) error("it was not possible to interpret atom name " + strings[i]); + // plumed_massert(ok,"it was not possible to interpret atom name " + strings[i]); } -} +} -void ActionAtomistic::retrieveAtoms(){ +void ActionAtomistic::retrieveAtoms() { pbc=atoms.pbc; Colvar*cc=dynamic_cast(this); if(cc && cc->checkIsEnergy()) energy=atoms.getEnergy(); @@ -220,15 +220,15 @@ void ActionAtomistic::retrieveAtoms(){ const vector & p(atoms.positions); const vector & c(atoms.charges); const vector & m(atoms.masses); - for(unsigned j=0;j& forcesToApply, unsigned ind ){ +void ActionAtomistic::setForcesOnAtoms( const std::vector& forcesToApply, unsigned ind ) { if(donotforce) return; - for(unsigned i=0;i& forcesToApply plumed_dbg_assert( ind+1==forcesToApply.size()); } -void ActionAtomistic::applyForces(){ +void ActionAtomistic::applyForces() { if(donotforce) return; vector & f(atoms.forces); Tensor & v(atoms.virial); - for(unsigned j=0;j(this); if(cc && cc->checkIsEnergy()) error("can't read energies from pdb files"); - for(unsigned j=0;jpdb.size() ) error("there are not enough atoms in the input pdb file"); - if( pdb.getAtomNumbers()[j].index()!=indexes[j].index() ) error("there are atoms missing in the pdb file"); - positions[j]=pdb.getPositions()[indexes[j].index()]; + for(unsigned j=0; jpdb.size() ) error("there are not enough atoms in the input pdb file"); + if( pdb.getAtomNumbers()[j].index()!=indexes[j].index() ) error("there are atoms missing in the pdb file"); + positions[j]=pdb.getPositions()[indexes[j].index()]; } - for(unsigned j=0;j indexes; // the set of needed atoms std::set unique; @@ -111,7 +111,7 @@ class ActionAtomistic : /// Get a reference to force on energy double & modifyForceOnEnergy(); /// Get number of available atoms - unsigned getNumberOfAtoms()const{return indexes.size();} + unsigned getNumberOfAtoms()const {return indexes.size();} /// Compute the pbc distance between two positions Vector pbcDistance(const Vector&,const Vector&)const; /// Applies PBCs to a seriens of positions or distances @@ -126,7 +126,7 @@ class ActionAtomistic : void parseAtomList(const std::string&key,const int num, std::vector &t); /// Convert a set of read in strings into an atom list (this is used in parseAtomList) void interpretAtomList( std::vector& strings, std::vector &t); -/// Change the box shape +/// Change the box shape void changeBox( const Tensor& newbox ); /// Get reference to Pbc const Pbc & getPbc() const; @@ -137,15 +137,15 @@ class ActionAtomistic : /// not going to be retrieved. Can be used for optimization. Notice that /// calling getPosition(int) in an Action where DoNotRetrieve() was called might /// lead to undefined behavior. - void doNotRetrieve(){donotretrieve=true;} + void doNotRetrieve() {donotretrieve=true;} /// Skip atom forces - use with care. /// If this function is called during initialization, then forces are /// not going to be propagated. Can be used for optimization. - void doNotForce(){donotforce=true;} + void doNotForce() {donotforce=true;} /// Make atoms whole, assuming they are in the proper order void makeWhole(); /// Allow calls to modifyGlobalForce() - void allowToAccessGlobalForces(){atoms.zeroallforces=true;} + void allowToAccessGlobalForces() {atoms.zeroallforces=true;} public: // virtual functions: @@ -157,10 +157,10 @@ class ActionAtomistic : void clearOutputForces(); -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. The default will be correct for the vast majority of cases virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); -/// Numerical derivative routine to use when using Actions that inherit from BOTH +/// Numerical derivative routine to use when using Actions that inherit from BOTH /// ActionWithArguments and ActionAtomistic void calculateAtomicNumericalDerivatives( ActionWithValue* a, const unsigned& startnum ); @@ -169,38 +169,38 @@ class ActionAtomistic : void lockRequests(); void unlockRequests(); const std::set & getUnique()const; -/// Read in an input file containing atom positions and calculate the action for the atomic +/// Read in an input file containing atom positions and calculate the action for the atomic /// configuration therin void readAtomsFromPDB( const PDB& pdb ); }; inline -const Vector & ActionAtomistic::getPosition(int i)const{ +const Vector & ActionAtomistic::getPosition(int i)const { return positions[i]; } inline -const Vector & ActionAtomistic::getPosition(AtomNumber i)const{ +const Vector & ActionAtomistic::getPosition(AtomNumber i)const { return atoms.positions[i.index()]; } inline -Vector & ActionAtomistic::modifyPosition(AtomNumber i){ +Vector & ActionAtomistic::modifyPosition(AtomNumber i) { return atoms.positions[i.index()]; } inline -Vector & ActionAtomistic::modifyGlobalForce(AtomNumber i){ +Vector & ActionAtomistic::modifyGlobalForce(AtomNumber i) { return atoms.forces[i.index()]; } inline -Tensor & ActionAtomistic::modifyGlobalVirial(){ +Tensor & ActionAtomistic::modifyGlobalVirial() { return atoms.virial; } inline -double ActionAtomistic::getMass(int i)const{ +double ActionAtomistic::getMass(int i)const { return masses[i]; } @@ -211,72 +211,72 @@ double ActionAtomistic::getCharge(int i) const { } inline -const std::vector & ActionAtomistic::getAbsoluteIndexes()const{ +const std::vector & ActionAtomistic::getAbsoluteIndexes()const { return indexes; } inline -AtomNumber ActionAtomistic::getAbsoluteIndex(int i)const{ +AtomNumber ActionAtomistic::getAbsoluteIndex(int i)const { return indexes[i]; } inline -const std::vector & ActionAtomistic::getPositions()const{ +const std::vector & ActionAtomistic::getPositions()const { return positions; } inline -const double & ActionAtomistic::getEnergy()const{ +const double & ActionAtomistic::getEnergy()const { return energy; } inline -const Tensor & ActionAtomistic::getBox()const{ +const Tensor & ActionAtomistic::getBox()const { return pbc.getBox(); } inline -std::vector & ActionAtomistic::modifyForces(){ +std::vector & ActionAtomistic::modifyForces() { return forces; } inline -Tensor & ActionAtomistic::modifyVirial(){ +Tensor & ActionAtomistic::modifyVirial() { return virial; } inline -double & ActionAtomistic::modifyForceOnEnergy(){ +double & ActionAtomistic::modifyForceOnEnergy() { return forceOnEnergy; } inline -const Pbc & ActionAtomistic::getPbc() const{ - return pbc; +const Pbc & ActionAtomistic::getPbc() const { + return pbc; } inline -void ActionAtomistic::lockRequests(){ +void ActionAtomistic::lockRequests() { lockRequestAtoms=true; } inline -void ActionAtomistic::unlockRequests(){ +void ActionAtomistic::unlockRequests() { lockRequestAtoms=false; } inline -const std::set & ActionAtomistic::getUnique()const{ +const std::set & ActionAtomistic::getUnique()const { return unique; } inline -unsigned ActionAtomistic::getTotAtoms()const{ +unsigned ActionAtomistic::getTotAtoms()const { return atoms.positions.size(); } inline -Pbc & ActionAtomistic::modifyGlobalPbc(){ +Pbc & ActionAtomistic::modifyGlobalPbc() { return atoms.pbc; } diff --git a/src/core/ActionPilot.cpp b/src/core/ActionPilot.cpp index 10007dedcb..fbd6d3bb2f 100644 --- a/src/core/ActionPilot.cpp +++ b/src/core/ActionPilot.cpp @@ -22,33 +22,33 @@ #include "ActionPilot.h" using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionPilot::registerKeywords(Keywords& keys){ +void ActionPilot::registerKeywords(Keywords& keys) { } ActionPilot::ActionPilot(const ActionOptions&ao): -Action(ao), -stride(1) + Action(ao), + stride(1) { - if( keywords.exists("STRIDE") ){ - parse("STRIDE",stride); - if( !keywords.style("STRIDE","hidden") ) log.printf(" with stride %d\n",stride); + if( keywords.exists("STRIDE") ) { + parse("STRIDE",stride); + if( !keywords.style("STRIDE","hidden") ) log.printf(" with stride %d\n",stride); } else { - stride=0; + stride=0; } } -bool ActionPilot::onStep()const{ +bool ActionPilot::onStep()const { if( stride>0 ) return getStep()%stride==0; return false; } -int ActionPilot::getStride()const{ +int ActionPilot::getStride()const { return stride; } -void ActionPilot::setStride( const int& n ){ +void ActionPilot::setStride( const int& n ) { stride=n; } diff --git a/src/core/ActionPilot.h b/src/core/ActionPilot.h index 007508ca64..bf3e024463 100644 --- a/src/core/ActionPilot.h +++ b/src/core/ActionPilot.h @@ -24,13 +24,13 @@ #include "Action.h" -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT This is used to create PLMD::Action objects that are run with some set frequency. -Any PLMD::Action -that does not inherit from PLMD::Action is only run when some other Action requires the output from +Any PLMD::Action +that does not inherit from PLMD::Action is only run when some other Action requires the output from it in order to run. This class is used in PLMD::Bias Action which drives the execution of other Action's. Action's of this kind are executed with a fixed stride diff --git a/src/core/ActionRegister.cpp b/src/core/ActionRegister.cpp index b948e69a54..e064392c39 100644 --- a/src/core/ActionRegister.cpp +++ b/src/core/ActionRegister.cpp @@ -27,34 +27,34 @@ using namespace std; -namespace PLMD{ +namespace PLMD { -ActionRegister::~ActionRegister(){ - if(m.size()>0){ +ActionRegister::~ActionRegister() { + if(m.size()>0) { string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: Directive "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -ActionRegister& actionRegister(){ +ActionRegister& actionRegister() { static ActionRegister ans; return ans; } -void ActionRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void ActionRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void ActionRegister::add(string key,creator_pointer f,keywords_pointer k){ - if(m.count(key)){ +void ActionRegister::add(string key,creator_pointer f,keywords_pointer k) { + if(m.count(key)) { m.erase(key); disabled.insert(key); - }else{ + } else { m.insert(pair(key,f)); // Store a pointer to the function that creates keywords // A pointer is stored and not the keywords because all @@ -63,66 +63,66 @@ void ActionRegister::add(string key,creator_pointer f,keywords_pointer k){ }; } -bool ActionRegister::check(string key){ +bool ActionRegister::check(string key) { if(m.count(key)>0 && mk.count(key)>0) return true; return false; } -Action* ActionRegister::create(const ActionOptions&ao){ +Action* ActionRegister::create(const ActionOptions&ao) { if(ao.line.size()<1)return NULL; - // Create a copy of the manual locally. The manual is - // then added to the ActionOptions. This allows us to + // Create a copy of the manual locally. The manual is + // then added to the ActionOptions. This allows us to // ensure during construction that all the keywords for // the action have been documented. In addition, we can // generate the documentation when the user makes an error // in the input. Action* action; - if( check(ao.line[0]) ){ - Keywords keys; mk[ao.line[0]](keys); - ActionOptions nao( ao,keys ); - action=m[ao.line[0]](nao); - keys.destroyData(); + if( check(ao.line[0]) ) { + Keywords keys; mk[ao.line[0]](keys); + ActionOptions nao( ao,keys ); + action=m[ao.line[0]](nao); + keys.destroyData(); } else action=NULL; return action; } -bool ActionRegister::printManual( const std::string& action, const bool& vimout ){ - if ( check(action) ){ - Keywords keys; mk[action](keys); - if( vimout ){ - printf("%s",action.c_str()); keys.print_vim(); printf("\n"); - } else { - keys.print_html(); - } - keys.destroyData(); - return true; +bool ActionRegister::printManual( const std::string& action, const bool& vimout ) { + if ( check(action) ) { + Keywords keys; mk[action](keys); + if( vimout ) { + printf("%s",action.c_str()); keys.print_vim(); printf("\n"); + } else { + keys.print_html(); + } + keys.destroyData(); + return true; } else { - return false; - } + return false; + } } -bool ActionRegister::printTemplate( const std::string& action, bool include_optional ){ - if( check(action) ){ - Keywords keys; mk[action](keys); - keys.print_template(action, include_optional); keys.destroyData(); - return true; +bool ActionRegister::printTemplate( const std::string& action, bool include_optional ) { + if( check(action) ) { + Keywords keys; mk[action](keys); + keys.print_template(action, include_optional); keys.destroyData(); + return true; } else { - return false; + return false; } } -std::ostream & operator<<(std::ostream &log,const ActionRegister&ar){ +std::ostream & operator<<(std::ostream &log,const ActionRegister&ar) { vector s; for(const auto & it : ar.m) s.push_back(it.first); sort(s.begin(),s.end()); - for(unsigned i=0;i #include "tools/Keywords.h" -namespace PLMD{ +namespace PLMD { class Action; class ActionOptions; @@ -42,7 +42,7 @@ class ActionOptions; /// If the same directive is used for different classes, it is automatically disabled /// to avoid random results. /// -class ActionRegister{ +class ActionRegister { /// Write on a stream the list of registered directives friend std::ostream &operator<<(std::ostream &,const ActionRegister&); /// Pointer to a function which, given the options, create an Action @@ -67,8 +67,8 @@ class ActionRegister{ /// \param ao object containing information for initialization, such as the full input line, a pointer to PlumedMain, etc Action* create(const ActionOptions&ao); /// Print out the keywords for an action in html/vim ready for input into the manual - bool printManual(const std::string& action, const bool& vimout); -/// Print out a template command for an action + bool printManual(const std::string& action, const bool& vimout); +/// Print out a template command for an action bool printTemplate(const std::string& action, bool include_optional); void remove(creator_pointer); ~ActionRegister(); diff --git a/src/core/ActionSet.cpp b/src/core/ActionSet.cpp index 9a1735dc20..35334eca21 100644 --- a/src/core/ActionSet.cpp +++ b/src/core/ActionSet.cpp @@ -22,35 +22,35 @@ #include "ActionSet.h" using namespace std; -namespace PLMD{ +namespace PLMD { ActionSet::ActionSet(PlumedMain&p): -plumed(p){ + plumed(p) { (void) plumed; // to suppress warning about "unused plumed" } ActionSet::~ActionSet() { - for(int i=size()-1;i>=0;i--) delete (*this)[i]; + for(int i=size()-1; i>=0; i--) delete (*this)[i]; } -void ActionSet::clearDelete(){ - for(int i=size()-1;i>=0;i--) delete (*this)[i]; +void ActionSet::clearDelete() { + for(int i=size()-1; i>=0; i--) delete (*this)[i]; clear(); } -std::string ActionSet::getLabelList() const{ +std::string ActionSet::getLabelList() const { std::string outlist; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { outlist+=dynamic_cast(p)->getLabel()+" "; }; return outlist; } -std::vector ActionSet::getLabelVector() const{ +std::vector ActionSet::getLabelVector() const { std::vector outlist; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { outlist.push_back(dynamic_cast(p)->getLabel()); }; return outlist; diff --git a/src/core/ActionSet.h b/src/core/ActionSet.h index 17b605dbf7..c2d48a2690 100644 --- a/src/core/ActionSet.h +++ b/src/core/ActionSet.h @@ -62,7 +62,7 @@ class ActionSet: T selectWithLabel(const std::string&s)const; /// get the labels in the list of actions in form of a string (useful to debug) std::string getLabelList() const; -/// get the labels in the form of a vector of strings +/// get the labels in the form of a vector of strings std::vector getLabelVector() const; }; @@ -70,9 +70,9 @@ class ActionSet: // INLINE IMPLEMENTATIONS: template -std::vector ActionSet::select()const{ +std::vector ActionSet::select()const { std::vector ret; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { T t=dynamic_cast(p); if(t) ret.push_back(t); }; @@ -80,8 +80,8 @@ std::vector ActionSet::select()const{ } template -T ActionSet::selectWithLabel(const std::string&s)const{ - for(const auto & p : (*this)){ +T ActionSet::selectWithLabel(const std::string&s)const { + for(const auto & p : (*this)) { T t=dynamic_cast(p); if(t && dynamic_cast(t)->getLabel()==s) return t; }; @@ -89,9 +89,9 @@ T ActionSet::selectWithLabel(const std::string&s)const{ } template -std::vector ActionSet::selectNot()const{ +std::vector ActionSet::selectNot()const { std::vector ret; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { T t=dynamic_cast(p); if(!t) ret.push_back(p); }; diff --git a/src/core/ActionSetup.cpp b/src/core/ActionSetup.cpp index 9bc9e527b0..1a0216a7b5 100644 --- a/src/core/ActionSetup.cpp +++ b/src/core/ActionSetup.cpp @@ -24,19 +24,19 @@ #include "ActionSet.h" #include "tools/Exception.h" -namespace PLMD{ +namespace PLMD { ActionSetup::ActionSetup(const ActionOptions&ao): Action(ao) { const ActionSet& actionset(plumed.getActionSet()); - for(const auto & p : actionset){ + for(const auto & p : actionset) { // check that all the preceeding actions are ActionSetup if( !dynamic_cast(p) ) error("Action " + getLabel() + " is a setup action, and should be only preceeded by other setup actions"); } } -void ActionSetup::registerKeywords( Keywords& keys ){ +void ActionSetup::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); keys.remove("LABEL"); } diff --git a/src/core/ActionSetup.h b/src/core/ActionSetup.h index bb9dfc5dc2..d76a0bea1a 100644 --- a/src/core/ActionSetup.h +++ b/src/core/ActionSetup.h @@ -24,7 +24,7 @@ #include "Action.h" -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT @@ -36,11 +36,11 @@ class ActionSetup : /// Constructor explicit ActionSetup(const ActionOptions&ao); /// Creator of keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Do nothing. - void calculate(){} + void calculate() {} /// Do nothing. - void apply(){} + void apply() {} }; } diff --git a/src/core/ActionWithArguments.cpp b/src/core/ActionWithArguments.cpp index b492410ca7..23b7729389 100644 --- a/src/core/ActionWithArguments.cpp +++ b/src/core/ActionWithArguments.cpp @@ -25,217 +25,217 @@ #include "PlumedMain.h" #include "ActionSet.h" #include -#ifdef __PLUMED_HAS_CREGEX +#ifdef __PLUMED_HAS_CREGEX #include -#include "regex.h" +#include "regex.h" #endif using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionWithArguments::registerKeywords(Keywords& keys){ +void ActionWithArguments::registerKeywords(Keywords& keys) { keys.reserve("numbered","ARG","the input for this action is the scalar output from one or more other actions. The particular scalars that you will use " - "are referenced using the label of the action. If the label appears on its own then it is assumed that the Action calculates " - "a single scalar value. The value of this scalar is thus used as the input to this new action. If * or *.* appears the " - "scalars calculated by all the proceding actions in the input file are taken. Some actions have multi-component outputs and " - "each component of the output has a specific label. For example a \\ref DISTANCE action labelled dist may have three componets " - "x, y and z. To take just the x component you should use dist.x, if you wish to take all three components then use dist.*." - "More information on the referencing of Actions can be found in the section of the manual on the PLUMED \\ref Syntax. " - "Scalar values can also be " - "referenced using POSIX regular expressions as detailed in the section on \\ref Regex. To use this feature you you must compile " - "PLUMED with the appropriate flag."); + "are referenced using the label of the action. If the label appears on its own then it is assumed that the Action calculates " + "a single scalar value. The value of this scalar is thus used as the input to this new action. If * or *.* appears the " + "scalars calculated by all the proceding actions in the input file are taken. Some actions have multi-component outputs and " + "each component of the output has a specific label. For example a \\ref DISTANCE action labelled dist may have three componets " + "x, y and z. To take just the x component you should use dist.x, if you wish to take all three components then use dist.*." + "More information on the referencing of Actions can be found in the section of the manual on the PLUMED \\ref Syntax. " + "Scalar values can also be " + "referenced using POSIX regular expressions as detailed in the section on \\ref Regex. To use this feature you you must compile " + "PLUMED with the appropriate flag."); } -void ActionWithArguments::parseArgumentList(const std::string&key,std::vector&arg){ - vector c; arg.clear(); parseVector(key,c); - if( c.size()==0 && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ){ +void ActionWithArguments::parseArgumentList(const std::string&key,std::vector&arg) { + vector c; arg.clear(); parseVector(key,c); + if( c.size()==0 && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) { std::string def; if( keywords.getDefaultValue(key,def) ) c.push_back( def ); } interpretArgumentList(c,arg); } -bool ActionWithArguments::parseArgumentList(const std::string&key,int i,std::vector&arg){ - vector c; - arg.clear(); +bool ActionWithArguments::parseArgumentList(const std::string&key,int i,std::vector&arg) { + vector c; + arg.clear(); if(parseNumberedVector(key,i,c)) { interpretArgumentList(c,arg); return true; } else return false; } -void ActionWithArguments::interpretArgumentList(const std::vector& c, std::vector&arg){ - for(unsigned i=0;ire_nsub==1,"I can parse with only one subexpression"); - pmatch = (regmatch_t*)malloc(sizeof(regmatch_t)*preg->re_nsub); - // select all the actions that have a value - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - for(unsigned j=0;j ss=all[j]->getComponentsVector(); - for(unsigned k=0;k str(ll); - strcpy(&str[0],ss[k].c_str()); - const char *ppstr=&str[0]; - if(!regexec(preg, ppstr , preg->re_nsub, pmatch, 0)) { - log.printf(" Something matched with \"%s\" : ",ss[k].c_str()); - do { - if (pmatch[0].rm_so != -1) { /* The regex is matching part of a string */ - char *submatch; - size_t matchlen = pmatch[0].rm_eo - pmatch[0].rm_so; - submatch = (char*)malloc(matchlen+1); - strncpy(submatch, ppstr+pmatch[0].rm_so, matchlen+1); - submatch[matchlen]='\0'; - log.printf(" subpattern %s\n", submatch); - // this is the match: try to see if it is a valid action - std::string putativeVal(submatch); - if( all[j]->exists(putativeVal) ){ - arg.push_back(all[j]->copyOutput(putativeVal)); - log.printf(" Action %s added! \n",putativeVal.c_str()); - } - free(submatch); - }; - ppstr += pmatch[0].rm_eo; /* Restart from last match */ - } while(!regexec(preg,ppstr,preg->re_nsub,pmatch,0)); - } - } - }; - regfree(preg); - free(preg); - free(pmatch); +void ActionWithArguments::interpretArgumentList(const std::vector& c, std::vector&arg) { + for(unsigned i=0; ire_nsub==1,"I can parse with only one subexpression"); + pmatch = (regmatch_t*)malloc(sizeof(regmatch_t)*preg->re_nsub); + // select all the actions that have a value + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + for(unsigned j=0; j ss=all[j]->getComponentsVector(); + for(unsigned k=0; k str(ll); + strcpy(&str[0],ss[k].c_str()); + const char *ppstr=&str[0]; + if(!regexec(preg, ppstr, preg->re_nsub, pmatch, 0)) { + log.printf(" Something matched with \"%s\" : ",ss[k].c_str()); + do { + if (pmatch[0].rm_so != -1) { /* The regex is matching part of a string */ + char *submatch; + size_t matchlen = pmatch[0].rm_eo - pmatch[0].rm_so; + submatch = (char*)malloc(matchlen+1); + strncpy(submatch, ppstr+pmatch[0].rm_so, matchlen+1); + submatch[matchlen]='\0'; + log.printf(" subpattern %s\n", submatch); + // this is the match: try to see if it is a valid action + std::string putativeVal(submatch); + if( all[j]->exists(putativeVal) ) { + arg.push_back(all[j]->copyOutput(putativeVal)); + log.printf(" Action %s added! \n",putativeVal.c_str()); + } + free(submatch); + }; + ppstr += pmatch[0].rm_eo; /* Restart from last match */ + } while(!regexec(preg,ppstr,preg->re_nsub,pmatch,0)); + } + } + }; + regfree(preg); + free(preg); + free(pmatch); #else - plumed_merror("Regexp support not compiled!"); + plumed_merror("Regexp support not compiled!"); #endif - }else{ - plumed_merror("did you want to use regexp to input arguments? enclose it between two round braces (...) with no spaces!"); - } - }else{ - std::size_t dot=c[i].find_first_of('.'); - string a=c[i].substr(0,dot); - string name=c[i].substr(dot+1); - if(c[i].find(".")!=string::npos){ // if it contains a dot: - if(a=="*" && name=="*"){ - // Take all values from all actions - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - for(unsigned j=0;jgetNumberOfComponents();++k) arg.push_back(all[j]->copyOutput(k)); - } - } else if ( name=="*"){ - // Take all the values from an action with a specific name - ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); - if(!action){ - std::string str=" (hint! the actions in this ActionSet are: "; - str+=plumed.getActionSet().getLabelList()+")"; - error("cannot find action named " + a + str); - } - if( action->getNumberOfComponents()==0 ) error("found " + a +".* indicating use all components calculated by action with label " + a + " but this action has no components"); - for(int k=0;kgetNumberOfComponents();++k) arg.push_back(action->copyOutput(k)); - } else if ( a=="*" ){ - // Take components from all actions with a specific name - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - unsigned nval=0; - for(unsigned j=0;jgetLabel() + "." + name; - if( all[j]->exists(flab) ){ arg.push_back(all[j]->copyOutput(flab)); nval++; } - } - if(nval==0) error("found no actions with a component called " + name ); - } else { - // Take values with a specific name - ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); - if(!action){ - std::string str=" (hint! the actions in this ActionSet are: "; - str+=plumed.getActionSet().getLabelList()+")"; - error("cannot find action named " + a +str); - } - if( !(action->exists(c[i])) ){ - std::string str=" (hint! the components in this actions are: "; - str+=action->getComponentsList()+")"; - error("action " + a + " has no component named " + name + str); - } ; - arg.push_back(action->copyOutput(c[i])); - } - } else { // if it doesn't contain a dot - if(c[i]=="*"){ - // Take all values from all actions - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - for(unsigned j=0;jgetNumberOfComponents();++k) arg.push_back(all[j]->copyOutput(k)); - } - } else { - ActionWithValue* action=plumed.getActionSet().selectWithLabel(c[i]); - if(!action){ - std::string str=" (hint! the actions in this ActionSet are: "; - str+=plumed.getActionSet().getLabelList()+")"; - error("cannot find action named " + c[i] + str ); - } - if( !(action->exists(c[i])) ){ - std::string str=" (hint! the components in this actions are: "; - str+=action->getComponentsList()+")"; - error("action " + c[i] + " has no component named " + c[i] +str); - }; - arg.push_back(action->copyOutput(c[i])); - } - } - } + } else { + plumed_merror("did you want to use regexp to input arguments? enclose it between two round braces (...) with no spaces!"); + } + } else { + std::size_t dot=c[i].find_first_of('.'); + string a=c[i].substr(0,dot); + string name=c[i].substr(dot+1); + if(c[i].find(".")!=string::npos) { // if it contains a dot: + if(a=="*" && name=="*") { + // Take all values from all actions + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + for(unsigned j=0; jgetNumberOfComponents(); ++k) arg.push_back(all[j]->copyOutput(k)); + } + } else if ( name=="*") { + // Take all the values from an action with a specific name + ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); + if(!action) { + std::string str=" (hint! the actions in this ActionSet are: "; + str+=plumed.getActionSet().getLabelList()+")"; + error("cannot find action named " + a + str); + } + if( action->getNumberOfComponents()==0 ) error("found " + a +".* indicating use all components calculated by action with label " + a + " but this action has no components"); + for(int k=0; kgetNumberOfComponents(); ++k) arg.push_back(action->copyOutput(k)); + } else if ( a=="*" ) { + // Take components from all actions with a specific name + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + unsigned nval=0; + for(unsigned j=0; jgetLabel() + "." + name; + if( all[j]->exists(flab) ) { arg.push_back(all[j]->copyOutput(flab)); nval++; } + } + if(nval==0) error("found no actions with a component called " + name ); + } else { + // Take values with a specific name + ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); + if(!action) { + std::string str=" (hint! the actions in this ActionSet are: "; + str+=plumed.getActionSet().getLabelList()+")"; + error("cannot find action named " + a +str); + } + if( !(action->exists(c[i])) ) { + std::string str=" (hint! the components in this actions are: "; + str+=action->getComponentsList()+")"; + error("action " + a + " has no component named " + name + str); + } ; + arg.push_back(action->copyOutput(c[i])); + } + } else { // if it doesn't contain a dot + if(c[i]=="*") { + // Take all values from all actions + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + for(unsigned j=0; jgetNumberOfComponents(); ++k) arg.push_back(all[j]->copyOutput(k)); + } + } else { + ActionWithValue* action=plumed.getActionSet().selectWithLabel(c[i]); + if(!action) { + std::string str=" (hint! the actions in this ActionSet are: "; + str+=plumed.getActionSet().getLabelList()+")"; + error("cannot find action named " + c[i] + str ); + } + if( !(action->exists(c[i])) ) { + std::string str=" (hint! the components in this actions are: "; + str+=action->getComponentsList()+")"; + error("action " + c[i] + " has no component named " + c[i] +str); + }; + arg.push_back(action->copyOutput(c[i])); + } + } + } } } -void ActionWithArguments::expandArgKeywordInPDB( PDB& pdb ){ +void ActionWithArguments::expandArgKeywordInPDB( PDB& pdb ) { std::vector pdb_remark=pdb.getRemark(); std::vector arg_names; bool found=Tools::parseVector(pdb_remark,"ARG",arg_names); - if( found ){ - std::vector arg_vals; - interpretArgumentList( arg_names, arg_vals ); - std::string new_args="ARG=" + arg_vals[0]->getName(); - for(unsigned i=1;igetName(); - pdb.setArgKeyword( new_args ); + if( found ) { + std::vector arg_vals; + interpretArgumentList( arg_names, arg_vals ); + std::string new_args="ARG=" + arg_vals[0]->getName(); + for(unsigned i=1; igetName(); + pdb.setArgKeyword( new_args ); } } -void ActionWithArguments::requestArguments(const vector &arg){ +void ActionWithArguments::requestArguments(const vector &arg) { plumed_massert(!lockRequestArguments,"requested argument list can only be changed in the prepare() method"); arguments=arg; clearDependencies(); std::string fullname,name; - for(unsigned i=0;igetName(); - if(fullname.find(".")!=string::npos){ - std::size_t dot=fullname.find_first_of('.'); - name=fullname.substr(0,dot); - } else { - name=fullname; - } - ActionWithValue* action=plumed.getActionSet().selectWithLabel(name); - plumed_massert(action,"cannot find action named (in requestArguments - this is weird)" + name); - addDependency(action); + for(unsigned i=0; igetName(); + if(fullname.find(".")!=string::npos) { + std::size_t dot=fullname.find_first_of('.'); + name=fullname.substr(0,dot); + } else { + name=fullname; + } + ActionWithValue* action=plumed.getActionSet().selectWithLabel(name); + plumed_massert(action,"cannot find action named (in requestArguments - this is weird)" + name); + addDependency(action); } } @@ -243,21 +243,21 @@ ActionWithArguments::ActionWithArguments(const ActionOptions&ao): Action(ao), lockRequestArguments(false) { - if( keywords.exists("ARG") && !keywords.exists("DATA") ){ - vector arg; - parseArgumentList("ARG",arg); + if( keywords.exists("ARG") && !keywords.exists("DATA") ) { + vector arg; + parseArgumentList("ARG",arg); - if(!arg.empty()){ - log.printf(" with arguments"); - for(unsigned i=0;igetName().c_str()); - log.printf("\n"); - } - requestArguments(arg); + if(!arg.empty()) { + log.printf(" with arguments"); + for(unsigned i=0; igetName().c_str()); + log.printf("\n"); + } + requestArguments(arg); } } -void ActionWithArguments::calculateNumericalDerivatives( ActionWithValue* a ){ - if(!a){ +void ActionWithArguments::calculateNumericalDerivatives( ActionWithValue* a ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"cannot compute numerical derivatives for an action without values"); } @@ -265,24 +265,24 @@ void ActionWithArguments::calculateNumericalDerivatives( ActionWithValue* a ){ const int nval=a->getNumberOfComponents(); const int npar=arguments.size(); std::vector value (nval*npar); - for(int i=0;iget(); arguments[i]->set(arg0+sqrt(epsilon)); a->calculate(); arguments[i]->set(arg0); - for(int j=0;jgetOutputQuantity(j); } } a->calculate(); a->clearDerivatives(); - for(int j=0;jcopyOutput(j); - if( v->hasDerivatives() ) for(int i=0;iaddDerivative(i,(value[i*nval+j]-a->getOutputQuantity(j))/sqrt(epsilon)); + if( v->hasDerivatives() ) for(int i=0; iaddDerivative(i,(value[i*nval+j]-a->getOutputQuantity(j))/sqrt(epsilon)); } } -double ActionWithArguments::getProjection(unsigned i,unsigned j)const{ +double ActionWithArguments::getProjection(unsigned i,unsigned j)const { plumed_massert(i& forces ){ - for(unsigned i=0;iaddForce( forces[i] ); +void ActionWithArguments::addForcesOnArguments( const std::vector& forces ) { + for(unsigned i=0; iaddForce( forces[i] ); } } diff --git a/src/core/ActionWithArguments.h b/src/core/ActionWithArguments.h index a4036f99c9..47a14b7607 100644 --- a/src/core/ActionWithArguments.h +++ b/src/core/ActionWithArguments.h @@ -26,16 +26,16 @@ #include "Value.h" #include -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT -This is used to create PLMD::Action objects that take the output from some other Action as input. +This is used to create PLMD::Action objects that take the output from some other Action as input. This is used in PLMD::Function and PLMD::Bias - PLMD::Action objects that inherit from PLMD::ActionWithArguments take + PLMD::Action objects that inherit from PLMD::ActionWithArguments take values and components calculated in other PLMD::Action objects and - use this information to calculate some new function. If you have - only one list of arguments you should use the reserved keyword ARG + use this information to calculate some new function. If you have + only one list of arguments you should use the reserved keyword ARG when you use parseArgumentList. */ @@ -60,7 +60,7 @@ class ActionWithArguments: virtual unsigned getNumberOfArguments() const ; /// Takes the difference taking into account pbc for arg i double difference(int, double, double) const; -/// Takes one value and brings it back into the pbc of argument i +/// Takes one value and brings it back into the pbc of argument i double bringBackInPbc(int i,double d1)const; /// Parse a list of arguments void parseArgumentList(const std::string&key,std::vector&args); @@ -72,9 +72,9 @@ class ActionWithArguments: void addForcesOnArguments( const std::vector& forces ); public: explicit ActionWithArguments(const ActionOptions&); - virtual ~ActionWithArguments(){} + virtual ~ActionWithArguments() {} /// Calculate the numerical derivatives -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. The default will be correct for the vast majority of cases virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); void lockRequests(); @@ -87,7 +87,7 @@ class ActionWithArguments: inline -Value* ActionWithArguments::getPntrToArgument( const unsigned n ){ +Value* ActionWithArguments::getPntrToArgument( const unsigned n ) { return arguments[n]; } @@ -97,27 +97,27 @@ double ActionWithArguments::getArgument(const unsigned n) const { } inline -unsigned ActionWithArguments::getNumberOfArguments()const{ +unsigned ActionWithArguments::getNumberOfArguments()const { return arguments.size(); } inline -double ActionWithArguments::difference(int i,double d1,double d2)const{ +double ActionWithArguments::difference(int i,double d1,double d2)const { return arguments[i]->difference(d1,d2); } inline -double ActionWithArguments::bringBackInPbc(int i,double d1)const{ +double ActionWithArguments::bringBackInPbc(int i,double d1)const { return arguments[i]->bringBackInPbc(d1); } inline -void ActionWithArguments::lockRequests(){ +void ActionWithArguments::lockRequests() { lockRequestArguments=true; } inline -void ActionWithArguments::unlockRequests(){ +void ActionWithArguments::unlockRequests() { lockRequestArguments=false; } diff --git a/src/core/ActionWithValue.cpp b/src/core/ActionWithValue.cpp index 1a8d821116..bc92a9410d 100644 --- a/src/core/ActionWithValue.cpp +++ b/src/core/ActionWithValue.cpp @@ -24,32 +24,32 @@ #include "tools/OpenMP.h" using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionWithValue::registerKeywords(Keywords& keys){ +void ActionWithValue::registerKeywords(Keywords& keys) { keys.setComponentsIntroduction("By default the value of the calculated quantity can be referenced elsewhere in the " "input file by using the label of the action. Alternatively this Action can be used " "to be used to calculate the following quantities by employing the keywords listed " - "below. These quanties can be referenced elsewhere in the input by using this Action's " + "below. These quanties can be referenced elsewhere in the input by using this Action's " "label followed by a dot and the name of the quantity required from the list below."); keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically"); } -void ActionWithValue::noAnalyticalDerivatives(Keywords& keys){ - keys.remove("NUMERICAL_DERIVATIVES"); - keys.addFlag("NUMERICAL_DERIVATIVES",true,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used"); +void ActionWithValue::noAnalyticalDerivatives(Keywords& keys) { + keys.remove("NUMERICAL_DERIVATIVES"); + keys.addFlag("NUMERICAL_DERIVATIVES",true,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used"); } -void ActionWithValue::componentsAreNotOptional(Keywords& keys){ - keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quanties can " - "be referenced elsewhere in the input by using this Action's label followed by a " - "dot and the name of the quantity required from the list below."); +void ActionWithValue::componentsAreNotOptional(Keywords& keys) { + keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quanties can " + "be referenced elsewhere in the input by using this Action's label followed by a " + "dot and the name of the quantity required from the list below."); } -void ActionWithValue::useCustomisableComponents(Keywords& keys){ - keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the " - "actions input file. However, in addition to these customizable components the " - "following quantities will always be output"); +void ActionWithValue::useCustomisableComponents(Keywords& keys) { + keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the " + "actions input file. However, in addition to these customizable components the " + "following quantities will always be output"); } ActionWithValue::ActionWithValue(const ActionOptions&ao): @@ -61,35 +61,35 @@ ActionWithValue::ActionWithValue(const ActionOptions&ao): if(numericalDerivatives) log.printf(" using numerical derivatives\n"); } -ActionWithValue::~ActionWithValue(){ - for(unsigned i=0;iclearInputForce(); +void ActionWithValue::clearInputForces() { + for(unsigned i=0; iclearInputForce(); } -void ActionWithValue::clearDerivatives(){ +void ActionWithValue::clearDerivatives() { unsigned nt = OpenMP::getGoodNumThreads(values); #pragma omp parallel num_threads(nt) - { + { #pragma omp for - for(unsigned i=0;iclearDerivatives(); + for(unsigned i=0; iclearDerivatives(); } -} +} // -- These are the routine for copying the value pointers to other classes -- // bool ActionWithValue::exists( const std::string& name ) const { - for(unsigned i=0;iname==name) return true; + for(unsigned i=0; iname==name) return true; } return false; } Value* ActionWithValue::copyOutput( const std::string& name ) const { - for(unsigned i=0;iname==name) return values[i]; + for(unsigned i=0; iname==name) return values[i]; } plumed_merror("there is no pointer with name " + name); return NULL; @@ -102,30 +102,30 @@ Value* ActionWithValue::copyOutput( const unsigned& n ) const { // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- // -void ActionWithValue::addValue(){ +void ActionWithValue::addValue() { plumed_massert(values.empty(),"You have already added the default value for this action"); values.push_back(new Value(this,getLabel(), false ) ); } -void ActionWithValue::addValueWithDerivatives(){ +void ActionWithValue::addValueWithDerivatives() { plumed_massert(values.empty(),"You have already added the default value for this action"); values.push_back(new Value(this,getLabel(), true ) ); } -void ActionWithValue::setNotPeriodic(){ +void ActionWithValue::setNotPeriodic() { plumed_massert(values.size()==1,"The number of components is not equal to one"); plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); values[0]->min=0; values[0]->max=0; values[0]->setupPeriodicity(); } -void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ){ +void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) { plumed_massert(values.size()==1,"The number of components is not equal to one"); plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); values[0]->setDomain( min, max ); } -Value* ActionWithValue::getPntrToValue(){ +Value* ActionWithValue::getPntrToValue() { plumed_dbg_massert(values.size()==1,"The number of components is not equal to one"); plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default"); return values[0]; @@ -133,34 +133,34 @@ Value* ActionWithValue::getPntrToValue(){ // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- // -void ActionWithValue::addComponent( const std::string& name ){ - if( !keywords.outputComponentExists(name,true) ){ - warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " - "registerKeywords as described in the developer docs."); +void ActionWithValue::addComponent( const std::string& name ) { + if( !keywords.outputComponentExists(name,true) ) { + warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " + "registerKeywords as described in the developer docs."); } std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname!=getLabel(),"Cannot mix single values with components"); - plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" - "Remove the line addComponent(\"bias\") from your bias."); - plumed_massert(values[i]->name!=thename,"there is already a value with this name"); + for(unsigned i=0; iname!=getLabel(),"Cannot mix single values with components"); + plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" + "Remove the line addComponent(\"bias\") from your bias."); + plumed_massert(values[i]->name!=thename,"there is already a value with this name"); } values.push_back(new Value(this,thename, false ) ); std::string msg=" added component to this action: "+thename+" \n"; log.printf(msg.c_str()); } -void ActionWithValue::addComponentWithDerivatives( const std::string& name ){ - if( !keywords.outputComponentExists(name,true) ){ - warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " - "registerKeywords as described in the developer doc."); +void ActionWithValue::addComponentWithDerivatives( const std::string& name ) { + if( !keywords.outputComponentExists(name,true) ) { + warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " + "registerKeywords as described in the developer doc."); } std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname!=getLabel(),"Cannot mix single values with components"); - plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" - "Remove the line addComponentWithDerivatives(\"bias\") from your bias."); - plumed_massert(values[i]->name!=thename,"there is already a value with this name"); + for(unsigned i=0; iname!=getLabel(),"Cannot mix single values with components"); + plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" + "Remove the line addComponentWithDerivatives(\"bias\") from your bias."); + plumed_massert(values[i]->name!=thename,"there is already a value with this name"); } values.push_back(new Value(this,thename, true ) ); std::string msg=" added component to this action: "+thename+" \n"; @@ -170,8 +170,8 @@ void ActionWithValue::addComponentWithDerivatives( const std::string& name ){ int ActionWithValue::getComponent( const std::string& name ) const { plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value"); std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname==thename) return i; + for(unsigned i=0; iname==thename) return i; } plumed_merror("there is no component with name " + name); return -1; @@ -179,55 +179,55 @@ int ActionWithValue::getComponent( const std::string& name ) const { std::string ActionWithValue::getComponentsList( ) const { std::string complist; - for(unsigned i=0;iname+" "; + for(unsigned i=0; iname+" "; } return complist; } std::vector ActionWithValue::getComponentsVector( ) const { std::vector complist; - for(unsigned i=0;iname); + for(unsigned i=0; iname); } return complist; } -void ActionWithValue::componentIsNotPeriodic( const std::string& name ){ +void ActionWithValue::componentIsNotPeriodic( const std::string& name ) { int kk=getComponent(name); values[kk]->min=0; values[kk]->max=0; values[kk]->setupPeriodicity(); } -void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ){ +void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) { int kk=getComponent(name); values[kk]->setDomain(min,max); } -void ActionWithValue::setGradientsIfNeeded(){ +void ActionWithValue::setGradientsIfNeeded() { if(isOptionOn("GRADIENTS")) { - for(unsigned i=0;isetGradients(); + for(unsigned i=0; isetGradients(); } } -void ActionWithValue::turnOnDerivatives(){ +void ActionWithValue::turnOnDerivatives() { // Turn on the derivatives noderiv=false; - // Resize the derivatives - for(unsigned i=0;iresizeDerivatives( getNumberOfDerivatives() ); + // Resize the derivatives + for(unsigned i=0; iresizeDerivatives( getNumberOfDerivatives() ); // And turn on the derivatives in all actions on which we are dependent - for(unsigned i=0;i( getDependencies()[i] ); - if(vv) vv->turnOnDerivatives(); + for(unsigned i=0; i( getDependencies()[i] ); + if(vv) vv->turnOnDerivatives(); } } -Value* ActionWithValue::getPntrToComponent( const std::string& name ){ +Value* ActionWithValue::getPntrToComponent( const std::string& name ) { int kk=getComponent(name); - return values[kk]; + return values[kk]; } -Value* ActionWithValue::getPntrToComponent( int n ){ +Value* ActionWithValue::getPntrToComponent( int n ) { plumed_dbg_massert(n -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT -Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some derivatives. -This is used for PLMD::Bias, PLMD::Colvar and PLMD::Function +Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some derivatives. +This is used for PLMD::Bias, PLMD::Colvar and PLMD::Function The vast majority of the PLMD::Action objects that are implemented in plumed calculate some quantity or a set of quantities. This could be @@ -43,26 +43,26 @@ quantities between PLMD::Actions. When you are deciding what quantities your new PLMD::Action will need to store using PLMD::ActionWithValue you must ask yourself the following two questions: -- Do I need to differentiate my output quantities -- Is my PLMD::Action calculating a single thing or does the output have multiple components +- Do I need to differentiate my output quantities +- Is my PLMD::Action calculating a single thing or does the output have multiple components If the answer to the first of these questions is yes then you must setup your values -you using either PLMD::ActionWithValue::addValueWithDerivatives() or -PLMD::ActionWithValue::addComponentWithDerivatives. If the answer is no you +you using either PLMD::ActionWithValue::addValueWithDerivatives() or +PLMD::ActionWithValue::addComponentWithDerivatives. If the answer is no you can set up values using PLMD::ActionWithValue::addValue() or PLMD::ActionWithValue::addComponent(). The precise routine you use to setup your values will depend on your answer to the -second question. As you are probably aware if the output of your PLMD::Action is a -single quantity you can reference that quantity in the input file using the label of the -PLMD::Action it was calculated in. If your action outputs only one quantity -we call that quantity the value of the Action. To set the value and get pointers to it -you should use the set of routines that have the word value in the name . If, by contrast, +second question. As you are probably aware if the output of your PLMD::Action is a +single quantity you can reference that quantity in the input file using the label of the +PLMD::Action it was calculated in. If your action outputs only one quantity +we call that quantity the value of the Action. To set the value and get pointers to it +you should use the set of routines that have the word value in the name . If, by contrast, your PLMD::Action calculates multiple quantities then these quantities are referenced in input using the -label.component syntax. We refer to these multiple quantities the components +label.component syntax. We refer to these multiple quantities the components of the PLMD::Action. Perhaps unsurprisingly, when you manipulate the components of an PLMD::Action you should use the routines with the word component in the name. */ -class ActionWithValue : +class ActionWithValue : public virtual Action { private: @@ -112,7 +112,7 @@ class ActionWithValue : explicit ActionWithValue(const ActionOptions&ao); ~ActionWithValue(); -/// Register all the relevant keywords for the action +/// Register all the relevant keywords for the action static void registerKeywords( Keywords& keys ); /// Insist that numerical derivatives should always be used for an action and make this fact appear in the manual static void noAnalyticalDerivatives(Keywords& keys); @@ -125,7 +125,7 @@ class ActionWithValue : /// Get the value of one of the components of the PLMD::Action double getOutputQuantity( const unsigned j ) const ; /// Get the value with a specific name (N.B. if there is no such value this returns zero) - double getOutputQuantity( const std::string& name ) const ; + double getOutputQuantity( const std::string& name ) const ; // --- Routines for passing stuff to ActionWithArguments -- // @@ -133,14 +133,14 @@ class ActionWithValue : /// You should not use it when manipulating components. bool exists( const std::string& name ) const; /// Return a pointer to the value with name (this is used to retrieve values in other PLMD::Actions) -/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use +/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use /// getPntrToComponent instead. Value* copyOutput( const std::string&name ) const; /// Return a pointer to the value with this number (this is used to retrieve values in other PLMD::Actions) -/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use +/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use /// getPntrToComponent instead. Value* copyOutput( const unsigned& n ) const; -/// get a string that contains all the available components +/// get a string that contains all the available components std::string getComponentsList( ) const ; /// get a vector that contains the label for all the components std::vector getComponentsVector( ) const ; @@ -154,17 +154,17 @@ class ActionWithValue : void clearInputForces(); /// Clear the derivatives of values wrt parameters virtual void clearDerivatives(); -/// Calculate the gradients and store them for all the values (need for projections) +/// Calculate the gradients and store them for all the values (need for projections) void setGradientsIfNeeded(); /// Set the value void setValue(Value*,double); /// Check if numerical derivatives should be used bool checkNumericalDerivatives() const ; -/// This forces the class to use numerical derivatives +/// This forces the class to use numerical derivatives void useNumericalDerivatives(); // These are things for using vectors of values as fields - virtual void checkFieldsAllowed(){ error("cannot use this action as a field"); } - virtual unsigned getNumberOfDerivatives()=0; + virtual void checkFieldsAllowed() { error("cannot use this action as a field"); } + virtual unsigned getNumberOfDerivatives()=0; /// Activate the calculation of derivatives virtual void turnOnDerivatives(); }; @@ -178,14 +178,14 @@ double ActionWithValue::getOutputQuantity(const unsigned j) const { inline double ActionWithValue::getOutputQuantity( const std::string& name ) const { std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname==thename ) return values[i]->value; } return 0.0; } inline -void ActionWithValue::setValue(const double& d){ +void ActionWithValue::setValue(const double& d) { plumed_massert(values.size()==1, "cannot use setValue in multi-component actions"); plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); values[0]->set(d); @@ -197,7 +197,7 @@ int ActionWithValue::getNumberOfComponents() const { } inline -void ActionWithValue::useNumericalDerivatives(){ +void ActionWithValue::useNumericalDerivatives() { plumed_massert( keywords.exists("NUMERICAL_DERIVATIVES"), "numerical derivatives are not permitted for this action" ); numericalDerivatives=true; } @@ -210,7 +210,7 @@ bool ActionWithValue::checkNumericalDerivatives() const { inline bool ActionWithValue::doNotCalculateDerivatives() const { return noderiv; -} +} diff --git a/src/core/ActionWithVirtualAtom.cpp b/src/core/ActionWithVirtualAtom.cpp index da6d8a6afe..668ea7e795 100644 --- a/src/core/ActionWithVirtualAtom.cpp +++ b/src/core/ActionWithVirtualAtom.cpp @@ -24,9 +24,9 @@ using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionWithVirtualAtom::registerKeywords(Keywords& keys){ +void ActionWithVirtualAtom::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionAtomistic::registerKeywords(keys); keys.add("atoms","ATOMS","the list of atoms which are involved the virtual atom's definition"); @@ -41,71 +41,71 @@ ActionWithVirtualAtom::ActionWithVirtualAtom(const ActionOptions&ao): log.printf(" serial associated to this virtual atom is %u\n",index.serial()); } -ActionWithVirtualAtom::~ActionWithVirtualAtom(){ +ActionWithVirtualAtom::~ActionWithVirtualAtom() { atoms.removeVirtualAtom(this); } -void ActionWithVirtualAtom::apply(){ +void ActionWithVirtualAtom::apply() { Vector & f(atoms.forces[index.index()]); - for(unsigned i=0;i & a){ +void ActionWithVirtualAtom::requestAtoms(const std::vector & a) { ActionAtomistic::requestAtoms(a); derivatives.resize(a.size()); } -void ActionWithVirtualAtom::setGradients(){ +void ActionWithVirtualAtom::setGradients() { gradients.clear(); - for(unsigned i=0;igradients){ + for(const auto & p : a->gradients) { gradients[p.first]+=matmul(derivatives[i],p.second); } - // this case if the atom is a normal one + // this case if the atom is a normal one } else { gradients[an]+=derivatives[i]; } } } -void ActionWithVirtualAtom::setBoxDerivatives(const std::vector &d){ +void ActionWithVirtualAtom::setBoxDerivatives(const std::vector &d) { boxDerivatives=d; plumed_assert(d.size()==3); // Subtract the trivial part coming from a distorsion applied to the ghost atom first. // Notice that this part alone should exactly cancel the already accumulated virial // due to forces on this atom. Vector pos=atoms.positions[index.index()]; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) boxDerivatives[j][i][j]+=pos[i]; + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) boxDerivatives[j][i][j]+=pos[i]; } -void ActionWithVirtualAtom::setBoxDerivativesNoPbc(){ +void ActionWithVirtualAtom::setBoxDerivativesNoPbc() { std::vector bd(3); - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) for(unsigned k=0;k<3;k++){ + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) for(unsigned k=0; k<3; k++) { // Notice that this expression is very similar to the one used in Colvar::setBoxDerivativesNoPbc(). // Indeed, we have the negative of a sum over dependent atoms (l) of the external product between positions // and derivatives. Notice that this only works only when Pbc have not been used to compute // derivatives. - for(unsigned l=0;l &d){ +void ActionWithVirtualAtom::setAtomsDerivatives(const std::vector &d) { derivatives=d; } inline -const std::map & ActionWithVirtualAtom::getGradients()const{ +const std::map & ActionWithVirtualAtom::getGradients()const { return gradients; } diff --git a/src/core/Atoms.cpp b/src/core/Atoms.cpp index ec0ba9c58f..8841bbefeb 100644 --- a/src/core/Atoms.cpp +++ b/src/core/Atoms.cpp @@ -67,111 +67,111 @@ Atoms::Atoms(PlumedMain&plumed): mdatoms=MDAtomsBase::create(sizeof(double)); } -Atoms::~Atoms(){ - if(actions.size()>0){ +Atoms::~Atoms() { + if(actions.size()>0) { std::cerr<<"WARNING: there is some inconsistency in action added to atoms, as some of them were not properly destroyed. This might indicate an internal bug!!\n"; } delete mdatoms; delete &pbc; } -void Atoms::startStep(){ +void Atoms::startStep() { collectEnergy=false; energyHasBeenSet=false; positionsHaveBeenSet=0; massesHaveBeenSet=false; chargesHaveBeenSet=false; boxHasBeenSet=false; forcesHaveBeenSet=0; virialHasBeenSet=false; dataCanBeSet=true; } -void Atoms::setBox(void*p){ +void Atoms::setBox(void*p) { mdatoms->setBox(p); Tensor b; mdatoms->getBox(b); boxHasBeenSet=true; } -void Atoms::setPositions(void*p){ - plumed_massert( dataCanBeSet ,"setPositions must be called after setStep in MD code interface"); +void Atoms::setPositions(void*p) { + plumed_massert( dataCanBeSet,"setPositions must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL position pointer with non-zero local atoms"); mdatoms->setp(p); positionsHaveBeenSet=3; } -void Atoms::setMasses(void*p){ - plumed_massert( dataCanBeSet ,"setMasses must be called after setStep in MD code interface"); +void Atoms::setMasses(void*p) { + plumed_massert( dataCanBeSet,"setMasses must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL mass pointer with non-zero local atoms"); mdatoms->setm(p); massesHaveBeenSet=true; } -void Atoms::setCharges(void*p){ +void Atoms::setCharges(void*p) { plumed_massert( dataCanBeSet, "setCharges must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL charges pointer with non-zero local atoms"); mdatoms->setc(p); chargesHaveBeenSet=true; } -void Atoms::setVirial(void*p){ - plumed_massert( dataCanBeSet ,"setVirial must be called after setStep in MD code interface"); +void Atoms::setVirial(void*p) { + plumed_massert( dataCanBeSet,"setVirial must be called after setStep in MD code interface"); mdatoms->setVirial(p); virialHasBeenSet=true; - + } -void Atoms::setEnergy(void*p){ - plumed_massert( dataCanBeSet ,"setEnergy must be called after setStep in MD code interface"); +void Atoms::setEnergy(void*p) { + plumed_massert( dataCanBeSet,"setEnergy must be called after setStep in MD code interface"); MD2double(p,md_energy); md_energy*=MDUnits.getEnergy()/units.getEnergy(); energyHasBeenSet=true; } -void Atoms::setForces(void*p){ - plumed_massert( dataCanBeSet ,"setForces must be called after setStep in MD code interface"); +void Atoms::setForces(void*p) { + plumed_massert( dataCanBeSet,"setForces must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL force pointer with non-zero local atoms"); forcesHaveBeenSet=3; mdatoms->setf(p); } -void Atoms::setPositions(void*p,int i){ - plumed_massert( dataCanBeSet ,"setPositions must be called after setStep in MD code interface"); +void Atoms::setPositions(void*p,int i) { + plumed_massert( dataCanBeSet,"setPositions must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL positions pointer with non-zero local atoms"); mdatoms->setp(p,i); positionsHaveBeenSet++; } -void Atoms::setForces(void*p,int i){ - plumed_massert( dataCanBeSet ,"setForces must be called after setStep in MD code interface"); +void Atoms::setForces(void*p,int i) { + plumed_massert( dataCanBeSet,"setForces must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL force pointer with non-zero local atoms"); mdatoms->setf(p,i); forcesHaveBeenSet++; } -void Atoms::share(){ +void Atoms::share() { std::set unique; // At first step I scatter all the atoms so as to store their mass and charge // Notice that this works with the assumption that charges and masses are // not changing during the simulation! - if(!massAndChargeOK && shareMassAndChargeOnlyAtFirstStep){ + if(!massAndChargeOK && shareMassAndChargeOnlyAtFirstStep) { shareAll(); return; } - for(unsigned i=0;iisActive()) { - if(dd && shuffledAtoms>0){ - unique.insert(actions[i]->getUnique().begin(),actions[i]->getUnique().end()); + for(unsigned i=0; iisActive()) { + if(dd && shuffledAtoms>0) { + unique.insert(actions[i]->getUnique().begin(),actions[i]->getUnique().end()); + } + if(!actions[i]->getUnique().empty()) atomsNeeded=true; } - if(!actions[i]->getUnique().empty()) atomsNeeded=true; - } share(unique); } -void Atoms::shareAll(){ +void Atoms::shareAll() { std::set unique; if(dd && shuffledAtoms>0) - for(int i=0;i& unique){ +void Atoms::share(const std::set& unique) { plumed_assert( positionsHaveBeenSet==3 && massesHaveBeenSet ); virial.zero(); - if(zeroallforces || int(gatindex.size())==natoms){ - for(int i=0;igetBox(box); @@ -179,7 +179,7 @@ void Atoms::share(const std::set& unique){ atomsNeeded=false; - if(int(gatindex.size())==natoms && shuffledAtoms==0){ + if(int(gatindex.size())==natoms && shuffledAtoms==0) { // faster version, which retrieves all atoms mdatoms->getPositions(0,natoms,positions); } else { @@ -188,7 +188,7 @@ void Atoms::share(const std::set& unique){ } // how many double per atom should be scattered: int ndata=3; - if(!massAndChargeOK){ + if(!massAndChargeOK) { ndata=5; masses.assign(masses.size(),NAN); charges.assign(charges.size(),NAN); @@ -196,34 +196,34 @@ void Atoms::share(const std::set& unique){ mdatoms->getMasses(gatindex,masses); } - if(dd && shuffledAtoms>0){ - if(dd.async){ - for(unsigned i=0;i0) { + if(dd.async) { + for(unsigned i=0; i=0){ + for(const auto & p : unique) { + if(dd.g2l[p.index()]>=0) { dd.indexToBeSent[count]=p.index(); dd.positionsToBeSent[ndata*count+0]=positions[p.index()][0]; dd.positionsToBeSent[ndata*count+1]=positions[p.index()][1]; dd.positionsToBeSent[ndata*count+2]=positions[p.index()][2]; - if(!massAndChargeOK){ + if(!massAndChargeOK) { dd.positionsToBeSent[ndata*count+3]=masses[p.index()]; dd.positionsToBeSent[ndata*count+4]=charges[p.index()]; } count++; } } - if(dd.async){ + if(dd.async) { asyncSent=true; dd.mpi_request_positions.resize(dd.Get_size()); dd.mpi_request_index.resize(dd.Get_size()); - for(int i=0;i counts(n); vector displ(n); @@ -231,17 +231,17 @@ void Atoms::share(const std::set& unique){ vector displ5(n); dd.Allgather(count,counts); displ[0]=0; - for(int i=1;i& unique){ } } -void Atoms::wait(){ +void Atoms::wait() { dataCanBeSet=false; // Everything should be set by this stage // How many double per atom should be scattered int ndata=3; if(!massAndChargeOK)ndata=5; - if(dd){ + if(dd) { dd.Bcast(box,0); } pbc.setBox(box); if(collectEnergy) energy=md_energy; - if(dd && shuffledAtoms>0){ + if(dd && shuffledAtoms>0) { // receive toBeReceived - if(asyncSent){ + if(asyncSent) { Communicator::Status status; int count=0; - for(int i=0;i(); dd.Recv(&dd.positionsToBeReceived[ndata*count],dd.positionsToBeReceived.size()-ndata*count,i,667); count+=c; } - for(int i=0;iepsilon){ - double alpha=1.0-forceOnEnergy; - mdatoms->rescaleForces(gatindex,alpha); + if(forceOnEnergy*forceOnEnergy>epsilon) { + double alpha=1.0-forceOnEnergy; + mdatoms->rescaleForces(gatindex,alpha); } mdatoms->updateForces(gatindex,forces); - if( !plumed.novirial && dd.Get_rank()==0 ){ - plumed_assert( virialHasBeenSet ); - mdatoms->updateVirial(virial); + if( !plumed.novirial && dd.Get_rank()==0 ) { + plumed_assert( virialHasBeenSet ); + mdatoms->updateVirial(virial); } } -void Atoms::setNatoms(int n){ +void Atoms::setNatoms(int n) { natoms=n; positions.resize(n); forces.resize(n); masses.resize(n); charges.resize(n); gatindex.resize(n); - for(unsigned i=0;igetRealPrecision(); } -void Atoms::MD2double(const void*m,double&d)const{ +void Atoms::MD2double(const void*m,double&d)const { plumed_assert(mdatoms); mdatoms->MD2double(m,d); } -void Atoms::double2MD(const double&d,void*m)const{ +void Atoms::double2MD(const double&d,void*m)const { plumed_assert(mdatoms); mdatoms->double2MD(d,m); } -void Atoms::updateUnits(){ +void Atoms::updateUnits() { mdatoms->setUnits(units,MDUnits); } -void Atoms::setTimeStep(void*p){ +void Atoms::setTimeStep(void*p) { MD2double(p,timestep); } -double Atoms::getTimeStep()const{ +double Atoms::getTimeStep()const { return timestep/units.getTime()*MDUnits.getTime(); } -void Atoms::setKbT(void*p){ +void Atoms::setKbT(void*p) { MD2double(p,kbT); } -double Atoms::getKbT()const{ +double Atoms::getKbT()const { return kbT/units.getEnergy()*MDUnits.getEnergy(); } -void Atoms::createFullList(int*n){ +void Atoms::createFullList(int*n) { vector fullListTmp; - for(unsigned i=0;iisActive()) - fullListTmp.insert(fullListTmp.end(),actions[i]->getUnique().begin(),actions[i]->getUnique().end()); + for(unsigned i=0; iisActive()) + fullListTmp.insert(fullListTmp.end(),actions[i]->getUnique().begin(),actions[i]->getUnique().end()); std::sort(fullListTmp.begin(),fullListTmp.end()); int nn=std::unique(fullListTmp.begin(),fullListTmp.end())-fullListTmp.begin(); fullList.resize(nn); - for(int i=0;i&a){ +void Atoms::insertGroup(const std::string&name,const std::vector&a) { plumed_massert(groups.count(name)==0,"group named "+name+" already exists"); groups[name]=a; } -void Atoms::removeGroup(const std::string&name){ +void Atoms::removeGroup(const std::string&name) { plumed_massert(groups.count(name)==1,"cannot remove group named "+name); groups.erase(name); } -void Atoms::writeBinary(std::ostream&o)const{ +void Atoms::writeBinary(std::ostream&o)const { o.write(reinterpret_cast(&positions[0][0]),natoms*3*sizeof(double)); o.write(reinterpret_cast(&box(0,0)),9*sizeof(double)); o.write(reinterpret_cast(&energy),sizeof(double)); } -void Atoms::readBinary(std::istream&i){ +void Atoms::readBinary(std::istream&i) { i.read(reinterpret_cast(&positions[0][0]),natoms*3*sizeof(double)); i.read(reinterpret_cast(&box(0,0)),9*sizeof(double)); i.read(reinterpret_cast(&energy),sizeof(double)); pbc.setBox(box); } -double Atoms::getKBoltzmann()const{ +double Atoms::getKBoltzmann()const { if(naturalUnits) return 1.0; else return kBoltzmann/units.getEnergy(); } -double Atoms::getMDKBoltzmann()const{ +double Atoms::getMDKBoltzmann()const { if(naturalUnits) return 1.0; else return kBoltzmann/MDUnits.getEnergy(); } -void Atoms::getLocalMasses(std::vector& localMasses){ - localMasses.resize(gatindex.size()); - for(unsigned i=0; i& localMasses) { + localMasses.resize(gatindex.size()); + for(unsigned i=0; i& localPositions){ +void Atoms::getLocalPositions(std::vector& localPositions) { localPositions.resize(gatindex.size()); mdatoms->getLocalPositions(localPositions); } -void Atoms::getLocalForces(std::vector& localForces){ +void Atoms::getLocalForces(std::vector& localForces) { localForces.resize(gatindex.size()); for(unsigned i=0; i& localForces){ +void Atoms::getLocalMDForces(std::vector& localForces) { localForces.resize(gatindex.size()); for(unsigned i=0; igetMDforces(i); diff --git a/src/core/Atoms.h b/src/core/Atoms.h index 4e7ed103d5..e9cccf399f 100644 --- a/src/core/Atoms.h +++ b/src/core/Atoms.h @@ -32,7 +32,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class MDAtomsBase; class PlumedMain; @@ -77,7 +77,7 @@ class Atoms void resizeVectors(unsigned); std::vector fullList; - + MDAtomsBase* mdatoms; PlumedMain & plumed; @@ -114,15 +114,15 @@ class Atoms std::vector mpi_request_positions; std::vector mpi_request_index; - + std::vector positionsToBeSent; std::vector positionsToBeReceived; std::vector indexToBeSent; std::vector indexToBeReceived; - operator bool() const{return on;} + operator bool() const {return on;} DomainDecomposition(): on(false), async(false) - {} + {} void enable(Communicator& c); }; @@ -164,7 +164,7 @@ class Atoms void getLocalMDForces(std::vector&); const Tensor& getVirial()const; - void setCollectEnergy(bool b){ collectEnergy=b; } + void setCollectEnergy(bool b) { collectEnergy=b; } void setDomainDecomposition(Communicator&); void setAtomsGatindex(int*,bool); @@ -194,18 +194,18 @@ class Atoms void add(const ActionAtomistic*); void remove(const ActionAtomistic*); - double getEnergy()const{plumed_assert(collectEnergy && energyHasBeenSet); return energy;} + double getEnergy()const {plumed_assert(collectEnergy && energyHasBeenSet); return energy;} - bool isEnergyNeeded()const{return collectEnergy;} + bool isEnergyNeeded()const {return collectEnergy;} - void setMDEnergyUnits(double d){MDUnits.setEnergy(d);} - void setMDLengthUnits(double d){MDUnits.setLength(d);} - void setMDTimeUnits(double d){MDUnits.setTime(d);} - void setMDChargeUnits(double d){MDUnits.setCharge(d);} - void setMDMassUnits(double d){MDUnits.setMass(d);} - const Units& getMDUnits(){return MDUnits;} - void setUnits(const Units&u){units=u;} - const Units& getUnits(){return units;} + void setMDEnergyUnits(double d) {MDUnits.setEnergy(d);} + void setMDLengthUnits(double d) {MDUnits.setLength(d);} + void setMDTimeUnits(double d) {MDUnits.setTime(d);} + void setMDChargeUnits(double d) {MDUnits.setCharge(d);} + void setMDMassUnits(double d) {MDUnits.setMass(d);} + const Units& getMDUnits() {return MDUnits;} + void setUnits(const Units&u) {units=u;} + const Units& getUnits() {return units;} void updateUnits(); AtomNumber addVirtualAtom(ActionWithVirtualAtom*); @@ -219,37 +219,37 @@ class Atoms double getKBoltzmann()const; double getMDKBoltzmann()const; bool usingNaturalUnits()const; - void setNaturalUnits(bool n){naturalUnits=n;} - void setMDNaturalUnits(bool n){MDnaturalUnits=n;} + void setNaturalUnits(bool n) {naturalUnits=n;} + void setMDNaturalUnits(bool n) {MDnaturalUnits=n;} }; inline -const int & Atoms::getNatoms()const{ +const int & Atoms::getNatoms()const { return natoms; } inline -const long int& Atoms::getDdStep()const{ +const long int& Atoms::getDdStep()const { return ddStep; } inline -const std::vector& Atoms::getGatindex()const{ +const std::vector& Atoms::getGatindex()const { return gatindex; } inline -const Pbc& Atoms::getPbc()const{ +const Pbc& Atoms::getPbc()const { return pbc; } inline -bool Atoms::isVirtualAtom(AtomNumber i)const{ +bool Atoms::isVirtualAtom(AtomNumber i)const { return i.index()>=(unsigned) getNatoms(); } inline -ActionWithVirtualAtom* Atoms::getVirtualAtomsAction(AtomNumber i)const{ +ActionWithVirtualAtom* Atoms::getVirtualAtomsAction(AtomNumber i)const { return virtualAtomsActions[i.index()-getNatoms()]; } @@ -269,7 +269,7 @@ bool Atoms::boxWasSet() const { } inline -const Tensor& Atoms::getVirial()const{ +const Tensor& Atoms::getVirial()const { return virial; } diff --git a/src/core/CLTool.cpp b/src/core/CLTool.cpp index 527e5b6cbe..c7441d41ed 100644 --- a/src/core/CLTool.cpp +++ b/src/core/CLTool.cpp @@ -21,148 +21,148 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "CLTool.h" -namespace PLMD{ +namespace PLMD { Keywords CLToolOptions::emptyKeys; -CLToolOptions::CLToolOptions(const std::string &name): -line(1,name), -keys(emptyKeys) +CLToolOptions::CLToolOptions(const std::string &name): + line(1,name), + keys(emptyKeys) { } CLToolOptions::CLToolOptions(const CLToolOptions& co, const Keywords& k): -line(co.line), -keys(k) + line(co.line), + keys(k) { } -void CLTool::registerKeywords( Keywords& keys ){ +void CLTool::registerKeywords( Keywords& keys ) { keys.addFlag("--help/-h",false,"print this help"); } -CLTool::CLTool(const CLToolOptions& co ): -name(co.line[0]), -keywords(co.keys), -inputdata(unset) +CLTool::CLTool(const CLToolOptions& co ): + name(co.line[0]), + keywords(co.keys), + inputdata(unset) { } -void CLTool::parseFlag( const std::string&key, bool&t ){ +void CLTool::parseFlag( const std::string&key, bool&t ) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); plumed_massert(keywords.style(key,"flag"),"keyword " + key + " has not been registered as a flag"); - plumed_assert(inputData.count(key)>0); + plumed_assert(inputData.count(key)>0); if( inputData[key]=="true") t=true; else if( inputData[key]=="false") t=false; else plumed_error(); } -bool CLTool::readInput( int argc, char**argv, FILE* in, FILE*out ){ +bool CLTool::readInput( int argc, char**argv, FILE* in, FILE*out ) { plumed_massert( inputdata!=unset,"You have not specified where your tool reads its input. " - "If it is from the command line (like driver) add inputdata=commandline to the " - "tools constructor. If it reads everything from an input file (like simplemd) " - "add inputdata=ifile to the tools constructor"); + "If it is from the command line (like driver) add inputdata=commandline to the " + "tools constructor. If it reads everything from an input file (like simplemd) " + "add inputdata=ifile to the tools constructor"); if(inputdata==commandline) return readCommandLineArgs( argc, argv, out ); if(inputdata==ifile) return readInputFile( argc, argv, in, out ); return true; } -bool CLTool::readCommandLineArgs( int argc, char**argv, FILE*out ){ +bool CLTool::readCommandLineArgs( int argc, char**argv, FILE*out ) { plumed_assert(inputdata==commandline); std::string prefix(""), a(""), thiskey; // Set all flags to default false - for(unsigned k=0;k(thiskey,"false")); + for(unsigned k=0; k(thiskey,"false")); } // Read command line arguments bool printhelp=false; - for(int i=1;i(thiskey,"")); - } else if(Tools::startWith(a,thiskey+"=")){ - a.erase(0,a.find("=")+1); prefix=""; found=true; - if(inputData.count(thiskey)==0){ - inputData.insert(std::pair(thiskey,a)); - } else { - inputData[thiskey]=a; - } - } - } - } - if(!found){ - fprintf(stderr,"ERROR in input for command line tool %s : %s option is unknown \n\n", name.c_str(), a.c_str() ); - fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); - fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); - keywords.print( out ); - printhelp=true; - } + for(int i=1; i(thiskey,"")); + } else if(Tools::startWith(a,thiskey+"=")) { + a.erase(0,a.find("=")+1); prefix=""; found=true; + if(inputData.count(thiskey)==0) { + inputData.insert(std::pair(thiskey,a)); + } else { + inputData[thiskey]=a; + } + } + } + } + if(!found) { + fprintf(stderr,"ERROR in input for command line tool %s : %s option is unknown \n\n", name.c_str(), a.c_str() ); + fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); + fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); + keywords.print( out ); + printhelp=true; } - if(printhelp) break; + } + if(printhelp) break; } if(!printhelp) setRemainingToDefault(out); - if(printhelp){ - fprintf(out,"Usage: %s [options] \n\n", name.c_str() ); - keywords.print( out ); + if(printhelp) { + fprintf(out,"Usage: %s [options] \n\n", name.c_str() ); + keywords.print( out ); } return !printhelp; } -void CLTool::setRemainingToDefault(FILE* out){ +void CLTool::setRemainingToDefault(FILE* out) { std::string def, thiskey; - for(unsigned k=0;k0 ); - inputData.insert(std::pair(thiskey,def)); - } else { - fprintf(out,"ERROR : argument %s is compulsory. Use --help option for help\n",thiskey.c_str() ); - plumed_error(); - } - } + for(unsigned k=0; k0 ); + inputData.insert(std::pair(thiskey,def)); + } else { + fprintf(out,"ERROR : argument %s is compulsory. Use --help option for help\n",thiskey.c_str() ); + plumed_error(); + } } + } } } -bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ){ +bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ) { plumed_assert(inputdata==ifile); // Check if use is just asking for help std::string a; - for(int i=1;i(thiskey,line.substr(keypos))); - Tools::stripLeadingAndTrailingBlanks( inputData[thiskey] ); - } - } - if(!found){ - fprintf(stderr,"ERROR in input for command line tool %s : unknown keyword %s found in input file\n\n",name.c_str(),keyword.c_str()); - fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); - fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); - keywords.print( out ); - fclose(mystdin); - return false; - } + while(fgets(buffer,256,mystdin)) { + line=buffer; + for(unsigned i=0; i(thiskey,line.substr(keypos))); + Tools::stripLeadingAndTrailingBlanks( inputData[thiskey] ); + } + } + if(!found) { + fprintf(stderr,"ERROR in input for command line tool %s : unknown keyword %s found in input file\n\n",name.c_str(),keyword.c_str()); + fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); + fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); + keywords.print( out ); + fclose(mystdin); + return false; + } } if(argc==2) fclose(mystdin); @@ -205,9 +205,9 @@ bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ){ return true; } -void CLTool::error( const std::string& msg ){ +void CLTool::error( const std::string& msg ) { fprintf(stderr,"ERROR : in input for command line tool %s : %s\n",name.c_str(),msg.c_str()); - plumed_error(); + plumed_error(); } } diff --git a/src/core/CLTool.h b/src/core/CLTool.h index 9385c93d82..c9ab30778e 100644 --- a/src/core/CLTool.h +++ b/src/core/CLTool.h @@ -28,11 +28,11 @@ #include "tools/Tools.h" #include "tools/Keywords.h" -namespace PLMD{ +namespace PLMD { class Communicator; -class CLToolOptions{ +class CLToolOptions { friend class CLTool; friend class CLToolRegister; private: @@ -67,92 +67,92 @@ class CLTool { void setRemainingToDefault(FILE* out); public: /// Set the input data: - void setInputData(const std::map&inputData){ + void setInputData(const std::map&inputData) { this->inputData=inputData; } - const std::map&getInputData(){ + const std::map&getInputData() { return this->inputData; } protected: -/// Get the value of one of the command line arguments +/// Get the value of one of the command line arguments template bool parse(const std::string&key,T&t); /// Find out whether one of the command line flags is present or not - void parseFlag(const std::string&key,bool&t); + void parseFlag(const std::string&key,bool&t); /// Crash the command line tool with an error void error(const std::string& msg); template - bool parseVector(const std::string&key,std::vector&t); + bool parseVector(const std::string&key,std::vector&t); public: /// How is the input specified on the command line or in an input file enum {unset,commandline,ifile} inputdata; -/// Create the help keywords +/// Create the help keywords static void registerKeywords( Keywords& keys ); - explicit CLTool(const CLToolOptions& co ); + explicit CLTool(const CLToolOptions& co ); /// Read the arguments from the command line bool readInput( int argc, char**argv, FILE* in, FILE*out ); /// virtual function mapping to the specific main for each tool virtual int main( FILE* in, FILE*out, Communicator&pc )=0; /// virtual function returning a one-line descriptor for the tool - virtual std::string description()const{return "(no description available)";} + virtual std::string description()const {return "(no description available)";} /// virtual destructor to allow inheritance - virtual ~CLTool(){} + virtual ~CLTool() {} }; template -bool CLTool::parse(const std::string&key,T&t){ +bool CLTool::parse(const std::string&key,T&t) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); - if(keywords.style(key,"compulsory") ){ - if(inputData.count(key)==0) error("missing data for keyword " + key); - bool check=Tools::convert(inputData[key],t); - if(!check) error("data input for keyword " + key + " has wrong type"); - return true; + if(keywords.style(key,"compulsory") ) { + if(inputData.count(key)==0) error("missing data for keyword " + key); + bool check=Tools::convert(inputData[key],t); + if(!check) error("data input for keyword " + key + " has wrong type"); + return true; } - if( inputData.count(key)==0 ) return false; + if( inputData.count(key)==0 ) return false; Tools::convert(inputData[key],t); return true; } -// very limited support and check: take more from core/Action.h parseVector +// very limited support and check: take more from core/Action.h parseVector template -bool CLTool::parseVector(const std::string&key,std::vector&t){ +bool CLTool::parseVector(const std::string&key,std::vector&t) { // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); // initial size - unsigned size=t.size(); + unsigned size=t.size(); bool skipcheck=false; - if(size==0) skipcheck=true; // if the vector in input has size zero, skip the check if size of input vector is the same of argument read + if(size==0) skipcheck=true; // if the vector in input has size zero, skip the check if size of input vector is the same of argument read // check if there is some value plumed_massert(inputData[key]!="false","compulsory keyword "+std::string(key)+"has no data"); std::vector words=Tools::getWords(inputData[key],"\t\n ,"); - t.resize(0); + t.resize(0); if(words.size()==0)return false; - for(unsigned i=0;i using namespace std; -namespace PLMD{ +namespace PLMD { CLToolMain::CLToolMain(): -argc(0), -in(stdin), -out(stdout), -comm(*new Communicator) + argc(0), + in(stdin), + out(stdout), + comm(*new Communicator) { } -CLToolMain::~CLToolMain(){ +CLToolMain::~CLToolMain() { delete &comm; } #define CHECK_NULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"CLTool " + word + "\")"); -void CLToolMain::cmd(const std::string& word,void*val){ - if(false){ - } else if(word=="setArgc"){ - CHECK_NULL(val,word); - argc=*static_cast(val); - } else if(word=="setArgv"){ - CHECK_NULL(val,word); - char**v=static_cast(val); - for(int i=0;i(val); - argv=Tools::getWords(v); - } else if(word=="setIn"){ - CHECK_NULL(val,word); - in=static_cast(val); - } else if(word=="setOut"){ - CHECK_NULL(val,word); - out=static_cast(val); - } else if(word=="setMPIComm"){ - comm.Set_comm(val); - } else if(word=="setMPIFComm"){ - comm.Set_fcomm(val); - } else if(word=="run"){ - CHECK_NULL(val,word); - argc=argv.size(); - int n=0; for(int i=0;i args(n); - std::vector v(argc); - char* ptr=&args[0]; - for(int i=0;i(val)=ret; +void CLToolMain::cmd(const std::string& word,void*val) { + if(false) { + } else if(word=="setArgc") { + CHECK_NULL(val,word); + argc=*static_cast(val); + } else if(word=="setArgv") { + CHECK_NULL(val,word); + char**v=static_cast(val); + for(int i=0; i(val); + argv=Tools::getWords(v); + } else if(word=="setIn") { + CHECK_NULL(val,word); + in=static_cast(val); + } else if(word=="setOut") { + CHECK_NULL(val,word); + out=static_cast(val); + } else if(word=="setMPIComm") { + comm.Set_comm(val); + } else if(word=="setMPIFComm") { + comm.Set_fcomm(val); + } else if(word=="run") { + CHECK_NULL(val,word); + argc=argv.size(); + int n=0; for(int i=0; i args(n); + std::vector v(argc); + char* ptr=&args[0]; + for(int i=0; i(val)=ret; } else { plumed_merror("cannot interpret cmd(\"CLTool " + word + "\"). check plumed developers manual to see the available commands."); } @@ -99,7 +99,7 @@ This is the entry point to the command line tools included in the plumed library. */ -int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ +int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc) { int i; bool printhelp=false; @@ -112,55 +112,55 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ // Start parsing options string prefix(""); string a(""); - for(i=1;i1){ + if(i>1) { fprintf(stderr,"--no-mpi option can only be used as the first option"); return 1; } - } else if(a=="--mpi"){ + } else if(a=="--mpi") { // this is ignored, as it is parsed in main - if(i>1){ + if(i>1) { fprintf(stderr,"--mpi option can only be used as the first option"); return 1; } - } else if(a=="--standalone-executable"){ + } else if(a=="--standalone-executable") { standalone_executable=true; - } else if(Tools::startWith(a,"--load=")){ + } else if(Tools::startWith(a,"--load=")) { a.erase(0,a.find("=")+1); prefix=""; void *p=dlloader.load(a); - if(!p){ + if(!p) { fprintf(stderr,"ERROR: cannot load library %s\n",a.c_str()); fprintf(stderr,"ERROR: %s\n",dlloader.error().c_str()); return 1; } - } else if(a=="--load"){ + } else if(a=="--load") { prefix="--load="; } else if(a[0]=='-') { string msg="ERROR: Unknown option " +a; @@ -170,11 +170,11 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ } // Check if plumedRoot/patches/ directory exists (as a further check) - if(!standalone_executable){ + if(!standalone_executable) { vector files=Tools::ls(root); if(find(files.begin(),files.end(),"patches")==files.end()) { string msg= - "WARNING: I cannot find "+root+"/patches/ directory. Set PLUMED_ROOT or reinstall PLUMED\n\n"; + "WARNING: I cannot find "+root+"/patches/ directory. Set PLUMED_ROOT or reinstall PLUMED\n\n"; fprintf(stderr,"%s",msg.c_str()); } } @@ -186,36 +186,36 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ if(!standalone_executable) { vector tmp; tmp=Tools::ls(string(root+"/scripts")); - for(unsigned j=0;j0) availableShell.push_back(tmp[j]); + for(unsigned j=0; j0) availableShell.push_back(tmp[j]); } - if(printhelp){ + if(printhelp) { string msg= - "Usage: plumed [options] [command] [command options]\n" - " plumed [command] -h|--help: to print help for a specific command\n" - "Options:\n" - " [help|-h|--help] : to print this help\n" - " [--is-installed] : fails if plumed is not installed\n" - " [--has-mpi] : fails if plumed is running without MPI\n" - " [--has-matheval] : fails if plumed is compiled without matheval\n" - " [--has-dlopen] : fails if plumed is compiled without dlopen\n" - " [--load LIB] : loads a shared object (typically a plugin library)\n" - " [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n" - "Commands:\n"; + "Usage: plumed [options] [command] [command options]\n" + " plumed [command] -h|--help: to print help for a specific command\n" + "Options:\n" + " [help|-h|--help] : to print this help\n" + " [--is-installed] : fails if plumed is not installed\n" + " [--has-mpi] : fails if plumed is running without MPI\n" + " [--has-matheval] : fails if plumed is compiled without matheval\n" + " [--has-dlopen] : fails if plumed is compiled without dlopen\n" + " [--load LIB] : loads a shared object (typically a plugin library)\n" + " [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n" + "Commands:\n"; fprintf(out,"%s",msg.c_str()); - for(unsigned j=0;jdescription(); delete cl; fprintf(out," plumed %s\n", manual.c_str()); } - for(unsigned j=0;jreadInput( argc-i,&argv[i],in,out ) ){ delete cl; return 0; } + if( !cl->readInput( argc-i,&argv[i],in,out ) ) { delete cl; return 0; } int ret=cl->main(in,out,pc); delete cl; return ret; } - if(find(availableShell.begin(),availableShell.end(),command)!=availableShell.end()){ + if(find(availableShell.begin(),availableShell.end(),command)!=availableShell.end()) { plumed_massert(in==stdin,"shell tools can only work on stdin"); plumed_massert(out==stdout,"shell tools can only work on stdin"); string cmd=config::getEnvCommand()+" \""+root+"/scripts/"+command+".sh\""; - for(int j=i+1;j0){ +CLToolRegister::~CLToolRegister() { + if(m.size()>0) { string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: CLTools "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -CLToolRegister& cltoolRegister(){ +CLToolRegister& cltoolRegister() { static CLToolRegister ans; return ans; } -void CLToolRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void CLToolRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void CLToolRegister::add(string key,creator_pointer f,keywords_pointer kf){ - if(m.count(key)){ +void CLToolRegister::add(string key,creator_pointer f,keywords_pointer kf) { + if(m.count(key)) { m.erase(key); disabled.insert(key); - }else{ + } else { m.insert(pair(key,f)); Keywords keys; kf(keys); mk.insert(pair(key,keys)); }; } -bool CLToolRegister::check(string key){ +bool CLToolRegister::check(string key) { if(m.count(key)>0) return true; return false; } -CLTool* CLToolRegister::create(const CLToolOptions&ao){ +CLTool* CLToolRegister::create(const CLToolOptions&ao) { if(ao.line.size()<1)return NULL; CLTool* cltool; - if(check(ao.line[0])){ - CLToolOptions nao( ao,mk[ao.line[0]] ); - cltool=m[ao.line[0]](nao); + if(check(ao.line[0])) { + CLToolOptions nao( ao,mk[ao.line[0]] ); + cltool=m[ao.line[0]](nao); } else cltool=NULL; return cltool; } -std::ostream & operator<<(std::ostream &log,const CLToolRegister&ar){ +std::ostream & operator<<(std::ostream &log,const CLToolRegister&ar) { vector s(ar.list()); - for(unsigned i=0;i CLToolRegister::list()const{ +vector CLToolRegister::list()const { vector s; for(const auto & it : m) s.push_back(it.first); sort(s.begin(),s.end()); diff --git a/src/core/CLToolRegister.h b/src/core/CLToolRegister.h index 1d91bfe145..f7b14a561f 100644 --- a/src/core/CLToolRegister.h +++ b/src/core/CLToolRegister.h @@ -29,13 +29,13 @@ #include #include "tools/Keywords.h" -namespace PLMD{ +namespace PLMD { class CLTool; class CLToolOptions; /// Same as ActionRegister, but for CLTools -class CLToolRegister{ +class CLToolRegister { /// Write on a stream the list of registered directives friend std::ostream &operator<<(std::ostream &,const CLToolRegister&); /// Pointer to a function which, given the options, create an CLTool @@ -64,7 +64,7 @@ class CLToolRegister{ /// Returns a list of the allowed CLTools std::vector list()const; /// Print out the instructions for using the tool in html ready for input into the manual - bool printManual(const std::string& cltool); + bool printManual(const std::string& cltool); }; /// Function returning a reference to the CLToolRegister. diff --git a/src/core/Colvar.cpp b/src/core/Colvar.cpp index bdd6b048ea..239afdc8d3 100644 --- a/src/core/Colvar.cpp +++ b/src/core/Colvar.cpp @@ -25,32 +25,32 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { Colvar::Colvar(const ActionOptions&ao): -Action(ao), -ActionAtomistic(ao), -ActionWithValue(ao), -isEnergy(false) + Action(ao), + ActionAtomistic(ao), + ActionWithValue(ao), + isEnergy(false) { } -void Colvar::registerKeywords( Keywords& keys ){ +void Colvar::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances"); -} +} -void Colvar::requestAtoms(const vector & a){ +void Colvar::requestAtoms(const vector & a) { plumed_massert(!isEnergy,"request atoms should not be called if this is energy"); // Tell actionAtomistic what atoms we are getting ActionAtomistic::requestAtoms(a); // Resize the derivatives of all atoms - for(int i=0;iresizeDerivatives(3*a.size()+9); + for(int i=0; iresizeDerivatives(3*a.size()+9); } -void Colvar::apply(){ +void Colvar::apply() { vector& f(modifyForces()); Tensor& v(modifyVirial()); const unsigned nat=getNumberOfAtoms(); @@ -67,16 +67,16 @@ void Colvar::apply(){ unsigned nt=OpenMP::getNumThreads(); if(nt>ncp/(2.*stride)) nt=1; - if(!isEnergy){ - #pragma omp parallel num_threads(nt) + if(!isEnergy) { + #pragma omp parallel num_threads(nt) { vector omp_f(fsz); Tensor omp_v; vector forces(3*nat+9); - #pragma omp for - for(unsigned i=rank;iapplyForce(forces)){ - for(unsigned j=0;japplyForce(forces)) { + for(unsigned j=0; j forces(1); if(getPntrToComponent(0)->applyForce(forces)) modifyForceOnEnergy()+=forces[0]; } } -void Colvar::setBoxDerivativesNoPbc(Value* v){ +void Colvar::setBoxDerivativesNoPbc(Value* v) { Tensor virial; unsigned nat=getNumberOfAtoms(); - for(unsigned i=0;igetDerivative(3*i+0), - v->getDerivative(3*i+1), - v->getDerivative(3*i+2))); + for(unsigned i=0; igetDerivative(3*i+0), + v->getDerivative(3*i+1), + v->getDerivative(3*i+2))); setBoxDerivatives(v,virial); } } diff --git a/src/core/Colvar.h b/src/core/Colvar.h index 08e962aa5f..4a7ef6a08b 100644 --- a/src/core/Colvar.h +++ b/src/core/Colvar.h @@ -32,14 +32,14 @@ namespace PLMD { /** \ingroup INHERIT -This is the abstract base class to use for implementing new collective variables, within it there is -\ref AddingAColvar "information" as to how to go about implementing a new CV. +This is the abstract base class to use for implementing new collective variables, within it there is +\ref AddingAColvar "information" as to how to go about implementing a new CV. */ class Colvar : public ActionAtomistic, public ActionWithValue - { +{ private: protected: bool isEnergy; @@ -47,7 +47,7 @@ class Colvar : // Set the derivatives for a particular atom equal to the input Vector // This routine is called setAtomsDerivatives because not because you // are setting the derivative of many atoms but because you are setting -// the derivatives of a particular atom. The s is an apostrophe s +// the derivatives of a particular atom. The s is an apostrophe s // but you can't put apostrophes in function names void setAtomsDerivatives(int,const Vector&); void setAtomsDerivatives(Value*,int,const Vector&); @@ -63,15 +63,15 @@ class Colvar : void setBoxDerivativesNoPbc(); void setBoxDerivativesNoPbc(Value*); public: - bool checkIsEnergy(){return isEnergy;} + bool checkIsEnergy() {return isEnergy;} explicit Colvar(const ActionOptions&); - ~Colvar(){} + ~Colvar() {} static void registerKeywords( Keywords& keys ); virtual unsigned getNumberOfDerivatives(); }; inline -void Colvar::setAtomsDerivatives(Value*v,int i,const Vector&d){ +void Colvar::setAtomsDerivatives(Value*v,int i,const Vector&d) { v->addDerivative(3*i+0,d[0]); v->addDerivative(3*i+1,d[1]); v->addDerivative(3*i+2,d[2]); @@ -79,7 +79,7 @@ void Colvar::setAtomsDerivatives(Value*v,int i,const Vector&d){ inline -void Colvar::setBoxDerivatives(Value* v,const Tensor&d){ +void Colvar::setBoxDerivatives(Value* v,const Tensor&d) { unsigned nat=getNumberOfAtoms(); v->addDerivative(3*nat+0,d(0,0)); v->addDerivative(3*nat+1,d(0,1)); @@ -93,22 +93,22 @@ void Colvar::setBoxDerivatives(Value* v,const Tensor&d){ } inline -void Colvar::setAtomsDerivatives(int i,const Vector&d){ +void Colvar::setAtomsDerivatives(int i,const Vector&d) { setAtomsDerivatives(getPntrToValue(),i,d); } inline -void Colvar::setBoxDerivatives(const Tensor&d){ +void Colvar::setBoxDerivatives(const Tensor&d) { setBoxDerivatives(getPntrToValue(),d); } inline -void Colvar::setBoxDerivativesNoPbc(){ +void Colvar::setBoxDerivativesNoPbc() { setBoxDerivativesNoPbc(getPntrToValue()); } inline -unsigned Colvar::getNumberOfDerivatives(){ +unsigned Colvar::getNumberOfDerivatives() { return 3*getNumberOfAtoms() + 9; } diff --git a/src/core/ExchangePatterns.cpp b/src/core/ExchangePatterns.cpp index a3b4d338c3..fdd22e74ec 100644 --- a/src/core/ExchangePatterns.cpp +++ b/src/core/ExchangePatterns.cpp @@ -24,7 +24,7 @@ using namespace std; -namespace PLMD{ +namespace PLMD { ExchangePatterns::ExchangePatterns(): PatternFlag(NONE), @@ -37,15 +37,15 @@ ExchangePatterns::~ExchangePatterns() delete &random; } -void ExchangePatterns::setNofR(const int nrepl){ +void ExchangePatterns::setNofR(const int nrepl) { NumberOfReplicas=nrepl; } -void ExchangePatterns::setFlag(const int flag){ +void ExchangePatterns::setFlag(const int flag) { PatternFlag=flag; } -void ExchangePatterns::getFlag(int &flag){ +void ExchangePatterns::getFlag(int &flag) { flag=PatternFlag; } @@ -58,19 +58,19 @@ void ExchangePatterns::getList(int *ind) { switch(PatternFlag) { - case RANDOM: - for(int i=0;i &smin, vector &smax):type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax){ - // initialize the averages and the variance matrices - if(type==diffusion){ - unsigned ncv=paction->getNumberOfArguments(); - vector average(ncv*(ncv+1)/2); - vector variance(ncv*(ncv+1)/2); - } - paction->log<<" Limits for sigmas using adaptive hills: \n"; - for(unsigned i=0;igetNumberOfArguments();++i){ - paction->log<<" CV "<getPntrToArgument(i)->getName()<<":\n"; - if(sigmamin[i]>0.){ - limitmin.push_back(true); - paction->log<<" Min "<log<<" Min No "; - } - if(sigmamax[i]>0.){ - limitmax.push_back(true); - paction->log<<" Max "<log<<" Max No "; - } - paction->log<<" \n"; - } +FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, double const &d, vector &smin, vector &smax):type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax) { + // initialize the averages and the variance matrices + if(type==diffusion) { + unsigned ncv=paction->getNumberOfArguments(); + vector average(ncv*(ncv+1)/2); + vector variance(ncv*(ncv+1)/2); + } + paction->log<<" Limits for sigmas using adaptive hills: \n"; + for(unsigned i=0; igetNumberOfArguments(); ++i) { + paction->log<<" CV "<getPntrToArgument(i)->getName()<<":\n"; + if(sigmamin[i]>0.) { + limitmin.push_back(true); + paction->log<<" Min "<log<<" Min No "; + } + if(sigmamax[i]>0.) { + limitmax.push_back(true); + paction->log<<" Max "<log<<" Max No "; + } + paction->log<<" \n"; + } } /// Constructure for 1D FB for PBMETAD -FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, +FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, double const &d, vector &smin, vector &smax): - type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax) + type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax) { - // initialize the averages and the variance matrices - if(type==diffusion){ - vector average(1); - vector variance(1); - } - paction->log<<" Limits for sigmas using adaptive hills: \n"; - paction->log<<" CV "<getPntrToArgument(iarg)->getName()<<":\n"; - if(sigmamin[0]>0.){ - limitmin.push_back(true); - paction->log<<" Min "<log<<" Min No "; - } - if(sigmamax[0]>0.){ - limitmax.push_back(true); - paction->log<<" Max "<log<<" Max No "; - } - paction->log<<" \n"; + // initialize the averages and the variance matrices + if(type==diffusion) { + vector average(1); + vector variance(1); + } + paction->log<<" Limits for sigmas using adaptive hills: \n"; + paction->log<<" CV "<getPntrToArgument(iarg)->getName()<<":\n"; + if(sigmamin[0]>0.) { + limitmin.push_back(true); + paction->log<<" Min "<log<<" Min No "; + } + if(sigmamax[0]>0.) { + limitmax.push_back(true); + paction->log<<" Max "<log<<" Max No "; + } + paction->log<<" \n"; } -/// Update the flexible bin +/// Update the flexible bin /// in case of diffusion based: update at every step -/// in case of gradient based: update only when you add the hill -void FlexibleBin::update(bool nowAddAHill){ - unsigned ncv=paction->getNumberOfArguments(); - unsigned dimension=ncv*(ncv+1)/2; - // this is done all the times from scratch. It is not an accumulator - unsigned k=0; - unsigned i; - vector cv; - vector delta; - // if you use this below then the decay is in time units - //double decay=paction->getTimeStep()/sigma; - // to be consistent with the rest of the program: everything is better to be in timesteps - double decay=1./sigma; - // here update the flexible bin according to the needs - switch (type){ - // This should be called every time - case diffusion: - // - // THE AVERAGE VALUE - // - // beware: the pbc - delta.resize(ncv); - for(i=0;igetArgument(i)); - if(average.size()==0){ // initial time: just set the initial vector - average.resize(ncv); - for(i=0;idifference(i,average[i],cv[i]); - average[i]+=decay*delta[i]; - average[i]=paction->bringBackInPbc(i,average[i]); // equation 8 of "Metadynamics with adaptive Gaussians" - } +/// in case of gradient based: update only when you add the hill +void FlexibleBin::update(bool nowAddAHill) { + unsigned ncv=paction->getNumberOfArguments(); + unsigned dimension=ncv*(ncv+1)/2; + // this is done all the times from scratch. It is not an accumulator + unsigned k=0; + unsigned i; + vector cv; + vector delta; + // if you use this below then the decay is in time units + //double decay=paction->getTimeStep()/sigma; + // to be consistent with the rest of the program: everything is better to be in timesteps + double decay=1./sigma; + // here update the flexible bin according to the needs + switch (type) { + // This should be called every time + case diffusion: + // + // THE AVERAGE VALUE + // + // beware: the pbc + delta.resize(ncv); + for(i=0; igetArgument(i)); + if(average.size()==0) { // initial time: just set the initial vector + average.resize(ncv); + for(i=0; idifference(i,average[i],cv[i]); + average[i]+=decay*delta[i]; + average[i]=paction->bringBackInPbc(i,average[i]); // equation 8 of "Metadynamics with adaptive Gaussians" + } - } - // - // THE VARIANCE - // - if(variance.size()==0){ - variance.resize(dimension,0.); // nonredundant members dimension=ncv*(ncv+1)/2; - }else{ - k=0; - for(i=0;igetProjection(i,j)); - k++; - } - }; - }; - break; - default: - cerr<< "This flexible bin is not recognized "<getProjection(i,j)); + k++; + } + }; + }; + break; + default: + cerr<< "This flexible bin is not recognized "< FlexibleBin::getMatrix() const{ - return variance; +vector FlexibleBin::getMatrix() const { + return variance; } /// Update the flexible bin for PBMetaD like FlexBin /// in case of diffusion based: update at every step -/// in case of gradient based: update only when you add the hill -void FlexibleBin::update(bool nowAddAHill, unsigned iarg){ - // this is done all the times from scratch. It is not an accumulator - vector cv; - vector delta; - // if you use this below then the decay is in time units - // to be consistent with the rest of the program: everything is better to be in timesteps - double decay=1./sigma; - // here update the flexible bin according to the needs - switch (type){ - // This should be called every time - case diffusion: - // - // THE AVERAGE VALUE - // - delta.resize(1); - cv.push_back(paction->getArgument(iarg)); - if(average.size()==0){ // initial time: just set the initial vector - average.resize(1); - average[0]=cv[0]; - }else{ // accumulate - delta[0]=paction->difference(iarg,average[0],cv[0]); - average[0]+=decay*delta[0]; - average[0]=paction->bringBackInPbc(iarg,average[0]); // equation 8 of "Metadynamics with adaptive Gaussians" - } - // - // THE VARIANCE - // - if(variance.size()==0){ - variance.resize(1,0.); // nonredundant members dimension=ncv*(ncv+1)/2; - }else{ - variance[0]+=decay*(delta[0]*delta[0]-variance[0]); - } - break; - case geometry: - // - //this calculates in variance the \nabla CV_i \dot \nabla CV_j - // - variance.resize(1); - // now the signal for retrieving the gradients should be already given by checkNeedsGradients. - // here just do the projections - // note that the call checkNeedsGradients() in BiasMetaD takes care of switching on the call to gradients - if (nowAddAHill){// geometry is sync with hill deposition - // eq 12 of "Metadynamics with adaptive Gaussians" - variance[0]=sigma*sigma*(paction->getProjection(iarg,iarg)); - } - break; - default: - cerr<< "This flexible bin is not recognized "< cv; + vector delta; + // if you use this below then the decay is in time units + // to be consistent with the rest of the program: everything is better to be in timesteps + double decay=1./sigma; + // here update the flexible bin according to the needs + switch (type) { + // This should be called every time + case diffusion: + // + // THE AVERAGE VALUE + // + delta.resize(1); + cv.push_back(paction->getArgument(iarg)); + if(average.size()==0) { // initial time: just set the initial vector + average.resize(1); + average[0]=cv[0]; + } else { // accumulate + delta[0]=paction->difference(iarg,average[0],cv[0]); + average[0]+=decay*delta[0]; + average[0]=paction->bringBackInPbc(iarg,average[0]); // equation 8 of "Metadynamics with adaptive Gaussians" + } + // + // THE VARIANCE + // + if(variance.size()==0) { + variance.resize(1,0.); // nonredundant members dimension=ncv*(ncv+1)/2; + } else { + variance[0]+=decay*(delta[0]*delta[0]-variance[0]); + } + break; + case geometry: + // + //this calculates in variance the \nabla CV_i \dot \nabla CV_j + // + variance.resize(1); + // now the signal for retrieving the gradients should be already given by checkNeedsGradients. + // here just do the projections + // note that the call checkNeedsGradients() in BiasMetaD takes care of switching on the call to gradients + if (nowAddAHill) { // geometry is sync with hill deposition + // eq 12 of "Metadynamics with adaptive Gaussians" + variance[0]=sigma*sigma*(paction->getProjection(iarg,iarg)); + } + break; + default: + cerr<< "This flexible bin is not recognized "< FlexibleBin::getInverseMatrix() const{ - unsigned ncv=paction->getNumberOfArguments(); - Matrix matrix(ncv,ncv); - unsigned i,j,k; - k=0; - //paction->log<<"------------ GET INVERSE MATRIX ---------------\n"; - // place the matrix in a complete matrix for compatibility - for (i=0;i FlexibleBin::getInverseMatrix() const { + unsigned ncv=paction->getNumberOfArguments(); + Matrix matrix(ncv,ncv); + unsigned i,j,k; + k=0; + //paction->log<<"------------ GET INVERSE MATRIX ---------------\n"; + // place the matrix in a complete matrix for compatibility + for (i=0; i eigenvecs(ncv,ncv); - vector eigenvals(ncv); + // diagonalize to impose boundaries (only if boundaries are set) + Matrix eigenvecs(ncv,ncv); + vector eigenvals(ncv); - //eigenvecs: first is eigenvec number, second is eigenvec component - if(diagMat( matrix , eigenvals , eigenvecs )!=0){plumed_merror("diagonalization in FlexibleBin failed! This matrix is weird\n");}; - - for (i=0;ipow(sigmamax[i],2) ){ - eigenvals[j]=sqrt(pow(sigmamax[i]/(eigenvecs[j][i]),2))*copysign(1.,eigenvals[j]); - } - } - } - } - for (i=0;ifmax){ - fmax=fact;imax=j; - } - } - if(fmax newinvmatrix(ncv,ncv); - for (i=0;ipow(sigmamax[i],2) ) { + eigenvals[j]=sqrt(pow(sigmamax[i]/(eigenvecs[j][i]),2))*copysign(1.,eigenvals[j]); + } + } + } + } + for (i=0; ifmax) { + fmax=fact; imax=j; + } + } + if(fmax uppervec(ncv*(ncv+1)/2); - k=0; - for (i=0;i invmatrix(ncv,ncv); - Invert(matrix,invmatrix); - vector uppervec(ncv*(ncv+1)/2); - // upper diagonal of the inverted matrix (that is symmetric) - k=0; - for (i=0;ilog<<"VV "< newinvmatrix(ncv,ncv); + for (i=0; i uppervec(ncv*(ncv+1)/2); + k=0; + for (i=0; i invmatrix(ncv,ncv); + Invert(matrix,invmatrix); + vector uppervec(ncv*(ncv+1)/2); + // upper diagonal of the inverted matrix (that is symmetric) + k=0; + for (i=0; ilog<<"VV "< FlexibleBin::getInverseMatrix(unsigned iarg) const{ - // diagonalize to impose boundaries (only if boundaries are set) - vector eigenvals(1, variance[0]); - if( limitmax[0] ){ - if(eigenvals[0]>sigmamax[0]){ - eigenvals[0]=sigmamax[0]; - } - } - // find the largest one: if it is smaller than min then rescale - if( limitmin[0] ){ - double fmax=-1.e10; - double fact=eigenvals[0]; - if(fact>fmax){ - fmax=fact; - } - if(fmax uppervec(1,1./eigenvals[0]); +vector FlexibleBin::getInverseMatrix(unsigned iarg) const { + // diagonalize to impose boundaries (only if boundaries are set) + vector eigenvals(1, variance[0]); + if( limitmax[0] ) { + if(eigenvals[0]>sigmamax[0]) { + eigenvals[0]=sigmamax[0]; + } + } + // find the largest one: if it is smaller than min then rescale + if( limitmin[0] ) { + double fmax=-1.e10; + double fact=eigenvals[0]; + if(fact>fmax) { + fmax=fact; + } + if(fmax uppervec(1,1./eigenvals[0]); - return uppervec; + return uppervec; } } diff --git a/src/core/FlexibleBin.h b/src/core/FlexibleBin.h index 4bd942a07e..3bcbd16f08 100644 --- a/src/core/FlexibleBin.h +++ b/src/core/FlexibleBin.h @@ -24,37 +24,37 @@ #include -namespace PLMD{ +namespace PLMD { class ActionWithArguments; -class FlexibleBin{ - private: - int type; - // this contains all the infos about the CVs including periodicity - ActionWithArguments *paction; - double sigma; - // variance is the matrix that really matters - std::vector variance; - // this is only there - std::vector average; - // minimum and maximum values - std::vector sigmamin; - std::vector sigmamax; - std::vector limitmax; - std::vector limitmin; - public: - /// a constructor that takes the pointer of the action that contains it - FlexibleBin(int type,ActionWithArguments *paction, double const &d, std::vector &sigmamin, std::vector &sigmamax ); - /// a constructor for 1D FlexBin (for PBMETAD) - FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, double const &d, std::vector &sigmamin, std::vector &sigmamax); - /// update the average (always for diffusion) or calculate the geom covariance ( only when do_when_zero is zero) - void update(bool nowAddAHill); - void update(bool nowAddAHill, unsigned iarg); - std::vector getMatrix() const; - std::vector getInverseMatrix() const; - std::vector getInverseMatrix(unsigned iarg) const; - enum AdaptiveHillsType { none, diffusion, geometry }; +class FlexibleBin { +private: + int type; + // this contains all the infos about the CVs including periodicity + ActionWithArguments *paction; + double sigma; + // variance is the matrix that really matters + std::vector variance; + // this is only there + std::vector average; + // minimum and maximum values + std::vector sigmamin; + std::vector sigmamax; + std::vector limitmax; + std::vector limitmin; +public: + /// a constructor that takes the pointer of the action that contains it + FlexibleBin(int type,ActionWithArguments *paction, double const &d, std::vector &sigmamin, std::vector &sigmamax ); + /// a constructor for 1D FlexBin (for PBMETAD) + FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, double const &d, std::vector &sigmamin, std::vector &sigmamax); + /// update the average (always for diffusion) or calculate the geom covariance ( only when do_when_zero is zero) + void update(bool nowAddAHill); + void update(bool nowAddAHill, unsigned iarg); + std::vector getMatrix() const; + std::vector getInverseMatrix() const; + std::vector getInverseMatrix(unsigned iarg) const; + enum AdaptiveHillsType { none, diffusion, geometry }; }; diff --git a/src/core/GREX.cpp b/src/core/GREX.cpp index 9e355ece1d..fb30166a3a 100644 --- a/src/core/GREX.cpp +++ b/src/core/GREX.cpp @@ -30,12 +30,12 @@ #include "GREXEnum.inc" using namespace std; -namespace PLMD{ +namespace PLMD { -const std::unordered_map & GREXWordMap(){ +const std::unordered_map & GREXWordMap() { static std::unordered_map word_map; static bool init=false; - if(!init){ + if(!init) { #include "GREXMap.inc" } init=true; @@ -58,7 +58,7 @@ GREX::GREX(PlumedMain&p): p.setSuffix(".NA"); } -GREX::~GREX(){ +GREX::~GREX() { delete &intercomm; delete &intracomm; } @@ -67,16 +67,16 @@ GREX::~GREX(){ #define CHECK_NOTINIT(ini,word) plumed_massert(!(ini),"cmd(\"" + word +"\") should be only used before GREX initialization") #define CHECK_NOTNULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"GREX " + word + "\")"); -void GREX::cmd(const string&key,void*val){ +void GREX::cmd(const string&key,void*val) { std::vector words=Tools::getWords(key); unsigned nw=words.size(); - if(nw==0){ + if(nw==0) { // do nothing } else { int iword=-1; const auto it=GREXWordMap().find(words[0]); if(it!=GREXWordMap().end()) iword=it->second; - switch(iword){ + switch(iword) { case cmd_initialized: CHECK_NOTNULL(val,key); *static_cast(val)=initialized; @@ -173,7 +173,7 @@ void GREX::cmd(const string&key,void*val){ CHECK_NOTNULL(val,key); plumed_assert(nw==2); plumed_massert(allDeltaBias.size()==static_cast(intercomm.Get_size()), - "to retrieve bias with cmd(\"GREX getDeltaBias\"), first share it with cmd(\"GREX shareAllDeltaBias\")"); + "to retrieve bias with cmd(\"GREX getDeltaBias\"), first share it with cmd(\"GREX shareAllDeltaBias\")"); { unsigned rep; Tools::convert(words[1],rep); @@ -189,7 +189,7 @@ void GREX::cmd(const string&key,void*val){ } } -void GREX::savePositions(){ +void GREX::savePositions() { plumedMain.prepareDependencies(); plumedMain.resetActive(true); atoms.shareAll(); @@ -199,12 +199,12 @@ void GREX::savePositions(){ buffer=o.str(); } -void GREX::calculate(){ +void GREX::calculate() { //fprintf(stderr,"CALCULATE %d %d\n",intercomm.Get_rank(),partner); unsigned nn=buffer.size(); vector rbuf(nn); localDeltaBias=-plumedMain.getBias(); - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { Communicator::Request req=intercomm.Isend(buffer,partner,1066); intercomm.Recv(rbuf,partner,1066); req.wait(); @@ -218,7 +218,7 @@ void GREX::calculate(){ plumedMain.setExchangeStep(false); localDeltaBias+=plumedMain.getBias(); localDeltaBias+=localUSwap-localUNow; - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { Communicator::Request req=intercomm.Isend(localDeltaBias,partner,1067); intercomm.Recv(foreignDeltaBias,partner,1067); req.wait(); diff --git a/src/core/GREX.h b/src/core/GREX.h index 3a2553e4cf..2266d1581f 100644 --- a/src/core/GREX.h +++ b/src/core/GREX.h @@ -26,7 +26,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class PlumedMain; class Atoms; diff --git a/src/core/MDAtoms.cpp b/src/core/MDAtoms.cpp index ba95c8facd..1f11ad9cd4 100644 --- a/src/core/MDAtoms.cpp +++ b/src/core/MDAtoms.cpp @@ -35,7 +35,7 @@ namespace PLMD { /// IT IS STILL UNDOCUMENTED. IT PROBABLY NEEDS A STRONG CLEANUP template class MDAtomsTyped: -public MDAtomsBase + public MDAtomsBase { T scalep,scalef; T scaleb,scalev; @@ -58,13 +58,13 @@ public MDAtomsBase void setp(void*p,int i); void setf(void*f,int i); void setUnits(const Units&,const Units&); - void MD2double(const void*m,double&d)const{ + void MD2double(const void*m,double&d)const { d=double(*(static_cast(m))); } - void double2MD(const double&d,void*m)const{ + void double2MD(const double&d,void*m)const { *(static_cast(m))=T(d); } - Vector getMDforces(const unsigned index)const{ + Vector getMDforces(const unsigned index)const { Vector force(fx[stride*index],fy[stride*index],fz[stride*index]); return force/scalef; } @@ -81,7 +81,7 @@ public MDAtomsBase }; template -void MDAtomsTyped::setUnits(const Units& units,const Units& MDUnits){ +void MDAtomsTyped::setUnits(const Units& units,const Units& MDUnits) { double lscale=units.getLength()/MDUnits.getLength(); double escale=units.getEnergy()/MDUnits.getEnergy(); double cscale=units.getCharge()/MDUnits.getCharge(); @@ -97,15 +97,15 @@ void MDAtomsTyped::setUnits(const Units& units,const Units& MDUnits){ } template -void MDAtomsTyped::getBox(Tensor&box)const{ - if(this->box) for(int i=0;i<3;i++)for(int j=0;j<3;j++) box(i,j)=this->box[3*i+j]*scaleb; +void MDAtomsTyped::getBox(Tensor&box)const { + if(this->box) for(int i=0; i<3; i++)for(int j=0; j<3; j++) box(i,j)=this->box[3*i+j]*scaleb; else box.zero(); } template -void MDAtomsTyped::getPositions(const vector&index,vector&positions)const{ +void MDAtomsTyped::getPositions(const vector&index,vector&positions)const { // cannot be parallelized with omp because access to positions is not ordered - for(unsigned i=0;i::getPositions(const vector&index,vector&positi } template -void MDAtomsTyped::getPositions(unsigned j,unsigned k,vector&positions)const{ +void MDAtomsTyped::getPositions(unsigned j,unsigned k,vector&positions)const { #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(&positions[j],(k-j))) - for(unsigned i=j;i::getPositions(unsigned j,unsigned k,vector&position template -void MDAtomsTyped::getLocalPositions(vector&positions)const{ +void MDAtomsTyped::getLocalPositions(vector&positions)const { #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(positions)) - for(unsigned i=0;i::getLocalPositions(vector&positions)const{ template -void MDAtomsTyped::getMasses(const vector&index,vector&masses)const{ - if(m) for(unsigned i=0;i::getMasses(const vector&index,vector&masses)const { + if(m) for(unsigned i=0; i -void MDAtomsTyped::getCharges(const vector&index,vector&charges)const{ - if(c) for(unsigned i=0;i::getCharges(const vector&index,vector&charges)const { + if(c) for(unsigned i=0; i -void MDAtomsTyped::updateVirial(const Tensor&virial)const{ - if(this->virial) for(int i=0;i<3;i++)for(int j=0;j<3;j++) this->virial[3*i+j]+=T(virial(i,j)*scalev); +void MDAtomsTyped::updateVirial(const Tensor&virial)const { + if(this->virial) for(int i=0; i<3; i++)for(int j=0; j<3; j++) this->virial[3*i+j]+=T(virial(i,j)*scalev); } template -void MDAtomsTyped::updateForces(const vector&index,const vector&forces){ +void MDAtomsTyped::updateForces(const vector&index,const vector&forces) { #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(fx,stride*index.size())) - for(unsigned i=0;i::updateForces(const vector&index,const vector& } template -void MDAtomsTyped::rescaleForces(const vector&index,double factor){ - if(virial) for(unsigned i=0;i<3;i++)for(unsigned j=0;j<3;j++) virial[3*i+j]*=T(factor); +void MDAtomsTyped::rescaleForces(const vector&index,double factor) { + if(virial) for(unsigned i=0; i<3; i++)for(unsigned j=0; j<3; j++) virial[3*i+j]*=T(factor); #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(fx,stride*index.size())) - for(unsigned i=0;i::rescaleForces(const vector&index,double factor){ } template -unsigned MDAtomsTyped::getRealPrecision()const{ +unsigned MDAtomsTyped::getRealPrecision()const { return sizeof(T); } template -void MDAtomsTyped::setp(void*pp){ +void MDAtomsTyped::setp(void*pp) { T*p=static_cast(pp); plumed_assert(stride==0 || stride==3); px=p; @@ -188,13 +188,13 @@ void MDAtomsTyped::setp(void*pp){ } template -void MDAtomsTyped::setBox(void*pp){ +void MDAtomsTyped::setBox(void*pp) { box=static_cast(pp); } template -void MDAtomsTyped::setf(void*ff){ +void MDAtomsTyped::setf(void*ff) { T*f=static_cast(ff); plumed_assert(stride==0 || stride==3); fx=f; @@ -204,7 +204,7 @@ void MDAtomsTyped::setf(void*ff){ } template -void MDAtomsTyped::setp(void*pp,int i){ +void MDAtomsTyped::setp(void*pp,int i) { T*p=static_cast(pp); plumed_assert(stride==0 || stride==1); if(i==0)px=p; @@ -214,13 +214,13 @@ void MDAtomsTyped::setp(void*pp,int i){ } template -void MDAtomsTyped::setVirial(void*pp){ +void MDAtomsTyped::setVirial(void*pp) { virial=static_cast(pp); } template -void MDAtomsTyped::setf(void*ff,int i){ +void MDAtomsTyped::setf(void*ff,int i) { T*f=static_cast(ff); plumed_assert(stride==0 || stride==1); if(i==0)fx=f; @@ -230,12 +230,12 @@ void MDAtomsTyped::setf(void*ff,int i){ } template -void MDAtomsTyped::setm(void*m){ +void MDAtomsTyped::setm(void*m) { this->m=static_cast(m); } template -void MDAtomsTyped::setc(void*c){ +void MDAtomsTyped::setc(void*c) { this->c=static_cast(c); } @@ -260,10 +260,10 @@ MDAtomsTyped::MDAtomsTyped(): virial(NULL) {} -MDAtomsBase* MDAtomsBase::create(unsigned p){ - if(p==sizeof(double)){ +MDAtomsBase* MDAtomsBase::create(unsigned p) { + if(p==sizeof(double)) { return new MDAtomsTyped; - } else if (p==sizeof(float)){ + } else if (p==sizeof(float)) { return new MDAtomsTyped; } std::string pp; diff --git a/src/core/MDAtoms.h b/src/core/MDAtoms.h index 04932a21f7..3926d47f13 100644 --- a/src/core/MDAtoms.h +++ b/src/core/MDAtoms.h @@ -51,7 +51,7 @@ class MDAtomsBase /// Creates an MDAtomsTyped object such that sizeof(T)==n static MDAtomsBase* create(unsigned n); /// Virtual destructor, just to allow inheritance. - virtual ~MDAtomsBase(){} + virtual ~MDAtomsBase() {} /// Get the size of MD-real virtual unsigned getRealPrecision()const=0; /// Set a pointer to the mass array in the MD code diff --git a/src/core/PlumedMain.cpp b/src/core/PlumedMain.cpp index ff4e9b79f3..dd96581db4 100644 --- a/src/core/PlumedMain.cpp +++ b/src/core/PlumedMain.cpp @@ -49,12 +49,12 @@ using namespace std; #include "PlumedMainEnum.inc" -namespace PLMD{ +namespace PLMD { -const std::unordered_map & plumedMainWordMap(){ +const std::unordered_map & plumedMainWordMap() { static std::unordered_map word_map; static bool init=false; - if(!init){ + if(!init) { #include "PlumedMainMap.inc" } init=true; @@ -92,7 +92,7 @@ PlumedMain::PlumedMain(): stopwatch.pause(); } -PlumedMain::~PlumedMain(){ +PlumedMain::~PlumedMain() { stopwatch.start(); stopwatch.stop(); if(initialized) log< words=Tools::getWords(word); unsigned nw=words.size(); - if(nw==0){ + if(nw==0) { // do nothing } else { int iword=-1; @@ -131,333 +131,333 @@ void PlumedMain::cmd(const std::string & word,void*val){ const auto it=plumedMainWordMap().find(words[0]); if(it!=plumedMainWordMap().end()) iword=it->second; switch(iword) { - case cmd_setBox: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setBox(val); - break; - case cmd_setPositions: - CHECK_INIT(initialized,word); - atoms.setPositions(val); - break; - case cmd_setMasses: - CHECK_INIT(initialized,word); - atoms.setMasses(val); - break; - case cmd_setCharges: - CHECK_INIT(initialized,word); - atoms.setCharges(val); - break; - case cmd_setPositionsX: - CHECK_INIT(initialized,word); - atoms.setPositions(val,0); - break; - case cmd_setPositionsY: - CHECK_INIT(initialized,word); - atoms.setPositions(val,1); - break; - case cmd_setPositionsZ: - CHECK_INIT(initialized,word); - atoms.setPositions(val,2); - break; - case cmd_setVirial: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setVirial(val); - break; - case cmd_setEnergy: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setEnergy(val); - break; - case cmd_setForces: - CHECK_INIT(initialized,word); - atoms.setForces(val); - break; - case cmd_setForcesX: - CHECK_INIT(initialized,word); - atoms.setForces(val,0); - break; - case cmd_setForcesY: - CHECK_INIT(initialized,word); - atoms.setForces(val,1); - break; - case cmd_setForcesZ: - CHECK_INIT(initialized,word); - atoms.setForces(val,2); - break; - case cmd_calc: - CHECK_INIT(initialized,word); - calc(); - break; - case cmd_prepareDependencies: - CHECK_INIT(initialized,word); - prepareDependencies(); - break; - case cmd_shareData: - CHECK_INIT(initialized,word); - shareData(); - break; - case cmd_prepareCalc: - CHECK_INIT(initialized,word); - prepareCalc(); - break; - case cmd_performCalc: - CHECK_INIT(initialized,word); - performCalc(); - break; - case cmd_performCalcNoUpdate: - CHECK_INIT(initialized,word); - performCalcNoUpdate(); - break; - case cmd_update: - CHECK_INIT(initialized,word); - update(); - break; - case cmd_setStep: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - step=(*static_cast(val)); - atoms.startStep(); - break; - case cmd_setStepLong: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - step=(*static_cast(val)); - atoms.startStep(); - break; - // words used less frequently: - case cmd_setAtomsNlocal: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setAtomsNlocal(*static_cast(val)); - break; - case cmd_setAtomsGatindex: - CHECK_INIT(initialized,word); - atoms.setAtomsGatindex(static_cast(val),false); - break; - case cmd_setAtomsFGatindex: - CHECK_INIT(initialized,word); - atoms.setAtomsGatindex(static_cast(val),true); - break; - case cmd_setAtomsContiguous: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setAtomsContiguous(*static_cast(val)); - break; - case cmd_createFullList: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.createFullList(static_cast(val)); - break; - case cmd_getFullList: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.getFullList(static_cast(val)); - break; - case cmd_clearFullList: - CHECK_INIT(initialized,word); - atoms.clearFullList(); - break; - case cmd_read: - CHECK_INIT(initialized,word); - if(val)readInputFile(static_cast(val)); - else readInputFile("plumed.dat"); - break; - case cmd_readInputLine: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - readInputLine(static_cast(val)); - break; - case cmd_clear: - CHECK_INIT(initialized,word); - actionSet.clearDelete(); - break; - case cmd_getApiVersion: - CHECK_NOTNULL(val,word); - *(static_cast(val))=4; - break; - // commands which can be used only before initialization: - case cmd_init: - CHECK_NOTINIT(initialized,word); - init(); - break; - case cmd_setRealPrecision: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setRealPrecision(*static_cast(val)); - break; - case cmd_setMDLengthUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDLengthUnits(d); - break; - case cmd_setMDChargeUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDChargeUnits(d); - break; - case cmd_setMDMassUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDMassUnits(d); - break; - case cmd_setMDEnergyUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDEnergyUnits(d); - break; - case cmd_setMDTimeUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDTimeUnits(d); - break; - case cmd_setNaturalUnits: + case cmd_setBox: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setBox(val); + break; + case cmd_setPositions: + CHECK_INIT(initialized,word); + atoms.setPositions(val); + break; + case cmd_setMasses: + CHECK_INIT(initialized,word); + atoms.setMasses(val); + break; + case cmd_setCharges: + CHECK_INIT(initialized,word); + atoms.setCharges(val); + break; + case cmd_setPositionsX: + CHECK_INIT(initialized,word); + atoms.setPositions(val,0); + break; + case cmd_setPositionsY: + CHECK_INIT(initialized,word); + atoms.setPositions(val,1); + break; + case cmd_setPositionsZ: + CHECK_INIT(initialized,word); + atoms.setPositions(val,2); + break; + case cmd_setVirial: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setVirial(val); + break; + case cmd_setEnergy: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setEnergy(val); + break; + case cmd_setForces: + CHECK_INIT(initialized,word); + atoms.setForces(val); + break; + case cmd_setForcesX: + CHECK_INIT(initialized,word); + atoms.setForces(val,0); + break; + case cmd_setForcesY: + CHECK_INIT(initialized,word); + atoms.setForces(val,1); + break; + case cmd_setForcesZ: + CHECK_INIT(initialized,word); + atoms.setForces(val,2); + break; + case cmd_calc: + CHECK_INIT(initialized,word); + calc(); + break; + case cmd_prepareDependencies: + CHECK_INIT(initialized,word); + prepareDependencies(); + break; + case cmd_shareData: + CHECK_INIT(initialized,word); + shareData(); + break; + case cmd_prepareCalc: + CHECK_INIT(initialized,word); + prepareCalc(); + break; + case cmd_performCalc: + CHECK_INIT(initialized,word); + performCalc(); + break; + case cmd_performCalcNoUpdate: + CHECK_INIT(initialized,word); + performCalcNoUpdate(); + break; + case cmd_update: + CHECK_INIT(initialized,word); + update(); + break; + case cmd_setStep: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + step=(*static_cast(val)); + atoms.startStep(); + break; + case cmd_setStepLong: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + step=(*static_cast(val)); + atoms.startStep(); + break; + // words used less frequently: + case cmd_setAtomsNlocal: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setAtomsNlocal(*static_cast(val)); + break; + case cmd_setAtomsGatindex: + CHECK_INIT(initialized,word); + atoms.setAtomsGatindex(static_cast(val),false); + break; + case cmd_setAtomsFGatindex: + CHECK_INIT(initialized,word); + atoms.setAtomsGatindex(static_cast(val),true); + break; + case cmd_setAtomsContiguous: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setAtomsContiguous(*static_cast(val)); + break; + case cmd_createFullList: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.createFullList(static_cast(val)); + break; + case cmd_getFullList: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.getFullList(static_cast(val)); + break; + case cmd_clearFullList: + CHECK_INIT(initialized,word); + atoms.clearFullList(); + break; + case cmd_read: + CHECK_INIT(initialized,word); + if(val)readInputFile(static_cast(val)); + else readInputFile("plumed.dat"); + break; + case cmd_readInputLine: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + readInputLine(static_cast(val)); + break; + case cmd_clear: + CHECK_INIT(initialized,word); + actionSet.clearDelete(); + break; + case cmd_getApiVersion: + CHECK_NOTNULL(val,word); + *(static_cast(val))=4; + break; + // commands which can be used only before initialization: + case cmd_init: + CHECK_NOTINIT(initialized,word); + init(); + break; + case cmd_setRealPrecision: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setRealPrecision(*static_cast(val)); + break; + case cmd_setMDLengthUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDLengthUnits(d); + break; + case cmd_setMDChargeUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDChargeUnits(d); + break; + case cmd_setMDMassUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDMassUnits(d); + break; + case cmd_setMDEnergyUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDEnergyUnits(d); + break; + case cmd_setMDTimeUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDTimeUnits(d); + break; + case cmd_setNaturalUnits: // set the boltzman constant for MD in natural units (kb=1) // only needed in LJ codes if the MD is passing temperatures to plumed (so, not yet...) // use as cmd("setNaturalUnits") - CHECK_NOTINIT(initialized,word); - atoms.setMDNaturalUnits(true); - break; - case cmd_setNoVirial: - CHECK_NOTINIT(initialized,word); - novirial=true; - break; - case cmd_setPlumedDat: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - plumedDat=static_cast(val); - break; - case cmd_setMPIComm: - CHECK_NOTINIT(initialized,word); - comm.Set_comm(val); - atoms.setDomainDecomposition(comm); - break; - case cmd_setMPIFComm: - CHECK_NOTINIT(initialized,word); - comm.Set_fcomm(val); - atoms.setDomainDecomposition(comm); - break; - case cmd_setMPImultiSimComm: - CHECK_NOTINIT(initialized,word); - multi_sim_comm.Set_comm(val); - break; - case cmd_setNatoms: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setNatoms(*static_cast(val)); - break; - case cmd_setTimestep: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setTimeStep(val); - break; - /* ADDED WITH API==2 */ - case cmd_setKbT: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setKbT(val); - break; - /* ADDED WITH API==3 */ - case cmd_setRestart: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - if(*static_cast(val)!=0) restart=true; - break; - /* ADDED WITH API==4 */ - case cmd_doCheckPoint: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - doCheckPoint = false; - if(*static_cast(val)!=0) doCheckPoint = true; - break; - /* STOP API */ - case cmd_setMDEngine: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - MDEngine=static_cast(val); - break; - case cmd_setLog: - CHECK_NOTINIT(initialized,word); - log.link(static_cast(val)); - break; - case cmd_setLogFile: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - log.open(static_cast(val)); - break; - // other commands that should be used after initialization: - case cmd_setStopFlag: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - stopFlag=static_cast(val); - break; - case cmd_getExchangesFlag: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.getFlag((*static_cast(val))); - break; - case cmd_setExchangesSeed: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.setSeed((*static_cast(val))); - break; - case cmd_setNumberOfReplicas: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.setNofR((*static_cast(val))); - break; - case cmd_getExchangesList: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.getList((static_cast(val))); - break; - case cmd_runFinalJobs: - CHECK_INIT(initialized,word); - runJobsAtEndOfCalculation(); - break; - case cmd_isEnergyNeeded: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - if(atoms.isEnergyNeeded()) *(static_cast(val))=1; - else *(static_cast(val))=0; - break; - case cmd_getBias: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.double2MD(getBias()/(atoms.getMDUnits().getEnergy()/atoms.getUnits().getEnergy()),val); - break; - case cmd_checkAction: - CHECK_NOTNULL(val,word); - plumed_assert(nw==2); - *(static_cast(val))=(actionRegister().check(words[1]) ? 1:0); - break; - case cmd_GREX: - if(!grex) grex=new GREX(*this); - plumed_massert(grex,"error allocating grex"); - { - std::string kk=words[1]; - for(unsigned i=2;icmd(kk.c_str(),val); - } - break; - case cmd_CLTool: - CHECK_NOTINIT(initialized,word); - if(!cltool) cltool=new CLToolMain; - { - std::string kk=words[1]; - for(unsigned i=2;icmd(kk.c_str(),val); - } - break; - default: - plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands."); - break; + CHECK_NOTINIT(initialized,word); + atoms.setMDNaturalUnits(true); + break; + case cmd_setNoVirial: + CHECK_NOTINIT(initialized,word); + novirial=true; + break; + case cmd_setPlumedDat: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + plumedDat=static_cast(val); + break; + case cmd_setMPIComm: + CHECK_NOTINIT(initialized,word); + comm.Set_comm(val); + atoms.setDomainDecomposition(comm); + break; + case cmd_setMPIFComm: + CHECK_NOTINIT(initialized,word); + comm.Set_fcomm(val); + atoms.setDomainDecomposition(comm); + break; + case cmd_setMPImultiSimComm: + CHECK_NOTINIT(initialized,word); + multi_sim_comm.Set_comm(val); + break; + case cmd_setNatoms: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setNatoms(*static_cast(val)); + break; + case cmd_setTimestep: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setTimeStep(val); + break; + /* ADDED WITH API==2 */ + case cmd_setKbT: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setKbT(val); + break; + /* ADDED WITH API==3 */ + case cmd_setRestart: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + if(*static_cast(val)!=0) restart=true; + break; + /* ADDED WITH API==4 */ + case cmd_doCheckPoint: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + doCheckPoint = false; + if(*static_cast(val)!=0) doCheckPoint = true; + break; + /* STOP API */ + case cmd_setMDEngine: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + MDEngine=static_cast(val); + break; + case cmd_setLog: + CHECK_NOTINIT(initialized,word); + log.link(static_cast(val)); + break; + case cmd_setLogFile: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + log.open(static_cast(val)); + break; + // other commands that should be used after initialization: + case cmd_setStopFlag: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + stopFlag=static_cast(val); + break; + case cmd_getExchangesFlag: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.getFlag((*static_cast(val))); + break; + case cmd_setExchangesSeed: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.setSeed((*static_cast(val))); + break; + case cmd_setNumberOfReplicas: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.setNofR((*static_cast(val))); + break; + case cmd_getExchangesList: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.getList((static_cast(val))); + break; + case cmd_runFinalJobs: + CHECK_INIT(initialized,word); + runJobsAtEndOfCalculation(); + break; + case cmd_isEnergyNeeded: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + if(atoms.isEnergyNeeded()) *(static_cast(val))=1; + else *(static_cast(val))=0; + break; + case cmd_getBias: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.double2MD(getBias()/(atoms.getMDUnits().getEnergy()/atoms.getUnits().getEnergy()),val); + break; + case cmd_checkAction: + CHECK_NOTNULL(val,word); + plumed_assert(nw==2); + *(static_cast(val))=(actionRegister().check(words[1]) ? 1:0); + break; + case cmd_GREX: + if(!grex) grex=new GREX(*this); + plumed_massert(grex,"error allocating grex"); + { + std::string kk=words[1]; + for(unsigned i=2; icmd(kk.c_str(),val); + } + break; + case cmd_CLTool: + CHECK_NOTINIT(initialized,word); + if(!cltool) cltool=new CLToolMain; + { + std::string kk=words[1]; + for(unsigned i=2; icmd(kk.c_str(),val); + } + break; + default: + plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands."); + break; } } stopwatch.pause(); @@ -465,7 +465,7 @@ void PlumedMain::cmd(const std::string & word,void*val){ //////////////////////////////////////////////////////////////////////// -void PlumedMain::init(){ +void PlumedMain::init() { // check that initialization just happens once initialized=true; atoms.init(); @@ -486,7 +486,7 @@ void PlumedMain::init(){ log.printf("Number of atoms: %d\n",atoms.getNatoms()); if(grex) log.printf("GROMACS-like replica exchange is on\n"); log.printf("File suffix: %s\n",getSuffix().c_str()); - if(plumedDat.length()>0){ + if(plumedDat.length()>0) { readInputFile(plumedDat); plumedDat=""; } @@ -504,7 +504,7 @@ void PlumedMain::init(){ log<<"Finished setup\n"; } -void PlumedMain::readInputFile(std::string str){ +void PlumedMain::readInputFile(std::string str) { plumed_assert(initialized); log.printf("FILE: %s\n",str.c_str()); IFile ifile; @@ -519,34 +519,34 @@ void PlumedMain::readInputFile(std::string str){ pilots=actionSet.select(); } -void PlumedMain::readInputLine(const std::string & str){ +void PlumedMain::readInputLine(const std::string & str) { plumed_assert(initialized); if(str.empty()) return; std::vector words=Tools::getWords(str); citations.clear(); readInputWords(words); - if(!citations.empty()){ + if(!citations.empty()) { log<<"Relevant bibliography:\n"; log< & words){ +void PlumedMain::readInputWords(const std::vector & words) { plumed_assert(initialized); if(words.empty())return; else if(words[0]=="ENDPLUMED") return; - else if(words[0]=="_SET_SUFFIX"){ + else if(words[0]=="_SET_SUFFIX") { plumed_assert(words.size()==2); setSuffix(words[1]); } else { std::vector interpreted(words); Tools::interpretLabel(interpreted); Action* action=actionRegister().create(ActionOptions(*this,interpreted)); - if(!action){ + if(!action) { log<<"ERROR\n"; log<<"I cannot understand line:"; - for(unsigned i=0;i & words){ //////////////////////////////////////////////////////////////////////// -void PlumedMain::exit(int c){ +void PlumedMain::exit(int c) { comm.Abort(c); } -Log& PlumedMain::getLog(){ +Log& PlumedMain::getLog() { return log; } -void PlumedMain::calc(){ +void PlumedMain::calc() { prepareCalc(); performCalc(); } -void PlumedMain::prepareCalc(){ +void PlumedMain::prepareCalc() { prepareDependencies(); shareData(); } @@ -582,7 +582,7 @@ void PlumedMain::prepareCalc(){ // here we have the main steps in "calc()" // they can be called individually, but the standard thing is to // traverse them in this order: -void PlumedMain::prepareDependencies(){ +void PlumedMain::prepareDependencies() { stopwatch.start("1 Prepare dependencies"); @@ -593,24 +593,24 @@ void PlumedMain::prepareDependencies(){ // which can be dynamically changed). // First switch off all actions - for(const auto & p : actionSet){ - p->deactivate(); - //I think this is already done inside deactivate - //(*p)->clearOptions(); + for(const auto & p : actionSet) { + p->deactivate(); + //I think this is already done inside deactivate + //(*p)->clearOptions(); } // for optimization, an "active" flag remains false if no action at all is active active=false; - for(unsigned i=0;ionStep()){ + for(unsigned i=0; ionStep()) { pilots[i]->activate(); active=true; - } + } }; // also, if one of them is the total energy, tell to atoms that energy should be collected - for(const auto & p : actionSet){ - if(p->isActive()){ + for(const auto & p : actionSet) { + if(p->isActive()) { if(p->checkNeedsGradients()) p->setOption("GRADIENTS"); } } @@ -618,7 +618,7 @@ void PlumedMain::prepareDependencies(){ stopwatch.stop("1 Prepare dependencies"); } -void PlumedMain::shareData(){ +void PlumedMain::shareData() { // atom positions are shared (but only if there is something to do) if(!active)return; stopwatch.start("2 Sharing data"); @@ -626,27 +626,27 @@ void PlumedMain::shareData(){ stopwatch.stop("2 Sharing data"); } -void PlumedMain::performCalcNoUpdate(){ +void PlumedMain::performCalcNoUpdate() { waitData(); justCalculate(); backwardPropagate(); } -void PlumedMain::performCalc(){ +void PlumedMain::performCalc() { waitData(); justCalculate(); backwardPropagate(); update(); } -void PlumedMain::waitData(){ +void PlumedMain::waitData() { if(!active)return; stopwatch.start("3 Waiting for data"); if(atoms.getNatoms()>0) atoms.wait(); stopwatch.stop("3 Waiting for data"); } -void PlumedMain::justCalculate(){ +void PlumedMain::justCalculate() { if(!active)return; stopwatch.start("4 Calculating (forward loop)"); bias=0.0; @@ -654,10 +654,10 @@ void PlumedMain::justCalculate(){ int iaction=0; // calculate the active actions in order (assuming *backward* dependence) - for(const auto & p : actionSet){ - if(p->isActive()){ + for(const auto & p : actionSet) { + if(p->isActive()) { std::string actionNumberLabel; - if(detailedTimers){ + if(detailedTimers) { Tools::convert(iaction,actionNumberLabel); actionNumberLabel="4A "+actionNumberLabel+" "+p->getLabel(); stopwatch.start(actionNumberLabel); @@ -674,12 +674,12 @@ void PlumedMain::justCalculate(){ } if(p->checkNumericalDerivatives()) p->calculateNumericalDerivatives(); else p->calculate(); - // This retrieves components called bias + // This retrieves components called bias if(av) bias+=av->getOutputQuantity("bias"); if(av) work+=av->getOutputQuantity("work"); - if(av)av->setGradientsIfNeeded(); + if(av)av->setGradientsIfNeeded(); ActionWithVirtualAtom*avv=dynamic_cast(p); - if(avv)avv->setGradientsIfNeeded(); + if(avv)avv->setGradientsIfNeeded(); if(detailedTimers) stopwatch.stop(actionNumberLabel); } iaction++; @@ -687,22 +687,22 @@ void PlumedMain::justCalculate(){ stopwatch.stop("4 Calculating (forward loop)"); } -void PlumedMain::justApply(){ +void PlumedMain::justApply() { backwardPropagate(); update(); } - -void PlumedMain::backwardPropagate(){ + +void PlumedMain::backwardPropagate() { if(!active)return; int iaction=0; stopwatch.start("5 Applying (backward loop)"); // apply them in reverse order - for(auto pp=actionSet.rbegin();pp!=actionSet.rend();++pp){ + for(auto pp=actionSet.rbegin(); pp!=actionSet.rend(); ++pp) { const auto & p(*pp); - if(p->isActive()){ + if(p->isActive()) { std::string actionNumberLabel; - if(detailedTimers){ + if(detailedTimers) { Tools::convert(iaction,actionNumberLabel); actionNumberLabel="5A "+actionNumberLabel+" "+p->getLabel(); stopwatch.start(actionNumberLabel); @@ -725,28 +725,28 @@ void PlumedMain::backwardPropagate(){ stopwatch.stop("5 Applying (backward loop)"); } -void PlumedMain::update(){ +void PlumedMain::update() { if(!active)return; stopwatch.start("6 Update"); // update step (for statistics, etc) updateFlags.push(true); - for(const auto & p : actionSet){ + for(const auto & p : actionSet) { p->beforeUpdate(); if(p->isActive() && p->checkUpdate() && updateFlagsTop()) p->update(); } while(!updateFlags.empty()) updateFlags.pop(); if(!updateFlags.empty()) plumed_merror("non matching changes in the update flags"); // Check that no action has told the calculation to stop - if(stopNow){ - if(stopFlag) (*stopFlag)=1; - else plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)"); - } + if(stopNow) { + if(stopFlag) (*stopFlag)=1; + else plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)"); + } // flush by default every 10000 steps // hopefully will not affect performance // also if receive checkpointing signal - if(step%10000==0||doCheckPoint){ + if(step%10000==0||doCheckPoint) { fflush(); log.flush(); for(const auto & p : actionSet) p->fflush(); @@ -754,49 +754,49 @@ void PlumedMain::update(){ stopwatch.stop("6 Update"); } -void PlumedMain::load(const std::string& ss){ - if(DLLoader::installed()){ - string s=ss; - size_t n=s.find_last_of("."); - string extension=""; - string base=s; - if(n!=std::string::npos && n0) log<<" (only on master node)"; - log<<"\n"; - if(comm.Get_rank()==0) system(cmd.c_str()); - comm.Barrier(); - base="./"+base; - } - s=base+"."+config::getSoExt(); - void *p=dlloader.load(s); - if(!p){ - const std::string error_msg="I cannot load library " + ss + " " + dlloader.error(); - log<<"ERROR\n"; - log<0) log<<" (only on master node)"; + log<<"\n"; + if(comm.Get_rank()==0) system(cmd.c_str()); + comm.Barrier(); + base="./"+base; + } + s=base+"."+config::getSoExt(); + void *p=dlloader.load(s); + if(!p) { + const std::string error_msg="I cannot load library " + ss + " " + dlloader.error(); + log<<"ERROR\n"; + log<flush(); } } -void PlumedMain::insertFile(FileBase&f){ +void PlumedMain::insertFile(FileBase&f) { files.insert(&f); } -void PlumedMain::eraseFile(FileBase&f){ +void PlumedMain::eraseFile(FileBase&f) { files.erase(&f); } -void PlumedMain::stop(){ +void PlumedMain::stop() { stopNow=true; } -void PlumedMain::runJobsAtEndOfCalculation(){ - for(const auto & p : actionSet){ - p->runFinalJobs(); +void PlumedMain::runJobsAtEndOfCalculation() { + for(const auto & p : actionSet) { + p->runFinalJobs(); } -} +} } diff --git a/src/core/PlumedMain.h b/src/core/PlumedMain.h index ced8d15c9a..ad26628444 100644 --- a/src/core/PlumedMain.h +++ b/src/core/PlumedMain.h @@ -171,104 +171,104 @@ class PlumedMain: PlumedMain(); // this is to access to WithCmd versions of cmd (allowing overloading of a virtual method) using WithCmd::cmd; -/** - cmd method, accessible with standard Plumed.h interface. - \param key The name of the command to be executed. - \param val The argument of the command to be executed. - It is called as plumed_cmd() or as PLMD::Plumed::cmd() - It is the interpreter for plumed commands. It basically contains the definition of the plumed interface. - If you want to add a new functionality to the interface between plumed - and an MD engine, this is the right place - Notice that this interface should always keep retro-compatibility -*/ + /** + cmd method, accessible with standard Plumed.h interface. + \param key The name of the command to be executed. + \param val The argument of the command to be executed. + It is called as plumed_cmd() or as PLMD::Plumed::cmd() + It is the interpreter for plumed commands. It basically contains the definition of the plumed interface. + If you want to add a new functionality to the interface between plumed + and an MD engine, this is the right place + Notice that this interface should always keep retro-compatibility + */ void cmd(const std::string&key,void*val=NULL); ~PlumedMain(); -/** - Read an input file. - \param str name of the file -*/ + /** + Read an input file. + \param str name of the file + */ void readInputFile(std::string str); -/** - Read an input string. - \param str name of the string -*/ + /** + Read an input string. + \param str name of the string + */ void readInputWords(const std::vector & str); -/** - Read an input string. - \param str name of the string - At variance with readInputWords(), this is splitting the string into words -*/ + /** + Read an input string. + \param str name of the string + At variance with readInputWords(), this is splitting the string into words + */ void readInputLine(const std::string & str); -/** - Initialize the object. - Should be called once. -*/ + /** + Initialize the object. + Should be called once. + */ void init(); -/** - Prepare the calculation. - Here it is checked which are the active Actions and communication of the relevant atoms is initiated. - Shortcut for prepareDependencies() + shareData() -*/ + /** + Prepare the calculation. + Here it is checked which are the active Actions and communication of the relevant atoms is initiated. + Shortcut for prepareDependencies() + shareData() + */ void prepareCalc(); -/** - Prepare the list of active Actions and needed atoms. - Scan the Actions to see which are active and which are not, so as to prepare a list of - the atoms needed at this step. -*/ + /** + Prepare the list of active Actions and needed atoms. + Scan the Actions to see which are active and which are not, so as to prepare a list of + the atoms needed at this step. + */ void prepareDependencies(); -/** - Share the needed atoms. - In asynchronous implementations, this method sends the required atoms to all the plumed processes, - without waiting for the communication to complete. -*/ + /** + Share the needed atoms. + In asynchronous implementations, this method sends the required atoms to all the plumed processes, + without waiting for the communication to complete. + */ void shareData(); -/** - Perform the calculation. - Shortcut for waitData() + justCalculate() + justApply(). - Equivalently: waitData() + justCalculate() + backwardPropagate() + update(). -*/ + /** + Perform the calculation. + Shortcut for waitData() + justCalculate() + justApply(). + Equivalently: waitData() + justCalculate() + backwardPropagate() + update(). + */ void performCalc(); -/** - Perform the calculation without update() - Shortcut for: waitData() + justCalculate() + backwardPropagate() -*/ + /** + Perform the calculation without update() + Shortcut for: waitData() + justCalculate() + backwardPropagate() + */ void performCalcNoUpdate(); -/** - Complete PLUMED calculation. - Shortcut for prepareCalc() + performCalc() -*/ + /** + Complete PLUMED calculation. + Shortcut for prepareCalc() + performCalc() + */ void calc(); -/** - Scatters the needed atoms. - In asynchronous implementations, this method waits for the communications started in shareData() - to be completed. Otherwise, just send around needed atoms. -*/ + /** + Scatters the needed atoms. + In asynchronous implementations, this method waits for the communications started in shareData() + to be completed. Otherwise, just send around needed atoms. + */ void waitData(); -/** - Perform the forward loop on active actions. -*/ + /** + Perform the forward loop on active actions. + */ void justCalculate(); -/** - Backward propagate and update. - Shortcut for backwardPropagate() + update() - I leave it here for backward compatibility -*/ + /** + Backward propagate and update. + Shortcut for backwardPropagate() + update() + I leave it here for backward compatibility + */ void justApply(); -/** - Perform the backward loop on active actions. - Needed to apply the forces back. -*/ + /** + Perform the backward loop on active actions. + Needed to apply the forces back. + */ void backwardPropagate(); -/** - Call the update() method. -*/ + /** + Call the update() method. + */ void update(); -/** - If there are calculations that need to be done at the very end of the calculations this - makes sures they are done -*/ + /** + If there are calculations that need to be done at the very end of the calculations this + makes sures they are done + */ void runJobsAtEndOfCalculation(); /// Reference to atoms object Atoms& getAtoms(); @@ -277,7 +277,7 @@ class PlumedMain: /// Referenge to the log stream Log & getLog(); /// Return the number of the step - long int getStep()const{return step;} + long int getStep()const {return step;} /// Stop the run void exit(int c=0); /// Load a shared library @@ -305,8 +305,8 @@ class PlumedMain: /// Check if restarting bool getRestart()const; /// Set restart flag - void setRestart(bool f){restart=f;} -/// Check if checkpointing + void setRestart(bool f) {restart=f;} +/// Check if checkpointing bool getCPT()const; /// Set exchangeStep flag void setExchangeStep(bool f); @@ -322,7 +322,7 @@ class PlumedMain: void resetActive(bool active); /// Access to exchange patterns - ExchangePatterns& getExchangePatterns(){return exchangePatterns;} + ExchangePatterns& getExchangePatterns() {return exchangePatterns;} /// Push a state to update flags void updateFlagsPush(bool); @@ -336,62 +336,62 @@ class PlumedMain: // FAST INLINE METHODS: inline -const ActionSet & PlumedMain::getActionSet()const{ +const ActionSet & PlumedMain::getActionSet()const { return actionSet; } inline -Atoms& PlumedMain::getAtoms(){ +Atoms& PlumedMain::getAtoms() { return atoms; } inline -const std::string & PlumedMain::getSuffix()const{ +const std::string & PlumedMain::getSuffix()const { return suffix; } inline -void PlumedMain::setSuffix(const std::string&s){ +void PlumedMain::setSuffix(const std::string&s) { suffix=s; } inline -bool PlumedMain::getRestart()const{ +bool PlumedMain::getRestart()const { return restart; } inline -bool PlumedMain::getCPT()const{ +bool PlumedMain::getCPT()const { return doCheckPoint; } inline -void PlumedMain::setExchangeStep(bool s){ +void PlumedMain::setExchangeStep(bool s) { exchangeStep=s; } inline -bool PlumedMain::getExchangeStep()const{ +bool PlumedMain::getExchangeStep()const { return exchangeStep; } inline -void PlumedMain::resetActive(bool active){ +void PlumedMain::resetActive(bool active) { this->active=active; } inline -void PlumedMain::updateFlagsPush(bool on){ +void PlumedMain::updateFlagsPush(bool on) { updateFlags.push(on); } inline -void PlumedMain::updateFlagsPop(){ +void PlumedMain::updateFlagsPop() { updateFlags.pop(); } inline -bool PlumedMain::updateFlagsTop(){ +bool PlumedMain::updateFlagsTop() { return updateFlags.top(); } diff --git a/src/core/PlumedMainInitializer.cpp b/src/core/PlumedMainInitializer.cpp index 20244e257c..b7fc8e3e45 100644 --- a/src/core/PlumedMainInitializer.cpp +++ b/src/core/PlumedMainInitializer.cpp @@ -43,16 +43,16 @@ typedef struct { /* These functions should be accessible from C, since they might be statically used from Plumed.c (for static binding) */ -extern "C" void*plumedmain_create(){ +extern "C" void*plumedmain_create() { return new PLMD::PlumedMain; } -extern "C" void plumedmain_cmd(void*plumed,const char*key,const void*val){ +extern "C" void plumedmain_cmd(void*plumed,const char*key,const void*val) { plumed_massert(plumed,"trying to use a plumed object which is not initialized"); static_cast(plumed)->cmd(key,val); } -extern "C" void plumedmain_finalize(void*plumed){ +extern "C" void plumedmain_finalize(void*plumed) { plumed_massert(plumed,"trying to deallocate a plumed object which is not initialized"); delete static_cast(plumed); } @@ -60,16 +60,16 @@ extern "C" void plumedmain_finalize(void*plumed){ /* This refers to a function implemented in Plumed.c */ extern "C" plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*); -namespace PLMD{ +namespace PLMD { /// Static object which registers Plumed. /// This is a static object which, during its construction at startup, /// registers the pointers to plumedmain_create, plumedmain_cmd and plumedmain_finalize /// to the plumed_kernel_register function -static class PlumedMainInitializer{ - public: - PlumedMainInitializer(){ - plumed_plumedmain_function_holder fh={plumedmain_create,plumedmain_cmd,plumedmain_finalize}; +static class PlumedMainInitializer { +public: + PlumedMainInitializer() { + plumed_plumedmain_function_holder fh= {plumedmain_create,plumedmain_cmd,plumedmain_finalize}; plumed_kernel_register(&fh); } } RegisterMe; diff --git a/src/core/SetupMolInfo.cpp b/src/core/SetupMolInfo.cpp index af6a4d5138..662ddfb1c4 100644 --- a/src/core/SetupMolInfo.cpp +++ b/src/core/SetupMolInfo.cpp @@ -38,24 +38,24 @@ compilation will exclude it from plumed. */ -void SetupMolInfo::registerKeywords( Keywords& keys ){ +void SetupMolInfo::registerKeywords( Keywords& keys ) { ActionSetup::registerKeywords(keys); keys.add("compulsory","STRUCTURE","a file in pdb format containing a reference structure. " - "This is used to defines the atoms in the various residues, chains, etc . " - "For more details on the PDB file format visit http://www.wwpdb.org/docs.html"); + "This is used to defines the atoms in the various residues, chains, etc . " + "For more details on the PDB file format visit http://www.wwpdb.org/docs.html"); keys.add("compulsory","MOLTYPE","protein","what kind of molecule is contained in the pdb file"); keys.add("atoms","CHAIN","(for masochists ( mostly Davide Branduardi ) ) The atoms involved in each of the chains of interest in the structure."); } -SetupMolInfo::~SetupMolInfo(){ +SetupMolInfo::~SetupMolInfo() { delete &pdb; } SetupMolInfo::SetupMolInfo( const ActionOptions&ao ): -Action(ao), -ActionSetup(ao), -ActionAtomistic(ao), -pdb(*new(PDB)) + Action(ao), + ActionSetup(ao), + ActionAtomistic(ao), + pdb(*new(PDB)) { // Read what is contained in the pdb file parse("MOLTYPE",mytype); @@ -65,126 +65,126 @@ pdb(*new(PDB)) std::vector backbone; parseAtomList("CHAIN",backbone); - if( read_backbone.size()==0 ){ - for(unsigned i=1;;++i){ - parseAtomList("CHAIN",i,backbone); - if( backbone.size()==0 ) break; - read_backbone.push_back(backbone); - backbone.resize(0); - } - } else { + if( read_backbone.size()==0 ) { + for(unsigned i=1;; ++i) { + parseAtomList("CHAIN",i,backbone); + if( backbone.size()==0 ) break; read_backbone.push_back(backbone); + backbone.resize(0); + } + } else { + read_backbone.push_back(backbone); } - if( read_backbone.size()==0 ){ + if( read_backbone.size()==0 ) { std::string reference; parse("STRUCTURE",reference); if( ! pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/plumed.getAtoms().getUnits().getLength()))plumed_merror("missing input file " + reference ); std::vector chains; pdb.getChainNames( chains ); log.printf(" pdb file named %s contains %u chains \n",reference.c_str(), static_cast(chains.size())); - for(unsigned i=0;i& restrings, const std::string& fortype, std::vector< std::vector >& backbone ){ +void SetupMolInfo::getBackbone( std::vector& restrings, const std::string& fortype, std::vector< std::vector >& backbone ) { if( fortype!=mytype ) error("cannot calculate a variable designed for " + fortype + " molecules for molecule type " + mytype ); if( MolDataClass::numberOfAtomsPerResidueInBackbone( mytype )==0 ) error("backbone is not defined for molecule type " + mytype ); - if( read_backbone.size()!=0 ){ - if( restrings.size()!=1 ) error("cannot interpret anything other than all for residues when using CHAIN keywords"); - if( restrings[0]!="all" ) error("cannot interpret anything other than all for residues when using CHAIN keywords"); - backbone.resize( read_backbone.size() ); - for(unsigned i=0;i chains; pdb.getChainNames( chains ); - for(unsigned i=0;i chains; pdb.getChainNames( chains ); + for(unsigned i=0; i > segments; - std::vector thissegment; - Tools::convert(restrings[0],nk); thissegment.push_back(nk); - for(unsigned i=1;i > segments; + std::vector thissegment; + Tools::convert(restrings[0],nk); thissegment.push_back(nk); + for(unsigned i=1; i atomnumbers; - for(unsigned i=0;i atomnumbers; + for(unsigned i=0; i& atoms )const{ +void SetupMolInfo::interpretSymbol( const std::string& symbol, std::vector& atoms )const { MolDataClass::specialSymbol( mytype, symbol, pdb, atoms ); } -std::string SetupMolInfo::getAtomName(AtomNumber a)const{ +std::string SetupMolInfo::getAtomName(AtomNumber a)const { return pdb.getAtomName(a); } -unsigned SetupMolInfo::getResidueNumber(AtomNumber a)const{ +unsigned SetupMolInfo::getResidueNumber(AtomNumber a)const { return pdb.getResidueNumber(a); } -std::string SetupMolInfo::getResidueName(AtomNumber a)const{ +std::string SetupMolInfo::getResidueName(AtomNumber a)const { return pdb.getResidueName(a); } diff --git a/src/core/SetupMolInfo.h b/src/core/SetupMolInfo.h index f347f616f5..362073b8bd 100644 --- a/src/core/SetupMolInfo.h +++ b/src/core/SetupMolInfo.h @@ -30,9 +30,9 @@ namespace PLMD { class PDB; -class SetupMolInfo : -public ActionSetup, -public ActionAtomistic { +class SetupMolInfo : + public ActionSetup, + public ActionAtomistic { private: /// A pdb file containing the topology PDB& pdb; diff --git a/src/core/TargetDist.cpp b/src/core/TargetDist.cpp index 4a666a8e0e..1bed184498 100644 --- a/src/core/TargetDist.cpp +++ b/src/core/TargetDist.cpp @@ -27,44 +27,44 @@ namespace PLMD { -void TargetDist::read( const PDB& pdb, std::vector ar ){ +void TargetDist::read( const PDB& pdb, std::vector ar ) { // Clear values in target actions - for(unsigned i=0;igetPntrToAction())->clearInputForces(); - (ar[i]->getPntrToAction())->clearDerivatives(); + for(unsigned i=0; igetPntrToAction())->clearInputForces(); + (ar[i]->getPntrToAction())->clearDerivatives(); } // Caclulate target actions from input in PDB file std::vector targ( ar.size() ); - for(unsigned i=0;ivalueHasBeenSet() ){ - targ[i]=ar[i]->get(); - } else { - (ar[i]->getPntrToAction())->calculateFromPDB( pdb ); - targ[i]=ar[i]->get(); - } + for(unsigned i=0; ivalueHasBeenSet() ) { + targ[i]=ar[i]->get(); + } else { + (ar[i]->getPntrToAction())->calculateFromPDB( pdb ); + targ[i]=ar[i]->get(); + } } read( targ, ar ); } -void TargetDist::read( const std::vector& targ, std::vector ar ){ +void TargetDist::read( const std::vector& targ, std::vector ar ) { plumed_assert( targ.size()==ar.size() ); target.resize( ar.size() ); args.resize( ar.size() ); log.printf(" distance from this point in cv space : "); - for(unsigned i=0;i& derivs ){ +double TargetDist::calculate( std::vector& derivs ) { plumed_assert( derivs.size()==args.size() ); double dist=0; - for(unsigned i=0;idifference( target[i], args[i]->get() ); - derivs[i]=tmp; dist+=tmp*tmp; + for(unsigned i=0; idifference( target[i], args[i]->get() ); + derivs[i]=tmp; dist+=tmp*tmp; } dist=sqrt(dist); - for(unsigned i=0;i #include -namespace PLMD{ +namespace PLMD { class Log; class PDB; @@ -33,12 +33,12 @@ class Value; class TargetDist { private: - std::vector args; + std::vector args; std::vector target; Log &log; public: explicit TargetDist(Log& log) : log(log) {} - void read( const PDB& pdb, std::vector args ); + void read( const PDB& pdb, std::vector args ); void read( const std::vector& targ, std::vector ar ); double calculate( std::vector& derivs ); }; diff --git a/src/core/Value.cpp b/src/core/Value.cpp index b1fd605b5a..76d43a0ac0 100644 --- a/src/core/Value.cpp +++ b/src/core/Value.cpp @@ -28,19 +28,19 @@ #include "Atoms.h" #include "PlumedMain.h" -namespace PLMD{ +namespace PLMD { Value::Value(): - action(NULL), - value_set(false), - value(0.0), + action(NULL), + value_set(false), + value(0.0), inputForce(0.0), hasForce(false), - hasDeriv(true), - periodicity(unset), - min(0.0), - max(0.0), - max_minus_min(0.0), + hasDeriv(true), + periodicity(unset), + min(0.0), + max(0.0), + max_minus_min(0.0), inv_max_minus_min(0.0) { } @@ -61,18 +61,18 @@ Value::Value(ActionWithValue* av, const std::string& name, const bool withderiv) { } -void Value::setupPeriodicity(){ - if( min==0 && max==0 ){ - periodicity=notperiodic; +void Value::setupPeriodicity() { + if( min==0 && max==0 ) { + periodicity=notperiodic; } else { - periodicity=periodic; - max_minus_min=max-min; - plumed_massert(max_minus_min>0, "your function has a very strange domain?"); - inv_max_minus_min=1.0/max_minus_min; + periodicity=periodic; + max_minus_min=max-min; + plumed_massert(max_minus_min>0, "your function has a very strange domain?"); + inv_max_minus_min=1.0/max_minus_min; } } -bool Value::isPeriodic()const{ +bool Value::isPeriodic()const { plumed_massert(periodicity!=unset,"periodicity should be set"); return periodicity==periodic; } @@ -81,18 +81,18 @@ bool Value::applyForce(std::vector& forces ) const { if( !hasForce ) return false; plumed_dbg_massert( derivatives.size()==forces.size()," forces array has wrong size" ); const unsigned N=derivatives.size(); - for(unsigned i=0;ierror("could not convert period string " + str_min + " to real"); - str_max=pmax; +void Value::setDomain(const std::string& pmin,const std::string& pmax) { + str_min=pmin; + if( !Tools::convert(str_min,min) ) action->error("could not convert period string " + str_min + " to real"); + str_max=pmax; if( !Tools::convert(str_max,max) ) action->error("could not convert period string " + str_max + " to read"); setupPeriodicity(); } @@ -109,28 +109,28 @@ void Value::getDomain(double&minout,double&maxout) const { maxout=max; } -void Value::setGradients(){ +void Value::setGradients() { gradients.clear(); ActionAtomistic*aa=dynamic_cast(action); ActionWithArguments*aw=dynamic_cast(action); - if(aa){ + if(aa) { Atoms&atoms((aa->plumed).getAtoms()); - for(unsigned j=0;jgetNumberOfAtoms();++j){ + for(unsigned j=0; jgetNumberOfAtoms(); ++j) { AtomNumber an=aa->getAbsoluteIndex(j); - if(atoms.isVirtualAtom(an)){ + if(atoms.isVirtualAtom(an)) { const ActionWithVirtualAtom* a=atoms.getVirtualAtomsAction(an); - for(const auto & p : a->getGradients()){ + for(const auto & p : a->getGradients()) { // controllare l'ordine del matmul: gradients[p.first]+=matmul(Vector(derivatives[3*j],derivatives[3*j+1],derivatives[3*j+2]),p.second); } } else { - for(unsigned i=0;i<3;i++) gradients[an][i]+=derivatives[3*j+i]; + for(unsigned i=0; i<3; i++) gradients[an][i]+=derivatives[3*j+i]; } } - } else if(aw){ + } else if(aw) { std::vector values=aw->getArguments(); - for(unsigned j=0;jgradients){ + for(unsigned j=0; jgradients) { AtomNumber iatom=p.first; gradients[iatom]+=p.second*derivatives[j]; } @@ -138,44 +138,44 @@ void Value::setGradients(){ } else plumed_error(); } -double Value::projection(const Value& v1,const Value&v2){ +double Value::projection(const Value& v1,const Value&v2) { double proj=0.0; const std::map & grad1(v1.gradients); const std::map & grad2(v2.gradients); - for(const auto & p1 : grad1){ + for(const auto & p1 : grad1) { AtomNumber a=p1.first; const auto p2=grad2.find(a); - if(p2!=grad2.end()){ + if(p2!=grad2.end()) { proj+=dotProduct(p1.second,(*p2).second); } } return proj; } -ActionWithValue* Value::getPntrToAction(){ +ActionWithValue* Value::getPntrToAction() { plumed_assert( action!=NULL ); return action; } -void copy( const Value& val1, Value& val2 ){ +void copy( const Value& val1, Value& val2 ) { unsigned nder=val1.getNumberOfDerivatives(); - if( nder!=val2.getNumberOfDerivatives() ){ val2.resizeDerivatives( nder ); } + if( nder!=val2.getNumberOfDerivatives() ) { val2.resizeDerivatives( nder ); } val2.clearDerivatives(); - for(unsigned i=0;igetNumberOfDerivatives() ){ val2->resizeDerivatives( nder ); } + if( nder!=val2->getNumberOfDerivatives() ) { val2->resizeDerivatives( nder ); } val2->clearDerivatives(); - for(unsigned i=0;iaddDerivative( i, val1.getDerivative(i) ); + for(unsigned i=0; iaddDerivative( i, val1.getDerivative(i) ); val2->set( val1.get() ); } -void add( const Value& val1, Value* val2 ){ +void add( const Value& val1, Value* val2 ) { plumed_assert( val1.getNumberOfDerivatives()==val2->getNumberOfDerivatives() ); - for(unsigned i=0;iaddDerivative( i, val1.getDerivative(i) ); + for(unsigned i=0; iaddDerivative( i, val1.getDerivative(i) ); val2->set( val1.get() + val2->get() ); } diff --git a/src/core/Value.h b/src/core/Value.h index d1a8509c7c..6bbd9b6cee 100644 --- a/src/core/Value.h +++ b/src/core/Value.h @@ -30,31 +30,31 @@ #include "tools/AtomNumber.h" #include "tools/Vector.h" -namespace PLMD{ +namespace PLMD { class ActionWithValue; /// \ingroup TOOLBOX /// A class for holding the value of a function together with its derivatives. -/// Typically, an object of type PLMD::ActionWithValue will contain one -/// object of type PLUMD::Value that will be named after the label. If the -/// PLMD::ActionWithValue is part of a class that calculates multiple components +/// Typically, an object of type PLMD::ActionWithValue will contain one +/// object of type PLUMD::Value that will be named after the label. If the +/// PLMD::ActionWithValue is part of a class that calculates multiple components /// then the class will contain multiple that will be called label.component-name -/// This class is used to pass information between different PLMD::Action +/// This class is used to pass information between different PLMD::Action /// objects. However, if you find a use for a tempory PLMD::Value in some method /// you are implementing please feel free to use it. -class Value{ -friend class ActionWithValue; +class Value { + friend class ActionWithValue; /// This copies the contents of a value into a second value (just the derivatives and value) -friend void copy( const Value& val1, Value& val2 ); + friend void copy( const Value& val1, Value& val2 ); /// This copies the contents of a value into a second value (but second value is a pointer) -friend void copy( const Value& val, Value* val2 ); + friend void copy( const Value& val, Value* val2 ); /// This adds some derivatives onto the value -friend void add( const Value& val1, Value* valout ); + friend void add( const Value& val1, Value* valout ); /// This calculates val1*val2 and sorts out the derivatives -friend void product( const Value& val1, const Value& val2, Value& valout ); + friend void product( const Value& val1, const Value& val2, Value& valout ); /// This calculates va1/val2 and sorts out the derivatives -friend void quotient( const Value& val1, const Value& val2, Value* valout ); + friend void quotient( const Value& val1, const Value& val2, Value* valout ); private: /// The action in which this quantity is calculated ActionWithValue* action; @@ -89,7 +89,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); Value(); /// A constructor that is used throughout the code to setup the value poiters Value(ActionWithValue* av, const std::string& name, const bool withderiv); -/// Set the value of the function +/// Set the value of the function void set(double); /// Add something to the value of the function void add(double); @@ -102,7 +102,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); /// Set the function not periodic void setNotPeriodic(); /// Set the domain of the function - void setDomain(const std::string&, const std::string&); + void setDomain(const std::string&, const std::string&); /// Get the domain of the quantity void getDomain(std::string&,std::string&) const; /// Get the domain of the quantity @@ -112,7 +112,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); /// Check whether or not this particular quantity has derivatives bool hasDerivatives()const; /// Get the number of derivatives that this particular value has - unsigned getNumberOfDerivatives() const; + unsigned getNumberOfDerivatives() const; /// Set the number of derivatives void resizeDerivatives(int n); /// Set all the derivatives to zero @@ -135,7 +135,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); bool applyForce( std::vector& forces ) const ; /// Calculate the difference between the instantaneous value of the function and some other point: other_point-inst_val double difference(double)const; -/// Calculate the difference between two values of this function: d2 -d1 +/// Calculate the difference between two values of this function: d2 -d1 double difference(double d1,double d2)const; /// This returns the pointer to the action where this value is calculated ActionWithValue* getPntrToAction(); @@ -151,57 +151,57 @@ void copy( const Value& val1, Value* val2 ); void add( const Value& val1, Value* valout ); inline -void Value::applyPeriodicity(){ - if(periodicity==periodic){ +void Value::applyPeriodicity() { + if(periodicity==periodic) { value=min+difference(min,value); if(valuederivatives.size()!=val1.derivatives.size() ) valout->resizeDerivatives( val1.derivatives.size() ); - valout->value_set=false; + valout->value_set=false; valout->clearDerivatives(); - double u=val1.get(); + double u=val1.get(); double v=val2.get(); - for(unsigned i=0;iaddDerivative(i, v*val1.getDerivative(i) - u*val2.getDerivative(i) ); + for(unsigned i=0; iaddDerivative(i, v*val1.getDerivative(i) - u*val2.getDerivative(i) ); } valout->chainRule( 1/(v*v) ); valout->set( u / v ); } inline -void Value::set(double v){ +void Value::set(double v) { value_set=true; value=v; applyPeriodicity(); } inline -void Value::add(double v){ +void Value::add(double v) { value_set=true; value+=v; applyPeriodicity(); } inline -double Value::get()const{ +double Value::get()const { return value; } @@ -211,7 +211,7 @@ bool Value::valueHasBeenSet() const { } inline -const std::string& Value::getName()const{ +const std::string& Value::getName()const { return name; } @@ -233,41 +233,41 @@ bool Value::hasDerivatives() const { } inline -void Value::resizeDerivatives(int n){ +void Value::resizeDerivatives(int n) { if(hasDeriv) derivatives.resize(n); } inline -void Value::addDerivative(unsigned i,double d){ +void Value::addDerivative(unsigned i,double d) { plumed_dbg_massert(i -namespace PLMD{ +namespace PLMD { /// Base for classes with cmd() method. /// This is an abstract base class for classes with /// cmd() method. It takes care of "const" cast, and /// in the future it may be used to enforce some sort /// of type checking on passed arguments. -class WithCmd{ +class WithCmd { public: virtual ~WithCmd(); /// Const val version, which indeed just overrides the const and call the virtual method. @@ -41,7 +41,7 @@ class WithCmd{ }; inline -void WithCmd::cmd(const std::string& key,const void*val){ +void WithCmd::cmd(const std::string& key,const void*val) { // this is nasty trick: cmd(key,const_cast(val)); // in this manner, a const pointer can be used for val, allowing the user to pass @@ -50,7 +50,7 @@ void WithCmd::cmd(const std::string& key,const void*val){ } inline -WithCmd::~WithCmd(){ +WithCmd::~WithCmd() { // do nothing // here just to allow inheriting from this class properly } diff --git a/src/crystallization/BondOrientation.cpp b/src/crystallization/BondOrientation.cpp index 450cc3b94f..638d70bf5d 100644 --- a/src/crystallization/BondOrientation.cpp +++ b/src/crystallization/BondOrientation.cpp @@ -49,49 +49,49 @@ class BondOrientation : public VectorMultiColvar { PLUMED_REGISTER_ACTION(BondOrientation,"BOND_DIRECTIONS") -void BondOrientation::registerKeywords( Keywords& keys ){ +void BondOrientation::registerKeywords( Keywords& keys ) { VectorMultiColvar::registerKeywords( keys ); keys.add("numbered","ATOMS","the atoms involved in each of the vectors you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one vector will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one vector will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); 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 " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); keys.add("compulsory","NN","12","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); keys.use("VMEAN"); keys.use("VSUM"); } BondOrientation::BondOrientation( const ActionOptions& ao ): -Action(ao), -VectorMultiColvar(ao) + Action(ao), + VectorMultiColvar(ao) { // Read atoms weightHasDerivatives=true; - std::vector all_atoms; + std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); - if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 2, all_atoms ); + if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 2, all_atoms ); setupMultiColvarBase( all_atoms ); // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" orientation of those bonds with lengths are less than %s\n",( switchingFunction.description() ).c_str() ); // Set the link cell cutoff @@ -106,10 +106,10 @@ double BondOrientation::calculateWeight( const unsigned& current, const double& if( distm>rcut2 ) return 0.0; double df, ww=switchingFunction.calculateSqr( distm, df ); // Derivatives of weights - addAtomDerivatives( 0, 0, -df*weight*distance, myatoms ); + addAtomDerivatives( 0, 0, -df*weight*distance, myatoms ); addAtomDerivatives( 0, 1, df*weight*distance, myatoms ); myatoms.addBoxDerivatives( 0, (-df)*weight*Tensor(distance,distance) ); - return ww; + return ww; } void BondOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) const { @@ -125,11 +125,11 @@ void BondOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) con myatoms.addBoxDerivatives( 3, Tensor(distance,Vector(0,-1.0,0)) ); myatoms.addValue( 3, distance[1] ); - addAtomDerivatives( 4 , 0, Vector(0,0,-1.0), myatoms ); - addAtomDerivatives( 4 , 1, Vector(0,0,+1.0), myatoms ); + addAtomDerivatives( 4, 0, Vector(0,0,-1.0), myatoms ); + addAtomDerivatives( 4, 1, Vector(0,0,+1.0), myatoms ); myatoms.addBoxDerivatives( 4, Tensor(distance,Vector(0,0,-1.0)) ); myatoms.addValue( 4, distance[2] ); } } -} +} diff --git a/src/crystallization/CubicHarmonicBase.cpp b/src/crystallization/CubicHarmonicBase.cpp index 3d793a0dc5..04a07426e1 100644 --- a/src/crystallization/CubicHarmonicBase.cpp +++ b/src/crystallization/CubicHarmonicBase.cpp @@ -27,10 +27,10 @@ using namespace std; -namespace PLMD{ -namespace crystallization{ +namespace PLMD { +namespace crystallization { -void CubicHarmonicBase::registerKeywords( Keywords& keys ){ +void CubicHarmonicBase::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); keys.add("compulsory","NN","6","The n parameter of the switching function "); @@ -38,8 +38,8 @@ void CubicHarmonicBase::registerKeywords( Keywords& keys ){ keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); keys.add("compulsory","PHI","0.0","The Euler rotational angle phi"); keys.add("compulsory","THETA","0.0","The Euler rotational angle theta"); keys.add("compulsory","PSI","0.0","The Euler rotational angle psi"); @@ -47,42 +47,42 @@ void CubicHarmonicBase::registerKeywords( Keywords& keys ){ // Use actionWithDistributionKeywords keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MAX"); keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); - keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); } CubicHarmonicBase::CubicHarmonicBase(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + if(sw.length()>0) { + switchingFunction.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } else { + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } - + double phi, theta, psi; parse("PHI",phi); parse("THETA",theta); parse("PSI",psi); log.printf(" creating rotation matrix with Euler angles phi=%f, theta=%f and psi=%f\n",phi,theta,psi); // Calculate the rotation matrix http://mathworld.wolfram.com/EulerAngles.html rotationmatrix[0][0]=cos(psi)*cos(phi)-cos(theta)*sin(phi)*sin(psi); rotationmatrix[0][1]=cos(psi)*sin(phi)+cos(theta)*cos(phi)*sin(psi); rotationmatrix[0][2]=sin(psi)*sin(theta); - + rotationmatrix[1][0]=-sin(psi)*cos(phi)-cos(theta)*sin(phi)*cos(psi); rotationmatrix[1][1]=-sin(psi)*sin(phi)+cos(theta)*cos(phi)*cos(psi); rotationmatrix[1][2]=cos(psi)*sin(theta); - + rotationmatrix[2][0]=sin(theta)*sin(phi); rotationmatrix[2][1]=-sin(theta)*cos(phi); rotationmatrix[2][2]=cos(theta); - - + + log.printf(" measure crystallinity around central atom. Includes those atoms within %s\n",( switchingFunction.description() ).c_str() ); parseFlag("UNORMALIZED",unormalized); if( unormalized ) log.printf(" output sum of vector functions \n"); @@ -91,57 +91,57 @@ MultiColvarBase(ao) rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); setLinkCellCutoff( switchingFunction.get_dmax() ); // And setup the ActionWithVessel - std::vector all_atoms; setupMultiColvarBase( all_atoms ); + std::vector all_atoms; setupMultiColvarBase( all_atoms ); } double CubicHarmonicBase::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { - double dfunc; Vector rotatedis; - - // Calculate the coordination number - Vector myder, rotateder, fder; unsigned nat=myatoms.getNumberOfAtoms(); - - double d2; - for(unsigned i=1;i der of... value [0], weight[1], x coord [2], y, z... [more magic] - updateActiveAtoms( myatoms ); - if( !unormalized ) myatoms.getUnderlyingMultiValue().quotientRule( 1, 1 ); - return myatoms.getValue(1); // this is equivalent to getting an "atomic" CV + double dfunc; Vector rotatedis; + + // Calculate the coordination number + Vector myder, rotateder, fder; unsigned nat=myatoms.getNumberOfAtoms(); + + double d2; + for(unsigned i=1; i der of... value [0], weight[1], x coord [2], y, z... [more magic] + updateActiveAtoms( myatoms ); + if( !unormalized ) myatoms.getUnderlyingMultiValue().quotientRule( 1, 1 ); + return myatoms.getValue(1); // this is equivalent to getting an "atomic" CV } } diff --git a/src/crystallization/CubicHarmonicBase.h b/src/crystallization/CubicHarmonicBase.h index 8cc2408e85..7986038a4e 100644 --- a/src/crystallization/CubicHarmonicBase.h +++ b/src/crystallization/CubicHarmonicBase.h @@ -26,8 +26,8 @@ #include "multicolvar/AtomValuePack.h" #include "tools/SwitchingFunction.h" -namespace PLMD{ -namespace crystallization{ +namespace PLMD { +namespace crystallization { class CubicHarmonicBase : public multicolvar::MultiColvarBase { private: @@ -43,7 +43,7 @@ class CubicHarmonicBase : public multicolvar::MultiColvarBase { double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; virtual double calculateCubicHarmonic( const Vector& distance, const double& d2, Vector& myder ) const = 0; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; } diff --git a/src/crystallization/Fccubic.cpp b/src/crystallization/Fccubic.cpp index cf27beaf1f..fc1793ab39 100644 --- a/src/crystallization/Fccubic.cpp +++ b/src/crystallization/Fccubic.cpp @@ -28,23 +28,23 @@ using namespace std; -namespace PLMD{ -namespace crystallization{ +namespace PLMD { +namespace crystallization { -//+PLUMEDOC MCOLVAR FCCUBIC +//+PLUMEDOC MCOLVAR FCCUBIC /* Measure how similar the environment around atoms is to that found in a FCC structure. This CV was introduced in this article \cite fcc-michele-1 and again in this article \cite fcc-michele-2 -This CV essentially determines whether the environment around any given atom is similar to that found in +This CV essentially determines whether the environment around any given atom is similar to that found in the FCC structure or not. The function that is used to make this determination is as follows: \f[ -s_i = \frac{ \sum_{i \ne j} \sigma(r_{ij}) \left\{ a\left[ \frac{(x_{ij}y_{ij})^4 + (x_{ij}z_{ij})^4 + (y_{ij}z_{ij})^4}{r_{ij}^8} - \frac{\alpha (x_{ij}y_{ij}z_{ij})^4}{r_{ij}^{12}} \right] + b \right\} }{ \sum_{i \ne j} \sigma(r_{ij}) } +s_i = \frac{ \sum_{i \ne j} \sigma(r_{ij}) \left\{ a\left[ \frac{(x_{ij}y_{ij})^4 + (x_{ij}z_{ij})^4 + (y_{ij}z_{ij})^4}{r_{ij}^8} - \frac{\alpha (x_{ij}y_{ij}z_{ij})^4}{r_{ij}^{12}} \right] + b \right\} }{ \sum_{i \ne j} \sigma(r_{ij}) } \f] -In this expression \f$x_{ij}\f$, \f$y_{ij}\f$ and \f$z_{ij}\f$ are the \f$x\f$, \f$y\f$ and \f$z\f$ components of the vector connecting atom \f$i\f$ to -atom \f$j\f$ and \f$r_{ij}\f$ is the magnitude of this vector. \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that acts on the distance between +In this expression \f$x_{ij}\f$, \f$y_{ij}\f$ and \f$z_{ij}\f$ are the \f$x\f$, \f$y\f$ and \f$z\f$ components of the vector connecting atom \f$i\f$ to +atom \f$j\f$ and \f$r_{ij}\f$ is the magnitude of this vector. \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that acts on the distance between atom \f$i\f$ and atom \f$j\f$ and its inclusion in the numerator and the denominator of the above expression as well as the fact that we are summing over all of the other atoms in the system ensures that we are calculating an average of the function of \f$x_{ij}\f$, \f$y_{ij}\f$ and \f$z_{ij}\f$ for the atoms in the first coordination sphere around atom \f$i\f$. Lastly, \f$\alpha\f$ @@ -52,15 +52,15 @@ is a parameter that can be set by the user, which by default is equal to three. \f[ a = \frac{ 80080}{ 2717 + 16 \alpha} \qquad \textrm{and} \qquad b = \frac{ 16(\alpha - 143) }{2717 + 16\alpha} -\f] +\f] This quantity is once again a multicolvar so you can compute it for multiple atoms using a single PLUMED action and then compute -the average value for the atoms in your system, the number of atoms that have an \f$s_i\f$ value that is more that some target and +the average value for the atoms in your system, the number of atoms that have an \f$s_i\f$ value that is more that some target and so on. Notice also that you can rotate the reference frame if you are using a non-standard unit cell. \par Examples -The following input calculates the FCCUBIC parameter for the 64 atoms in the system +The following input calculates the FCCUBIC parameter for the 64 atoms in the system and then calculates and prints the average value for this quantity. \verbatim @@ -83,14 +83,14 @@ class Fccubic : public CubicHarmonicBase { PLUMED_REGISTER_ACTION(Fccubic,"FCCUBIC") -void Fccubic::registerKeywords( Keywords& keys ){ +void Fccubic::registerKeywords( Keywords& keys ) { CubicHarmonicBase::registerKeywords( keys ); keys.add("compulsory","ALPHA","3.0","The alpha parameter of the angular function"); } Fccubic::Fccubic(const ActionOptions&ao): -Action(ao), -CubicHarmonicBase(ao) + Action(ao), + CubicHarmonicBase(ao) { // Scaling factors such that '1' corresponds to fcc lattice // and '0' corresponds to isotropic (liquid) @@ -110,7 +110,7 @@ double Fccubic::calculateCubicHarmonic( const Vector& distance, const double& d2 double z2 = distance[2]*distance[2]; double z4 = z2*z2; - + double r8 = pow( d2, 4 ); double r12 = pow( d2, 6 ); @@ -119,12 +119,12 @@ double Fccubic::calculateCubicHarmonic( const Vector& distance, const double& d2 double t0 = (x2*y4+x2*z4)/r8-alpha*x2*y4*z4/r12; double t1 = (y2*x4+y2*z4)/r8-alpha*y2*x4*z4/r12; double t2 = (z2*x4+z2*y4)/r8-alpha*z2*x4*y4/r12; - double t3 = (2*tmp-alpha*x4*y4*z4/r12)/d2; - + double t3 = (2*tmp-alpha*x4*y4*z4/r12)/d2; + myder[0]=4*a1*distance[0]*(t0-t3); myder[1]=4*a1*distance[1]*(t1-t3); myder[2]=4*a1*distance[2]*(t2-t3); - + return a1*tmp+b1; } diff --git a/src/crystallization/Gradient.cpp b/src/crystallization/Gradient.cpp index 0c2f7c729f..173d9e5adb 100644 --- a/src/crystallization/Gradient.cpp +++ b/src/crystallization/Gradient.cpp @@ -35,24 +35,24 @@ This command allows you to calculate the collective variable discussed in \cite \par Examples -The input below calculates the gradient of the density of atoms in the manner +The input below calculates the gradient of the density of atoms in the manner described in \cite fede-grad in order to detect whether or not atoms are distributed uniformly along the x-axis of the simulation cell. \verbatim -d1: DENSITY SPECIES=1-50 -s1: GRADIENT ORIGIN=1 DATA=d1 DIR=x NBINS=4 SIGMA=1.0 +d1: DENSITY SPECIES=1-50 +s1: GRADIENT ORIGIN=1 DATA=d1 DIR=x NBINS=4 SIGMA=1.0 PRINT ARG=s1 FILE=colvar \endverbatim The input below calculates the coordination numbers of the 50 atoms in the simulation cell. The gradient of this quantity is then evaluated in the manner described using the equation above -to detect whether the average values of the coordination number are uniformly distributed along the +to detect whether the average values of the coordination number are uniformly distributed along the x-axis of the simulation cell. \verbatim -d2: COORDINATIONNUMBER SPECIES=1-50 SWITCH={RATIONAL R_0=2.0} MORE_THAN={EXP R_0=4.0} -s2: GRADIENT ORIGIN=1 DATA=d2 DIR=x NBINS=4 SIGMA=1.0 +d2: COORDINATIONNUMBER SPECIES=1-50 SWITCH={RATIONAL R_0=2.0} MORE_THAN={EXP R_0=4.0} +s2: GRADIENT ORIGIN=1 DATA=d2 DIR=x NBINS=4 SIGMA=1.0 PRINT ARG=s2 FILE=colvar \endverbatim @@ -61,7 +61,7 @@ PRINT ARG=s2 FILE=colvar PLUMED_REGISTER_ACTION(Gradient,"GRADIENT") -void Gradient::registerKeywords( Keywords& keys ){ +void Gradient::registerKeywords( Keywords& keys ) { VolumeGradientBase::registerKeywords( keys ); keys.add("atoms","ORIGIN","we will use the position of this atom as the origin in our calculation"); keys.add("compulsory","DIR","xyz","the directions in which we are calculating the graident. Should be x, y, z, xy, xz, yz or xyz"); @@ -71,9 +71,9 @@ void Gradient::registerKeywords( Keywords& keys ){ } Gradient::Gradient(const ActionOptions&ao): -Action(ao), -VolumeGradientBase(ao), -nbins(3) + Action(ao), + VolumeGradientBase(ao), + nbins(3) { std::vector atom; parseAtomList("ORIGIN",atom); @@ -82,48 +82,48 @@ nbins(3) std::string direction; parse("DIR",direction); std::vector tbins; parseVector("NBINS",tbins); - for(unsigned i=0;iisDensity() ) vend=2; else if( getPntrToMultiColvar()->getNumberOfQuantities()==2 ) vend=2; - else vend = getPntrToMultiColvar()->getNumberOfQuantities(); + else vend = getPntrToMultiColvar()->getNumberOfQuantities(); nquantities = vend + nbins[0] + nbins[1] + nbins[2]; // Output some nice information std::string functype=getPntrToMultiColvar()->getName(); std::transform( functype.begin(), functype.end(), functype.begin(), tolower ); - log.printf(" calculating gradient of %s in %s direction \n",functype.c_str(), direction.c_str() ); + log.printf(" calculating gradient of %s in %s direction \n",functype.c_str(), direction.c_str() ); log<<" Bibliography:"<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 oderiv, fpos = (getPntrToMultiColvar()->getPbc()).realToScaled( cpos ); + Vector deriv; unsigned nbase=vend; std::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( nbins[idir] ); - for(unsigned jbead=0;jbeadgetPbc()).realToScaled( deriv ); - // Set and derivatives - refder[0]=-oderiv; // vir = -Tensor(cpos,oderiv); - setNumberInVolume( nbase+jbead, curr, weight, oderiv, vir, refder, outvals ); + for(unsigned idir=0; idir<3; ++idir) { + deriv[0]=deriv[1]=deriv[2]=0.0; + double delx = 1.0 / static_cast( nbins[idir] ); + for(unsigned jbead=0; jbeadgetPbc()).realToScaled( deriv ); + // Set and derivatives + 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]; + } + nbase += nbins[idir]; } } diff --git a/src/crystallization/Gradient.h b/src/crystallization/Gradient.h index bb3b81bd7b..e639a84587 100644 --- a/src/crystallization/Gradient.h +++ b/src/crystallization/Gradient.h @@ -28,7 +28,7 @@ namespace PLMD { namespace crystallization { class Gradient : public multicolvar::VolumeGradientBase { -friend class GradientVessel; + friend class GradientVessel; private: /// The value of sigma double sigma; @@ -52,7 +52,7 @@ friend class GradientVessel; inline unsigned Gradient::getNumberOfQuantities() const { return nquantities; -} +} } } diff --git a/src/crystallization/GradientVessel.cpp b/src/crystallization/GradientVessel.cpp index d1ad12fe99..a266bbf019 100644 --- a/src/crystallization/GradientVessel.cpp +++ b/src/crystallization/GradientVessel.cpp @@ -46,55 +46,55 @@ class GradientVessel : public vesselbase::FunctionVessel { PLUMED_REGISTER_VESSEL(GradientVessel,"GRADIENT") -void GradientVessel::registerKeywords( Keywords& keys ){ +void GradientVessel::registerKeywords( Keywords& keys ) { vesselbase::FunctionVessel::registerKeywords(keys); } -void GradientVessel::reserveKeyword( Keywords& keys ){ +void GradientVessel::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","GRADIENT","calculate the gradient"); keys.addOutputComponent("gradient","GRADIENT","the gradient"); } GradientVessel::GradientVessel( const vesselbase::VesselOptions& da ) : -FunctionVessel(da) + FunctionVessel(da) { - Gradient* vg=dynamic_cast( getAction() ); - plumed_assert( vg ); isdens=(vg->getPntrToMultiColvar())->isDensity(); - nweights = vg->nbins[0] + vg->nbins[1] + vg->nbins[2]; - if( (vg->getPntrToMultiColvar())->getNumberOfQuantities()>2 ){ - ncomponents = (vg->getPntrToMultiColvar())->getNumberOfQuantities() - 2; - } else { - ncomponents = 1; - } - - starts.push_back(0); - if( vg->nbins[0]>0 ){ - starts.push_back( vg->nbins[0] ); - if( vg->nbins[1]>0 ){ - starts.push_back( vg->nbins[0] + vg->nbins[1] ); - if( vg->nbins[2]>0 ) starts.push_back( nweights ); - } else if( vg->nbins[2]>0 ){ - starts.push_back( nweights ); - } - } else if( vg->nbins[1]>0 ){ - starts.push_back( vg->nbins[1] ); - if( vg->nbins[2]>0 ) starts.push_back( nweights ); - } else if( vg->nbins[2]>0 ){ - starts.push_back( nweights ); - } + Gradient* vg=dynamic_cast( getAction() ); + plumed_assert( vg ); isdens=(vg->getPntrToMultiColvar())->isDensity(); + nweights = vg->nbins[0] + vg->nbins[1] + vg->nbins[2]; + if( (vg->getPntrToMultiColvar())->getNumberOfQuantities()>2 ) { + ncomponents = (vg->getPntrToMultiColvar())->getNumberOfQuantities() - 2; + } else { + ncomponents = 1; + } + + starts.push_back(0); + if( vg->nbins[0]>0 ) { + starts.push_back( vg->nbins[0] ); + if( vg->nbins[1]>0 ) { + starts.push_back( vg->nbins[0] + vg->nbins[1] ); + if( vg->nbins[2]>0 ) starts.push_back( nweights ); + } else if( vg->nbins[2]>0 ) { + starts.push_back( nweights ); + } + } else if( vg->nbins[1]>0 ) { + starts.push_back( vg->nbins[1] ); + if( vg->nbins[2]>0 ) starts.push_back( nweights ); + } else if( vg->nbins[2]>0 ) { + starts.push_back( nweights ); + } } -std::string GradientVessel::value_descriptor(){ +std::string GradientVessel::value_descriptor() { return "the gradient"; } -void GradientVessel::resize(){ - if( getAction()->derivativesAreRequired() ){ - unsigned nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*(ncomponents+1)*nweights ); - getFinalValue()->resizeDerivatives( nder ); +void GradientVessel::resize() { + if( getAction()->derivativesAreRequired() ) { + unsigned nder=getAction()->getNumberOfDerivatives(); + resizeBuffer( (1+nder)*(ncomponents+1)*nweights ); + getFinalValue()->resizeDerivatives( nder ); } else { - resizeBuffer( (ncomponents+1)*nweights ); + resizeBuffer( (ncomponents+1)*nweights ); } } @@ -102,90 +102,90 @@ void GradientVessel::calculate( const unsigned& current, MultiValue& myvals, std unsigned nder; if( getAction()->derivativesAreRequired() ) nder=getAction()->getNumberOfDerivatives(); else nder=0; - unsigned wstart, cstart; if( ncomponents==1 ){ cstart=1; wstart=2; } else { cstart=2; wstart=2+ncomponents; } - - for(unsigned iw=0;iw& buffer ){ +void GradientVessel::finish( const std::vector& buffer ) { std::vector val_interm( ncomponents*nweights ); unsigned nder; if( getAction()->derivativesAreRequired() ) nder=getAction()->getNumberOfDerivatives(); else nder=0; Matrix der_interm( ncomponents*nweights, nder ); der_interm=0; - if( isdens ){ - for(unsigned iw=0;iwderivativesAreRequired() ){ - unsigned wstart = bufstart + 2*iw*(nder+1) + 1; - for(unsigned jder=0;jderderivativesAreRequired() ) { + unsigned wstart = bufstart + 2*iw*(nder+1) + 1; + for(unsigned jder=0; jderderivativesAreRequired() ){ - unsigned wstart = bufstart + xx*(nder+1) + 1; - for(unsigned jc=0;jcderivativesAreRequired() ) { + unsigned wstart = bufstart + xx*(nder+1) + 1; + for(unsigned jc=0; jcderivativesAreRequired() ){ - Value* fval=getFinalValue(); - for(unsigned j=0;jaddDerivative( jder, +2.0*tmp*der_interm( (starts[j+1]-1)*ncomponents + jc, jder) ); - fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); - } - } else { - tmp=val_interm[(bin-1)*ncomponents + jc] - val_interm[bin*ncomponents + jc]; - for(unsigned jder=0;jderaddDerivative( jder, +2.0*tmp*der_interm( (bin-1)*ncomponents + jc, jder) ); - fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); - } - } - diff2+=tmp*tmp; - } + double tmp, diff2=0.0; + + if( getAction()->derivativesAreRequired() ) { + Value* fval=getFinalValue(); + for(unsigned j=0; jaddDerivative( jder, +2.0*tmp*der_interm( (starts[j+1]-1)*ncomponents + jc, jder) ); + fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); + } + } else { + tmp=val_interm[(bin-1)*ncomponents + jc] - val_interm[bin*ncomponents + jc]; + for(unsigned jder=0; jderaddDerivative( jder, +2.0*tmp*der_interm( (bin-1)*ncomponents + jc, jder) ); + fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); + } + } + diff2+=tmp*tmp; } - } + } + } } else { - for(unsigned j=0;j #include @@ -43,32 +43,32 @@ Here the sums run over all pairs of molecules. \f$\sigma(r_{ij})\f$ is a \ref sw action on the distance between the centers of molecules \f$i\f$ and \f$j\f$. \f$\theta_{ij}\f$ is then the torsional angle between an orientation vector for molecule \f$i\f$ and molecule \f$j\f$. -This command can be used to calculate the intermolecular torsional angles between the orientations of nearby molecules. The orientation of a -molecule can be calculated by using either the \ref MOLECULES or the \ref PLANES commands. These two commands calculate the orientation of a -bond in the molecule or the orientation of a plane containing three of the molecule's atoms. Furthermore, when we use these commands we think of +This command can be used to calculate the intermolecular torsional angles between the orientations of nearby molecules. The orientation of a +molecule can be calculated by using either the \ref MOLECULES or the \ref PLANES commands. These two commands calculate the orientation of a +bond in the molecule or the orientation of a plane containing three of the molecule's atoms. Furthermore, when we use these commands we think of molecules as objects that lie at a point in space and that have an orientation. This command calculates the torsional angles between the orientations -of these objects. We can then calculates functions of a large number of these torsional angles that measures things such as the number of torsional -angles that are within a particular range. Because it is often useful to only consider the torsional angles between objects that are within a certain +of these objects. We can then calculates functions of a large number of these torsional angles that measures things such as the number of torsional +angles that are within a particular range. Because it is often useful to only consider the torsional angles between objects that are within a certain distance of each other we can, when calculating these sums, perform a weighted sum and use a \ref switchingfunction to ensure that we focus on molecules -that are close together. +that are close together. \par Examples The example input below is necessarily but gives you an idea of what can be achieved using this action. -The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the +The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the centeres of mass of the two atoms specified and the direction of the vector connecting the two atoms that were specified. The torsional angles between the molecules are then calculated by the \ref INTERMOLECULARTORSIONS command labelled tt_p. We then compute a \ref HISTOGRAM that shows the distribution that these torsional angles take in the structure. The weight a given torsional angle contributes to this \ref HISTOGRAM is determined using a \ref switchingfunction that acts on the distance -between the two molecules. As such the torsional angles between molecules that are close together contribute a high weight to the -histogram while the torsional angles between molecules that are far apart does not contribute to the histogram. The histogram is +between the two molecules. As such the torsional angles between molecules that are close together contribute a high weight to the +histogram while the torsional angles between molecules that are far apart does not contribute to the histogram. The histogram is averaged over the whole trajectory and output once all the trajectory frames have been read. \verbatim m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 -tt_p: INTERMOLECULARTORSIONS MOLS=m1 SWITCH={RATIONAL R_0=0.25 D_0=2.0 D_MAX=3.0} -htt_p: HISTOGRAM DATA=tt_p GRID_MIN=-pi GRID_MAX=pi BANDWIDTH=0.1 GRID_BIN=200 STRIDE=1 -DUMPGRID GRID=htt_p FILE=myhist.out +tt_p: INTERMOLECULARTORSIONS MOLS=m1 SWITCH={RATIONAL R_0=0.25 D_0=2.0 D_MAX=3.0} +htt_p: HISTOGRAM DATA=tt_p GRID_MIN=-pi GRID_MAX=pi BANDWIDTH=0.1 GRID_BIN=200 STRIDE=1 +DUMPGRID GRID=htt_p FILE=myhist.out \endverbatim */ @@ -89,57 +89,57 @@ class InterMolecularTorsions : public multicolvar::MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return true; } - void retrieveDomain( std::string& min, std::string& max ){ min="-pi"; max="+pi"; } + bool isPeriodic() { return true; } + void retrieveDomain( std::string& min, std::string& max ) { min="-pi"; max="+pi"; } }; PLUMED_REGISTER_ACTION(InterMolecularTorsions,"INTERMOLECULARTORSIONS") -void InterMolecularTorsions::registerKeywords( Keywords& keys ){ +void InterMolecularTorsions::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("atoms","MOLS","The molecules you would like to calculate the torsional angles between. This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); - keys.add("atoms-1","MOLSA","In this version of the input the torsional angles between all pairs of atoms including one atom from MOLA one atom from MOLB will be computed. " - "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); + keys.add("atoms-1","MOLSA","In this version of the input the torsional angles between all pairs of atoms including one atom from MOLA one atom from MOLB will be computed. " + "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); keys.add("atoms-1","MOLSB","In this version of the input the torsional angles between all pairs of atoms including one atom from MOLA one atom from MOLB will be computed. " - "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); + "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords - keys.remove("LOWMEM"); + keys.remove("LOWMEM"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); } InterMolecularTorsions::InterMolecularTorsions(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { - for(unsigned i=0;igetNumberOfQuantities()!=5 ) error("input multicolvar does not calculate molecular orientations"); + for(unsigned i=0; igetNumberOfQuantities()!=5 ) error("input multicolvar does not calculate molecular orientations"); } // The weight of this does have derivatives weightHasDerivatives=true; // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" calculating number of links with atoms separation of %s\n",( switchingFunction.description() ).c_str() ); std::vector all_atoms; readTwoGroups( "MOLS", "MOLSA", "MOLSB", all_atoms ); setupMultiColvarBase( all_atoms ); setLinkCellCutoff( switchingFunction.get_dmax() ); - for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); } @@ -154,39 +154,39 @@ double InterMolecularTorsions::calculateWeight( const unsigned& taskCode, const Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc ); - if( !doNotCalculateDerivatives() ){ - addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); - addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); - myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); + if( !doNotCalculateDerivatives() ) { + addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); + addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); + myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); } return sw; } double InterMolecularTorsions::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { - Vector v1, v2, dv1, dv2, dconn, conn = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - - // Retrieve vectors - std::vector orient0( 5 ), orient1( 5 ); - getInputData( 0, true, myatoms, orient0 ); - getInputData( 1, true, myatoms, orient1 ); - for(unsigned i=0;i<3;++i){ v1[i]=orient0[2+i]; v2[i]=orient1[2+i]; } - if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; - - // Evaluate angle - Torsion t; double angle = t.compute( v1, conn, v2, dv1, dconn, dv2 ); - for(unsigned i=0;i<3;++i){ orient0[i+2]=dv1[i]; orient1[i+2]=dv2[i]; } - - // And accumulate derivatives - if( !doNotCalculateDerivatives() ){ - MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); - mergeInputDerivatives( 1, 2, orient1.size(), 0, orient0, myder0, myatoms ); - MultiValue& myder1=getInputDerivatives( 1, true, myatoms ); - mergeInputDerivatives( 1, 2, orient0.size(), 1, orient1, myder1, myatoms ); - addAtomDerivatives( 1, 0, -dconn, myatoms ); addAtomDerivatives( 1, 1, dconn, myatoms ); - myatoms.addBoxDerivatives( 1, -extProduct( conn, dconn ) ); - } - - return angle; + Vector v1, v2, dv1, dv2, dconn, conn = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + + // Retrieve vectors + std::vector orient0( 5 ), orient1( 5 ); + getInputData( 0, true, myatoms, orient0 ); + getInputData( 1, true, myatoms, orient1 ); + for(unsigned i=0; i<3; ++i) { v1[i]=orient0[2+i]; v2[i]=orient1[2+i]; } + if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; + + // Evaluate angle + Torsion t; double angle = t.compute( v1, conn, v2, dv1, dconn, dv2 ); + for(unsigned i=0; i<3; ++i) { orient0[i+2]=dv1[i]; orient1[i+2]=dv2[i]; } + + // And accumulate derivatives + if( !doNotCalculateDerivatives() ) { + MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); + mergeInputDerivatives( 1, 2, orient1.size(), 0, orient0, myder0, myatoms ); + MultiValue& myder1=getInputDerivatives( 1, true, myatoms ); + mergeInputDerivatives( 1, 2, orient0.size(), 1, orient1, myder1, myatoms ); + addAtomDerivatives( 1, 0, -dconn, myatoms ); addAtomDerivatives( 1, 1, dconn, myatoms ); + myatoms.addBoxDerivatives( 1, -extProduct( conn, dconn ) ); + } + + return angle; } } diff --git a/src/crystallization/LocalSteinhardt.h b/src/crystallization/LocalSteinhardt.h index a71c6e65ed..c7ced6ab35 100644 --- a/src/crystallization/LocalSteinhardt.h +++ b/src/crystallization/LocalSteinhardt.h @@ -29,31 +29,31 @@ namespace crystallization { template class LocalSteinhardt : public OrientationSphere { public: - static void registerKeywords( Keywords& keys ){ + static void registerKeywords( Keywords& keys ) { OrientationSphere::registerKeywords(keys); } explicit LocalSteinhardt(const ActionOptions& ao): Action(ao), OrientationSphere(ao) { - for(unsigned i=0;i( getBaseMultiColvar(i) ); - if(!mc){ - if( getBaseMultiColvar(i)->getNumberOfBaseMultiColvars()==0 ){ - error("input action is not calculating the correct vectors"); - } - for(unsigned j=0;jgetNumberOfBaseMultiColvars();++j){ - T* mmc=dynamic_cast( getBaseMultiColvar(i)->getBaseMultiColvar(j) ); - if( !mmc ) error("input action is not calculating the correct vectors"); - } - } - } + for(unsigned i=0; i( getBaseMultiColvar(i) ); + if(!mc) { + if( getBaseMultiColvar(i)->getNumberOfBaseMultiColvars()==0 ) { + error("input action is not calculating the correct vectors"); + } + for(unsigned j=0; jgetNumberOfBaseMultiColvars(); ++j) { + T* mmc=dynamic_cast( getBaseMultiColvar(i)->getBaseMultiColvar(j) ); + if( !mmc ) error("input action is not calculating the correct vectors"); + } + } + } } double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { - double dot=0; dconn.zero(); - for(unsigned k=2;k all_atoms; - readAtomsLikeKeyword("MOL",-1,all_atoms); + readAtomsLikeKeyword("MOL",-1,all_atoms); nvectors = std::floor( ablocks.size() / 2 ); if( ablocks.size()%2!=0 && 2*nvectors+1!=ablocks.size() ) error("number of atoms in molecule specification is wrong. Should be two or three."); if( all_atoms.size()==0 ) error("No atoms were specified"); setVectorDimensionality( 3*nvectors ); setupMultiColvarBase( all_atoms ); - if( ablocks.size()==2*nvectors+1 ){ + if( ablocks.size()==2*nvectors+1 ) { std::vector catom_ind(ablocks.size(), false); catom_ind[ablocks.size()-1]=true; setAtomsForCentralAtom( catom_ind ); - } + } } AtomNumber MoleculeOrientation::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const { @@ -97,55 +97,55 @@ AtomNumber MoleculeOrientation::getAbsoluteIndexOfCentralAtom( const unsigned& i } void MoleculeOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) const { - for(unsigned i=0;i& vals ) const { - for(unsigned i=0;iepsilon ) inorm = 1.0 / norm; - for(unsigned j=0;j<3;++j) vals[2+3*i+j] = inorm*vals[2+3*i+j]; +void MoleculeOrientation::normalizeVector( std::vector& vals ) const { + for(unsigned i=0; iepsilon ) inorm = 1.0 / norm; + for(unsigned j=0; j<3; ++j) vals[2+3*i+j] = inorm*vals[2+3*i+j]; } } void MoleculeOrientation::normalizeVectorDerivatives( MultiValue& myvals ) const { std::vector weight( nvectors ), wdf( nvectors ); - for(unsigned ivec=0;ivecepsilon ){ weight[ivec] = 1.0 / v; wdf[ivec] = 1.0 / ( v*v*v ); } + for(unsigned ivec=0; ivecepsilon ) { weight[ivec] = 1.0 / v; wdf[ivec] = 1.0 / ( v*v*v ); } } - for(unsigned j=0;j all_atoms; - readAtomsLikeKeyword("MOL",-1,all_atoms); + readAtomsLikeKeyword("MOL",-1,all_atoms); if( ablocks.size()!=3 && ablocks.size()!=4 ) error("number of atoms in molecule specification is wrong. Should be three or four."); if( all_atoms.size()==0 ) error("No atoms were specified"); @@ -76,56 +76,56 @@ AtomNumber MoleculePlane::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) return ActionAtomistic::getAbsoluteIndex( ablocks[0][atom_lab[iatom].second] ); } -void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ) const { - Vector d1, d2, cp; - if( myatoms.getNumberOfAtoms()==3 ){ - d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); - d2=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); +void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ) const { + Vector d1, d2, cp; + if( myatoms.getNumberOfAtoms()==3 ) { + d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); + d2=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); } else { - d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); - d2=getSeparation( myatoms.getPosition(2), myatoms.getPosition(3) ); + d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); + d2=getSeparation( myatoms.getPosition(2), myatoms.getPosition(3) ); } cp = crossProduct( d1, d2 ); addAtomDerivatives( 2, 0, crossProduct( Vector(-1.0,0,0), d2 ), myatoms ); - if( myatoms.getNumberOfAtoms()==3 ){ - addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ) + crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); - addAtomDerivatives( 2, 2, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); + if( myatoms.getNumberOfAtoms()==3 ) { + addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ) + crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); + addAtomDerivatives( 2, 2, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); } else { - addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ), myatoms ); - addAtomDerivatives( 2, 2, crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); - addAtomDerivatives( 2, 3, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); + addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ), myatoms ); + addAtomDerivatives( 2, 2, crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); + addAtomDerivatives( 2, 3, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); } 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] ); addAtomDerivatives( 3, 0, crossProduct( Vector(0,-1.0,0), d2 ), myatoms ); - if( myatoms.getNumberOfAtoms()==3 ){ - addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ) + crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); - addAtomDerivatives( 3, 2, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); + if( myatoms.getNumberOfAtoms()==3 ) { + addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ) + crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); + addAtomDerivatives( 3, 2, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); } else { - addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ), myatoms ); - addAtomDerivatives( 3, 2, crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); - addAtomDerivatives( 3, 3, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); + addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ), myatoms ); + addAtomDerivatives( 3, 2, crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); + addAtomDerivatives( 3, 3, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); } 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] ); addAtomDerivatives( 4, 0, crossProduct( Vector(0,0,-1.0), d2 ), myatoms ); - if( myatoms.getNumberOfAtoms()==3 ){ - addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,+1.0), d2 ) + crossProduct( Vector(0,0,-1.0), d1 ), myatoms ); - addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); + if( myatoms.getNumberOfAtoms()==3 ) { + addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,+1.0), d2 ) + crossProduct( Vector(0,0,-1.0), d1 ), myatoms ); + addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); } else { - addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,-1.0), d2 ), myatoms); - addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,-1.0), d1 ), myatoms); - addAtomDerivatives( 4, 3, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); + addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,-1.0), d2 ), myatoms); + addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,-1.0), d1 ), myatoms); + addAtomDerivatives( 4, 3, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); } 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(); +// Vector com; com.zero(); // if( getNAtoms()==3 ){ // com+=(1.0/3.0)*getPosition(0); // com+=(1.0/3.0)*getPosition(1); diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp index b17a2821cd..8d6fa46d12 100644 --- a/src/crystallization/OrientationSphere.cpp +++ b/src/crystallization/OrientationSphere.cpp @@ -25,40 +25,40 @@ using namespace std; -namespace PLMD{ +namespace PLMD { namespace crystallization { -void OrientationSphere::registerKeywords( Keywords& keys ){ +void OrientationSphere::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords - keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); + keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); + keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("LOWEST"); keys.use("HIGHEST"); } OrientationSphere::OrientationSphere(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { if( getNumberOfBaseMultiColvars()>1 ) warning("not sure if orientation sphere works with more than one base multicolvar - check numerical derivatives"); // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); - } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + if(sw.length()>0) { + switchingFunction.set(sw,errors); + } else { + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" degree of overlap in orientation between central molecule and those within %s\n",( switchingFunction.description() ).c_str() ); log<<" Bibliography "<getNumberOfQuantities(); - std::vector catom_orient( ncomponents ), this_orient( ncomponents ); - std::vector this_der( ncomponents ), catom_der( ncomponents ); - - getInputData( 0, true, myatoms, catom_orient ); - MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); - - for(unsigned i=1;igetNumberOfQuantities(); + std::vector catom_orient( ncomponents ), this_orient( ncomponents ); + std::vector this_der( ncomponents ), catom_der( ncomponents ); + + getInputData( 0, true, myatoms, catom_orient ); + MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); + + for(unsigned i=1; iepsilon ){ rdenom = 1.0 / denom; } - else { plumed_assert(fabs(value)epsilon ) { rdenom = 1.0 / denom; } + else { plumed_assert(fabs(value)& vec1, const std::vector& vec2, + virtual double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const = 0; virtual double calculateCoordinationPrefactor( const double& coord, double& df ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; inline diff --git a/src/crystallization/Q3.cpp b/src/crystallization/Q3.cpp index 25a5b77bd1..6c3aeedc2f 100644 --- a/src/crystallization/Q3.cpp +++ b/src/crystallization/Q3.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "Steinhardt.h" -#include "LocalSteinhardt.h" +#include "LocalSteinhardt.h" #include "core/ActionRegister.h" //+PLUMEDOC MCOLVAR Q3 @@ -28,7 +28,7 @@ Calculate 3rd order Steinhardt parameters. The 3rd order Steinhardt parameters allow us to measure the degree to which the first coordination shell -around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are +around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are calculated using the following formula: \f[ @@ -36,9 +36,9 @@ q_{3m}(i) = \frac{\sum_j \sigma( r_{ij} ) Y_{3m}(\mathbf{r}_{ij}) }{\sum_j \sigm \f] where \f$Y_{3m}\f$ is one of the 3rd order spherical harmonics so \f$m\f$ is a number that runs from \f$-3\f$ to -\f$+3\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +\f$+3\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The Steinhardt parameters can be used to measure the degree of order in the system in a variety of different ways. The simplest way of measuring whether or not the coordination sphere is ordered is to simply take the norm of the above vector i.e. @@ -47,11 +47,11 @@ simplest way of measuring whether or not the coordination sphere is ordered is t Q_3(i) = \sqrt{ \sum_{m=-3}^3 q_{3m}(i)^{*} q_{3m}(i) } \f] -This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when +This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when the keywords LESS_THAN, MIN, MAX, HISTOGRAM, MEAN and so on are used with this colvar it is the distribution of these normed quantities -that is investigated. +that is investigated. -Other measures of order can be taken by averaging the components of the individual \f$q_3\f$ vectors individually or by taking dot products of +Other measures of order can be taken by averaging the components of the individual \f$q_3\f$ vectors individually or by taking dot products of the \f$q_{3}\f$ vectors on adjacent atoms. More information on these variables can be found in the documentation for \ref LOCAL_Q3, \ref LOCAL_AVERAGE and \ref NLINKS. @@ -75,7 +75,7 @@ PRINT ARG=q3.* FILE=colvar The following command could be used to measure the Q3 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input -with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q3 paramter is calculated and output to a +with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q3 paramter is calculated and output to a file called colvar \verbatim @@ -92,12 +92,12 @@ Calculate the local degree of order around an atoms by taking the average dot pr on the atoms in the first coordination sphere. The \ref Q3 command allows one to calculate one complex vectors for each of the atoms in your system that describe the degree of order in the coordination sphere -around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a -measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is +around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a +measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is examining nucleation say only the order parameters for those atoms in the nucleus will change significantly when the nucleus forms. The order parameters for the atoms in the surrounding liquid will remain pretty much the same. As such if one models a small nucleus embedded in a very large amount of solution/melt any -change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only -because the number of atoms is relatively small. +change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only +because the number of atoms is relatively small. When the average \ref Q3 parameter is used to bias the dynamics a problems can occur. These averaged coordinates cannot distinguish between the correct, @@ -116,17 +116,17 @@ biased dynamics what is really required is an order parameter that measures: - Whether or not the atoms that are ordered are clustered together in a crystalline nucleus \ref LOCAL_AVERAGE and \ref NLINKS are variables that can be combined with the Steinhardt parameteters allow to calculate variables that satisfy these requirements. -LOCAL_Q3 is another variable that can be used in these sorts of calculations. The LOCAL_Q3 parameter for a particular atom is a number that measures the extent to -which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following +LOCAL_Q3 is another variable that can be used in these sorts of calculations. The LOCAL_Q3 parameter for a particular atom is a number that measures the extent to +which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following quantity for each of the atoms in the system: \f[ s_i = \frac{ \sum_j \sigma( r_{ij} ) \sum_{m=-3}^3 q_{3m}^{*}(i)q_{3m}(j) }{ \sum_j \sigma( r_{ij} ) } \f] - + where \f$q_{3m}(i)\f$ and \f$q_{3m}(j)\f$ are the 3rd order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes complex conjugation. The function -\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set +\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The sum in the numerator of this expression is the dot product of the Steinhardt parameters for atoms \f$i\f$ and \f$j\f$ and thus measures the degree to which the orientations of these adjacent atoms is correlated. @@ -178,13 +178,13 @@ PLUMED_REGISTER_ACTION(Q3,"Q3") typedef LocalSteinhardt LOCAL_Q3; PLUMED_REGISTER_ACTION(LOCAL_Q3,"LOCAL_Q3") -void Q3::registerKeywords( Keywords& keys ){ +void Q3::registerKeywords( Keywords& keys ) { Steinhardt::registerKeywords( keys ); } Q3::Q3(const ActionOptions& ao ): -Action(ao), -Steinhardt(ao) + Action(ao), + Steinhardt(ao) { setAngularMomentum(3); @@ -200,10 +200,10 @@ Steinhardt(ao) // Legendre polynomial coefficients of order three - coeff_poly.resize( 4 ); - coeff_poly[0]=0.0; + coeff_poly.resize( 4 ); + coeff_poly[0]=0.0; coeff_poly[1]=-1.5; - coeff_poly[2]=0.0; + coeff_poly[2]=0.0; coeff_poly[3]=2.5; } diff --git a/src/crystallization/Q4.cpp b/src/crystallization/Q4.cpp index 6be9c9b470..fa76b0d10e 100644 --- a/src/crystallization/Q4.cpp +++ b/src/crystallization/Q4.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "Steinhardt.h" -#include "LocalSteinhardt.h" +#include "LocalSteinhardt.h" #include "core/ActionRegister.h" //+PLUMEDOC MCOLVAR Q4 @@ -28,7 +28,7 @@ Calculate 4th order Steinhardt parameters. The 4th order Steinhardt parameters allow us to measure the degree to which the first coordination shell -around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are +around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are calculated using the following formula: \f[ @@ -36,9 +36,9 @@ q_{4m}(i) = \frac{\sum_j \sigma( r_{ij} ) Y_{4m}(\mathbf{r}_{ij}) }{\sum_j \sigm \f] where \f$Y_{4m}\f$ is one of the 4th order spherical harmonics so \f$m\f$ is a number that runs from \f$-4\f$ to -\f$+4\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +\f$+4\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The Steinhardt parameters can be used to measure the degree of order in the system in a variety of different ways. The simplest way of measuring whether or not the coordination sphere is ordered is to simply take the norm of the above vector i.e. @@ -47,11 +47,11 @@ simplest way of measuring whether or not the coordination sphere is ordered is t Q_4(i) = \sqrt{ \sum_{m=-4}^4 q_{4m}(i)^{*} q_{4m}(i) } \f] -This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when +This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when the keywords LESS_THAN, MIN, MAX, HISTOGRAM, MEAN and so on are used with this colvar it is the distribution of these normed quantities -that is investigated. +that is investigated. -Other measures of order can be taken by averaging the components of the individual \f$q_4\f$ vectors individually or by taking dot products of +Other measures of order can be taken by averaging the components of the individual \f$q_4\f$ vectors individually or by taking dot products of the \f$q_{4}\f$ vectors on adjacent atoms. More information on these variables can be found in the documentation for \ref LOCAL_Q4, \ref LOCAL_AVERAGE and \ref NLINKS. @@ -75,7 +75,7 @@ PRINT ARG=q4.* FILE=colvar The following command could be used to measure the Q4 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input -with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q4 paramter is calculated and output to a +with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q4 paramter is calculated and output to a file called colvar \verbatim @@ -92,12 +92,12 @@ Calculate the local degree of order around an atoms by taking the average dot pr on the atoms in the first coordination sphere. The \ref Q4 command allows one to calculate one complex vectors for each of the atoms in your system that describe the degree of order in the coordination sphere -around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a -measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is +around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a +measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is examining nucleation say only the order parameters for those atoms in the nucleus will change significantly when the nucleus forms. The order parameters for the atoms in the surrounding liquid will remain pretty much the same. As such if one models a small nucleus embedded in a very large amount of solution/melt any -change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only -because the number of atoms is relatively small. +change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only +because the number of atoms is relatively small. When the average \ref Q4 parameter is used to bias the dynamics a problems can occur. These averaged coordinates cannot distinguish between the correct, @@ -116,17 +116,17 @@ biased dynamics what is really required is an order parameter that measures: - Whether or not the atoms that are ordered are clustered together in a crystalline nucleus \ref LOCAL_AVERAGE and \ref NLINKS are variables that can be combined with the Steinhardt parameteters allow to calculate variables that satisfy these requirements. -LOCAL_Q4 is another variable that can be used in these sorts of calculations. The LOCAL_Q4 parameter for a particular atom is a number that measures the extent to -which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following +LOCAL_Q4 is another variable that can be used in these sorts of calculations. The LOCAL_Q4 parameter for a particular atom is a number that measures the extent to +which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following quantity for each of the atoms in the system: \f[ s_i = \frac{ \sum_j \sigma( r_{ij} ) \sum_{m=-4}^4 q_{4m}^{*}(i)q_{4m}(j) }{ \sum_j \sigma( r_{ij} ) } \f] - + where \f$q_{4m}(i)\f$ and \f$q_{4m}(j)\f$ are the 4th order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes complex conjugation. The function -\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set +\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The sum in the numerator of this expression is the dot product of the Steinhardt parameters for atoms \f$i\f$ and \f$j\f$ and thus measures the degree to which the orientations of these adjacent atoms is correlated. @@ -177,13 +177,13 @@ PLUMED_REGISTER_ACTION(Q4,"Q4") typedef LocalSteinhardt LOCAL_Q4; PLUMED_REGISTER_ACTION(LOCAL_Q4,"LOCAL_Q4") -void Q4::registerKeywords( Keywords& keys ){ +void Q4::registerKeywords( Keywords& keys ) { Steinhardt::registerKeywords( keys ); } Q4::Q4(const ActionOptions& ao ): -Action(ao), -Steinhardt(ao) + Action(ao), + Steinhardt(ao) { setAngularMomentum(4); @@ -194,10 +194,10 @@ Steinhardt(ao) normaliz[3] = -sqrt( ( 9.0*1) / (4.0*pi*5040.0) ); normaliz[4] = sqrt( (9.0*1) / (4.0*pi*40320.0) ); - coeff_poly.resize( 5 ); + coeff_poly.resize( 5 ); coeff_poly[0]=0.375; coeff_poly[1]=0.0; coeff_poly[2]=-3.75; coeff_poly[3]=0.0; - coeff_poly[4]=4.375; + coeff_poly[4]=4.375; } } diff --git a/src/crystallization/Q6.cpp b/src/crystallization/Q6.cpp index e473d8b65f..447b0e1cb4 100644 --- a/src/crystallization/Q6.cpp +++ b/src/crystallization/Q6.cpp @@ -28,7 +28,7 @@ Calculate 6th order Steinhardt parameters. The 6th order Steinhardt parameters allow us to measure the degree to which the first coordination shell -around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are +around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are calculated using the following formula: \f[ @@ -36,9 +36,9 @@ q_{6m}(i) = \frac{\sum_j \sigma( r_{ij} ) Y_{6m}(\mathbf{r}_{ij}) }{\sum_j \sigm \f] where \f$Y_{6m}\f$ is one of the 6th order spherical harmonics so \f$m\f$ is a number that runs from \f$-6\f$ to -\f$+6\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +\f$+6\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The Steinhardt parameters can be used to measure the degree of order in the system in a variety of different ways. The simplest way of measuring whether or not the coordination sphere is ordered is to simply take the norm of the above vector i.e. @@ -47,11 +47,11 @@ simplest way of measuring whether or not the coordination sphere is ordered is t Q_6(i) = \sqrt{ \sum_{m=-6}^6 q_{6m}(i)^{*} q_{6m}(i) } \f] -This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when +This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when the keywords LESS_THAN, MIN, MAX, HISTOGRAM, MEAN and so on are used with this colvar it is the distribution of these normed quantities -that is investigated. +that is investigated. -Other measures of order can be taken by averaging the components of the individual \f$q_6\f$ vectors individually or by taking dot products of +Other measures of order can be taken by averaging the components of the individual \f$q_6\f$ vectors individually or by taking dot products of the \f$q_{6}\f$ vectors on adjacent atoms. More information on these variables can be found in the documentation for \ref LOCAL_Q6, \ref LOCAL_AVERAGE and \ref NLINKS. @@ -75,7 +75,7 @@ PRINT ARG=q6.* FILE=colvar The following command could be used to measure the Q6 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input -with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q6 paramter is calculated and output to a +with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q6 paramter is calculated and output to a file called colvar \verbatim @@ -92,12 +92,12 @@ Calculate the local degree of order around an atoms by taking the average dot pr on the atoms in the first coordination sphere. The \ref Q6 command allows one to calculate one complex vectors for each of the atoms in your system that describe the degree of order in the coordination sphere -around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a -measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is +around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a +measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is examining nucleation say only the order parameters for those atoms in the nucleus will change significantly when the nucleus forms. The order parameters for the atoms in the surrounding liquid will remain pretty much the same. As such if one models a small nucleus embedded in a very large amount of solution/melt any -change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only -because the number of atoms is relatively small. +change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only +because the number of atoms is relatively small. When the average \ref Q6 parameter is used to bias the dynamics a problems can occur. These averaged coordinates cannot distinguish between the correct, @@ -116,17 +116,17 @@ biased dynamics what is really required is an order parameter that measures: - Whether or not the atoms that are ordered are clustered together in a crystalline nucleus \ref LOCAL_AVERAGE and \ref NLINKS are variables that can be combined with the Steinhardt parameteters allow to calculate variables that satisfy these requirements. -LOCAL_Q6 is another variable that can be used in these sorts of calculations. The LOCAL_Q6 parameter for a particular atom is a number that measures the extent to -which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following +LOCAL_Q6 is another variable that can be used in these sorts of calculations. The LOCAL_Q6 parameter for a particular atom is a number that measures the extent to +which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following quantity for each of the atoms in the system: \f[ s_i = \frac{ \sum_j \sigma( r_{ij} ) \sum_{m=-6}^6 q_{6m}^{*}(i)q_{6m}(j) }{ \sum_j \sigma( r_{ij} ) } \f] - -where \f$q_{6m}(i)\f$ and \f$q_{6m}(j)\f$ are the 6th order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes + +where \f$q_{6m}(i)\f$ and \f$q_{6m}(j)\f$ are the 6th order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes complex conjugation. The function -\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set +\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The sum in the numerator of this expression is the dot product of the Steinhardt parameters for atoms \f$i\f$ and \f$j\f$ and thus measures the degree to which the orientations of these adjacent atoms is correlated. @@ -177,13 +177,13 @@ PLUMED_REGISTER_ACTION(Q6,"Q6") typedef LocalSteinhardt LOCAL_Q6; PLUMED_REGISTER_ACTION(LOCAL_Q6,"LOCAL_Q6") -void Q6::registerKeywords( Keywords& keys ){ +void Q6::registerKeywords( Keywords& keys ) { Steinhardt::registerKeywords( keys ); } Q6::Q6(const ActionOptions& ao ): -Action(ao), -Steinhardt(ao) + Action(ao), + Steinhardt(ao) { setAngularMomentum(6); @@ -196,11 +196,11 @@ Steinhardt(ao) normaliz[5] = -sqrt( (13.0*1) / (4.0*pi*39916800) ); normaliz[6] = sqrt( (13.0*1) / (4.0*pi*479001600) ); - coeff_poly.resize( 7 ); + coeff_poly.resize( 7 ); coeff_poly[0]=-0.3125; coeff_poly[1]=0.0; coeff_poly[2]=6.5625; coeff_poly[3]=0.0; coeff_poly[4]=-19.6875; coeff_poly[5]=0.0; - coeff_poly[6]=14.4375; + coeff_poly[6]=14.4375; } } diff --git a/src/crystallization/SMAC.cpp b/src/crystallization/SMAC.cpp index 18e9a2ab05..ce83df7380 100644 --- a/src/crystallization/SMAC.cpp +++ b/src/crystallization/SMAC.cpp @@ -28,40 +28,40 @@ /* Calculate a variant on the SMAC collective variable discussed in \cite smac-paper -The SMAC collective variable can be used to study the formation of molecular solids -from either the melt or from solution. The idea behind this variable is that what -differentiates a molecular solid from a molecular liquid is an alignment of -internal vectors in neighboring molecules. In other words, the relative orientation +The SMAC collective variable can be used to study the formation of molecular solids +from either the melt or from solution. The idea behind this variable is that what +differentiates a molecular solid from a molecular liquid is an alignment of +internal vectors in neighboring molecules. In other words, the relative orientation of neighboring molecules is no longer random as it is in a liquid. In a solid particular torsional angles between molecules are preferred. As such this CV calculates the following average: \f[ s_i = \frac{ \left\{ 1 - \psi\left[ \sum_{j \ne i} \sigma(r_{ij}) \right] \right\} \sum_{j \ne i} \sigma(r_{ij}) \sum_n K_n(\theta_{ij}) }{ \sum_{j \ne i} \sigma(r_{ij}) } -\f] +\f] In this expression \f$r_{ij}\f$ is the distance between molecule \f$i\f$ and molecule \f$j\f$ and \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that acts on this distance. By including this switching function in the second summation in the -numerator and in the denominator we are thus ensuring that we calculate an average over the molecules in the first coordination -sphere of molecule \f$i\f$. All molecules in higher coordination sphere will essentially contribute zero to the sums in the -above expression because their \f$\sigma(r_{ij})\f$ will be very small. \f$\psi\f$ is also a switching function. The term +numerator and in the denominator we are thus ensuring that we calculate an average over the molecules in the first coordination +sphere of molecule \f$i\f$. All molecules in higher coordination sphere will essentially contribute zero to the sums in the +above expression because their \f$\sigma(r_{ij})\f$ will be very small. \f$\psi\f$ is also a switching function. The term including \f$\psi\f$ in the numerator is there to ensure that only those molecules that are attached to a reasonably large number of molecules. It is important to include this "more than" switching function when you are simulating nucleation -from solution with this CV. Lastly, the $K_n functions are \ref kernelfunctions that take the torsion angle, \f$\theta_{ij}\f$, between the +from solution with this CV. Lastly, the $K_n functions are \ref kernelfunctions that take the torsion angle, \f$\theta_{ij}\f$, between the internal orientation vectors for molecules \f$i\f$ and \f$j\f$ as input. These kernel functions should be set so that they are equal to one when the relative orientation of the moleclues are as they are in the solid and equal to zero otherwise. The final \f$s_i\f$ quantity thus measures whether (on average) the molecules in the first coordination sphere around molecule \f$i\f$ -are oriented as they would be in the solid. Furthermore, this Action is a multicolvar so you can calculate the \f$s_i\f$ values -for all the molecules in your system simultaneously and then determine the average, the number less than and so on. +are oriented as they would be in the solid. Furthermore, this Action is a multicolvar so you can calculate the \f$s_i\f$ values +for all the molecules in your system simultaneously and then determine the average, the number less than and so on. \par Examples -In the example below the orientation of the molecules in the system is determined by calculating the +In the example below the orientation of the molecules in the system is determined by calculating the vector that connects a pair of atoms. SMAC is then used to determine whether the molecules are sitting -in a solid or liquid like environment. We can determine whether the environment is solid or liquid like because in the solid the torsional angle between +in a solid or liquid like environment. We can determine whether the environment is solid or liquid like because in the solid the torsional angle between the bond vectors on adjacent molecules is close to 0 or \f$\pi\f$. The final quantity that is output to the colvar file measures the number of molecules that have a SMAC parameter that is greater than 0.7. N.B. By using -the indices of three atoms for each of the MOL keywords below we are telling PLUMED to use the first two +the indices of three atoms for each of the MOL keywords below we are telling PLUMED to use the first two numbers to determine the orientation of the molecule that will ultimately be used when calculating the \f$\theta_{ij}\f$ terms in the formula above. The atom with the third index meanwhile is used when we calculate \f$r_{ij}\f$. @@ -79,8 +79,8 @@ LABEL=m3 ... MOLECULES SMAC ... - SPECIES=m3 LOWMEM - KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} + SPECIES=m3 LOWMEM + KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} SWITCH={RATIONAL R_0=0.6} MORE_THAN={RATIONAL R_0=0.7} SWITCH_COORD={EXP R_0=4} LABEL=s2 ... SMAC @@ -89,7 +89,7 @@ PRINT ARG=s2.* FILE=colvar \endverbatim This second example works in a way that is very similar to the previous command. Now, however, -the orientation of the molecules is determined by finding the plane that contains the positions +the orientation of the molecules is determined by finding the plane that contains the positions of three atoms. \verbatim @@ -106,9 +106,9 @@ VMEAN LABEL=m3 ... PLANES -SMAC ... - SPECIES=m3 LOWMEM - KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} +SMAC ... + SPECIES=m3 LOWMEM + KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} SWITCH={RATIONAL R_0=0.6} MORE_THAN={RATIONAL R_0=0.7} SWITCH_COORD={EXP R_0=3.0} LABEL=s2 ... SMAC @@ -127,70 +127,70 @@ class SMAC : public OrientationSphere { std::vector kernels; SwitchingFunction coord_switch; public: - static void registerKeywords( Keywords& keys ); - explicit SMAC(const ActionOptions& ao); - double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, + static void registerKeywords( Keywords& keys ); + explicit SMAC(const ActionOptions& ao); + double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; double calculateCoordinationPrefactor( const double& coord, double& df ) const ; }; PLUMED_REGISTER_ACTION(SMAC,"SMAC") -void SMAC::registerKeywords( Keywords& keys ){ +void SMAC::registerKeywords( Keywords& keys ) { OrientationSphere::registerKeywords(keys); keys.add("numbered","KERNEL","The kernels used in the function of the angle"); keys.add("compulsory","SWITCH_COORD","This keyword is used to define the coordination switching function."); - keys.reset_style("KERNEL","compulsory"); + keys.reset_style("KERNEL","compulsory"); } SMAC::SMAC(const ActionOptions& ao): -Action(ao), -OrientationSphere(ao) + Action(ao), + OrientationSphere(ao) { - if( mybasemulticolvars.size()==0 ) error("SMAC must take multicolvar as input"); - for(unsigned i=0;igetNumberOfQuantities()-2)%3!=0 ) error("SMAC is only possible with three dimensional vectors"); - } - - std::string kernelinpt; - for(int i=1;;i++){ - if( !parseNumbered("KERNEL",i,kernelinpt) ) break; - KernelFunctions mykernel( kernelinpt, false ); - kernels.push_back( mykernel ); - } - if( kernels.size()==0 ) error("no kernels defined"); - - std::string sw, errors; parse("SWITCH_COORD",sw); - if(sw.length()==0) error("SWITCH_COORD keyword is missing"); - coord_switch.set(sw,errors); - if(errors.length()>0) error("the following errors were found in input to SWITCH_COORD : " + errors ); + if( mybasemulticolvars.size()==0 ) error("SMAC must take multicolvar as input"); + for(unsigned i=0; igetNumberOfQuantities()-2)%3!=0 ) error("SMAC is only possible with three dimensional vectors"); + } + + std::string kernelinpt; + for(int i=1;; i++) { + if( !parseNumbered("KERNEL",i,kernelinpt) ) break; + KernelFunctions mykernel( kernelinpt, false ); + kernels.push_back( mykernel ); + } + if( kernels.size()==0 ) error("no kernels defined"); + + std::string sw, errors; parse("SWITCH_COORD",sw); + if(sw.length()==0) error("SWITCH_COORD keyword is missing"); + coord_switch.set(sw,errors); + if(errors.length()>0) error("the following errors were found in input to SWITCH_COORD : " + errors ); } -double SMAC::computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, +double SMAC::computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { unsigned nvectors = ( vec1.size() - 2 ) / 3; plumed_assert( (vec1.size()-2)%3==0 ); std::vector dv1(nvectors), dv2(nvectors), tdconn(nvectors); Torsion t; std::vector v1(nvectors), v2(nvectors); - std::vector pos; for(unsigned i=0;isetDomain( "-pi", "pi" ); } - - for(unsigned j=0;jset( angle ); + std::vector pos; for(unsigned i=0; isetDomain( "-pi", "pi" ); } + + for(unsigned j=0; jset( angle ); } - double ans=0; std::vector deriv( nvectors ), df( nvectors, 0 ); - for(unsigned i=0;i deriv( nvectors ), df( nvectors, 0 ); + for(unsigned i=0; i0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" Steinhardt parameter of central atom and those within %s\n",( switchingFunction.description() ).c_str() ); log<<" Bibliography "< all_atoms; setupMultiColvarBase( all_atoms ); } -void Steinhardt::setAngularMomentum( const unsigned& ang ){ +void Steinhardt::setAngularMomentum( const unsigned& ang ) { tmom=ang; setVectorDimensionality( 2*(2*ang + 1) ); -} +} void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { - double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; + double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; Vector dz, myrealvec, myimagvec, real_dz, imag_dz; // The square root of -1 std::complex ii( 0.0, 1.0 ), dp_x, dp_y, dp_z; - unsigned ncomp=2*tmom+1; + unsigned ncomp=2*tmom+1; double sw, poly_ass, d2, dlen; std::complex powered; - for(unsigned i=1;i com1( distance[0]/dlen ,distance[1]/dlen ); - - // Do stuff for all other m values - for(unsigned m=1;m<=tmom;++m){ - // Calculate Legendre Polynomial - poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass ); - // Calculate powe of complex number - powered=pow(com1,m-1); md=static_cast(m); - // Real and imaginary parts of z - real_z = real(com1*powered); imag_z = imag(com1*powered ); - - // Calculate steinhardt parameter - tq6=poly_ass*real_z; // Real part of steinhardt parameter - itq6=poly_ass*imag_z; // Imaginary part of steinhardt parameter - - // Derivatives wrt ( x/r + iy )^m - dp_x = md*powered*( (1.0/dlen)-(distance[0]*distance[0])/dlen3-ii*(distance[0]*distance[1])/dlen3 ); - dp_y = md*powered*( ii*(1.0/dlen)-(distance[0]*distance[1])/dlen3-ii*(distance[1]*distance[1])/dlen3 ); - dp_z = md*powered*( -(distance[0]*distance[2])/dlen3-ii*(distance[1]*distance[2])/dlen3 ); - - // Derivatives of real and imaginary parts of above - real_dz[0] = real( dp_x ); real_dz[1] = real( dp_y ); real_dz[2] = real( dp_z ); - imag_dz[0] = imag( dp_x ); imag_dz[1] = imag( dp_y ); imag_dz[2] = imag( dp_z ); - - // Complete derivative of steinhardt parameter - myrealvec = (+sw)*dpoly_ass*real_z*dz + (+dfunc)*distance*tq6 + (+sw)*poly_ass*real_dz; - myimagvec = (+sw)*dpoly_ass*imag_z*dz + (+dfunc)*distance*itq6 + (+sw)*poly_ass*imag_dz; - - // Real part - accumulateSymmetryFunction( 2 + tmom + m, i, sw*tq6, myrealvec, Tensor( -myrealvec,distance ), myatoms ); - // Imaginary part - accumulateSymmetryFunction( 2+ncomp+tmom+m, i, sw*itq6, myimagvec, Tensor( -myimagvec,distance ), myatoms ); - // 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 - accumulateSymmetryFunction( 2+tmom-m, i, pref*sw*tq6, pref*myrealvec, pref*Tensor( -myrealvec,distance ), myatoms ); - // Imaginary part - accumulateSymmetryFunction( 2+ncomp+tmom-m, i, -pref*sw*itq6, -pref*myimagvec, pref*Tensor( myimagvec,distance ), myatoms ); - } - } - } - - // Normalize + for(unsigned i=1; i com1( distance[0]/dlen,distance[1]/dlen ); + + // Do stuff for all other m values + for(unsigned m=1; m<=tmom; ++m) { + // Calculate Legendre Polynomial + poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass ); + // Calculate powe of complex number + powered=pow(com1,m-1); md=static_cast(m); + // Real and imaginary parts of z + real_z = real(com1*powered); imag_z = imag(com1*powered ); + + // Calculate steinhardt parameter + tq6=poly_ass*real_z; // Real part of steinhardt parameter + itq6=poly_ass*imag_z; // Imaginary part of steinhardt parameter + + // Derivatives wrt ( x/r + iy )^m + dp_x = md*powered*( (1.0/dlen)-(distance[0]*distance[0])/dlen3-ii*(distance[0]*distance[1])/dlen3 ); + dp_y = md*powered*( ii*(1.0/dlen)-(distance[0]*distance[1])/dlen3-ii*(distance[1]*distance[1])/dlen3 ); + dp_z = md*powered*( -(distance[0]*distance[2])/dlen3-ii*(distance[1]*distance[2])/dlen3 ); + + // Derivatives of real and imaginary parts of above + real_dz[0] = real( dp_x ); real_dz[1] = real( dp_y ); real_dz[2] = real( dp_z ); + imag_dz[0] = imag( dp_x ); imag_dz[1] = imag( dp_y ); imag_dz[2] = imag( dp_z ); + + // Complete derivative of steinhardt parameter + myrealvec = (+sw)*dpoly_ass*real_z*dz + (+dfunc)*distance*tq6 + (+sw)*poly_ass*real_dz; + myimagvec = (+sw)*dpoly_ass*imag_z*dz + (+dfunc)*distance*itq6 + (+sw)*poly_ass*imag_dz; + + // Real part + accumulateSymmetryFunction( 2 + tmom + m, i, sw*tq6, myrealvec, Tensor( -myrealvec,distance ), myatoms ); + // Imaginary part + accumulateSymmetryFunction( 2+ncomp+tmom+m, i, sw*itq6, myimagvec, Tensor( -myimagvec,distance ), myatoms ); + // 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 + accumulateSymmetryFunction( 2+tmom-m, i, pref*sw*tq6, pref*myrealvec, pref*Tensor( -myrealvec,distance ), myatoms ); + // Imaginary part + accumulateSymmetryFunction( 2+ncomp+tmom-m, i, -pref*sw*itq6, -pref*myimagvec, pref*Tensor( myimagvec,distance ), myatoms ); + } + } + } + + // Normalize updateActiveAtoms( myatoms ); - for(unsigned i=0;igetNumberOfQuantities() - 2; - if( getAction()->derivativesAreRequired() ){ - nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*(ncomp+1) ); getFinalValue()->resizeDerivatives( nder ); + if( getAction()->derivativesAreRequired() ) { + nder=getAction()->getNumberOfDerivatives(); + resizeBuffer( (1+nder)*(ncomp+1) ); getFinalValue()->resizeDerivatives( nder ); } else { - nder=0; resizeBuffer(ncomp+1); + nder=0; resizeBuffer(ncomp+1); } } void VectorMean::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); buffer[bufstart] += weight; - for(unsigned i=0;iderivativesAreRequired() ) return; if( diffweight ) myvals.chainRule( 0, 0, 1, 0, 1.0, bufstart, buffer ); - for(unsigned i=0;i& buffer ){ +void VectorMean::finish( const std::vector& buffer ) { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double sum=0, ww=buffer[bufstart]; - for(unsigned i=0;iderivativesAreRequired() ) return; Value* fval=getFinalValue(); double tw = 1.0 / sqrt(sum); - for(unsigned icomp=0;icompaddDerivative( jder, (tw*tmp/ww)*( buffer[bstart + jder] - tmp*buffer[bufstart + 1 + jder] ) ); + for(unsigned icomp=0; icompaddDerivative( 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 e3bd4d4d59..9a070de58e 100644 --- a/src/crystallization/VectorMultiColvar.cpp +++ b/src/crystallization/VectorMultiColvar.cpp @@ -25,24 +25,24 @@ namespace PLMD { namespace crystallization { -void VectorMultiColvar::registerKeywords( Keywords& keys ){ +void VectorMultiColvar::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); } VectorMultiColvar::VectorMultiColvar(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao), -store_director(true) + Action(ao), + MultiColvarBase(ao), + store_director(true) { setLowMemOption(true); } -void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp ){ +void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp ) { ncomponents = ncomp; resizeFunctions(); // This resize needs to be here to ensure buffers are set to correct size in base } -void VectorMultiColvar::doNotCalculateDirector(){ - 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 +void VectorMultiColvar::doNotCalculateDirector() { + 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::compute( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ) const { @@ -52,46 +52,46 @@ double VectorMultiColvar::compute( const unsigned& taskIndex, multicolvar::AtomV updateActiveAtoms( myatoms ); // Now calculate the norm of the vector (this is what we return here) - double norm=0; - for(unsigned i=0;i dervec( ncomponents ); - for(unsigned i=0;i dervec( ncomponents ); + for(unsigned i=0; i& vals ) const { double inorm = 1.0; if( vals[1]>epsilon ) inorm = 1.0 / vals[1]; - for(unsigned i=2;i& inforces ){ +void VectorMultiColvar::addForcesOnAtoms( const std::vector& inforces ) { plumed_dbg_assert( inforces.size()==getNumberOfDerivatives() ); - std::vector oldforces( getNumberOfDerivatives() ); - getForcesFromVessels( oldforces ); - for(unsigned i=0;i oldforces( getNumberOfDerivatives() ); + getForcesFromVessels( oldforces ); + for(unsigned i=0; i& vals ) const ; - virtual void normalizeVectorDerivatives( MultiValue& myvals ) const ; + virtual void normalizeVector( std::vector& vals ) const ; + virtual void normalizeVectorDerivatives( MultiValue& myvals ) const ; }; inline unsigned VectorMultiColvar::getNumberOfComponentsInVector() const { - return ncomponents; + return ncomponents; } inline diff --git a/src/crystallization/VectorSum.cpp b/src/crystallization/VectorSum.cpp index 2c0eb346fc..ca0eaf6529 100644 --- a/src/crystallization/VectorSum.cpp +++ b/src/crystallization/VectorSum.cpp @@ -43,70 +43,70 @@ class VectorSum : public vesselbase::FunctionVessel { PLUMED_REGISTER_VESSEL(VectorSum,"VSUM") -void VectorSum::registerKeywords( Keywords& keys ){ +void VectorSum::registerKeywords( Keywords& keys ) { vesselbase::FunctionVessel::registerKeywords(keys); } -void VectorSum::reserveKeyword( Keywords& keys ){ +void VectorSum::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","VSUM","calculate the norm of the sum of vectors."); keys.addOutputComponent("vsum","VSUM","the norm of sum of vectors. The output component can be refererred to elsewhere in the input " - "file by using the label.vsum"); + "file by using the label.vsum"); } VectorSum::VectorSum( const vesselbase::VesselOptions& da ) : -FunctionVessel(da), -nder(0) + FunctionVessel(da), + nder(0) { } -std::string VectorSum::value_descriptor(){ +std::string VectorSum::value_descriptor() { return "the norm of the mean vector"; } -void VectorSum::resize(){ +void VectorSum::resize() { unsigned ncomp=getAction()->getNumberOfQuantities() - 2; - if( getAction()->derivativesAreRequired() ){ - nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*ncomp ); getFinalValue()->resizeDerivatives( nder ); + if( getAction()->derivativesAreRequired() ) { + nder=getAction()->getNumberOfDerivatives(); + resizeBuffer( (1+nder)*ncomp ); getFinalValue()->resizeDerivatives( nder ); } else { - nder=0; resizeBuffer(ncomp); + nder=0; resizeBuffer(ncomp); } } void VectorSum::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double weight=myvals.get(0); + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); - for(unsigned i=0;iderivativesAreRequired() ) return; - for(unsigned i=0;i& buffer ){ +void VectorSum::finish( const std::vector& buffer ) { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double sum=0; - for(unsigned i=0;iderivativesAreRequired() ) return; Value* fval=getFinalValue(); - for(unsigned icomp=0;icompaddDerivative( jder, tw*tmp*buffer[bstart + jder] ); + for(unsigned icomp=0; icompaddDerivative( jder, tw*tmp*buffer[bstart + jder] ); } } diff --git a/src/eds/EDS.cpp b/src/eds/EDS.cpp index 9d8187555d..e5e575abe1 100644 --- a/src/eds/EDS.cpp +++ b/src/eds/EDS.cpp @@ -104,7 +104,7 @@ eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 IN_RESTART=restart. */ //+ENDPLUMEDOC -class EDS : public Bias{ +class EDS : public Bias { private: @@ -160,7 +160,7 @@ class EDS : public Bias{ void calc_ssd_step_size(); void reset_statistics(); void update_bias(); - void apply_bias(); + void apply_bias(); public: explicit EDS(const ActionOptions&); @@ -171,616 +171,617 @@ class EDS : public Bias{ ~EDS(); }; - PLUMED_REGISTER_ACTION(EDS,"EDS") - - void EDS::registerKeywords(Keywords& keys){ - Bias::registerKeywords(keys); - keys.use("ARG"); - keys.add("optional","CENTER","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. This is for fixed values"); - keys.add("optional","CENTER_ARG","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. " - "CENTER_ARG is for calculated centers, e.g. from a CV or analysis. "); - - keys.add("compulsory","PERIOD","Steps over which to adjust bias"); - - keys.add("compulsory","RANGE","3.0","The largest magnitude of the force constant which one expects (in kBT) for each CV based"); - keys.add("compulsory","SEED","0","Seed for random order of changing bias"); - keys.add("compulsory","INIT","0","Starting value for coupling coefficients"); - keys.add("compulsory","FIXED","0","Fixed target values for bias factors (not adaptive)"); - keys.add("optional","BIAS_SCALE","A divisor to set the units of the bias. " - "If not set, this will be the experimental value by default (as is done in White and Voth 2014)."); - keys.add("optional","TEMP","The system temperature. If not provided will be taken from MD code (if available)"); - keys.add("optional","MULTI_PROP","What proportion of dimensions to update at each step. " - "Must be in interval [1,0), where 1 indicates all and any other indicates a stochastic update. " - "If not set, default is 1 / N, where N is the number of CVs. "); - keys.add("optional","RESTART_FMT","the format that should be used to output real numbers in EDS restarts"); - keys.add("optional","OUT_RESTART","Output file for all information needed to continue EDS simulation. " - "If you have the RESTART directive set (global or for EDS), this file will be appended to. " - "Note that the header will be printed again if appending."); - keys.add("optional","IN_RESTART","Read this file to continue an EDS simulation. " - "If same as OUT_RESTART and you have not set the RESTART directive, the file will be backed-up and overwritten with new output. " - "If you do have the RESTART flag set and it is the same name as OUT_RESTART, this file will be appended."); - - keys.addFlag("RAMP",false,"Slowly increase bias constant to a fixed value"); - keys.addFlag("COVAR",false,"Utilize the covariance matrix when updating the bias. Default Off, but may be enabled due to other options"); - keys.addFlag("FREEZE",false,"Fix bias at current level (only used for restarting). Can also set PERIOD=0 if not using RESTART."); - keys.addFlag("MEAN",false,"Instead of using final bias level from restart, use average. Can only be used in conjunction with FREEZE"); - - keys.use("RESTART"); - - keys.addOutputComponent("force2","default","squared value of force from the bias"); - keys.addOutputComponent("_coupling","default", "For each named CV biased, there will be a corresponding output CV_coupling storing the current linear bias prefactor."); +PLUMED_REGISTER_ACTION(EDS,"EDS") + +void EDS::registerKeywords(Keywords& keys) { + Bias::registerKeywords(keys); + keys.use("ARG"); + keys.add("optional","CENTER","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. This is for fixed values"); + keys.add("optional","CENTER_ARG","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. " + "CENTER_ARG is for calculated centers, e.g. from a CV or analysis. "); + + keys.add("compulsory","PERIOD","Steps over which to adjust bias"); + + keys.add("compulsory","RANGE","3.0","The largest magnitude of the force constant which one expects (in kBT) for each CV based"); + keys.add("compulsory","SEED","0","Seed for random order of changing bias"); + keys.add("compulsory","INIT","0","Starting value for coupling coefficients"); + keys.add("compulsory","FIXED","0","Fixed target values for bias factors (not adaptive)"); + keys.add("optional","BIAS_SCALE","A divisor to set the units of the bias. " + "If not set, this will be the experimental value by default (as is done in White and Voth 2014)."); + keys.add("optional","TEMP","The system temperature. If not provided will be taken from MD code (if available)"); + keys.add("optional","MULTI_PROP","What proportion of dimensions to update at each step. " + "Must be in interval [1,0), where 1 indicates all and any other indicates a stochastic update. " + "If not set, default is 1 / N, where N is the number of CVs. "); + keys.add("optional","RESTART_FMT","the format that should be used to output real numbers in EDS restarts"); + keys.add("optional","OUT_RESTART","Output file for all information needed to continue EDS simulation. " + "If you have the RESTART directive set (global or for EDS), this file will be appended to. " + "Note that the header will be printed again if appending."); + keys.add("optional","IN_RESTART","Read this file to continue an EDS simulation. " + "If same as OUT_RESTART and you have not set the RESTART directive, the file will be backed-up and overwritten with new output. " + "If you do have the RESTART flag set and it is the same name as OUT_RESTART, this file will be appended."); + + keys.addFlag("RAMP",false,"Slowly increase bias constant to a fixed value"); + keys.addFlag("COVAR",false,"Utilize the covariance matrix when updating the bias. Default Off, but may be enabled due to other options"); + keys.addFlag("FREEZE",false,"Fix bias at current level (only used for restarting). Can also set PERIOD=0 if not using RESTART."); + keys.addFlag("MEAN",false,"Instead of using final bias level from restart, use average. Can only be used in conjunction with FREEZE"); + + keys.use("RESTART"); + + keys.addOutputComponent("force2","default","squared value of force from the bias"); + keys.addOutputComponent("_coupling","default", "For each named CV biased, there will be a corresponding output CV_coupling storing the current linear bias prefactor."); +} + +EDS::EDS(const ActionOptions&ao): + PLUMED_BIAS_INIT(ao), + ncvs_(getNumberOfArguments()), + scale_(ncvs_,0.0), + current_coupling_(ncvs_,0.0), + set_coupling_(ncvs_,0.0), + target_coupling_(ncvs_,0.0), + max_coupling_range_(ncvs_,3.0), + max_coupling_grad_(ncvs_,0.0), + coupling_rate_(ncvs_,1.0), + coupling_accum_(ncvs_,1.0), + means_(ncvs_,0.0), + step_size_(ncvs_,0.0), + out_coupling_(ncvs_,NULL), + in_restart_name_(""), + out_restart_name_(""), + fmt_("%f"), + b_adaptive_(true), + b_freeze_(false), + b_equil_(true), + b_ramp_(false), + b_covar_(false), + b_restart_(false), + b_write_restart_(false), + b_hard_c_range_(false), + seed_(0), + update_period_(0), + avg_coupling_count_(1), + update_calls_(0), + kbt_(0.0), + c_range_increase_f_(1.25), + multi_prop_(-1.0), + value_force2_(NULL) +{ + double temp=-1.0; + bool b_mean=false; + + addComponent("force2"); + componentIsNotPeriodic("force2"); + value_force2_ = getPntrToComponent("force2"); + + for(unsigned int i = 0; igetName() + "_coupling"; + addComponent(comp); + componentIsNotPeriodic(comp); + out_coupling_[i]=getPntrToComponent(comp); } - EDS::EDS(const ActionOptions&ao): - PLUMED_BIAS_INIT(ao), - ncvs_(getNumberOfArguments()), - scale_(ncvs_,0.0), - current_coupling_(ncvs_,0.0), - set_coupling_(ncvs_,0.0), - target_coupling_(ncvs_,0.0), - max_coupling_range_(ncvs_,3.0), - max_coupling_grad_(ncvs_,0.0), - coupling_rate_(ncvs_,1.0), - coupling_accum_(ncvs_,1.0), - means_(ncvs_,0.0), - step_size_(ncvs_,0.0), - out_coupling_(ncvs_,NULL), - in_restart_name_(""), - out_restart_name_(""), - fmt_("%f"), - b_adaptive_(true), - b_freeze_(false), - b_equil_(true), - b_ramp_(false), - b_covar_(false), - b_restart_(false), - b_write_restart_(false), - b_hard_c_range_(false), - seed_(0), - update_period_(0), - avg_coupling_count_(1), - update_calls_(0), - kbt_(0.0), - c_range_increase_f_(1.25), - multi_prop_(-1.0), - value_force2_(NULL) - { - double temp=-1.0; - bool b_mean=false; - - addComponent("force2"); - componentIsNotPeriodic("force2"); - value_force2_ = getPntrToComponent("force2"); - - for(unsigned int i = 0;igetName() + "_coupling"; - addComponent(comp); - componentIsNotPeriodic(comp); - out_coupling_[i]=getPntrToComponent(comp); - } - - parseVector("CENTER",center_); - parseArgumentList("CENTER_ARG",center_values_); - parseVector("BIAS_SCALE", scale_); - parseVector("RANGE",max_coupling_range_); - parseVector("FIXED",target_coupling_); - parseVector("INIT",set_coupling_); - parse("PERIOD",update_period_); - parse("TEMP",temp); - parse("SEED",seed_); - parse("MULTI_PROP",multi_prop_); - parse("RESTART_FMT", fmt_); - fmt_ = " " + fmt_;//add space since parse strips them - parse("OUT_RESTART",out_restart_name_); - parseFlag("RAMP",b_ramp_); - parseFlag("FREEZE",b_freeze_); - parseFlag("MEAN",b_mean); - parseFlag("COVAR",b_covar_); - parse("IN_RESTART",in_restart_name_); - checkRead(); - - /* - * Things that are different when usnig changing centers: - * 1. Scale - * 2. The log file - * 3. Reading Restarts - */ - - if(center_.size() == 0) { - if(center_values_.size() == 0) - error("Must set either CENTER or CENTER_ARG"); - else if(center_values_.size() != ncvs_) - error("CENTER_ARG must contain the same number of variables as ARG"); - b_c_values_ = true; - center_.resize(ncvs_); - log.printf(" EDS will use possibly varying centers\n"); - } else { - if(center_.size() != ncvs_) - error("Must have same number of CENTER arguments as ARG arguments"); - else if(center_values_.size() != 0) - error("You can only set CENTER or CENTER_ARG. Not both"); - b_c_values_ = false; - log.printf(" EDS will use fixed centers\n"); - } - - - - log.printf(" setting scaling:"); - if(scale_.size() > 0 && scale_.size() < ncvs_) { - error("the number of BIAS_SCALE values be the same as number of CVs"); - } else if(scale_.size() == 0 && b_c_values_) { - log.printf(" Setting SCALE to be 1 for all CVs\n"); - scale_.resize(ncvs_); - for(unsigned int i = 0; i < ncvs_; ++i) - scale_[i] = 1; - } else if(scale_.size() == 0 && !b_c_values_) { - log.printf(" (default) "); - - scale_.resize(ncvs_); - for(unsigned int i = 0; i < scale_.size(); i++) { - if(center_[i]==0) - error("BIAS_SCALE parameter has been set to CENTER value of 0 (as is default). This will divide by 0, so giving up. See doc for EDS bias"); - scale_[i] = center_[i]; - } - } else { - for(unsigned int i = 0; i < scale_.size(); i++) - log.printf(" %f",scale_[i]); - } - log.printf("\n"); + parseVector("CENTER",center_); + parseArgumentList("CENTER_ARG",center_values_); + parseVector("BIAS_SCALE", scale_); + parseVector("RANGE",max_coupling_range_); + parseVector("FIXED",target_coupling_); + parseVector("INIT",set_coupling_); + parse("PERIOD",update_period_); + parse("TEMP",temp); + parse("SEED",seed_); + parse("MULTI_PROP",multi_prop_); + parse("RESTART_FMT", fmt_); + fmt_ = " " + fmt_;//add space since parse strips them + parse("OUT_RESTART",out_restart_name_); + parseFlag("RAMP",b_ramp_); + parseFlag("FREEZE",b_freeze_); + parseFlag("MEAN",b_mean); + parseFlag("COVAR",b_covar_); + parse("IN_RESTART",in_restart_name_); + checkRead(); + + /* + * Things that are different when usnig changing centers: + * 1. Scale + * 2. The log file + * 3. Reading Restarts + */ + + if(center_.size() == 0) { + if(center_values_.size() == 0) + error("Must set either CENTER or CENTER_ARG"); + else if(center_values_.size() != ncvs_) + error("CENTER_ARG must contain the same number of variables as ARG"); + b_c_values_ = true; + center_.resize(ncvs_); + log.printf(" EDS will use possibly varying centers\n"); + } else { + if(center_.size() != ncvs_) + error("Must have same number of CENTER arguments as ARG arguments"); + else if(center_values_.size() != 0) + error("You can only set CENTER or CENTER_ARG. Not both"); + b_c_values_ = false; + log.printf(" EDS will use fixed centers\n"); + } - if(b_covar_) { - log.printf(" EDS will utilize covariance matrix for update steps\n"); - covar_.resize(ncvs_, ncvs_); - } else { - log.printf(" EDS will utilize variance for update steps\n"); - ssds_.resize(ncvs_); - } + log.printf(" setting scaling:"); + if(scale_.size() > 0 && scale_.size() < ncvs_) { + error("the number of BIAS_SCALE values be the same as number of CVs"); + } else if(scale_.size() == 0 && b_c_values_) { + log.printf(" Setting SCALE to be 1 for all CVs\n"); + scale_.resize(ncvs_); + for(unsigned int i = 0; i < ncvs_; ++i) + scale_[i] = 1; + } else if(scale_.size() == 0 && !b_c_values_) { + log.printf(" (default) "); - if (b_mean == true and b_freeze_ == false) { - error("EDS keyworkd MEAN can only be used along with keyword FREEZE"); + scale_.resize(ncvs_); + for(unsigned int i = 0; i < scale_.size(); i++) { + if(center_[i]==0) + error("BIAS_SCALE parameter has been set to CENTER value of 0 (as is default). This will divide by 0, so giving up. See doc for EDS bias"); + scale_[i] = center_[i]; } + } else { + for(unsigned int i = 0; i < scale_.size(); i++) + log.printf(" %f",scale_[i]); + } + log.printf("\n"); - if(in_restart_name_ != ""){ - b_restart_ = true; - log.printf(" reading simulation information from file: %s\n",in_restart_name_.c_str()); - readInRestart(b_mean); - } else{ - - if(temp>=0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; - else kbt_ = plumed.getAtoms().getKbT(); - - //in driver, this results in kbt of 0 - if(kbt_ == 0){ - error(" Unable to determine valid kBT. " - "Could be because you are runnning from driver or MD didn't give temperature.\n" - "Consider setting temperature manually with the TEMP keyword."); - kbt_ = 1; - } - log.printf(" kBT = %f\n",kbt_); - log.printf(" Updating every %i steps\n",update_period_); - - if(!b_c_values_) { - log.printf(" with centers:"); - for(unsigned int i = 0;i< ncvs_;i++){ - log.printf(" %f ",center_[i]); - } - } else { - log.printf(" with actions centers:"); - for(unsigned int i = 0;i< ncvs_;i++){ - log.printf(" %s ",center_values_[i]->getName().c_str()); - //add dependency on these actions - addDependency(center_values_[i]->getPntrToAction()); - } - } + if(b_covar_) { + log.printf(" EDS will utilize covariance matrix for update steps\n"); + covar_.resize(ncvs_, ncvs_); + } else { + log.printf(" EDS will utilize variance for update steps\n"); + ssds_.resize(ncvs_); + } - log.printf("\n with initial ranges / rates:\n"); - for(unsigned int i = 0;i0){ - log.printf(" setting random seed = %i",seed_); - rand_.setSeed(seed_); - } + if (b_mean == true and b_freeze_ == false) { + error("EDS keyworkd MEAN can only be used along with keyword FREEZE"); + } - for(unsigned int i = 0;i=0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; + else kbt_ = plumed.getAtoms().getKbT(); + + //in driver, this results in kbt of 0 + if(kbt_ == 0) { + error(" Unable to determine valid kBT. " + "Could be because you are runnning from driver or MD didn't give temperature.\n" + "Consider setting temperature manually with the TEMP keyword."); + kbt_ = 1; + } - if(!b_adaptive_){ - if(b_ramp_) { - log.printf(" ramping up coupling constants over %i steps\n",update_period_); - } + log.printf(" kBT = %f\n",kbt_); + log.printf(" Updating every %i steps\n",update_period_); - log.printf(" with starting coupling constants"); - for(unsigned int i = 0;i0){ - update_period_ /= 2; + } else { + log.printf(" with actions centers:"); + for(unsigned int i = 0; i< ncvs_; i++) { + log.printf(" %s ",center_values_[i]->getName().c_str()); + //add dependency on these actions + addDependency(center_values_[i]->getPntrToAction()); } - - } - if(b_freeze_){ - b_adaptive_=false; - update_period_ = 0; - if (b_mean) { - log.printf(" freezing bias at the average level from the restart file\n"); - } else{ - log.printf(" freezing bias at current level\n"); - } + log.printf("\n with initial ranges / rates:\n"); + for(unsigned int i = 0; i 0 && multi_prop_ <= 1.0) { - log.printf(" Will update each dimension stochastically with probability %f\n", multi_prop_); - } else{ - error(" MULTI_PROP must be between 0 and 1\n"); + if(seed_>0) { + log.printf(" setting random seed = %i",seed_); + rand_.setSeed(seed_); } - if(out_restart_name_.length()>0) { - log.printf(" writing restart information every %i steps to file %s with format %s\n",abs(update_period_),out_restart_name_.c_str(), fmt_.c_str()); - b_write_restart_ = true; - setupOutRestart(); - } + for(unsigned int i = 0; i fields; - in_restart_.scanFieldList(fields); - log.printf("field"); - for(unsigned int i = 0;i0) { + update_period_ /= 2; + } - if(in_restart_.FieldExist("update_period")){ - in_restart_.scanField("update_period",update_period_); - }else{ error("No field 'update_period' in restart file"); } - log.printf(" Updating every %i steps\n",update_period_); - if(in_restart_.FieldExist("adaptive")){ - //note, no version of scanField for boolean - in_restart_.scanField("adaptive",adaptive_i); - }else{ error("No field 'adaptive' in restart file"); } - b_adaptive_ = bool(adaptive_i); + } - if(in_restart_.FieldExist("seed")){ - in_restart_.scanField("seed",seed_); - }else{ error("No field 'seed' in restart file"); } - if(seed_>0){ - log.printf(" setting random seed = %i",seed_); - rand_.setSeed(seed_); + if(b_freeze_) { + b_adaptive_=false; + update_period_ = 0; + if (b_mean) { + log.printf(" freezing bias at the average level from the restart file\n"); + } else { + log.printf(" freezing bias at current level\n"); } + } - double time; - std::vector avg_bias = std::vector(center_.size()); - unsigned int N = 0; - std::string cv_name; + if(multi_prop_ == -1.0) { + log.printf(" Will update each dimension stochastically with probability 1 / number of CVs\n"); + multi_prop_ = 1.0 / ncvs_; + } else if(multi_prop_ > 0 && multi_prop_ <= 1.0) { + log.printf(" Will update each dimension stochastically with probability %f\n", multi_prop_); + } else { + error(" MULTI_PROP must be between 0 and 1\n"); + } - while(in_restart_.scanField("time",time)){ + if(out_restart_name_.length()>0) { + log.printf(" writing restart information every %i steps to file %s with format %s\n",abs(update_period_),out_restart_name_.c_str(), fmt_.c_str()); + b_write_restart_ = true; + setupOutRestart(); + } - for(unsigned int i = 0;igetName(); - in_restart_.scanField(cv_name + "_center", set_coupling_[i]); - in_restart_.scanField(cv_name + "_set", set_coupling_[i]); - in_restart_.scanField(cv_name + "_target",target_coupling_[i]); - in_restart_.scanField(cv_name + "_coupling",current_coupling_[i]); - in_restart_.scanField(cv_name + "_maxrange",max_coupling_range_[i]); - in_restart_.scanField(cv_name + "_maxgrad",max_coupling_grad_[i]); + log<<" Bibliography "< fields; + in_restart_.scanFieldList(fields); + log.printf("field"); + for(unsigned int i = 0;i0) { + log.printf(" setting random seed = %i",seed_); + rand_.setSeed(seed_); + } - log.printf(" with centers:"); - for(unsigned int i = 0;i avg_bias = std::vector(center_.size()); + unsigned int N = 0; + std::string cv_name; - log.printf("\n with initial ranges / rates:\n"); - for(unsigned int i = 0;igetName(); + in_restart_.scanField(cv_name + "_center", set_coupling_[i]); + in_restart_.scanField(cv_name + "_set", set_coupling_[i]); + in_restart_.scanField(cv_name + "_target",target_coupling_[i]); + in_restart_.scanField(cv_name + "_coupling",current_coupling_[i]); + in_restart_.scanField(cv_name + "_maxrange",max_coupling_range_[i]); + in_restart_.scanField(cv_name + "_maxgrad",max_coupling_grad_[i]); + + avg_bias[i] += current_coupling_[i]; } + N++; - if(b_mean) { - log.printf("Loaded in averages for coupling constants...\n"); - for(unsigned int i = 0;igetName(); - out_restart_.printField(cv_name + "_center",center_[i]); - out_restart_.printField(cv_name + "_set",set_coupling_[i]); - out_restart_.printField(cv_name + "_target",target_coupling_[i]); - out_restart_.printField(cv_name + "_coupling",current_coupling_[i]); - out_restart_.printField(cv_name + "_maxrange",max_coupling_range_[i]); - out_restart_.printField(cv_name + "_maxgrad",max_coupling_grad_[i]); - } - out_restart_.printField(); + log.printf(" with current coupling constants:\n "); + for(unsigned int i = 0; igetName(); + out_restart_.printField(cv_name + "_center",center_[i]); + out_restart_.printField(cv_name + "_set",set_coupling_[i]); + out_restart_.printField(cv_name + "_target",target_coupling_[i]); + out_restart_.printField(cv_name + "_coupling",current_coupling_[i]); + out_restart_.printField(cv_name + "_maxrange",max_coupling_range_[i]); + out_restart_.printField(cv_name + "_maxgrad",max_coupling_grad_[i]); } + out_restart_.printField(); +} - void EDS::calculate(){ - - //get center values from action if necessary - if(b_c_values_) - for(unsigned int i = 0; i < ncvs_; ++i) - center_[i] = center_values_[i]->get(); +void EDS::calculate() { - apply_bias(); + //get center values from action if necessary + if(b_c_values_) + for(unsigned int i = 0; i < ncvs_; ++i) + center_[i] = center_values_[i]->get(); - //adjust parameters according to EDS recipe - update_calls_++; + apply_bias(); - //check if we're ramping or doing normal updates and then restart if needed. The ramping check - //is complicated because we could be frozen, finished ramping or not ramping. - //The + 2 is so we have an extra line showing that the bias isn't changing (for my sanity and yours) - if( b_write_restart_){ - if(getStep() == 0 || - ( (update_period_ < 0 && !b_freeze_ && update_calls_ <= fabs(update_period_) + 2) || - (update_period_ > 0 && update_calls_ % update_period_ == 0 ) ) ) - writeOutRestart(); - } + //adjust parameters according to EDS recipe + update_calls_++; - int b_finished_equil_flag = 1; + //check if we're ramping or doing normal updates and then restart if needed. The ramping check + //is complicated because we could be frozen, finished ramping or not ramping. + //The + 2 is so we have an extra line showing that the bias isn't changing (for my sanity and yours) + if( b_write_restart_) { + if(getStep() == 0 || + ( (update_period_ < 0 && !b_freeze_ && update_calls_ <= fabs(update_period_) + 2) || + (update_period_ > 0 && update_calls_ % update_period_ == 0 ) ) ) + writeOutRestart(); + } - //assume forces already applied and saved + int b_finished_equil_flag = 1; + //assume forces already applied and saved - //are we ramping to a constant value and not done equilibrating? - if(update_period_ < 0){ - if(update_calls_ <= fabs(update_period_) && !b_freeze_){ - for(unsigned int i = 0;i < ncvs_; ++i) - current_coupling_[i] += (target_coupling_[i]-set_coupling_[i])/fabs(update_period_); + + //are we ramping to a constant value and not done equilibrating? + if(update_period_ < 0) { + if(update_calls_ <= fabs(update_period_) && !b_freeze_) { + for(unsigned int i = 0; i < ncvs_; ++i) + current_coupling_[i] += (target_coupling_[i]-set_coupling_[i])/fabs(update_period_); + } + //make sure we don't reset update calls + b_finished_equil_flag = 0; + } else if(update_period_ == 0) { //do we have a no-update case? + //not updating + //pass + } else if(!b_equil_) { + //if we aren't wating for the bias to equilibrate, collect data + update_statistics(); + } else { + // equilibrating + //check if we've reached the setpoint + for(unsigned int i = 0; i < ncvs_; ++i) { + if(coupling_rate_[i] == 0 || pow(current_coupling_[i] - set_coupling_[i],2) < pow(coupling_rate_[i],2)) { + b_finished_equil_flag &= 1; } - //make sure we don't reset update calls - b_finished_equil_flag = 0; - } else if(update_period_ == 0){ //do we have a no-update case? - //not updating - //pass - } else if(!b_equil_){ - //if we aren't wating for the bias to equilibrate, collect data - update_statistics(); - } else { - // equilibrating - //check if we've reached the setpoint - for(unsigned int i = 0;i < ncvs_; ++i) { - if(coupling_rate_[i] == 0 || pow(current_coupling_[i] - set_coupling_[i],2) < pow(coupling_rate_[i],2)) { - b_finished_equil_flag &= 1; - } - else{ - current_coupling_[i] += coupling_rate_[i]; - b_finished_equil_flag = 0; - } + else { + current_coupling_[i] += coupling_rate_[i]; + b_finished_equil_flag = 0; } } + } - //Update max coupling range if not hard - if(!b_hard_c_range_) { - for(unsigned int i = 0;i < ncvs_; ++i) { - if(fabs(current_coupling_[i])>max_coupling_range_[i]) { - max_coupling_range_[i]*=c_range_increase_f_; - max_coupling_grad_[i]*=c_range_increase_f_; - } + //Update max coupling range if not hard + if(!b_hard_c_range_) { + for(unsigned int i = 0; i < ncvs_; ++i) { + if(fabs(current_coupling_[i])>max_coupling_range_[i]) { + max_coupling_range_[i]*=c_range_increase_f_; + max_coupling_grad_[i]*=c_range_increase_f_; } } - - //reduce all the flags - if(b_equil_ && b_finished_equil_flag) { - b_equil_ = false; - update_calls_ = 0; - } - - //Now we update coupling constant, if necessary - if(!b_equil_ && update_period_ > 0 && update_calls_ == update_period_ && !b_freeze_) { - update_bias(); - update_calls_ = 0; - avg_coupling_count_++; - b_equil_ = true; //back to equilibration now - } //close update if - - //pass couplings out so they are accessible - for(unsigned int i = 0;iset(current_coupling_[i]); - } } - void EDS::apply_bias() { - //Compute linear force as in "restraint" - double ene = 0, totf2 = 0, cv, m , f; - - for(unsigned int i = 0; i < ncvs_; ++i) { - cv = difference(i, center_[i], getArgument(i)); - m = current_coupling_[i]; - f = -m; - ene += m*cv; - setOutputForce(i,f); - totf2 += f*f; - }; - - setBias(ene); - value_force2_->set(totf2); - + //reduce all the flags + if(b_equil_ && b_finished_equil_flag) { + b_equil_ = false; + update_calls_ = 0; } - void EDS::update_statistics() { - double s; - std::vector deltas(ncvs_); - //Welford, West, and Hanso online variance method - for(unsigned int i = 0; i < ncvs_; ++i) { - deltas[i] = difference(i,means_[i],getArgument(i)); - means_[i] += deltas[i]/update_calls_; - if(!b_covar_) - ssds_[i] += deltas[i]*difference(i,means_[i],getArgument(i)); - } - if(b_covar_) { - for(unsigned int i = 0; i < ncvs_; ++i) { - for(unsigned int j = i; j < ncvs_; ++j) { - s = (update_calls_ - 1) * deltas[i] * deltas[j] / update_calls_ / update_calls_ - covar_(i,j) / update_calls_; - covar_(i,j) += s; - //do this so we don't double count - covar_(j,i) = covar_(i,j); - } + //Now we update coupling constant, if necessary + if(!b_equil_ && update_period_ > 0 && update_calls_ == update_period_ && !b_freeze_) { + update_bias(); + update_calls_ = 0; + avg_coupling_count_++; + b_equil_ = true; //back to equilibration now + } //close update if + + //pass couplings out so they are accessible + for(unsigned int i = 0; iset(current_coupling_[i]); + } +} + +void EDS::apply_bias() { + //Compute linear force as in "restraint" + double ene = 0, totf2 = 0, cv, m, f; + + for(unsigned int i = 0; i < ncvs_; ++i) { + cv = difference(i, center_[i], getArgument(i)); + m = current_coupling_[i]; + f = -m; + ene += m*cv; + setOutputForce(i,f); + totf2 += f*f; + }; + + setBias(ene); + value_force2_->set(totf2); + +} + +void EDS::update_statistics() { + double s; + std::vector deltas(ncvs_); + //Welford, West, and Hanso online variance method + for(unsigned int i = 0; i < ncvs_; ++i) { + deltas[i] = difference(i,means_[i],getArgument(i)); + means_[i] += deltas[i]/update_calls_; + if(!b_covar_) + ssds_[i] += deltas[i]*difference(i,means_[i],getArgument(i)); + } + if(b_covar_) { + for(unsigned int i = 0; i < ncvs_; ++i) { + for(unsigned int j = i; j < ncvs_; ++j) { + s = (update_calls_ - 1) * deltas[i] * deltas[j] / update_calls_ / update_calls_ - covar_(i,j) / update_calls_; + covar_(i,j) += s; + //do this so we don't double count + covar_(j,i) = covar_(i,j); } } } +} - void EDS::reset_statistics() { - for(unsigned int i = 0; i < ncvs_; ++i) { - means_[i] = 0; - if(!b_covar_) - ssds_[i] = 0; - } - if(b_covar_) - for(unsigned int i = 0; i < ncvs_; ++i) - for(unsigned int j = 0; j < ncvs_; ++j) - covar_(i,j) = 0; +void EDS::reset_statistics() { + for(unsigned int i = 0; i < ncvs_; ++i) { + means_[i] = 0; + if(!b_covar_) + ssds_[i] = 0; } - - void EDS::calc_covar_step_size() { - //calulcate step size - //uses scale here, which by default is center - double tmp; - for(unsigned int i = 0; i< ncvs_; ++i){ - tmp = 0; + if(b_covar_) + for(unsigned int i = 0; i < ncvs_; ++i) for(unsigned int j = 0; j < ncvs_; ++j) - tmp += difference(i, means_[i], center_[i]) * covar_(i,j); - step_size_[i] = 2 * tmp / kbt_ / scale_[i] * update_calls_ / (update_calls_ - 1); - } - + covar_(i,j) = 0; +} + +void EDS::calc_covar_step_size() { + //calulcate step size + //uses scale here, which by default is center + double tmp; + for(unsigned int i = 0; i< ncvs_; ++i) { + tmp = 0; + for(unsigned int j = 0; j < ncvs_; ++j) + tmp += difference(i, means_[i], center_[i]) * covar_(i,j); + step_size_[i] = 2 * tmp / kbt_ / scale_[i] * update_calls_ / (update_calls_ - 1); } - void EDS::calc_ssd_step_size() { - double tmp; - for(unsigned int i = 0; i< ncvs_; ++i){ - tmp = 2. * difference(i, means_[i], center_[i]) * ssds_[i] / (update_calls_ - 1); - step_size_[i] = tmp / kbt_/scale_[i]; - } +} + +void EDS::calc_ssd_step_size() { + double tmp; + for(unsigned int i = 0; i< ncvs_; ++i) { + tmp = 2. * difference(i, means_[i], center_[i]) * ssds_[i] / (update_calls_ - 1); + step_size_[i] = tmp / kbt_/scale_[i]; } +} - void EDS::update_bias() - { - if(b_covar_) - calc_covar_step_size(); - else - calc_ssd_step_size(); - - for(unsigned int i = 0; i< ncvs_; ++i){ - - //check if the step_size exceeds maximum possible gradient - step_size_[i] = copysign(fmin(fabs(step_size_[i]), max_coupling_grad_[i]), step_size_[i]); - - //reset means/vars - reset_statistics(); - - //multidimesional stochastic step - if(ncvs_ == 1 || (rand_.RandU01() < (multi_prop_) ) ) { - coupling_accum_[i] += step_size_[i] * step_size_[i]; - - //equation 5 in White and Voth, JCTC 2014 - //no negative sign because it's in step_size - set_coupling_[i] += max_coupling_range_[i]/sqrt(coupling_accum_[i])*step_size_[i]; - coupling_rate_[i] = (set_coupling_[i]-current_coupling_[i])/update_period_; - - } else { - //do not change the bias - coupling_rate_[i] = 0; - } +void EDS::update_bias() +{ + if(b_covar_) + calc_covar_step_size(); + else + calc_ssd_step_size(); + + for(unsigned int i = 0; i< ncvs_; ++i) { + + //check if the step_size exceeds maximum possible gradient + step_size_[i] = copysign(fmin(fabs(step_size_[i]), max_coupling_grad_[i]), step_size_[i]); + + //reset means/vars + reset_statistics(); + + //multidimesional stochastic step + if(ncvs_ == 1 || (rand_.RandU01() < (multi_prop_) ) ) { + coupling_accum_[i] += step_size_[i] * step_size_[i]; + + //equation 5 in White and Voth, JCTC 2014 + //no negative sign because it's in step_size + set_coupling_[i] += max_coupling_range_[i]/sqrt(coupling_accum_[i])*step_size_[i]; + coupling_rate_[i] = (set_coupling_[i]-current_coupling_[i])/update_period_; + + } else { + //do not change the bias + coupling_rate_[i] = 0; } } +} - void EDS::update(){ - //pass - } +void EDS::update() { + //pass +} - EDS::~EDS(){ - out_restart_.close(); - } +EDS::~EDS() { + out_restart_.close(); +} - void EDS::turnOnDerivatives(){ - // do nothing - // this is to avoid errors triggered when a bias is used as a CV - // (This is done in ExtendedLagrangian.cpp) - } +void EDS::turnOnDerivatives() { + // do nothing + // this is to avoid errors triggered when a bias is used as a CV + // (This is done in ExtendedLagrangian.cpp) +} -}}//close the 2 namespaces +} +}//close the 2 namespaces diff --git a/src/function/Combine.cpp b/src/function/Combine.cpp index 5e3ac9b29f..e76ed7b8bb 100644 --- a/src/function/Combine.cpp +++ b/src/function/Combine.cpp @@ -26,8 +26,8 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION COMBINE /* @@ -92,7 +92,7 @@ class Combine : PLUMED_REGISTER_ACTION(Combine,"COMBINE") -void Combine::registerKeywords(Keywords& keys){ +void Combine::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.use("PERIODIC"); keys.add("compulsory","COEFFICIENTS","1.0","the coefficients of the arguments in your function"); @@ -102,12 +102,12 @@ void Combine::registerKeywords(Keywords& keys){ } Combine::Combine(const ActionOptions&ao): -Action(ao), -Function(ao), -normalize(false), -coefficients(getNumberOfArguments(),1.0), -parameters(getNumberOfArguments(),0.0), -powers(getNumberOfArguments(),1.0) + Action(ao), + Function(ao), + normalize(false), + coefficients(getNumberOfArguments(),1.0), + parameters(getNumberOfArguments(),0.0), + powers(getNumberOfArguments(),1.0) { parseVector("COEFFICIENTS",coefficients); if(coefficients.size()!=static_cast(getNumberOfArguments())) @@ -123,29 +123,29 @@ powers(getNumberOfArguments(),1.0) parseFlag("NORMALIZE",normalize); - if(normalize){ + if(normalize) { double n=0.0; - for(unsigned i=0;ilabel.cvlabel. +Each collective variable is averaged separately and stored in a component labelled label.cvlabel. \par Examples The following input tells plumed to calculate the distance between atoms 3 and 5 and the average it over the available replicas. \verbatim -dist: DISTANCE ATOMS=3,5 +dist: DISTANCE ATOMS=3,5 ens: ENSEMBLE ARG=dist PRINT ARG=dist,ens.dist \endverbatim @@ -72,11 +72,11 @@ class Ensemble : PLUMED_REGISTER_ACTION(Ensemble,"ENSEMBLE") -void Ensemble::registerKeywords(Keywords& keys){ +void Ensemble::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); - keys.addFlag("REWEIGHT",false,"simple REWEIGHT using the latest ARG as energy"); - keys.addFlag("CENTRAL",false,"calculate a central moment instead of a standard moment"); + keys.addFlag("REWEIGHT",false,"simple REWEIGHT using the latest ARG as energy"); + keys.addFlag("CENTRAL",false,"calculate a central moment instead of a standard moment"); keys.add("optional","TEMP","the system temperature - this is only needed if you are reweighting"); keys.add("optional","MOMENT","the moment you want to calculate in alternative to the mean or the variance"); keys.add("optional","POWER","the power of the mean (and moment)"); @@ -84,17 +84,17 @@ void Ensemble::registerKeywords(Keywords& keys){ } Ensemble::Ensemble(const ActionOptions&ao): -Action(ao), -Function(ao), -do_reweight(false), -do_moments(false), -do_central(false), -do_powers(false), -kbt(-1.0), -moment(0), -power(0) + Action(ao), + Function(ao), + do_reweight(false), + do_moments(false), + do_central(false), + do_powers(false), + kbt(-1.0), + moment(0), + power(0) { - parseFlag("REWEIGHT", do_reweight); + parseFlag("REWEIGHT", do_reweight); double temp=0.0; parse("TEMP",temp); if(do_reweight) { @@ -108,7 +108,7 @@ power(0) if(moment!=0) do_moments=true; parseFlag("CENTRAL", do_central); if(!do_moments&&do_central) error("To calculate a CENTRAL moment you need to define for which MOMENT"); - + parse("POWER",power); if(power==1) error("POWER can be any number but for 0 and 1"); if(power!=0) do_powers=true; @@ -116,7 +116,7 @@ power(0) checkRead(); master = (comm.Get_rank()==0); - ens_dim=0; + ens_dim=0; my_repl=0; if(master) { ens_dim=multi_sim_comm.Get_size(); @@ -125,22 +125,22 @@ power(0) comm.Bcast(ens_dim,0); comm.Bcast(my_repl,0); if(ens_dim<2) log.printf("WARNING: ENSEMBLE with one replica is not doing any averaging!\n"); - + // prepare output components, the number depending on reweighing or not narg = getNumberOfArguments(); if(do_reweight) narg--; - + // these are the averages - for(unsigned i=0;igetName(); - addComponentWithDerivatives(s); - getPntrToComponent(i)->setNotPeriodic(); + for(unsigned i=0; igetName(); + addComponentWithDerivatives(s); + getPntrToComponent(i)->setNotPeriodic(); } - // these are the moments + // these are the moments if(do_moments) { - for(unsigned i=0;igetName()+"_m"; - addComponentWithDerivatives(s); + addComponentWithDerivatives(s); getPntrToComponent(i+narg)->setNotPeriodic(); } } @@ -152,38 +152,38 @@ power(0) if(do_powers) log.printf(" calculating the %lf power of the mean (and moment)\n", power); } -void Ensemble::calculate(){ +void Ensemble::calculate() { double norm = 0.0; double fact = 0.0; - // calculate the weights either from BIAS - if(do_reweight){ + // calculate the weights either from BIAS + if(do_reweight) { vector bias; bias.resize(ens_dim); - if(master){ - bias[my_repl] = getArgument(narg); - if(ens_dim>1) multi_sim_comm.Sum(&bias[0], ens_dim); + if(master) { + bias[my_repl] = getArgument(narg); + if(ens_dim>1) multi_sim_comm.Sum(&bias[0], ens_dim); } comm.Sum(&bias[0], ens_dim); const double maxbias = *(std::max_element(bias.begin(), bias.end())); - for(unsigned i=0; i(ens_dim); - fact = 1.0/norm; + norm = static_cast(ens_dim); + fact = 1.0/norm; } const double fact_kbt = fact/kbt; vector mean(narg); vector dmean(narg,fact); - // calculate the mean + // calculate the mean if(master) { - for(unsigned i=0;i1) multi_sim_comm.Sum(&mean[0], narg); } comm.Sum(&mean[0], narg); @@ -196,29 +196,29 @@ void Ensemble::calculate(){ // standard moment if(!do_central) { if(master) { - for(unsigned i=0;i1) multi_sim_comm.Sum(&v_moment[0], narg); } else { - for(unsigned i=0;i1) multi_sim_comm.Sum(&v_moment[0], narg); } else { - for(unsigned i=0;iset(mean[i]); @@ -261,7 +261,7 @@ void Ensemble::calculate(){ setDerivative(u, narg, w_tmp); } } - } + } } } diff --git a/src/function/FuncPathMSD.cpp b/src/function/FuncPathMSD.cpp index 5aa68d1209..f4d481d733 100644 --- a/src/function/FuncPathMSD.cpp +++ b/src/function/FuncPathMSD.cpp @@ -30,30 +30,30 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION FUNCPATHMSD /* -This function calculates path collective variables. +This function calculates path collective variables. -This is the Path Collective Variables implementation +This is the Path Collective Variables implementation ( see \cite brand07 ). -This variable computes the progress along a given set of frames that is provided -in input ("s" component) and the distance from them ("z" component). -It is a function of MSD that are obtained by the joint use of MSD variable and SQUARED flag +This variable computes the progress along a given set of frames that is provided +in input ("s" component) and the distance from them ("z" component). +It is a function of MSD that are obtained by the joint use of MSD variable and SQUARED flag (see below). \par Examples -Here below is a case where you have defined three frames and you want to +Here below is a case where you have defined three frames and you want to calculate the progress alng the path and the distance from it in p1 \verbatim t1: RMSD REFERENCE=frame_1.dat TYPE=OPTIMAL SQUARED t2: RMSD REFERENCE=frame_21.dat TYPE=OPTIMAL SQUARED t3: RMSD REFERENCE=frame_42.dat TYPE=OPTIMAL SQUARED -p1: FUNCPATHMSD ARG=t1,t2,t3 LAMBDA=500.0 +p1: FUNCPATHMSD ARG=t1,t2,t3 LAMBDA=500.0 PRINT ARG=t1,t2,t3,p1.s,p1.z STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim @@ -61,83 +61,83 @@ In this second example is shown how to define a PATH in the \ref CONTACTMAP spac \verbatim CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=0.1 -ATOMS2=3,4 REFERENCE2=0.5 -ATOMS3=4,5 REFERENCE3=0.25 -ATOMS4=5,6 REFERENCE4=0.0 -SWITCH=(RATIONAL R_0=1.5) +ATOMS1=1,2 REFERENCE1=0.1 +ATOMS2=3,4 REFERENCE2=0.5 +ATOMS3=4,5 REFERENCE3=0.25 +ATOMS4=5,6 REFERENCE4=0.0 +SWITCH=(RATIONAL R_0=1.5) LABEL=c1 CMDIST ... CONTACTMAP CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=0.3 -ATOMS2=3,4 REFERENCE2=0.9 -ATOMS3=4,5 REFERENCE3=0.45 -ATOMS4=5,6 REFERENCE4=0.1 -SWITCH=(RATIONAL R_0=1.5) +ATOMS1=1,2 REFERENCE1=0.3 +ATOMS2=3,4 REFERENCE2=0.9 +ATOMS3=4,5 REFERENCE3=0.45 +ATOMS4=5,6 REFERENCE4=0.1 +SWITCH=(RATIONAL R_0=1.5) LABEL=c2 CMDIST ... CONTACTMAP CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=1.0 -ATOMS2=3,4 REFERENCE2=1.0 -ATOMS3=4,5 REFERENCE3=1.0 -ATOMS4=5,6 REFERENCE4=1.0 -SWITCH=(RATIONAL R_0=1.5) +ATOMS1=1,2 REFERENCE1=1.0 +ATOMS2=3,4 REFERENCE2=1.0 +ATOMS3=4,5 REFERENCE3=1.0 +ATOMS4=5,6 REFERENCE4=1.0 +SWITCH=(RATIONAL R_0=1.5) LABEL=c3 CMDIST ... CONTACTMAP -p1: FUNCPATHMSD ARG=c1,c2,c3 LAMBDA=500.0 +p1: FUNCPATHMSD ARG=c1,c2,c3 LAMBDA=500.0 PRINT ARG=c1,c2,c3,p1.s,p1.z STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim */ //+ENDPLUMEDOC - + class FuncPathMSD : public Function { double lambda; int neigh_size; double neigh_stride; vector< pair > neighpair; map indexmap; // use double to allow isomaps - vector allArguments; + vector allArguments; // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -// this below is useful when one wants to sort a vector of double and have back the order +// this below is useful when one wants to sort a vector of double and have back the order // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // create a custom sorter -typedef vector::const_iterator myiter; -struct ordering { - bool operator ()(pair const& a, pair const& b) { - return *(a.second) < *(b.second); - } -}; + typedef vector::const_iterator myiter; + struct ordering { + bool operator ()(pair const& a, pair const& b) { + return *(a.second) < *(b.second); + } + }; // sorting utility -vector increasingOrder( vector &v){ - // make a pair - vector< pair > order(v.size()); - unsigned n = 0; - for (myiter it = v.begin(); it != v.end(); ++it, ++n){ - order[n] = make_pair(n, it); // note: heere i do not put the values but the addresses that point to the value - } - // now sort according the second value - sort(order.begin(), order.end(), ordering()); - vector vv(v.size());n=0; - for (const auto & it : order){ - vv[n]=it.first;n++; - } - return vv; -} + vector increasingOrder( vector &v) { + // make a pair + vector< pair > order(v.size()); + unsigned n = 0; + for (myiter it = v.begin(); it != v.end(); ++it, ++n) { + order[n] = make_pair(n, it); // note: heere i do not put the values but the addresses that point to the value + } + // now sort according the second value + sort(order.begin(), order.end(), ordering()); + vector vv(v.size()); n=0; + for (const auto & it : order) { + vv[n]=it.first; n++; + } + return vv; + } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -struct pairordering { - bool operator ()(pair const& a, pair const& b) { - return (a).second > (b).second; - } -}; + struct pairordering { + bool operator ()(pair const& a, pair const& b) { + return (a).second > (b).second; + } + }; public: explicit FuncPathMSD(const ActionOptions&); @@ -149,7 +149,7 @@ struct pairordering { PLUMED_REGISTER_ACTION(FuncPathMSD,"FUNCPATHMSD") -void FuncPathMSD::registerKeywords(Keywords& keys){ +void FuncPathMSD::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","LAMBDA","the lambda parameter is needed for smoothing, is in the units of plumed"); @@ -160,10 +160,10 @@ void FuncPathMSD::registerKeywords(Keywords& keys){ keys.addOutputComponent("z","default","the distance from the path"); } FuncPathMSD::FuncPathMSD(const ActionOptions&ao): -Action(ao), -Function(ao), -neigh_size(-1), -neigh_stride(-1.) + Action(ao), + Function(ao), + neigh_size(-1), + neigh_stride(-1.) { parse("LAMBDA",lambda); @@ -171,52 +171,52 @@ neigh_stride(-1.) parse("NEIGH_STRIDE",neigh_stride); checkRead(); log.printf(" lambda is %f\n",lambda); - // list the action involved and check the type + // list the action involved and check the type std::string myname=getPntrToArgument(0)->getPntrToAction()->getName(); if(myname!="RMSD"&&myname!="CONTACTMAP"&&myname!="DISTANCE") error("One or more of your arguments is not of RMSD/CONTACTMAP/DISTANCE type!!!"); - for(unsigned i=1;igetPntrToAction()->getName()!=myname ) error("mismatch between the types of arguments"); - } - log.printf(" Consistency check completed! Your path cvs look good!\n"); + for(unsigned i=1; igetPntrToAction()->getName()!=myname ) error("mismatch between the types of arguments"); + } + log.printf(" Consistency check completed! Your path cvs look good!\n"); // do some neighbor printout - if(neigh_stride>0. || neigh_size>0){ - if(neigh_size>getNumberOfArguments()){ - log.printf(" List size required ( %d ) is too large: resizing to the maximum number of arg required: %d \n",neigh_size,getNumberOfArguments()); - neigh_size=getNumberOfArguments(); - } - log.printf(" Neighbor list enabled: \n"); - log.printf(" size : %d elements\n",neigh_size); - log.printf(" stride : %f time \n",neigh_stride); - }else{ - log.printf(" Neighbor list NOT enabled \n"); + if(neigh_stride>0. || neigh_size>0) { + if(neigh_size>getNumberOfArguments()) { + log.printf(" List size required ( %d ) is too large: resizing to the maximum number of arg required: %d \n",neigh_size,getNumberOfArguments()); + neigh_size=getNumberOfArguments(); + } + log.printf(" Neighbor list enabled: \n"); + log.printf(" size : %d elements\n",neigh_size); + log.printf(" stride : %f time \n",neigh_stride); + } else { + log.printf(" Neighbor list NOT enabled \n"); } addComponentWithDerivatives("s"); componentIsNotPeriodic("s"); addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); - // now backup the arguments - for(unsigned i=0;iget())); s_path+=(indexmap[it.first])*it.second; partition+=it.second; @@ -225,7 +225,7 @@ void FuncPathMSD::calculate(){ val_s_path->set(s_path); val_z_path->set(-(1./lambda)*std::log(partition)); int n=0; - for(const auto & it : neighpair){ + for(const auto & it : neighpair) { double expval=it.second; double tmp=lambda*expval*(s_path-(indexmap[it.first]))/partition; setDerivative(val_s_path,n,tmp); @@ -238,60 +238,60 @@ void FuncPathMSD::calculate(){ /// /// this function updates the needed argument list /// -void FuncPathMSD::prepare(){ +void FuncPathMSD::prepare() { - // neighbor list: rank and activate the chain for the next step + // neighbor list: rank and activate the chain for the next step // neighbor list: if neigh_size<0 never sort and keep the full vector - // neighbor list: if neigh_size>0 - // if the size is full -> sort the vector and decide the dependencies for next step - // if the size is not full -> check if next step will need the full dependency otherwise keep this dependencies + // neighbor list: if neigh_size>0 + // if the size is full -> sort the vector and decide the dependencies for next step + // if the size is not full -> check if next step will need the full dependency otherwise keep this dependencies // here just resize the neighpair. The real resizing of reinit will be done by the prepare stage that will modify the list of arguments - if (neigh_size>0){ - if(neighpair.size()==allArguments.size()){ // I just did the complete round: need to sort, shorten and give it a go - // sort the values - sort(neighpair.begin(),neighpair.end(),pairordering()); - // resize the effective list - neighpair.resize(neigh_size); - log.printf(" NEIGH LIST NOW INCLUDE INDEXES: "); - for(int i=0;i0) { + if(neighpair.size()==allArguments.size()) { // I just did the complete round: need to sort, shorten and give it a go + // sort the values + sort(neighpair.begin(),neighpair.end(),pairordering()); + // resize the effective list + neighpair.resize(neigh_size); + log.printf(" NEIGH LIST NOW INCLUDE INDEXES: "); + for(int i=0; i argstocall; - //log.printf("PREPARING \n"); - argstocall.clear(); - if(!neighpair.empty()){ - for(const auto & it : neighpair){ - argstocall.push_back( it.first ); - // log.printf("CALLING %p %f ",(*it).first ,indexmap[(*it).first] ); + vector argstocall; +//log.printf("PREPARING \n"); + argstocall.clear(); + if(!neighpair.empty()) { + for(const auto & it : neighpair) { + argstocall.push_back( it.first ); + // log.printf("CALLING %p %f ",(*it).first ,indexmap[(*it).first] ); } - }else{ - for(unsigned i=0;iclearDerivatives(); - getPntrToComponent(i)->resizeDerivatives(getNumberOfArguments()); - } - //log.printf("PREPARING DONE! \n"); + } +// now the list of argument changes + requestArguments(argstocall); +//now resize the derivatives as well +//for each value in this action + for(int i=0; i< getNumberOfComponents(); i++) { + //resize the derivative to the number the + getPntrToComponent(i)->clearDerivatives(); + getPntrToComponent(i)->resizeDerivatives(getNumberOfArguments()); + } +//log.printf("PREPARING DONE! \n"); } } diff --git a/src/function/FuncSumHills.cpp b/src/function/FuncSumHills.cpp index 5231b0fdc9..65049b9b63 100644 --- a/src/function/FuncSumHills.cpp +++ b/src/function/FuncSumHills.cpp @@ -31,18 +31,18 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { -//+PLUMEDOC FUNCTION FUNCSUMHILLS +//+PLUMEDOC FUNCTION FUNCSUMHILLS /* This function is intended to be called by the command line tool sum_hills -and it is meant to integrate a HILLS file or an HILLS file interpreted as -a histogram i a variety of ways. Therefore it is not expected that you use this +and it is meant to integrate a HILLS file or an HILLS file interpreted as +a histogram i a variety of ways. Therefore it is not expected that you use this during your dynamics (it will crash!) -In the future one could implement periodic integration during the metadynamics +In the future one could implement periodic integration during the metadynamics or straightforward MD as a tool to check convergence \par Examples @@ -52,130 +52,131 @@ There are currently no examples for this keyword. */ //+ENDPLUMEDOC -class FilesHandler{ - vector filenames; - vector ifiles; - Action *action; - Log *log; - bool parallelread; - unsigned beingread; - bool isopen; - public: - FilesHandler(const vector &filenames, const bool ¶llelread , Action &myaction , Log &mylog); - bool readBunch(BiasRepresentation *br, int stride); - bool scanOneHill(BiasRepresentation *br, IFile *ifile ); - void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin); - void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma); - ~FilesHandler(); +class FilesHandler { + vector filenames; + vector ifiles; + Action *action; + Log *log; + bool parallelread; + unsigned beingread; + bool isopen; +public: + FilesHandler(const vector &filenames, const bool ¶llelread, Action &myaction, Log &mylog); + bool readBunch(BiasRepresentation *br, int stride); + bool scanOneHill(BiasRepresentation *br, IFile *ifile ); + void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin); + void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma); + ~FilesHandler(); }; -FilesHandler::FilesHandler(const vector &filenames, const bool ¶llelread , Action &action , Log &mylog ):filenames(filenames),log(&mylog),parallelread(parallelread),beingread(0),isopen(false){ - this->action=&action; - for(unsigned i=0;ilink(action); - ifiles.push_back(ifile); - plumed_massert((ifile->FileExist(filenames[i])), "the file "+filenames[i]+" does not exist " ); - } - +FilesHandler::FilesHandler(const vector &filenames, const bool ¶llelread, Action &action, Log &mylog ):filenames(filenames),log(&mylog),parallelread(parallelread),beingread(0),isopen(false) { + this->action=&action; + for(unsigned i=0; ilink(action); + ifiles.push_back(ifile); + plumed_massert((ifile->FileExist(filenames[i])), "the file "+filenames[i]+" does not exist " ); + } + } -FilesHandler::~FilesHandler(){ - for(unsigned i=0;iopen(filenames[beingread]);isopen=true; - } - int n; - while(true){ - bool fileisover=true; - while(scanOneHill(br,ff)){ - // here do the dump if needed - n=br->getNumberOfKernels(); - if(stride>0 && n%stride==0 && n!=0 ){ - (*log)<<" done with this chunk: now with "<close(); - isopen=false; - (*log)<<" now total "<getNumberOfKernels()<<" kernels \n"; - beingread++; - if(beingreadopen(filenames[beingread]); - (*log)<<" opening file "<open(filenames[beingread]); isopen=true; + } + int n; + while(true) { + bool fileisover=true; + while(scanOneHill(br,ff)) { + // here do the dump if needed + n=br->getNumberOfKernels(); + if(stride>0 && n%stride==0 && n!=0 ) { + (*log)<<" done with this chunk: now with "<close(); + isopen=false; + (*log)<<" now total "<getNumberOfKernels()<<" kernels \n"; + beingread++; + if(beingreadopen(filenames[beingread]); + (*log)<<" opening file "< vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin){ - // create the representation (no grid) - BiasRepresentation br(vals,cc); - // read all the kernels - readBunch(&br); - // loop over the kernels and get the support - br.getMinMaxBin(vmin,vmax,vbin); +void FilesHandler::getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin) { + // create the representation (no grid) + BiasRepresentation br(vals,cc); + // read all the kernels + readBunch(&br); + // loop over the kernels and get the support + br.getMinMaxBin(vmin,vmax,vbin); } -void FilesHandler::getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma){ - BiasRepresentation br(vals,cc,histosigma); - // read all the kernels - readBunch(&br); - // loop over the kernels and get the support - br.getMinMaxBin(vmin,vmax,vbin); - //for(unsigned i=0;i vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma) { + BiasRepresentation br(vals,cc,histosigma); + // read all the kernels + readBunch(&br); + // loop over the kernels and get the support + br.getMinMaxBin(vmin,vmax,vbin); + //for(unsigned i=0;iscanField("time",dummy)){ - //(*log)<<" scanning one hill: "<FieldExist("biasf")) ifile->scanField("biasf",dummy); - if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy); - // keep this intermediate function in case you need to parse more data in the future - br->pushKernel(ifile); - //(*log)<<" read hill\n"; - if(br->hasSigmaInInput())ifile->allowIgnoredFields(); - ifile->scanField(); - return true; - }else{ - return false; - } +bool FilesHandler::scanOneHill(BiasRepresentation *br, IFile *ifile ) { + double dummy; + if(ifile->scanField("time",dummy)) { + //(*log)<<" scanning one hill: "<FieldExist("biasf")) ifile->scanField("biasf",dummy); + if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy); + // keep this intermediate function in case you need to parse more data in the future + br->pushKernel(ifile); + //(*log)<<" read hill\n"; + if(br->hasSigmaInInput())ifile->allowIgnoredFields(); + ifile->scanField(); + return true; + } else { + return false; + } } -double mylog( double v1 ){ - return log(v1); +double mylog( double v1 ) { + return log(v1); } -double mylogder( double v1 ){ - return 1./v1; +double mylogder( double v1 ) { + return 1./v1; } @@ -183,8 +184,8 @@ double mylogder( double v1 ){ class FuncSumHills : public Function { - vector hillsFiles,histoFiles; - vector proj; + vector hillsFiles,histoFiles; + vector proj; int initstride; bool iscltool,integratehills,integratehisto,parallelread; bool negativebias; @@ -201,23 +202,23 @@ class FuncSumHills : explicit FuncSumHills(const ActionOptions&); ~FuncSumHills(); void calculate(); // this probably is not needed - bool checkFilesAreExisting(const vector & hills ); + bool checkFilesAreExisting(const vector & hills ); static void registerKeywords(Keywords& keys); }; PLUMED_REGISTER_ACTION(FuncSumHills,"FUNCSUMHILLS") -void FuncSumHills::registerKeywords(Keywords& keys){ +void FuncSumHills::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); - keys.use("ARG"); - keys.add("optional","HILLSFILES"," source file for hills creation(may be the same as HILLS)"); // this can be a vector! + keys.use("ARG"); + keys.add("optional","HILLSFILES"," source file for hills creation(may be the same as HILLS)"); // this can be a vector! keys.add("optional","HISTOFILES"," source file for histogram creation(may be the same as HILLS)"); // also this can be a vector! - keys.add("optional","HISTOSIGMA"," sigmas for binning when the histogram correction is needed "); + keys.add("optional","HISTOSIGMA"," sigmas for binning when the histogram correction is needed "); keys.add("optional","PROJ"," only with sumhills: the projection on the cvs"); keys.add("optional","KT"," only with sumhills: the kt factor when projection on cvs"); keys.add("optional","GRID_MIN","the lower bounds for the grid"); keys.add("optional","GRID_MAX","the upper bounds for the grid"); - keys.add("optional","GRID_BIN","the number of bins for the grid"); + keys.add("optional","GRID_BIN","the number of bins for the grid"); keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); keys.add("optional","INTERVAL","set monodimensional INTERVAL"); keys.add("optional","OUTHILLS"," output file for hills "); @@ -233,29 +234,29 @@ void FuncSumHills::registerKeywords(Keywords& keys){ } FuncSumHills::FuncSumHills(const ActionOptions&ao): -Action(ao), -Function(ao), -initstride(-1), -iscltool(false), -integratehills(false), -integratehisto(false), -parallelread(false), -negativebias(false), -nohistory(false), -minTOzero(false), -doInt(false), -lowI_(-1.), -uppI_(-1.), -beta(-1.), -fmt("%14.9f"), -biasrep(NULL), -historep(NULL) + Action(ao), + Function(ao), + initstride(-1), + iscltool(false), + integratehills(false), + integratehisto(false), + parallelread(false), + negativebias(false), + nohistory(false), + minTOzero(false), + doInt(false), + lowI_(-1.), + uppI_(-1.), + beta(-1.), + fmt("%14.9f"), + biasrep(NULL), + historep(NULL) { // format parse("FMT",fmt); - log<<" Output format is "< gmin; parseVector("GRID_MIN",gmin); @@ -273,20 +274,20 @@ historep(NULL) parseVector("GRID_SPACING",gspacing); plumed_massert(gspacing.size()==getNumberOfArguments() || gspacing.size()==0,"need GRID_SPACING argument for this") ; if(gspacing.size()!=getNumberOfArguments() && gspacing.size()!=0) error("not enough values for GRID_SPACING"); - if(gspacing.size()!=0 && gbin.size()==0){ + if(gspacing.size()!=0 && gbin.size()==0) { log<<" The number of bins will be estimated from GRID_SPACING\n"; - } else if(gspacing.size()!=0 && gbin.size()!=0){ + } else if(gspacing.size()!=0 && gbin.size()!=0) { log<<" You specified both GRID_BIN and GRID_SPACING\n"; log<<" The more conservative (highest) number of bins will be used for each variable\n"; } - if(gspacing.size()!=0) for(unsigned i=0;i tmpI(2); @@ -309,31 +310,31 @@ historep(NULL) if(gmax.size()==0) gmax.push_back(strsmax.str()); if(gbin.size()==0) gbin.push_back(200); } - - // hills file: + + // hills file: parseVector("HILLSFILES",hillsFiles); - if(hillsFiles.size()==0){ - integratehills=false; // default behaviour - }else{ - integratehills=true; - for(unsigned i=0;i histoSigma; - if(integratehisto){ - parseVector("HISTOSIGMA",histoSigma); - for(unsigned i=0;igetName()); + for(unsigned i=0; igetName()); } - // add some automatic hills width: not in case stride is defined + // add some automatic hills width: not in case stride is defined // since when you start from zero the automatic size will be zero! - if(gmin.size()==0 || gmax.size()==0){ - log<<" \n"; - log<<" No boundaries defined: need to do a prescreening of hills \n"; - std::vector tmphillsvalues, tmphistovalues; - if(integratehills) { - for(unsigned i=0;igetName(); - for(unsigned j=0;j tmphillsvalues, tmphistovalues; + if(integratehills) { + for(unsigned i=0; igetName(); + for(unsigned j=0; j vmin,vmax; - vector vbin; - hillsHandler.getMinMaxBin(tmphillsvalues,comm,vmin,vmax,vbin); - log<<" found boundaries from hillsfile: \n"; - gmin.resize(vmin.size()); - gmax.resize(vmax.size()); - if(gbin.size()==0){ - gbin=vbin; - }else{ - log<<" found nbins in input, this overrides the automatic choice \n"; - } - for(unsigned i=0;igetName()<<" min: "< vmin,vmax; - vector vbin; - histoHandler.getMinMaxBin(tmphistovalues,comm,vmin,vmax,vbin,histoSigma); - log<<" found boundaries from histofile: \n"; - gmin.resize(vmin.size()); - gmax.resize(vmax.size()); - if(gbin.size()==0){ - gbin=vbin; - }else{ - log<<" found nbins in input, this overrides the automatic choice \n"; - } - for(unsigned i=0;i vmin,vmax; + vector vbin; + hillsHandler.getMinMaxBin(tmphillsvalues,comm,vmin,vmax,vbin); + log<<" found boundaries from hillsfile: \n"; + gmin.resize(vmin.size()); + gmax.resize(vmax.size()); + if(gbin.size()==0) { + gbin=vbin; + } else { + log<<" found nbins in input, this overrides the automatic choice \n"; + } + for(unsigned i=0; igetName()<<" min: "< vmin,vmax; + vector vbin; + histoHandler.getMinMaxBin(tmphistovalues,comm,vmin,vmax,vbin,histoSigma); + log<<" found boundaries from histofile: \n"; + gmin.resize(vmin.size()); + gmax.resize(vmax.size()); + if(gbin.size()==0) { + gbin=vbin; + } else { + log<<" found nbins in input, this overrides the automatic choice \n"; + } + for(unsigned i=0; i0.,"if you make a projection or a histogram correction then you need KT flag!"); - beta=1./beta; - log<<" beta is "<0.,"if you make a projection or a histogram correction then you need KT flag!"); + beta=1./beta; + log<<" beta is "< tmphillsvalues, tmphistovalues; + std::vector tmphillsvalues, tmphistovalues; if(integratehills) { - for(unsigned i=0;igetName(); - for(unsigned j=0;jgetName(); + for(unsigned j=0; jsetRescaledToBias(true); - log<<" required the -bias instead of the free energy \n"; - if(initstride<0){outhills="negativebias.dat";} - else{outhills="negativebias_";} - } + // check if the files exists + if(integratehills) { + checkFilesAreExisting(hillsFiles); + biasrep=new BiasRepresentation(tmphillsvalues,comm, gmin, gmax, gbin, doInt, lowI_, uppI_); + if(negativebias) { + biasrep->setRescaledToBias(true); + log<<" required the -bias instead of the free energy \n"; + if(initstride<0) {outhills="negativebias.dat";} + else {outhills="negativebias_";} + } } parse("OUTHILLS",outhills); parse("OUTHISTO",outhisto); - if(integratehills)log<<" output file for fes/bias is : "<clear();log<<" clearing history before reading a new block\n";}; - log<<" reading hills: \n"; - ibias=hillsHandler->readBunch(biasrep,initstride) ; log<<"\n"; - } - - if( integratehisto && ihisto ){ - if(nohistory){historep->clear();log<<" clearing history before reading a new block\n";}; - log<<" reading histogram: \n"; - ihisto=histoHandler->readBunch(historep,initstride) ; log<<"\n"; - } - - // dump: need to project? - if(proj.size()!=0){ - - if(integratehills){ - - log<<" Bias: Projecting on subgrid... \n"; - BiasWeight Bw(beta); - Grid biasGrid=*(biasrep->getGridPtr()); - Grid smallGrid=biasGrid.project(proj,&Bw); - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhills+ostr.str()+".dat" ;}else{myout=outhills;} - log<<" Bias: Writing subgrid on file "<getGridPtr()); - - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhisto+ostr.str()+".dat" ;}else{myout=outhisto;} - log<<" Histo: Writing subgrid on file "<getGridPtr()); - biasGrid.scaleAllValuesAndDerivatives(-1.); - - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhills+ostr.str()+".dat" ;}else{myout=outhills;} - log<<" Writing full grid on file "<getGridPtr()); - // do this if you want a free energy from a grid, otherwise do not - histoGrid.applyFunctionAllValuesAndDerivatives(&mylog,&mylogder); - histoGrid.scaleAllValuesAndDerivatives(-1./beta); - - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhisto+ostr.str()+".dat" ;}else{myout=outhisto;} - log<<" Writing full grid on file "<clear(); log<<" clearing history before reading a new block\n";}; + log<<" reading hills: \n"; + ibias=hillsHandler->readBunch(biasrep,initstride) ; log<<"\n"; + } + + if( integratehisto && ihisto ) { + if(nohistory) {historep->clear(); log<<" clearing history before reading a new block\n";}; + log<<" reading histogram: \n"; + ihisto=histoHandler->readBunch(historep,initstride) ; log<<"\n"; + } + + // dump: need to project? + if(proj.size()!=0) { + + if(integratehills) { + + log<<" Bias: Projecting on subgrid... \n"; + BiasWeight Bw(beta); + Grid biasGrid=*(biasrep->getGridPtr()); + Grid smallGrid=biasGrid.project(proj,&Bw); + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhills+ostr.str()+".dat" ;} else {myout=outhills;} + log<<" Bias: Writing subgrid on file "<getGridPtr()); + + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhisto+ostr.str()+".dat" ;} else {myout=outhisto;} + log<<" Histo: Writing subgrid on file "<getGridPtr()); + biasGrid.scaleAllValuesAndDerivatives(-1.); + + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhills+ostr.str()+".dat" ;} else {myout=outhills;} + log<<" Writing full grid on file "<getGridPtr()); + // do this if you want a free energy from a grid, otherwise do not + histoGrid.applyFunctionAllValuesAndDerivatives(&mylog,&mylogder); + histoGrid.scaleAllValuesAndDerivatives(-1./beta); + + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhisto+ostr.str()+".dat" ;} else {myout=outhisto;} + log<<" Writing full grid on file "< & hills ){ - plumed_massert(hills.size()!=0,"the number of files provided should be at least one" ); - IFile *ifile = new IFile(); - ifile->link(*this); - for(unsigned i=0; i< hills.size();i++){ - plumed_massert(ifile->FileExist(hills[i]),"missing file "+hills[i]); - } - delete ifile; - return true; +bool FuncSumHills::checkFilesAreExisting(const vector & hills ) { + plumed_massert(hills.size()!=0,"the number of files provided should be at least one" ); + IFile *ifile = new IFile(); + ifile->link(*this); + for(unsigned i=0; i< hills.size(); i++) { + plumed_massert(ifile->FileExist(hills[i]),"missing file "+hills[i]); + } + delete ifile; + return true; } diff --git a/src/function/Function.cpp b/src/function/Function.cpp index 39b5ea82be..0852d31810 100644 --- a/src/function/Function.cpp +++ b/src/function/Function.cpp @@ -23,10 +23,10 @@ #include "tools/OpenMP.h" using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { -void Function::registerKeywords(Keywords& keys){ +void Function::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionWithValue::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -34,29 +34,29 @@ void Function::registerKeywords(Keywords& keys){ } Function::Function(const ActionOptions&ao): -Action(ao), -ActionWithValue(ao), -ActionWithArguments(ao) + Action(ao), + ActionWithValue(ao), + ActionWithArguments(ao) { } -void Function::addValueWithDerivatives(){ +void Function::addValueWithDerivatives() { plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values"); - ActionWithValue::addValueWithDerivatives(); + ActionWithValue::addValueWithDerivatives(); getPntrToValue()->resizeDerivatives(getNumberOfArguments()); - if( keywords.exists("PERIODIC") ){ - std::vector period; - parseVector("PERIODIC",period); - if(period.size()==1 && period[0]=="NO"){ - setNotPeriodic(); - } else if(period.size()==2){ - setPeriodic(period[0],period[1]); - } else error("missing PERIODIC keyword"); + if( keywords.exists("PERIODIC") ) { + std::vector period; + parseVector("PERIODIC",period); + if(period.size()==1 && period[0]=="NO") { + setNotPeriodic(); + } else if(period.size()==2) { + setPeriodic(period[0],period[1]); + } else error("missing PERIODIC keyword"); } -} - -void Function::addComponentWithDerivatives( const std::string& name ){ +} + +void Function::addComponentWithDerivatives( const std::string& name ) { plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values"); ActionWithValue::addComponentWithDerivatives(name); getPntrToComponent(name)->resizeDerivatives(getNumberOfArguments()); @@ -83,19 +83,19 @@ void Function::apply() vector omp_f(noa,0.0); vector forces(noa); #pragma omp for reduction( + : at_least_one_forced) - for(unsigned i=rank;iapplyForce(forces)) { at_least_one_forced+=1; - for(unsigned j=0;j0&&ncp>4*cgs) { comm.Sum(&f[0],noa); comm.Sum(at_least_one_forced); } - if(at_least_one_forced>0) for(unsigned i=0;iaddForce(f[i]); + if(at_least_one_forced>0) for(unsigned i=0; iaddForce(f[i]); } } diff --git a/src/function/Function.h b/src/function/Function.h index e0dfae9080..02215e1cce 100644 --- a/src/function/Function.h +++ b/src/function/Function.h @@ -26,12 +26,12 @@ #include "core/ActionWithArguments.h" #include "tools/Communicator.h" -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { /** \ingroup INHERIT -This is the abstract base class to use for implementing new CV function, within it there is +This is the abstract base class to use for implementing new CV function, within it there is \ref AddingAFunction "information" as to how to go about implementing a new function. */ @@ -43,27 +43,27 @@ class Function: void setDerivative(int,double); void setDerivative(Value*,int,double); void addValueWithDerivatives(); - void addComponentWithDerivatives( const std::string& name ); + void addComponentWithDerivatives( const std::string& name ); public: explicit Function(const ActionOptions&); - virtual ~Function(){} + virtual ~Function() {} void apply(); static void registerKeywords(Keywords&); unsigned getNumberOfDerivatives(); }; inline -void Function::setDerivative(Value*v,int i,double d){ +void Function::setDerivative(Value*v,int i,double d) { v->addDerivative(i,d); } inline -void Function::setDerivative(int i,double d){ +void Function::setDerivative(int i,double d) { setDerivative(getPntrToValue(),i,d); } inline -unsigned Function::getNumberOfDerivatives(){ +unsigned Function::getNumberOfDerivatives() { return getNumberOfArguments(); } diff --git a/src/function/LocalEnsemble.cpp b/src/function/LocalEnsemble.cpp index aee9a076fa..6e3bd96f68 100644 --- a/src/function/LocalEnsemble.cpp +++ b/src/function/LocalEnsemble.cpp @@ -25,15 +25,15 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION LOCALENSEMBLE /* Calculates the average over multiple arguments. If more than one collective variable is given for each argument then they -are averaged separately. The average is stored in a component labelled label.cvlabel. +are averaged separately. The average is stored in a component labelled label.cvlabel. \par Examples The following input tells plumed to calculate the chemical shifts for four @@ -88,7 +88,7 @@ class LocalEnsemble : PLUMED_REGISTER_ACTION(LocalEnsemble,"LOCALENSEMBLE") -void LocalEnsemble::registerKeywords(Keywords& keys){ +void LocalEnsemble::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","NUM","the number of local replicas"); @@ -96,24 +96,24 @@ void LocalEnsemble::registerKeywords(Keywords& keys){ } LocalEnsemble::LocalEnsemble(const ActionOptions&ao): -Action(ao), -Function(ao), -ens_dim(0) + Action(ao), + Function(ao), + ens_dim(0) { parse("NUM",ens_dim); if(ens_dim==0) error("NUM should be greater or equal to 1"); vector arg; int oldsize=-1; - for(unsigned i=1;i<=ens_dim;++i ){ + for(unsigned i=1; i<=ens_dim; ++i ) { vector larg; if(!parseArgumentList("ARG",i,larg)) break; - for(unsigned j=0;jgetName().c_str()); + for(unsigned j=0; jgetName().c_str()); log.printf("\n"); } } @@ -121,9 +121,9 @@ ens_dim(0) narg = arg.size()/ens_dim; // these are the averages - for(unsigned i=0;igetName(); - addComponentWithDerivatives(s); + addComponentWithDerivatives(s); getPntrToComponent(i)->setNotPeriodic(); } @@ -132,18 +132,18 @@ ens_dim(0) void LocalEnsemble::calculate() { - const double fact = 1.0/static_cast(ens_dim); + const double fact = 1.0/static_cast(ens_dim); #pragma omp parallel for num_threads(OpenMP::getNumThreads()) - for(unsigned i=0;iset(mean); - } + } } } diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp index 55a7f439ee..59e6e9bf05 100644 --- a/src/function/Matheval.cpp +++ b/src/function/Matheval.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION MATHEVAL @@ -186,7 +186,7 @@ class Matheval : #ifdef __PLUMED_HAS_MATHEVAL PLUMED_REGISTER_ACTION(Matheval,"MATHEVAL") -void Matheval::registerKeywords(Keywords& keys){ +void Matheval::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.use("PERIODIC"); keys.add("compulsory","FUNC","the function you wish to evaluate"); @@ -194,14 +194,14 @@ void Matheval::registerKeywords(Keywords& keys){ } Matheval::Matheval(const ActionOptions&ao): -Action(ao), -Function(ao), -evaluator_deriv(getNumberOfArguments()), -values(getNumberOfArguments()), -names(getNumberOfArguments()) + Action(ao), + Function(ao), + evaluator_deriv(getNumberOfArguments()), + values(getNumberOfArguments()), + names(getNumberOfArguments()) { parseVector("VAR",var); - if(var.size()==0){ + if(var.size()==0) { var.resize(getNumberOfArguments()); if(getNumberOfArguments()>3) error("Using more than 3 arguments you should explicitly write their names with VAR"); @@ -212,7 +212,7 @@ names(getNumberOfArguments()) if(var.size()!=getNumberOfArguments()) error("Size of VAR array should be the same as number of arguments"); parse("FUNC",func); - addValueWithDerivatives(); + addValueWithDerivatives(); checkRead(); evaluator=evaluator_create(const_cast(func.c_str())); @@ -222,46 +222,46 @@ names(getNumberOfArguments()) char **check_names; int check_count; evaluator_get_variables(evaluator,&check_names,&check_count); - if(check_count!=int(getNumberOfArguments())){ + if(check_count!=int(getNumberOfArguments())) { string sc; Tools::convert(check_count,sc); error("Your function string contains "+sc+" arguments. This should be equal to the number of ARGs"); } - for(unsigned i=0;i(var[i].c_str())); log.printf(" with function : %s\n",func.c_str()); log.printf(" with variables :"); - for(unsigned i=0;i(var[i].c_str()); +void Matheval::calculate() { + for(unsigned i=0; i(var[i].c_str()); setValue(evaluator_evaluate(evaluator,names.size(),&names[0],&values[0])); - for(unsigned i=0;ix_{N-1} +y_N ; if x>x_{N-1} \f] \f[ -y_1 ; if x pp; if(!parseNumberedVector("POINT",i,pp) ) break; - if(pp.size()!=2) error("points should be in x,y format"); - points.push_back(std::pair(pp[0],pp[1])); - if(i>0 && points[i].first<=points[i-1].first) error("points abscissas should be monotonously increasing"); + if(pp.size()!=2) error("points should be in x,y format"); + points.push_back(std::pair(pp[0],pp[1])); + if(i>0 && points[i].first<=points[i-1].first) error("points abscissas should be monotonously increasing"); } - for(unsigned i=0;iisPeriodic()) - error("Cannot use PIECEWISE on periodic arguments"); + error("Cannot use PIECEWISE on periodic arguments"); - if(getNumberOfArguments()==1){ - addValueWithDerivatives(); + if(getNumberOfArguments()==1) { + addValueWithDerivatives(); setNotPeriodic(); - }else{ - for(unsigned i=0;igetName()+"_pfunc" ); getPntrToComponent(i)->setNotPeriodic(); } @@ -123,22 +123,22 @@ Function(ao) checkRead(); log.printf(" on points:"); - for(unsigned i=0;ilabel.1, the second lowest will be labelled label.2 and so on. +This function sorts its arguments according to their magnitudes. The lowest argument will be +labelled label.1, the second lowest will be labelled label.2 and so on. \par Examples The following input tells plumed to print the distance of the closest and of @@ -69,38 +69,38 @@ class Sort : PLUMED_REGISTER_ACTION(Sort,"SORT") -void Sort::registerKeywords(Keywords& keys){ +void Sort::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); ActionWithValue::useCustomisableComponents(keys); } Sort::Sort(const ActionOptions&ao): -Action(ao), -Function(ao) + Action(ao), + Function(ao) { - for(unsigned i=0;iisPeriodic()) error("Cannot sort periodic values (check argument "+s+")"); - addComponentWithDerivatives(s); + addComponentWithDerivatives(s); getPntrToComponent(i)->setNotPeriodic(); } checkRead(); } -void Sort::calculate(){ +void Sort::calculate() { vector > vals(getNumberOfArguments()); - for(unsigned i=0;iset(vals[i].first); setDerivative(v,vals[i].second,1.0); diff --git a/src/function/Stats.cpp b/src/function/Stats.cpp index c9f5ef8040..429442e6d8 100644 --- a/src/function/Stats.cpp +++ b/src/function/Stats.cpp @@ -24,8 +24,8 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION STATS /* @@ -38,7 +38,7 @@ from other actions using PARARG (for example using experimental values from coll \ref CS2BACKBONE, \ref RDC, \ref NOE, \ref PRE). \par Examples -The following input tells plumed to print the distance between three couple of atoms +The following input tells plumed to print the distance between three couple of atoms and compare them with three reference distances. \verbatim @@ -69,28 +69,28 @@ class Stats : PLUMED_REGISTER_ACTION(Stats,"STATS") -void Stats::registerKeywords(Keywords& keys){ +void Stats::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); useCustomisableComponents(keys); keys.use("ARG"); - keys.add("optional","PARARG","the input for this action is the scalar output from one or more other actions without derivatives."); + keys.add("optional","PARARG","the input for this action is the scalar output from one or more other actions without derivatives."); keys.add("optional","PARAMETERS","the parameters of the arguments in your function"); keys.addFlag("SQDEVSUM",false,"calculates only SQDEVSUM"); keys.addFlag("SQDEV",false,"calculates and store the SQDEV as components"); keys.addFlag("UPPERDISTS",false,"calculates and store the SQDEV as components"); - keys.addOutputComponent("sqdevsum","default","the sum of the squared deviations between arguments and parameters"); - keys.addOutputComponent("corr","default","the correlation between arguments and parameters"); - keys.addOutputComponent("slope","default","the slope of a linear fit between arguments and parameters"); - keys.addOutputComponent("intercept","default","the intercept of a linear fit between arguments and parameters"); - keys.addOutputComponent("sqd","SQDEV","the squared deviations between arguments and parameters"); + keys.addOutputComponent("sqdevsum","default","the sum of the squared deviations between arguments and parameters"); + keys.addOutputComponent("corr","default","the correlation between arguments and parameters"); + keys.addOutputComponent("slope","default","the slope of a linear fit between arguments and parameters"); + keys.addOutputComponent("intercept","default","the intercept of a linear fit between arguments and parameters"); + keys.addOutputComponent("sqd","SQDEV","the squared deviations between arguments and parameters"); } Stats::Stats(const ActionOptions&ao): -Action(ao), -Function(ao), -sqdonly(false), -components(false), -upperd(false) + Action(ao), + Function(ao), + sqdonly(false), + components(false), + upperd(false) { parseVector("PARAMETERS",parameters); if(parameters.size()!=static_cast(getNumberOfArguments())&&!parameters.empty()) @@ -102,13 +102,13 @@ upperd(false) if(!arg2.empty()) { if(parameters.size()>0) error("It is not possible to use PARARG and PARAMETERS together"); if(arg2.size()!=getNumberOfArguments()) error("Size of PARARG array should be the same as number for arguments in ARG"); - for(unsigned i=0;iget()); + for(unsigned i=0; iget()); if(arg2[i]->hasDerivatives()==true) error("PARARG can only accept arguments without derivatives"); } } - if(parameters.size()!=getNumberOfArguments()) + if(parameters.size()!=getNumberOfArguments()) error("PARARG or PARAMETERS arrays should include the same number of elements as the arguments in ARG"); if(getNumberOfArguments()<2) error("STATS need at least two arguments to be used"); @@ -123,12 +123,12 @@ upperd(false) if(!arg2.empty()) log.printf(" using %zu parameters from inactive actions:", arg2.size()); else log.printf(" using %zu parameters:", arg2.size()); - for(unsigned i=0;iset(dev*dev); - } else { + } else { nsqd += dev*dev; } setDerivative(val,i,2.*dev); @@ -175,8 +175,8 @@ void Stats::calculate() } else { double scx=0., scx2=0., scy=0., scy2=0., scxy=0.; - - for(unsigned i=0;iset(inter); /* derivatives */ - for(unsigned i=0;icalculate( getArguments(), mypack, false ); setValue(r); - for(unsigned i=0;i0){ + if(file.length()>0) { ofile.open(file); log.printf(" on file %s\n",file.c_str()); } else { @@ -104,17 +104,17 @@ novirial(false){ checkRead(); } -void Debug::apply(){ - if(logActivity){ +void Debug::apply() { + if(logActivity) { const ActionSet&actionSet(plumed.getActionSet()); int a=0; - for(const auto & p : actionSet){ + for(const auto & p : actionSet) { if(dynamic_cast(p))continue; if(p->isActive()) a++; }; - if(a>0){ + if(a>0) { ofile.printf("activity at step %i: ",getStep()); - for(const auto & p : actionSet){ + for(const auto & p : actionSet) { if(dynamic_cast(p))continue; if(p->isActive()) ofile.printf("+"); else ofile.printf("-"); @@ -122,13 +122,13 @@ void Debug::apply(){ ofile.printf("\n"); }; }; - if(logRequestedAtoms){ + if(logRequestedAtoms) { ofile.printf("requested atoms at step %i: ",getStep()); int* l; int n; plumed.cmd("createFullList",&n); plumed.cmd("getFullList",&l); - for(int i=0;i0){ + if(ntype.length()>0) { if(ntype!="xyz" && ntype!="gro" #ifdef __PLUMED_HAS_XDRFILE - && ntype!="xtc" && ntype!="trr" + && ntype!="xtc" && ntype!="trr" #endif - ) error("TYPE cannot be understood"); + ) error("TYPE cannot be understood"); log<<" file type enforced to be "<0){ + if(precision.length()>0) { Tools::convert(precision,iprecision); log<<" with precision "< moldat=plumed.getActionSet().select(); - if( moldat.size()==1 ){ + if( moldat.size()==1 ) { log<<" MOLINFO DATA found, using proper atom names\n"; names.resize(atoms.size()); - for(unsigned i=0;igetAtomName(atoms[i]); + for(unsigned i=0; igetAtomName(atoms[i]); residueNumbers.resize(atoms.size()); - for(unsigned i=0;igetResidueNumber(atoms[i]); + for(unsigned i=0; igetResidueNumber(atoms[i]); residueNames.resize(atoms.size()); - for(unsigned i=0;igetResidueName(atoms[i]); + for(unsigned i=0; igetResidueName(atoms[i]); } } -void DumpAtoms::update(){ - if(type=="xyz"){ +void DumpAtoms::update() { + if(type=="xyz") { of.printf("%d\n",getNumberOfAtoms()); const Tensor & t(getPbc().getBox()); - if(getPbc().isOrthorombic()){ + if(getPbc().isOrthorombic()) { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ + } else { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(), - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); } - for(unsigned i=0;i0) if(names[i].length()>0) name=names[i].c_str(); of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),name,lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2)); } - } else if(type=="gro"){ + } else if(type=="gro") { const Tensor & t(getPbc().getBox()); of.printf("Made with PLUMED t=%f\n",getTime()/plumed.getAtoms().getUnits().getTime()); of.printf("%d\n",getNumberOfAtoms()); - for(unsigned i=0;i0) resname=residueNames[i]; of.printf(("%5u%-5s%5s%5d"+fmt_gro_pos+fmt_gro_pos+fmt_gro_pos+"\n").c_str(), - residueNumber%100000,resname.c_str(),name,getAbsoluteIndex(i).serial()%100000, - lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2)); + residueNumber%100000,resname.c_str(),name,getAbsoluteIndex(i).serial()%100000, + lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2)); } of.printf((fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+"\n").c_str(), - lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2), - lenunit*t(0,1),lenunit*t(0,2),lenunit*t(1,0), - lenunit*t(1,2),lenunit*t(2,0),lenunit*t(2,1)); + lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2), + lenunit*t(0,1),lenunit*t(0,2),lenunit*t(1,0), + lenunit*t(1,2),lenunit*t(2,0),lenunit*t(2,1)); #if defined(__PLUMED_HAS_XDRFILE) - } else if(type=="xtc" || type=="trr"){ + } else if(type=="xtc" || type=="trr") { matrix box; const Tensor & t(getPbc().getBox()); int natoms=getNumberOfAtoms(); int step=getStep(); float time=getTime()/plumed.getAtoms().getUnits().getTime(); float precision=Tools::fastpow(10.0,iprecision); - for(int i=0;i<3;i++) for(int j=0;j<3;j++) box[i][j]=lenunit*t(i,j); + for(int i=0; i<3; i++) for(int j=0; j<3; j++) box[i][j]=lenunit*t(i,j); rvec* pos=new rvec [natoms]; // Notice that code below cannot throw any exception. // Thus, this pointer is excepton safe - for(int i=0;igetPntrToAction())->turnOnDerivatives(); unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); if( npar==0 ) error("one or more arguments has no derivatives"); - for(unsigned i=1;igetPntrToAction())->turnOnDerivatives(); - if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) error("the number of derivatives must be the same in all values being dumped"); + for(unsigned i=1; igetPntrToAction())->turnOnDerivatives(); + if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) error("the number of derivatives must be the same in all values being dumped"); } checkRead(); } -void DumpDerivatives::update(){ +void DumpDerivatives::update() { unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); - for(unsigned ipar=0;ipargetName(),getPntrToArgument(i)->getDerivative(ipar) ); } @@ -125,7 +125,7 @@ void DumpDerivatives::update(){ } } -DumpDerivatives::~DumpDerivatives(){ +DumpDerivatives::~DumpDerivatives() { } } diff --git a/src/generic/DumpForces.cpp b/src/generic/DumpForces.cpp index ab96bb0708..f5e204d65b 100644 --- a/src/generic/DumpForces.cpp +++ b/src/generic/DumpForces.cpp @@ -26,12 +26,12 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC PRINTANALYSIS DUMPFORCES /* -Dump the force acting on one of a values in a file. +Dump the force acting on one of a values in a file. For a CV this command will dump the force on the CV itself. Be aware that in order to have the forces on the atoms @@ -42,7 +42,7 @@ by specifying more than one argument. You can control the buffering of output us \par Examples The following input instructs plumed to write a file called forces that contains -the force acting on the distance between atoms 1 and 2. +the force acting on the distance between atoms 1 and 2. \verbatim DISTANCE ATOM=1,2 LABEL=distance DUMPFORCES ARG=distance STRIDE=1 FILE=forces @@ -54,24 +54,24 @@ DUMPFORCES ARG=distance STRIDE=1 FILE=forces //+ENDPLUMEDOC class DumpForces : -public ActionPilot, -public ActionWithArguments + public ActionPilot, + public ActionWithArguments { string file; string fmt; OFile of; public: - void calculate(){} + void calculate() {} explicit DumpForces(const ActionOptions&); static void registerKeywords(Keywords& keys); - void apply(){} + void apply() {} void update(); ~DumpForces(); }; PLUMED_REGISTER_ACTION(DumpForces,"DUMPFORCES") -void DumpForces::registerKeywords(Keywords& keys){ +void DumpForces::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -85,10 +85,10 @@ void DumpForces::registerKeywords(Keywords& keys){ } DumpForces::DumpForces(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -fmt("%15.10f") + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + fmt("%15.10f") { parse("FILE",file); if( file.length()==0 ) error("name of file was not specified"); @@ -103,17 +103,17 @@ fmt("%15.10f") } -void DumpForces::update(){ +void DumpForces::update() { of.fmtField(" %f"); of.printField("time",getTime()); - for(unsigned i=0;igetName(),getPntrToArgument(i)->getForce()); } of.printField(); } -DumpForces::~DumpForces(){ +DumpForces::~DumpForces() { } } diff --git a/src/generic/DumpMassCharge.cpp b/src/generic/DumpMassCharge.cpp index f6f4e83923..4153bc8384 100644 --- a/src/generic/DumpMassCharge.cpp +++ b/src/generic/DumpMassCharge.cpp @@ -30,7 +30,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC PRINTANALYSIS DUMPMASSCHARGE /* @@ -59,7 +59,7 @@ DUMPMASSCHARGE FILE=mcfile (see also \ref COM and \ref PRINT) In this way, you will be able to use the same masses while processing -a trajectory from the \ref driver . To do so, you need to +a trajectory from the \ref driver . To do so, you need to add the --mc flag on the driver command line, e.g. \verbatim plumed driver --mc mcfile --plumed plumed.dat --ixyz traj.xyz @@ -100,14 +100,14 @@ class DumpMassCharge: explicit DumpMassCharge(const ActionOptions&); ~DumpMassCharge(); static void registerKeywords( Keywords& keys ); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void update(); }; PLUMED_REGISTER_ACTION(DumpMassCharge,"DUMPMASSCHARGE") -void DumpMassCharge::registerKeywords( Keywords& keys ){ +void DumpMassCharge::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -128,8 +128,8 @@ DumpMassCharge::DumpMassCharge(const ActionOptions&ao): parseAtomList("ATOMS",atoms); - if(atoms.size()==0){ - for(unsigned i=0;igetPntrToAction())->turnOnDerivatives(); + for(unsigned i=0; igetPntrToAction())->turnOnDerivatives(); } } -void DumpProjections::update(){ +void DumpProjections::update() { of.fmtField(" %f").printField("time",getTime()); - for(unsigned i=0;igetName()+"-"+getPntrToArgument(j)->getName(),getProjection(i,j)); } @@ -113,7 +113,7 @@ void DumpProjections::update(){ of.printField(); } -DumpProjections::~DumpProjections(){ +DumpProjections::~DumpProjections() { } } diff --git a/src/generic/EffectiveEnergyDrift.cpp b/src/generic/EffectiveEnergyDrift.cpp index 885491e2ba..1c3961390a 100644 --- a/src/generic/EffectiveEnergyDrift.cpp +++ b/src/generic/EffectiveEnergyDrift.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -/* +/* This class was originally written by Marco Jacopo Ferrarotti (marco.ferrarotti@gmail.com) and Giovanni Bussi */ @@ -42,7 +42,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC EFFECTIVE_ENERGY_DRIFT /* @@ -57,7 +57,7 @@ simulation on the Debye-Huckel energy. Since this variable is very expensive, it could be conveniently computed every second step. \verbatim dh: DHENERGY GROUPA=1-10 GROUPB=11-20 EPSILON=80.0 I=0.1 TEMP=300.0 -METAD ARG=dh HEIGHT=0.5 SIGMA=0.1 PACE=500 STRIDE=2 +METAD ARG=dh HEIGHT=0.5 SIGMA=0.1 PACE=500 STRIDE=2 EFFECTIVE_ENERGY_DRIFT PRINT_STRIDE=100 FILE=eff \endverbatim @@ -73,7 +73,7 @@ EFFECTIVE_ENERGY_DRIFT PRINT_STRIDE=100 FILE=eff class EffectiveEnergyDrift: -public ActionPilot{ + public ActionPilot { OFile output; long int printStride; @@ -115,14 +115,14 @@ public ActionPilot{ static void registerKeywords( Keywords& keys ); - void calculate(){}; - void apply(){}; + void calculate() {}; + void apply() {}; void update(); }; PLUMED_REGISTER_ACTION(EffectiveEnergyDrift,"EFFECTIVE_ENERGY_DRIFT") -void EffectiveEnergyDrift::registerKeywords( Keywords& keys ){ +void EffectiveEnergyDrift::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); @@ -136,14 +136,14 @@ void EffectiveEnergyDrift::registerKeywords( Keywords& keys ){ } EffectiveEnergyDrift::EffectiveEnergyDrift(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -eed(0.0), -atoms(plumed.getAtoms()), -nProc(plumed.comm.Get_size()), -initialBias(0.0), -isFirstStep(true), -ensemble(false) + Action(ao), + ActionPilot(ao), + eed(0.0), + atoms(plumed.getAtoms()), + nProc(plumed.comm.Get_size()), + initialBias(0.0), + isFirstStep(true), + ensemble(false) { //stride must be == 1 if(getStride()!=1) error("EFFECTIVE_ENERGY_DRIFT must have STRIDE=1 to work properly"); @@ -163,13 +163,13 @@ ensemble(false) parseFlag("ENSEMBLE",ensemble); if(ensemble&&comm.Get_rank()==0) { if(multi_sim_comm.Get_size()<2) error("You CANNOT run Replica-Averaged simulations without running multiple replicas!\n"); - } + } log<<"Bibliography "< tmpActions=plumed.getActionSet().select(); - for(unsigned i=0;iexists(tmpActions[i]->getLabel()+".bias")) biases.push_back(tmpActions[i]); + for(unsigned i=0; iexists(tmpActions[i]->getLabel()+".bias")) biases.push_back(tmpActions[i]); //resize counters and displacements useful to communicate with MPI_Allgatherv indexCnt.resize(nProc); @@ -182,11 +182,11 @@ ensemble(false) backmap.resize(atoms.getNatoms()); } -EffectiveEnergyDrift::~EffectiveEnergyDrift(){ +EffectiveEnergyDrift::~EffectiveEnergyDrift() { } -void EffectiveEnergyDrift::update(){ +void EffectiveEnergyDrift::update() { bool pbc=atoms.getPbc().isSet(); //retrive data of local atoms @@ -194,11 +194,11 @@ void EffectiveEnergyDrift::update(){ nLocalAtoms = gatindex.size(); atoms.getLocalPositions(positions); atoms.getLocalForces(forces); - if(pbc){ + if(pbc) { Tensor B=atoms.getPbc().getBox(); Tensor IB=atoms.getPbc().getInvBox(); -#pragma omp parallel for - for(unsigned i=0;igetOutputQuantity("bias"); + for(unsigned i=0; igetOutputQuantity("bias"); plumed.comm.Sum(&eedSum,1); - + double effective = eedSum+bias-initialBias-plumed.getWork(); // this is to take into account ensemble averaging if(ensemble) { diff --git a/src/generic/FitToTemplate.cpp b/src/generic/FitToTemplate.cpp index ad35b40b73..37e38333f6 100644 --- a/src/generic/FitToTemplate.cpp +++ b/src/generic/FitToTemplate.cpp @@ -41,7 +41,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC FIT_TO_TEMPLATE /* @@ -65,7 +65,7 @@ change the result. Examples are: \attention The implementation of TYPE=OPTIMAL is available but should be considered in testing phase. Please report any -strange behavior. +strange behavior. \attention This directive modifies the stored position at the precise moment @@ -104,7 +104,7 @@ class FitToTemplate: Vector center; Vector shift; // optimal alignment related stuff - PLMD::RMSD* rmsd; + PLMD::RMSD* rmsd; Tensor rotation; Matrix< std::vector > drotdpos; std::vector positions; @@ -113,19 +113,19 @@ class FitToTemplate: std::vector centeredpositions; Vector center_positions; - + public: explicit FitToTemplate(const ActionOptions&ao); ~FitToTemplate(); static void registerKeywords( Keywords& keys ); void calculate(); void apply(); - unsigned getNumberOfDerivatives(){plumed_merror("You should not call this function");}; + unsigned getNumberOfDerivatives() {plumed_merror("You should not call this function");}; }; PLUMED_REGISTER_ACTION(FitToTemplate,"FIT_TO_TEMPLATE") -void FitToTemplate::registerKeywords( Keywords& keys ){ +void FitToTemplate::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); keys.add("compulsory","STRIDE","1","the frequency with which molecules are reassembled. Unless you are completely certain about what you are doing leave this set equal to 1!"); @@ -134,18 +134,18 @@ void FitToTemplate::registerKeywords( Keywords& keys ){ } FitToTemplate::FitToTemplate(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao), -ActionWithValue(ao), -rmsd(NULL) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao), + ActionWithValue(ao), + rmsd(NULL) { string reference; parse("REFERENCE",reference); type.assign("SIMPLE"); parse("TYPE",type); - // if(type!="SIMPLE") error("Only TYPE=SIMPLE is implemented in FIT_TO_TEMPLATE"); +// if(type!="SIMPLE") error("Only TYPE=SIMPLE is implemented in FIT_TO_TEMPLATE"); checkRead(); @@ -153,7 +153,7 @@ rmsd(NULL) // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + reference ); + error("missing input file " + reference ); requestAtoms(pdb.getAtomNumbers()); @@ -163,22 +163,22 @@ rmsd(NULL) // normalize weights - double n=0.0; for(unsigned i=0;i weights_measure=pdb.getBeta(); - n=0.0; for(unsigned i=0;iset(weights,weights_measure,positions,type,false,false);// note: the reference is shifted now with center in the origin - log<<" Method chosen for fitting: "<getMethod()<<" \n"; + if(type=="OPTIMAL" or type=="OPTIMAL-FAST" ) { + rmsd=new RMSD(); + rmsd->set(weights,weights_measure,positions,type,false,false);// note: the reference is shifted now with center in the origin + log<<" Method chosen for fitting: "<getMethod()<<" \n"; } // register the value of rmsd (might be useful sometimes) addValue(); setNotPeriodic(); @@ -191,92 +191,92 @@ rmsd(NULL) } -void FitToTemplate::calculate(){ +void FitToTemplate::calculate() { - Vector cc; + Vector cc; - for(unsigned i=0;icalc_FitElements( positions, rotation , drotdpos , centeredpositions, center_positions); - setValue(r); - for(unsigned i=0;icalc_FitElements( positions, rotation, drotdpos, centeredpositions, center_positions); + setValue(r); + for(unsigned i=0; ifflush(); + p->fflush(); } }; PLUMED_REGISTER_ACTION(Flush,"FLUSH") -void Flush::registerKeywords( Keywords& keys ){ +void Flush::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); keys.add("compulsory","STRIDE","the frequency with which all the open files should be flushed"); diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index a214aa3536..0403d6b761 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -31,19 +31,19 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC GENERIC GROUP /* Define a group of atoms so that a particular list of atoms can be referenced with a single label -in definitions of CVs or virtual atoms. +in definitions of CVs or virtual atoms. Atoms can be listed as comma separated numbers (i.e. 1,2,3,10,45,7,9,..) , simple positive ranges (i.e. 20-40), ranges with a stride either positive or negative (i.e. 20-40:2 or 80-50:-2) or as -combinations of all the former methods (1,2,4,5,10-20,21-40:2,80-50:-2). +combinations of all the former methods (1,2,4,5,10-20,21-40:2,80-50:-2). -Moreover, lists can be imported from ndx files (GROMACS format). Use NDX_FILE to set the name of +Moreover, lists can be imported from ndx files (GROMACS format). Use NDX_FILE to set the name of the index file and NDX_GROUP to set the name of the group to be imported (default is first one). It is also possible to remove atoms from a list and or sort them using keywords REMOVE, SORT, and UNIQUE. @@ -126,8 +126,8 @@ class Group: explicit Group(const ActionOptions&ao); ~Group(); static void registerKeywords( Keywords& keys ); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} }; PLUMED_REGISTER_ACTION(Group,"GROUP") @@ -144,25 +144,25 @@ Group::Group(const ActionOptions&ao): if(ndxfile.length()>0 && atoms.size()>0) error("either use explicit atom list or import from index file"); if(ndxfile.length()==0 && ndxgroup.size()>0) error("NDX_GROUP can be only used is NDX_FILE is also used"); - if(ndxfile.length()>0){ + if(ndxfile.length()>0) { if(ndxgroup.size()>0) log<<" importing group '"+ndxgroup+"'"; else log<<" importing first group"; log<<" from index file "< words=Tools::getWords(line); - if(words.size()>=3 && words[0]=="[" && words[2]=="]"){ + if(words.size()>=3 && words[0]=="[" && words[2]=="]") { if(groupname.length()>0) firstgroup=false; groupname=words[1]; if(groupname==ndxgroup || ndxgroup.length()==0) groupfound=true; - } else if(groupname==ndxgroup || (firstgroup && ndxgroup.length()==0)){ - for(unsigned i=0;i remove; parseAtomList("REMOVE",remove); - if(remove.size()>0){ + if(remove.size()>0) { std::vector notfound; log<<" removing these atoms from the list:"; - for(unsigned i=0;i0){ + if(notfound.size()>0) { log<<" the following atoms were not found:"; - for(unsigned i=0;iatoms.insertGroup(getLabel(),atoms); log.printf(" list of atoms "); - for(unsigned i=0;i rotateArguments; ///////////////////////////////////////// public: - void calculate(){} + void calculate() {} void prepare(); explicit Print(const ActionOptions&); static void registerKeywords(Keywords& keys); - void apply(){} + void apply() {} void update(); ~Print(); }; PLUMED_REGISTER_ACTION(Print,"PRINT") -void Print::registerKeywords(Keywords& keys){ +void Print::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -95,15 +95,15 @@ void Print::registerKeywords(Keywords& keys){ } Print::Print(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -fmt("%f"), -rotate(0) + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + fmt("%f"), + rotate(0) { ofile.link(*this); parse("FILE",file); - if(file.length()>0){ + if(file.length()>0) { ofile.open(file); log.printf(" on file %s\n",file.c_str()); } else { @@ -113,15 +113,15 @@ rotate(0) parse("FMT",fmt); fmt=" "+fmt; log.printf(" with format %s\n",fmt.c_str()); - for(unsigned i=0;i0){ + if(rotate>0) { rotateCountdown=rotate; - for(unsigned i=0;i a(1,rotateArguments[0]); requestArguments(vector(1,rotateArguments[0])); rotateLast=0; @@ -130,14 +130,14 @@ rotate(0) checkRead(); } -void Print::prepare(){ +void Print::prepare() { ///////////////////////////////////////// // these are crazy things just for debug: // they allow to change regularly the // printed argument - if(rotate>0){ + if(rotate>0) { rotateCountdown--; - if(rotateCountdown==0){ + if(rotateCountdown==0) { rotateCountdown=rotate; rotateLast++; rotateLast%=rotateArguments.size(); @@ -147,18 +147,18 @@ void Print::prepare(){ ///////////////////////////////////////// } -void Print::update(){ - ofile.fmtField(" %f"); - ofile.printField("time",getTime()); - for(unsigned i=0;igetName(),getArgument(i)); - } - ofile.printField(); +void Print::update() { + ofile.fmtField(" %f"); + ofile.printField("time",getTime()); + for(unsigned i=0; igetName(),getArgument(i)); + } + ofile.printField(); } -Print::~Print(){ +Print::~Print() { } } diff --git a/src/generic/RandomExchanges.cpp b/src/generic/RandomExchanges.cpp index b98889e2ff..be36873bcc 100644 --- a/src/generic/RandomExchanges.cpp +++ b/src/generic/RandomExchanges.cpp @@ -27,8 +27,8 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC GENERIC RANDOM_EXCHANGES /* @@ -78,19 +78,19 @@ class RandomExchanges: public: static void registerKeywords( Keywords& keys ); explicit RandomExchanges(const ActionOptions&ao); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} }; PLUMED_REGISTER_ACTION(RandomExchanges,"RANDOM_EXCHANGES") -void RandomExchanges::registerKeywords( Keywords& keys ){ +void RandomExchanges::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); keys.add("optional","SEED","seed for random exchanges"); } RandomExchanges::RandomExchanges(const ActionOptions&ao): -Action(ao) + Action(ao) { plumed.getExchangePatterns().setFlag(ExchangePatterns::RANDOM); // I convert the seed to -seed because I think it is more general to use a positive seed in input diff --git a/src/generic/Read.cpp b/src/generic/Read.cpp index 2b67c1685a..88c2796300 100644 --- a/src/generic/Read.cpp +++ b/src/generic/Read.cpp @@ -27,20 +27,20 @@ #include "core/Atoms.h" #include "tools/IFile.h" -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC GENERIC READ -/* +/* Read quantities from a colvar file. -This Action can be used with driver to read in a colvar file that was generated during +This Action can be used with driver to read in a colvar file that was generated during an MD simulation \par Description of components The READ command will read those fields that are labelled with the text string given to the -VALUE keyword. It will also read in any fields that are labelleled with the text string +VALUE keyword. It will also read in any fields that are labelleled with the text string given to the VALUE keyword followed by a dot and a further string. If a single Value is read in this value can be referenced using the label of the Action. Alternatively, if multiple quanties are read in, they can be referenced elsewhere in the input by using the label for the Action @@ -49,7 +49,7 @@ followed by a dot and the character string that appeared after the dot in the ti \par Examples This input reads in data from a file called input_colvar.data that was generated -in a calculation that involved PLUMED. The first command reads in the data from the +in a calculation that involved PLUMED. The first command reads in the data from the column headed phi1 while the second reads in the data from the column headed phi2. \verbatim @@ -62,8 +62,8 @@ PRINT ARG=rphi1,rphi2 STRIDE=500 FILE=output_colvar.data //+ENDPLUMEDOC class Read : -public ActionPilot, -public ActionWithValue + public ActionPilot, + public ActionWithValue { private: bool ignore_time; @@ -78,7 +78,7 @@ public ActionWithValue explicit Read(const ActionOptions&); ~Read(); void prepare(); - void apply(){} + void apply() {} void calculate(); void update(); std::string getFilename() const; @@ -89,7 +89,7 @@ public ActionWithValue PLUMED_REGISTER_ACTION(Read,"READ") -void Read::registerKeywords(Keywords& keys){ +void Read::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithValue::registerKeywords(keys); @@ -98,9 +98,9 @@ void Read::registerKeywords(Keywords& keys){ keys.add("compulsory","VALUES","the values to read from the file"); keys.add("compulsory","FILE","the name of the file from which to read these quantities"); keys.addFlag("IGNORE_TIME",false,"ignore the time in the colvar file. When this flag is not present read will be quite strict " - "about the start time of the simulation and the stride between frames"); + "about the start time of the simulation and the stride between frames"); keys.addFlag("IGNORE_FORCES",false,"use this flag if the forces added by any bias can be safely ignored. As an example forces can be " - "safely ignored if you are doing postprocessing that does not involve outputting forces"); + "safely ignored if you are doing postprocessing that does not involve outputting forces"); keys.remove("NUMERICAL_DERIVATIVES"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); @@ -108,12 +108,12 @@ void Read::registerKeywords(Keywords& keys){ } Read::Read(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithValue(ao), -ignore_time(false), -ignore_forces(false), -nlinesPerStep(1) + Action(ao), + ActionPilot(ao), + ActionWithValue(ao), + ignore_time(false), + ignore_forces(false), + nlinesPerStep(1) { // Read the file name from the input line parse("FILE",filename); @@ -124,18 +124,18 @@ nlinesPerStep(1) // Open the file if it is not already opened cloned_file=false; std::vector other_reads=plumed.getActionSet().select(); - for(unsigned i=0;igetFilename()==filename ){ - ifile=other_reads[i]->getFile(); - cloned_file=true; - } + for(unsigned i=0; igetFilename()==filename ) { + ifile=other_reads[i]->getFile(); + cloned_file=true; + } } - if( !cloned_file ){ - ifile=new IFile(); - if( !ifile->FileExist(filename) ) error("could not find file named " + filename); - ifile->link(*this); - ifile->open(filename); - ifile->allowIgnoredFields(); + if( !cloned_file ) { + ifile=new IFile(); + if( !ifile->FileExist(filename) ) error("could not find file named " + filename); + ifile->link(*this); + ifile->open(filename); + ifile->allowIgnoredFields(); } parse("EVERY",nlinesPerStep); if(nlinesPerStep>1) log.printf(" only reading every %uth line of file %s\n",nlinesPerStep,filename.c_str() ); @@ -144,93 +144,93 @@ nlinesPerStep(1) std::vector valread; parseVector("VALUES",valread); std::size_t dot=valread[0].find_first_of('.'); - if( valread[0].find(".")!=std::string::npos ){ - std::string label=valread[0].substr(0,dot); - std::string name=valread[0].substr(dot+1); - if( name=="*" ){ - if( valread.size()>1 ) error("all values must be from the same Action when using READ"); - std::vector fieldnames; - ifile->scanFieldList( fieldnames ); - for(unsigned i=0;iFieldExist("min_" + fieldnames[i]) ) componentIsPeriodic( fieldnames[i].substr(dot+1), "-pi","pi" ); - else componentIsNotPeriodic( fieldnames[i].substr(dot+1) ); - } - } - } else { - readvals.push_back(new Value(this, valread[0], false) ); addComponentWithDerivatives( name ); - if( ifile->FieldExist("min_" + valread[0]) ) componentIsPeriodic( valread[0].substr(dot+1), "-pi", "pi" ); - else componentIsNotPeriodic( valread[0].substr(dot+1) ); - for(unsigned i=1;iFieldExist("min_" + valread[i]) ) componentIsPeriodic( valread[i].substr(dot+1), "-pi", "pi" ); - else componentIsNotPeriodic( valread[i].substr(dot+1) ); - } + if( valread[0].find(".")!=std::string::npos ) { + std::string label=valread[0].substr(0,dot); + std::string name=valread[0].substr(dot+1); + if( name=="*" ) { + if( valread.size()>1 ) error("all values must be from the same Action when using READ"); + std::vector fieldnames; + ifile->scanFieldList( fieldnames ); + for(unsigned i=0; iFieldExist("min_" + fieldnames[i]) ) componentIsPeriodic( fieldnames[i].substr(dot+1), "-pi","pi" ); + else componentIsNotPeriodic( fieldnames[i].substr(dot+1) ); + } + } + } else { + readvals.push_back(new Value(this, valread[0], false) ); addComponentWithDerivatives( name ); + if( ifile->FieldExist("min_" + valread[0]) ) componentIsPeriodic( valread[0].substr(dot+1), "-pi", "pi" ); + else componentIsNotPeriodic( valread[0].substr(dot+1) ); + for(unsigned i=1; iFieldExist("min_" + valread[i]) ) componentIsPeriodic( valread[i].substr(dot+1), "-pi", "pi" ); + else componentIsNotPeriodic( valread[i].substr(dot+1) ); } + } } else { - if( valread.size()!=1 ) error("all values must be from the same Action when using READ"); - readvals.push_back(new Value(this, valread[0], false) ); addValueWithDerivatives(); - if( ifile->FieldExist("min_" + valread[0]) ) setPeriodic( "-pi", "pi" ); - else setNotPeriodic(); - log.printf(" reading value %s and storing as %s\n",valread[0].c_str() ,getLabel().c_str() ); + if( valread.size()!=1 ) error("all values must be from the same Action when using READ"); + readvals.push_back(new Value(this, valread[0], false) ); addValueWithDerivatives(); + if( ifile->FieldExist("min_" + valread[0]) ) setPeriodic( "-pi", "pi" ); + else setNotPeriodic(); + log.printf(" reading value %s and storing as %s\n",valread[0].c_str(),getLabel().c_str() ); } checkRead(); } -Read::~Read(){ - if( !cloned_file ){ ifile->close(); delete ifile; } - for(unsigned i=0;iclose(); delete ifile; } + for(unsigned i=0; iscanField("time",du_time) ){ - error("Reached end of file " + filename + " before end of trajectory"); - } else if( fabs( du_time-getTime() )>plumed.getAtoms().getTimeStep() && !ignore_time ){ - std::string str_dutime,str_ptime; Tools::convert(du_time,str_dutime); Tools::convert(getTime(),str_ptime); - error("mismatched times in colvar files : colvar time=" + str_dutime + " plumed time=" + str_ptime + ". Add IGNORE_TIME to ignore error."); - } - } +void Read::prepare() { + if( !cloned_file ) { + double du_time; + if( !ifile->scanField("time",du_time) ) { + error("Reached end of file " + filename + " before end of trajectory"); + } else if( fabs( du_time-getTime() )>plumed.getAtoms().getTimeStep() && !ignore_time ) { + std::string str_dutime,str_ptime; Tools::convert(du_time,str_dutime); Tools::convert(getTime(),str_ptime); + error("mismatched times in colvar files : colvar time=" + str_dutime + " plumed time=" + str_ptime + ". Add IGNORE_TIME to ignore error."); + } + } } -void Read::calculate(){ +void Read::calculate() { std::string smin, smax; - for(unsigned i=0;iscanField( readvals[i] ); - getPntrToComponent(i)->set( readvals[i]->get() ); - if( readvals[i]->isPeriodic() ){ - readvals[i]->getDomain( smin, smax ); - getPntrToComponent(i)->setDomain( smin, smax ); - } + for(unsigned i=0; iscanField( readvals[i] ); + getPntrToComponent(i)->set( readvals[i]->get() ); + if( readvals[i]->isPeriodic() ) { + readvals[i]->getDomain( smin, smax ); + getPntrToComponent(i)->setDomain( smin, smax ); + } } } -void Read::update(){ - if( !cloned_file ){ - for(unsigned i=0;iscanField(); double du_time; - if( plumed.getAtoms().getNatoms()==0 && !ifile->scanField("time",du_time) ) plumed.stop(); - } +void Read::update() { + if( !cloned_file ) { + for(unsigned i=0; iscanField(); double du_time; + if( plumed.getAtoms().getNatoms()==0 && !ifile->scanField("time",du_time) ) plumed.stop(); + } } } diff --git a/src/generic/ResetCell.cpp b/src/generic/ResetCell.cpp index c595b4d9cc..fd14c1fe10 100644 --- a/src/generic/ResetCell.cpp +++ b/src/generic/ResetCell.cpp @@ -35,7 +35,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC RESET_CELL /* @@ -58,7 +58,7 @@ arbitrary. \attention The implementation of this action is available but should be considered in testing phase. Please report any -strange behavior. +strange behavior. \attention This directive modifies the stored position at the precise moment @@ -91,7 +91,7 @@ class ResetCell: { std::string type; Tensor rotation,newbox; - + public: explicit ResetCell(const ActionOptions&ao); static void registerKeywords( Keywords& keys ); @@ -101,7 +101,7 @@ class ResetCell: PLUMED_REGISTER_ACTION(ResetCell,"RESET_CELL") -void ResetCell::registerKeywords( Keywords& keys ){ +void ResetCell::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); keys.add("compulsory","STRIDE","1","the frequency with which molecules are reassembled. Unless you are completely certain about what you are doing leave this set equal to 1!"); @@ -109,66 +109,66 @@ void ResetCell::registerKeywords( Keywords& keys ){ } ResetCell::ResetCell(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao) { type.assign("TRIANGULAR"); parse("TYPE",type); log<<" type: "<resizeDerivatives(1); } -void Time::calculate(){ - setValue (getTime()); +void Time::calculate() { + setValue (getTime()); } } diff --git a/src/generic/UpdateIf.cpp b/src/generic/UpdateIf.cpp index 987cbc2c04..1db2b6cb19 100644 --- a/src/generic/UpdateIf.cpp +++ b/src/generic/UpdateIf.cpp @@ -26,8 +26,8 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC PRINTANALYSIS UPDATE_IF /* @@ -76,8 +76,8 @@ UPDATE_IF ARG=coord END //+ENDPLUMEDOC class UpdateIf: -public ActionPilot, -public ActionWithArguments + public ActionPilot, + public ActionWithArguments { std::vector lower; std::vector upper; @@ -89,13 +89,13 @@ public ActionWithArguments void beforeUpdate(); explicit UpdateIf(const ActionOptions&); static void registerKeywords(Keywords& keys); - void apply(){} + void apply() {} ~UpdateIf(); }; PLUMED_REGISTER_ACTION(UpdateIf,"UPDATE_IF") -void UpdateIf::registerKeywords(Keywords& keys){ +void UpdateIf::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -107,11 +107,11 @@ void UpdateIf::registerKeywords(Keywords& keys){ } UpdateIf::UpdateIf(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -on(false), -end(false) + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + on(false), + end(false) { parseFlag("END",end); parseVector("LESS_THAN",upper); @@ -122,24 +122,24 @@ end(false) if(lower.size()==0) lower.assign(getNumberOfArguments(),-std::numeric_limits::max()); if(upper.size()!=getNumberOfArguments()) error("LESS_THAN should have the same size as ARG"); if(lower.size()!=getNumberOfArguments()) error("MORE_THAN should have the same size as ARG"); - for(unsigned i=0;i=upper[i] || getArgument(i)<=lower[i]) on=false; } } -void UpdateIf::beforeUpdate(){ +void UpdateIf::beforeUpdate() { if(end) plumed.updateFlagsPop(); else { if(on) plumed.updateFlagsPush(plumed.updateFlagsTop()); @@ -148,7 +148,7 @@ void UpdateIf::beforeUpdate(){ } -UpdateIf::~UpdateIf(){ +UpdateIf::~UpdateIf() { } } diff --git a/src/generic/WholeMolecules.cpp b/src/generic/WholeMolecules.cpp index 6d8551774b..12e9c82813 100644 --- a/src/generic/WholeMolecules.cpp +++ b/src/generic/WholeMolecules.cpp @@ -36,7 +36,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC WHOLEMOLECULES /* @@ -47,7 +47,7 @@ It is similar to the ALIGN_ATOMS keyword of plumed1, and is needed since some MD dynamics code (e.g. GROMACS) can break molecules during the calculation. Running some CVs without this command can cause there to be discontinuities changes -in the CV value and artifacts in the calculations. This command can be applied +in the CV value and artifacts in the calculations. This command can be applied more than once. To see what effect is has use a variable without pbc or use the \ref DUMPATOMS directive to output the atomic positions. @@ -90,12 +90,12 @@ DUMPATOMS FILE=dump.xyz ATOMS=1-20,30-40 \endverbatim (see also \ref DUMPATOMS) -This command instructs plumed to reconstruct the chain of backbone atoms in a +This command instructs plumed to reconstruct the chain of backbone atoms in a protein \verbatim MOLINFO STRUCTURE=helix.pdb -WHOLEMOLECULES RESIDUES=all MOLTYPE=protein +WHOLEMOLECULES RESIDUES=all MOLTYPE=protein \endverbatim (See also \ref MOLINFO) @@ -112,12 +112,12 @@ class WholeMolecules: explicit WholeMolecules(const ActionOptions&ao); static void registerKeywords( Keywords& keys ); void calculate(); - void apply(){} + void apply() {} }; PLUMED_REGISTER_ACTION(WholeMolecules,"WHOLEMOLECULES") -void WholeMolecules::registerKeywords( Keywords& keys ){ +void WholeMolecules::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -125,24 +125,24 @@ void WholeMolecules::registerKeywords( Keywords& keys ){ keys.add("numbered","ENTITY","the atoms that make up a molecule that you wish to align. To specify multiple molecules use a list of ENTITY keywords: ENTITY0, ENTITY1,..."); keys.reset_style("ENTITY","atoms"); keys.add("residues","RESIDUES","this command specifies that the backbone atoms in a set of residues all must be aligned. It must be used in tandem with the \\ref MOLINFO " - "action and the MOLTYPE keyword. If you wish to use all the residues from all the chains in your system you can do so by " - "specifying all. Alternatively, if you wish to use a subset of the residues you can specify the particular residues " - "you are interested in as a list of numbers"); + "action and the MOLTYPE keyword. If you wish to use all the residues from all the chains in your system you can do so by " + "specifying all. Alternatively, if you wish to use a subset of the residues you can specify the particular residues " + "you are interested in as a list of numbers"); keys.add("optional","MOLTYPE","the type of molecule that is under study. This is used to define the backbone atoms"); } WholeMolecules::WholeMolecules(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao) { vector merge; - for(int i=0;;i++){ + for(int i=0;; i++) { vector group; - parseAtomList("ENTITY",i,group); + parseAtomList("ENTITY",i,group); if( group.empty() ) break; log.printf(" atoms in entity %d : ",i); - for(unsigned j=0;j resstrings; parseVector("RESIDUES",resstrings); - if( resstrings.size()>0 ){ - if( resstrings.size()==1 ){ - if( resstrings[0]=="all" ) resstrings[0]="all-ter"; // Include terminal groups in alignment - } - string moltype; parse("MOLTYPE",moltype); - if(moltype.length()==0) error("Found RESIDUES keyword without specification of the moleclue - use MOLTYPE"); - std::vector moldat=plumed.getActionSet().select(); - if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); - std::vector< std::vector > backatoms; - moldat[0]->getBackbone( resstrings, moltype, backatoms ); - for(unsigned i=0;i(groups.size()+1)); - for(unsigned j=0;j0 ) { + if( resstrings.size()==1 ) { + if( resstrings[0]=="all" ) resstrings[0]="all-ter"; // Include terminal groups in alignment + } + string moltype; parse("MOLTYPE",moltype); + if(moltype.length()==0) error("Found RESIDUES keyword without specification of the moleclue - use MOLTYPE"); + std::vector moldat=plumed.getActionSet().select(); + if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); + std::vector< std::vector > backatoms; + moldat[0]->getBackbone( resstrings, moltype, backatoms ); + for(unsigned i=0; i(groups.size()+1)); + for(unsigned j=0; j1) log<<" atoms will be grouped by "<::max(); int closest=-1; - for(unsigned j=0;j0 ){ - vstring += " TYPE=fibonacci CONCENTRATION=" + vconc; - } else { - std::string kstring; parse("KERNEL",kstring); - if( kstring=="DISCRETE" ) vstring += " KERNEL=" + kstring; - else vstring += " KERNEL=" + kstring + " " + getKeyword("BANDWIDTH"); - } + std::string vstring = inputstr; + if( keywords.exists("KERNEL") ) { + std::string vconc; parse("CONCENTRATION",vconc); + if( vconc.length()>0 ) { + vstring += " TYPE=fibonacci CONCENTRATION=" + vconc; + } else { + std::string kstring; parse("KERNEL",kstring); + if( kstring=="DISCRETE" ) vstring += " KERNEL=" + kstring; + else vstring += " KERNEL=" + kstring + " " + getKeyword("BANDWIDTH"); + } } vesselbase::VesselOptions da("mygrid","",-1,vstring,this); Keywords keys; gridtools::AverageOnGrid::registerKeywords( keys ); vesselbase::VesselOptions dar( da, keys ); - if( type=="histogram" ){ - mygrid = new HistogramOnGrid(dar); - } else if( type=="average" ){ - mygrid = new AverageOnGrid(dar); - } else if( type=="grid" ){ - mygrid = new GridVessel(dar); + if( type=="histogram" ) { + mygrid = new HistogramOnGrid(dar); + } else if( type=="average" ) { + mygrid = new AverageOnGrid(dar); + } else if( type=="grid" ) { + mygrid = new GridVessel(dar); } else { - plumed_merror("no way to create grid of type " + type ); - } + plumed_merror("no way to create grid of type " + type ); + } } -void ActionWithGrid::turnOnDerivatives(){ - needsDerivatives(); ActionWithValue::turnOnDerivatives(); +void ActionWithGrid::turnOnDerivatives() { + needsDerivatives(); ActionWithValue::turnOnDerivatives(); if( getStride()==1 ) setStride(0); else if( getStride()!=0 ) error("conflicting instructions for grid - stride was set but must be evaluated on every step for derivatives - remove STRIDE keyword"); - if( clearstride>1 ) error("conflicting instructions for grid - CLEAR was set but grid must be reset on every step for derivatives - remove CLEAR keyword" ); - if( weights.size()>0 ) error("conflicting instructions for grid - LOGWEIGHTS was set but weights are not considered when derivatives of grid are evaluated - remove LOGWEIGHTS keyword"); + if( clearstride>1 ) error("conflicting instructions for grid - CLEAR was set but grid must be reset on every step for derivatives - remove CLEAR keyword" ); + if( weights.size()>0 ) error("conflicting instructions for grid - LOGWEIGHTS was set but weights are not considered when derivatives of grid are evaluated - remove LOGWEIGHTS keyword"); } -void ActionWithGrid::calculate(){ +void ActionWithGrid::calculate() { // Do nothing if derivatives are not required if( doNotCalculateDerivatives() ) return; // Clear on every step diff --git a/src/gridtools/ActionWithGrid.h b/src/gridtools/ActionWithGrid.h index f87c5e6e61..c01a50ef10 100644 --- a/src/gridtools/ActionWithGrid.h +++ b/src/gridtools/ActionWithGrid.h @@ -43,7 +43,7 @@ class ActionWithGrid : public vesselbase::ActionWithAveraging { void createGrid( const std::string& type, const std::string& inputstr ); public: static void registerKeywords( Keywords& keys ); - explicit ActionWithGrid( const ActionOptions& ); + explicit ActionWithGrid( const ActionOptions& ); virtual void turnOnDerivatives(); void calculate(); void performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const ; diff --git a/src/gridtools/ActionWithInputGrid.cpp b/src/gridtools/ActionWithInputGrid.cpp index e409d9662b..12d358115c 100644 --- a/src/gridtools/ActionWithInputGrid.cpp +++ b/src/gridtools/ActionWithInputGrid.cpp @@ -26,52 +26,52 @@ namespace PLMD { namespace gridtools { -void ActionWithInputGrid::registerKeywords( Keywords& keys ){ +void ActionWithInputGrid::registerKeywords( Keywords& keys ) { ActionWithGrid::registerKeywords( keys ); keys.add("compulsory","GRID","the action that creates the input grid you would like to use"); keys.add("optional","COMPONENT","if your input is a vector field use this to specifiy the component of the input vector field for which you wish to use"); } ActionWithInputGrid::ActionWithInputGrid(const ActionOptions&ao): -Action(ao), -ActionWithGrid(ao), -ingrid(NULL) + Action(ao), + ActionWithGrid(ao), + ingrid(NULL) { std::string mlab; parse("GRID",mlab); vesselbase::ActionWithVessel* mves= plumed.getActionSet().selectWithLabel(mlab); if(!mves) error("action labelled " + mlab + " does not exist or does not have vessels"); addDependency(mves); - for(unsigned i=0;igetNumberOfVessels();++i){ - ingrid=dynamic_cast( mves->getPntrToVessel(i) ); - if( ingrid ) break; + for(unsigned i=0; igetNumberOfVessels(); ++i) { + ingrid=dynamic_cast( mves->getPntrToVessel(i) ); + if( ingrid ) break; } if( !ingrid ) error("input action does not calculate a grid"); - if( ingrid->getNumberOfComponents()==1 ){ - mycomp=0; + if( ingrid->getNumberOfComponents()==1 ) { + mycomp=0; } else { - int tcomp=-1; parse("COMPONENT",tcomp); - if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); - mycomp=tcomp; + int tcomp=-1; parse("COMPONENT",tcomp); + if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); + mycomp=tcomp; } log.printf(" using %uth component of grid calculated by action %s \n",mycomp,mves->getLabel().c_str() ); } -void ActionWithInputGrid::clearAverage(){ +void ActionWithInputGrid::clearAverage() { if( mygrid->getType()=="flat" ) mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), mygrid->getNbin(), mygrid->getGridSpacing() ); ActionWithAveraging::clearAverage(); } -void ActionWithInputGrid::prepareForAveraging(){ - if( checkAllActive() ){ - for(unsigned i=0;igetNumberOfPoints();++i){ - if( ingrid->inactive(i) ) error("if FIND_CONTOUR is used with BUFFER option then other actions cannot be performed with grid"); - } +void ActionWithInputGrid::prepareForAveraging() { + if( checkAllActive() ) { + for(unsigned i=0; igetNumberOfPoints(); ++i) { + if( ingrid->inactive(i) ) error("if FIND_CONTOUR is used with BUFFER option then other actions cannot be performed with grid"); + } } } -void ActionWithInputGrid::performOperations( const bool& from_update ){ +void ActionWithInputGrid::performOperations( const bool& from_update ) { prepareForAveraging(); runAllTasks(); } diff --git a/src/gridtools/ActionWithInputGrid.h b/src/gridtools/ActionWithInputGrid.h index 0799f4de69..cc1ba009e5 100644 --- a/src/gridtools/ActionWithInputGrid.h +++ b/src/gridtools/ActionWithInputGrid.h @@ -29,7 +29,7 @@ namespace PLMD { namespace gridtools { class ActionWithInputGrid : public ActionWithGrid { -friend class DumpGrid; + friend class DumpGrid; private: unsigned mycomp; protected: @@ -44,12 +44,12 @@ friend class DumpGrid; virtual void prepareForAveraging(); virtual bool checkAllActive() const { return true; } virtual void performOperations( const bool& from_update ); - virtual void apply(){}; + virtual void apply() {}; }; inline double ActionWithInputGrid::getFunctionValue( const unsigned& ipoint ) const { - unsigned dim=ingrid->getDimension(); if( ingrid->noderiv ) dim=0; + unsigned dim=ingrid->getDimension(); if( ingrid->noderiv ) dim=0; return ingrid->getGridElement( ipoint, mycomp*(1+dim) ); } @@ -61,7 +61,7 @@ double ActionWithInputGrid::getFunctionValue( const std::vector& ip ) inline double ActionWithInputGrid::getFunctionValueAndDerivatives( const std::vector& x, std::vector& der ) const { return ingrid->getValueAndDerivatives( x, mycomp, der ); -} +} } } diff --git a/src/gridtools/ActionWithIntegral.cpp b/src/gridtools/ActionWithIntegral.cpp index addfb46db4..7deb7fbd39 100644 --- a/src/gridtools/ActionWithIntegral.cpp +++ b/src/gridtools/ActionWithIntegral.cpp @@ -24,37 +24,37 @@ namespace PLMD { namespace gridtools { -void ActionWithIntegral::registerKeywords( Keywords& keys ){ +void ActionWithIntegral::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); - keys.remove("KERNEL"); keys.remove("BANDWIDTH"); + keys.remove("KERNEL"); keys.remove("BANDWIDTH"); keys.remove("CLEAR"); keys.add("compulsory","CLEAR","1","the frequency with which to clear all the accumulated data."); } ActionWithIntegral::ActionWithIntegral(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao) + Action(ao), + ActionWithInputGrid(ao) { - plumed_assert( ingrid->getNumberOfComponents()==1 ); + plumed_assert( ingrid->getNumberOfComponents()==1 ); // Retrieve the volume of the grid (for integration) volume = ingrid->getCellVolume(); - // Create something that is going to calculate the sum of all the values + // Create something that is going to calculate the sum of all the values // at the various grid points - this is going to be the integral std::string fake_input; addVessel( "SUM", fake_input, -1 ); readVesselKeywords(); // Now create task list - number of tasks is equal to the number of grid points // as we have to evaluate the function at each grid points - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); // And activate all tasks - deactivateAllTasks(); - for(unsigned i=0;igetNumberOfPoints();++i) taskFlags[i]=1; + deactivateAllTasks(); + for(unsigned i=0; igetNumberOfPoints(); ++i) taskFlags[i]=1; lockContributors(); } -void ActionWithIntegral::turnOnDerivatives(){ +void ActionWithIntegral::turnOnDerivatives() { ActionWithGrid::turnOnDerivatives(); forcesToApply.resize( ingrid->getNumberOfPoints() ); } -void ActionWithIntegral::apply(){ +void ActionWithIntegral::apply() { if( getForcesFromVessels( forcesToApply ) ) ingrid->setForce( forcesToApply ); } diff --git a/src/gridtools/ActionWithIntegral.h b/src/gridtools/ActionWithIntegral.h index 635ce663b1..b4fcbf2b96 100644 --- a/src/gridtools/ActionWithIntegral.h +++ b/src/gridtools/ActionWithIntegral.h @@ -40,7 +40,7 @@ class ActionWithIntegral : public ActionWithInputGrid { unsigned getNumberOfDerivatives(); void turnOnDerivatives(); /// Unless I am mistaken an integral should never be a periodic function - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } void apply(); }; @@ -50,7 +50,7 @@ double ActionWithIntegral::getVolume() const { } inline -unsigned ActionWithIntegral::getNumberOfDerivatives(){ +unsigned ActionWithIntegral::getNumberOfDerivatives() { return ingrid->getNumberOfPoints(); } diff --git a/src/gridtools/AverageOnGrid.cpp b/src/gridtools/AverageOnGrid.cpp index 75d04579bc..0f9c5cc737 100644 --- a/src/gridtools/AverageOnGrid.cpp +++ b/src/gridtools/AverageOnGrid.cpp @@ -24,16 +24,16 @@ namespace PLMD { namespace gridtools { -void AverageOnGrid::registerKeywords( Keywords& keys ){ +void AverageOnGrid::registerKeywords( Keywords& keys ) { HistogramOnGrid::registerKeywords( keys ); } AverageOnGrid::AverageOnGrid( const vesselbase::VesselOptions& da ): -HistogramOnGrid(da) + HistogramOnGrid(da) { arg_names.push_back( "density" ); - if( !discrete ){ - for(unsigned i=0;i& der, std::vector& buffer ) const { buffer[bufstart+nper*ipoint] += weight*dens; buffer[ bufstart+nper*(ipoint+1) - (dimension+1) ] += dens; - if( der.size()>0 ){ - for(unsigned j=0;j0 ) { + for(unsigned j=0; j=(nper-(dimension+1)) ) return getDataElement( nper*ipoint + jelement ); + if( jelement>=(nper-(dimension+1)) ) return getDataElement( nper*ipoint + jelement ); if( noderiv ) return getDataElement( nper*ipoint+jelement ) / getDataElement( nper*(1+ipoint) - 1); - double rdenom = 1.0; + double rdenom = 1.0; if( fabs(getDataElement( nper*(ipoint+1) -(dimension+1) ))>epsilon ) rdenom = 1. / getDataElement( nper*(ipoint+1) - (dimension+1) ); - + unsigned jderiv = jelement%(1+dimension); - if( jderiv==0 ) return rdenom*getDataElement( nper*ipoint+jelement ); + if( jderiv==0 ) return rdenom*getDataElement( nper*ipoint+jelement ); unsigned jfloor = std::floor( jelement / (1+dimension) ); - return rdenom*getDataElement( nper*ipoint+jelement ) - rdenom*rdenom*getDataElement(nper*ipoint+jfloor)*getDataElement(nper*(ipoint+1) - (dimension+1) + jderiv); + return rdenom*getDataElement( nper*ipoint+jelement ) - rdenom*rdenom*getDataElement(nper*ipoint+jfloor)*getDataElement(nper*(ipoint+1) - (dimension+1) + jderiv); } } diff --git a/src/gridtools/AverageOnGrid.h b/src/gridtools/AverageOnGrid.h index 8b224bf056..ad38b50e71 100644 --- a/src/gridtools/AverageOnGrid.h +++ b/src/gridtools/AverageOnGrid.h @@ -35,7 +35,7 @@ class AverageOnGrid : public HistogramOnGrid { void accumulateForce( const unsigned& ipoint, const double& weight, const std::vector& der, std::vector& intforce ) const { plumed_error(); } double getGridElement( const unsigned& ipoint, const unsigned& jelement ) const ; unsigned getNumberOfComponents() const ; - void getFinalForces( const std::vector& buffer, std::vector& finalForces ){ plumed_error(); } + void getFinalForces( const std::vector& buffer, std::vector& finalForces ) { plumed_error(); } }; inline diff --git a/src/gridtools/ContourFindingBase.cpp b/src/gridtools/ContourFindingBase.cpp index cb6d374f5d..3a20dd6724 100644 --- a/src/gridtools/ContourFindingBase.cpp +++ b/src/gridtools/ContourFindingBase.cpp @@ -24,19 +24,19 @@ namespace PLMD { namespace gridtools { -void ContourFindingBase::registerKeywords( Keywords& keys ){ +void ContourFindingBase::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.add("compulsory","CONTOUR","the value we would like to draw the contour at in the space"); keys.remove("KERNEL"); keys.remove("BANDWIDTH"); } ContourFindingBase::ContourFindingBase(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao), -mymin(this) + Action(ao), + ActionWithInputGrid(ao), + mymin(this) { if( ingrid->noDerivatives() ) error("cannot find contours if input grid has no derivatives"); - parse("CONTOUR",contour); + parse("CONTOUR",contour); log.printf(" calculating dividing surface along which function equals %f \n", contour); } diff --git a/src/gridtools/ContourFindingBase.h b/src/gridtools/ContourFindingBase.h index ec6c1eee95..5a1752d5e5 100644 --- a/src/gridtools/ContourFindingBase.h +++ b/src/gridtools/ContourFindingBase.h @@ -43,9 +43,9 @@ class ContourFindingBase : public ActionWithInputGrid { /// Get the contour value double getDifferenceFromContour( const std::vector& x, std::vector& der ) const ; /// Overwrite not needed stuff - unsigned getNumberOfDerivatives(){ return 0; } + unsigned getNumberOfDerivatives() { return 0; } /// This is not periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; inline diff --git a/src/gridtools/ConvertToFES.cpp b/src/gridtools/ConvertToFES.cpp index 1edf196f04..4e3bbdf170 100644 --- a/src/gridtools/ConvertToFES.cpp +++ b/src/gridtools/ConvertToFES.cpp @@ -42,13 +42,13 @@ The free energy calculated on a grid is output by this action and can be printed This is a typical example showing how CONVERT_TO_FES might be used when postprocessing a trajectory. The input below calculates the free energy as a function of the distance between atom 1 and atom 2. This is done by accumulating a histogram as a function of this distance using kernel density estimation -and the HISTOGRAM action. All the data within this trajectory is used in the construction of this -HISTOGRAM. Finally, once all the data has been read in, the histogram is converted to a free energy +and the HISTOGRAM action. All the data within this trajectory is used in the construction of this +HISTOGRAM. Finally, once all the data has been read in, the histogram is converted to a free energy using the formula above and the free energy is output to a file called fes.dat \verbatim x: DISTANCE ATOMS=1,2 -hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 +hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 ff: CONVERT_TO_FES GRID=hA1 TEMP=300 DUMPGRID GRID=ff FILE=fes.dat \endverbatim @@ -67,35 +67,35 @@ class ConvertToFES : public ActionWithInputGrid { static void registerKeywords( Keywords& keys ); explicit ConvertToFES(const ActionOptions&ao); unsigned getNumberOfQuantities() const ; - void prepare(){ activated=true; } - void prepareForAveraging(){ ActionWithInputGrid::prepareForAveraging(); activated=false; } + void prepare() { activated=true; } + void prepareForAveraging() { ActionWithInputGrid::prepareForAveraging(); activated=false; } void compute( const unsigned& current, MultiValue& myvals ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } bool onStep() const { return activated; } void runFinalJobs(); }; PLUMED_REGISTER_ACTION(ConvertToFES,"CONVERT_TO_FES") -void ConvertToFES::registerKeywords( Keywords& keys ){ +void ConvertToFES::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.add("optional","TEMP","the temperature at which you are operating"); - keys.remove("STRIDE"); keys.remove("KERNEL"); keys.remove("BANDWIDTH"); + keys.remove("STRIDE"); keys.remove("KERNEL"); keys.remove("BANDWIDTH"); keys.remove("LOGWEIGHTS"); keys.remove("CLEAR"); keys.remove("UNORMALIZED"); } ConvertToFES::ConvertToFES(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao), -activated(false) + Action(ao), + ActionWithInputGrid(ao), + activated(false) { plumed_assert( ingrid->getNumberOfComponents()==1 ); // Create a grid - createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); - if( ingrid->noDerivatives() ) mygrid->setNoDerivatives(); + createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); + if( ingrid->noDerivatives() ) mygrid->setNoDerivatives(); std::vector fspacing; - mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), ingrid->getNbin(), fspacing); + mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), ingrid->getNbin(), fspacing); setAveragingAction( mygrid, true ); simtemp=0.; parse("TEMP",simtemp); @@ -104,10 +104,10 @@ activated(false) if( simtemp==0 ) error("TEMP not set - use keyword TEMP"); // Now create task list - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); // And activate all tasks - deactivateAllTasks(); - for(unsigned i=0;igetNumberOfPoints();++i) taskFlags[i]=1; + deactivateAllTasks(); + for(unsigned i=0; igetNumberOfPoints(); ++i) taskFlags[i]=1; lockContributors(); } @@ -118,12 +118,12 @@ unsigned ConvertToFES::getNumberOfQuantities() const { void ConvertToFES::compute( const unsigned& current, MultiValue& myvals ) const { double val=getFunctionValue( current ); myvals.setValue(1, -simtemp*std::log(val) ); - if( !mygrid->noDerivatives() && val>0 ){ - for(unsigned i=0;igetDimension();++i) myvals.setValue( 2+i, -(simtemp/val)*ingrid->getGridElement(current,i+1) ); + if( !mygrid->noDerivatives() && val>0 ) { + for(unsigned i=0; igetDimension(); ++i) myvals.setValue( 2+i, -(simtemp/val)*ingrid->getGridElement(current,i+1) ); } } -void ConvertToFES::runFinalJobs(){ +void ConvertToFES::runFinalJobs() { activated=true; update(); } diff --git a/src/gridtools/DumpCube.cpp b/src/gridtools/DumpCube.cpp index 22676175bd..0fbc47f566 100644 --- a/src/gridtools/DumpCube.cpp +++ b/src/gridtools/DumpCube.cpp @@ -28,22 +28,22 @@ Output a three dimensional grid using the Gaussian cube file format. Suppose you have calculated the value of a function on a three dimensional grid. -This function might be a \ref HISTOGRAM or it might be a free energy energy surface +This function might be a \ref HISTOGRAM or it might be a free energy energy surface that was calculated from this histogram by using \ref CONVERT_TO_FES. Alternatively, your function might be a phase-field that was calculated using \ref MULTICOLVARDENS. Whatever the function is, however, you obviously cannot show it using a typical contour -plotting program such as gnuplot as you have three input variables. +plotting program such as gnuplot as you have three input variables. Tools like VMD have nice features for plotting these types of three dimensional functions -but typically you are required to use a Gaussian cube file format to input the data. This +but typically you are required to use a Gaussian cube file format to input the data. This action thus allows you to output a function evaluated on a grid to a Gaussian cube file format. \par Examples The input below can be used to postprocess a trajectory. A histogram as a function of the distance between atoms 1 and 2, the distance between atom 1 and 3 and the angle between the vector connecting atoms 1 and -2 and 1 and 3 is computed using kernel density estimation. Once all the data contained in the trajectory has been read in and -all the kernels have been added the resulting histogram is output to a file called histoA1.cube. This file has the +2 and 1 and 3 is computed using kernel density estimation. Once all the data contained in the trajectory has been read in and +all the kernels have been added the resulting histogram is output to a file called histoA1.cube. This file has the Gaussian cube file format. The histogram can thus be visualized using tools such as VMD. \verbatim @@ -52,7 +52,7 @@ x2: DISTANCE ATOMS=1,3 x3: ANGLE ATOMS=1,2,3 hA1: HISTOGRAM ARG=x1,x2,x3 GRID_MIN=0.0,0.0,0.0 GRID_MAX=3.0,3.0,3.0 GRID_BIN=10,10,10 BANDWIDTH=1.0,1.0,1.0 -DUMPCUBE GRID=hA1 FILE=histoA1.cube +DUMPCUBE GRID=hA1 FILE=histoA1.cube \endverbatim */ @@ -66,32 +66,32 @@ class DumpCube : public GridPrintingBase { unsigned mycomp; public: static void registerKeywords( Keywords& keys ); - explicit DumpCube(const ActionOptions&ao); + explicit DumpCube(const ActionOptions&ao); void printGrid( OFile& ofile ) const ; }; PLUMED_REGISTER_ACTION(DumpCube,"DUMPCUBE") -void DumpCube::registerKeywords( Keywords& keys ){ +void DumpCube::registerKeywords( Keywords& keys ) { GridPrintingBase::registerKeywords( keys ); keys.add("optional","COMPONENT","if your input is a vector field use this to specifiy the component of the input vector field for which you wish to output"); } DumpCube::DumpCube(const ActionOptions&ao): -Action(ao), -GridPrintingBase(ao) + Action(ao), + GridPrintingBase(ao) { fmt = fmt + " "; if( ingrid->getType()!="flat" ) error("cannot dump grid of type " + ingrid->getType() + " using DUMPCUBE"); if( ingrid->getDimension()!=3 ) error("cannot print cube file if grid does not contain three dimensional data"); - if( ingrid->getNumberOfComponents()==1 ){ - mycomp=0; + if( ingrid->getNumberOfComponents()==1 ) { + mycomp=0; } else { - int tcomp=-1; parse("COMPONENT",tcomp); - if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); - mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; - log.printf(" using %dth component of grid \n",tcomp ); + int tcomp=-1; parse("COMPONENT",tcomp); + if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); + mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; + log.printf(" using %dth component of grid \n",tcomp ); } checkRead(); @@ -105,19 +105,19 @@ void DumpCube::printGrid( OFile& ofile ) const { // Number of atoms followed by position of origin (origin set so that center of grid is in center of cell) std::string ostr = "%d " + fmt + fmt + fmt + "\n"; ofile.printf(ostr.c_str(),1,-0.5*lunit*ingrid->getGridExtent(0),-0.5*lunit*ingrid->getGridExtent(1),-0.5*lunit*ingrid->getGridExtent(2)); - ofile.printf(ostr.c_str(),ingrid->getNbin()[0],lunit*ingrid->getGridSpacing()[0],0.0,0.0); // Number of bins in each direction followed by + ofile.printf(ostr.c_str(),ingrid->getNbin()[0],lunit*ingrid->getGridSpacing()[0],0.0,0.0); // Number of bins in each direction followed by ofile.printf(ostr.c_str(),ingrid->getNbin()[1],0.0,lunit*ingrid->getGridSpacing()[1],0.0); // shape of voxel ofile.printf(ostr.c_str(),ingrid->getNbin()[2],0.0,0.0,lunit*ingrid->getGridSpacing()[2]); ofile.printf(ostr.c_str(),1,0.0,0.0,0.0); // Fake atom otherwise VMD doesn't work std::vector pp(3); std::vector nbin( ingrid->getNbin() ); - for(pp[0]=0;pp[0]getGridElement( ingrid->getIndex(pp), mycomp ) ); - if(pp[2]%6==5) ofile.printf("\n"); - } - ofile.printf("\n"); - } + for(pp[0]=0; pp[0]getGridElement( ingrid->getIndex(pp), mycomp ) ); + if(pp[2]%6==5) ofile.printf("\n"); + } + ofile.printf("\n"); + } } } diff --git a/src/gridtools/DumpGrid.cpp b/src/gridtools/DumpGrid.cpp index acbcdc805e..608742a8bf 100644 --- a/src/gridtools/DumpGrid.cpp +++ b/src/gridtools/DumpGrid.cpp @@ -32,12 +32,12 @@ Output the function on the grid to a file with the PLUMED grid format. PLUMED provides a number of actions that calculate the values of functions on grids. For instance, whenver you calculate a free energy as a function of a collective variable using -\ref HISTOGRAM and \ref CONVERT_TO_FES you will generally want to output the value of the free energy at a number of points on a +\ref HISTOGRAM and \ref CONVERT_TO_FES you will generally want to output the value of the free energy at a number of points on a discrete grid that covers the CV space uniformly. Alternatively you may want to calculate -what value some symmetry function takes at different points inside your simulation cell using \ref MULTICOLVARDENS. +what value some symmetry function takes at different points inside your simulation cell using \ref MULTICOLVARDENS. -This action allows you to output these functions calculated on a grid using a format that can be read in using gnuplot -and other such plotting programs. The file output using this action will have a header that contains some essential +This action allows you to output these functions calculated on a grid using a format that can be read in using gnuplot +and other such plotting programs. The file output using this action will have a header that contains some essential information about the function plotted and that looks something like this: \verbatim @@ -51,17 +51,17 @@ information about the function plotted and that looks something like this: #! SET max_y 3.0 #! SET nbins_y 100 #! SET periodic_y false -\endverbatim +\endverbatim -The header shown here tells us that we have grid showing the values that a function with two arguments x and y -takes at various points in our cell. The lines beheath the first line then tell us a little bit about these two -input arguments. +The header shown here tells us that we have grid showing the values that a function with two arguments x and y +takes at various points in our cell. The lines beheath the first line then tell us a little bit about these two +input arguments. -The remaining lines of the file give us information on the positions of our grid points and the value the function and -its partial derivatives with respect to x and y. If the header is as above a list of values of the function that have +The remaining lines of the file give us information on the positions of our grid points and the value the function and +its partial derivatives with respect to x and y. If the header is as above a list of values of the function that have x=0 and 100 values of y between 0.0 and 3.0 will be provided. This block of data will be followed with a blank line. There will then be a second block of values which will all have been evaluated the same value of x and all possible values -for y. This block is then followed by a blank line again and this pattern continues until all points of the grid have been covered. +for y. This block is then followed by a blank line again and this pattern continues until all points of the grid have been covered. \par Examples @@ -71,11 +71,11 @@ and outputs a continuos histogram as a function of them at the end of the simula TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + ARG=r1,r2 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 - BANDWIDTH=0.05,0.05 + BANDWIDTH=0.05,0.05 LABEL=hh ... HISTOGRAM @@ -88,11 +88,11 @@ and outputs a discrete histogram as a function of them at the end of the simulat TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 + ARG=r1,r2 USE_ALL_DATA KERNEL=DISCRETE - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 LABEL=hh ... HISTOGRAM @@ -106,11 +106,11 @@ and outputs the histogram accumulated thus far every 100000 steps. TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + ARG=r1,r2 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 - BANDWIDTH=0.05,0.05 + BANDWIDTH=0.05,0.05 LABEL=hh ... HISTOGRAM @@ -119,18 +119,18 @@ DUMPGRID GRID=hh FILE=histo STRIDE=100000 The following input monitors two torsional angles during a simulation and outputs a separate histogram for each 100000 steps worth of trajectory. -Notice how the CLEAR keyword is used here and how it is not used in the +Notice how the CLEAR keyword is used here and how it is not used in the previous example. \verbatim TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 CLEAR=100000 - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + ARG=r1,r2 CLEAR=100000 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 - BANDWIDTH=0.05,0.05 + BANDWIDTH=0.05,0.05 GRID_WFILE=histo LABEL=hh ... HISTOGRAM @@ -144,19 +144,19 @@ DUMPGRID GRID=hh FILE=histo STRIDE=100000 class DumpGrid : public GridPrintingBase { public: static void registerKeywords( Keywords& keys ); - explicit DumpGrid(const ActionOptions&ao); + explicit DumpGrid(const ActionOptions&ao); void printGrid( OFile& ofile ) const ; }; PLUMED_REGISTER_ACTION(DumpGrid,"DUMPGRID") -void DumpGrid::registerKeywords( Keywords& keys ){ +void DumpGrid::registerKeywords( Keywords& keys ) { GridPrintingBase::registerKeywords( keys ); } DumpGrid::DumpGrid(const ActionOptions&ao): -Action(ao), -GridPrintingBase(ao) + Action(ao), + GridPrintingBase(ao) { if( ingrid->getType()!="flat" ) error("cannot dump grid of type " + ingrid->getType() + " using DUMPGRID"); fmt = " " + fmt; checkRead(); @@ -164,33 +164,33 @@ GridPrintingBase(ao) void DumpGrid::printGrid( OFile& ofile ) const { ofile.addConstantField("normalisation"); - for(unsigned i=0;igetDimension();++i){ - ofile.addConstantField("min_" + ingrid->getComponentName(i) ); - ofile.addConstantField("max_" + ingrid->getComponentName(i) ); - ofile.addConstantField("nbins_" + ingrid->getComponentName(i) ); - ofile.addConstantField("periodic_" + ingrid->getComponentName(i) ); + for(unsigned i=0; igetDimension(); ++i) { + ofile.addConstantField("min_" + ingrid->getComponentName(i) ); + ofile.addConstantField("max_" + ingrid->getComponentName(i) ); + ofile.addConstantField("nbins_" + ingrid->getComponentName(i) ); + ofile.addConstantField("periodic_" + ingrid->getComponentName(i) ); } std::vector xx( ingrid->getDimension() ); std::vector ind( ingrid->getDimension() ); - for(unsigned i=0;igetNumberOfPoints();++i){ - ingrid->getIndices( i, ind ); - if(i>0 && ingrid->getDimension()==2 && ind[ingrid->getDimension()-2]==0) ofile.printf("\n"); - ofile.fmtField(fmt); ofile.printField("normalisation", ingrid->getNorm() ); - for(unsigned j=0;jgetDimension();++j){ - ofile.printField("min_" + ingrid->getComponentName(j), ingrid->getMin()[j] ); - ofile.printField("max_" + ingrid->getComponentName(j), ingrid->getMax()[j] ); - ofile.printField("nbins_" + ingrid->getComponentName(j), static_cast(ingrid->getNbin()[j]) ); - if( ingrid->isPeriodic(j) ) ofile.printField("periodic_" + ingrid->getComponentName(j), "true" ); - else ofile.printField("periodic_" + ingrid->getComponentName(j), "false" ); - } - // Retrieve and print the grid coordinates - ingrid->getGridPointCoordinates(i, xx ); - for(unsigned j=0;jgetDimension();++j){ ofile.fmtField(fmt); ofile.printField(ingrid->getComponentName(j),xx[j]); } - for(unsigned j=0;jgetNumberOfQuantities();++j){ - ofile.fmtField(fmt); ofile.printField(ingrid->arg_names[ingrid->dimension+j], ingrid->getGridElement( i, j ) ); - } - ofile.printField(); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + ingrid->getIndices( i, ind ); + if(i>0 && ingrid->getDimension()==2 && ind[ingrid->getDimension()-2]==0) ofile.printf("\n"); + ofile.fmtField(fmt); ofile.printField("normalisation", ingrid->getNorm() ); + for(unsigned j=0; jgetDimension(); ++j) { + ofile.printField("min_" + ingrid->getComponentName(j), ingrid->getMin()[j] ); + ofile.printField("max_" + ingrid->getComponentName(j), ingrid->getMax()[j] ); + ofile.printField("nbins_" + ingrid->getComponentName(j), static_cast(ingrid->getNbin()[j]) ); + if( ingrid->isPeriodic(j) ) ofile.printField("periodic_" + ingrid->getComponentName(j), "true" ); + else ofile.printField("periodic_" + ingrid->getComponentName(j), "false" ); + } + // Retrieve and print the grid coordinates + ingrid->getGridPointCoordinates(i, xx ); + for(unsigned j=0; jgetDimension(); ++j) { ofile.fmtField(fmt); ofile.printField(ingrid->getComponentName(j),xx[j]); } + for(unsigned j=0; jgetNumberOfQuantities(); ++j) { + ofile.fmtField(fmt); ofile.printField(ingrid->arg_names[ingrid->dimension+j], ingrid->getGridElement( i, j ) ); + } + ofile.printField(); } } diff --git a/src/gridtools/FindContour.cpp b/src/gridtools/FindContour.cpp index 1fb94949af..a58e4f650e 100644 --- a/src/gridtools/FindContour.cpp +++ b/src/gridtools/FindContour.cpp @@ -29,14 +29,14 @@ /* Find an isocontour in a smooth function. -As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate -a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables +As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate +a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables or it might be a phase field that has been calcualted using \ref MULTICOLVARDENS. If this function has one or two input arguments it is relatively straightforward to plot the function. If by contrast the data has a three or more dimensions -it can be difficult to visualize. +it can be difficult to visualize. -This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour -where the function takes a particular values. In other words, for the function \f$f(x,y)\f$ this action would find a set +This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour +where the function takes a particular values. In other words, for the function \f$f(x,y)\f$ this action would find a set of points \f$\{x_c,y_c\}\f$ that have: \f[ @@ -55,14 +55,14 @@ Furthermore, the topology of the contour will be determined by the algorithm and \par Examples The input below allows you to calculate something akin to a Willard-Chandler dividing surface \cite wcsurface. -The simulation cell in this case contains a solid phase and a liquid phase. The Willard-Chandler surface is the +The simulation cell in this case contains a solid phase and a liquid phase. The Willard-Chandler surface is the surface that separates the parts of the box containing the solid from the parts containing the liquid. To compute the position of this surface the \ref FCCUBIC symmetry function is calculated for each of the atoms in the system from on the geometry of the atoms in the first coordination sphere of each of the atoms. These quantities are then transformed using a switching function. -This procedure generates a single number for each atom in the system and this quantity has a value of one for atoms that are in +This procedure generates a single number for each atom in the system and this quantity has a value of one for atoms that are in parts of the box that resemble the solid structure and zero for atoms that are in parts of the box that resemble the liquid. The position of a virtual atom is then computed using \ref CENTER_OF_MULTICOLVAR and a phase field model is constructed using -\ref MULTICOLVARDENS. These procedure ensures that we have a continuous function that gives a measure of the average degree of +\ref MULTICOLVARDENS. These procedure ensures that we have a continuous function that gives a measure of the average degree of solidness at each point in the simulation cell. The Willard-Chandler dividing surface is calculated by finding a a set of points at which the value of this phase field is equal to 0.5. This set of points is output to file called mycontour.dat. A new contour is found on every single step for each frame that is read in. @@ -70,20 +70,20 @@ is found on every single step for each frame that is read in. \verbatim UNITS NATURAL FCCUBIC ... - SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} + SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} ALPHA=27 PHI=0.0 THETA=-1.5708 PSI=-2.35619 LABEL=fcc ... FCCUBIC tfcc: MTRANSFORM_MORE DATA=fcc SWITCH={SMAP R_0=0.5 A=8 B=8} center: CENTER_OF_MULTICOLVAR DATA=tfcc -MULTICOLVARDENS ... - DATA=tfcc ORIGIN=center DIR=xyz LABEL=dens +MULTICOLVARDENS ... + DATA=tfcc ORIGIN=center DIR=xyz LABEL=dens NBINS=80,80,80 BANDWIDTH=1.0,1.0,1.0 STRIDE=25 LABEL=dens STRIDE=1 CLEAR=1 ... MULTICOLVARDENS -FIND_CONTOUR GRID=dens CONTOUR=0.5 FILE=mycontour.dat +FIND_CONTOUR GRID=dens CONTOUR=0.5 FILE=mycontour.dat \endverbatim */ @@ -96,7 +96,7 @@ class FindContour : public ContourFindingBase { private: bool firsttime; unsigned gbuffer; -/// Stuff for output +/// Stuff for output OFile of; double lenunit; std::string fmt_xyz; @@ -107,7 +107,7 @@ class FindContour : public ContourFindingBase { explicit FindContour(const ActionOptions&ao); bool checkAllActive() const { return gbuffer==0; } void prepareForAveraging(); - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } unsigned getNumberOfQuantities() const { return 1 + ingrid->getDimension(); } void compute( const unsigned& current, MultiValue& myvals ) const ; void finishAveraging(); @@ -115,7 +115,7 @@ class FindContour : public ContourFindingBase { PLUMED_REGISTER_ACTION(FindContour,"FIND_CONTOUR") -void FindContour::registerKeywords( Keywords& keys ){ +void FindContour::registerKeywords( Keywords& keys ) { ContourFindingBase::registerKeywords( keys ); // We want a better way of doing this bit keys.add("compulsory","BUFFER","0","number of buffer grid points around location where grid was found on last step. If this is zero the full grid is calculated on each step"); @@ -125,9 +125,9 @@ void FindContour::registerKeywords( Keywords& keys ){ } FindContour::FindContour(const ActionOptions&ao): -Action(ao), -ContourFindingBase(ao), -firsttime(true) + Action(ao), + ContourFindingBase(ao), + firsttime(true) { parse("BUFFER",gbuffer); @@ -137,20 +137,20 @@ firsttime(true) if( file.length()==0 ) error("name out output file was not specified"); std::string type=Tools::extension(file); log<<" file name "<0){ - int p; Tools::convert(precision,p); - log<<" with precision "<0) { + int p; Tools::convert(precision,p); + log<<" with precision "<getDimension()*ingrid->getNumberOfPoints();++i) addTaskToList( i ); + if( firsttime ) { + for(unsigned i=0; igetDimension()*ingrid->getNumberOfPoints(); ++i) addTaskToList( i ); } firsttime=false; deactivateAllTasks(); @@ -171,34 +171,34 @@ void FindContour::prepareForAveraging(){ std::vector ind( ingrid->getDimension() ); std::vector ones( ingrid->getDimension(), 1 ); unsigned num_neighbours; std::vector neighbours; - for(unsigned i=0;igetNumberOfPoints();++i){ - // Ensure inactive grid points are ignored - if( ingrid->inactive(i) ) continue; - - // Get the index of the current grid point - ingrid->getIndices( i, ind ); - ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); - bool cycle=false; - for(unsigned j=0;jinactive( neighbours[j]) ){ cycle=true; break; } - } - if( cycle ) continue; - - // Get the value of a point on the grid - double val1=getFunctionValue( i ) - contour; - bool edge=false; - for(unsigned j=0;jgetDimension();++j){ - // Make sure we don't search at the edge of the grid - if( !ingrid->isPeriodic(j) && (ind[j]+1)==nbin[j] ) continue; - else if( (ind[j]+1)==nbin[j] ){ edge=true; ind[j]=0; } - else ind[j]+=1; - double val2=getFunctionValue( ind ) - contour; - if( val1*val2<0 ) taskFlags[ ingrid->getDimension()*i + j ] = 1; - if( ingrid->isPeriodic(j) && edge ){ edge=false; ind[j]=nbin[j]-1; } - else ind[j]-=1; - } + for(unsigned i=0; igetNumberOfPoints(); ++i) { + // Ensure inactive grid points are ignored + if( ingrid->inactive(i) ) continue; + + // Get the index of the current grid point + ingrid->getIndices( i, ind ); + ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); + bool cycle=false; + for(unsigned j=0; jinactive( neighbours[j]) ) { cycle=true; break; } + } + if( cycle ) continue; + + // Get the value of a point on the grid + double val1=getFunctionValue( i ) - contour; + bool edge=false; + for(unsigned j=0; jgetDimension(); ++j) { + // Make sure we don't search at the edge of the grid + if( !ingrid->isPeriodic(j) && (ind[j]+1)==nbin[j] ) continue; + else if( (ind[j]+1)==nbin[j] ) { edge=true; ind[j]=0; } + else ind[j]+=1; + double val2=getFunctionValue( ind ) - contour; + if( val1*val2<0 ) taskFlags[ ingrid->getDimension()*i + j ] = 1; + if( ingrid->isPeriodic(j) && edge ) { edge=false; ind[j]=nbin[j]-1; } + else ind[j]-=1; + } } - lockContributors(); + lockContributors(); } void FindContour::compute( const unsigned& current, MultiValue& myvals ) const { @@ -209,40 +209,40 @@ void FindContour::compute( const unsigned& current, MultiValue& myvals ) const { // Retrieve the direction we are searching for the contour unsigned gdir = current%(ingrid->getDimension() ); - std::vector direction( ingrid->getDimension() , 0 ); + std::vector direction( ingrid->getDimension(), 0 ); direction[gdir] = 0.999999999*ingrid->getGridSpacing()[gdir]; // Now find the contour findContour( direction, point ); // And transfer to the store data vessel - for(unsigned i=0;igetDimension();++i) myvals.setValue( 1+i, point[i] ); + for(unsigned i=0; igetDimension(); ++i) myvals.setValue( 1+i, point[i] ); } -void FindContour::finishAveraging(){ +void FindContour::finishAveraging() { // And update the list of active grid points - if( gbuffer>0 ){ - std::vector neighbours; unsigned num_neighbours; - std::vector ugrid_indices( ingrid->getDimension() ); - std::vector active( ingrid->getNumberOfPoints(), false ); - std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); - for(unsigned i=0;igetDimension() ); - // Get the indices of this point - ingrid->getIndices( ipoint, ugrid_indices ); - // Now activate buffer region - ingrid->getNeighbors( ugrid_indices , gbuffer_vec, num_neighbours, neighbours ); - for(unsigned n=0;nactivateThesePoints( active ); + if( gbuffer>0 ) { + std::vector neighbours; unsigned num_neighbours; + std::vector ugrid_indices( ingrid->getDimension() ); + std::vector active( ingrid->getNumberOfPoints(), false ); + std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); + for(unsigned i=0; igetDimension() ); + // Get the indices of this point + ingrid->getIndices( ipoint, ugrid_indices ); + // Now activate buffer region + ingrid->getNeighbors( ugrid_indices, gbuffer_vec, num_neighbours, neighbours ); + for(unsigned n=0; nactivateThesePoints( active ); } std::vector point( 1 + ingrid->getDimension() ); of.printf("%u\n",mydata->getNumberOfStoredValues()); of.printf("Points found on isocontour\n"); - for(unsigned i=0;igetNumberOfStoredValues();++i){ - mydata->retrieveSequentialValue( i, false, point ); of.printf("X"); - for(unsigned j=0;jgetDimension();++j) of.printf( (" " + fmt_xyz).c_str(), lenunit*point[1+j] ); - of.printf("\n"); + for(unsigned i=0; igetNumberOfStoredValues(); ++i) { + mydata->retrieveSequentialValue( i, false, point ); of.printf("X"); + for(unsigned j=0; jgetDimension(); ++j) of.printf( (" " + fmt_xyz).c_str(), lenunit*point[1+j] ); + of.printf("\n"); } } diff --git a/src/gridtools/FindContourSurface.cpp b/src/gridtools/FindContourSurface.cpp index 6a83c0abdc..ce24d757f1 100644 --- a/src/gridtools/FindContourSurface.cpp +++ b/src/gridtools/FindContourSurface.cpp @@ -26,14 +26,14 @@ /* Find an isocontour by searching along either the x, y or z direction. -As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate -a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables +As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate +a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables or it might be a phase field that has been calcualted using \ref MULTICOLVARDENS. If this function has one or two input -arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be +arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be difficult to visualize. -This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour -wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set +This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour +wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set of points \f$\{x_c,y_c,z_c\}\f$ that have: \f[ @@ -41,34 +41,34 @@ f(x_c,y_c,z_c) - c = 0 \f] where \f$c\f$ is some constant value that is specified by the user. The points on this contour are find by searching along lines -that run parallel to the \f$x\f$, \f$y\f$ or \f$z\f$ axis of the simulation cell. The result is, therefore, a two dimensional -function evaluated on a grid that gives us the height of the interface as a function of two coordinates. +that run parallel to the \f$x\f$, \f$y\f$ or \f$z\f$ axis of the simulation cell. The result is, therefore, a two dimensional +function evaluated on a grid that gives us the height of the interface as a function of two coordinates. -It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to -find the full set of contour points if the contour does not have the same topology as an infinite plane. If you are uncertain that the isocontours in your +It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to +find the full set of contour points if the contour does not have the same topology as an infinite plane. If you are uncertain that the isocontours in your function have the appropriate topology you should use \ref FIND_CONTOUR in place of \ref FIND_CONTOUR_SURFACE. \par Examples -The input shown below was used to analyse the results from a simulation of an interface between solid and molten Lennard Jones. The interface between -the solid and the liquid was set up in the plane perpendicular to the \f$z\f$ direction of the simulation cell. The input below calculates something -akin to a Willard-Chandler dividing surface \cite wcsurface between the solid phase and the liquid phase. There are two of these interfaces within the -simulation box because of the periodic boundary conditions but we were able to determine that one of these two surfaces lies in a particular part of the -simulation box. The input below detects the height profile of one of these two interfaces. It does so by computing a phase field average of the +The input shown below was used to analyse the results from a simulation of an interface between solid and molten Lennard Jones. The interface between +the solid and the liquid was set up in the plane perpendicular to the \f$z\f$ direction of the simulation cell. The input below calculates something +akin to a Willard-Chandler dividing surface \cite wcsurface between the solid phase and the liquid phase. There are two of these interfaces within the +simulation box because of the periodic boundary conditions but we were able to determine that one of these two surfaces lies in a particular part of the +simulation box. The input below detects the height profile of one of these two interfaces. It does so by computing a phase field average of the \ref FCCUBIC symmetry function using the \ref MULTICOLVARDENS action. Notice that we use the fact that we know roughly where the interface is when specifying -how this phase field is to be calculated and specify the region over the \f$z\f$-axis in which we are going to search for the phase field in the line defining +how this phase field is to be calculated and specify the region over the \f$z\f$-axis in which we are going to search for the phase field in the line defining the \ref MULTICOLVARDENS. Once we have calculated the phase field we search for contour points on the lines that run parallel to the \f$z\f$-direction of the cell -box using the FIND_CONTOUR_SURFACE command. The final result is a \f$14 \times 14\f$ grid of values for the height of the interface as a function of the \f$(x,y)\f$ +box using the FIND_CONTOUR_SURFACE command. The final result is a \f$14 \times 14\f$ grid of values for the height of the interface as a function of the \f$(x,y)\f$ position. This grid is then output to a file called contour2.dat. Notice that the commands below calculate the instantaneous position of the surface separating the solid and liquid and that as such the accumulated average is cleared -on every step. +on every step. \verbatim UNITS NATURAL FCCUBIC ... - SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} + SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} ALPHA=27 PHI=0.0 THETA=-1.5708 PSI=-2.35619 LABEL=fcc ... FCCUBIC @@ -105,17 +105,17 @@ class FindContourSurface : public ContourFindingBase { PLUMED_REGISTER_ACTION(FindContourSurface,"FIND_CONTOUR_SURFACE") -void FindContourSurface::registerKeywords( Keywords& keys ){ +void FindContourSurface::registerKeywords( Keywords& keys ) { ContourFindingBase::registerKeywords( keys ); keys.add("compulsory","SEARCHDIR","In which directions do you wish to search for the contour."); keys.add("compulsory","BUFFER","0","number of buffer grid points around location where grid was found on last step. If this is zero the full grid is calculated on each step"); } FindContourSurface::FindContourSurface(const ActionOptions&ao): -Action(ao), -ContourFindingBase(ao), -firsttime(true), -ones(ingrid->getDimension(),1) + Action(ao), + ContourFindingBase(ao), + firsttime(true), + ones(ingrid->getDimension(),1) { if( ingrid->getDimension()<2 ) error("cannot find dividing surface if input grid is one dimensional"); @@ -125,85 +125,85 @@ ones(ingrid->getDimension(),1) checkRead(); unsigned n=0; gdirs.resize( ingrid->getDimension()-1 ); - for(unsigned i=0;igetDimension();++i){ - if( ingrid->getComponentName(i)==dir ){ - dir_n=i; - } else { - if( n==gdirs.size() ) error("could not find " + dir + " direction in input grid"); - gdirs[n]=i; n++; - } + for(unsigned i=0; igetDimension(); ++i) { + if( ingrid->getComponentName(i)==dir ) { + dir_n=i; + } else { + if( n==gdirs.size() ) error("could not find " + dir + " direction in input grid"); + gdirs[n]=i; n++; + } } if( n!=(ingrid->getDimension()-1) ) error("output of grid is not understood"); // Create the input from the old string std::string vstring = "COMPONENTS=" + getLabel() + " COORDINATES=" + ingrid->getComponentName( gdirs[0] ); - for(unsigned i=1;igetComponentName( gdirs[i] ); + for(unsigned i=1; igetComponentName( gdirs[i] ); vstring += " PBC="; if( ingrid->isPeriodic(gdirs[0]) ) vstring+="T"; else vstring+="F"; - for(unsigned i=1;iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; + for(unsigned i=1; iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; } - createGrid( "grid", vstring ); mygrid->setNoDerivatives(); + createGrid( "grid", vstring ); mygrid->setNoDerivatives(); setAveragingAction( mygrid, true ); } -void FindContourSurface::clearAverage(){ +void FindContourSurface::clearAverage() { // Set the boundaries of the output grid std::vector fspacing; std::vector snbins( ingrid->getDimension()-1 ); std::vector smin( ingrid->getDimension()-1 ), smax( ingrid->getDimension()-1 ); - for(unsigned i=0;igetMin()[gdirs[i]]; smax[i]=ingrid->getMax()[gdirs[i]]; - snbins[i]=ingrid->getNbin()[gdirs[i]]; - } + for(unsigned i=0; igetMin()[gdirs[i]]; smax[i]=ingrid->getMax()[gdirs[i]]; + snbins[i]=ingrid->getNbin()[gdirs[i]]; + } mygrid->setBounds( smin, smax, snbins, fspacing); resizeFunctions(); ActionWithAveraging::clearAverage(); } -void FindContourSurface::prepareForAveraging(){ +void FindContourSurface::prepareForAveraging() { // Create a task list if first time - if( firsttime ){ - std::vector find( ingrid->getDimension() ); - std::vector ind( mygrid->getDimension() ); - for(unsigned i=0;igetNumberOfPoints();++i){ - find.assign( find.size(), 0 ); mygrid->getIndices( i, ind ); - for(unsigned j=0;jgetIndex(find) ); - } - // And prepare the task list - deactivateAllTasks(); - for(unsigned i=0;igetDimension(), 0 ); - direction[dir_n] = 0.999999999*ingrid->getGridSpacing()[dir_n]; + if( firsttime ) { + std::vector find( ingrid->getDimension() ); + std::vector ind( mygrid->getDimension() ); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + find.assign( find.size(), 0 ); mygrid->getIndices( i, ind ); + for(unsigned j=0; jgetIndex(find) ); + } + // And prepare the task list + deactivateAllTasks(); + for(unsigned i=0; igetDimension(), 0 ); + direction[dir_n] = 0.999999999*ingrid->getGridSpacing()[dir_n]; } } -void FindContourSurface::finishAveraging(){ +void FindContourSurface::finishAveraging() { ContourFindingBase::finishAveraging(); // And update the list of active grid points - if( gbuffer>0 ){ - std::vector dx( ingrid->getGridSpacing() ); - std::vector point( ingrid->getDimension() ); - std::vector lpoint( mygrid->getDimension() ); - std::vector neighbours; unsigned num_neighbours; - std::vector ugrid_indices( ingrid->getDimension() ); - std::vector active( ingrid->getNumberOfPoints(), false ); - std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); - for(unsigned i=0;igetNumberOfPoints();++i){ - // Retrieve the coordinates of this grid point - mygrid->getGridPointCoordinates( i, lpoint ); - point[dir_n] = mygrid->getGridElement( i, 0 ); - // 0.5*dx added here to prevent problems with flooring of grid points - for(unsigned j=0;jgetIndices( point, ugrid_indices ); - // Now activate buffer region - ingrid->getNeighbors( ugrid_indices , gbuffer_vec, num_neighbours, neighbours ); - for(unsigned n=0;nactivateThesePoints( active ); + if( gbuffer>0 ) { + std::vector dx( ingrid->getGridSpacing() ); + std::vector point( ingrid->getDimension() ); + std::vector lpoint( mygrid->getDimension() ); + std::vector neighbours; unsigned num_neighbours; + std::vector ugrid_indices( ingrid->getDimension() ); + std::vector active( ingrid->getNumberOfPoints(), false ); + std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + // Retrieve the coordinates of this grid point + mygrid->getGridPointCoordinates( i, lpoint ); + point[dir_n] = mygrid->getGridElement( i, 0 ); + // 0.5*dx added here to prevent problems with flooring of grid points + for(unsigned j=0; jgetIndices( point, ugrid_indices ); + // Now activate buffer region + ingrid->getNeighbors( ugrid_indices, gbuffer_vec, num_neighbours, neighbours ); + for(unsigned n=0; nactivateThesePoints( active ); } firsttime=false; } @@ -212,51 +212,51 @@ void FindContourSurface::compute( const unsigned& current, MultiValue& myvals ) std::vector neighbours; unsigned num_neighbours; unsigned nfound=0; double minv=0, minp; std::vector bins_n( ingrid->getNbin() ); unsigned shiftn=current; std::vector ind( ingrid->getDimension() ); std::vector point( ingrid->getDimension() ); -#ifndef DNDEBUG - std::vector oind( mygrid->getDimension() ); mygrid->getIndices( current, oind ); +#ifndef DNDEBUG + std::vector oind( mygrid->getDimension() ); mygrid->getIndices( current, oind ); #endif - for(unsigned i=0;i base_ind( ingrid->getDimension() ); ingrid->getIndices( shiftn, base_ind ); - for(unsigned j=0;j base_ind( ingrid->getDimension() ); ingrid->getIndices( shiftn, base_ind ); + for(unsigned j=0; jinactive( shiftn ) ){ shiftn += ingrid->getStride()[dir_n]; continue; } - // Get the index of the current grid point - ingrid->getIndices( shiftn, ind ); - // Exit if we are at the edge of the grid - if( !ingrid->isPeriodic(dir_n) && (ind[dir_n]+1)==bins_n[dir_n] ){ - shiftn += ingrid->getStride()[dir_n]; continue; - } - - // Ensure points with inactive neighbours are ignored - ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); - bool cycle=false; - for(unsigned j=0;jinactive( neighbours[j]) ){ cycle=true; break; } - } - if( cycle ){ shiftn += ingrid->getStride()[dir_n]; continue; } - - // Now get the function value at two points - double val1=getFunctionValue( shiftn ) - contour; double val2; - if( (ind[dir_n]+1)==bins_n[dir_n] ) val2 = getFunctionValue( current ) - contour; - else val2=getFunctionValue( shiftn + ingrid->getStride()[dir_n] ) - contour; - - // Check if the minimum is bracketed - if( val1*val2<0 ){ - ingrid->getGridPointCoordinates( shiftn, point ); findContour( direction, point ); - minp=point[dir_n]; nfound++; break; - } - - - // This moves us on to the next point - shiftn += ingrid->getStride()[dir_n]; + // Ensure inactive grid points are ignored + if( ingrid->inactive( shiftn ) ) { shiftn += ingrid->getStride()[dir_n]; continue; } + // Get the index of the current grid point + ingrid->getIndices( shiftn, ind ); + // Exit if we are at the edge of the grid + if( !ingrid->isPeriodic(dir_n) && (ind[dir_n]+1)==bins_n[dir_n] ) { + shiftn += ingrid->getStride()[dir_n]; continue; + } + + // Ensure points with inactive neighbours are ignored + ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); + bool cycle=false; + for(unsigned j=0; jinactive( neighbours[j]) ) { cycle=true; break; } + } + if( cycle ) { shiftn += ingrid->getStride()[dir_n]; continue; } + + // Now get the function value at two points + double val1=getFunctionValue( shiftn ) - contour; double val2; + if( (ind[dir_n]+1)==bins_n[dir_n] ) val2 = getFunctionValue( current ) - contour; + else val2=getFunctionValue( shiftn + ingrid->getStride()[dir_n] ) - contour; + + // Check if the minimum is bracketed + if( val1*val2<0 ) { + ingrid->getGridPointCoordinates( shiftn, point ); findContour( direction, point ); + minp=point[dir_n]; nfound++; break; + } + + + // This moves us on to the next point + shiftn += ingrid->getStride()[dir_n]; } - if( nfound==0 ){ - std::string num; Tools::convert( getStep(), num ); - error("On step " + num + " failed to find required grid point"); + if( nfound==0 ) { + std::string num; Tools::convert( getStep(), num ); + error("On step " + num + " failed to find required grid point"); } - myvals.setValue( 1, minp ); + myvals.setValue( 1, minp ); } } diff --git a/src/gridtools/FindSphericalContour.cpp b/src/gridtools/FindSphericalContour.cpp index 5d99abeda7..a2ee2aa862 100644 --- a/src/gridtools/FindSphericalContour.cpp +++ b/src/gridtools/FindSphericalContour.cpp @@ -27,59 +27,59 @@ /* Find an isocontour in a three dimensional grid by searching over a Fibonacci sphere. -As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate -a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables +As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate +a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables or it might be a phase field that has been calcualted using \ref MULTICOLVARDENS. If this function has one or two input -arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be +arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be difficult to visualize. -This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour -wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set +This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour +wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set of points \f$\{x_c,y_c,z_c\}\f$ that have: \f[ f(x_c,y_c,z_c) - c = 0 \f] -where \f$c\f$ is some constant value that is specified by the user. The points on this contour are find by searching along a -set of equally spaced radii of a sphere that centered at on particular, user-speciified atom or virtual atom. To ensure that -these search radii are equally spaced on the surface of the sphere the search directions are generated by using a fibonacci +where \f$c\f$ is some constant value that is specified by the user. The points on this contour are find by searching along a +set of equally spaced radii of a sphere that centered at on particular, user-speciified atom or virtual atom. To ensure that +these search radii are equally spaced on the surface of the sphere the search directions are generated by using a fibonacci spiral projected on a sphere. In other words, the search directions are given by: \f[ -\mathbf{r}_i = \left( +\mathbf{r}_i = \left( \begin{matrix} \sqrt{1 - y^2} \cos(\phi) \\ \frac{2i}{n} - 1 + \frac{1}{n} \\ \sqrt{1 - y^2} \sin(\phi) -\end{matrix} +\end{matrix} \right) \f] -where \f$y\f$ is the quantity second component of the vector defined above, \f$n\f$ is the number of directions to look in and \f$\phi\f$ is +where \f$y\f$ is the quantity second component of the vector defined above, \f$n\f$ is the number of directions to look in and \f$\phi\f$ is \f[ \phi = \mod(i + R, n) \pi ( 3 - \sqrt{5} ) \f] -where \f$R\f$ is a random variable between 0 and \f$n-1\f$ that is generated during the read in of the input file and that is fixed during -the whole calculation. +where \f$R\f$ is a random variable between 0 and \f$n-1\f$ that is generated during the read in of the input file and that is fixed during +the whole calculation. -It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to -find the full set of contour points if the contour does not have the same topology as a sphere. If you are uncertain that the isocontours in your -function have a spherical topology you should use \ref FIND_CONTOUR in place of \ref FIND_SPHERICAL_CONTOUR. +It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to +find the full set of contour points if the contour does not have the same topology as a sphere. If you are uncertain that the isocontours in your +function have a spherical topology you should use \ref FIND_CONTOUR in place of \ref FIND_SPHERICAL_CONTOUR. \par Examples -The following input demonstrates how this action can be used. The input here is used to study the shape of a droplet that has been formed during the +The following input demonstrates how this action can be used. The input here is used to study the shape of a droplet that has been formed during the condensation of Lennard Jones from the vapour. The input below achieves this by calculating the coordination numbers of all the atoms within the gas. Obviously, those atoms within the droplet will have a large value for the coordination number while the isolated atoms in the gas will have a low value. As such we can detect the sizes of the droplets by constructing a \ref CONTACT_MATRIX whose \f$ij\f$ element tells us whether atom \f$i\f$ and atom \f$j\f$ -have coordination number that is greater that two. The atoms within the various droplets within the system can then be found by performing a +have coordination number that is greater that two. The atoms within the various droplets within the system can then be found by performing a \ref DFSCLUSTERING on this matrix to detect the connected components. We can take the largest of these connected components and find the center of the droplet -by exploiting the functionality within \ref CENTER_OF_MULTICOLVAR. We can then construct a phase field based on the positions of the atoms in the largest +by exploiting the functionality within \ref CENTER_OF_MULTICOLVAR. We can then construct a phase field based on the positions of the atoms in the largest cluster and the values of the coordination numbers of these atoms. The final line in the input then finds the a set of points on the dividing surface that separates -teh droplet from the surrounding gas. The value of the phase field on this isocontour is equal to 0.75. +teh droplet from the surrounding gas. The value of the phase field on this isocontour is equal to 0.75. \verbatim # Calculate coordination numbers @@ -119,7 +119,7 @@ class FindSphericalContour : public ContourFindingBase { PLUMED_REGISTER_ACTION(FindSphericalContour,"FIND_SPHERICAL_CONTOUR") -void FindSphericalContour::registerKeywords( Keywords& keys ){ +void FindSphericalContour::registerKeywords( Keywords& keys ) { ContourFindingBase::registerKeywords( keys ); keys.add("compulsory","NPOINTS","the number of points for which we are looking for the contour"); keys.add("compulsory","INNER_RADIUS","the minimum radius on which to look for the contour"); @@ -128,8 +128,8 @@ void FindSphericalContour::registerKeywords( Keywords& keys ){ } FindSphericalContour::FindSphericalContour(const ActionOptions&ao): -Action(ao), -ContourFindingBase(ao) + Action(ao), + ContourFindingBase(ao) { if( ingrid->getDimension()!=3 ) error("input grid must be three dimensional"); @@ -145,9 +145,9 @@ ContourFindingBase(ao) checkRead(); // Create a task list - for(unsigned i=0;igetGridPointCoordinates( current, direction ); // Now setup contour point on inner sphere - for(unsigned j=0;j<3;++j){ - contour_point[j] = min*direction[j]; - direction[j] = (max-min)*direction[j] / static_cast(nbins); + for(unsigned j=0; j<3; ++j) { + contour_point[j] = min*direction[j]; + direction[j] = (max-min)*direction[j] / static_cast(nbins); } bool found=false; - for(unsigned k=0;k fourier_params; public: static void registerKeywords( Keywords& keys ); - explicit FourierTransform(const ActionOptions&ao); + explicit FourierTransform(const ActionOptions&ao); #ifndef __PLUMED_HAS_FFTW - void performOperations( const bool& from_update ){} + void performOperations( const bool& from_update ) {} #else void performOperations( const bool& from_update ); #endif - void compute( const unsigned& , MultiValue& ) const {} - bool isPeriodic(){ return false; } + void compute( const unsigned&, MultiValue& ) const {} + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(FourierTransform,"FOURIER_TRANSFORM") -void FourierTransform::registerKeywords( Keywords& keys ){ +void FourierTransform::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.remove("BANDWIDTH"); keys.remove("KERNEL"); keys.add("optional","FT_TYPE","choose what kind of data you want as output on the grid. Possible values are: ABS = compute the complex modulus of Fourier coefficients (DEFAULT); NORM = compute the norm (i.e. ABS^2) of Fourier coefficients; COMPLEX = store the FFTW complex output on the grid (as a vector)."); keys.add("compulsory","FOURIER_PARAMETERS","default","what kind of normalization is applied to the output and if the Fourier transform in FORWARD or BACKWARD. This keyword takes the form FOURIER_PARAMETERS=A,B, where A and B can be 0, 1 or -1. The default values are A=1 (no normalization at all) and B=1 (forward FFT). Other possible choices for A are: " - "A=-1: normalize by the number of data, " - "A=0: normalize by the square root of the number of data (one forward and followed by backward FFT recover the original data). "); + "A=-1: normalize by the number of data, " + "A=0: normalize by the square root of the number of data (one forward and followed by backward FFT recover the original data). "); } FourierTransform::FourierTransform(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao), -real_output(true), -store_norm(false), -fourier_params(2) + Action(ao), + ActionWithInputGrid(ao), + real_output(true), + store_norm(false), + fourier_params(2) { #ifndef __PLUMED_HAS_FFTW error("this feature is only available if you compile PLUMED with FFTW"); @@ -108,58 +108,58 @@ fourier_params(2) // Get the type of FT parse("FT_TYPE",output_type); if (output_type.length()==0) { - log<<" keyword FT_TYPE unset. By default output grid will contain REAL Fourier coefficients\n"; + log<<" keyword FT_TYPE unset. By default output grid will contain REAL Fourier coefficients\n"; } else if ( output_type=="ABS" || output_type=="abs") { - log << " keyword FT_TYPE is '"<< output_type << "' : will compute the MODULUS of Fourier coefficients\n"; + log << " keyword FT_TYPE is '"<< output_type << "' : will compute the MODULUS of Fourier coefficients\n"; } else if ( output_type=="NORM" || output_type=="norm") { - log << " keyword FT_TYPE is '"<< output_type << "' : will compute the NORM of Fourier coefficients\n"; - store_norm=true; + log << " keyword FT_TYPE is '"<< output_type << "' : will compute the NORM of Fourier coefficients\n"; + store_norm=true; } else if ( output_type=="COMPLEX" || output_type=="complex" ) { - log<<" keyword FT_TYPE is '"<< output_type <<"' : output grid will contain the COMPLEX Fourier coefficients\n"; - real_output=false; + log<<" keyword FT_TYPE is '"<< output_type <<"' : output grid will contain the COMPLEX Fourier coefficients\n"; + real_output=false; } else error("keyword FT_TYPE unrecognized!"); // Normalize output? std::string params_str; parse("FOURIER_PARAMETERS",params_str); if (params_str=="default") { - fourier_params.assign( fourier_params.size(), 1 ); - log.printf(" default values of Fourier parameters A=%i, B=%i : the output will NOT be normalized and BACKWARD Fourier transform is computed \n", fourier_params[0],fourier_params[1]); + fourier_params.assign( fourier_params.size(), 1 ); + log.printf(" default values of Fourier parameters A=%i, B=%i : the output will NOT be normalized and BACKWARD Fourier transform is computed \n", fourier_params[0],fourier_params[1]); } else { - std::vector fourier_str = Tools::getWords(params_str, "\t\n ,"); - if (fourier_str.size()>2) error("FOURIER_PARAMETERS can take just two values"); - for (unsigned i=0; i1 || fourier_params[i]<-1) error("values accepted for FOURIER_PARAMETERS are only -1, 1 or 0"); - } - log.printf(" Fourier parameters are A=%i, B=%i \n", fourier_params[0],fourier_params[1]); + std::vector fourier_str = Tools::getWords(params_str, "\t\n ,"); + if (fourier_str.size()>2) error("FOURIER_PARAMETERS can take just two values"); + for (unsigned i=0; i1 || fourier_params[i]<-1) error("values accepted for FOURIER_PARAMETERS are only -1, 1 or 0"); + } + log.printf(" Fourier parameters are A=%i, B=%i \n", fourier_params[0],fourier_params[1]); } // Create the input from the old string std::string vstring; unsigned n=0; gdirs.resize( ingrid->getDimension() ); - for(unsigned i=0;igetDimension();++i){ - gdirs[n]=i; n++; + for(unsigned i=0; igetDimension(); ++i) { + gdirs[n]=i; n++; } - + plumed_assert( n==ingrid->getDimension() ); - - if (real_output) { - if (!store_norm) vstring="COMPONENTS=" + getLabel() + "_abs"; - else vstring="COMPONENTS=" + getLabel() + "_norm"; + + if (real_output) { + if (!store_norm) vstring="COMPONENTS=" + getLabel() + "_abs"; + else vstring="COMPONENTS=" + getLabel() + "_norm"; } else vstring="COMPONENTS=" + getLabel() + "_real," + getLabel() + "_imag"; - + // Set COORDINATES keyword vstring += " COORDINATES=" + ingrid->getComponentName( gdirs[0] ); for(unsigned i=1; igetComponentName( gdirs[i] ); - + // Set PBC keyword vstring += " PBC="; if( ingrid->isPeriodic(gdirs[0]) ) vstring+="T"; else vstring+="F"; - for(unsigned i=1; iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; + for(unsigned i=1; iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; } - + // Create a grid on which to store the fourier transform of the input grid createGrid( "grid", vstring ); @@ -171,97 +171,97 @@ fourier_params(2) } #ifdef __PLUMED_HAS_FFTW -void FourierTransform::performOperations( const bool& from_update ){ - - // Spacing of the real grid - std::vector g_spacing ( ingrid->getGridSpacing() ); - // Spacing of the k-grid - std::vector ft_spacing; - // Extents of the k-grid - std::vector ft_min( ingrid->getMin() ), ft_max( ingrid->getMax() ); - // Number of bins in the k-grid (equal to the number of bins in the real grid) - std::vector ft_bins ( ingrid->getNbin() ); - - for (unsigned i=0; igetDimension(); ++i) { - // Check PBC in current grid dimension - if( !ingrid->isPeriodic(i) ) ft_bins[i]++; - // Compute k-grid extents - double dmin, dmax; - Tools::convert(ft_min[i],dmin); Tools::convert(ft_max[i],dmax); - // We want to have the min of k-grid at point (0,0) - dmin=0.0; - dmax=2.0*pi*ft_bins[i]/( ingrid->getGridExtent(i) ); - Tools::convert(dmin,ft_min[i]); Tools::convert(dmax,ft_max[i]); - } - - // This is the actual setup of the k-grid - mygrid->setBounds( ft_min, ft_max, ft_bins, ft_spacing); resizeFunctions(); - - // *** CHECK CORRECT k-GRID BOUNDARIES *** - //log<<"Real grid boundaries: \n" - // <<" min_x: "<getMin()[0]<<" min_y: "<getMin()[1]<<"\n" - // <<" max_x: "<getMax()[0]<<" max_y: "<getMax()[1]<<"\n" - // <<"K-grid boundaries:"<<"\n" - // <<" min_x: "< N_input_data( ingrid->getNbin() ); - size_t fft_dimension=1; for(unsigned i=0; i( N_input_data[i] ); - - // FFT arrays - std::vector > input_data(fft_dimension), fft_data(fft_dimension); - - - // Fill real input with the data on the grid - std::vector ind( ingrid->getDimension() ); - for (unsigned i=0;igetNumberOfPoints();++i) { - // Get point indices - ingrid->getIndices(i, ind); - // Fill input data in row-major order - input_data[ind[0]*N_input_data[0]+ind[1]].real( getFunctionValue( i ) ); - input_data[ind[0]*N_input_data[0]+ind[1]].imag( 0.0 ); - } +void FourierTransform::performOperations( const bool& from_update ) { + + // Spacing of the real grid + std::vector g_spacing ( ingrid->getGridSpacing() ); + // Spacing of the k-grid + std::vector ft_spacing; + // Extents of the k-grid + std::vector ft_min( ingrid->getMin() ), ft_max( ingrid->getMax() ); + // Number of bins in the k-grid (equal to the number of bins in the real grid) + std::vector ft_bins ( ingrid->getNbin() ); + + for (unsigned i=0; igetDimension(); ++i) { + // Check PBC in current grid dimension + if( !ingrid->isPeriodic(i) ) ft_bins[i]++; + // Compute k-grid extents + double dmin, dmax; + Tools::convert(ft_min[i],dmin); Tools::convert(ft_max[i],dmax); + // We want to have the min of k-grid at point (0,0) + dmin=0.0; + dmax=2.0*pi*ft_bins[i]/( ingrid->getGridExtent(i) ); + Tools::convert(dmin,ft_min[i]); Tools::convert(dmax,ft_max[i]); + } + + // This is the actual setup of the k-grid + mygrid->setBounds( ft_min, ft_max, ft_bins, ft_spacing); resizeFunctions(); + + // *** CHECK CORRECT k-GRID BOUNDARIES *** + //log<<"Real grid boundaries: \n" + // <<" min_x: "<getMin()[0]<<" min_y: "<getMin()[1]<<"\n" + // <<" max_x: "<getMax()[0]<<" max_y: "<getMax()[1]<<"\n" + // <<"K-grid boundaries:"<<"\n" + // <<" min_x: "<(&input_data[0]), reinterpret_cast(&fft_data[0]), fourier_params[1], FFTW_ESTIMATE); - - // Compute FT - fftw_execute( plan_complex ); - // Compute the normalization constant - double norm=1.0; - for (unsigned i=0; i N_out_data ( mygrid->getNbin() ); - std::vector out_ind ( mygrid->getDimension() ); - for(unsigned i=0; igetNumberOfPoints(); ++i){ - mygrid->getIndices( i, out_ind ); - if (real_output) { - double ft_value; - // Compute abs/norm and fix normalization - if (!store_norm) ft_value=std::abs( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); - else ft_value=std::norm( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); - // Set the value - mygrid->setGridElement( i, 0, ft_value ); - } else { - double ft_value_real, ft_value_imag; - ft_value_real=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].real() / norm; - ft_value_imag=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].imag() / norm; - // Set values - mygrid->setGridElement( i, 0, ft_value_real); - mygrid->setGridElement( i, 1, ft_value_imag); - } + // Get the size of the input data arrays (to allocate FFT data) + std::vector N_input_data( ingrid->getNbin() ); + size_t fft_dimension=1; for(unsigned i=0; i( N_input_data[i] ); + + // FFT arrays + std::vector > input_data(fft_dimension), fft_data(fft_dimension); + + + // Fill real input with the data on the grid + std::vector ind( ingrid->getDimension() ); + for (unsigned i=0; igetNumberOfPoints(); ++i) { + // Get point indices + ingrid->getIndices(i, ind); + // Fill input data in row-major order + input_data[ind[0]*N_input_data[0]+ind[1]].real( getFunctionValue( i ) ); + input_data[ind[0]*N_input_data[0]+ind[1]].imag( 0.0 ); + } + + // *** HERE is the only clear limitation: I'm computing explicitly a 2D FT. It should not happen to deal with other than two-dimensional grid ... + fftw_plan plan_complex = fftw_plan_dft_2d(N_input_data[0], N_input_data[1], reinterpret_cast(&input_data[0]), reinterpret_cast(&fft_data[0]), fourier_params[1], FFTW_ESTIMATE); + + // Compute FT + fftw_execute( plan_complex ); + + // Compute the normalization constant + double norm=1.0; + for (unsigned i=0; i N_out_data ( mygrid->getNbin() ); + std::vector out_ind ( mygrid->getDimension() ); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + mygrid->getIndices( i, out_ind ); + if (real_output) { + double ft_value; + // Compute abs/norm and fix normalization + if (!store_norm) ft_value=std::abs( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); + else ft_value=std::norm( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); + // Set the value + mygrid->setGridElement( i, 0, ft_value ); + } else { + double ft_value_real, ft_value_imag; + ft_value_real=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].real() / norm; + ft_value_imag=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].imag() / norm; + // Set values + mygrid->setGridElement( i, 0, ft_value_real); + mygrid->setGridElement( i, 1, ft_value_imag); } - - // Free FFTW stuff - fftw_destroy_plan(plan_complex); - + } + + // Free FFTW stuff + fftw_destroy_plan(plan_complex); + } #endif diff --git a/src/gridtools/GridPrintingBase.cpp b/src/gridtools/GridPrintingBase.cpp index 90bf949735..616284d459 100644 --- a/src/gridtools/GridPrintingBase.cpp +++ b/src/gridtools/GridPrintingBase.cpp @@ -27,42 +27,42 @@ namespace PLMD { namespace gridtools { -void GridPrintingBase::registerKeywords( Keywords& keys ){ +void GridPrintingBase::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); keys.add("compulsory","GRID","the action that creates the grid you would like to output"); keys.add("compulsory","STRIDE","0","the frequency with which the grid should be output to the file. The default " - "value of 0 ensures that the grid is only output at the end of the trajectory"); + "value of 0 ensures that the grid is only output at the end of the trajectory"); keys.add("compulsory","FILE","density","the file on which to write the grid."); keys.add("optional","FMT","the format that should be used to output real numbers"); } GridPrintingBase::GridPrintingBase(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -fmt("%f") + Action(ao), + ActionPilot(ao), + fmt("%f") { std::string mlab; parse("GRID",mlab); vesselbase::ActionWithVessel* mves= plumed.getActionSet().selectWithLabel(mlab); if(!mves) error("action labelled " + mlab + " does not exist or does not have vessels"); addDependency(mves); - for(unsigned i=0;igetNumberOfVessels();++i){ - ingrid=dynamic_cast( mves->getPntrToVessel(i) ); - if( ingrid ) break; + for(unsigned i=0; igetNumberOfVessels(); ++i) { + ingrid=dynamic_cast( mves->getPntrToVessel(i) ); + if( ingrid ) break; } if( !ingrid ) error("input action does not calculate a grid"); - parse("FILE",filename); + parse("FILE",filename); if(filename.length()==0) error("name out output file was not specified"); log.printf(" outputting grid calculated by action %s to file named %s",mves->getLabel().c_str(), filename.c_str() ); - if( keywords.exists("FMT") ){ - parse("FMT",fmt); log.printf(" with format %s \n", fmt.c_str() ); + if( keywords.exists("FMT") ) { + parse("FMT",fmt); log.printf(" with format %s \n", fmt.c_str() ); } else { - log.printf("\n"); + log.printf("\n"); } } -void GridPrintingBase::update(){ +void GridPrintingBase::update() { if( getStep()==0 || getStride()==0 ) return ; OFile ofile; ofile.link(*this); @@ -70,7 +70,7 @@ void GridPrintingBase::update(){ ofile.open( filename ); printGrid( ofile ); ofile.close(); } -void GridPrintingBase::runFinalJobs(){ +void GridPrintingBase::runFinalJobs() { if( getStride()>0 ) return; OFile ofile; ofile.link(*this); diff --git a/src/gridtools/GridPrintingBase.h b/src/gridtools/GridPrintingBase.h index a9b79cd329..d33865d73b 100644 --- a/src/gridtools/GridPrintingBase.h +++ b/src/gridtools/GridPrintingBase.h @@ -36,8 +36,8 @@ class GridPrintingBase : public ActionPilot { public: static void registerKeywords( Keywords& keys ); explicit GridPrintingBase(const ActionOptions&ao); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void update(); void runFinalJobs(); virtual void printGrid( OFile& ofile ) const=0; diff --git a/src/gridtools/GridToXYZ.cpp b/src/gridtools/GridToXYZ.cpp index 214e33903d..75e508a3f2 100644 --- a/src/gridtools/GridToXYZ.cpp +++ b/src/gridtools/GridToXYZ.cpp @@ -43,13 +43,13 @@ class GridToXYZ : public GridPrintingBase { unsigned mycomp; public: static void registerKeywords( Keywords& keys ); - explicit GridToXYZ(const ActionOptions&ao); + explicit GridToXYZ(const ActionOptions&ao); void printGrid( OFile& ofile ) const ; }; PLUMED_REGISTER_ACTION(GridToXYZ,"GRID_TO_XYZ") -void GridToXYZ::registerKeywords( Keywords& keys ){ +void GridToXYZ::registerKeywords( Keywords& keys ) { GridPrintingBase::registerKeywords( keys ); keys.add("optional","COMPONENT","if your input is a vector field use this to specifiy the component of the input vector field for which you wish to output"); keys.add("compulsory","UNITS","PLUMED","the units in which to print out the coordinates. PLUMED means internal PLUMED units"); @@ -58,32 +58,32 @@ void GridToXYZ::registerKeywords( Keywords& keys ){ } GridToXYZ::GridToXYZ(const ActionOptions&ao): -Action(ao), -GridPrintingBase(ao) + Action(ao), + GridPrintingBase(ao) { if( ingrid->getDimension()!=3 ) error("cannot print grid xyz file if grid does not contain three dimensional data"); - fmt = " " + fmt; + fmt = " " + fmt; - if( ingrid->getNumberOfComponents()==1 ){ - mycomp=0; + if( ingrid->getNumberOfComponents()==1 ) { + mycomp=0; } else { - int tcomp=-1; parse("COMPONENT",tcomp); - if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); - mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; - log.printf(" using %dth component of grid \n",tcomp ); + int tcomp=-1; parse("COMPONENT",tcomp); + if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); + mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; + log.printf(" using %dth component of grid \n",tcomp ); } fmt="%f"; std::string precision; parse("PRECISION",precision); - if(precision.length()>0){ - int p; Tools::convert(precision,p); - log<<" with precision "<0) { + int p; Tools::convert(precision,p); + log<<" with precision "< point( 3 ); double val; ofile.printf("%u\n",ingrid->getNumberOfPoints()); ofile.printf("Grid converted to xyz file \n"); - for(unsigned i=0;igetNumberOfPoints();++i){ - ingrid->getGridPointCoordinates( i, point ); - ofile.printf("X"); double val=ingrid->getGridElement( i, 0 ); - if( ingrid->getType()=="flat" ) val=1.0; - else val=ingrid->getGridElement( i, 0 ); - for(unsigned j=0;j<3;++j){ ofile.printf( (" " + fmt).c_str(), val*lenunit*point[j] ); } - ofile.printf("\n"); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + ingrid->getGridPointCoordinates( i, point ); + ofile.printf("X"); double val=ingrid->getGridElement( i, 0 ); + if( ingrid->getType()=="flat" ) val=1.0; + else val=ingrid->getGridElement( i, 0 ); + for(unsigned j=0; j<3; ++j) { ofile.printf( (" " + fmt).c_str(), val*lenunit*point[j] ); } + ofile.printf("\n"); } } diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp index f09e3f21a8..5282667a4c 100644 --- a/src/gridtools/GridVessel.cpp +++ b/src/gridtools/GridVessel.cpp @@ -27,7 +27,7 @@ namespace PLMD { namespace gridtools { -void GridVessel::registerKeywords( Keywords& keys ){ +void GridVessel::registerKeywords( Keywords& keys ) { AveragingVessel::registerKeywords( keys ); keys.add("compulsory","TYPE","flat","how the grid points are being generated"); keys.add("compulsory","COMPONENTS","the names of the components in the vector"); @@ -36,12 +36,12 @@ void GridVessel::registerKeywords( Keywords& keys ){ } GridVessel::GridVessel( const vesselbase::VesselOptions& da ): -AveragingVessel(da), -bounds_set(false), -cube_units(1.0), -noderiv(false), -npoints(0), -wasforced(false) + AveragingVessel(da), + bounds_set(false), + cube_units(1.0), + noderiv(false), + npoints(0), + wasforced(false) { std::string geom; parse("TYPE",geom); if( geom=="flat" ) gtype=flat; @@ -49,102 +49,102 @@ wasforced(false) else plumed_merror( geom + " is invalid geometry type"); std::vector compnames; parseVector("COMPONENTS",compnames); std::vector coordnames; parseVector("COORDINATES",coordnames); - if( gtype==flat ){ - dimension=coordnames.size(); - str_min.resize( dimension); str_max.resize( dimension ); stride.resize( dimension ); - max.resize( dimension ); dx.resize( dimension ); nbin.resize( dimension ); min.resize( dimension ); - } else if( gtype==fibonacci ){ - if( coordnames.size()!=3 ) error("cannot generate fibonacci grid points on surface of sphere if not 3 input coordinates"); - dimension=3; + if( gtype==flat ) { + dimension=coordnames.size(); + str_min.resize( dimension); str_max.resize( dimension ); stride.resize( dimension ); + max.resize( dimension ); dx.resize( dimension ); nbin.resize( dimension ); min.resize( dimension ); + } else if( gtype==fibonacci ) { + if( coordnames.size()!=3 ) error("cannot generate fibonacci grid points on surface of sphere if not 3 input coordinates"); + dimension=3; } unsigned n=0; nper=compnames.size()*( 1 + coordnames.size() ); arg_names.resize( coordnames.size() + compnames.size()*( 1 + coordnames.size() ) ); - for(unsigned i=0;i spbc( dimension ); parseVector("PBC",spbc); - for(unsigned i=0;i tnames( dimension ), cnames(nper); - for(unsigned i=0;i& smin, const std::vector& smax, - const std::vector& binsin, const std::vector& spacing ){ + const std::vector& binsin, const std::vector& spacing ) { plumed_dbg_assert( smin.size()==dimension && smax.size()==dimension ); plumed_assert( gtype==flat && (spacing.size()==dimension || binsin.size()==dimension) ); npoints=1; bounds_set=true; - for(unsigned i=0;iepsilon ) spc += 1; - if( spc>binsin[i] ) nbin[i]=spc; else nbin[i]=binsin[i]; - } else if( binsin.size()==dimension ) nbin[i]=binsin[i]; - else if( spacing.size()==dimension ) nbin[i] = std::floor(( max[i] - min[i] ) / spacing[i]) + 1; - else plumed_error(); - dx[i] = ( max[i] - min[i] ) / static_cast( nbin[i] ); - if( !pbc[i] ){ max[i] +=dx[i]; nbin[i]+=1; } - stride[i]=npoints; - npoints*=nbin[i]; + for(unsigned i=0; iepsilon ) spc += 1; + if( spc>binsin[i] ) nbin[i]=spc; else nbin[i]=binsin[i]; + } else if( binsin.size()==dimension ) nbin[i]=binsin[i]; + else if( spacing.size()==dimension ) nbin[i] = std::floor(( max[i] - min[i] ) / spacing[i]) + 1; + else plumed_error(); + dx[i] = ( max[i] - min[i] ) / static_cast( nbin[i] ); + if( !pbc[i] ) { max[i] +=dx[i]; nbin[i]+=1; } + stride[i]=npoints; + npoints*=nbin[i]; } - resize(); // Always resize after setting new bounds as grid size may have have changed -} + resize(); // Always resize after setting new bounds as grid size may have have changed +} -void GridVessel::setupFibonacciGrid( const unsigned& np ){ +void GridVessel::setupFibonacciGrid( const unsigned& np ) { bounds_set=true; npoints = np; fib_increment = pi*( 3 - sqrt(5) ); - fib_offset = 2 / static_cast( npoints ); + fib_offset = 2 / static_cast( npoints ); Random random; fib_rnd = std::floor( npoints*random.RandU01() ); resize(); } -std::string GridVessel::description(){ +std::string GridVessel::description() { if( !bounds_set ) return ""; - + std::string des; - if( gtype==flat ){ - des="grid of "; std::string num; - for(unsigned i=0;i0, "Number of datapoints at each grid point has not been set"); - resizeBuffer( getNumberOfBufferPoints()*nper + 1 + 2*getAction()->getNumberOfDerivatives() ); + resizeBuffer( getNumberOfBufferPoints()*nper + 1 + 2*getAction()->getNumberOfDerivatives() ); setDataSize( npoints*nper ); forces.resize( npoints ); if( active.size()!=npoints) active.resize( npoints, true ); } @@ -153,18 +153,18 @@ unsigned GridVessel::getIndex( const std::vector& indices ) const { plumed_dbg_assert( gtype==flat && bounds_set && indices.size()==dimension ); // indices are flattended using a column-major order unsigned index=indices[dimension-1]; - for(unsigned i=dimension-1;i>0;--i){ + for(unsigned i=dimension-1; i>0; --i) { index=index*nbin[i-1]+indices[i-1]; - } + } return index; } -void GridVessel::getIndices( const std::vector& point, std::vector& indices ) const { +void GridVessel::getIndices( const std::vector& point, std::vector& indices ) const { plumed_dbg_assert( gtype==flat && bounds_set && point.size()==dimension && indices.size()==dimension ); - for(unsigned i=0;inbin[i] ) plumed_merror("point is outside grid range"); + for(unsigned i=0; inbin[i] ) plumed_merror("point is outside grid range"); } } @@ -175,37 +175,37 @@ unsigned GridVessel::getIndex( const std::vector& point ) const { } void GridVessel::convertIndexToIndices( const unsigned& index, const std::vector& nnbin, std::vector& indices ) const { - plumed_dbg_assert( gtype==flat ); unsigned kk=index; indices[0]=index%nnbin[0]; - for(unsigned i=1;i=2){ // I think this is wrong + } + if(dimension>=2) { // I think this is wrong indices[dimension-1]=(kk-indices[dimension-2])/nnbin[dimension-2]; - } + } } void GridVessel::getIndices( const unsigned& index, std::vector& indices ) const { - plumed_dbg_assert( gtype==flat ); convertIndexToIndices( index, nbin, indices ); + plumed_dbg_assert( gtype==flat ); convertIndexToIndices( index, nbin, indices ); } -void GridVessel::getGridPointCoordinates( const unsigned& ipoint , std::vector& x ) const { +void GridVessel::getGridPointCoordinates( const unsigned& ipoint, std::vector& x ) const { plumed_dbg_assert( bounds_set && x.size()==dimension && ipoint tindices( dimension ); getIndices( ipoint, tindices ); - for(unsigned i=0;i tindices( dimension ); getIndices( ipoint, tindices ); + for(unsigned i=0; i tmp_indices( dimension ); std::vector my_indices( dimension ); getIndices( mybox, my_indices ); - for(unsigned i=0;ierror("Extrapolating function on grid"); - if( pbc[j] && i0==nbin[j]) i0=0; - tmp_indices[j]=i0; - } - mysneigh[i]=getIndex( tmp_indices ); - plumed_massert( active[mysneigh[i]], "inactive grid point required for splines"); + for(unsigned i=0; ierror("Extrapolating function on grid"); + if( pbc[j] && i0==nbin[j]) i0=0; + tmp_indices[j]=i0; + } + mysneigh[i]=getIndex( tmp_indices ); + plumed_massert( active[mysneigh[i]], "inactive grid point required for splines"); } } @@ -233,22 +233,22 @@ double GridVessel::getGridElement( const unsigned& ipoint, const unsigned& jelem return getDataElement( nper*ipoint + jelement ); } -void GridVessel::setGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ){ +void GridVessel::setGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ) { plumed_dbg_assert( bounds_set && ipoint& buffer, std::vector& der_list ) const { plumed_dbg_assert( myvals.getNumberOfValues()==(nper+1) ); - for(unsigned i=0;i& buffer ){ +void GridVessel::finish( const std::vector& buffer ) { if( wasforced ) getFinalForces( buffer, finalForces ); else AveragingVessel::finish( buffer ); } @@ -257,14 +257,14 @@ double GridVessel::getGridElement( const std::vector& indices, const u return getGridElement( getIndex( indices ), jelement ); } -void GridVessel::setGridElement( const std::vector& indices, const unsigned& jelement, const double& value ){ +void GridVessel::setGridElement( const std::vector& indices, const unsigned& jelement, const double& value ) { setGridElement( getIndex( indices ), jelement, value ); } std::vector GridVessel::getMin() const { plumed_dbg_assert( gtype==flat ); return str_min; } - + std::vector GridVessel::getMax() const { plumed_dbg_assert( gtype==flat ); return str_max; } @@ -272,9 +272,9 @@ std::vector GridVessel::getMax() const { std::vector GridVessel::getNbin() const { plumed_dbg_assert( gtype==flat && bounds_set ); std::vector ngrid( dimension ); - for(unsigned i=0;i& pp, const std::vector< plumed_dbg_assert( gtype==flat && bounds_set && nneigh.size()==dimension ); std::vector indices( dimension ); - for(unsigned i=0;i& indices, const std::vector& nneigh, +void GridVessel::getNeighbors( const std::vector& indices, const std::vector& nneigh, unsigned& num_neighbors, std::vector& neighbors ) const { plumed_dbg_assert( gtype==flat && bounds_set && nneigh.size()==dimension ); unsigned num_neigh=1; std::vector small_bin( dimension ); - for(unsigned i=0;i s_indices(dimension), t_indices(dimension); - for(unsigned index=0;index=nbin[i]) found=false; - if( pbc[i] && i0<0) i0=nbin[i]-(-i0)%nbin[i]; - if( pbc[i] && i0>=nbin[i]) i0%=nbin[i]; - t_indices[i]=static_cast(i0); - } - if( found ){ - neighbors[num_neighbors]=getIndex( t_indices ); - num_neighbors++; - } + for(unsigned index=0; index=nbin[i]) found=false; + if( pbc[i] && i0<0) i0=nbin[i]-(-i0)%nbin[i]; + if( pbc[i] && i0>=nbin[i]) i0%=nbin[i]; + t_indices[i]=static_cast(i0); + } + if( found ) { + neighbors[num_neighbors]=getIndex( t_indices ); + num_neighbors++; + } } } -void GridVessel::setCubeUnits( const double& units ){ +void GridVessel::setCubeUnits( const double& units ) { plumed_dbg_assert( gtype==flat ); cube_units=units; } @@ -329,17 +329,17 @@ double GridVessel::getCubeUnits() const { std::string GridVessel::getInputString() const { std::string mstring="COORDINATES="+arg_names[0]; - for(unsigned i=1;i& x, const u std::vector xfloor(dimension); getGridPointCoordinates( getIndex(x), xfloor ); // loop over neighbors - for(unsigned int ipoint=0;ipoint& to_activate ){ +void GridVessel::activateThesePoints( const std::vector& to_activate ) { plumed_dbg_assert( to_activate.size()==npoints ); - for(unsigned i=0;i& inforces ){ +void GridVessel::setForce( const std::vector& inforces ) { plumed_dbg_assert( inforces.size()==npoints ); - wasforced=true; for(unsigned i=0;i& fforces ){ - plumed_dbg_assert( fforces.size()==finalForces.size() ); +bool GridVessel::applyForce( std::vector& fforces ) { + plumed_dbg_assert( fforces.size()==finalForces.size() ); if( !wasforced ) return false; - for(unsigned i=0;i min, max; + std::vector min, max; /// The numerical distance between adjacent grid points - std::vector stride; + std::vector stride; /// The number of bins in each grid direction - std::vector nbin; + std::vector nbin; /// The grid point that was requested last by getGridPointCoordinates - unsigned currentGridPoint; + unsigned currentGridPoint; /// The forces that will be output at the end of the calculation - std::vector finalForces; + std::vector finalForces; protected: /// Is forced - bool wasforced; + bool wasforced; /// Forces acting on grid elements - std::vector forces; + std::vector forces; /// Do we have derivatives - bool noderiv; + bool noderiv; /// The names of the various columns in the grid file - std::vector arg_names; -/// The number of pieces of information we are storing for each + std::vector arg_names; +/// The number of pieces of information we are storing for each /// point in the grid - unsigned nper; + unsigned nper; /// Is this direction periodic - std::vector pbc; -/// The minimum and maximum in the grid stored as strings - std::vector str_min, str_max; + std::vector pbc; +/// The minimum and maximum in the grid stored as strings + std::vector str_min, str_max; /// The spacing between grid points - std::vector dx; + std::vector dx; /// The dimensionality of the grid - unsigned dimension; + unsigned dimension; /// Which grid points are we actively accumulating - std::vector active; + std::vector active; /// Convert a point in space the the correspoinding grid point - unsigned getIndex( const std::vector& p ) const ; + unsigned getIndex( const std::vector& p ) const ; public: /// keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Constructor - explicit GridVessel( const vesselbase::VesselOptions& ); -/// Remove the derivatives - void setNoDerivatives(); + explicit GridVessel( const vesselbase::VesselOptions& ); +/// Remove the derivatives + void setNoDerivatives(); /// Get the type of grid we are using - std::string getType() const ; + std::string getType() const ; /// Set the minimum and maximum of the grid - virtual void setBounds( const std::vector& smin, const std::vector& smax, const std::vector& nbins, const std::vector& spacing ); + virtual void setBounds( const std::vector& smin, const std::vector& smax, const std::vector& nbins, const std::vector& spacing ); /// Setup the grid if it is a fibonacci grid on the surface of a sphere - void setupFibonacciGrid( const unsigned& np ); + void setupFibonacciGrid( const unsigned& np ); /// Get a description of the grid to output to the log - std::string description(); + std::string description(); /// Convert an index into indices - void convertIndexToIndices( const unsigned& index, const std::vector& nnbin, std::vector& indices ) const ; + void convertIndexToIndices( const unsigned& index, const std::vector& nnbin, std::vector& indices ) const ; /// Flatten the grid and get the grid index for a point - unsigned getIndex( const std::vector& indices ) const ; + unsigned getIndex( const std::vector& indices ) const ; /// Get the indices fof a point - void getIndices( const unsigned& index, std::vector& indices ) const ; + void getIndices( const unsigned& index, std::vector& indices ) const ; /// Get the indices of a particular point - void getIndices( const std::vector& point, std::vector& indices ) const ; + void getIndices( const std::vector& point, std::vector& indices ) const ; /// Operations on one of the elements of grid point i - void setGridElement( const unsigned&, const unsigned&, const double& ); + void setGridElement( const unsigned&, const unsigned&, const double& ); /// Add data to an element of the grid - void addToGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ); + void addToGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ); /// Operations on one of the elements of grid point specified by vector - double getGridElement( const std::vector&, const unsigned& ) const ; - void setGridElement( const std::vector&, const unsigned&, const double& ); + double getGridElement( const std::vector&, const unsigned& ) const ; + void setGridElement( const std::vector&, const unsigned&, const double& ); /// Set the size of the buffer equal to nper*npoints - virtual void resize(); + virtual void resize(); /// Get the number of points in the grid - unsigned getNumberOfPoints() const; + unsigned getNumberOfPoints() const; /// Get the coordinates for a point in the grid - void getGridPointCoordinates( const unsigned& , std::vector& ) const ; + void getGridPointCoordinates( const unsigned&, std::vector& ) const ; /// Get the dimensionality of the function - unsigned getDimension() const ; + unsigned getDimension() const ; /// Get the number of components in the vector stored on each grid point - virtual unsigned getNumberOfComponents() const ; + virtual unsigned getNumberOfComponents() const ; /// Is the grid periodic in the ith direction - bool isPeriodic( const unsigned& i ) const ; + bool isPeriodic( const unsigned& i ) const ; /// Get the number of quantities we have stored at each grid point - unsigned getNumberOfQuantities() const ; + unsigned getNumberOfQuantities() const ; /// Get the number of grid points for each dimension - std::vector getNbin() const ; + std::vector getNbin() const ; /// Get the name of the ith component - std::string getComponentName( const unsigned& i ) const ; + std::string getComponentName( const unsigned& i ) const ; /// Get the vector containing the minimum value of the grid in each dimension - std::vector getMin() const ; + std::vector getMin() const ; /// Get the vector containing the maximum value of the grid in each dimension - std::vector getMax() const ; + std::vector getMax() const ; /// Get the number of points needed in the buffer - virtual unsigned getNumberOfBufferPoints() const ; + virtual unsigned getNumberOfBufferPoints() const ; /// Get the stride (the distance between the grid points of an index) - const std::vector& getStride() const ; + const std::vector& getStride() const ; /// Return the volume of one of the grid cells - double getCellVolume() const ; -/// Get the value of the ith grid element - virtual double getGridElement( const unsigned&, const unsigned& ) const ; + double getCellVolume() const ; +/// Get the value of the ith grid element + virtual double getGridElement( const unsigned&, const unsigned& ) const ; /// Get the set of points neighouring a particular location in space - void getNeighbors( const std::vector& pp, const std::vector& nneigh, - unsigned& num_neighbours, std::vector& neighbors ) const ; + void getNeighbors( const std::vector& pp, const std::vector& nneigh, + unsigned& num_neighbours, std::vector& neighbors ) const ; /// Get the neighbors for a set of indices of a point - void getNeighbors( const std::vector& indices, const std::vector& nneigh, - unsigned& num_neighbors, std::vector& neighbors ) const ; + void getNeighbors( const std::vector& indices, const std::vector& nneigh, + unsigned& num_neighbors, std::vector& neighbors ) const ; /// Get the points neighboring a particular spline point - void getSplineNeighbors( const unsigned& mybox, std::vector& mysneigh ) const ; + void getSplineNeighbors( const unsigned& mybox, std::vector& mysneigh ) const ; /// Get the spacing between grid points - const std::vector& getGridSpacing() const ; + const std::vector& getGridSpacing() const ; /// Get the extent of the grid in one of the axis - double getGridExtent( const unsigned& i ) const ; + double getGridExtent( const unsigned& i ) const ; /// Copy data from the action into the grid - virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; + virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; /// Finish the calculation - virtual void finish( const std::vector& buffer ); + virtual void finish( const std::vector& buffer ); /// This ensures that Gaussian cube fies are in correct units - void setCubeUnits( const double& units ); + void setCubeUnits( const double& units ); /// This ensures that Gaussian cube files are in correct units - double getCubeUnits() const ; + double getCubeUnits() const ; /// Return a string containing the input to the grid so we can clone it - std::string getInputString() const ; + std::string getInputString() const ; /// Does this have derivatives - bool noDerivatives() const ; + bool noDerivatives() const ; /// Get the value and derivatives at a particular location using spline interpolation - double getValueAndDerivatives( const std::vector& x, const unsigned& ind, std::vector& der ) const ; + double getValueAndDerivatives( const std::vector& x, const unsigned& ind, std::vector& der ) const ; /// Deactivate all the grid points - void activateThesePoints( const std::vector& to_activate ); + void activateThesePoints( const std::vector& to_activate ); /// Is this point active - bool inactive( const unsigned& ip ) const ; + bool inactive( const unsigned& ip ) const ; /// This retrieves the final force - virtual void getFinalForces( const std::vector& buffer, std::vector& finalForces ){ plumed_error(); } + virtual void getFinalForces( const std::vector& buffer, std::vector& finalForces ) { plumed_error(); } /// Apply the forces - void setForce( const std::vector& inforces ); + void setForce( const std::vector& inforces ); /// Was a force added to the grid - bool wasForced() const ; + bool wasForced() const ; /// And retrieve the forces - bool applyForce( std::vector& fforces ); + bool applyForce( std::vector& fforces ); }; inline @@ -200,11 +200,11 @@ const std::vector& GridVessel::getGridSpacing() const { inline double GridVessel::getCellVolume() const { - if( gtype==flat ){ - double myvol=1.0; for(unsigned i=0;i( getNumberOfPoints() ); + return 4*pi / static_cast( getNumberOfPoints() ); } } diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index 6fac76cd56..43fe891c27 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace gridtools { -void HistogramOnGrid::registerKeywords( Keywords& keys ){ +void HistogramOnGrid::registerKeywords( Keywords& keys ) { GridVessel::registerKeywords( keys ); keys.add("compulsory","KERNEL","the type of kernel to use"); keys.add("compulsory","BANDWIDTH","the bandwidths"); @@ -33,23 +33,23 @@ void HistogramOnGrid::registerKeywords( Keywords& keys ){ } HistogramOnGrid::HistogramOnGrid( const vesselbase::VesselOptions& da ): -GridVessel(da), -neigh_tot(0), -addOneKernelAtATime(false), -bandwidths(dimension), -discrete(false) + GridVessel(da), + neigh_tot(0), + addOneKernelAtATime(false), + bandwidths(dimension), + discrete(false) { - if( getType()=="flat" ){ - parse("KERNEL",kerneltype); - if( kerneltype=="discrete" || kerneltype=="DISCRETE" ){ - discrete=true; setNoDerivatives(); - } else { - parseVector("BANDWIDTH",bandwidths); - } + if( getType()=="flat" ) { + parse("KERNEL",kerneltype); + if( kerneltype=="discrete" || kerneltype=="DISCRETE" ) { + discrete=true; setNoDerivatives(); + } else { + parseVector("BANDWIDTH",bandwidths); + } } else { - parse("CONCENTRATION",von_misses_concentration); - von_misses_norm = von_misses_concentration / ( 4*pi*sinh( von_misses_concentration ) ); - } + parse("CONCENTRATION",von_misses_concentration); + von_misses_norm = von_misses_concentration / ( 4*pi*sinh( von_misses_concentration ) ); + } } bool HistogramOnGrid::noDiscreteKernels() const { @@ -57,151 +57,151 @@ bool HistogramOnGrid::noDiscreteKernels() const { } void HistogramOnGrid::setBounds( const std::vector& smin, const std::vector& smax, - const std::vector& nbins, const std::vector& spacing ){ + const std::vector& nbins, const std::vector& spacing ) { GridVessel::setBounds( smin, smax, nbins, spacing ); - if( !discrete ){ - std::vector point(dimension,0); - KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true ); neigh_tot=1; - nneigh=kernel.getSupport( dx ); std::vector support( kernel.getContinuousSupport() ); - for(unsigned i=0;igetGridExtent(i) ) error("bandwidth is too large for periodic grid"); - neigh_tot *= (2*nneigh[i]+1); - } - } + if( !discrete ) { + std::vector point(dimension,0); + KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true ); neigh_tot=1; + nneigh=kernel.getSupport( dx ); std::vector support( kernel.getContinuousSupport() ); + for(unsigned i=0; igetGridExtent(i) ) error("bandwidth is too large for periodic grid"); + neigh_tot *= (2*nneigh[i]+1); + } + } } KernelFunctions* HistogramOnGrid::getKernelAndNeighbors( std::vector& point, unsigned& num_neigh, std::vector& neighbors ) const { - if( discrete ){ - plumed_assert( getType()=="flat" ); - num_neigh=1; for(unsigned i=0;igetCenter(), nneigh, num_neigh, neighbors ); - return kernel; + if( discrete ) { + plumed_assert( getType()=="flat" ); + num_neigh=1; for(unsigned i=0; igetCenter(), nneigh, num_neigh, neighbors ); + return kernel; } else { - num_neigh = getNumberOfPoints(); - if( neighbors.size()!=getNumberOfPoints() ) neighbors.resize( getNumberOfPoints() ); - for(unsigned i=0;i HistogramOnGrid::getVectorOfValues() const { std::vector vv; - for(unsigned i=0;isetDomain( str_min[i], str_max[i] ); - else vv[i]->setNotPeriodic(); + for(unsigned i=0; isetDomain( str_min[i], str_max[i] ); + else vv[i]->setNotPeriodic(); } return vv; } void HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { - if( addOneKernelAtATime ){ - plumed_dbg_assert( myvals.getNumberOfValues()==2 && !wasforced ); - std::vector der( dimension ); - for(unsigned i=0;igetPositionInCurrentTaskList(current), myvals.get(0), myvals.get(1), der, buffer ); + if( addOneKernelAtATime ) { + plumed_dbg_assert( myvals.getNumberOfValues()==2 && !wasforced ); + std::vector der( dimension ); + for(unsigned i=0; igetPositionInCurrentTaskList(current), myvals.get(0), myvals.get(1), der, buffer ); } else { - plumed_dbg_assert( myvals.getNumberOfValues()==dimension+2 ); - std::vector point( dimension ); double weight=myvals.get(0)*myvals.get( 1+dimension ); - for(unsigned i=0;i neighbors; - std::vector der( dimension ); - KernelFunctions* kernel=getKernelAndNeighbors( point, num_neigh, neighbors ); - - if( !kernel && getType()=="flat" ){ - plumed_dbg_assert( num_neigh==1 ); der.resize(0); - accumulate( neighbors[0], weight, 1.0, der, buffer ); - } else { - double totwforce=0.0; - std::vector intforce( 2*dimension, 0.0 ); - std::vector vv( getVectorOfValues() ); - - double newval; std::vector xx( dimension ); - for(unsigned i=0;iset(xx[j]); - newval = kernel->evaluate( vv, der, true ); - } else { - // Evalulate dot product - double dot=0; for(unsigned j=0;jgetNumberOfDerivatives(); - unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); - for(unsigned j=0;j point( dimension ); double weight=myvals.get(0)*myvals.get( 1+dimension ); + for(unsigned i=0; i neighbors; + std::vector der( dimension ); + KernelFunctions* kernel=getKernelAndNeighbors( point, num_neigh, neighbors ); + + if( !kernel && getType()=="flat" ) { + plumed_dbg_assert( num_neigh==1 ); der.resize(0); + accumulate( neighbors[0], weight, 1.0, der, buffer ); + } else { + double totwforce=0.0; + std::vector intforce( 2*dimension, 0.0 ); + std::vector vv( getVectorOfValues() ); + + double newval; std::vector xx( dimension ); + for(unsigned i=0; iset(xx[j]); + newval = kernel->evaluate( vv, der, true ); + } else { + // Evalulate dot product + double dot=0; for(unsigned j=0; jgetNumberOfDerivatives(); + unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); + for(unsigned j=0; j& der, std::vector& buffer ) const { - buffer[bufstart+nper*ipoint] += weight*dens; - if( der.size()>0 ) for(unsigned j=0;j0 ) for(unsigned j=0; j& der, std::vector& intforce ) const { - for(unsigned j=0;j& buffer, std::vector& finalForces ){ +void HistogramOnGrid::getFinalForces( const std::vector& buffer, std::vector& finalForces ) { if( finalForces.size()!=getAction()->getNumberOfDerivatives() ) finalForces.resize( getAction()->getNumberOfDerivatives() ); // And the final force - unsigned nder = getAction()->getNumberOfDerivatives(); + unsigned nder = getAction()->getNumberOfDerivatives(); // Derivatives due to normalization unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); - for(unsigned i=0;i& buffer ){ - if( addOneKernelAtATime ){ - for(unsigned i=0;igetCurrentNumberOfActiveTasks();++i){ - for(unsigned j=0;jgetActiveTask(i)+j, buffer[bufstart+i*nper+j] ); - } +void HistogramOnGrid::finish( const std::vector& buffer ) { + if( addOneKernelAtATime ) { + for(unsigned i=0; igetCurrentNumberOfActiveTasks(); ++i) { + for(unsigned j=0; jgetActiveTask(i)+j, buffer[bufstart+i*nper+j] ); + } } else { - GridVessel::finish( buffer ); + GridVessel::finish( buffer ); } } diff --git a/src/gridtools/HistogramOnGrid.h b/src/gridtools/HistogramOnGrid.h index 5171a9f6cc..2eb9a253da 100644 --- a/src/gridtools/HistogramOnGrid.h +++ b/src/gridtools/HistogramOnGrid.h @@ -53,7 +53,7 @@ class HistogramOnGrid : public GridVessel { unsigned getNumberOfBufferPoints() const ; KernelFunctions* getKernelAndNeighbors( std::vector& point, unsigned& num_neigh, std::vector& neighbors ) const; std::vector getVectorOfValues() const ; - void addOneKernelEachTimeOnly(){ addOneKernelAtATime=true; } + void addOneKernelEachTimeOnly() { addOneKernelAtATime=true; } virtual void getFinalForces( const std::vector& buffer, std::vector& finalForces ); bool noDiscreteKernels() const ; }; diff --git a/src/gridtools/IntegrateGrid.cpp b/src/gridtools/IntegrateGrid.cpp index 02f59826ad..fc966a46d1 100644 --- a/src/gridtools/IntegrateGrid.cpp +++ b/src/gridtools/IntegrateGrid.cpp @@ -43,13 +43,13 @@ class IntegrateGrid : public ActionWithIntegral { PLUMED_REGISTER_ACTION(IntegrateGrid,"INTEGRATE_GRID") -void IntegrateGrid::registerKeywords( Keywords& keys ){ +void IntegrateGrid::registerKeywords( Keywords& keys ) { ActionWithIntegral::registerKeywords( keys ); } IntegrateGrid::IntegrateGrid(const ActionOptions&ao): -Action(ao), -ActionWithIntegral(ao) + Action(ao), + ActionWithIntegral(ao) { } diff --git a/src/gridtools/InterpolateGrid.cpp b/src/gridtools/InterpolateGrid.cpp index f35f10de8c..e8f97c0d4a 100644 --- a/src/gridtools/InterpolateGrid.cpp +++ b/src/gridtools/InterpolateGrid.cpp @@ -28,20 +28,20 @@ /* Interpolate a smooth function stored on a grid onto a grid with a smaller grid spacing. -This action takes a function evaluated on a grid as input and can be used to interpolate the values of that +This action takes a function evaluated on a grid as input and can be used to interpolate the values of that function on to a finer grained grid. The interpolation within this algorithm is done using splines. \par Examples -The input below can be used to postprocess a trajectory. It calculates a \ref HISTOGRAM as a function the +The input below can be used to postprocess a trajectory. It calculates a \ref HISTOGRAM as a function the distance between atoms 1 and 2 using kernel density estimation. During the calculation the values of the kernels -are evaluated at 100 points on a uniform grid between 0.0 and 3.0. Prior to outputting this function at the end of the -simulation this function is interpolated onto a finer grid of 200 points between 0.0 and 3.0. +are evaluated at 100 points on a uniform grid between 0.0 and 3.0. Prior to outputting this function at the end of the +simulation this function is interpolated onto a finer grid of 200 points between 0.0 and 3.0. \verbatim x: DISTANCE ATOMS=1,2 -hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 -ii: INTERPOLATE_GRID GRID=hA1 GRID_BIN=200 +hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 +ii: INTERPOLATE_GRID GRID=hA1 GRID_BIN=200 DUMPGRID GRID=ii FILE=histo.dat \endverbatim @@ -57,42 +57,42 @@ class InterpolateGrid : public ActionWithInputGrid { explicit InterpolateGrid(const ActionOptions&ao); unsigned getNumberOfQuantities() const ; void compute( const unsigned& current, MultiValue& myvals ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(InterpolateGrid,"INTERPOLATE_GRID") -void InterpolateGrid::registerKeywords( Keywords& keys ){ +void InterpolateGrid::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.add("optional","GRID_BIN","the number of bins for the grid"); keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); - keys.remove("KERNEL"); keys.remove("BANDWIDTH"); + keys.remove("KERNEL"); keys.remove("BANDWIDTH"); } InterpolateGrid::InterpolateGrid(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao) + Action(ao), + ActionWithInputGrid(ao) { plumed_assert( ingrid->getNumberOfComponents()==1 ); - if( ingrid->noDerivatives() ) error("cannot interpolate a grid that does not have derivatives"); + if( ingrid->noDerivatives() ) error("cannot interpolate a grid that does not have derivatives"); // Create the input from the old string createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); - std::vector nbin; parseVector("GRID_BIN",nbin); + std::vector nbin; parseVector("GRID_BIN",nbin); std::vector gspacing; parseVector("GRID_SPACING",gspacing); - if( nbin.size()!=ingrid->getDimension() && gspacing.size()!=ingrid->getDimension() ){ - error("GRID_BIN or GRID_SPACING must be set"); - } + if( nbin.size()!=ingrid->getDimension() && gspacing.size()!=ingrid->getDimension() ) { + error("GRID_BIN or GRID_SPACING must be set"); + } // Need this for creation of tasks - mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), nbin, gspacing ); + mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), nbin, gspacing ); setAveragingAction( mygrid, true ); // Now create task list - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); // And activate all tasks - deactivateAllTasks(); - for(unsigned i=0;igetNumberOfPoints();++i) taskFlags[i]=1; + deactivateAllTasks(); + for(unsigned i=0; igetNumberOfPoints(); ++i) taskFlags[i]=1; lockContributors(); } @@ -103,8 +103,8 @@ unsigned InterpolateGrid::getNumberOfQuantities() const { void InterpolateGrid::compute( const unsigned& current, MultiValue& myvals ) const { std::vector pos( mygrid->getDimension() ); mygrid->getGridPointCoordinates( current, pos ); std::vector der( mygrid->getDimension() ); double val = getFunctionValueAndDerivatives( pos, der ); - myvals.setValue( 0, 1.0 ); myvals.setValue(1, val ); - for(unsigned i=0;igetDimension();++i) myvals.setValue( 2+i, der[i] ); + myvals.setValue( 0, 1.0 ); myvals.setValue(1, val ); + for(unsigned i=0; igetDimension(); ++i) myvals.setValue( 2+i, der[i] ); } } diff --git a/src/main/main.cpp b/src/main/main.cpp index 797ce80396..4e3d6376cd 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -32,10 +32,10 @@ using namespace std; This main uses only the interface published in Plumed.h. The object file generated from this .cpp is the only part of the plumed library that should - not be linked with external MD codes, so as + not be linked with external MD codes, so as to avoid linker error. */ -int main(int argc,char**argv){ +int main(int argc,char**argv) { #ifdef __PLUMED_HAS_MPI bool nompi=false; if(argc>1 && !strcmp(argv[1],"--no-mpi")) nompi=true; @@ -48,7 +48,7 @@ int main(int argc,char**argv){ p->cmd("CLTool setArgc",&argc); p->cmd("CLTool setArgv",argv); #ifdef __PLUMED_HAS_MPI - if(!nompi){ + if(!nompi) { MPI_Comm comm; MPI_Comm_dup(MPI_COMM_WORLD,&comm); p->cmd("CLTool setMPIComm",&comm); diff --git a/src/manyrestraints/LWalls.cpp b/src/manyrestraints/LWalls.cpp index 4075bacd8b..7c0ad569ec 100644 --- a/src/manyrestraints/LWalls.cpp +++ b/src/manyrestraints/LWalls.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace manyrestraints { -//+PLUMEDOC MCOLVARB LWALLS +//+PLUMEDOC MCOLVARB LWALLS /* Add \ref LOWER_WALLS restraints on all the multicolvar values @@ -36,20 +36,20 @@ keyword and places a restraint on each quantity, \f$x\f$, with the following fun k((x-a+o)/s)^e \f$ -\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and +\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and \f$e\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFF = 0. \par Examples The following set of commands can be used to stop any of the 800 atoms in group A from moving more than 2.46425 nm -in the z direction from atom 34137. This is done by adding a lower wall on the z-distance between all the atoms in -group A and the position of 34137. +in the z direction from atom 34137. This is done by adding a lower wall on the z-distance between all the atoms in +group A and the position of 34137. \verbatim l: ZDISTANCES GROUPA=1-800 GROUPB=34137 NOPBC LWALLS DATA=l AT=2.46465 KAPPA=150.0 EXP=2 EPS=1 OFFSET=0 LABEL=lwall \endverbatim - + */ //+ENDPLUMEDOC @@ -70,7 +70,7 @@ class LWalls : public ManyRestraintsBase { PLUMED_REGISTER_ACTION(LWalls,"LWALLS") -void LWalls::registerKeywords( Keywords& keys ){ +void LWalls::registerKeywords( Keywords& keys ) { ManyRestraintsBase::registerKeywords( keys ); keys.add("compulsory","AT","the radius of the sphere"); keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall."); @@ -80,8 +80,8 @@ void LWalls::registerKeywords( Keywords& keys ){ } LWalls::LWalls(const ActionOptions& ao): -Action(ao), -ManyRestraintsBase(ao) + Action(ao), + ManyRestraintsBase(ao) { parse("AT",at); parse("OFFSET",offset); @@ -91,13 +91,13 @@ ManyRestraintsBase(ao) checkRead(); } -double LWalls::calcPotential( const double& val, double& df ) const { +double LWalls::calcPotential( const double& val, double& df ) const { double uscale = (val - at + offset)/eps; - if( uscale < 0. ){ - double power = pow( uscale, exp ); - df = ( kappa / eps ) * exp * power / uscale; + if( uscale < 0. ) { + double power = pow( uscale, exp ); + df = ( kappa / eps ) * exp * power / uscale; - return kappa*power; + return kappa*power; } return 0.0; diff --git a/src/manyrestraints/ManyRestraintsBase.cpp b/src/manyrestraints/ManyRestraintsBase.cpp index 60dd82b2e5..d13d51cfac 100644 --- a/src/manyrestraints/ManyRestraintsBase.cpp +++ b/src/manyrestraints/ManyRestraintsBase.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace manyrestraints { -void ManyRestraintsBase::registerKeywords( Keywords& keys ){ +void ManyRestraintsBase::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionWithVessel::registerKeywords( keys ); @@ -37,11 +37,11 @@ void ManyRestraintsBase::registerKeywords( Keywords& keys ){ } ManyRestraintsBase::ManyRestraintsBase(const ActionOptions& ao): -Action(ao), -ActionWithValue(ao), -ActionPilot(ao), -ActionWithVessel(ao), -ActionWithInputVessel(ao) + Action(ao), + ActionWithValue(ao), + ActionPilot(ao), + ActionWithVessel(ao), + ActionWithInputVessel(ao) { // Read in the vessel we are action on readArgument("bridge"); @@ -49,44 +49,44 @@ ActionWithInputVessel(ao) 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()); + aves->getName().c_str(),aves->getLabel().c_str()); // Add a task list in order to avoid problems - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList( aves->getTaskCode(i) ); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList( aves->getTaskCode(i) ); // And turn on the derivatives (note problems here because of ActionWithValue) turnOnDerivatives(); needsDerivatives(); // Now create the vessel std::string fake_input="LABEL=bias"; - addVessel( "SUM", fake_input, 0 ); + addVessel( "SUM", fake_input, 0 ); readVesselKeywords(); } -void ManyRestraintsBase::doJobsRequiredBeforeTaskList(){ +void ManyRestraintsBase::doJobsRequiredBeforeTaskList() { ActionWithVessel::doJobsRequiredBeforeTaskList(); ActionWithValue::clearDerivatives(); } void ManyRestraintsBase::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const { outvals.setValue( 0, invals.get(0) ); - + // Get the potential double dval=0, val=calcPotential( invals.get(1), dval ); outvals.setValue( 1, val ); - for(unsigned i=0;iaddForce( -1.0*getStride() ); } diff --git a/src/manyrestraints/ManyRestraintsBase.h b/src/manyrestraints/ManyRestraintsBase.h index 9e1c3cae96..565ea340df 100644 --- a/src/manyrestraints/ManyRestraintsBase.h +++ b/src/manyrestraints/ManyRestraintsBase.h @@ -32,10 +32,10 @@ namespace PLMD { namespace manyrestraints { class ManyRestraintsBase : - public ActionWithValue, - public ActionPilot, - public vesselbase::ActionWithVessel, - public vesselbase::ActionWithInputVessel + public ActionWithValue, + public ActionPilot, + public vesselbase::ActionWithVessel, + public vesselbase::ActionWithInputVessel { private: /// Pointer to underlying action with vessel @@ -43,13 +43,13 @@ class ManyRestraintsBase : public: static void registerKeywords( Keywords& keys ); explicit ManyRestraintsBase(const ActionOptions&); - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } unsigned getNumberOfDerivatives(); /// Routines that have to be defined so as not to have problems with virtual methods - 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(){} + 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 @@ -57,16 +57,16 @@ class ManyRestraintsBase : /// Calculate the potential virtual double calcPotential( const double& val, double& df ) const=0; // Calculate does nothing - void calculate(){}; + void calculate() {}; /// This should never be called - void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); } + void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); } /// Deactivate task now does nothing void apply(); - void applyBridgeForces( const std::vector& bb ){ plumed_assert( bb.size()==0 ); } + void applyBridgeForces( const std::vector& bb ) { plumed_assert( bb.size()==0 ); } }; inline -unsigned ManyRestraintsBase::getNumberOfDerivatives(){ +unsigned ManyRestraintsBase::getNumberOfDerivatives() { return aves->getNumberOfDerivatives(); } diff --git a/src/manyrestraints/UWalls.cpp b/src/manyrestraints/UWalls.cpp index 474eab490c..f4c75f0d89 100644 --- a/src/manyrestraints/UWalls.cpp +++ b/src/manyrestraints/UWalls.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace manyrestraints { -//+PLUMEDOC MCOLVARB UWALLS +//+PLUMEDOC MCOLVARB UWALLS /* Add \ref UPPER_WALLS restraints on all the multicolvar values @@ -36,14 +36,14 @@ keyword and places a restraint on each quantity, \f$x\f$, with the following fun k((x-a+o)/s)^e \f$ -\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and +\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and \f$e\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFF = 0. \par Examples -The following set of commands can be used to stop a cluster composed of 20 atoms subliming. The position of -the centre of mass of the cluster is calculated by the \ref COM command labelled c1. The \ref DISTANCES -command labelled d1 is then used to calculate the distance between each of the 20 atoms in the cluster +The following set of commands can be used to stop a cluster composed of 20 atoms subliming. The position of +the centre of mass of the cluster is calculated by the \ref COM command labelled c1. The \ref DISTANCES +command labelled d1 is then used to calculate the distance between each of the 20 atoms in the cluster and the center of mass of the cluster. These distances are then passed to the UWALLS command, which adds a \ref UPPER_WALLS restraint on each of them and thereby prevents each of them from moving very far from the centre of mass of the cluster. @@ -53,7 +53,7 @@ COM ATOMS=1-20 LABEL=c1 DISTANCES GROUPA=c1 GROUPB=1-20 LABEL=d1 UWALLS DATA=d1 AT=2.5 KAPPA=0.2 LABEL=sr \endverbatim - + */ //+ENDPLUMEDOC @@ -74,7 +74,7 @@ class UWalls : public ManyRestraintsBase { PLUMED_REGISTER_ACTION(UWalls,"UWALLS") -void UWalls::registerKeywords( Keywords& keys ){ +void UWalls::registerKeywords( Keywords& keys ) { ManyRestraintsBase::registerKeywords( keys ); keys.add("compulsory","AT","the radius of the sphere"); keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall."); @@ -84,8 +84,8 @@ void UWalls::registerKeywords( Keywords& keys ){ } UWalls::UWalls(const ActionOptions& ao): -Action(ao), -ManyRestraintsBase(ao) + Action(ao), + ManyRestraintsBase(ao) { parse("AT",at); parse("OFFSET",offset); @@ -95,13 +95,13 @@ ManyRestraintsBase(ao) checkRead(); } -double UWalls::calcPotential( const double& val, double& df ) const { +double UWalls::calcPotential( const double& val, double& df ) const { double uscale = (val - at + offset)/eps; - if( uscale > 0. ){ - double power = pow( uscale, exp ); - df = ( kappa / eps ) * exp * power / uscale; + if( uscale > 0. ) { + double power = pow( uscale, exp ); + df = ( kappa / eps ) * exp * power / uscale; - return kappa*power; + return kappa*power; } return 0.0; diff --git a/src/mapping/Mapping.cpp b/src/mapping/Mapping.cpp index ac80b6bee0..c1a6dba33d 100644 --- a/src/mapping/Mapping.cpp +++ b/src/mapping/Mapping.cpp @@ -31,72 +31,72 @@ namespace PLMD { namespace mapping { -void Mapping::registerKeywords( Keywords& keys ){ - Action::registerKeywords( keys ); +void Mapping::registerKeywords( Keywords& keys ) { + Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); - ActionWithArguments::registerKeywords( keys ); - ActionAtomistic::registerKeywords( keys ); + ActionWithArguments::registerKeywords( keys ); + ActionAtomistic::registerKeywords( keys ); vesselbase::ActionWithVessel::registerKeywords( keys ); keys.add("compulsory","REFERENCE","a pdb file containing the set of reference configurations"); keys.add("compulsory","PROPERTY","the property to be used in the index. This should be in the REMARK of the reference"); keys.add("compulsory","TYPE","OPTIMAL-FAST","the manner in which distances are calculated. More information on the different " - "metrics that are available in PLUMED can be found in the section of the manual on " - "\\ref dists"); + "metrics that are available in PLUMED can be found in the section of the manual on " + "\\ref dists"); keys.addFlag("DISABLE_CHECKS",false,"disable checks on reference input structures."); } Mapping::Mapping(const ActionOptions&ao): -Action(ao), -ActionAtomistic(ao), -ActionWithArguments(ao), -ActionWithValue(ao), -ActionWithVessel(ao) + Action(ao), + ActionAtomistic(ao), + ActionWithArguments(ao), + ActionWithValue(ao), + ActionWithVessel(ao) { // Read the input std::string mtype; parse("TYPE",mtype); bool skipchecks; parseFlag("DISABLE_CHECKS",skipchecks); // Setup the object that does the mapping - mymap = new PointWiseMapping( mtype, skipchecks ); - + mymap = new PointWiseMapping( mtype, skipchecks ); + // Read the properties we require - if( keywords.exists("PROPERTY") ){ - std::vector property; - parseVector("PROPERTY",property); - if(property.size()==0) error("no properties were specified"); - mymap->setPropertyNames( property, false ); + if( keywords.exists("PROPERTY") ) { + std::vector property; + parseVector("PROPERTY",property); + if(property.size()==0) error("no properties were specified"); + mymap->setPropertyNames( property, false ); } else { - std::vector property(1); - property[0]="spath"; - mymap->setPropertyNames( property, true ); + std::vector property(1); + property[0]="spath"; + mymap->setPropertyNames( property, true ); } // Open reference file - std::string reference; parse("REFERENCE",reference); - FILE* fp=fopen(reference.c_str(),"r"); + std::string reference; parse("REFERENCE",reference); + FILE* fp=fopen(reference.c_str(),"r"); if(!fp) error("could not open reference file " + reference ); - // Read all reference configurations - bool do_read=true; std::vector weights; + // Read all reference configurations + bool do_read=true; std::vector weights; unsigned nfram=0, wnorm=0., ww; - while (do_read){ - PDB mypdb; - // Read the pdb file - do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); - // Fix argument names - expandArgKeywordInPDB( mypdb ); - if(do_read){ - mymap->readFrame( mypdb ); ww=mymap->getWeight( nfram ); - weights.push_back( ww ); - wnorm+=ww; nfram++; - } else { - break; - } + while (do_read) { + PDB mypdb; + // Read the pdb file + do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); + // Fix argument names + expandArgKeywordInPDB( mypdb ); + if(do_read) { + mymap->readFrame( mypdb ); ww=mymap->getWeight( nfram ); + weights.push_back( ww ); + wnorm+=ww; nfram++; + } else { + break; + } } - fclose(fp); + fclose(fp); if(nfram==0 ) error("no reference configurations were specified"); log.printf(" found %u configurations in file %s\n",nfram,reference.c_str() ); - for(unsigned i=0;isetWeights( weights ); // Finish the setup of the mapping object @@ -106,49 +106,49 @@ ActionWithVessel(ao) requestAtoms( atoms ); std::vector req_args; interpretArgumentList( args, req_args ); requestArguments( req_args ); // Duplicate all frames (duplicates are used by sketch-map) - // mymap->duplicateFrameList(); + // mymap->duplicateFrameList(); // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); // plumed_assert( !mymap->mappingNeedsSetup() ); // Resize all derivative arrays // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() ); // Resize forces array - if( getNumberOfAtoms()>0 ){ - forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); + if( getNumberOfAtoms()>0 ) { + forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); } else { - forcesToApply.resize( getNumberOfArguments() ); + forcesToApply.resize( getNumberOfArguments() ); } } -void Mapping::turnOnDerivatives(){ +void Mapping::turnOnDerivatives() { ActionWithValue::turnOnDerivatives(); needsDerivatives(); -} +} -Mapping::~Mapping(){ +Mapping::~Mapping() { delete mymap; } -void Mapping::prepare(){ - if( mymap->mappingNeedsSetup() ){ - // Get the arguments and atoms that are required - std::vector atoms; std::vector args; - mymap->getAtomAndArgumentRequirements( atoms, args ); - requestAtoms( atoms ); std::vector req_args; - interpretArgumentList( args, req_args ); requestArguments( req_args ); - // Duplicate all frames (duplicates are used by sketch-map) - //mymap->duplicateFrameList(); - // Get the number of frames in the path - // unsigned nfram=getNumberOfReferencePoints(); - // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); - // plumed_assert( !mymap->mappingNeedsSetup() ); - // Resize all derivative arrays - // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() ); - // Resize forces array - if( getNumberOfAtoms()>0 ){ - forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); - } else { - forcesToApply.resize( getNumberOfArguments() ); - } +void Mapping::prepare() { + if( mymap->mappingNeedsSetup() ) { + // Get the arguments and atoms that are required + std::vector atoms; std::vector args; + mymap->getAtomAndArgumentRequirements( atoms, args ); + requestAtoms( atoms ); std::vector req_args; + interpretArgumentList( args, req_args ); requestArguments( req_args ); + // Duplicate all frames (duplicates are used by sketch-map) + //mymap->duplicateFrameList(); + // Get the number of frames in the path + // unsigned nfram=getNumberOfReferencePoints(); + // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); + // plumed_assert( !mymap->mappingNeedsSetup() ); + // Resize all derivative arrays + // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() ); + // Resize forces array + if( getNumberOfAtoms()>0 ) { + forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); + } else { + forcesToApply.resize( getNumberOfArguments() ); + } } } @@ -156,72 +156,72 @@ unsigned Mapping::getPropertyIndex( const std::string& name ) const { return mymap->getPropertyIndex( name ); } -void Mapping::setPropertyValue( const unsigned& iframe, const unsigned& jprop, const double& property ){ +void Mapping::setPropertyValue( const unsigned& iframe, const unsigned& jprop, const double& property ) { mymap->setProjectionCoordinate( iframe, jprop, property ); } -double Mapping::getLambda(){ +double Mapping::getLambda() { plumed_merror("lambda is not defined in this mapping type"); } -std::string Mapping::getArgumentName( unsigned& iarg ){ +std::string Mapping::getArgumentName( unsigned& iarg ) { if( iarg < getNumberOfArguments() ) return getPntrToArgument(iarg)->getName(); unsigned iatom=iarg - getNumberOfArguments(); std::string atnum; Tools::convert( getAbsoluteIndex(iatom).serial(),atnum); unsigned icomp=iatom%3; if(icomp==0) return "pos" + atnum + "x"; if(icomp==1) return "pos" + atnum + "y"; - return "pos" + atnum + "z"; -} + return "pos" + atnum + "z"; +} void Mapping::finishPackSetup( const unsigned& ifunc, ReferenceValuePack& mypack ) const { - ReferenceConfiguration* myref=mymap->getFrame(ifunc); mypack.setValIndex(0); - unsigned nargs2=myref->getNumberOfReferenceArguments(); unsigned nat2=myref->getNumberOfReferencePositions(); - if( mypack.getNumberOfAtoms()!=nat2 || mypack.getNumberOfArguments()!=nargs2 ) mypack.resize( nargs2, nat2 ); - if( nat2>0 ){ - ReferenceAtoms* myat2=dynamic_cast( myref ); plumed_dbg_assert( myat2 ); - for(unsigned i=0;igetAtomIndex(i) ); - } + ReferenceConfiguration* myref=mymap->getFrame(ifunc); mypack.setValIndex(0); + unsigned nargs2=myref->getNumberOfReferenceArguments(); unsigned nat2=myref->getNumberOfReferencePositions(); + if( mypack.getNumberOfAtoms()!=nat2 || mypack.getNumberOfArguments()!=nargs2 ) mypack.resize( nargs2, nat2 ); + if( nat2>0 ) { + ReferenceAtoms* myat2=dynamic_cast( myref ); plumed_dbg_assert( myat2 ); + for(unsigned i=0; igetAtomIndex(i) ); + } } double Mapping::calculateDistanceFunction( const unsigned& ifunc, ReferenceValuePack& myder, const bool& squared ) const { // Calculate the distance - double dd = mymap->calcDistanceFromConfiguration( ifunc, getPositions(), getPbc(), getArguments(), myder, squared ); + double dd = mymap->calcDistanceFromConfiguration( ifunc, getPositions(), getPbc(), getArguments(), myder, squared ); // Transform distance by whatever double df, ff=transformHD( dd, df ); myder.scaleAllDerivatives( df ); // And the virial - if( getNumberOfAtoms()>0 && !myder.virialWasSet() ){ - Tensor tvir; tvir.zero(); - for(unsigned i=0;i0 && !myder.virialWasSet() ) { + Tensor tvir; tvir.zero(); + for(unsigned i=0; igetFrame( ifunc ); } -void Mapping::calculateNumericalDerivatives( ActionWithValue* a ){ - if( getNumberOfArguments()>0 ){ - ActionWithArguments::calculateNumericalDerivatives( a ); +void Mapping::calculateNumericalDerivatives( ActionWithValue* a ) { + if( getNumberOfArguments()>0 ) { + ActionWithArguments::calculateNumericalDerivatives( a ); } - if( getNumberOfAtoms()>0 ){ - Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); - for(unsigned j=0;jgetDerivative(i); - } - calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); - for(unsigned j=0;jaddDerivative( i, save_derivatives(j,i) ); - } + if( getNumberOfAtoms()>0 ) { + Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); + for(unsigned j=0; jgetDerivative(i); + } + calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); + for(unsigned j=0; jaddDerivative( i, save_derivatives(j,i) ); + } } } -void Mapping::apply(){ - if( getForcesFromVessels( forcesToApply ) ){ - addForcesOnArguments( forcesToApply ); - if( getNumberOfAtoms()>0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); +void Mapping::apply() { + if( getForcesFromVessels( forcesToApply ) ) { + addForcesOnArguments( forcesToApply ); + if( getNumberOfAtoms()>0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); } } diff --git a/src/mapping/Mapping.h b/src/mapping/Mapping.h index 9b3145129a..02299d4c3a 100644 --- a/src/mapping/Mapping.h +++ b/src/mapping/Mapping.h @@ -40,8 +40,8 @@ class Mapping : public ActionWithArguments, public ActionWithValue, public vesselbase::ActionWithVessel - { -friend class TrigonometricPathVessel; +{ + friend class TrigonometricPathVessel; private: // The derivative wrt to the distance from the frame std::vector dfframes; @@ -76,10 +76,10 @@ friend class TrigonometricPathVessel; void lockRequests(); void unlockRequests(); /// Distance from a point is never periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } /// Get the number of derivatives for this action unsigned getNumberOfDerivatives(); // N.B. This is replacing the virtual function in ActionWithValue -/// Get the value of lambda for paths and property maps +/// Get the value of lambda for paths and property maps virtual double getLambda(); /// This does the transformation of the distance by whatever function is required virtual double transformHD( const double& dist, double& df ) const=0; @@ -87,7 +87,7 @@ friend class TrigonometricPathVessel; unsigned getNumberOfProperties() const ; /// Get the name of the ith property we are projecting std::string getPropertyName( const unsigned& iprop ) const ; -/// Get the index of a particular named property +/// Get the index of a particular named property unsigned getPropertyIndex( const std::string& name ) const ; /// Set the value of one of the projection coordinates void setPropertyValue( const unsigned& iframe, const unsigned& iprop, const double& property ); @@ -97,57 +97,57 @@ friend class TrigonometricPathVessel; double getPropertyValue( const unsigned& current, const unsigned& iprop ) const ; /// Stuff to do before we do the calculation void prepare(); -/// Apply the forces +/// Apply the forces void apply(); }; inline unsigned Mapping::getNumberOfReferencePoints() const { - return mymap->getNumberOfMappedPoints(); + return mymap->getNumberOfMappedPoints(); } inline -unsigned Mapping::getNumberOfDerivatives(){ +unsigned Mapping::getNumberOfDerivatives() { unsigned nat=getNumberOfAtoms(); if(nat>0) return 3*nat + 9 + getNumberOfArguments(); return getNumberOfArguments(); } inline -void Mapping::lockRequests(){ +void Mapping::lockRequests() { ActionWithArguments::lockRequests(); ActionAtomistic::lockRequests(); } inline -void Mapping::unlockRequests(){ +void Mapping::unlockRequests() { ActionWithArguments::unlockRequests(); ActionAtomistic::unlockRequests(); } inline unsigned Mapping::getNumberOfProperties() const { - return mymap->getNumberOfProperties(); + return mymap->getNumberOfProperties(); } inline std::string Mapping::getPropertyName( const unsigned& iprop ) const { - return mymap->getPropertyName(iprop); + return mymap->getPropertyName(iprop); } inline double Mapping::getPropertyValue( const unsigned& cur, const unsigned& iprop ) const { plumed_dbg_assert( ipropgetPropertyValue( cur, iprop ); + return mymap->getPropertyValue( cur, iprop ); } inline double Mapping::getWeight( const unsigned& current ) const { - return mymap->getWeight( current ); + return mymap->getWeight( current ); } inline -void Mapping::storeDistanceFunction( const unsigned& ifunc ){ +void Mapping::storeDistanceFunction( const unsigned& ifunc ) { plumed_dbg_assert( ifunc& Mapping::getAllReferenceConfigurations(){ +std::vector& Mapping::getAllReferenceConfigurations() { return mymap->getReferenceConfigurations(); } diff --git a/src/mapping/PCAVars.cpp b/src/mapping/PCAVars.cpp index 0ae940a749..d029720ed8 100644 --- a/src/mapping/PCAVars.cpp +++ b/src/mapping/PCAVars.cpp @@ -33,25 +33,25 @@ /* Projection on principal component eigenvectors or other high dimensional linear subspace -The collective variables described in \ref dists allow one to calculate the distance between the -instaneous structure adopted by the system and some high-dimensional, reference configuration. The +The collective variables described in \ref dists allow one to calculate the distance between the +instaneous structure adopted by the system and some high-dimensional, reference configuration. The problem with doing this is that, as one gets further and further from the reference configuration, the distance from it becomes a progressively poorer and poorer collective variable. This happens because -the ``number" of structures at a distance \f$d\f$ from a reference configuration is proportional to \f$d^N\f$ in -an \f$N\f$ dimensional space. Consequently, when \f$d\f$ is small the distance from the reference configuration +the ``number" of structures at a distance \f$d\f$ from a reference configuration is proportional to \f$d^N\f$ in +an \f$N\f$ dimensional space. Consequently, when \f$d\f$ is small the distance from the reference configuration may well be a good collective variable. However, when \f$d\f$ is large it is unlikely that the distance from the reference -structure is a good CV. When the distance is large there will almost certainly be markedly different -configuration that have the same CV value and hence barriers in transverse degrees of -freedom. +structure is a good CV. When the distance is large there will almost certainly be markedly different +configuration that have the same CV value and hence barriers in transverse degrees of +freedom. -For these reasons dimensionality reduction is often employed so a projection \f$\mathbf{s}\f$ of a high-dimensional configuration +For these reasons dimensionality reduction is often employed so a projection \f$\mathbf{s}\f$ of a high-dimensional configuration \f$\mathbf{X}\f$ in a lower dimensionality space using a function: \f[ \mathbf{s} = F(\mathbf{X}-\mathbf{X}^{ref}) \f] -where here we have introduced some high-dimensional reference configuration \f$\mathbf{X}^{ref}\f$. By far the simplest way to +where here we have introduced some high-dimensional reference configuration \f$\mathbf{X}^{ref}\f$. By far the simplest way to do this is to use some linear operator for \f$F\f$. That is to say we find a low-dimensional projection by rotating the basis vectors using some linear algebra: @@ -61,9 +61,9 @@ by rotating the basis vectors using some linear algebra: Here \f$A\f$ is a \f$d\f$ by \f$D\f$ matrix where \f$D\f$ is the dimensionality of the high dimensional space and \f$d\f$ is the dimensionality of the lower dimensional subspace. In plumed when this kind of projection you can use the majority -of the metrics detailed on \ref dists to calculate the displacement, \f$\mathbf{X}-\mathbf{X}^{ref}\f$, from the reference configuration. -The matrix \f$A\f$ can be found by various means including principal component analysis and normal mode analysis. In both these methods the -rows of \f$A\f$ would be the principle eigenvectors of a square matrix. For PCA the covariance while for normal modes the Hessian. +of the metrics detailed on \ref dists to calculate the displacement, \f$\mathbf{X}-\mathbf{X}^{ref}\f$, from the reference configuration. +The matrix \f$A\f$ can be found by various means including principal component analysis and normal mode analysis. In both these methods the +rows of \f$A\f$ would be the principle eigenvectors of a square matrix. For PCA the covariance while for normal modes the Hessian. \bug It is not possible to use the \ref DRMSD metric with this variable. You can get around this by listing the set of distances you wish to calculate for your DRMSD in the plumed file explicitally and using the EUCLIDEAN metric. MAHALONOBIS and NORM-EUCLIDEAN also do not work with this variable but using these options makes little sense when projecting on a linear subspace. @@ -72,19 +72,19 @@ rows of \f$A\f$ would be the principle eigenvectors of a square matrix. For PCA The following input calculates a projection on a linear subspace where the displacements from the reference configuration are calculated using the OPTIMAL metric. Consequently, both translation of the center of mass of the atoms and rotation of the reference -frame are removed from these displacements. The matrix \f$A\f$ and the reference -configuration \f$R^{ref}\f$ are specified in the pdb input file reference.pdb and the +frame are removed from these displacements. The matrix \f$A\f$ and the reference +configuration \f$R^{ref}\f$ are specified in the pdb input file reference.pdb and the value of all projections (and the residual) are output to a file called colvar2. \verbatim PCAVARS REFERENCE=reference.pdb TYPE=OPTIMAL LABEL=pca2 -PRINT ARG=pca2.* FILE=colvar2 +PRINT ARG=pca2.* FILE=colvar2 \endverbatim The reference configurations can be specified using a pdb file. The first configuration that you provide is the reference configuration, -which is refered to in the above as \f$X^{ref}\f$ subsequent configurations give the directions of row vectors that are contained in -the matrix \f$A\f$ above. These directions can be specified by specifying a second configuration - in this case a vector will -be constructed by calculating the displacement of this second configuration from the reference configuration. A pdb input prepared +which is refered to in the above as \f$X^{ref}\f$ subsequent configurations give the directions of row vectors that are contained in +the matrix \f$A\f$ above. These directions can be specified by specifying a second configuration - in this case a vector will +be constructed by calculating the displacement of this second configuration from the reference configuration. A pdb input prepared in this way would look as follows: \verbatim @@ -106,7 +106,7 @@ ATOM 21 HH32 NME 3 18.572 -13.148 -16.346 1.00 1.00 END \endverbatim -Alternatively, the second configuration can specify the components of \f$A\f$ explicitally. In this case you need to include the +Alternatively, the second configuration can specify the components of \f$A\f$ explicitally. In this case you need to include the keyword TYPE=DIRECTION in the remarks to the pdb as shown below. \verbatim @@ -134,12 +134,12 @@ for each of the frames of your path. An input file in this case might look like \verbatim DESCRIPTION: a pca eigenvector specified using the start point and direction in the HD space. -REMARK WEIGHT=1.0 -REMARK ARG=d1,d2 +REMARK WEIGHT=1.0 +REMARK ARG=d1,d2 REMARK d1=1.0 d2=1.0 END REMARK TYPE=DIRECTION -REMARK ARG=d1,d2 +REMARK ARG=d1,d2 REMARK d1=0.1 d2=0.25 END \endverbatim @@ -151,11 +151,11 @@ If we wanted to specify the direction in this metric using the start and end poi \verbatim DESCRIPTION: a pca eigenvector specified using the start and end point of a vector in the HD space. -REMARK WEIGHT=1.0 -REMARK ARG=d1,d2 +REMARK WEIGHT=1.0 +REMARK ARG=d1,d2 REMARK d1=1.0 d2=1.0 END -REMARK ARG=d1,d2 +REMARK ARG=d1,d2 REMARK d1=1.1 d2=1.25 END \endverbatim @@ -170,13 +170,13 @@ class PCAVars : public ActionWithValue, public ActionAtomistic, public ActionWithArguments - { +{ private: /// The holders for the derivatives MultiValue myvals; ReferenceValuePack mypack; /// The position of the reference configuration (the one we align to) - ReferenceConfiguration* myref; + ReferenceConfiguration* myref; /// The eigenvectors we are interested in std::vector directions; /// Stuff for applying forces @@ -195,30 +195,30 @@ class PCAVars : PLUMED_REGISTER_ACTION(PCAVars,"PCAVARS") -void PCAVars::registerKeywords( Keywords& keys ){ +void PCAVars::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionWithArguments::registerKeywords( keys ); componentsAreNotOptional(keys); - keys.addOutputComponent("eig","default","the projections on each eigenvalue are stored on values labeled eig-1, eig-2, ..."); + keys.addOutputComponent("eig","default","the projections on each eigenvalue are stored on values labeled eig-1, eig-2, ..."); keys.addOutputComponent("residual","default","the distance of the configuration from the linear subspace defined " - "by the vectors, \\f$e_i\\f$, that are contained in the rows of \\f$A\\f$. In other words this is " - "\\f$\\sqrt( r^2 - \\sum_i [\\mathbf{r}.\\mathbf{e_i}]^2)\\f$ where " - "\\f$r\\f$ is the distance between the instantaneous position and the " - "reference point."); + "by the vectors, \\f$e_i\\f$, that are contained in the rows of \\f$A\\f$. In other words this is " + "\\f$\\sqrt( r^2 - \\sum_i [\\mathbf{r}.\\mathbf{e_i}]^2)\\f$ where " + "\\f$r\\f$ is the distance between the instantaneous position and the " + "reference point."); keys.add("compulsory","REFERENCE","a pdb file containing the reference configuration and configurations that define the directions for each eigenvector"); keys.add("compulsory","TYPE","OPTIMAL","The method we are using for alignment to the reference structure"); keys.addFlag("NORMALIZE",false,"calculate the length of the eigenvector input and divide the components by it so as to have a normalised vector"); } PCAVars::PCAVars(const ActionOptions& ao): -Action(ao), -ActionWithValue(ao), -ActionAtomistic(ao), -ActionWithArguments(ao), -myvals(1,0), -mypack(0,0,myvals) + Action(ao), + ActionWithValue(ao), + ActionAtomistic(ao), + ActionWithArguments(ao), + myvals(1,0), + mypack(0,0,myvals) { // What type of distance are we calculating @@ -229,30 +229,30 @@ mypack(0,0,myvals) FILE* fp=fopen(reference.c_str(),"r"); if(!fp) error("could not open reference file " + reference ); - // Read all reference configurations + // Read all reference configurations MultiReferenceBase myframes( "", false ); bool do_read=true; unsigned nfram=0; - while (do_read){ - PDB mypdb; - // Read the pdb file - do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); - // Fix argument names - expandArgKeywordInPDB( mypdb ); - if(do_read){ - if( nfram==0 ){ - myref = metricRegister().create( mtype, mypdb ); - Direction* tdir = dynamic_cast( myref ); - if( tdir ) error("first frame should be reference configuration - not direction of vector"); - if( !myref->pcaIsEnabledForThisReference() ) error("can't do PCA with reference type " + mtype ); - std::vector remarks( mypdb.getRemark() ); std::string rtype; - bool found=Tools::parse( remarks, "TYPE", rtype ); - if(!found){ std::vector newrem(1); newrem[0]="TYPE="+mtype; mypdb.addRemark(newrem); } - myframes.readFrame( mypdb ); - } else myframes.readFrame( mypdb ); - nfram++; - } else { - break; - } + while (do_read) { + PDB mypdb; + // Read the pdb file + do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); + // Fix argument names + expandArgKeywordInPDB( mypdb ); + if(do_read) { + if( nfram==0 ) { + myref = metricRegister().create( mtype, mypdb ); + Direction* tdir = dynamic_cast( myref ); + if( tdir ) error("first frame should be reference configuration - not direction of vector"); + if( !myref->pcaIsEnabledForThisReference() ) error("can't do PCA with reference type " + mtype ); + std::vector remarks( mypdb.getRemark() ); std::string rtype; + bool found=Tools::parse( remarks, "TYPE", rtype ); + if(!found) { std::vector newrem(1); newrem[0]="TYPE="+mtype; mypdb.addRemark(newrem); } + myframes.readFrame( mypdb ); + } else myframes.readFrame( mypdb ); + nfram++; + } else { + break; + } } fclose(fp); @@ -267,170 +267,170 @@ mypack(0,0,myvals) interpretArgumentList( args, req_args ); requestArguments( req_args ); // Setup the derivative pack - if( atoms.size()>0 ) myvals.resize( 1, args.size() + 3*atoms.size() + 9 ); + if( atoms.size()>0 ) myvals.resize( 1, args.size() + 3*atoms.size() + 9 ); else myvals.resize( 1, args.size() ); - mypack.resize( args.size(), atoms.size() ); - for(unsigned i=0;isetupPCAStorage( mypack ); // Retrieve the position of the first frame, as we use this for alignment myref->setNamesAndAtomNumbers( atoms, args ); // Check there are no periodic arguments - for(unsigned i=0;iisPeriodic() ) error("cannot use periodic variables in pca projections"); + for(unsigned i=0; iisPeriodic() ) error("cannot use periodic variables in pca projections"); } // Work out if the user wants to normalise the input vector bool nflag; parseFlag("NORMALIZE",nflag); checkRead(); - // Resize the matrices that will hold our eivenvectors - for(unsigned i=1;iextractDisplacementVector( myref->getReferencePositions(), getArguments(), myref->getReferenceArguments(), false, nflag, directions[i-1] ); - // Create a component to store the output - std::string num; Tools::convert( i, num ); - addComponentWithDerivatives("eig-"+num); componentIsNotPeriodic("eig-"+num); + // Now calculate the eigenvectors + for(unsigned i=1; iextractDisplacementVector( myref->getReferencePositions(), getArguments(), myref->getReferenceArguments(), false, nflag, directions[i-1] ); + // Create a component to store the output + std::string num; Tools::convert( i, num ); + addComponentWithDerivatives("eig-"+num); componentIsNotPeriodic("eig-"+num); } addComponentWithDerivatives("residual"); componentIsNotPeriodic("residual"); // Get appropriate number of derivatives unsigned nder; - if( getNumberOfAtoms()>0 ){ - nder = 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); + if( getNumberOfAtoms()>0 ) { + nder = 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); } else { - nder = getNumberOfArguments(); + nder = getNumberOfArguments(); } // Resize all derivative arrays - forces.resize( nder ); forcesToApply.resize( nder ); - for(unsigned i=0;iresizeDerivatives(nder); + forces.resize( nder ); forcesToApply.resize( nder ); + for(unsigned i=0; iresizeDerivatives(nder); } -PCAVars::~PCAVars(){ - delete myref; +PCAVars::~PCAVars() { + delete myref; } -unsigned PCAVars::getNumberOfDerivatives(){ - if( getNumberOfAtoms()>0 ){ - return 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); - } +unsigned PCAVars::getNumberOfDerivatives() { + if( getNumberOfAtoms()>0 ) { + return 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); + } return getNumberOfArguments(); -} +} -void PCAVars::lockRequests(){ +void PCAVars::lockRequests() { ActionWithArguments::lockRequests(); ActionAtomistic::lockRequests(); } -void PCAVars::unlockRequests(){ - ActionWithArguments::unlockRequests(); +void PCAVars::unlockRequests() { + ActionWithArguments::unlockRequests(); ActionAtomistic::unlockRequests(); -} +} -void PCAVars::calculate(){ +void PCAVars::calculate() { // Clear the reference value pack mypack.clear(); // Calculate distance between instaneous configuration and reference double dist = myref->calculate( getPositions(), getPbc(), getArguments(), mypack, true ); - + // Start accumulating residual by adding derivatives of distance Value* resid=getPntrToComponent( getNumberOfComponents()-1 ); unsigned nargs=getNumberOfArguments(); - for(unsigned j=0;jaddDerivative( j, mypack.getArgumentDerivative(j) ); - for(unsigned j=0;jaddDerivative( nargs +3*j+k, ader[k] ); + for(unsigned j=0; jaddDerivative( j, mypack.getArgumentDerivative(j) ); + for(unsigned j=0; jaddDerivative( nargs +3*j+k, ader[k] ); } // Retrieve the values of all arguments - std::vector args( getNumberOfArguments() ); for(unsigned i=0;i args( getNumberOfArguments() ); for(unsigned i=0; iprojectDisplacementOnVector( directions[i], getPositions(), getArguments(), args, mypack ); - - // And now accumulate derivatives - Value* eid=getPntrToComponent(i); - for(unsigned j=0;jaddDerivative( j, mypack.getArgumentDerivative(j) ); - if( getNumberOfAtoms()>0 ){ - tvir.zero(); - for(unsigned j=0;jaddDerivative( nargs + 3*j+k, myader[k] ); - resid->addDerivative( nargs + 3*j+k, -2*proj*myader[k] ); - } - tvir += -1.0*Tensor( getPosition(j), myader ); - } - for(unsigned j=0;j<3;++j){ - for(unsigned k=0;k<3;++k) eid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); - } + for(unsigned i=0; iprojectDisplacementOnVector( directions[i], getPositions(), getArguments(), args, mypack ); + + // And now accumulate derivatives + Value* eid=getPntrToComponent(i); + for(unsigned j=0; jaddDerivative( j, mypack.getArgumentDerivative(j) ); + if( getNumberOfAtoms()>0 ) { + tvir.zero(); + for(unsigned j=0; jaddDerivative( nargs + 3*j+k, myader[k] ); + resid->addDerivative( nargs + 3*j+k, -2*proj*myader[k] ); + } + tvir += -1.0*Tensor( getPosition(j), myader ); + } + for(unsigned j=0; j<3; ++j) { + for(unsigned k=0; k<3; ++k) eid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); } - dist -= proj*proj; // Subtract square from total squared distance to get residual squared - // Derivatives of residual - for(unsigned j=0;jaddDerivative( j, -2*proj*eid->getDerivative(j) ); - // for(unsigned j=0;jaddDerivative( j, -2*proj*arg_eigv(i,j) ); - // And set final value - getPntrToComponent(i)->set( proj ); + } + dist -= proj*proj; // Subtract square from total squared distance to get residual squared + // Derivatives of residual + for(unsigned j=0; jaddDerivative( j, -2*proj*eid->getDerivative(j) ); + // for(unsigned j=0;jaddDerivative( j, -2*proj*arg_eigv(i,j) ); + // And set final value + getPntrToComponent(i)->set( proj ); } dist=sqrt(dist); resid->set( dist ); // Take square root of residual derivatives double prefactor = 0.5 / dist; - for(unsigned j=0;jsetDerivative( j, prefactor*resid->getDerivative(j) ); - for(unsigned j=0;jsetDerivative( nargs + 3*j+k, prefactor*resid->getDerivative( nargs+3*j+k ) ); + for(unsigned j=0; jsetDerivative( j, prefactor*resid->getDerivative(j) ); + for(unsigned j=0; jsetDerivative( nargs + 3*j+k, prefactor*resid->getDerivative( nargs+3*j+k ) ); } // And finally virial for residual - if( getNumberOfAtoms()>0 ){ - tvir.zero(); - for(unsigned j=0;jgetDerivative( nargs + 3*j+k ); - tvir += -1.0*Tensor( getPosition(j), ader ); - } - for(unsigned j=0;j<3;++j){ - for(unsigned k=0;k<3;++k) resid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); - } + if( getNumberOfAtoms()>0 ) { + tvir.zero(); + for(unsigned j=0; jgetDerivative( nargs + 3*j+k ); + tvir += -1.0*Tensor( getPosition(j), ader ); + } + for(unsigned j=0; j<3; ++j) { + for(unsigned k=0; k<3; ++k) resid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); + } } } -void PCAVars::calculateNumericalDerivatives( ActionWithValue* a ){ - if( getNumberOfArguments()>0 ){ - ActionWithArguments::calculateNumericalDerivatives( a ); +void PCAVars::calculateNumericalDerivatives( ActionWithValue* a ) { + if( getNumberOfArguments()>0 ) { + ActionWithArguments::calculateNumericalDerivatives( a ); } - if( getNumberOfAtoms()>0 ){ - Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); - for(unsigned j=0;jgetDerivative(i); - } - calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); - for(unsigned j=0;jaddDerivative( i, save_derivatives(j,i) ); - } + if( getNumberOfAtoms()>0 ) { + Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); + for(unsigned j=0; jgetDerivative(i); + } + calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); + for(unsigned j=0; jaddDerivative( i, save_derivatives(j,i) ); + } } -} +} -void PCAVars::apply(){ +void PCAVars::apply() { bool wasforced=false; forcesToApply.assign(forcesToApply.size(),0.0); - for(unsigned i=0;iapplyForce( forces ) ){ - wasforced=true; - for(unsigned i=0;iapplyForce( forces ) ) { + wasforced=true; + for(unsigned i=0; i0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); + if( wasforced ) { + addForcesOnArguments( forcesToApply ); + if( getNumberOfAtoms()>0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); } } diff --git a/src/mapping/Path.cpp b/src/mapping/Path.cpp index 7928ff3a2c..37db777d2e 100644 --- a/src/mapping/Path.cpp +++ b/src/mapping/Path.cpp @@ -24,14 +24,14 @@ //+PLUMEDOC COLVAR PATH /* -Path collective variables with a more flexible framework for the distance metric being used. +Path collective variables with a more flexible framework for the distance metric being used. The Path Collective Variables developed by Branduardi and co-workers \cite brand07 allow one to compute the progress along a high-dimensional path and the distance from the high-dimensional path. The progress along the path (s) is computed using: \f[ -s = \frac{ \sum_{i=1}^N i \exp( -\lambda R[X - X_i] ) }{ \sum_{i=1}^N \exp( -\lambda R[X - X_i] ) } +s = \frac{ \sum_{i=1}^N i \exp( -\lambda R[X - X_i] ) }{ \sum_{i=1}^N \exp( -\lambda R[X - X_i] ) } \f] while the distance from the path (z) is measured using: @@ -44,7 +44,7 @@ In these expressions \f$N\f$ high-dimensional frames (\f$X_i\f$) are used to des space. The two expressions above are then functions of the distances from each of the high-dimensional frames \f$R[X - X_i]\f$. Within PLUMED there are multiple ways to define the distance from a high-dimensional configuration. You could calculate the RMSD distance or you could calculate the ammount by which a set of collective variables change. As such this implementation -of the path cv allows one to use all the difference distance metrics that are discussed in \ref dists. This is as opposed to +of the path cv allows one to use all the difference distance metrics that are discussed in \ref dists. This is as opposed to the alternative implementation of path (\ref PATHMSD) which is a bit faster but which only allows one to use the RMSD distance. The \f$s\f$ and \f$z\f$ variables are calculated using the above formulas by default. However, there is an alternative method @@ -54,14 +54,14 @@ geometry (as opposed to algebra, which is used in the equations above). In this \f[ s = i_2 + \textrm{sign}(i_2-i_1) \frac{ \sqrt{( \mathbf{v}_1\cdot\mathbf{v}_2 )^2 - |\mathbf{v}_3|^2(|\mathbf{v}_1|^2 - |\mathbf{v}_2|^2) } }{2|\mathbf{v}_3|^2} - \frac{\mathbf{v}_1\cdot\mathbf{v}_3 - |\mathbf{v}_3|^2}{2|\mathbf{v}_3|^2} -\f] +\f] -where \f$\mathbf{v}_1\f$ and \f$\mathbf{v}_3\f$ are the vectors connecting the current position to the closest and second closest node of the path, -respectfully and \f$i_1\f$ and \f$i_2\f$ are the projections of the closest and second closest frames of the path. \f$\mathbf{v}_2\f$, meanwhile, is the +where \f$\mathbf{v}_1\f$ and \f$\mathbf{v}_3\f$ are the vectors connecting the current position to the closest and second closest node of the path, +respectfully and \f$i_1\f$ and \f$i_2\f$ are the projections of the closest and second closest frames of the path. \f$\mathbf{v}_2\f$, meanwhile, is the vector connecting the closest frame to the second closest frame. The distance from the path, \f$z\f$ is calculated using: \f[ -z = \sqrt{ \left[ |\mathbf{v}_1|^2 - |\mathbf{v}_2| \left( \frac{ \sqrt{( \mathbf{v}_1\cdot\mathbf{v}_2 )^2 - |\mathbf{v}_3|^2(|\mathbf{v}_1|^2 - |\mathbf{v}_2|^2) } }{2|\mathbf{v}_3|^2} - \frac{\mathbf{v}_1\cdot\mathbf{v}_3 - |\mathbf{v}_3|^2}{2|\mathbf{v}_3|^2} \right) \right]^2 } +z = \sqrt{ \left[ |\mathbf{v}_1|^2 - |\mathbf{v}_2| \left( \frac{ \sqrt{( \mathbf{v}_1\cdot\mathbf{v}_2 )^2 - |\mathbf{v}_3|^2(|\mathbf{v}_1|^2 - |\mathbf{v}_2|^2) } }{2|\mathbf{v}_3|^2} - \frac{\mathbf{v}_1\cdot\mathbf{v}_3 - |\mathbf{v}_3|^2}{2|\mathbf{v}_3|^2} \right) \right]^2 } \f] The symbols here are as they were for \f$s\f$. If you would like to use these equations to calculate \f$s\f$ and \f$z\f$ then you should use the GPATH flag. @@ -71,26 +71,26 @@ The values of \f$s\f$ and \f$z\f$ can then be referenced using the gspath and gz In the example below the path is defined using RMSD distance from frames. The reference frames in the path are defined in the pdb file. In this frame -each configuration in the path is separated by a line containing just the word END. +each configuration in the path is separated by a line containing just the word END. -\verbatim -p1: PATH REFERENCE=file.pdb TYPE=OPTIMAL LAMBDA=500.0 +\verbatim +p1: PATH REFERENCE=file.pdb TYPE=OPTIMAL LAMBDA=500.0 PRINT ARG=p1.sss,p1.zzz STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim In the example below the path is defined using the values of two torsional angles (t1 and t2). -In addition, the \f$s\f$ and \f$z\f$ are calculated using the geometric expressions described +In addition, the \f$s\f$ and \f$z\f$ are calculated using the geometric expressions described above rather than the alegebraic expressions that are used by default. \verbatim t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 pp: PATH TYPE=EUCLIDEAN REFERENCE=epath.pdb GPATH NOSPATH NOZPATH -PRINT ARG=pp.* FILE=colvar +PRINT ARG=pp.* FILE=colvar \endverbatim Notice that the LAMBDA parameter is not required here as we are not calculating \f$s\f$ and \f$s\f$ -using the algebraic formulae defined earlier. The positions of the frames in the path are defined +using the algebraic formulae defined earlier. The positions of the frames in the path are defined in the file epath.pdb. An extract from this file looks as shown below. \verbatim @@ -102,16 +102,16 @@ REMARK ARG=t1,t2 t1=-3.96947 t2=3.61947 END \endverbatim -The remarks in this pdb file tell PLUMED the labels that are being used to define the position in the +The remarks in this pdb file tell PLUMED the labels that are being used to define the position in the high dimensional space and the values that these arguments have at each point on the path. -The following input instructs PLUMED to calculate the values of the path collective variables. The frames that make up this -path are defined in the file all.pdb and all distances are measured using the OPTIMAL metric that is discussed in the manual -page on \ref RMSD. +The following input instructs PLUMED to calculate the values of the path collective variables. The frames that make up this +path are defined in the file all.pdb and all distances are measured using the OPTIMAL metric that is discussed in the manual +page on \ref RMSD. \verbatim p2: PATH REFERENCE=all.pdb LAMBDA=69087 -PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar +PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar \endverbatim If you wish to use collective variable values in the definition of your path you would use an input file with something like this: @@ -120,19 +120,19 @@ If you wish to use collective variable values in the definition of your path you d1: DISTANCE ATOMS=1,2 d2: DISTANCE ATOMS=3,4a p2: PATH REFERENCE=mypath.pdb LAMBDA=2 TYPE=EUCLIDEAN -PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar +PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar \endverbatim The corresponding pdb file containing the definitions of the frames in the path would then look like this: \verbatim DESCRIPTION: a defintiion of a PATH -REMARK TYPE=EUCLIDEAN -REMARK ARG=d1,d2 +REMARK TYPE=EUCLIDEAN +REMARK ARG=d1,d2 REMARK d1=1.0 d2=1.0 END REMARK TYPE=EUCLIDEAN -REMARK ARG=d1,d2 +REMARK ARG=d1,d2 REMARK d1=2.0 d2=2.0 END \endverbatim @@ -144,7 +144,7 @@ of the system and the reference configurations together with the values that the //+ENDPLUMEDOC namespace PLMD { -namespace mapping{ +namespace mapping { class Path : public PathBase { public: @@ -154,27 +154,27 @@ class Path : public PathBase { PLUMED_REGISTER_ACTION(Path,"PATH") -void Path::registerKeywords( Keywords& keys ){ +void Path::registerKeywords( Keywords& keys ) { PathBase::registerKeywords( keys ); keys.remove("PROPERTY"); keys.addFlag("NOSPATH",false,"do not calculate the spath position"); keys.remove("LOWMEM"); keys.use("GPATH"); } Path::Path(const ActionOptions& ao): -Action(ao), -PathBase(ao) + Action(ao), + PathBase(ao) { - setLowMemOption( true ); + setLowMemOption( true ); bool nos; parseFlag("NOSPATH",nos); std::string empty; - if(!nos){ - if( getPropertyIndex("spath")!=0 || getNumberOfProperties()>1 ){ - error("paths only work when there is a single property called sss being calculated"); - } - if( getLambda()==0 ) error("you must set LAMBDA parameter in order to calculate spath position. Use LAMBDA/NOSPATH keyword"); - empty="LABEL=spath"; - addVessel("SPATH",empty,0); + if(!nos) { + if( getPropertyIndex("spath")!=0 || getNumberOfProperties()>1 ) { + error("paths only work when there is a single property called sss being calculated"); + } + if( getLambda()==0 ) error("you must set LAMBDA parameter in order to calculate spath position. Use LAMBDA/NOSPATH keyword"); + empty="LABEL=spath"; + addVessel("SPATH",empty,0); } readVesselKeywords(); checkRead(); diff --git a/src/mapping/PathBase.cpp b/src/mapping/PathBase.cpp index 25c2862f9a..af50f0375d 100644 --- a/src/mapping/PathBase.cpp +++ b/src/mapping/PathBase.cpp @@ -23,41 +23,41 @@ #include "tools/SwitchingFunction.h" namespace PLMD { -namespace mapping{ +namespace mapping { -void PathBase::registerKeywords( Keywords& keys ){ - Mapping::registerKeywords( keys ); +void PathBase::registerKeywords( Keywords& keys ) { + Mapping::registerKeywords( keys ); keys.add("compulsory","LAMBDA","0","the value of the lambda parameter for paths"); keys.addFlag("NOZPATH",false,"do not calculate the zpath position"); } PathBase::PathBase(const ActionOptions& ao): -Action(ao), -Mapping(ao) + Action(ao), + Mapping(ao) { weightHasDerivatives=true; bool noz; parseFlag("NOZPATH",noz); parse("LAMBDA",lambda); // Create the list of tasks - for(unsigned i=0;i& iargs, std::vector& pp ): -mydpack( 1, pp[0]->getNumberOfReferenceArguments() + 3*pp[0]->getNumberOfReferencePositions() + 9 ), -mypack( pp[0]->getNumberOfReferenceArguments(), pp[0]->getNumberOfReferencePositions(), mydpack ), -mypath(pp), -pbc(ipbc), -args(iargs), -mydir(ReferenceConfigurationOptions("DIRECTION")), -len(pp.size()), -sumlen(pp.size()), -sfrac(pp.size()), -MAXCYCLES(100) +PathReparameterization::PathReparameterization( const Pbc& ipbc, const std::vector& iargs, std::vector& pp ): + mydpack( 1, pp[0]->getNumberOfReferenceArguments() + 3*pp[0]->getNumberOfReferencePositions() + 9 ), + mypack( pp[0]->getNumberOfReferenceArguments(), pp[0]->getNumberOfReferencePositions(), mydpack ), + mypath(pp), + pbc(ipbc), + args(iargs), + mydir(ReferenceConfigurationOptions("DIRECTION")), + len(pp.size()), + sumlen(pp.size()), + sfrac(pp.size()), + MAXCYCLES(100) { - mydir.setNamesAndAtomNumbers( pp[0]->getAbsoluteIndexes(), pp[0]->getArgumentNames() ); + mydir.setNamesAndAtomNumbers( pp[0]->getAbsoluteIndexes(), pp[0]->getArgumentNames() ); mydir.zeroDirection(); pp[0]->setupPCAStorage( mypack ); } bool PathReparameterization::loopEnd( const int& index, const int& end, const int& inc ) const { if( inc>0 && indexend ) return false; - return true; + return true; } -void PathReparameterization::calcCurrentPathSpacings( const int& istart, const int& iend ){ +void PathReparameterization::calcCurrentPathSpacings( const int& istart, const int& iend ) { plumed_dbg_assert( istartiend ){ incr=-1; } + int incr=1; if( istart>iend ) { incr=-1; } - for(int i=istart+incr;loopEnd(i,iend+incr,incr)==false;i+=incr){ - len[i] = mypath[i-incr]->calc( mypath[i]->getReferencePositions(), pbc, args, mypath[i]->getReferenceArguments(), mypack, false ); - sumlen[i] = sumlen[i-incr] + len[i]; - //printf("FRAME %d TO FRAME %d EQUALS %f : %f \n",i-incr,i,len[i],sumlen[i] ); + for(int i=istart+incr; loopEnd(i,iend+incr,incr)==false; i+=incr) { + len[i] = mypath[i-incr]->calc( mypath[i]->getReferencePositions(), pbc, args, mypath[i]->getReferenceArguments(), mypack, false ); + sumlen[i] = sumlen[i-incr] + len[i]; + //printf("FRAME %d TO FRAME %d EQUALS %f : %f \n",i-incr,i,len[i],sumlen[i] ); } } -void PathReparameterization::reparameterizePart( const int& istart, const int& iend, const double& target, const double& TOL ){ +void PathReparameterization::reparameterizePart( const int& istart, const int& iend, const double& target, const double& TOL ) { calcCurrentPathSpacings( istart, iend ); unsigned cfin; // If a target separation is set we fix where we want the nodes - int incr=1; if( istart>iend ){ incr=-1; } - - if( target>0 ){ - if( iend>istart ){ - for(unsigned i=istart;iiend-1;--i) sfrac[i]=target*(istart-i); - } - cfin = iend+incr; + int incr=1; if( istart>iend ) { incr=-1; } + + if( target>0 ) { + if( iend>istart ) { + for(unsigned i=istart; iiend-1; --i) sfrac[i]=target*(istart-i); + } + cfin = iend+incr; } else { - cfin = iend; + cfin = iend; } std::vector newpath; - for(unsigned i=0;igetAbsoluteIndexes(), mypath[i]->getArgumentNames() ); + for(unsigned i=0; igetAbsoluteIndexes(), mypath[i]->getArgumentNames() ); } double prevsum=0.; - for(unsigned iter=0;iter( iend - istart ); - for(unsigned i=istart;i=sfrac[i])) ){ - k+=incr; - if( cfin==iend && k>= iend+1 ) plumed_merror("path reparameterization error"); - else if( cfin==(iend+1) && k>=iend ){ k=iend-1; break; } - else if( cfin==(iend-1) && k<=iend ){ k=iend+1; break; } - } - double dr = (sfrac[i]-sumlen[k])/len[k+incr]; - // Calculate the displacement between the appropriate points - // double dd = mypath[k]->calc( mypath[k+incr]->getReferencePositions(), pbc, args, mypath[k+incr]->getReferenceArguments(), mypack, true ); - // Copy the reference configuration from the configuration to a tempory direction - newpath[i].setDirection( mypath[k]->getReferencePositions(), mypath[k]->getReferenceArguments() ); - // Get the displacement of the path - mypath[k]->extractDisplacementVector( mypath[k+incr]->getReferencePositions(), args, mypath[k+incr]->getReferenceArguments(), false, false, mydir ); - // Set our direction equal to the displacement - // mydir.setDirection( mypack ); - // Shift the reference configuration by this ammount - newpath[i].displaceReferenceConfiguration( dr, mydir ); - } - - // Copy the positions of the new path to the new paths - for(int i=istart+incr;loopEnd(i,cfin,incr)==false;i+=incr){ - mypath[i]->setReferenceConfig( newpath[i].getReferencePositions(), newpath[i].getReferenceArguments(), mypath[i]->getReferenceMetric() ); - } - - // Recompute the separations between frames - calcCurrentPathSpacings( istart, iend ); + for(unsigned iter=0; iter( iend - istart ); + for(unsigned i=istart; i=sfrac[i])) ) { + k+=incr; + if( cfin==iend && k>= iend+1 ) plumed_merror("path reparameterization error"); + else if( cfin==(iend+1) && k>=iend ) { k=iend-1; break; } + else if( cfin==(iend-1) && k<=iend ) { k=iend+1; break; } + } + double dr = (sfrac[i]-sumlen[k])/len[k+incr]; + // Calculate the displacement between the appropriate points + // double dd = mypath[k]->calc( mypath[k+incr]->getReferencePositions(), pbc, args, mypath[k+incr]->getReferenceArguments(), mypack, true ); + // Copy the reference configuration from the configuration to a tempory direction + newpath[i].setDirection( mypath[k]->getReferencePositions(), mypath[k]->getReferenceArguments() ); + // Get the displacement of the path + mypath[k]->extractDisplacementVector( mypath[k+incr]->getReferencePositions(), args, mypath[k+incr]->getReferenceArguments(), false, false, mydir ); + // Set our direction equal to the displacement + // mydir.setDirection( mypack ); + // Shift the reference configuration by this ammount + newpath[i].displaceReferenceConfiguration( dr, mydir ); + } + + // Copy the positions of the new path to the new paths + for(int i=istart+incr; loopEnd(i,cfin,incr)==false; i+=incr) { + mypath[i]->setReferenceConfig( newpath[i].getReferencePositions(), newpath[i].getReferenceArguments(), mypath[i]->getReferenceMetric() ); + } + + // Recompute the separations between frames + calcCurrentPathSpacings( istart, iend ); } } -void PathReparameterization::reparameterize( const int& ifix1, const int& ifix2, const double& TOL ){ +void PathReparameterization::reparameterize( const int& ifix1, const int& ifix2, const double& TOL ) { plumed_dbg_assert( ifix10 ) reparameterizePart( ifix1, 0, target, TOL ); if( ifix2<(mypath.size()-1) ) reparameterizePart( ifix2, mypath.size()-1, target, TOL ); -// calcCurrentPathSpacings( 0, mypath.size()-1 ); +// calcCurrentPathSpacings( 0, mypath.size()-1 ); } } diff --git a/src/mapping/PathReparameterization.h b/src/mapping/PathReparameterization.h index dfbf61e62e..9a5a6c318f 100644 --- a/src/mapping/PathReparameterization.h +++ b/src/mapping/PathReparameterization.h @@ -55,7 +55,7 @@ class PathReparameterization { /// Reparameterize the frames of the path between istart and iend and make the spacing equal to target void reparameterizePart( const int& istart, const int& iend, const double& target, const double& TOL ); public: - PathReparameterization( const Pbc& ipbc, const std::vector& iargs, std::vector& pp ); + PathReparameterization( const Pbc& ipbc, const std::vector& iargs, std::vector& pp ); /// Reparameterize the frames of the path between istart and iend so as to make the spacing constant void reparameterize( const int& istart, const int& iend, const double& TOL ); }; diff --git a/src/mapping/PathTools.cpp b/src/mapping/PathTools.cpp index a4884b4fa9..abb9f7c5cc 100644 --- a/src/mapping/PathTools.cpp +++ b/src/mapping/PathTools.cpp @@ -35,30 +35,30 @@ using namespace std; namespace PLMD { -namespace mapping{ +namespace mapping { //+PLUMEDOC TOOLS pathtools /* pathtools can be used to construct paths from pdb data The path CVs in PLUMED are curvilinear coordinates through a high dimensional vector space. -Enhanced sampling calculations are ofen run using the progress along the paths and the distance from the path as CVs +Enhanced sampling calculations are ofen run using the progress along the paths and the distance from the path as CVs as this provides a convenient way of defining a reaction coordinate for a complicated process. This method is explained in the documentation for \ref PATH. The path itself is an ordered set of equally-spaced, high-dimensional frames the way in which these frames should be constructed will depend on the problem in hand. In other words, you will need to understand the reaction -you wish to study in order to select a sensible set of frames to use in your path CV. This tool provides two +you wish to study in order to select a sensible set of frames to use in your path CV. This tool provides two methods that may be useful when it comes to constructing paths; namely: - A tool that takes in an initial guess path in which the frames are not equally spaced. This tool adjusts the positions of the frames in order to make them equally spaced so that they can be used as the basis for a path CV. -- A tool that takes two frames as input and that allows you to return a linear path connecting these two frames. The -output from this method may be useful as an initial guess path. It is arguable that a linear path rather defeats the +- A tool that takes two frames as input and that allows you to return a linear path connecting these two frames. The +output from this method may be useful as an initial guess path. It is arguable that a linear path rather defeats the purpose of the path CV method, however, as the whole purpose is to be able to define non-linear paths. -Notice that you can use these two methods and take advantage of all the ways of measuring \ref dists that are available within +Notice that you can use these two methods and take advantage of all the ways of measuring \ref dists that are available within PLUMED. The way you do this with each of these tools described above is explained in the example below. \par Examples @@ -75,12 +75,12 @@ The example below shows how can create an initial linear path connecting the two end.pdb. In this case the path output to path.pdb will consist of 6 frames: the initial and final frames that were contained in start.pdb and end.pdb as well as four equally spaced frames along the vector connecting start.pdb to end.pdb. - + \verbatim plumed pathtools --start start.pdb --end end.pdb --nframes 4 --metric OPTIMAL --out path.pdb \endverbatim -Often the idea with path cvs is to create a path connecting some initial state A to some final state B. You would +Often the idea with path cvs is to create a path connecting some initial state A to some final state B. You would in this case have representative configurations from your A and B states defined in the input files to pathtools that we have called start.pdb and end.pdb in the example above. Furthermore, it may be useful to have a few frames before your start frame and after your end frame. You can use path tools to create these extended paths as shown below. @@ -93,7 +93,7 @@ plumed pathtools --start start.pdb --end end.pdb --nframes 4 --metric OPTIMAL -- \endverbatim Notice also that when you reparameterise paths you must choose two frames to fix. Generally you chose to fix the states -that are representative of your states A and B. By default pathtools will fix the first and last frames. You can, however, +that are representative of your states A and B. By default pathtools will fix the first and last frames. You can, however, change the states to fix by taking advantage of the fixed flag as shown below. \verbatim @@ -104,20 +104,20 @@ plumed pathtools --path inpath.pdb --metric EUCLIDEAN --out outpath.pdb --fixed //+ENDPLUMEDOC class PathTools : -public CLTool + public CLTool { public: static void registerKeywords( Keywords& keys ); explicit PathTools(const CLToolOptions& co ); int main(FILE* in, FILE*out,Communicator& pc); - string description()const{ + string description()const { return "print out a description of the keywords for an action in html"; } }; PLUMED_REGISTER_CLTOOL(PathTools,"pathtools") -void PathTools::registerKeywords( Keywords& keys ){ +void PathTools::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.add("atoms","--start","a pdb file that contains the structure for the initial frame of your path"); keys.add("atoms","--end","a pdb file that contains the structure for the final frame of your path"); @@ -133,160 +133,160 @@ void PathTools::registerKeywords( Keywords& keys ){ } PathTools::PathTools(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { inputdata=commandline; } -int PathTools::main(FILE* in, FILE*out,Communicator& pc){ - - std::string mtype; parse("--metric",mtype); - std::string ifilename; parse("--path",ifilename); - std::string ofmt; parse("--arg-fmt",ofmt); - std::string ofilename; parse("--out",ofilename); - if( ifilename.length()>0 ){ - fprintf(out,"Reparameterising path in file named %s so that all frames are equally spaced \n",ifilename.c_str() ); - FILE* fp=fopen(ifilename.c_str(),"r"); - bool do_read=true; std::vector frames; - while (do_read) { - PDB mypdb; - // Read the pdb file - do_read=mypdb.readFromFilepointer(fp,false,0.1); - if( do_read ){ - ReferenceConfiguration* mymsd=metricRegister().create( mtype, mypdb ); - frames.push_back( mymsd ); mymsd->checkRead(); - } - } - std::vector fixed; parseVector("--fixed",fixed); - if( fixed.size()==1 ){ - if( fixed[0]!=0 ) error("input to --fixed should be two integers"); - fixed.resize(2); fixed[0]=0; fixed[1]=frames.size()-1; - } else if( fixed.size()==2 ){ - if( fixed[0]<0 || fixed[1]<0 || fixed[0]>(frames.size()-1) || fixed[1]>(frames.size()-1) ){ - error("input to --fixed should be two numbers between 0 and the number of frames-1"); - } - } else { - error("input to --fixed should be two integers"); - } - std::vector atoms; std::vector arg_names; - for(unsigned i=0;igetAtomRequests( atoms); - frames[i]->getArgumentRequests( arg_names ); - } - // Generate stuff to reparameterize - Pbc fake_pbc; std::vector vals; - for(unsigned i=0;igetNumberOfReferenceArguments();++i){ - vals.push_back(new Value()); vals[vals.size()-1]->setNotPeriodic(); - } - // And reparameterize - PathReparameterization myparam( fake_pbc, vals, frames ); - // And make all points equally spaced - double tol; parse("--tolerance",tol); myparam.reparameterize( fixed[0], fixed[1], tol ); - - // Ouput data on spacings - double mean=0; - MultiValue myvpack( 1, frames[0]->getNumberOfReferenceArguments() + 3*frames[0]->getNumberOfReferencePositions() + 9 ); - ReferenceValuePack mypack( frames[0]->getNumberOfReferenceArguments(), frames[0]->getNumberOfReferencePositions(), myvpack ); - for(unsigned i=1;icalc( frames[i-1]->getReferencePositions(), fake_pbc, vals, frames[i-1]->getReferenceArguments(), mypack, false ); - printf("FINAL DISTANCE BETWEEN FRAME %u AND %u IS %f \n",i-1,i,len ); - mean+=len; - } - printf("SUGGESTED LAMBDA PARAMETER IS THUS %f \n",2.3/mean/static_cast( frames.size()-1 ) ); - - // Delete all the frames - OFile ofile; ofile.open(ofilename); - for(unsigned i=0;iprint( ofile, ofmt, 10. ); delete frames[i]; } - // Delete the vals as we don't need them - for(unsigned i=0;i( mtype, mystartpdb ); - fclose(fp2); - - // Read final frame - std::string iend; parse("--end",iend); FILE* fp1=fopen(iend.c_str(),"r"); PDB myendpdb; - if( iend.length()==0 ) error("input is missing using --istart + --iend or --path"); - if( !myendpdb.readFromFilepointer(fp1,false,0.1) ) error("could not read fila " + iend); - ReferenceConfiguration* eframe=metricRegister().create( mtype, myendpdb ); - fclose(fp1); - - // Get atoms and arg requests - std::vector atoms; std::vector arg_names; - sframe->getAtomRequests( atoms); eframe->getAtomRequests( atoms); - sframe->getArgumentRequests( arg_names ); eframe->getArgumentRequests( arg_names ); - - // Now read in the rest of the instructions - unsigned nbefore, nbetween, nafter; - parse("--nframes-before-start",nbefore); parse("--nframes",nbetween); parse("--nframes-after-end",nafter); - nbetween++; - fprintf(out,"Generating linear path connecting structure in file named %s to structure in file named %s \n",istart.c_str(),iend.c_str() ); - fprintf(out,"A path consisting of %u equally-spaced frames before the initial structure, %u frames between the intial and final structures " - "and %u frames after the final structure will be created \n",nbefore,nbetween,nafter); - - // Create a vector of arguments to use for calculating displacements - Pbc fpbc; std::vector args; - for(unsigned i=0;igetNumberOfReferenceArguments();++i){ - args.push_back(new Value()); args[args.size()-1]->setNotPeriodic(); - } - - // Calculate the distance between the start and the end - MultiValue myvpack( 1, sframe->getNumberOfReferenceArguments() + 3*sframe->getNumberOfReferencePositions() + 9); - ReferenceValuePack mypack( sframe->getNumberOfReferenceArguments(), sframe->getNumberOfReferencePositions(), myvpack ); - double pathlen = sframe->calc( eframe->getReferencePositions(), fpbc, args, eframe->getReferenceArguments(), mypack, false ); - // And the spacing between frames - double delr = 1.0 / static_cast( nbetween ); - // Calculate the vector connecting the start to the end - Direction mydir(ReferenceConfigurationOptions("DIRECTION")); sframe->setupPCAStorage( mypack ); - mydir.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); mydir.zeroDirection(); - sframe->extractDisplacementVector( eframe->getReferencePositions(), args, eframe->getReferenceArguments(), false, false, mydir ); - - - // Now create frames - std::vector final_path; - Direction pos(ReferenceConfigurationOptions("DIRECTION")); - pos.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); - for(int i=0;i0 ) { + fprintf(out,"Reparameterising path in file named %s so that all frames are equally spaced \n",ifilename.c_str() ); + FILE* fp=fopen(ifilename.c_str(),"r"); + bool do_read=true; std::vector frames; + while (do_read) { + PDB mypdb; + // Read the pdb file + do_read=mypdb.readFromFilepointer(fp,false,0.1); + if( do_read ) { + ReferenceConfiguration* mymsd=metricRegister().create( mtype, mypdb ); + frames.push_back( mymsd ); mymsd->checkRead(); + } + } + std::vector fixed; parseVector("--fixed",fixed); + if( fixed.size()==1 ) { + if( fixed[0]!=0 ) error("input to --fixed should be two integers"); + fixed.resize(2); fixed[0]=0; fixed[1]=frames.size()-1; + } else if( fixed.size()==2 ) { + if( fixed[0]<0 || fixed[1]<0 || fixed[0]>(frames.size()-1) || fixed[1]>(frames.size()-1) ) { + error("input to --fixed should be two numbers between 0 and the number of frames-1"); + } + } else { + error("input to --fixed should be two integers"); + } + std::vector atoms; std::vector arg_names; + for(unsigned i=0; igetAtomRequests( atoms); + frames[i]->getArgumentRequests( arg_names ); + } + // Generate stuff to reparameterize + Pbc fake_pbc; std::vector vals; + for(unsigned i=0; igetNumberOfReferenceArguments(); ++i) { + vals.push_back(new Value()); vals[vals.size()-1]->setNotPeriodic(); + } + // And reparameterize + PathReparameterization myparam( fake_pbc, vals, frames ); + // And make all points equally spaced + double tol; parse("--tolerance",tol); myparam.reparameterize( fixed[0], fixed[1], tol ); + + // Ouput data on spacings + double mean=0; + MultiValue myvpack( 1, frames[0]->getNumberOfReferenceArguments() + 3*frames[0]->getNumberOfReferencePositions() + 9 ); + ReferenceValuePack mypack( frames[0]->getNumberOfReferenceArguments(), frames[0]->getNumberOfReferencePositions(), myvpack ); + for(unsigned i=1; icalc( frames[i-1]->getReferencePositions(), fake_pbc, vals, frames[i-1]->getReferenceArguments(), mypack, false ); + printf("FINAL DISTANCE BETWEEN FRAME %u AND %u IS %f \n",i-1,i,len ); + mean+=len; + } + printf("SUGGESTED LAMBDA PARAMETER IS THUS %f \n",2.3/mean/static_cast( frames.size()-1 ) ); + + // Delete all the frames + OFile ofile; ofile.open(ofilename); + for(unsigned i=0; iprint( ofile, ofmt, 10. ); delete frames[i]; } + // Delete the vals as we don't need them + for(unsigned i=0; i( mtype, mystartpdb ); + fclose(fp2); + +// Read final frame + std::string iend; parse("--end",iend); FILE* fp1=fopen(iend.c_str(),"r"); PDB myendpdb; + if( iend.length()==0 ) error("input is missing using --istart + --iend or --path"); + if( !myendpdb.readFromFilepointer(fp1,false,0.1) ) error("could not read fila " + iend); + ReferenceConfiguration* eframe=metricRegister().create( mtype, myendpdb ); + fclose(fp1); + +// Get atoms and arg requests + std::vector atoms; std::vector arg_names; + sframe->getAtomRequests( atoms); eframe->getAtomRequests( atoms); + sframe->getArgumentRequests( arg_names ); eframe->getArgumentRequests( arg_names ); + +// Now read in the rest of the instructions + unsigned nbefore, nbetween, nafter; + parse("--nframes-before-start",nbefore); parse("--nframes",nbetween); parse("--nframes-after-end",nafter); + nbetween++; + fprintf(out,"Generating linear path connecting structure in file named %s to structure in file named %s \n",istart.c_str(),iend.c_str() ); + fprintf(out,"A path consisting of %u equally-spaced frames before the initial structure, %u frames between the intial and final structures " + "and %u frames after the final structure will be created \n",nbefore,nbetween,nafter); + +// Create a vector of arguments to use for calculating displacements + Pbc fpbc; std::vector args; + for(unsigned i=0; igetNumberOfReferenceArguments(); ++i) { + args.push_back(new Value()); args[args.size()-1]->setNotPeriodic(); + } + +// Calculate the distance between the start and the end + MultiValue myvpack( 1, sframe->getNumberOfReferenceArguments() + 3*sframe->getNumberOfReferencePositions() + 9); + ReferenceValuePack mypack( sframe->getNumberOfReferenceArguments(), sframe->getNumberOfReferencePositions(), myvpack ); + double pathlen = sframe->calc( eframe->getReferencePositions(), fpbc, args, eframe->getReferenceArguments(), mypack, false ); +// And the spacing between frames + double delr = 1.0 / static_cast( nbetween ); +// Calculate the vector connecting the start to the end + Direction mydir(ReferenceConfigurationOptions("DIRECTION")); sframe->setupPCAStorage( mypack ); + mydir.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); mydir.zeroDirection(); + sframe->extractDisplacementVector( eframe->getReferencePositions(), args, eframe->getReferenceArguments(), false, false, mydir ); + + +// Now create frames + std::vector final_path; + Direction pos(ReferenceConfigurationOptions("DIRECTION")); + pos.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); + for(int i=0; igetReferencePositions(), sframe->getReferenceArguments() ); - pos.displaceReferenceConfiguration( -i*delr, mydir ); - final_path.push_back( metricRegister().create(mtype) ); + pos.displaceReferenceConfiguration( -i*delr, mydir ); + final_path.push_back( metricRegister().create(mtype) ); final_path[final_path.size()-1]->setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); final_path[final_path.size()-1]->setReferenceConfig( pos.getReferencePositions(), pos.getReferenceArguments(), sframe->getReferenceMetric() ); - } - for(unsigned i=1;igetReferencePositions(), sframe->getReferenceArguments() ); pos.displaceReferenceConfiguration( i*delr, mydir ); - final_path.push_back( metricRegister().create(mtype) ); + final_path.push_back( metricRegister().create(mtype) ); final_path[final_path.size()-1]->setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); final_path[final_path.size()-1]->setReferenceConfig( pos.getReferencePositions(), pos.getReferenceArguments(), sframe->getReferenceMetric() ); - } - for(unsigned i=0;igetReferencePositions(), eframe->getReferenceArguments() ); pos.displaceReferenceConfiguration( i*delr, mydir ); final_path.push_back( metricRegister().create(mtype) ); final_path[final_path.size()-1]->setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); final_path[final_path.size()-1]->setReferenceConfig( pos.getReferencePositions(), pos.getReferenceArguments(), sframe->getReferenceMetric() ); - } + } - double mean=0; printf("DISTANCE BETWEEN ORIGINAL FRAMES %f \n",pathlen); - for(unsigned i=1;icalc( final_path[i-1]->getReferencePositions(), fpbc, args, final_path[i-1]->getReferenceArguments(), mypack, false ); printf("FINAL DISTANCE BETWEEN FRAME %u AND %u IS %f \n",i-1,i,len ); mean+=len; - } - printf("SUGGESTED LAMBDA PARAMETER IS THUS %f \n",2.3/mean/static_cast( final_path.size()-1 ) ); - - OFile ofile; ofile.open(ofilename); - for(unsigned i=0;iprint( ofile, ofmt, 10. ); delete final_path[i]; } - // Delete the args as we don't need them anymore - for(unsigned i=0;i( final_path.size()-1 ) ); + + OFile ofile; ofile.open(ofilename); + for(unsigned i=0; iprint( ofile, ofmt, 10. ); delete final_path[i]; } +// Delete the args as we don't need them anymore + for(unsigned i=0; i( getAction() ); 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; + mycoordnumber=mymap->getPropertyIndex( getLabel() ); + usetol=true; norm=true; - for(unsigned i=0;igetFullNumberOfTasks();++i){ - if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) { + if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); } } -std::string SpathVessel::value_descriptor(){ +std::string SpathVessel::value_descriptor() { return "the position on the path"; } -void SpathVessel::prepare(){ +void SpathVessel::prepare() { foundoneclose=false; } @@ -78,10 +78,10 @@ void SpathVessel::calculate( const unsigned& current, MultiValue& myvals, std::v double pp=mymap->getPropertyValue( current, mycoordnumber ), weight=myvals.get(0); if( weightgetNumberOfDerivatives(); - buffer[bufstart] += weight*pp; buffer[bufstart+1+nderivatives] += weight; - if( getAction()->derivativesAreRequired() ){ - myvals.chainRule( 0, 0, 1, 0, pp, bufstart, buffer ); - myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); + buffer[bufstart] += weight*pp; buffer[bufstart+1+nderivatives] += weight; + if( getAction()->derivativesAreRequired() ) { + myvals.chainRule( 0, 0, 1, 0, pp, bufstart, buffer ); + myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); } } diff --git a/src/mapping/TrigonometricPathVessel.cpp b/src/mapping/TrigonometricPathVessel.cpp index 920a792e8e..adf049b708 100644 --- a/src/mapping/TrigonometricPathVessel.cpp +++ b/src/mapping/TrigonometricPathVessel.cpp @@ -27,193 +27,193 @@ namespace mapping { PLUMED_REGISTER_VESSEL(TrigonometricPathVessel,"GPATH") -void TrigonometricPathVessel::registerKeywords( Keywords& keys ){ +void TrigonometricPathVessel::registerKeywords( Keywords& keys ) { StoreDataVessel::registerKeywords(keys); } -void TrigonometricPathVessel::reserveKeyword( Keywords& keys ){ +void TrigonometricPathVessel::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","GPATH","calculate the position on the path using trigonometry"); keys.addOutputComponent("gspath","GPATH","the position on the path calculated using trigonometry"); keys.addOutputComponent("gzpath","GPATH","the distance from the path calculated using trigonometry"); } TrigonometricPathVessel::TrigonometricPathVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da), -projdir(ReferenceConfigurationOptions("DIRECTION")), -mydpack1( 1, getAction()->getNumberOfDerivatives() ), -mydpack2( 1, getAction()->getNumberOfDerivatives() ), -mydpack3( 1, getAction()->getNumberOfDerivatives() ), -mypack1( 0, 0, mydpack1 ), -mypack2( 0, 0, mydpack2 ), -mypack3( 0, 0, mydpack3 ) + StoreDataVessel(da), + projdir(ReferenceConfigurationOptions("DIRECTION")), + mydpack1( 1, getAction()->getNumberOfDerivatives() ), + mydpack2( 1, getAction()->getNumberOfDerivatives() ), + mydpack3( 1, getAction()->getNumberOfDerivatives() ), + mypack1( 0, 0, mydpack1 ), + mypack2( 0, 0, mydpack2 ), + mypack3( 0, 0, mydpack3 ) { mymap=dynamic_cast( getAction() ); plumed_massert( mymap, "Trigonometric path vessel can only be used with mappings"); // Retrieve the index of the property in the underlying mapping if( mymap->getNumberOfProperties()!=1 ) error("cannot use trigonometric paths when there are multiple properties"); - for(unsigned i=0;igetFullNumberOfTasks();++i){ - if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) { + if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); } - mymap->addComponentWithDerivatives("gspath"); mymap->componentIsNotPeriodic("gspath"); + mymap->addComponentWithDerivatives("gspath"); mymap->componentIsNotPeriodic("gspath"); sp=mymap->copyOutput( mymap->getNumberOfComponents()-1 ); sp->resizeDerivatives( mymap->getNumberOfDerivatives() ); - mymap->addComponentWithDerivatives("gzpath"); mymap->componentIsNotPeriodic("gzpath"); + mymap->addComponentWithDerivatives("gzpath"); mymap->componentIsNotPeriodic("gzpath"); zp=mymap->copyOutput( mymap->getNumberOfComponents()-1 ); zp->resizeDerivatives( mymap->getNumberOfDerivatives() ); // Check we have PCA - ReferenceConfiguration* ref0=mymap->getReferenceConfiguration(0); - for(unsigned i=0;igetFullNumberOfTasks();++i){ - if( !(mymap->getReferenceConfiguration(i))->pcaIsEnabledForThisReference() ) error("pca must be implemented in order to use trigometric path"); - if( ref0->getName()!=(mymap->getReferenceConfiguration(i))->getName() ) error("cannot use mixed metrics"); - if( mymap->getNumberOfAtoms()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferencePositions() ) error("all frames must use the same set of atoms"); - if( mymap->getNumberOfArguments()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferenceArguments() ) error("all frames must use the same set of arguments"); + ReferenceConfiguration* ref0=mymap->getReferenceConfiguration(0); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) { + if( !(mymap->getReferenceConfiguration(i))->pcaIsEnabledForThisReference() ) error("pca must be implemented in order to use trigometric path"); + if( ref0->getName()!=(mymap->getReferenceConfiguration(i))->getName() ) error("cannot use mixed metrics"); + if( mymap->getNumberOfAtoms()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferencePositions() ) error("all frames must use the same set of atoms"); + if( mymap->getNumberOfArguments()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferenceArguments() ) error("all frames must use the same set of arguments"); } cargs.resize( mymap->getNumberOfArguments() ); std::vector argument_names( mymap->getNumberOfArguments() ); - for(unsigned i=0;igetNumberOfArguments();++i) argument_names[i] = (mymap->getPntrToArgument(i))->getName(); + for(unsigned i=0; igetNumberOfArguments(); ++i) argument_names[i] = (mymap->getPntrToArgument(i))->getName(); projdir.setNamesAndAtomNumbers( mymap->getAbsoluteIndexes(), argument_names ); mypack1.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); ref0->setupPCAStorage( mypack1 ); mypack2.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); ref0->setupPCAStorage( mypack2 ); - mypack3.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); - for(unsigned i=0;igetNumberOfAtoms();++i){ mypack1.setAtomIndex(i,i); mypack2.setAtomIndex(i,i); mypack3.setAtomIndex(i,i); } + mypack3.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); + for(unsigned i=0; igetNumberOfAtoms(); ++i) { mypack1.setAtomIndex(i,i); mypack2.setAtomIndex(i,i); mypack3.setAtomIndex(i,i); } mypack1_stashd_atoms.resize( mymap->getNumberOfAtoms() ); mypack1_stashd_args.resize( mymap->getNumberOfArguments() ); } -std::string TrigonometricPathVessel::description(){ - return "values gspath and gzpath contain the position on and distance from the path calculated using trigonometry"; +std::string TrigonometricPathVessel::description() { + return "values gspath and gzpath contain the position on and distance from the path calculated using trigonometry"; } -void TrigonometricPathVessel::resize(){ +void TrigonometricPathVessel::resize() { StoreDataVessel::resize(); - if( getAction()->derivativesAreRequired() ){ + if( getAction()->derivativesAreRequired() ) { unsigned nderivatives=getAction()->getNumberOfDerivatives(); sp->resizeDerivatives( nderivatives ); zp->resizeDerivatives( nderivatives ); } } -void TrigonometricPathVessel::finish( const std::vector& buffer ){ +void TrigonometricPathVessel::finish( const std::vector& buffer ) { // Store the data calculated during mpi loop StoreDataVessel::finish( buffer ); - // Get current value of all arguments - for(unsigned i=0;igetArgument(i); + // Get current value of all arguments + for(unsigned i=0; igetArgument(i); // Determine closest and second closest point to current position double lambda=mymap->getLambda(); std::vector dist( getNumberOfComponents() ), dist2( getNumberOfComponents() );; - retrieveSequentialValue( 0, false, dist ); + retrieveSequentialValue( 0, false, dist ); retrieveSequentialValue( 1, false, dist2 ); iclose1=getStoreIndex(0); iclose2=getStoreIndex(1); - double mindist1=dist[0], mindist2=dist2[0]; - if( lambda>0.0 ){ - mindist1=-std::log( dist[0] ) / lambda; - mindist2=-std::log( dist2[0] ) / lambda; + double mindist1=dist[0], mindist2=dist2[0]; + if( lambda>0.0 ) { + mindist1=-std::log( dist[0] ) / lambda; + mindist2=-std::log( dist2[0] ) / lambda; } - if( mindist20.0 ) ndist=-std::log( dist[0] ) / lambda; - if( ndist0.0 ) ndist=-std::log( dist[0] ) / lambda; + if( ndist1 ) isign=1; else if( isign<-1 ) isign=-1; int iclose3 = iclose1 + isign; double v2v2; - // We now have to compute vectors connecting the three closest points to the + // We now have to compute vectors connecting the three closest points to the // new point double v1v1 = (mymap->getReferenceConfiguration( iclose1 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack1, true ); - double v3v3 = (mymap->getReferenceConfiguration( iclose2 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack3, true ); - if( iclose3<0 || iclose3>=mymap->getFullNumberOfTasks() ){ - ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); - v2v2=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), - conf2->getReferenceArguments(), mypack2, true ); - (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), - conf2->getReferenceArguments(), true, false, projdir ); + double v3v3 = (mymap->getReferenceConfiguration( iclose2 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack3, true ); + if( iclose3<0 || iclose3>=mymap->getFullNumberOfTasks() ) { + ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); + v2v2=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), + conf2->getReferenceArguments(), mypack2, true ); + (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), + conf2->getReferenceArguments(), true, false, projdir ); } else { - ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose3 ); - v2v2=(mymap->getReferenceConfiguration( iclose1 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), - conf2->getReferenceArguments(), mypack2, true ); - (mymap->getReferenceConfiguration( iclose1 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), - conf2->getReferenceArguments(), true, false, projdir ); + ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose3 ); + v2v2=(mymap->getReferenceConfiguration( iclose1 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), + conf2->getReferenceArguments(), mypack2, true ); + (mymap->getReferenceConfiguration( iclose1 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), + conf2->getReferenceArguments(), true, false, projdir ); } // Stash derivatives of v1v1 - for(unsigned i=0;igetNumberOfArguments();++i) mypack1_stashd_args[i]=mypack1.getArgumentDerivative(i); - for(unsigned i=0;igetNumberOfAtoms();++i) mypack1_stashd_atoms[i]=mypack1.getAtomDerivative(i); + for(unsigned i=0; igetNumberOfArguments(); ++i) mypack1_stashd_args[i]=mypack1.getArgumentDerivative(i); + for(unsigned i=0; igetNumberOfAtoms(); ++i) mypack1_stashd_atoms[i]=mypack1.getAtomDerivative(i); // Calculate the dot product of v1 with v2 double v1v2 = (mymap->getReferenceConfiguration(iclose1))->projectDisplacementOnVector( projdir, mymap->getPositions(), mymap->getArguments(), cargs, mypack1 ); - + // This computes s value double spacing = mymap->getPropertyValue( iclose1, 0 ) - mymap->getPropertyValue( iclose2, 0 ); double root = sqrt( v1v2*v1v2 - v2v2 * ( v1v1 - v3v3) ); dx = 0.5 * ( (root + v1v2) / v2v2 - 1.); - double path_s = mymap->getPropertyValue(iclose1, 0) + spacing * dx; sp->set( path_s ); - double fact = 0.25*spacing / v2v2; + double path_s = mymap->getPropertyValue(iclose1, 0) + spacing * dx; sp->set( path_s ); + double fact = 0.25*spacing / v2v2; // Derivative of s wrt arguments - for(unsigned i=0;igetNumberOfArguments();++i){ - sp->setDerivative( i, fact*( mypack2.getArgumentDerivative(i) + (v2v2 * (-mypack1_stashd_args[i] + mypack3.getArgumentDerivative(i)) + for(unsigned i=0; igetNumberOfArguments(); ++i) { + sp->setDerivative( i, fact*( mypack2.getArgumentDerivative(i) + (v2v2 * (-mypack1_stashd_args[i] + mypack3.getArgumentDerivative(i)) + v1v2*mypack2.getArgumentDerivative(i) )/root ) ); } // Derivative of s wrt atoms unsigned narg=mymap->getNumberOfArguments(); Tensor vir; vir.zero(); fact = 0.5*spacing / v2v2; - if( mymap->getNumberOfAtoms()>0 ){ - for(unsigned i=0;igetNumberOfAtoms();++i){ - Vector ader = fact*(( v1v2*mypack1.getAtomDerivative(i) + 0.5*v2v2*(-mypack1_stashd_atoms[i] + mypack3.getAtomDerivative(i) ) )/root + mypack1.getAtomDerivative(i) ); - for(unsigned k=0;k<3;++k) sp->setDerivative( narg+3*i+k, ader[k] ); - vir-=Tensor( mymap->getPosition(i), ader ); - } - // Set the virial - unsigned nbase=narg+3*mymap->getNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) sp->setDerivative( nbase+3*i+j, vir(i,j) ); + if( mymap->getNumberOfAtoms()>0 ) { + for(unsigned i=0; igetNumberOfAtoms(); ++i) { + Vector ader = fact*(( v1v2*mypack1.getAtomDerivative(i) + 0.5*v2v2*(-mypack1_stashd_atoms[i] + mypack3.getAtomDerivative(i) ) )/root + mypack1.getAtomDerivative(i) ); + for(unsigned k=0; k<3; ++k) sp->setDerivative( narg+3*i+k, ader[k] ); + vir-=Tensor( mymap->getPosition(i), ader ); + } + // Set the virial + unsigned nbase=narg+3*mymap->getNumberOfAtoms(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) sp->setDerivative( nbase+3*i+j, vir(i,j) ); } // Now compute z value ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); - double v4v4=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), - conf2->getReferenceArguments(), mypack2, true ); + double v4v4=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), + conf2->getReferenceArguments(), mypack2, true ); // Extract vector connecting frames (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), - conf2->getReferenceArguments(), true, false, projdir ); + conf2->getReferenceArguments(), true, false, projdir ); // Calculate projection of vector on line connnecting frames double proj = (mymap->getReferenceConfiguration(iclose1))->projectDisplacementOnVector( projdir, mymap->getPositions(), mymap->getArguments(), cargs, mypack1 ); - double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; + double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; - // Derivatives for z path - path_z = sqrt(path_z); zp->set( path_z ); vir.zero(); - for(unsigned i=0;igetNumberOfArguments();++i) zp->setDerivative( i, (mypack1_stashd_args[i] - 2*dx*mypack1.getArgumentDerivative(i))/(2.0*path_z) ); + // Derivatives for z path + path_z = sqrt(path_z); zp->set( path_z ); vir.zero(); + for(unsigned i=0; igetNumberOfArguments(); ++i) zp->setDerivative( i, (mypack1_stashd_args[i] - 2*dx*mypack1.getArgumentDerivative(i))/(2.0*path_z) ); // Derivative wrt atoms - if( mymap->getNumberOfAtoms()>0 ){ - for(unsigned i=0;igetNumberOfAtoms();++i){ - Vector dxder; for(unsigned k=0;k<3;++k) dxder[k] = ( 2*v4v4*dx - 2*proj )*spacing*sp->getDerivative( narg + 3*i+k ); - Vector ader = ( mypack1_stashd_atoms[i] - 2.*dx*mypack1.getAtomDerivative(i) + dxder )/ (2.0*path_z); - for(unsigned k=0;k<3;++k) zp->setDerivative( narg+3*i+k, ader[k] ); - vir-=Tensor( mymap->getPosition(i), ader ); - } - // Set the virial - unsigned nbase=narg+3*mymap->getNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) zp->setDerivative( nbase+3*i+j, vir(i,j) ); + if( mymap->getNumberOfAtoms()>0 ) { + for(unsigned i=0; igetNumberOfAtoms(); ++i) { + Vector dxder; for(unsigned k=0; k<3; ++k) dxder[k] = ( 2*v4v4*dx - 2*proj )*spacing*sp->getDerivative( narg + 3*i+k ); + Vector ader = ( mypack1_stashd_atoms[i] - 2.*dx*mypack1.getAtomDerivative(i) + dxder )/ (2.0*path_z); + for(unsigned k=0; k<3; ++k) zp->setDerivative( narg+3*i+k, ader[k] ); + vir-=Tensor( mymap->getPosition(i), ader ); + } + // Set the virial + unsigned nbase=narg+3*mymap->getNumberOfAtoms(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) zp->setDerivative( nbase+3*i+j, vir(i,j) ); } } -bool TrigonometricPathVessel::applyForce( std::vector& forces ){ - std::vector tmpforce( forces.size(), 0.0 ); - forces.assign(forces.size(),0.0); bool wasforced=false; - if( sp->applyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;j& forces ) { + std::vector tmpforce( forces.size(), 0.0 ); + forces.assign(forces.size(),0.0); bool wasforced=false; + if( sp->applyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; japplyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; j( getAction() ); plumed_massert( mymap, "ZpathVessel should only be used with mappings"); invlambda = 1.0 / mymap->getLambda(); usetol=true; } -std::string ZpathVessel::value_descriptor(){ +std::string ZpathVessel::value_descriptor() { return "the distance from the low-dimensional manifold"; } @@ -65,10 +65,10 @@ double ZpathVessel::calcTransform( const double& val, double& dv ) const { dv=0.0; return 1.0; } -double ZpathVessel::finalTransform( const double& val, double& dv ){ - dv = -invlambda / val; - return -invlambda*std::log( val ); -} +double ZpathVessel::finalTransform( const double& val, double& dv ) { + dv = -invlambda / val; + return -invlambda*std::log( val ); +} } } diff --git a/src/multicolvar/ActionVolume.cpp b/src/multicolvar/ActionVolume.cpp index d490ef31d9..5f12881e13 100644 --- a/src/multicolvar/ActionVolume.cpp +++ b/src/multicolvar/ActionVolume.cpp @@ -24,7 +24,7 @@ namespace PLMD { namespace multicolvar { -void ActionVolume::registerKeywords( Keywords& keys ){ +void ActionVolume::registerKeywords( Keywords& keys ) { VolumeGradientBase::registerKeywords( keys ); if( keys.reserved("VMEAN") ) keys.use("VMEAN"); keys.use("MEAN"); keys.use("LESS_THAN"); keys.use("MORE_THAN"); @@ -35,39 +35,39 @@ void ActionVolume::registerKeywords( Keywords& keys ){ } ActionVolume::ActionVolume(const ActionOptions&ao): -Action(ao), -VolumeGradientBase(ao) + Action(ao), + VolumeGradientBase(ao) { // Find number of quantities - if( getPntrToMultiColvar()->isDensity() ) nquantities=2; // Value + 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 + else nquantities = 1 + getPntrToMultiColvar()->getNumberOfQuantities()-2 + 1; // Norm + vector + weight // Output some nice information std::string functype=getPntrToMultiColvar()->getName(); std::transform( functype.begin(), functype.end(), functype.begin(), tolower ); - log.printf(" calculating %s inside region of insterest\n",functype.c_str() ); + log.printf(" calculating %s inside region of insterest\n",functype.c_str() ); parseFlag("OUTSIDE",not_in); sigma=0.0; - if( keywords.exists("SIGMA") ) parse("SIGMA",sigma); - if( keywords.exists("KERNEL") ) parse("KERNEL",kerneltype); - - if( getPntrToMultiColvar()->isDensity() ){ - std::string input; - addVessel( "SUM", input, -1 ); // -1 here means that this value will be named getLabel() - } + if( keywords.exists("SIGMA") ) parse("SIGMA",sigma); + if( keywords.exists("KERNEL") ) parse("KERNEL",kerneltype); + + if( getPntrToMultiColvar()->isDensity() ) { + std::string input; + addVessel( "SUM", input, -1 ); // -1 here means that this value will be named getLabel() + } readVesselKeywords(); } void ActionVolume::calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const { Vector catom_pos=getPntrToMultiColvar()->getCentralAtomPos( curr ); - double weight; Vector wdf; Tensor vir; std::vector refders( getNumberOfAtoms() ); - weight=calculateNumberInside( catom_pos, wdf, vir, refders ); - if( not_in ){ - weight = 1.0 - weight; wdf *= -1.; vir *=-1; - for(unsigned i=0;i refders( getNumberOfAtoms() ); + weight=calculateNumberInside( catom_pos, wdf, vir, refders ); + if( not_in ) { + weight = 1.0 - weight; wdf *= -1.; vir *=-1; + for(unsigned i=0; i all_atoms; @@ -129,28 +129,28 @@ MultiColvarBase(ao) // Resize target target.resize( getFullNumberOfTasks() ); // Setup central atom indices - std::vector catom_ind(4, false); + std::vector catom_ind(4, false); catom_ind[1]=catom_ind[2]=true; setAtomsForCentralAtom( catom_ind ); // Read in reference values unsigned ntarget=0; - for(unsigned i=0;i0 ){ + if( sfinput.length()>0 ) { + use_sf=true; + weightHasDerivatives=true; + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + sf2.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); + } else { + parse("SWITCHA",sfinput); + if(sfinput.length()>0) { use_sf=true; weightHasDerivatives=true; sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); + sfinput.clear(); parse("SWITCHB",sfinput); + if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); - } else { - parse("SWITCHA",sfinput); - if(sfinput.length()>0){ - use_sf=true; - weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); - sfinput.clear(); parse("SWITCHB",sfinput); - if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); - sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); - log.printf(" only calculating angles when the distance between GROUPA and GROUPB atoms is less than %s\n", sf1.description().c_str() ); - log.printf(" only calculating angles when the distance between GROUPA and GROUPC atoms is less than %s\n", sf2.description().c_str() ); - } + if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); + log.printf(" only calculating angles when the distance between GROUPA and GROUPB atoms is less than %s\n", sf1.description().c_str() ); + log.printf(" only calculating angles when the distance between GROUPA and GROUPC atoms is less than %s\n", sf2.description().c_str() ); + } } // Read in the atoms std::vector all_atoms; readGroupKeywords( "GROUP", "GROUPA", "GROUPB", "GROUPC", false, true, all_atoms ); if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 3, all_atoms ); setupMultiColvarBase( all_atoms ); - // Set cutoff for link cells - if( use_sf ){ - setLinkCellCutoff( sf1.get_dmax() ); - rcut2_1=sf1.get_dmax()*sf1.get_dmax(); - rcut2_2=sf2.get_dmax()*sf2.get_dmax(); + // Set cutoff for link cells + if( use_sf ) { + setLinkCellCutoff( sf1.get_dmax() ); + rcut2_1=sf1.get_dmax()*sf1.get_dmax(); + rcut2_2=sf2.get_dmax()*sf2.get_dmax(); } // And check everything has been read in correctly @@ -180,23 +180,23 @@ use_sf(false) } double Angles::calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& myatoms ) const { - if(!use_sf) return 1.0; + if(!use_sf) return 1.0; Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) ); Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double w1, w2, dw1, dw2, wtot; - double ldij = dij.modulo2(), ldik = dik.modulo2(); + double ldij = dij.modulo2(), ldik = dik.modulo2(); - if( use_sf ){ - if( ldij>rcut2_1 || ldik>rcut2_2 ) return 0.0; + if( use_sf ) { + if( ldij>rcut2_1 || ldik>rcut2_2 ) return 0.0; } w1=sf1.calculateSqr( ldij, dw1 ); w2=sf2.calculateSqr( ldik, dw2 ); - wtot=w1*w2; dw1*=weight*w2; dw2*=weight*w1; + wtot=w1*w2; dw1*=weight*w2; dw2*=weight*w1; addAtomDerivatives( 0, 1, dw2*dik, myatoms ); - addAtomDerivatives( 0, 0, -dw1*dij - dw2*dik, myatoms ); + addAtomDerivatives( 0, 0, -dw1*dij - dw2*dik, myatoms ); addAtomDerivatives( 0, 2, dw1*dij, myatoms ); myatoms.addBoxDerivatives( 0, (-dw1)*Tensor(dij,dij) + (-dw2)*Tensor(dik,dik) ); return wtot; @@ -206,7 +206,7 @@ double Angles::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) ); Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - Vector ddij,ddik; PLMD::Angle a; + Vector ddij,ddik; PLMD::Angle a; double angle=a.compute(dij,dik,ddij,ddik); // And finish the calculation diff --git a/src/multicolvar/AtomValuePack.cpp b/src/multicolvar/AtomValuePack.cpp index b9bf9793ee..03f4c14f10 100644 --- a/src/multicolvar/AtomValuePack.cpp +++ b/src/multicolvar/AtomValuePack.cpp @@ -27,72 +27,72 @@ namespace PLMD { namespace multicolvar { AtomValuePack::AtomValuePack( MultiValue& vals, MultiColvarBase const * mcolv ): -myvals(vals), -mycolv(mcolv), -natoms(0), -indices( vals.getIndices() ), -sort_vector( vals.getSortIndices() ), -myatoms( vals.getAtomVector() ) + myvals(vals), + mycolv(mcolv), + natoms(0), + indices( vals.getIndices() ), + sort_vector( vals.getSortIndices() ), + myatoms( vals.getAtomVector() ) { - if( indices.size()!=mcolv->getNumberOfAtoms() ){ - indices.resize( mcolv->getNumberOfAtoms() ); - sort_vector.resize( mcolv->getNumberOfAtoms() ); + if( indices.size()!=mcolv->getNumberOfAtoms() ) { + indices.resize( mcolv->getNumberOfAtoms() ); + sort_vector.resize( mcolv->getNumberOfAtoms() ); myatoms.resize( mcolv->getNumberOfAtoms() ); } } -unsigned AtomValuePack::setupAtomsFromLinkCells( const std::vector& cind, const Vector& cpos, const LinkCells& linkcells ){ +unsigned AtomValuePack::setupAtomsFromLinkCells( const std::vector& cind, const Vector& cpos, const LinkCells& linkcells ) { if( cells_required.size()!=linkcells.getNumberOfCells() ) cells_required.resize( linkcells.getNumberOfCells() ); // Build the list of cells that we need unsigned ncells_required=0; linkcells.addRequiredCells( linkcells.findMyCell( cpos ), ncells_required, cells_required ); // Now build the list of atoms we need - natoms=cind.size(); for(unsigned i=0;igetPositionOfAtomForLinkCells( indices[i] ) - cpos; +// linkcells.retrieveNeighboringAtoms( cpos, natoms, indices ); + for(unsigned i=0; igetPositionOfAtomForLinkCells( indices[i] ) - cpos; if( mycolv->usesPbc() ) mycolv->applyPbc( myatoms, natoms ); return natoms; } -void AtomValuePack::updateUsingIndices(){ +void AtomValuePack::updateUsingIndices() { if( myvals.updateComplete() ) return; unsigned jactive=0; - for(unsigned i=0;igetNumberOfAtoms(); - if( myvals.isActive( nvir ) ){ - for(unsigned i=0;i<9;++i) myvals.putIndexInActiveArray( nvir + i ); + if( myvals.isActive( nvir ) ) { + for(unsigned i=0; i<9; ++i) myvals.putIndexInActiveArray( nvir + i ); } myvals.completeUpdate(); } -void AtomValuePack::addComDerivatives( const int& ind, const Vector& der, CatomPack& catom_der ){ - if( ind<0 ){ - for(unsigned ider=0;ider& myatoms; /// This is stuff for link cells - std::vector cells_required; + std::vector cells_required; /// - void addDerivative( const unsigned& , const unsigned& , const double& ); + void addDerivative( const unsigned&, const unsigned&, const double& ); /// - void addAtomsDerivatives( const unsigned& , const unsigned& , const Vector& ); + void addAtomsDerivatives( const unsigned&, const unsigned&, const Vector& ); /// void addTemporyAtomsDerivatives( const unsigned& jder, const Vector& der ); public: @@ -62,7 +62,7 @@ friend class LocalAverage; /// Set the number of atoms void setNumberOfAtoms( const unsigned& ); /// Set the index for one of the atoms - void setIndex( const unsigned& , const unsigned& ); + void setIndex( const unsigned&, const unsigned& ); /// void setAtomIndex( const unsigned& j, const unsigned& ind ); /// @@ -80,13 +80,13 @@ friend class LocalAverage; /// Get the absolute index of the ith atom in the list AtomNumber getAbsoluteIndex( const unsigned& j ) const ; /// - void setValue( const unsigned& , const double& ); + void setValue( const unsigned&, const double& ); /// void addValue( const unsigned& ival, const double& vv ); /// double getValue( const unsigned& ) const ; /// - void addBoxDerivatives( const unsigned& , const Tensor& ); + void addBoxDerivatives( const unsigned&, const Tensor& ); /// void addTemporyBoxDerivatives( const Tensor& vir ); /// @@ -94,13 +94,13 @@ friend class LocalAverage; /// void updateDynamicList(); /// - void addComDerivatives( const int& , const Vector& , CatomPack& ); + void addComDerivatives( const int&, const Vector&, CatomPack& ); /// MultiValue& getUnderlyingMultiValue(); }; inline -void AtomValuePack::setNumberOfAtoms( const unsigned& nat ){ +void AtomValuePack::setNumberOfAtoms( const unsigned& nat ) { natoms=nat; } @@ -115,17 +115,17 @@ unsigned AtomValuePack::getNumberOfDerivatives() const { } inline -void AtomValuePack::setIndex( const unsigned& j, const unsigned& ind ){ - plumed_dbg_assert( jgetPositionOfAtomForLinkCells( ind ); } @@ -134,29 +134,29 @@ unsigned AtomValuePack::getIndex( const unsigned& j ) const { plumed_dbg_assert( jatom_lab[jatom].first>0 ){ - unsigned mmc=mycolv->atom_lab[jatom].first - 1; - return (mycolv->mybasemulticolvars[mmc])->getAbsoluteIndexOfCentralAtom( mycolv->atom_lab[jatom].second ); + if( mycolv->atom_lab[jatom].first>0 ) { + unsigned mmc=mycolv->atom_lab[jatom].first - 1; + return (mycolv->mybasemulticolvars[mmc])->getAbsoluteIndexOfCentralAtom( mycolv->atom_lab[jatom].second ); } return mycolv->getAbsoluteIndex( mycolv->atom_lab[jatom].second ); } inline -Vector& AtomValuePack::getPosition( const unsigned& iatom ){ +Vector& AtomValuePack::getPosition( const unsigned& iatom ) { plumed_dbg_assert( iatomgetNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addTemporyDerivative( nvir + 3*i+j, vir(i,j) ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addTemporyDerivative( nvir + 3*i+j, vir(i,j) ); } inline -void AtomValuePack::addBoxDerivatives( const unsigned& ival , const Tensor& vir ){ +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) ); + 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(){ +void AtomValuePack::updateDynamicList() { if( myvals.updateComplete() ) return; myvals.updateDynamicList(); } inline -MultiValue& AtomValuePack::getUnderlyingMultiValue(){ +MultiValue& AtomValuePack::getUnderlyingMultiValue() { return myvals; -} +} } } diff --git a/src/multicolvar/Bridge.cpp b/src/multicolvar/Bridge.cpp index e56ec84d11..42198ffa1e 100644 --- a/src/multicolvar/Bridge.cpp +++ b/src/multicolvar/Bridge.cpp @@ -29,10 +29,10 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { -//+PLUMEDOC MCOLVAR BRIDGE +//+PLUMEDOC MCOLVAR BRIDGE /* Calculate the number of atoms that bridge two parts of a structure @@ -40,20 +40,20 @@ This quantity calculates: \f[ f(x) = \sum_{ijk} s_A(r_{ij})s_B(r_{ik}) -\f] +\f] -where the sum over \f$i\f$ is over all the ``bridging atoms" and +where the sum over \f$i\f$ is over all the ``bridging atoms" and \f$s_A\f$ and \f$s_B\f$ are \ref switchingfunction. \par Examples The following example instructs plumed to calculate the number of water molecules -that are bridging betweeen atoms 1-10 and atoms 11-20 and to print the value +that are bridging betweeen atoms 1-10 and atoms 11-20 and to print the value to a file \verbatim BRIDGE BRIDGING_ATOMS=100-200 GROUPA=1-10 GROUPB=11-20 LABEL=w1 -PRINT ARG=a1.mean FILE=colvar +PRINT ARG=a1.mean FILE=colvar \endverbatim */ @@ -69,27 +69,27 @@ class Bridge : public MultiColvarBase { explicit Bridge(const ActionOptions&); // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(Bridge,"BRIDGE") -void Bridge::registerKeywords( Keywords& keys ){ +void Bridge::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("atoms-2","BRIDGING_ATOMS","The list of atoms that can form the bridge between the two interesting parts " - "of the structure."); - keys.add("atoms-2","GROUPA","The list of atoms that are in the first interesting part of the structure"); - keys.add("atoms-2","GROUPB","The list of atoms that are in the second interesting part of the structure"); + "of the structure."); + keys.add("atoms-2","GROUPA","The list of atoms that are in the first interesting part of the structure"); + keys.add("atoms-2","GROUPB","The list of atoms that are in the second interesting part of the structure"); keys.add("optional","SWITCH","The parameters of the two \\ref switchingfunction in the above formula"); keys.add("optional","SWITCHA","The \\ref switchingfunction on the distance between bridging atoms and the atoms in " - "group A"); + "group A"); keys.add("optional","SWITCHB","The \\ref switchingfunction on the distance between the bridging atoms and the atoms in " - "group B"); + "group B"); } Bridge::Bridge(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms std::vector all_atoms; @@ -98,27 +98,27 @@ MultiColvarBase(ao) setupMultiColvarBase( all_atoms ); // Setup Central atom atoms std::vector catom_ind(3, false); catom_ind[0]=true; - setAtomsForCentralAtom( catom_ind ); + setAtomsForCentralAtom( catom_ind ); std::string sfinput,errors; parse("SWITCH",sfinput); - if( sfinput.length()>0 ){ + if( sfinput.length()>0 ) { + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + sf2.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } else { + parse("SWITCHA",sfinput); + if(sfinput.length()>0) { + weightHasDerivatives=true; sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); + sfinput.clear(); parse("SWITCHB",sfinput); + if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - } else { - parse("SWITCHA",sfinput); - if(sfinput.length()>0){ - weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); - sfinput.clear(); parse("SWITCHB",sfinput); - if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); - sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); - } else { - error("missing definition of switching functions"); - } + if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); + } else { + error("missing definition of switching functions"); + } } log.printf(" distance between bridging atoms and atoms in GROUPA must be less than %s\n",sf1.description().c_str()); log.printf(" distance between bridging atoms and atoms in GROUPB must be less than %s\n",sf2.description().c_str()); @@ -137,18 +137,18 @@ MultiColvarBase(ao) double Bridge::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { double tot=0; - for(unsigned i=2;i(mlab); @@ -47,12 +47,12 @@ MultiColvarBase(ao) myBridgeVessel = mycolv->addBridgingVessel( this ); addDependency(mycolv); weightHasDerivatives=true; usespecies=mycolv->usespecies; // Number of tasks is the same as the number in the underlying MultiColvar - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList( mycolv->getTaskCode(i) ); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList( mycolv->getTaskCode(i) ); } -void BridgedMultiColvarFunction::turnOnDerivatives(){ +void BridgedMultiColvarFunction::turnOnDerivatives() { BridgedMultiColvarFunction* check = dynamic_cast( mycolv ); - if( check ){ + if( check ) { if( check->getNumberOfAtoms()>0 ) error("cannot calculate required derivatives of this quantity"); } MultiColvarBase::turnOnDerivatives(); @@ -60,18 +60,18 @@ void BridgedMultiColvarFunction::turnOnDerivatives(){ void BridgedMultiColvarFunction::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const { completeTask( current, invals, outvals ); - + // Now update the outvals derivatives lists - if( derivativesAreRequired() ){ - outvals.emptyActiveMembers(); - if( mycolv->isDensity() ){ - for(unsigned j=0;j<3;++j) outvals.putIndexInActiveArray( 3*current+j ); - for(unsigned j=invals.getNumberOfDerivatives()-9;jisDensity() ) { + for(unsigned j=0; j<3; ++j) outvals.putIndexInActiveArray( 3*current+j ); + for(unsigned j=invals.getNumberOfDerivatives()-9; jgetTemporyMultiValue(); if( invals.getNumberOfValues()!=mycolv->getNumberOfQuantities() || - invals.getNumberOfDerivatives()!=mycolv->getNumberOfDerivatives() ){ - invals.resize( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() ); + invals.getNumberOfDerivatives()!=mycolv->getNumberOfDerivatives() ) { + invals.resize( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() ); } invals.clearAll(); mycolv->performTask( taskIndex, current, invals ); - transformBridgedDerivatives( taskIndex, invals, myvals ); + transformBridgedDerivatives( taskIndex, invals, myvals ); } -void BridgedMultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ){ - if(!a){ +void BridgedMultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"cannot compute numerical derivatives for an action without values"); } - if( myBridgeVessel ){ - myBridgeVessel->completeNumericalDerivatives(); + if( myBridgeVessel ) { + myBridgeVessel->completeNumericalDerivatives(); } else { - error("numerical derivatives are not implemented"); + error("numerical derivatives are not implemented"); } } -void BridgedMultiColvarFunction::applyBridgeForces( const std::vector& bb ){ +void BridgedMultiColvarFunction::applyBridgeForces( const std::vector& bb ) { if( getNumberOfAtoms()==0 ) return ; std::vector& f( modifyForces() ); - for(unsigned i=0;iisPeriodic(); } -void BridgedMultiColvarFunction::deactivate_task( const unsigned& taskno ){ +void BridgedMultiColvarFunction::deactivate_task( const unsigned& taskno ) { plumed_merror("This should never be called"); } -void BridgedMultiColvarFunction::getCentralAtomPack( const unsigned& basn, const unsigned& curr, CatomPack& mypack ){ +void BridgedMultiColvarFunction::getCentralAtomPack( const unsigned& basn, const unsigned& curr, CatomPack& mypack ) { return mycolv->getCentralAtomPack( basn, curr, mypack ); } diff --git a/src/multicolvar/BridgedMultiColvarFunction.h b/src/multicolvar/BridgedMultiColvarFunction.h index 216bd52a1b..b23ccb9065 100644 --- a/src/multicolvar/BridgedMultiColvarFunction.h +++ b/src/multicolvar/BridgedMultiColvarFunction.h @@ -29,8 +29,8 @@ namespace PLMD { namespace multicolvar { class BridgedMultiColvarFunction : public MultiColvarBase { -friend class MultiColvarBase; -friend class MultiColvarFunction; + friend class MultiColvarBase; + friend class MultiColvarFunction; private: /// This is used for storing positions properly Vector tmp_p; @@ -51,23 +51,23 @@ friend class MultiColvarFunction; explicit BridgedMultiColvarFunction(const ActionOptions&); /// Get a pointer to the base multicolvar MultiColvarBase* getPntrToMultiColvar() const ; -/// 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(){} +/// 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() {} /// Check nothing impossible being done with derivatives virtual void turnOnDerivatives(); /// Get the number of derivatives for this action - unsigned getNumberOfDerivatives(); + unsigned getNumberOfDerivatives(); /// Get the size of the atoms with derivatives array unsigned getSizeOfAtomsWithDerivatives(); /// Is the output quantity periodic bool isPeriodic(); -/// Routines that have to be defined so as not to have problems with virtual methods +/// Routines that have to be defined so as not to have problems with virtual methods void deactivate_task( const unsigned& taskno ); - void calculate(){} + void calculate() {} /// This does the task void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const ; - void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; + void performTask( const unsigned&, const unsigned&, MultiValue& ) const ; virtual void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const=0; /// Get the central atom position Vector retrieveCentralAtomPos(); @@ -77,11 +77,11 @@ friend class MultiColvarFunction; const std::vector & getAbsoluteIndexes()const ; /// We need our own calculate numerical derivatives here void calculateNumericalDerivatives( ActionWithValue* a=NULL ); - void apply(){}; -/// Is this atom currently being copied + void apply() {}; +/// Is this atom currently being copied bool isCurrentlyActive( const unsigned& ); /// This should not be called - Vector calculateCentralAtomPosition(){ plumed_error(); } + Vector calculateCentralAtomPosition() { plumed_error(); } double compute( const unsigned& tindex, AtomValuePack& myvals ) const { plumed_error(); } Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const ; void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector& indices ); @@ -103,33 +103,33 @@ MultiColvarBase* BridgedMultiColvarFunction::getPntrToMultiColvar() const { } inline -unsigned BridgedMultiColvarFunction::getNumberOfDerivatives(){ +unsigned BridgedMultiColvarFunction::getNumberOfDerivatives() { return mycolv->getNumberOfDerivatives() + 3*getNumberOfAtoms(); } inline -bool BridgedMultiColvarFunction::isCurrentlyActive( const unsigned& code ){ +bool BridgedMultiColvarFunction::isCurrentlyActive( const unsigned& code ) { return mycolv->isCurrentlyActive( code ); } inline -unsigned BridgedMultiColvarFunction::getSizeOfAtomsWithDerivatives(){ +unsigned BridgedMultiColvarFunction::getSizeOfAtomsWithDerivatives() { return mycolv->getNumberOfAtoms(); } -inline -Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { +inline +Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { return mycolv->getPositionOfAtomForLinkCells(iatom); } inline -Vector BridgedMultiColvarFunction::getCentralAtomPos( const unsigned& curr ){ +Vector BridgedMultiColvarFunction::getCentralAtomPos( const unsigned& curr ) { return mycolv->getCentralAtomPos( curr ); } inline AtomNumber BridgedMultiColvarFunction::getAbsoluteIndexOfCentralAtom(const unsigned& i) const { - return mycolv->getAbsoluteIndexOfCentralAtom(i); + return mycolv->getAbsoluteIndexOfCentralAtom(i); } inline diff --git a/src/multicolvar/CatomPack.cpp b/src/multicolvar/CatomPack.cpp index 59e1d8e44b..900fa5e706 100644 --- a/src/multicolvar/CatomPack.cpp +++ b/src/multicolvar/CatomPack.cpp @@ -21,10 +21,10 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "CatomPack.h" -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { -void CatomPack::resize( const unsigned& size ){ +void CatomPack::resize( const unsigned& size ) { indices.resize(size); derivs.resize(size); } diff --git a/src/multicolvar/CatomPack.h b/src/multicolvar/CatomPack.h index e960d3db51..130e971cdb 100644 --- a/src/multicolvar/CatomPack.h +++ b/src/multicolvar/CatomPack.h @@ -36,24 +36,24 @@ class CatomPack { std::vector derivs; public: void resize( const unsigned& ); - void setIndex( const unsigned& , const unsigned& ); - void setDerivative( const unsigned& , const Tensor& ); + 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 ; + double getDerivative( const unsigned&, const unsigned&, const Vector& ) const ; }; inline -void CatomPack::setIndex( const unsigned& jind, const unsigned& ind ){ +void CatomPack::setIndex( const unsigned& jind, const unsigned& ind ) { plumed_dbg_assert( jind( mycolv ); - if( mybr ){ - requestAtoms( (mybr->getPntrToMultiColvar())->getAbsoluteIndexes() ); comp=1; - } else { - if( mycolv->getNumberOfQuantities()>5 ){ - int incomp=-1; parse("COMPONENT",incomp); - if( incomp<0 ) error("vector input but component was not specified"); - comp=incomp; - } else { - comp=1; - } - requestAtoms( mycolv->getAbsoluteIndexes () ); + if( mybr ) { + requestAtoms( (mybr->getPntrToMultiColvar())->getAbsoluteIndexes() ); comp=1; + } else { + if( mycolv->getNumberOfQuantities()>5 ) { + int incomp=-1; parse("COMPONENT",incomp); + if( incomp<0 ) error("vector input but component was not specified"); + comp=incomp; + } else { + comp=1; + } + requestAtoms( mycolv->getAbsoluteIndexes () ); } // We need the derivatives - mycolv->turnOnDerivatives(); addDependency(mycolv); + mycolv->turnOnDerivatives(); addDependency(mycolv); mystash = mycolv->buildDataStashes( NULL ); log.printf(" building center of mass based on weights calculated in multicolvar action named %s \n",mycolv->getLabel().c_str() ); } -void CenterOfMultiColvar::calculate(){ +void CenterOfMultiColvar::calculate() { // Retrieve the periodic boundary conditions const Pbc& pbc=mycolv->getPbc(); - if( !pbc.isOrthorombic() ) error("Berry phase does not work for non orthorhombic cells"); - + if( !pbc.isOrthorombic() ) error("Berry phase does not work for non orthorhombic cells"); + // Create a multivalue to store the derivatives MultiValue myvals( 7, mycolv->getNumberOfDerivatives() ); myvals.clearAll(); MultiValue tvals( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() ); tvals.clearAll(); - // Now loop over all active multicolvars - Vector stmp, ctmp, scom, ccom, sder, cder; + // Now loop over all active multicolvars + Vector stmp, ctmp, scom, ccom, sder, cder; scom.zero(); ccom.zero(); double norm=0; std::vector cvals( mycolv->getNumberOfQuantities() ); - for(unsigned i=0;igetNumberOfStoredValues();++i){ - // Retrieve value and derivatives - mystash->retrieveSequentialValue( i, false, cvals ); - mystash->retrieveDerivatives( mycolv->getPositionInFullTaskList(i), false, tvals ); - // Convert position into fractionals - Vector fpos = pbc.realToScaled( mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(i) ) ); - // Now accumulate Berry phase averages - for(unsigned j=0;j<3;++j){ - stmp[j] = sin( 2*pi*fpos[j] ); ctmp[j] = cos( 2*pi*fpos[j] ); - scom[j] += cvals[0]*cvals[comp]*stmp[j]; ccom[j] += cvals[0]*cvals[comp]*ctmp[j]; - double icell = 1.0 / getPbc().getBox().getRow(j).modulo(); - sder[j] = 2*pi*icell*cvals[0]*cvals[comp]*cos( 2*pi*fpos[j] ); - cder[j]=-2*pi*icell*cvals[0]*cvals[comp]*sin( 2*pi*fpos[j] ); - } - // Now accumulate derivatives - for(unsigned k=0;kgetNumberOfStoredValues(); ++i) { + // Retrieve value and derivatives + mystash->retrieveSequentialValue( i, false, cvals ); + mystash->retrieveDerivatives( mycolv->getPositionInFullTaskList(i), false, tvals ); + // Convert position into fractionals + Vector fpos = pbc.realToScaled( mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(i) ) ); + // Now accumulate Berry phase averages + for(unsigned j=0; j<3; ++j) { + stmp[j] = sin( 2*pi*fpos[j] ); ctmp[j] = cos( 2*pi*fpos[j] ); + scom[j] += cvals[0]*cvals[comp]*stmp[j]; ccom[j] += cvals[0]*cvals[comp]*ctmp[j]; + double icell = 1.0 / getPbc().getBox().getRow(j).modulo(); + sder[j] = 2*pi*icell*cvals[0]*cvals[comp]*cos( 2*pi*fpos[j] ); + cder[j]=-2*pi*icell*cvals[0]*cvals[comp]*sin( 2*pi*fpos[j] ); + } + // Now accumulate derivatives + for(unsigned k=0; kgetCentralAtomPack( 0, mycolv->getPositionInFullTaskList(i), mypack ); - for(unsigned j=0;jgetCentralAtomPack( 0, mycolv->getPositionInFullTaskList(i), mypack ); + for(unsigned j=0; j fderiv( getNumberOfAtoms() ); - for(unsigned j=0;j0){ - switchingFunction.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + if(sw.length()>0) { + switchingFunction.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } else { + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" coordination of central atom and those within %s\n",( switchingFunction.description() ).c_str() ); // Set the link cell cutoff @@ -121,20 +121,20 @@ MultiColvarBase(ao) } double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - // Calculate the coordination number - double dfunc, d2, sw; - for(unsigned i=1;i& weight, MultiColvarFunction* func ){} void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector& indices ); // unsigned getNumberOfQuantities(); @@ -69,37 +69,37 @@ class Density : public MultiColvarBase { PLUMED_REGISTER_ACTION(Density,"DENSITY") -void Density::registerKeywords( Keywords& keys ){ +void Density::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("SPECIES"); + keys.use("SPECIES"); } Density::Density(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { std::vector all_atoms; parseMultiColvarAtomList("SPECIES", -1, all_atoms); - ablocks.resize(1); ablocks[0].resize( atom_lab.size() ); - for(unsigned i=0;i& indices ){ - indices[jstore]=0; +void Density::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector& indices ) { + indices[jstore]=0; } // unsigned Density::getNumberOfQuantities(){ // return 2; // } -void Density::getValueForTask( const unsigned& iatom, std::vector& vals ){ - plumed_dbg_assert( vals.size()==2 ); vals[0]=vals[1]=1.0; +void Density::getValueForTask( const unsigned& iatom, std::vector& 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 fb5b644c42..e75bde6680 100644 --- a/src/multicolvar/DihedralCorrelation.cpp +++ b/src/multicolvar/DihedralCorrelation.cpp @@ -29,8 +29,8 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC COLVAR DIHCOR /* @@ -87,39 +87,39 @@ class DihedralCorrelation : public MultiColvarBase { static void registerKeywords( Keywords& keys ); explicit DihedralCorrelation(const ActionOptions&); virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(DihedralCorrelation,"DIHCOR") -void DihedralCorrelation::registerKeywords( Keywords& keys ){ +void DihedralCorrelation::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("numbered","ATOMS","the atoms involved in each of the dihedral correlation values you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dihedral correlation will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of 8 atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dihedral correlation will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of 8 atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); } DihedralCorrelation::DihedralCorrelation(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms std::vector all_atoms; readAtomsLikeKeyword( "ATOMS", 8, all_atoms ); setupMultiColvarBase( all_atoms ); // Stuff for central atoms - std::vector catom_ind(8, false); + std::vector 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 ){ - std::string fake_input; - addVessel( "SUM", fake_input, -1 ); // -1 here means that this value will be named getLabel() - readVesselKeywords(); // This makes sure resizing is done + if( getNumberOfVessels()==0 ) { + std::string fake_input; + addVessel( "SUM", fake_input, -1 ); // -1 here means that this value will be named getLabel() + readVesselKeywords(); // This makes sure resizing is done } // And check everything has been read in correctly @@ -148,9 +148,9 @@ double DihedralCorrelation::compute( const unsigned& tindex, AtomValuePack& myat const double value = 0.5*(1.+cos(diff)); // Derivatives wrt phi1 const double dval = 0.5*sin(diff); - dd10 *= dval; - dd11 *= dval; - dd12 *= dval; + dd10 *= dval; + dd11 *= dval; + dd12 *= dval; // And add addAtomDerivatives(1, 0, dd10, myatoms ); addAtomDerivatives(1, 1, dd11-dd10, myatoms ); diff --git a/src/multicolvar/DistanceFromContour.cpp b/src/multicolvar/DistanceFromContour.cpp index 3a942c5fb2..214930392e 100644 --- a/src/multicolvar/DistanceFromContour.cpp +++ b/src/multicolvar/DistanceFromContour.cpp @@ -31,7 +31,7 @@ Calculate the perpendicular distance from a Willard-Chandler dividing surface. Suppose that you have calculated a multicolvar. By doing so you have calculated a -set of colvars, \f$s_i\f$, and each of these colvars has a well defined position in +set of colvars, \f$s_i\f$, and each of these colvars has a well defined position in space \f$(x_i,y_i,z_i)\f$. You can use this information to calculate a phase-field model of the colvar density using: @@ -39,7 +39,7 @@ model of the colvar density using: p(x,y,x) = \sum_{i} s_i K\left[\frac{x-x_i}{\sigma_x},\frac{y-y_i}{\sigma_y},\frac{z-z_i}{\sigma_z} \right] \f] -In this expression \f$\sigma_x, \sigma_y\f$ and \f$\sigma_z\f$ are bandwidth parameters and +In this expression \f$\sigma_x, \sigma_y\f$ and \f$\sigma_z\f$ are bandwidth parameters and \f$K\f$ is one of the \ref kernelfunctions. This is what is done within \ref MULTICOLVARDENS The Willard-Chandler surface is a surface of constant density in the above phase field \f$p(x,y,z)\f$. @@ -50,13 +50,13 @@ p(x',y',z') = \rho \f] where \f$\rho\f$ is some target density. This action caculates the distance projected on the \f$x, y\f$ or -\f$z\f$ axis between the position of some test particle and this surface of constant field density. +\f$z\f$ axis between the position of some test particle and this surface of constant field density. \par Examples -In this example atoms 2-100 are assumed to be concentraed along some part of the \f$z\f$ axis so that you -an interface between a liquid/solid and the vapour. The quantity dc measures the distance between the -surface at which the density of 2-100 atoms is equal to 0.2 and the position of the test particle atom 1. +In this example atoms 2-100 are assumed to be concentraed along some part of the \f$z\f$ axis so that you +an interface between a liquid/solid and the vapour. The quantity dc measures the distance between the +surface at which the density of 2-100 atoms is equal to 0.2 and the position of the test particle atom 1. \verbatim dens: DENSITY SPECIES=2-100 @@ -81,7 +81,7 @@ class DistanceFromContour : public MultiColvarBase { std::vector bw, pos1, pos2, dirv, dirv2; std::vector forces; std::vector perp_dirs; - vesselbase::ValueVessel* myvalue_vessel; + vesselbase::ValueVessel* myvalue_vessel; vesselbase::ValueVessel* myderiv_vessel; RootFindingBase mymin; public: @@ -91,16 +91,16 @@ class DistanceFromContour : public MultiColvarBase { bool isDensity() const { return true; } void calculate(); unsigned getNumberOfQuantities() const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; double getDifferenceFromContour( const std::vector& x, std::vector& der ); -// We need an apply action as we are using an independent value +// We need an apply action as we are using an independent value void apply(); }; PLUMED_REGISTER_ACTION(DistanceFromContour,"DISTANCE_FROM_CONTOUR") -void DistanceFromContour::registerKeywords( Keywords& keys ){ +void DistanceFromContour::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.addOutputComponent("dist1","default","the distance between the reference atom and the nearest contour"); keys.addOutputComponent("dist2","default","the distance between the reference atom and the other contour"); @@ -110,31 +110,31 @@ void DistanceFromContour::registerKeywords( Keywords& keys ){ keys.add("atoms","ATOM","The atom whose perpendicular distance we are calculating from the contour"); keys.add("compulsory","BANDWIDTH","the bandwidths for kernel density esimtation"); keys.add("compulsory","KERNEL","gaussian","the kernel function you are using. More details on the kernels available " - "in plumed plumed can be found in \\ref kernelfunctions."); + "in plumed plumed can be found in \\ref kernelfunctions."); keys.add("compulsory","DIR","the direction perpendicular to the contour that you are looking for"); keys.add("compulsory","CONTOUR","the value we would like for the contour"); keys.add("compulsory","TOLERANCE","0.1","this parameter is used to manage periodic boundary conditions. The problem " - "here is that we can be between contours even when we are not within the membrane " - "because of periodic boundary conditions. When we are in the contour, however, we " - "should have it so that the sums of the absoluate values of the distances to the two " - "contours is approximately the distance between the two contours. There can be numerical errors in these calculations, however, so " - "we specify a small tolerance here"); + "here is that we can be between contours even when we are not within the membrane " + "because of periodic boundary conditions. When we are in the contour, however, we " + "should have it so that the sums of the absoluate values of the distances to the two " + "contours is approximately the distance between the two contours. There can be numerical errors in these calculations, however, so " + "we specify a small tolerance here"); } DistanceFromContour::DistanceFromContour( const ActionOptions& ao ): -Action(ao), -MultiColvarBase(ao), -derivTime(false), -bw(3), -pos1(3,0.0), -pos2(3,0.0), -dirv(3,0.0), -dirv2(3,0.0), -perp_dirs(2), -mymin(this) + Action(ao), + MultiColvarBase(ao), + derivTime(false), + bw(3), + pos1(3,0.0), + pos2(3,0.0), + dirv(3,0.0), + dirv2(3,0.0), + perp_dirs(2), + mymin(this) { // Read in the multicolvar/atoms - std::vector all_atoms; parse("TOLERANCE",pbc_param); + std::vector all_atoms; parse("TOLERANCE",pbc_param); bool read2 = parseMultiColvarAtomList("DATA", -1, all_atoms); if( !read2 ) error("missing DATA keyword"); bool read1 = parseMultiColvarAtomList("ATOM", -1, all_atoms); @@ -146,10 +146,10 @@ mymin(this) if( getNumberOfBaseMultiColvars()!=1 ) error("should only be one input multicolvar"); // Get the direction - std::string ldir; parse("DIR",ldir ); - if( ldir=="x" ){ dir=0; perp_dirs[0]=1; perp_dirs[1]=2; dirv[0]=1; dirv2[0]=-1; } - else if( ldir=="y" ){ dir=1; perp_dirs[0]=0; perp_dirs[1]=2; dirv[1]=1; dirv2[1]=-1; } - else if( ldir=="z" ){ dir=2; perp_dirs[0]=0; perp_dirs[1]=1; dirv[2]=1; dirv2[2]=-1; } + std::string ldir; parse("DIR",ldir ); + if( ldir=="x" ) { dir=0; perp_dirs[0]=1; perp_dirs[1]=2; dirv[0]=1; dirv2[0]=-1; } + else if( ldir=="y" ) { dir=1; perp_dirs[0]=0; perp_dirs[1]=2; dirv[1]=1; dirv2[1]=-1; } + else if( ldir=="z" ) { dir=2; perp_dirs[0]=0; perp_dirs[1]=1; dirv[2]=1; dirv2[2]=-1; } else error(ldir + " is not a valid direction use x, y or z"); // Read in details of phase field construction @@ -158,45 +158,45 @@ mymin(this) log.printf(" constructing phase field using %s kernels with bandwidth (%f, %f, %f) \n",kerneltype.c_str(), bw[0], bw[1], bw[2] ); // Now create a task list - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList(i); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList(i); // And a cutoff std::vector pp( bw.size(),0 ); KernelFunctions kernel( pp, bw, kerneltype, false, 1.0, true ); - double rcut = kernel.getCutoff( bw[0] ); - for(unsigned j=1;jrcut ) rcut=kernel.getCutoff(bw[j]); + double rcut = kernel.getCutoff( bw[0] ); + for(unsigned j=1; jrcut ) rcut=kernel.getCutoff(bw[j]); } - rcut2=rcut*rcut; - // Create the values + rcut2=rcut*rcut; + // Create the values addComponent("thickness"); componentIsNotPeriodic("thickness"); addComponent("dist1"); componentIsNotPeriodic("dist1"); addComponent("dist2"); componentIsNotPeriodic("dist2"); addComponentWithDerivatives("qdist"); componentIsNotPeriodic("qdist"); - // Create sum vessels + // Create sum vessels std::string fake_input; std::string deriv_input="COMPONENT=2"; - if( mybasemulticolvars[0]->isDensity() ){ - addVessel( "SUM", fake_input, -1 ); addVessel( "SUM", deriv_input, -1 ); - } else { - addVessel( "MEAN", fake_input, -1 ); addVessel( "MEAN", deriv_input, -1 ); + if( mybasemulticolvars[0]->isDensity() ) { + addVessel( "SUM", fake_input, -1 ); addVessel( "SUM", deriv_input, -1 ); + } else { + addVessel( "MEAN", fake_input, -1 ); addVessel( "MEAN", deriv_input, -1 ); } // And convert to a value vessel so we can get the final value myvalue_vessel = dynamic_cast( getPntrToVessel(0) ); - myderiv_vessel = dynamic_cast( getPntrToVessel(1) ); - plumed_assert( myvalue_vessel && myderiv_vessel ); resizeFunctions(); + myderiv_vessel = dynamic_cast( getPntrToVessel(1) ); + plumed_assert( myvalue_vessel && myderiv_vessel ); resizeFunctions(); // Create the vector of values that holds the position - for(unsigned i=0;i<3;++i) pval.push_back( new Value() ); + for(unsigned i=0; i<3; ++i) pval.push_back( new Value() ); } -DistanceFromContour::~DistanceFromContour(){ - for(unsigned i=0;i<3;++i) delete pval[i]; +DistanceFromContour::~DistanceFromContour() { + for(unsigned i=0; i<3; ++i) delete pval[i]; } unsigned DistanceFromContour::getNumberOfQuantities() const { return 3; } -void DistanceFromContour::calculate(){ +void DistanceFromContour::calculate() { // Check box is orthorhombic if( !getPbc().isOrthorombic() ) error("cell box must be orthorhombic"); @@ -207,14 +207,14 @@ void DistanceFromContour::calculate(){ deactivateAllTasks(); Vector myvec = getSeparation( getPosition(getNumberOfAtoms()-1), getPosition(0) ); pos2[dir]=myvec[dir]; taskFlags[0]=1; double d2, mindist = myvec.modulo2(); - for(unsigned j=1;jepsilon ){ pos2[dir]=distance[dir]; mindist = d2; } - taskFlags[j]=1; - } + for(unsigned j=1; jepsilon ) { pos2[dir]=distance[dir]; mindist = d2; } + taskFlags[j]=1; + } } lockContributors(); derivTime=false; // pos1 position of the nanoparticle, in the first time @@ -224,29 +224,29 @@ void DistanceFromContour::calculate(){ std::vector faked(3); double fa = getDifferenceFromContour( pos1, faked ); double fb = getDifferenceFromContour( pos2, faked ); - if( fa*fb>0 ){ - unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); - for(unsigned i=0;i0)? -1 : +1; // If the nanoparticle is inside the membrane push it out - pos1[dir] += sign*bw[dir]; fa = getDifferenceFromContour( pos1, faked ); - if( fa*fb<0 ) break; - // if fa*fb is less than zero the new pos 1 is outside the contour - } + if( fa*fb>0 ) { + unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); + for(unsigned i=0; i0)? -1 : +1; // If the nanoparticle is inside the membrane push it out + pos1[dir] += sign*bw[dir]; fa = getDifferenceFromContour( pos1, faked ); + if( fa*fb<0 ) break; + // if fa*fb is less than zero the new pos 1 is outside the contour + } } // Set direction for contour search - dirv[dir] = pos2[dir] - pos1[dir]; + dirv[dir] = pos2[dir] - pos1[dir]; // Bracket for second root starts in center of membrane - double fc = getDifferenceFromContour( pos2, faked ); - if( fc*fb>0 ){ - // first time is true, because fc=fb - // push pos2 from its initial position inside the membrane towards the second contourn - unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); - for(unsigned i=0;i0)? +1 : -1; - pos2[dir] += sign*bw[dir]; fc = getDifferenceFromContour( pos2, faked ); - if( fc*fb<0 ) break; - } - dirv2[dir] = ( pos1[dir] + dirv[dir] ) - pos2[dir]; + double fc = getDifferenceFromContour( pos2, faked ); + if( fc*fb>0 ) { + // first time is true, because fc=fb + // push pos2 from its initial position inside the membrane towards the second contourn + unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); + for(unsigned i=0; i0)? +1 : -1; + pos2[dir] += sign*bw[dir]; fc = getDifferenceFromContour( pos2, faked ); + if( fc*fb<0 ) break; + } + dirv2[dir] = ( pos1[dir] + dirv[dir] ) - pos2[dir]; } // Now do a search for the two contours @@ -255,50 +255,50 @@ void DistanceFromContour::calculate(){ Vector root1; root1.zero(); root1[dir] = pval[dir]->get(); mymin.lsearch( dirv2, pos2, &DistanceFromContour::getDifferenceFromContour ); // Calculate the separation between the two roots using PBC - Vector root2; root2.zero(); root2[dir]=pval[dir]->get(); + Vector root2; root2.zero(); root2[dir]=pval[dir]->get(); Vector sep = getSeparation( root1, root2 ); double spacing = fabs( sep[dir] ); plumed_assert( spacing>epsilon ); getPntrToComponent("thickness")->set( spacing ); // Make sure the sign is right - double predir=(root1[dir]*root2[dir]<0)? -1 : 1; - // This deals with periodic boundary conditions - if we are inside the membrane the sum of the absolute + double predir=(root1[dir]*root2[dir]<0)? -1 : 1; + // This deals with periodic boundary conditions - if we are inside the membrane the sum of the absolute // distances from the contours should add up to the spacing. When this is not the case we must be outside // the contour - // if( predir==-1 && (fabs(root1[dir])+fabs(root2[dir]))>(spacing+pbc_param) ) predir=1; + // if( predir==-1 && (fabs(root1[dir])+fabs(root2[dir]))>(spacing+pbc_param) ) predir=1; // Set the final value to root that is closest to the "origin" = position of atom - if( fabs(root1[dir])set( predir*fabs(root1[dir]) ); - getPntrToComponent("dist2")->set( fabs(root2[dir]) ); - } else { - getPntrToComponent("dist1")->set( predir*fabs(root2[dir]) ); - getPntrToComponent("dist2")->set( fabs(root1[dir]) ); + if( fabs(root1[dir])set( predir*fabs(root1[dir]) ); + getPntrToComponent("dist2")->set( fabs(root2[dir]) ); + } else { + getPntrToComponent("dist1")->set( predir*fabs(root2[dir]) ); + getPntrToComponent("dist2")->set( fabs(root1[dir]) ); } getPntrToComponent("qdist")->set( root2[dir]*root1[dir] ); // Now calculate the derivatives - if( !doNotCalculateDerivatives() ){ - Value* ival=myvalue_vessel->getFinalValue(); ival->clearDerivatives(); - std::vector root1v(3); for(unsigned i=0;i<3;++i) root1v[i]=root1[i]; - derivTime=true; std::vector der(3); getDifferenceFromContour( root1v, der ); double prefactor; - if( mybasemulticolvars[0]->isDensity() ) prefactor = root2[dir] / myderiv_vessel->getOutputValue(); - else plumed_error(); - Value* val=getPntrToComponent("qdist"); - for(unsigned i=0;igetNumberOfDerivatives();++i) val->setDerivative( i, -prefactor*ival->getDerivative(i) ); - ival->clearDerivatives(); - std::vector root2v(3); for(unsigned i=0;i<3;++i) root2v[i]=root2[i]; - getDifferenceFromContour( root2v, der ); - if( mybasemulticolvars[0]->isDensity() ) prefactor = root1[dir] / myderiv_vessel->getOutputValue(); - else plumed_error(); - for(unsigned i=0;igetNumberOfDerivatives();++i) val->addDerivative( i, -prefactor*ival->getDerivative(i) ); + if( !doNotCalculateDerivatives() ) { + Value* ival=myvalue_vessel->getFinalValue(); ival->clearDerivatives(); + std::vector root1v(3); for(unsigned i=0; i<3; ++i) root1v[i]=root1[i]; + derivTime=true; std::vector der(3); getDifferenceFromContour( root1v, der ); double prefactor; + if( mybasemulticolvars[0]->isDensity() ) prefactor = root2[dir] / myderiv_vessel->getOutputValue(); + else plumed_error(); + Value* val=getPntrToComponent("qdist"); + for(unsigned i=0; igetNumberOfDerivatives(); ++i) val->setDerivative( i, -prefactor*ival->getDerivative(i) ); + ival->clearDerivatives(); + std::vector root2v(3); for(unsigned i=0; i<3; ++i) root2v[i]=root2[i]; + getDifferenceFromContour( root2v, der ); + if( mybasemulticolvars[0]->isDensity() ) prefactor = root1[dir] / myderiv_vessel->getOutputValue(); + else plumed_error(); + for(unsigned i=0; igetNumberOfDerivatives(); ++i) val->addDerivative( i, -prefactor*ival->getDerivative(i) ); } } -double DistanceFromContour::getDifferenceFromContour( const std::vector& x, std::vector& der ){ - std::string min, max; - for(unsigned j=0;j<3;++j){ - Tools::convert( -0.5*getBox()(j,j), min ); - Tools::convert( +0.5*getBox()(j,j), max ); - pval[j]->setDomain( min, max ); pval[j]->set( x[j] ); +double DistanceFromContour::getDifferenceFromContour( const std::vector& x, std::vector& der ) { + std::string min, max; + for(unsigned j=0; j<3; ++j) { + Tools::convert( -0.5*getBox()(j,j), min ); + Tools::convert( +0.5*getBox()(j,j), max ); + pval[j]->setDomain( min, max ); pval[j]->set( x[j] ); } runAllTasks(); return myvalue_vessel->getOutputValue() - contour; @@ -306,24 +306,24 @@ double DistanceFromContour::getDifferenceFromContour( const std::vector& double DistanceFromContour::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { Vector distance = getSeparation( getPosition(getNumberOfAtoms()-1), myatoms.getPosition(0) ); - std::vector pp(3), der(3,0); for(unsigned j=0;j<3;++j) pp[j] = distance[j]; + std::vector pp(3), der(3,0); for(unsigned j=0; j<3; ++j) pp[j] = distance[j]; // Now create the kernel and evaluate KernelFunctions kernel( pp, bw, kerneltype, false, 1.0, true ); double newval = kernel.evaluate( pval, der, true ); - if( mybasemulticolvars[0]->isDensity() ){ - if( !doNotCalculateDerivatives() && derivTime ){ - MultiValue& myvals=myatoms.getUnderlyingMultiValue(); - Vector vder; unsigned basen=myvals.getNumberOfDerivatives() - 12; - for(unsigned i=0;i<3;++i){ - vder[i]=der[i]; myvals.addDerivative( 1, basen+i, vder[i] ); - } - myatoms.setValue( 2, der[dir] ); - addAtomDerivatives( 1, 0, -vder, myatoms ); - myatoms.addBoxDerivatives( 1, Tensor(vder,distance) ); + if( mybasemulticolvars[0]->isDensity() ) { + if( !doNotCalculateDerivatives() && derivTime ) { + MultiValue& myvals=myatoms.getUnderlyingMultiValue(); + Vector vder; unsigned basen=myvals.getNumberOfDerivatives() - 12; + for(unsigned i=0; i<3; ++i) { + vder[i]=der[i]; myvals.addDerivative( 1, basen+i, vder[i] ); } - myatoms.setValue( 0, 1.0 ); return newval; + myatoms.setValue( 2, der[dir] ); + addAtomDerivatives( 1, 0, -vder, myatoms ); + myatoms.addBoxDerivatives( 1, Tensor(vder,distance) ); + } + myatoms.setValue( 0, 1.0 ); return newval; } // This does the stuff for averaging @@ -332,10 +332,10 @@ double DistanceFromContour::compute( const unsigned& tindex, AtomValuePack& myat // This gets the average if we are using a phase field std::vector cvals( mybasemulticolvars[0]->getNumberOfQuantities() ); mybasedata[0]->retrieveValueWithIndex( tindex, false, cvals ); - return newval*cvals[0]*cvals[1]; + return newval*cvals[0]*cvals[1]; } -void DistanceFromContour::apply(){ +void DistanceFromContour::apply() { if( getPntrToComponent("qdist")->applyForce( forces ) ) setForcesOnAtoms( forces ); } diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp index 4ea6d867e9..d5cb8fde00 100644 --- a/src/multicolvar/Distances.cpp +++ b/src/multicolvar/Distances.cpp @@ -30,17 +30,17 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR DISTANCES /* Calculate the distances between one or many pairs of atoms. You can then calculate functions of the distribution of -distances such as the minimum, the number less than a certain quantity and so on. +distances such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the distances between atoms 3 and 5 and between atoms 1 and 2 and to +The following input tells plumed to calculate the distances between atoms 3 and 5 and between atoms 1 and 2 and to print the minimum for these two distances. \verbatim DISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 @@ -70,7 +70,7 @@ In other words the distances between atoms 1 and 2 and the distance between atom more than 0.1 is then printed to a file. \verbatim DISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) @@ -80,7 +80,7 @@ PRINT ARG=d1.gt0.1 To calculate and print the minimum distance between two groups of atoms you use the following commands \verbatim -d1: DISTANCES GROUPA=1-10 GROUPB=11-20 MIN={BETA=500.} +d1: DISTANCES GROUPA=1-10 GROUPB=11-20 MIN={BETA=500.} PRINT ARG=d1.min FILE=colvar STRIDE=10 \endverbatim (see \ref DISTANCES and \ref PRINT) @@ -93,29 +93,29 @@ s = \frac{\beta}{ \log \sum_i \exp\left( \frac{\beta}{s_i} \right) } where \f$\beta\f$ is a user specified parameter. -This input is used rather than a separate MINDIST colvar so that the same routine and the same input style can be -used to calculate minimum coordinatetion numbers (see \ref COORDINATIONNUMBER), minimum -angles (see \ref ANGLES) and many other variables. +This input is used rather than a separate MINDIST colvar so that the same routine and the same input style can be +used to calculate minimum coordinatetion numbers (see \ref COORDINATIONNUMBER), minimum +angles (see \ref ANGLES) and many other variables. This new way of calculating mindist is part of plumed 2's multicolvar functionality. These special actions -allow you to calculate multiple functions of a distribution of simple collective variables. As an example you +allow you to calculate multiple functions of a distribution of simple collective variables. As an example you can calculate the number of distances less than 1.0, the minimum distance, the number of distances more than 2.0 and the number of distances between 1.0 and 2.0 by using the following command: \verbatim DISTANCES ... - GROUPA=1-10 GROUPB=11-20 - LESS_THAN={RATIONAL R_0=1.0} - MORE_THAN={RATIONAL R_0=2.0} - BETWEEN={GAUSSIAN LOWER=1.0 UPPER=2.0} + GROUPA=1-10 GROUPB=11-20 + LESS_THAN={RATIONAL R_0=1.0} + MORE_THAN={RATIONAL R_0=2.0} + BETWEEN={GAUSSIAN LOWER=1.0 UPPER=2.0} MIN={BETA=500.} ... DISTANCES PRINT ARG=d1.lessthan,d1.morethan,d1.between,d1.min FILE=colvar STRIDE=10 \endverbatim (see \ref DISTANCES and \ref PRINT) -A calculation performed this way is fast because the expensive part of the calculation - the calculation of all the distances - is only -done once per step. Furthermore, it can be made faster by using the TOL keyword to discard those distance that make only a small contributions +A calculation performed this way is fast because the expensive part of the calculation - the calculation of all the distances - is only +done once per step. Furthermore, it can be made faster by using the TOL keyword to discard those distance that make only a small contributions to the final values together with the NL_STRIDE keyword, which ensures that the distances that make only a small contribution to the final values aren't calculated at every step. @@ -131,35 +131,35 @@ class Distances : public MultiColvarBase { // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(Distances,"DISTANCES") -void Distances::registerKeywords( Keywords& keys ){ +void Distances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); 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("numbered","ATOMS","the atoms involved in each of the distances you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); 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 " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); } Distances::Distances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms - std::vector all_atoms; + std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 2, all_atoms ); setupMultiColvarBase( all_atoms ); @@ -168,44 +168,44 @@ MultiColvarBase(ao) // Now check if we can use link cells bool use_link=false; double rcut; - if( getNumberOfVessels()>0 ){ - vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); - if( lt ){ - use_link=true; rcut=lt->getCutoff(); - } else { - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); - if( bt ){ use_link=true; rcut=bt->getCutoff(); } - } - if( use_link ){ - for(unsigned i=1;i( getPntrToVessel(i) ); - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); - if( lt2 ){ - double tcut=lt2->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else if( bt ){ - double tcut=bt->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else { - use_link=false; - } - } - } - if( use_link ) setLinkCellCutoff( rcut ); + if( getNumberOfVessels()>0 ) { + vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); + if( lt ) { + use_link=true; rcut=lt->getCutoff(); + } else { + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); + if( bt ) { use_link=true; rcut=bt->getCutoff(); } + } + if( use_link ) { + for(unsigned i=1; i( getPntrToVessel(i) ); + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); + if( lt2 ) { + double tcut=lt2->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else if( bt ) { + double tcut=bt->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else { + use_link=false; + } + } + } + if( use_link ) setLinkCellCutoff( rcut ); } } double Distances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector distance; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - const double value=distance.modulo(); - const double invvalue=1.0/value; - - // And finish the calculation - addAtomDerivatives( 1, 0,-invvalue*distance, myatoms ); - addAtomDerivatives( 1, 1, invvalue*distance, myatoms ); - myatoms.addBoxDerivatives( 1, -invvalue*Tensor(distance,distance) ); - return value; + Vector distance; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + const double value=distance.modulo(); + const double invvalue=1.0/value; + + // And finish the calculation + addAtomDerivatives( 1, 0,-invvalue*distance, myatoms ); + addAtomDerivatives( 1, 1, invvalue*distance, myatoms ); + myatoms.addBoxDerivatives( 1, -invvalue*Tensor(distance,distance) ); + return value; } } diff --git a/src/multicolvar/DumpMultiColvar.cpp b/src/multicolvar/DumpMultiColvar.cpp index 39760fbd46..27029a4369 100644 --- a/src/multicolvar/DumpMultiColvar.cpp +++ b/src/multicolvar/DumpMultiColvar.cpp @@ -40,13 +40,13 @@ namespace PLMD { namespace multicolvar { -//+PLUMEDOC PRINTANALYSIS DUMPMULTICOLVAR +//+PLUMEDOC PRINTANALYSIS DUMPMULTICOLVAR /* Dump atom positions and multicolvar on a file. \par Examples -In this examples we calculate the distances between the atoms of the first and the second -group and we write them in the file MULTICOLVAR.xyz. For each couple it writes the +In this examples we calculate the distances between the atoms of the first and the second +group and we write them in the file MULTICOLVAR.xyz. For each couple it writes the coordinates of their geometric center and their distance. \verbatim @@ -69,21 +69,21 @@ class DumpMultiColvar: { OFile of; double lenunit; - MultiColvarBase* mycolv; + MultiColvarBase* mycolv; std::string fmt_xyz; public: explicit DumpMultiColvar(const ActionOptions&); ~DumpMultiColvar(); static void registerKeywords( Keywords& keys ); - void calculate(){} - void calculateNumericalDerivatives( ActionWithValue* vv ){ plumed_error(); } - void apply(){} + void calculate() {} + void calculateNumericalDerivatives( ActionWithValue* vv ) { plumed_error(); } + void apply() {} void update(); }; PLUMED_REGISTER_ACTION(DumpMultiColvar,"DUMPMULTICOLVAR") -void DumpMultiColvar::registerKeywords( Keywords& keys ){ +void DumpMultiColvar::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); @@ -103,7 +103,7 @@ DumpMultiColvar::DumpMultiColvar(const ActionOptions&ao): { readArgument("store"); mycolv = dynamic_cast( getDependencies()[0] ); - plumed_assert( getDependencies().size()==1 ); + plumed_assert( getDependencies().size()==1 ); if(!mycolv) error("action labeled " + mycolv->getLabel() + " is not a multicolvar"); log.printf(" printing colvars calculated by action %s \n",mycolv->getLabel().c_str() ); @@ -121,7 +121,7 @@ DumpMultiColvar::DumpMultiColvar(const ActionOptions&ao): fmt_xyz="%f"; string precision; parse("PRECISION",precision); - if(precision.length()>0){ + if(precision.length()>0) { int p; Tools::convert(precision,p); log<<" with precision "<getCurrentNumberOfActiveTasks()); const Tensor & t(mycolv->getPbc().getBox()); - if(mycolv->getPbc().isOrthorombic()){ + if(mycolv->getPbc().isOrthorombic()) { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ + } else { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(), - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); } vesselbase::StoreDataVessel* stash=dynamic_cast( getPntrToArgument() ); plumed_dbg_assert( stash ); std::vector cvals( mycolv->getNumberOfQuantities() ); - for(unsigned i=0;igetCurrentNumberOfActiveTasks();++i){ + for(unsigned i=0; igetCurrentNumberOfActiveTasks(); ++i) { const char* defname="X"; const char* name=defname; @@ -167,18 +167,18 @@ void DumpMultiColvar::update(){ if( getNumberOfAtoms()>0 ) apos=pbcDistance( getPosition(0), apos ); of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz).c_str(),name,lenunit*apos[0],lenunit*apos[1],lenunit*apos[2]); stash->retrieveSequentialValue( i, true, cvals ); - if( mycolv->weightWithDerivatives() ){ - for(unsigned j=0;jweightWithDerivatives() ) { + for(unsigned j=0; jisPeriodic() ){ - std::string min, max; getPntrToMultiColvar()->retrieveDomain( min, max ); - double mlow, mhigh; Tools::convert( min,mlow ); Tools::convert( max, mhigh); - hb.isPeriodic( mlow, mhigh ); + if( getPntrToMultiColvar()->isPeriodic() ) { + std::string min, max; getPntrToMultiColvar()->retrieveDomain( min, max ); + double mlow, mhigh; Tools::convert( min,mlow ); Tools::convert( max, mhigh); + hb.isPeriodic( mlow, mhigh ); } else { - hb.isNotPeriodic(); + hb.isNotPeriodic(); } - if(sw.length()>0){ - hb.set(sw,errors); - if( errors.length()!=0 ) error("problem reading BEAD keyword : " + errors ); + if(sw.length()>0) { + hb.set(sw,errors); + if( errors.length()!=0 ) error("problem reading BEAD keyword : " + errors ); } else { - double l, u, s; std::string ll, uu, ss; - parse("LOWER",l); parse("UPPER",u); parse("SMEAR",s); - Tools::convert(l,ll); Tools::convert(u,uu); Tools::convert(s,ss); - sw="GAUSSIAN LOWER=" + ll + " UPPER=" + uu + " SMEAR=" + ss; - hb.set(sw,errors); plumed_massert(errors.length()==0,"problems with bead" + errors); + double l, u, s; std::string ll, uu, ss; + parse("LOWER",l); parse("UPPER",u); parse("SMEAR",s); + Tools::convert(l,ll); Tools::convert(u,uu); Tools::convert(s,ss); + sw="GAUSSIAN LOWER=" + ll + " UPPER=" + uu + " SMEAR=" + ss; + hb.set(sw,errors); plumed_massert(errors.length()==0,"problems with bead" + errors); } log.printf(" filtering colvar values and focussing only on those values in range %s\n",( hb.description() ).c_str() ); - checkRead(); + checkRead(); } double FilterBetween::applyFilter( const double& val, double& df ) const { - double f = hb.calculate( val, df ); + double f = hb.calculate( val, df ); return f; } diff --git a/src/multicolvar/FilterLessThan.cpp b/src/multicolvar/FilterLessThan.cpp index e24d8ad23c..6363bcbb43 100644 --- a/src/multicolvar/FilterLessThan.cpp +++ b/src/multicolvar/FilterLessThan.cpp @@ -27,9 +27,9 @@ /* This action can be useed to transform the colvar values calculated by a multicolvar using a \ref switchingfunction -In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that -is equal to one if the colvar is less than a certain target value and which is equal to zero otherwise. -It is important to understand the distinction between what is done here and what is done by \ref MFILTER_LESS. +In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that +is equal to one if the colvar is less than a certain target value and which is equal to zero otherwise. +It is important to understand the distinction between what is done here and what is done by \ref MFILTER_LESS. In \ref MFILTER_LESS a weight, \f$w_i\f$ for the colvar is calculated using the \ref switchingfunction. If one calculates the MEAN for \ref MFILTER_LESS one is thus calculating: @@ -37,19 +37,19 @@ MEAN for \ref MFILTER_LESS one is thus calculating: \mu = \frac{ \sum_i \sigma(s_i) s_i }{\sum_i \simga(s_i) } \f] -where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by +where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. If one thus calculates a MEAN for thia action one computes: \f[ -\mu = \frac{ \sum_{i=1}^N \simga(s_i) }{ N } +\mu = \frac{ \sum_{i=1}^N \simga(s_i) }{ N } \f] -In other words, you are calculating the mean for the transformed colvar. +In other words, you are calculating the mean for the transformed colvar. \par Examples -The following input gives an example of how a MTRANSFORM_LESS action can be used to duplicate -functionality that is elsehwere in PLUMED. +The following input gives an example of how a MTRANSFORM_LESS action can be used to duplicate +functionality that is elsehwere in PLUMED. \verbatim DISTANCES ... @@ -63,30 +63,30 @@ In this case you can achieve the same result by using: \verbatim DISTANCES ... - GROUPA=1-10 GROUPB=11-20 + GROUPA=1-10 GROUPB=11-20 LESS_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} ... DISTANCES \endverbatim (see \ref DISTANCES) The advantage of MTRANSFORM_LESS comes, however, if you want to use transformed colvars as input -for \ref MULTICOLVARDENS +for \ref MULTICOLVARDENS */ //+ENDPLUMEDOC //+PLUMEDOC MFILTERS MFILTER_LESS /* -This action can be used to filter the distribution of colvar values in a multicolvar +This action can be used to filter the distribution of colvar values in a multicolvar so that one can compute the mean and so on for only those multicolvars less than a tolerance. This action can be used to create a dynamic group of atom based on the value of a multicolvar. In this action a multicolvar is within the dynamic group if its value is less than a target. In practise a weight, \f$w_i\f$ is ascribed to each colvar, \f$s_i\f$ calculated by a multicolvar -and this weight measures the degree to which a colvar is a member of the group. This weight is a number -between 0 and 1 that is calculated using a \ref switchingfunction , \f$\sigma\f$. +and this weight measures the degree to which a colvar is a member of the group. This weight is a number +between 0 and 1 that is calculated using a \ref switchingfunction , \f$\sigma\f$. If one calculates a function of the set of multicolvars -these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered +these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered multicolvar what is computed is the following: \f[ @@ -117,41 +117,41 @@ class FilterLess : public MultiColvarFilter { static void registerKeywords( Keywords& keys ); explicit FilterLess(const ActionOptions& ao); double applyFilter( const double& val, double& df ) const ; -}; +}; PLUMED_REGISTER_ACTION(FilterLess,"MFILTER_LESS") PLUMED_REGISTER_ACTION(FilterLess,"MTRANSFORM_LESS") -void FilterLess::registerKeywords( Keywords& keys ){ +void FilterLess::registerKeywords( Keywords& keys ) { MultiColvarFilter::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function "); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); } FilterLess::FilterLess(const ActionOptions& ao): -Action(ao), -MultiColvarFilter(ao) + Action(ao), + MultiColvarFilter(ao) { // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - sf.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if(sw.length()>0) { + sf.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - sf.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + sf.set(nn,mm,r_0,d_0); } log.printf(" filtering colvar values and focussing only on those less than %s\n",( sf.description() ).c_str() ); - checkRead(); + checkRead(); } double FilterLess::applyFilter( const double& val, double& df ) const { diff --git a/src/multicolvar/FilterMoreThan.cpp b/src/multicolvar/FilterMoreThan.cpp index 2c0f0e68e6..961c33d016 100644 --- a/src/multicolvar/FilterMoreThan.cpp +++ b/src/multicolvar/FilterMoreThan.cpp @@ -27,9 +27,9 @@ /* This action can be useed to transform the colvar values calculated by a multicolvar using one minus a \ref switchingfunction -In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that -is equal to one if the colvar is greater than a certain target value and which is equal to zero otherwise. -It is important to understand the distinction between what is done here and what is done by \ref MFILTER_MORE. +In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that +is equal to one if the colvar is greater than a certain target value and which is equal to zero otherwise. +It is important to understand the distinction between what is done here and what is done by \ref MFILTER_MORE. In \ref MFILTER_MORE a weight, \f$w_i\f$ for the colvar is calculated using the \ref histogrambead. If one calculates the MEAN for \ref MFILTER_MORE one is thus calculating: @@ -37,19 +37,19 @@ MEAN for \ref MFILTER_MORE one is thus calculating: \mu = \frac{ \sum_i [1 - \sigma(s_i) ] s_i }{\sum_i [1 - \sigma(s_i)] } \f] -where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. +where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. If one thus calculates a MEAN for this action one computes: \f[ -\mu = \frac{ \sum_{i=1}^N 1 - \sigma(s_i) }{ N } +\mu = \frac{ \sum_{i=1}^N 1 - \sigma(s_i) }{ N } \f] -In other words, you are calculating the mean for the transformed colvar. +In other words, you are calculating the mean for the transformed colvar. \par Examples -The following input gives an example of how a MTRANSFORM_MORE action can be used to duplicate -functionality that is elsehwere in PLUMED. +The following input gives an example of how a MTRANSFORM_MORE action can be used to duplicate +functionality that is elsehwere in PLUMED. \verbatim DISTANCES ... @@ -63,27 +63,27 @@ In this case you can achieve the same result by using: \verbatim DISTANCES ... - GROUPA=1-10 GROUPB=11-20 + GROUPA=1-10 GROUPB=11-20 MORE_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} ... DISTANCES \endverbatim (see \ref DISTANCES) The advantage of MTRANSFORM_MORE comes, however, if you want to use transformed colvars as input -for \ref MULTICOLVARDENS +for \ref MULTICOLVARDENS */ //+ENDPLUMEDOC //+PLUMEDOC MFILTERS MFILTER_MORE /* -This action can be used to filter the distribution of colvar values in a multicolvar +This action can be used to filter the distribution of colvar values in a multicolvar so that one can compute the mean and so on for only those multicolvars more than a tolerance. This action can be used to create a dynamic group of atom based on the value of a multicolvar. In this action a multicolvar is within the dynamic group if its value is greater than a target. In practise a weight, \f$w_i\f$ is ascribed to each colvar, \f$s_i\f$ calculated by a multicolvar -and this weight measures the degree to which a colvar is a member of the group. This weight is +and this weight measures the degree to which a colvar is a member of the group. This weight is calculated using a \ref switchingfunction , \f$\sigma\f$ so it is given by: \f[ @@ -91,7 +91,7 @@ w_i = 1 - \sigma(s_i) \f] If one calculates a function of the set of multicolvars -these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered +these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered multicolvar what is computed is the following: \f[ @@ -109,10 +109,10 @@ DISTANCES GROUPA=1 GROUPB=2-50 MEAN LABEL=d1 MFILTER_MORE DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} MEAN LABEL=d4 \endverbatim -More complicated things can be done by using the label of a filter as input to a new multicolvar as shown -in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination +More complicated things can be done by using the label of a filter as input to a new multicolvar as shown +in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination number greater than 2 are then identified using the filter. This reduced list of atoms is then used as input -to a second coordination number calculation. This second coordination number thus measures the number of +to a second coordination number calculation. This second coordination number thus measures the number of two-coordinated atoms that each of the two-coordinated atoms is bound to. \verbatim @@ -134,41 +134,41 @@ class FilterMore : public MultiColvarFilter { static void registerKeywords( Keywords& keys ); explicit FilterMore(const ActionOptions& ao); double applyFilter( const double& val, double& df ) const ; -}; +}; PLUMED_REGISTER_ACTION(FilterMore,"MFILTER_MORE") PLUMED_REGISTER_ACTION(FilterMore,"MTRANSFORM_MORE") -void FilterMore::registerKeywords( Keywords& keys ){ +void FilterMore::registerKeywords( Keywords& keys ) { MultiColvarFilter::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); } FilterMore::FilterMore(const ActionOptions& ao): -Action(ao), -MultiColvarFilter(ao) + Action(ao), + MultiColvarFilter(ao) { // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - sf.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if(sw.length()>0) { + sf.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - sf.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + sf.set(nn,mm,r_0,d_0); } log.printf(" filtering colvar values and focussing only on those more than %s\n",( sf.description() ).c_str() ); - checkRead(); + checkRead(); } double FilterMore::applyFilter( const double& val, double& df ) const { diff --git a/src/multicolvar/InPlaneDistances.cpp b/src/multicolvar/InPlaneDistances.cpp index 1801e31bf6..d041fa1e02 100644 --- a/src/multicolvar/InPlaneDistances.cpp +++ b/src/multicolvar/InPlaneDistances.cpp @@ -32,14 +32,14 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR INPLANEDISTANCES /* Calculate distances in the plane perpendicular to an axis -Each quantity calculated in this CV uses the positions of two atoms, this indices of which are specified using the VECTORSTART and VECTOREND keywords, to specify the +Each quantity calculated in this CV uses the positions of two atoms, this indices of which are specified using the VECTORSTART and VECTOREND keywords, to specify the orientation of a vector, \f$\mathbf{n}\f$. The perpendicular distance between this vector and the position of some third atom is then computed using: \f[ x_j = |\mathbf{r}_{j}| \sin (\theta_j) @@ -50,8 +50,8 @@ Keywords such as MORE_THAN and LESS_THAN can then be used to calculate the numbe \par Examples -The following input can be used to calculate the number of atoms that have indices greater than 3 and less than 101 that -are within a cylinder with a radius of 0.3 nm that has its long axis aligned with the vector connecting atoms 1 and 2. +The following input can be used to calculate the number of atoms that have indices greater than 3 and less than 101 that +are within a cylinder with a radius of 0.3 nm that has its long axis aligned with the vector connecting atoms 1 and 2. \verbatim d1: INPLANEDISTANCES VECTORSTART=1 VECTOREND=2 GROUP=3-100 LESS_THAN={RATIONAL D_0=0.2 R_0=0.1} @@ -67,16 +67,16 @@ class InPlaneDistances : public MultiColvarBase { static void registerKeywords( Keywords& keys ); explicit InPlaneDistances(const ActionOptions&); // active methods: - virtual double compute(const unsigned& tindex, AtomValuePack& myatoms ) const ; - bool isPeriodic(){ return false; } + virtual double compute(const unsigned& tindex, AtomValuePack& myatoms ) const ; + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(InPlaneDistances,"INPLANEDISTANCES") -void InPlaneDistances::registerKeywords( Keywords& keys ){ +void InPlaneDistances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); - keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); + keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("atoms","VECTORSTART","The first atom position that is used to define the normal to the plane of interest"); keys.add("atoms","VECTOREND","The second atom position that is used to defin the normal to the plane of interest"); @@ -84,8 +84,8 @@ void InPlaneDistances::registerKeywords( Keywords& keys ){ } InPlaneDistances::InPlaneDistances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms std::vector all_atoms; @@ -99,32 +99,32 @@ MultiColvarBase(ao) // And check everything has been read in correctly checkRead(); - // Now check if we can use link cells +// Now check if we can use link cells bool use_link=false; double rcut; - if( getNumberOfVessels()>0 ){ - vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); - if( lt ){ - use_link=true; rcut=lt->getCutoff(); - } else { - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); - if( bt ) use_link=true; rcut=bt->getCutoff(); - } - if( use_link ){ - for(unsigned i=1;i( getPntrToVessel(i) ); - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); - if( lt2 ){ - double tcut=lt2->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else if( bt ){ - double tcut=bt->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else { - use_link=false; - } - } - } - if( use_link ) setLinkCellCutoff( rcut ); + if( getNumberOfVessels()>0 ) { + vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); + if( lt ) { + use_link=true; rcut=lt->getCutoff(); + } else { + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); + if( bt ) use_link=true; rcut=bt->getCutoff(); + } + if( use_link ) { + for(unsigned i=1; i( getPntrToVessel(i) ); + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); + if( lt2 ) { + double tcut=lt2->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else if( bt ) { + double tcut=bt->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else { + use_link=false; + } + } + } + if( use_link ) setLinkCellCutoff( rcut ); } } @@ -132,7 +132,7 @@ double InPlaneDistances::compute( const unsigned& tindex, AtomValuePack& myatoms Vector normal=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); Vector dir=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); PLMD::Angle a; Vector ddij, ddik; double angle=a.compute(normal,dir,ddij,ddik); - double sangle=sin(angle), cangle=cos(angle); + double sangle=sin(angle), cangle=cos(angle); double dd=dir.modulo(), invdd=1.0/dd, val=dd*sangle; addAtomDerivatives( 1, 0, dd*cangle*ddik + sangle*invdd*dir, myatoms ); diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index 1e1d5c6c02..fdc3e09c4f 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -29,29 +29,29 @@ Calculate averages over spherical regions centered on atoms As is explained in this video certain multicolvars -calculate one scalar quantity or one vector for each of the atoms in the system. For example +calculate one scalar quantity or one vector for each of the atoms in the system. For example \ref COORDINATIONNUMBER measures the coordination number of each of the atoms in the system and \ref Q4 measures the 4th order Steinhardt parameter for each of the atoms in the system. These quantities provide tell us something about the disposition of the atoms in the first coordination sphere of each of the atoms of interest. Lechner and Dellago \cite dellago-q6 have suggested that one can probe local order in a system by taking the average value of such symmetry functions over the atoms within a spherical cutoff of each of these atoms in the systems. When this is done with Steinhardt parameters -they claim this gives a coordinate that is better able to distinguish solid and liquid configurations of Lennard-Jones atoms. +they claim this gives a coordinate that is better able to distinguish solid and liquid configurations of Lennard-Jones atoms. -You can calculate such locally averaged quantities within plumed by using the LOCAL_AVERAGE command. This command calculates +You can calculate such locally averaged quantities within plumed by using the LOCAL_AVERAGE command. This command calculates the following atom-centered quantities: \f[ -s_i = \frac{ c_i + \sum_j \sigma(r_{ij})c_j }{ 1 + \sum_j \sigma(r_{ij}) } +s_i = \frac{ c_i + \sum_j \sigma(r_{ij})c_j }{ 1 + \sum_j \sigma(r_{ij}) } \f] -where the \f$c_i\f$ and \f$c_j\f$ values can be for any one of the symmetry functions that can be calculated using plumed -multicolvars. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +where the \f$c_i\f$ and \f$c_j\f$ values can be for any one of the symmetry functions that can be calculated using plumed +multicolvars. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. Lechner and Dellago suggest that the parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. -The \f$s_i\f$ quantities calculated using the above command can be again thought of as atom-centred symmetry functions. They +The \f$s_i\f$ quantities calculated using the above command can be again thought of as atom-centred symmetry functions. They thus operate much like multicolvars. You can thus calculate properties of the distribution of \f$s_i\f$ values using MEAN, LESS_THAN, HISTOGRAM -and so on. You can also probe the value of these averaged variables in regions of the box by using the command in tandem with the +and so on. You can also probe the value of these averaged variables in regions of the box by using the command in tandem with the \ref AROUND command. \par Examples @@ -62,12 +62,12 @@ spherical regions. The number of averaged coordination numbers that are greater \verbatim COORDINATIONNUMBER SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=d1 LOCAL_AVERAGE ARG=d1 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MORE_THAN={RATIONAL R_0=4} LABEL=la -PRINT ARG=la.* FILE=colvar +PRINT ARG=la.* FILE=colvar \endverbatim -This example input calculates the \f$q_4\f$ (see \ref Q4) vectors for each of the atoms in the system. These vectors are then averaged -component by component over a spherical region. The average value for this quantity is then outputeed to a file. This calculates the -quantities that were used in the paper by Lechner and Dellago \cite dellago-q6 +This example input calculates the \f$q_4\f$ (see \ref Q4) vectors for each of the atoms in the system. These vectors are then averaged +component by component over a spherical region. The average value for this quantity is then outputeed to a file. This calculates the +quantities that were used in the paper by Lechner and Dellago \cite dellago-q6 \verbatim Q4 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q4 @@ -95,49 +95,49 @@ class LocalAverage : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(LocalAverage,"LOCAL_AVERAGE") -void LocalAverage::registerKeywords( Keywords& keys ){ +void LocalAverage::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); keys.remove("LOWMEM"); keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); - keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); + 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), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { if( getNumberOfBaseMultiColvars()>1 ) error("local average with more than one base colvar makes no sense"); // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" averaging over central molecule and those within %s\n",( switchingFunction.description() ).c_str() ); rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); setLinkCellCutoff( switchingFunction.get_dmax() ); - std::vector all_atoms; setupMultiColvarBase( all_atoms ); + std::vector all_atoms; setupMultiColvarBase( all_atoms ); } unsigned LocalAverage::getNumberOfQuantities() const { @@ -146,113 +146,113 @@ unsigned LocalAverage::getNumberOfQuantities() const { double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { double d2, sw, dfunc; MultiValue& myvals = myatoms.getUnderlyingMultiValue(); - std::vector values( getBaseMultiColvar(0)->getNumberOfQuantities() ); + std::vector values( getBaseMultiColvar(0)->getNumberOfQuantities() ); getInputData( 0, false, myatoms, values ); myvals.addTemporyValue( values[0] ); - if( values.size()>2 ){ - for(unsigned j=2;j2 ) { + for(unsigned j=2; j2 ){ - for(unsigned j=0;j2 ) { + for(unsigned j=0; j2 ){ - for(unsigned j=2;j2 ){ - for(unsigned j=0;j2 ) { + for(unsigned j=2; j2 ) { + for(unsigned j=0; j2){ - double norm=0; - for(unsigned i=2;i2) { + double norm=0; + for(unsigned i=2; i& all_atoms ){ +void MultiColvarBase::readAtomsLikeKeyword( const std::string & key, const int& natoms, std::vector& all_atoms ) { plumed_assert( !usespecies ); if( all_atoms.size()>0 ) return; std::vector t; - for(int i=1;;++i ){ - parseAtomList(key, i, t ); - if( t.empty() ) break; - - log.printf(" Colvar %d is calculated from atoms : ", i); - for(unsigned j=0;j( 0, ablocks.size()*(i-1)+j ) ); - } - t.resize(0); + for(int i=1;; ++i ) { + parseAtomList(key, i, t ); + if( t.empty() ) break; + + log.printf(" Colvar %d is calculated from atoms : ", i); + for(unsigned j=0; j( 0, ablocks.size()*(i-1)+j ) ); + } + t.resize(0); } - if( all_atoms.size()>0 ){ - nblock=0; - for(unsigned i=0;i0 ) { + nblock=0; + for(unsigned i=0; i& t){ - std::vector mlabs; +bool MultiColvarBase::parseMultiColvarAtomList(const std::string& key, const int& num, std::vector& t) { + std::vector mlabs; if( num<0 ) parseVector(key,mlabs); else parseNumberedVector(key,num,mlabs); if( mlabs.size()==0 ) return false; std::string mname; unsigned found_mcolv=mlabs.size(); - for(unsigned i=0;i(mlabs[i]); - if(!mycolv){ found_mcolv=i; break; } - // Check all base multicolvars are of same type - if( i==0 ){ - mname = mycolv->getName(); - 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"); - } - // And track which variable stores each colvar - for(unsigned j=0;jgetFullNumberOfTasks();++j) atom_lab.push_back( std::pair( mybasemulticolvars.size()+1, j ) ); - // And store the multicolvar base - mybasemulticolvars.push_back( mycolv ); - // And create a basedata stash - mybasedata.push_back( mybasemulticolvars[mybasemulticolvars.size()-1]->buildDataStashes( this ) ); - // Check if weight has derivatives - if( mybasemulticolvars[ mybasemulticolvars.size()-1 ]->weightHasDerivatives ) weightHasDerivatives=true; - plumed_assert( mybasemulticolvars.size()==mybasedata.size() ); + for(unsigned i=0; i(mlabs[i]); + if(!mycolv) { found_mcolv=i; break; } + // Check all base multicolvars are of same type + if( i==0 ) { + mname = mycolv->getName(); + 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"); + } + // And track which variable stores each colvar + for(unsigned j=0; jgetFullNumberOfTasks(); ++j) atom_lab.push_back( std::pair( mybasemulticolvars.size()+1, j ) ); + // And store the multicolvar base + mybasemulticolvars.push_back( mycolv ); + // And create a basedata stash + mybasedata.push_back( mybasemulticolvars[mybasemulticolvars.size()-1]->buildDataStashes( this ) ); + // Check if weight has derivatives + if( mybasemulticolvars[ mybasemulticolvars.size()-1 ]->weightHasDerivatives ) weightHasDerivatives=true; + plumed_assert( mybasemulticolvars.size()==mybasedata.size() ); } // Have we conventional atoms to read in - if( found_mcolv==0 ){ - std::vector tt; ActionAtomistic::interpretAtomList( mlabs, tt ); - for(unsigned i=0;i( 0, t.size() + i ) ); } - log.printf(" keyword %s takes atoms : ", key.c_str() ); - for(unsigned i=0;i tt; ActionAtomistic::interpretAtomList( mlabs, tt ); + for(unsigned i=0; i( 0, t.size() + i ) ); } + log.printf(" keyword %s takes atoms : ", key.c_str() ); + for(unsigned i=0; i& all_atoms ){ +void MultiColvarBase::readTwoGroups( const std::string& key0, const std::string& key1, const std::string& key2, std::vector& all_atoms ) { plumed_dbg_assert( keywords.exists(key0) && keywords.exists(key1) && keywords.exists(key2) ); ablocks.resize( 2 ); - if( parseMultiColvarAtomList(key0,-1,all_atoms) ){ - nblock=atom_lab.size(); for(unsigned i=0;i<2;++i) ablocks[i].resize(nblock); - resizeBookeepingArray( nblock, nblock ); - for(unsigned i=0;iablocks[1].size() ) nblock = ablocks[0].size(); - else nblock=ablocks[1].size(); - - resizeBookeepingArray( ablocks[0].size(), ablocks[1].size() ); - for(unsigned i=0;i0 && atom_lab[ablocks[1][j]].first>0 ){ - if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && - atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second ) addTaskToList( i*nblock + j ); - } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] ) addTaskToList( i*nblock + j ); - bookeeping(i,j).second=getFullNumberOfTasks(); - } + parseMultiColvarAtomList(key1,-1,all_atoms); + ablocks[0].resize( atom_lab.size() ); for(unsigned i=0; iablocks[1].size() ) nblock = ablocks[0].size(); + else nblock=ablocks[1].size(); + + resizeBookeepingArray( ablocks[0].size(), ablocks[1].size() ); + for(unsigned i=0; i0 && atom_lab[ablocks[1][j]].first>0 ) { + if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && + atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second ) addTaskToList( i*nblock + j ); + } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] ) addTaskToList( i*nblock + j ); + bookeeping(i,j).second=getFullNumberOfTasks(); } + } } } -void MultiColvarBase::readGroupKeywords( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& key3, - const bool& no_third_dim_accum, const bool& symmetric, std::vector& all_atoms ){ +void MultiColvarBase::readGroupKeywords( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& key3, + const bool& no_third_dim_accum, const bool& symmetric, std::vector& all_atoms ) { plumed_dbg_assert( keywords.exists(key0) && keywords.exists(key1) && keywords.exists(key2) && keywords.exists(key3) ); ablocks.resize( 3 ); - if( parseMultiColvarAtomList(key0,-1,all_atoms) ){ - if( no_third_dim_accum ){ - nblock=atom_lab.size(); ablocks[0].resize(nblock); ablocks[1].resize( nblock ); - for(unsigned i=0;i& all_atoms ){ +void MultiColvarBase::readThreeGroups( const std::string& key1, const std::string& key2, const std::string& key3, + const bool& allow2, const bool& no_third_dim_accum, std::vector& all_atoms ) { plumed_dbg_assert( keywords.exists(key1) && keywords.exists(key2) && keywords.exists(key3) ); ablocks.resize( 3 ); bool readkey1=parseMultiColvarAtomList(key1,-1,all_atoms); - ablocks[0].resize( atom_lab.size() ); for(unsigned i=0;iablocks[0].size() ) nblock=ablocks[1].size(); - else nblock=ablocks[0].size(); - - ablocks[2].resize( ablocks[1].size() ); - for(unsigned i=0;i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ){ - if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && - atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && - all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && - all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } - bookeeping(i,j).second=getFullNumberOfTasks(); + if( !readkey3 && !allow2 ) { + error("missing atom specification " + key3); + } else if( !readkey3 ) { + if( ablocks[1].size()>ablocks[0].size() ) nblock=ablocks[1].size(); + else nblock=ablocks[0].size(); + + ablocks[2].resize( ablocks[1].size() ); + for(unsigned i=0; i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ) { + if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && + atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); + } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && + all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && + all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); } + bookeeping(i,j).second=getFullNumberOfTasks(); } + } } else { - ablocks[2].resize( atom_lab.size() - ablocks[1].size() - ablocks[0].size() ); - for(unsigned i=0;iablocks[0].size() ) nblock=ablocks[1].size(); - else nblock=ablocks[0].size(); - if( ablocks[2].size()>nblock ) nblock=ablocks[2].size(); - - unsigned kcount; if( no_third_dim_accum ) kcount=1; else kcount=ablocks[2].size(); - - for(unsigned i=0;i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ){ - if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && - atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && - all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && - all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } - bookeeping(i,j).second=getFullNumberOfTasks(); - } + ablocks[2].resize( atom_lab.size() - ablocks[1].size() - ablocks[0].size() ); + for(unsigned i=0; iablocks[0].size() ) nblock=ablocks[1].size(); + else nblock=ablocks[0].size(); + if( ablocks[2].size()>nblock ) nblock=ablocks[2].size(); + + unsigned kcount; if( no_third_dim_accum ) kcount=1; else kcount=ablocks[2].size(); + + for(unsigned i=0; i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ) { + if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && + atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); + } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && + all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && + all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); + } + bookeeping(i,j).second=getFullNumberOfTasks(); } + } } } -void MultiColvarBase::buildSets(){ +void MultiColvarBase::buildSets() { std::vector fake_atoms; if( !parseMultiColvarAtomList("DATA",-1,fake_atoms) ) error("missing DATA keyword"); if( fake_atoms.size()>0 ) error("no atoms should appear in the specification for this object. Input should be other multicolvars"); nblock = mybasemulticolvars[0]->getFullNumberOfTasks(); - for(unsigned i=0;igetFullNumberOfTasks()!=nblock ){ - error("mismatch between numbers of tasks in various base multicolvars"); - } + for(unsigned i=0; igetFullNumberOfTasks()!=nblock ) { + error("mismatch between numbers of tasks in various base multicolvars"); + } } ablocks.resize( mybasemulticolvars.size() ); usespecies=false; - for(unsigned i=0;iresizeTemporyMultiValues( mybasemulticolvars.size() ); setupMultiColvarBase( fake_atoms ); } -void MultiColvarBase::addTaskToList( const unsigned& taskCode ){ +void MultiColvarBase::addTaskToList( const unsigned& taskCode ) { plumed_assert( getNumberOfVessels()==0 ); ActionWithVessel::addTaskToList( taskCode ); } -void MultiColvarBase::resizeBookeepingArray( const unsigned& num1, const unsigned& num2 ){ +void MultiColvarBase::resizeBookeepingArray( const unsigned& num1, const unsigned& num2 ) { bookeeping.resize( num1, num2 ); - for(unsigned i=0;i& atoms ){ +void MultiColvarBase::setupMultiColvarBase( const std::vector& atoms ) { if( !matsums && atom_lab.size()==0 ) error("No atoms have been read in"); std::vector all_atoms; // Setup decoder array - if( !usespecies && nblock>0 ){ - - ncentral=ablocks.size(); use_for_central_atom.resize( ablocks.size(), true ); - numberForCentralAtom = 1.0 / static_cast( ablocks.size() ); - if( ablocks.size()==3 ){ - allthirdblockintasks=uselinkforthree=true; - for(unsigned i=0;istd::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); - } else { - decoder.resize( ablocks.size() ); - // Check if number of atoms is too large - if( pow( double(nblock), double(ablocks.size()) )>std::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); - } - unsigned code=1; for(unsigned i=0;i( ablocks.size() ); - } else if( keywords.exists("SPECIESA") ){ - plumed_assert( atom_lab.size()==0 && all_atoms.size()==0 ); - ablocks.resize( 1 ); bool readspecies=parseMultiColvarAtomList("SPECIES", -1, all_atoms); - if( readspecies ){ - ablocks[0].resize( atom_lab.size() ); for(unsigned i=0;i0 && atom_lab[j].first>0 ){ - if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== - mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ){ found=true; inum=j; break; } - } else if( all_atoms[atom_lab[nat1+i].second]==all_atoms[atom_lab[j].second] ){ found=true; inum=j; break; } - } - // This prevents mistakes being made in colvar setup - if( found ){ ablocks[0][i]=inum; } - else { ablocks[0][i]=nat1 + i; } - } - } - } - if( mybasemulticolvars.size()>0 ){ - for(unsigned i=0;iresizeTemporyMultiValues(2); mybasemulticolvars[i]->my_tmp_capacks.resize(2); + if( !usespecies && nblock>0 ) { + + ncentral=ablocks.size(); use_for_central_atom.resize( ablocks.size(), true ); + numberForCentralAtom = 1.0 / static_cast( ablocks.size() ); + if( ablocks.size()==3 ) { + allthirdblockintasks=uselinkforthree=true; + for(unsigned i=0; istd::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); + } else { + decoder.resize( ablocks.size() ); + // Check if number of atoms is too large + if( pow( double(nblock), double(ablocks.size()) )>std::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); + } + unsigned code=1; for(unsigned i=0; i( ablocks.size() ); + } else if( keywords.exists("SPECIESA") ) { + plumed_assert( atom_lab.size()==0 && all_atoms.size()==0 ); + ablocks.resize( 1 ); bool readspecies=parseMultiColvarAtomList("SPECIES", -1, all_atoms); + if( readspecies ) { + ablocks[0].resize( atom_lab.size() ); for(unsigned i=0; i0 && atom_lab[j].first>0 ) { + if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== + mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ) { found=true; inum=j; break; } + } else if( all_atoms[atom_lab[nat1+i].second]==all_atoms[atom_lab[j].second] ) { found=true; inum=j; break; } + } + // This prevents mistakes being made in colvar setup + if( found ) { ablocks[0][i]=inum; } + else { ablocks[0][i]=nat1 + i; } + } + } + } + if( mybasemulticolvars.size()>0 ) { + for(unsigned i=0; iresizeTemporyMultiValues(2); mybasemulticolvars[i]->my_tmp_capacks.resize(2); + } } - // Copy lists of atoms involved from base multicolvars + // Copy lists of atoms involved from base multicolvars std::vector tmp_atoms; - for(unsigned i=0;igetAbsoluteIndexes(); - for(unsigned j=0;jgetAbsoluteIndexes(); + for(unsigned j=0; j& catom_ind ){ +void MultiColvarBase::setAtomsForCentralAtom( const std::vector& catom_ind ) { unsigned nat=0; plumed_assert( catom_ind.size()==ablocks.size() ); - for(unsigned i=0;i0 ); ncentral=nat; numberForCentralAtom = 1.0 / static_cast( nat ); } -void MultiColvarBase::turnOnDerivatives(){ +void MultiColvarBase::turnOnDerivatives() { ActionWithValue::turnOnDerivatives(); - needsDerivatives(); + needsDerivatives(); forcesToApply.resize( getNumberOfDerivatives() ); -} +} -void MultiColvarBase::setLinkCellCutoff( const double& lcut, double tcut ){ +void MultiColvarBase::setLinkCellCutoff( const double& lcut, double tcut ) { plumed_assert( usespecies || ablocks.size()<4 ); if( tcut<0 ) tcut=lcut; - linkcells.setCutoff( lcut ); + linkcells.setCutoff( lcut ); threecells.setCutoff( tcut ); } @@ -498,132 +498,132 @@ double MultiColvarBase::getLinkCellCutoff() const { return linkcells.getCutoff(); } -void MultiColvarBase::setupLinkCells(){ +void MultiColvarBase::setupLinkCells() { if( (!usespecies && nblock==0) || !linkcells.enabled() ) return ; // Retrieve any atoms that haven't already been retrieved - for(std::vector::iterator p=mybasemulticolvars.begin();p!=mybasemulticolvars.end();++p){ - (*p)->retrieveAtoms(); + for(std::vector::iterator p=mybasemulticolvars.begin(); p!=mybasemulticolvars.end(); ++p) { + (*p)->retrieveAtoms(); } retrieveAtoms(); unsigned iblock; - if( usespecies ){ - iblock=0; - } else if( ablocks.size()<4 ){ - iblock=1; + if( usespecies ) { + iblock=0; + } else if( ablocks.size()<4 ) { + iblock=1; } else { - plumed_error(); + plumed_error(); } - + // Count number of currently active atoms nactive_atoms=0; - for(unsigned i=0;i0 ){ - std::vector ltmp_pos( nactive_atoms ); - std::vector ltmp_ind( nactive_atoms ); - - nactive_atoms=0; - if( usespecies ){ - for(unsigned i=0;i0 ) { + std::vector ltmp_pos( nactive_atoms ); + std::vector ltmp_ind( nactive_atoms ); + + nactive_atoms=0; + if( usespecies ) { + for(unsigned i=0; i requiredlinkcells; - if( !uselinkforthree && nactive_atoms>0 ){ - // Get some parallel info - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if( serialCalculation() ){ stride=1; rank=0; } - - // Ensure we only do tasks where atoms are in appropriate link cells - std::vector linked_atoms( 1+ablocks[1].size() ); - for(unsigned i=rank;i0 ){ - // Get some parallel info - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if( serialCalculation() ){ stride=1; rank=0; } - - unsigned nactive_three=0; - for(unsigned i=0;i lttmp_pos( nactive_three ); - std::vector lttmp_ind( nactive_three ); - - nactive_three=0; - if( allthirdblockintasks ){ - for(unsigned i=0;i linked_atoms( 1+ablocks[1].size() ); - std::vector tlinked_atoms( 1+ablocks[2].size() ); - for(unsigned i=rank;i0 ) { + // Get some parallel info + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if( serialCalculation() ) { stride=1; rank=0; } + + // Ensure we only do tasks where atoms are in appropriate link cells + std::vector linked_atoms( 1+ablocks[1].size() ); + for(unsigned i=rank; i0 ) { + // Get some parallel info + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if( serialCalculation() ) { stride=1; rank=0; } + + unsigned nactive_three=0; + for(unsigned i=0; i lttmp_pos( nactive_three ); + std::vector lttmp_ind( nactive_three ); + + nactive_three=0; + if( allthirdblockintasks ) { + for(unsigned i=0; i linked_atoms( 1+ablocks[1].size() ); + std::vector tlinked_atoms( 1+ablocks[2].size() ); + for(unsigned i=rank; i& atoms ) const { @@ -631,118 +631,118 @@ void MultiColvarBase::decodeIndexToAtoms( const unsigned& taskCode, std::vector< if( atoms.size()!=decoder.size() ) atoms.resize( decoder.size() ); unsigned scode = taskCode; - for(unsigned i=0;i task_atoms(1); task_atoms[0]=taskCode; - unsigned natomsper=myatoms.setupAtomsFromLinkCells( task_atoms, getPositionOfAtomForLinkCells( taskCode ), linkcells ); - return natomsper>1; - } else if( matsums ){ - myatoms.setNumberOfAtoms( getNumberOfAtoms() ); - for(unsigned i=0;i atoms(2); decodeIndexToAtoms( taskCode, atoms ); - myatoms.setupAtomsFromLinkCells( atoms, getPositionOfAtomForLinkCells( atoms[0] ), threecells ); - } else if( nblock>0 ){ - std::vector atoms( ablocks.size() ); - decodeIndexToAtoms( taskCode, atoms ); myatoms.setNumberOfAtoms( ablocks.size() ); - for(unsigned i=0;i task_atoms(1); task_atoms[0]=taskCode; + unsigned natomsper=myatoms.setupAtomsFromLinkCells( task_atoms, getPositionOfAtomForLinkCells( taskCode ), linkcells ); + return natomsper>1; + } else if( matsums ) { + myatoms.setNumberOfAtoms( getNumberOfAtoms() ); + for(unsigned i=0; i atoms(2); decodeIndexToAtoms( taskCode, atoms ); + myatoms.setupAtomsFromLinkCells( atoms, getPositionOfAtomForLinkCells( atoms[0] ), threecells ); + } else if( nblock>0 ) { + std::vector atoms( ablocks.size() ); + decodeIndexToAtoms( taskCode, atoms ); myatoms.setNumberOfAtoms( ablocks.size() ); + for(unsigned i=0; i& active_tasks, const std::string& input_label ){ - if( !setup_completed ){ - bool justVolumes=false; - if( usespecies ){ - justVolumes=true; - for(unsigned i=0;i( getPntrToVessel(i) ); - if( mys ) continue; - vesselbase::BridgeVessel* myb=dynamic_cast( getPntrToVessel(i) ); - if( !myb ){ justVolumes=false; break; } - ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); - if( !myv ){ justVolumes=false; break; } - } +void MultiColvarBase::setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ) { + if( !setup_completed ) { + bool justVolumes=false; + if( usespecies ) { + justVolumes=true; + for(unsigned i=0; i( getPntrToVessel(i) ); + if( mys ) continue; + vesselbase::BridgeVessel* myb=dynamic_cast( getPntrToVessel(i) ); + if( !myb ) { justVolumes=false; break; } + ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); + if( !myv ) { justVolumes=false; break; } } - deactivateAllTasks(); - if( justVolumes && mydata ){ - if( mydata->getNumberOfDataUsers()==0 ) justVolumes=false; - - for(unsigned i=0;igetNumberOfDataUsers();++i){ - MultiColvarBase* myu=dynamic_cast( mydata->getDataUser(i) ); - if( myu ){ - myu->setupActiveTaskSet( taskFlags, getLabel() ); - } else { - for(unsigned i=0;igetNumberOfDataUsers()==0 ) justVolumes=false; + + for(unsigned i=0; igetNumberOfDataUsers(); ++i) { + MultiColvarBase* myu=dynamic_cast( mydata->getDataUser(i) ); + if( myu ) { + myu->setupActiveTaskSet( taskFlags, getLabel() ); + } else { + for(unsigned i=0; i( getPntrToVessel(j) ); - if( !myb ) continue ; - ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); - if( !myv ) continue ; - myv->retrieveAtoms(); myv->setupRegions(); - - for(unsigned i=0;iinVolumeOfInterest(i) ) taskFlags[i]=1; - } - } - } else { - for(unsigned i=0;i( getPntrToVessel(j) ); + if( !myb ) continue ; + ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); + if( !myv ) continue ; + myv->retrieveAtoms(); myv->setupRegions(); + + for(unsigned i=0; iinVolumeOfInterest(i) ) taskFlags[i]=1; + } + } + } else { + for(unsigned i=0; igetLabel()==input_label ){ input_code=i+1; break; } - } - - MultiValue my_tvals( getNumberOfQuantities(), getNumberOfDerivatives() ); - AtomValuePack mytmp_atoms( my_tvals, this ); - for(unsigned i=0;igetLabel()==input_label ) { input_code=i+1; break; } + } + + MultiValue my_tvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + AtomValuePack mytmp_atoms( my_tvals, this ); + for(unsigned i=0; i( mybasemulticolvars[i] ); - if( myfilt || mybasemulticolvars[i]->filtersUsedAsInput() ) inputAreFilters=true; + for(unsigned i=0; i( mybasemulticolvars[i] ); + if( myfilt || mybasemulticolvars[i]->filtersUsedAsInput() ) inputAreFilters=true; } return inputAreFilters; } -void MultiColvarBase::calculate(){ +void MultiColvarBase::calculate() { // Recursive function that sets up tasks setupActiveTaskSet( taskFlags, getLabel() ); @@ -750,38 +750,38 @@ void MultiColvarBase::calculate(){ if( mybasemulticolvars.size()>0 && filtersUsedAsInput() ) setupLinkCells(); // Setup the link cells if we are not using species - if( !usespecies && ablocks.size()>1 ){ - // This loop finds the first active atom, which is always checked because - // of a peculiarity in linkcells - unsigned first_active; - for(unsigned i=0;i1 ) { + // This loop finds the first active atom, which is always checked because + // of a peculiarity in linkcells + unsigned first_active; + for(unsigned i=0; i0 ) plumed_merror("cannot calculate numerical derivatives for this quantity"); calculateAtomicNumericalDerivatives( this, 0 ); } -void MultiColvarBase::prepare(){ +void MultiColvarBase::prepare() { setup_completed=false; atomsWereRetrieved=false; } -void MultiColvarBase::retrieveAtoms(){ - if( !atomsWereRetrieved ){ ActionAtomistic::retrieveAtoms(); atomsWereRetrieved=true; } +void MultiColvarBase::retrieveAtoms() { + if( !atomsWereRetrieved ) { ActionAtomistic::retrieveAtoms(); atomsWereRetrieved=true; } } void MultiColvarBase::mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, - const unsigned& jatom, const std::vector& der, - MultiValue& myder, AtomValuePack& myatoms ) const { + const unsigned& jatom, const std::vector& der, + MultiValue& myder, AtomValuePack& myatoms ) const { MultiValue& myvals=myatoms.getUnderlyingMultiValue(); plumed_dbg_assert( ivaltaskIsCurrentlyActive( atom_lab[katom].second ) ); // Get start of indices for this atom - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9; + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9; plumed_dbg_assert( basen%3==0 ); // Check the number of atoms is consistent with input derivatives unsigned virbas = myvals.getNumberOfDerivatives()-9; - for(unsigned j=0;jgetNumberOfDerivatives()-9 ){ - unsigned kder=basen+jder; - for(unsigned icomp=start;icompgetNumberOfDerivatives() + 9); - for(unsigned icomp=start;icompgetNumberOfDerivatives()-9 ) { + unsigned kder=basen+jder; + for(unsigned icomp=start; icompgetNumberOfDerivatives() + 9); + for(unsigned icomp=start; icomp& der, - MultiValue& myder, AtomValuePack& myatoms ) const { + const unsigned& jatom, const std::vector& der, + MultiValue& myder, AtomValuePack& myatoms ) const { MultiValue& myvals=myatoms.getUnderlyingMultiValue(); plumed_dbg_assert( ivaltaskIsCurrentlyActive( atom_lab[katom].second ) ); // Get start of indices for this atom - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9; + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9; plumed_dbg_assert( basen%3==0 ); // Check the number of atoms is consistent with input derivatives unsigned virbas = myvals.getNumberOfDerivatives()-9; - for(unsigned j=0;jgetNumberOfDerivatives()-9 ){ - unsigned kder=basen+jder; plumed_assert( kdergetNumberOfDerivatives() + 9); - for(unsigned icomp=start;icompgetNumberOfDerivatives()-9 ) { + unsigned kder=basen+jder; plumed_assert( kdergetNumberOfDerivatives() + 9); + for(unsigned icomp=start; icomp(myatoms.getUnderlyingMultiValue().getNumberOfValues()) && iatom0 ); // Find base colvar unsigned mmc = atom_lab[katom].first - 1; plumed_dbg_assert( mybasemulticolvars[mmc]->taskIsCurrentlyActive( atom_lab[katom].second ) ); - if( usespecies && iatom==0 ){ myatoms.addComDerivatives( ival, der, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); return; } + if( usespecies && iatom==0 ) { myatoms.addComDerivatives( ival, der, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); return; } // Get start of indices for this atom - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9) / 3; + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9) / 3; mybasemulticolvars[mmc]->getCentralAtomPack( basen, atom_lab[katom].second, mybasemulticolvars[mmc]->my_tmp_capacks[1] ); myatoms.addComDerivatives( ival, der, mybasemulticolvars[mmc]->my_tmp_capacks[1] ); } -void MultiColvarBase::getInputData( const unsigned& ind, const bool& normed, - const multicolvar::AtomValuePack& myatoms, +void MultiColvarBase::getInputData( const unsigned& ind, const bool& normed, + const multicolvar::AtomValuePack& myatoms, std::vector& orient ) const { // Converint input atom to local index - unsigned katom = myatoms.getIndex(ind); plumed_dbg_assert( atom_lab[katom].first>0 ); + unsigned katom = myatoms.getIndex(ind); plumed_dbg_assert( atom_lab[katom].first>0 ); // Find base colvar unsigned mmc = atom_lab[katom].first - 1; plumed_dbg_assert( mybasemulticolvars[mmc]->taskIsCurrentlyActive( atom_lab[katom].second ) ); // Check if orient is the correct size - if( orient.size()!=mybasemulticolvars[mmc]->getNumberOfQuantities() ) orient.resize( mybasemulticolvars[mmc]->getNumberOfQuantities() ); - // Retrieve the value + if( orient.size()!=mybasemulticolvars[mmc]->getNumberOfQuantities() ) orient.resize( mybasemulticolvars[mmc]->getNumberOfQuantities() ); + // Retrieve the value mybasedata[mmc]->retrieveValueWithIndex( atom_lab[katom].second, normed, orient ); } MultiValue& MultiColvarBase::getInputDerivatives( const unsigned& iatom, const bool& normed, const multicolvar::AtomValuePack& myatoms ) const { // Converint input atom to local index - unsigned katom = myatoms.getIndex(iatom); plumed_dbg_assert( atom_lab[katom].first>0 ); + unsigned katom = myatoms.getIndex(iatom); plumed_dbg_assert( atom_lab[katom].first>0 ); // Find base colvar unsigned mmc = atom_lab[katom].first - 1; plumed_dbg_assert( mybasemulticolvars[mmc]->taskIsCurrentlyActive( atom_lab[katom].second ) ); if( usespecies && !normed && iatom==0 ) return mybasedata[mmc]->getTemporyMultiValue(0); unsigned oval=0; if( iatom>0 ) oval=1; - MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(oval); + MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(oval); if( myder.getNumberOfValues()!=mybasemulticolvars[mmc]->getNumberOfQuantities() || - myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ){ - myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); - } + myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ) { + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); + } mybasedata[mmc]->retrieveDerivatives( atom_lab[katom].second, normed, myder ); return myder; } @@ -892,31 +892,31 @@ void MultiColvarBase::accumulateSymmetryFunction( const int& ival, const unsigne double weighti=1.0; if( atom_lab[jatom].first>0 ) weighti=mybasedata[atom_lab[jatom].first-1]->retrieveWeightWithIndex( atom_lab[jatom].second ); // Accumulate the value if( ival<0 ) myatoms.getUnderlyingMultiValue().addTemporyValue( weight0*weighti*val ); - else myatoms.addValue( ival, weight0*weighti*val ); + else myatoms.addValue( ival, weight0*weighti*val ); // Return if we don't need derivatives if( doNotCalculateDerivatives() ) return ; // And virial - if( ival<0 ) myatoms.addTemporyBoxDerivatives( weight0*weighti*vir ); + if( ival<0 ) myatoms.addTemporyBoxDerivatives( weight0*weighti*vir ); else myatoms.addBoxDerivatives( ival, weight0*weighti*vir ); // Add derivatives of central atom - if( atom_lab[katom].first>0 ){ - addComDerivatives( ival, 0, -weight0*weighti*der, myatoms ); - std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); - tmpder[0]=weighti*val; mergeInputDerivatives( ival, 0, 1, 0, tmpder, getInputDerivatives(0, false, myatoms), myatoms ); + if( atom_lab[katom].first>0 ) { + addComDerivatives( ival, 0, -weight0*weighti*der, myatoms ); + std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); + tmpder[0]=weighti*val; mergeInputDerivatives( ival, 0, 1, 0, tmpder, getInputDerivatives(0, false, myatoms), myatoms ); } else { - if( ival<0 ) myatoms.addTemporyAtomsDerivatives( 0, -der ); - else myatoms.addAtomsDerivatives( ival, 0, -der ); + if( ival<0 ) myatoms.addTemporyAtomsDerivatives( 0, -der ); + else myatoms.addAtomsDerivatives( ival, 0, -der ); } // Add derivatives of atom in coordination sphere - if( atom_lab[jatom].first>0 ){ - addComDerivatives( ival, iatom, weight0*weighti*der, myatoms ); - std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); - tmpder[0]=weight0*val; mergeInputDerivatives( ival, 0, 1, iatom, tmpder, getInputDerivatives(iatom, false, myatoms), myatoms ); + if( atom_lab[jatom].first>0 ) { + addComDerivatives( ival, iatom, weight0*weighti*der, myatoms ); + std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); + tmpder[0]=weight0*val; mergeInputDerivatives( ival, 0, 1, iatom, tmpder, getInputDerivatives(iatom, false, myatoms), myatoms ); } else { - if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); - else myatoms.addAtomsDerivatives( ival, iatom, der ); + if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); + else myatoms.addAtomsDerivatives( ival, iatom, der ); } } @@ -924,11 +924,11 @@ void MultiColvarBase::addAtomDerivatives( const int& ival, const unsigned& iatom if( doNotCalculateDerivatives() ) return ; unsigned jatom=myatoms.getIndex(iatom); - if( atom_lab[jatom].first>0 ){ - addComDerivatives( ival, iatom, der, myatoms ); + if( atom_lab[jatom].first>0 ) { + addComDerivatives( ival, iatom, der, myatoms ); } else { - if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); - else myatoms.addAtomsDerivatives( ival, iatom, der ); + if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); + else myatoms.addAtomsDerivatives( ival, iatom, der ); } } @@ -941,61 +941,61 @@ void MultiColvarBase::performTask( const unsigned& task_index, const unsigned& c // Retrieve the atom list if( !setupCurrentAtomList( current, myatoms ) ) return; // Get weight due to dynamic groups - double weight = 1.0; - if( !matsums ){ - for(unsigned i=0;i1 ) break; - unsigned mmc = atom_lab[myatoms.getIndex(i)].first - 1; - weight *= mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); - } - } else if( usespecies ){ - if( atom_lab[myatoms.getIndex(0)].first>0 ){ - if( mybasedata[atom_lab[myatoms.getIndex(0)].first-1]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(0)].second )1 ) break; + unsigned mmc = atom_lab[myatoms.getIndex(i)].first - 1; + weight *= mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); + } + } else if( usespecies ) { + if( atom_lab[myatoms.getIndex(0)].first>0 ) { + if( mybasedata[atom_lab[myatoms.getIndex(0)].first-1]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(0)].second )0 ){ - MultiValue& outder=myatoms.getUnderlyingMultiValue(); MultiValue myder(0,0); - for(unsigned i=0;igetNumberOfQuantities() || myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ){ - myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); - } - mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(i)].second, false, myder ); - - // Retrieve the prefactor (product of all other weights) - double prefactor = multweight*weight / mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); - // And accumulate the derivatives - for(unsigned j=0;j0 ) { + MultiValue& outder=myatoms.getUnderlyingMultiValue(); MultiValue myder(0,0); + for(unsigned i=0; igetNumberOfQuantities() || myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ) { + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); } + mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(i)].second, false, myder ); + + // Retrieve the prefactor (product of all other weights) + double prefactor = multweight*weight / mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); + // And accumulate the derivatives + for(unsigned j=0; j0 && atom_lab[myatoms.getIndex(0)].first>0 ){ - unsigned mmc = atom_lab[0].first - 1; - MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(0); - if( myder.getNumberOfValues()!=mybasemulticolvars[mmc]->getNumberOfQuantities() || - myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ){ - myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); - } - mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(0)].second, false, myder ); - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9; - mybasemulticolvars[mmc]->getCentralAtomPack( basen, atom_lab[myatoms.getIndex(0)].second, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); + if( !doNotCalculateDerivatives() ) { + if( usespecies && mybasemulticolvars.size()>0 && atom_lab[myatoms.getIndex(0)].first>0 ) { + unsigned mmc = atom_lab[0].first - 1; + MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(0); + if( myder.getNumberOfValues()!=mybasemulticolvars[mmc]->getNumberOfQuantities() || + myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ) { + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); } + mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(0)].second, false, myder ); + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9; + mybasemulticolvars[mmc]->getCentralAtomPack( basen, atom_lab[myatoms.getIndex(0)].second, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); + } } // Compute everything double vv=compute( task_index, myatoms ); updateActiveAtoms( myatoms ); @@ -1008,71 +1008,71 @@ void MultiColvarBase::updateActiveAtoms( AtomValuePack& myatoms ) const { else myatoms.updateDynamicList(); } -Vector MultiColvarBase::getCentralAtomPos( const unsigned& taskIndex ){ +Vector MultiColvarBase::getCentralAtomPos( const unsigned& taskIndex ) { unsigned curr=getTaskCode( taskIndex ); - if( usespecies || isDensity() ){ - return getPositionOfAtomForLinkCells(curr); - } else if( nblock>0 ){ - // double factor=1.0/static_cast( ablocks.size() ); - Vector mypos; mypos.zero(); - std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); - for(unsigned i=0;i0 ) { + // double factor=1.0/static_cast( ablocks.size() ); + Vector mypos; mypos.zero(); + std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); + for(unsigned i=0; i0 ){ - if( mypack.getNumberOfAtomsWithDerivatives()!=ncentral ) mypack.resize(ncentral); - unsigned k=0; - std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); - for(unsigned i=0;i0 ) { + if( mypack.getNumberOfAtomsWithDerivatives()!=ncentral ) mypack.resize(ncentral); + unsigned k=0; + std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); + for(unsigned i=0; i& dlist, unsigned int max_index) const { - if (usepbc) pbcApply(dlist, max_index); + if (usepbc) pbcApply(dlist, max_index); } -void MultiColvarBase::apply(){ +void MultiColvarBase::apply() { if( getForcesFromVessels( forcesToApply ) ) setForcesOnAtoms( forcesToApply ); } - + } } diff --git a/src/multicolvar/MultiColvarBase.h b/src/multicolvar/MultiColvarBase.h index 0cd946996b..96be83ee36 100644 --- a/src/multicolvar/MultiColvarBase.h +++ b/src/multicolvar/MultiColvarBase.h @@ -42,11 +42,11 @@ class MultiColvarBase : public ActionAtomistic, public ActionWithValue, public vesselbase::ActionWithVessel - { - friend class BridgedMultiColvarFunction; - friend class VolumeGradientBase; - friend class MultiColvarFilter; - friend class AtomValuePack; +{ + friend class BridgedMultiColvarFunction; + friend class VolumeGradientBase; + friend class MultiColvarFilter; + friend class AtomValuePack; private: /// Use periodic boundary conditions bool usepbc; @@ -105,9 +105,9 @@ class MultiColvarBase : /// Finish setting up the multicolvar base void setupMultiColvarBase( const std::vector& atoms ); /// Add some derivatives to a particular component of a particular atom - void addAtomDerivatives( const int& , const unsigned& , const Vector& , multicolvar::AtomValuePack& ) const ; + void addAtomDerivatives( const int&, const unsigned&, const Vector&, multicolvar::AtomValuePack& ) const ; /// Add derivative of the input value - void mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, const unsigned& jatom, + void mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, const unsigned& jatom, const std::vector& der, MultiValue& myder, AtomValuePack& myatoms ) const ; /// This routine take the ith set of input derivatives and adds it to each of the (end-start) output derivatives /// In other words one set of derivatives comes in and end-start sets of derivatives come out @@ -150,9 +150,9 @@ class MultiColvarBase : void buildSets(); public: explicit MultiColvarBase(const ActionOptions&); - ~MultiColvarBase(){} + ~MultiColvarBase() {} static void registerKeywords( Keywords& keys ); -/// Turn on the derivatives +/// Turn on the derivatives virtual void turnOnDerivatives(); /// Do we use pbc to calculate this quantity bool usesPbc() const ; @@ -169,7 +169,7 @@ class MultiColvarBase : /// Calculate numerical derivatives virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); /// Perform one of the tasks - virtual void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; + virtual void performTask( const unsigned&, const unsigned&, MultiValue& ) const ; /// Update the active atoms virtual void updateActiveAtoms( AtomValuePack& myatoms ) const ; /// This gets the position of an atom for the link cell setup @@ -197,12 +197,12 @@ class MultiColvarBase : /// This is true if multicolvar is calculating a vector or if the multicolvar is the density virtual bool hasDifferentiableOrientation() const { return false; } /// This makes sure we are not calculating the director when we do LocalAverage - virtual void doNotCalculateDirector(){} + virtual void doNotCalculateDirector() {} /// Ensure that derivatives are only calculated when needed bool doNotCalculateDerivatives() const ; -/// Get the icolv th base multicolvar +/// Get the icolv th base multicolvar MultiColvarBase* getBaseMultiColvar( const unsigned& icolv ) const ; -/// Get the number of base multicolvars +/// Get the number of base multicolvars unsigned getNumberOfBaseMultiColvars() const ; /// Get an input data virtual void getInputData( const unsigned& ind, const bool& normed, const multicolvar::AtomValuePack& myatoms, std::vector& orient ) const ; @@ -211,10 +211,10 @@ class MultiColvarBase : }; inline -bool MultiColvarBase::isCurrentlyActive( const unsigned& code ){ - if( setup_completed && atom_lab[code].first>0 ){ - unsigned mmc=atom_lab[code].first - 1; - return mybasedata[mmc]->storedValueIsActive( atom_lab[code].second ); +bool MultiColvarBase::isCurrentlyActive( const unsigned& code ) { + if( setup_completed && atom_lab[code].first>0 ) { + unsigned mmc=atom_lab[code].first - 1; + return mybasedata[mmc]->storedValueIsActive( atom_lab[code].second ); } return true; } @@ -222,26 +222,26 @@ bool MultiColvarBase::isCurrentlyActive( const unsigned& code ){ inline AtomNumber MultiColvarBase::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const { plumed_dbg_assert( iatom0 ){ - unsigned mmc=atom_lab[iatom].first - 1; - return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); + if( atom_lab[iatom].first>0 ) { + unsigned mmc=atom_lab[iatom].first - 1; + return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); } plumed_dbg_assert( usespecies ); return ActionAtomistic::getAbsoluteIndex( atom_lab[getTaskCode(iatom)].second ); -} +} inline Vector MultiColvarBase::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { plumed_dbg_assert( iatom0 ){ - unsigned mmc=atom_lab[iatom].first - 1; - return mybasemulticolvars[mmc]->getCentralAtomPos( atom_lab[iatom].second ); + if( atom_lab[iatom].first>0 ) { + unsigned mmc=atom_lab[iatom].first - 1; + return mybasemulticolvars[mmc]->getCentralAtomPos( atom_lab[iatom].second ); } return ActionAtomistic::getPosition( atom_lab[iatom].second ); } inline -unsigned MultiColvarBase::getNumberOfDerivatives(){ +unsigned MultiColvarBase::getNumberOfDerivatives() { return 3*getNumberOfAtoms()+9; } @@ -258,14 +258,14 @@ bool MultiColvarBase::doNotCalculateDerivatives() const { inline unsigned MultiColvarBase::getNumberOfBaseMultiColvars() const { - return mybasemulticolvars.size(); -} + return mybasemulticolvars.size(); +} -inline +inline MultiColvarBase* MultiColvarBase::getBaseMultiColvar( const unsigned& icolv ) const { plumed_dbg_assert( icolv -#include +#include //+PLUMEDOC MCOLVARF MCOLV_COMBINE /* @@ -47,46 +47,46 @@ class MultiColvarCombine : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(MultiColvarCombine,"MCOLV_COMBINE") -void MultiColvarCombine::registerKeywords( Keywords& keys ){ +void MultiColvarCombine::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","DATA","the multicolvars you are calculating linear combinations for"); keys.add("compulsory","COEFFICIENTS","1.0","the coeficients to use for the various multicolvars"); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); + keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); keys.use("MIN"); keys.use("MAX"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("ALT_MIN"); keys.use("BETWEEN"); keys.use("MOMENTS"); } MultiColvarCombine::MultiColvarCombine(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { buildSets(); - for(unsigned i=0;iweightWithDerivatives() ) error("cannot combine multicolvars with weights"); + for(unsigned i=0; iweightWithDerivatives() ) error("cannot combine multicolvars with weights"); } coeff.resize( getNumberOfBaseMultiColvars() ); parseVector("COEFFICIENTS",coeff); log.printf(" coefficients of multicolvars %f", coeff[0] ); - for(unsigned i=1;i tval(2); - for(unsigned i=0;i tval(2); + for(unsigned i=0; i cc(2); - for(unsigned i=0;i cc(2); + for(unsigned i=0; i atom; parseAtomList("ORIGIN",atom); @@ -151,82 +151,82 @@ ActionWithGrid(ao) parseFlag("FRACTIONAL",fractional); std::string direction; parse("DIR",direction); log.printf(" calculating for %s density profile along ", mycolv->getLabel().c_str() ); - if( direction=="x" ){ - log.printf("x axis"); - directions.resize(1); directions[0]=0; - } else if( direction=="y" ){ - log.printf("y axis"); - directions.resize(1); directions[0]=1; - } else if( direction=="z" ){ - log.printf("z axis"); - directions.resize(1); directions[0]=2; - } else if( direction=="xy" ){ - log.printf("x and y axes"); - directions.resize(2); directions[0]=0; directions[1]=1; - } else if( direction=="xz" ){ - log.printf("x and z axes"); - directions.resize(2); directions[0]=0; directions[1]=2; - } else if( direction=="yz" ){ - log.printf("y and z axis"); - directions.resize(2); directions[0]=1; directions[1]=2; - } else if( direction=="xyz" ){ - log.printf("x, y and z axes"); - directions.resize(3); directions[0]=0; directions[1]=1; directions[2]=2; + if( direction=="x" ) { + log.printf("x axis"); + directions.resize(1); directions[0]=0; + } else if( direction=="y" ) { + log.printf("y axis"); + directions.resize(1); directions[0]=1; + } else if( direction=="z" ) { + log.printf("z axis"); + directions.resize(1); directions[0]=2; + } else if( direction=="xy" ) { + log.printf("x and y axes"); + directions.resize(2); directions[0]=0; directions[1]=1; + } else if( direction=="xz" ) { + log.printf("x and z axes"); + directions.resize(2); directions[0]=0; directions[1]=2; + } else if( direction=="yz" ) { + log.printf("y and z axis"); + directions.resize(2); directions[0]=1; directions[1]=2; + } else if( direction=="xyz" ) { + log.printf("x, y and z axes"); + directions.resize(3); directions[0]=0; directions[1]=1; directions[2]=2; } else { - error( direction + " is not valid gradient direction"); - } + error( direction + " is not valid gradient direction"); + } log.printf(" for colvars calculated by action %s \n",mycolv->getLabel().c_str() ); parseVector("NBINS",nbins); parseVector("SPACING",gspacing); if( nbins.size()!=directions.size() && gspacing.size()!=directions.size() ) error("NBINS or SPACING must be set"); confined.resize( directions.size() ); cmin.resize( directions.size(), 0 ); cmax.resize( directions.size(), 0 ); - for(unsigned i=0;igetLabel() + ".dens"; vstring +=" COORDINATES="; if( directions[0]==0 ) vstring+="x"; else if( directions[0]==1 ) vstring+="y"; else if( directions[0]==2 ) vstring+="z"; - for(unsigned i=1;igetFullNumberOfTasks();++i) addTaskToList(i); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList(i); // And create the grid if( mycolv->isDensity() ) createGrid( "histogram", vstring ); else createGrid( "average", vstring ); @@ -234,12 +234,12 @@ ActionWithGrid(ao) setAveragingAction( mygrid, true ); // Enusre units for cube files are set correctly - if( !fractional ){ - if( plumed.getAtoms().usingNaturalUnits() ) mygrid->setCubeUnits( 1.0/0.5292 ); - else mygrid->setCubeUnits( plumed.getAtoms().getUnits().getLength()/.05929 ); + if( !fractional ) { + if( plumed.getAtoms().usingNaturalUnits() ) mygrid->setCubeUnits( 1.0/0.5292 ); + else mygrid->setCubeUnits( plumed.getAtoms().getUnits().getLength()/.05929 ); } - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); // Stupid dependencies cleared by requestAtoms - why GBussi why? That's got me so many times addDependency( mycolv ); } @@ -248,49 +248,49 @@ unsigned MultiColvarDensity::getNumberOfQuantities() const { return directions.size() + 2; } -void MultiColvarDensity::clearAverage(){ +void MultiColvarDensity::clearAverage() { std::vector min(directions.size()), max(directions.size()); std::vector gmin(directions.size()), gmax(directions.size());; - for(unsigned i=0;igetPbc().isOrthorombic() ){ - error("I think that density profiles with non-orthorhombic cells don't work. If you want it have a look and see if you can work it out"); - } - - for(unsigned i=0;igetBox()(directions[i],directions[i]); - max[i]*=mycolv->getBox()(directions[i],directions[i]); - } else { - min[i]=cmin[i]; max[i]=cmax[i]; - } - } + for(unsigned i=0; igetPbc().isOrthorombic() ) { + error("I think that density profiles with non-orthorhombic cells don't work. If you want it have a look and see if you can work it out"); + } + + for(unsigned i=0; igetBox()(directions[i],directions[i]); + max[i]*=mycolv->getBox()(directions[i],directions[i]); + } else { + min[i]=cmin[i]; max[i]=cmax[i]; + } + } } - for(unsigned i=0;isetBounds( gmin, gmax, nbins, gspacing ); resizeFunctions(); } -void MultiColvarDensity::prepareForAveraging(){ - for(unsigned i=0;igetBox()(directions[i],directions[i]), max ); - if( max!=mygrid->getMax()[i] ) error("box size should be fixed. Use FRACTIONAL"); +void MultiColvarDensity::prepareForAveraging() { + for(unsigned i=0; igetBox()(directions[i],directions[i]), max ); + if( max!=mygrid->getMax()[i] ) error("box size should be fixed. Use FRACTIONAL"); } // Ensure we only work with active multicolvars deactivateAllTasks(); - for(unsigned i=0;igetNumberOfStoredValues();++i) taskFlags[i]=1; + for(unsigned i=0; igetNumberOfStoredValues(); ++i) taskFlags[i]=1; lockContributors(); // Retrieve the origin - origin = getPosition(0); + origin = getPosition(0); } void MultiColvarDensity::compute( const unsigned& current, MultiValue& myvals ) const { std::vector cvals( mycolv->getNumberOfQuantities() ); stash->retrieveSequentialValue( current, false, cvals ); Vector fpos, apos = pbcDistance( origin, mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(current) ) ); - if( fractional ){ fpos = getPbc().realToScaled( apos ); } else { fpos=apos; } + if( fractional ) { fpos = getPbc().realToScaled( apos ); } else { fpos=apos; } - myvals.setValue( 0, cweight*cvals[0] ); for(unsigned j=0;jisDensity() ) error("filtering/transforming density makes no sense"); @@ -43,10 +43,10 @@ BridgedMultiColvarFunction(ao) filter=false; } - readVesselKeywords(); + readVesselKeywords(); } -void MultiColvarFilter::doJobsRequiredBeforeTaskList(){ +void MultiColvarFilter::doJobsRequiredBeforeTaskList() { ActionWithValue::clearDerivatives(); ActionWithVessel::doJobsRequiredBeforeTaskList(); } @@ -54,39 +54,39 @@ void MultiColvarFilter::doJobsRequiredBeforeTaskList(){ void MultiColvarFilter::completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const { invals.copyValues( outvals ); if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); - + // Retrive the value of the multicolvar and apply filter double val=invals.get(1), df, weight=applyFilter( val, df ); // Now propegate derivatives - if( filter && !getPntrToMultiColvar()->weightHasDerivatives ){ - outvals.setValue( 0, weight ); - if( derivativesAreRequired() ){ - for(unsigned i=0;iweightHasDerivatives ) { + outvals.setValue( 0, weight ); + if( derivativesAreRequired() ) { + for(unsigned i=0; i& bb ){ +void MultiColvarFilter::addBridgeForces( const std::vector& bb ) { plumed_dbg_assert( bb.size()==0 ); } diff --git a/src/multicolvar/MultiColvarFilter.h b/src/multicolvar/MultiColvarFilter.h index 8ad4f58f15..e6310bf109 100644 --- a/src/multicolvar/MultiColvarFilter.h +++ b/src/multicolvar/MultiColvarFilter.h @@ -30,7 +30,7 @@ namespace multicolvar { /** \ingroup INHERIT -This is the abstract base class to use for implementing a new way of filtering collective variable values +This is the abstract base class to use for implementing a new way of filtering collective variable values to see whether or not they are within a certain range */ diff --git a/src/multicolvar/MultiColvarProduct.cpp b/src/multicolvar/MultiColvarProduct.cpp index 627cacc530..c7dd7d2c34 100644 --- a/src/multicolvar/MultiColvarProduct.cpp +++ b/src/multicolvar/MultiColvarProduct.cpp @@ -24,7 +24,7 @@ #include "core/ActionRegister.h" #include -#include +#include //+PLUMEDOC MCOLVARF MCOLV_PRODUCT /* @@ -46,41 +46,41 @@ class MultiColvarProduct : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(MultiColvarProduct,"MCOLV_PRODUCT") -void MultiColvarProduct::registerKeywords( Keywords& keys ){ +void MultiColvarProduct::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","DATA","the multicolvars you are calculating the product of"); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); + keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); keys.use("MIN"); keys.use("MAX"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("ALT_MIN"); keys.use("BETWEEN"); keys.use("MOMENTS"); } MultiColvarProduct::MultiColvarProduct(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { buildSets(); - for(unsigned i=0;iweightWithDerivatives() ) error("cannot take product of multicolvars with weights"); + for(unsigned i=0; iweightWithDerivatives() ) error("cannot take product of multicolvars with weights"); } } double MultiColvarProduct::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - double dot=1; std::vector tval(2); - for(unsigned i=0;i tval(2); + for(unsigned i=0; i cc(2); - for(unsigned i=0;i cc(2); + for(unsigned i=0; i -#include +#include -//+PLUMEDOC MCOLVARF NLINKS +//+PLUMEDOC MCOLVARF NLINKS /* Calculate number of pairs of atoms/molecules that are "linked" In its simplest guise this coordinate calculates a coordination number. Each pair -of atoms is assumed "linked" if they are within some cutoff of each other. In more +of atoms is assumed "linked" if they are within some cutoff of each other. In more complex applications each entity is a vector and this quantity measures whether -pairs of vectors are (a) within a certain cutoff and (b) if the two vectors have +pairs of vectors are (a) within a certain cutoff and (b) if the two vectors have similar orientations. The vectors on individual atoms could be Steinhardt parameters (see \ref Q3, \ref Q4 and \ref Q6) or they could describe some internal vector in a molecule. @@ -50,7 +50,7 @@ PRINT ARG=dd FILE=colvar \endverbatim The following calculates how many pairs of neighbouring atoms in a system containg 64 atoms have -similar dispositions for the atoms in their coordination sphere. This calculation uses the +similar dispositions for the atoms in their coordination sphere. This calculation uses the dot product of the Q6 vectors on adjacent atoms to measure whether or not two atoms have the same ``orientation" @@ -58,7 +58,7 @@ dot product of the Q6 vectors on adjacent atoms to measure whether or not two at Q6 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q6 NLINKS ARG=q6 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=dd PRINT ARG=dd FILE=colvar -\endverbatim +\endverbatim */ //+ENDPLUMEDOC @@ -69,7 +69,7 @@ namespace multicolvar { class NumberOfLinks : public MultiColvarBase { private: /// The values of the quantities in the dot products - std::vector orient0, orient1; + std::vector orient0, orient1; /// The switching function that tells us if atoms are close enough together SwitchingFunction switchingFunction; public: @@ -80,12 +80,12 @@ class NumberOfLinks : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(NumberOfLinks,"NLINKS") -void NumberOfLinks::registerKeywords( Keywords& keys ){ +void NumberOfLinks::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("atoms","GROUP",""); keys.add("atoms-1","GROUPA",""); @@ -95,36 +95,36 @@ void NumberOfLinks::registerKeywords( Keywords& keys ){ keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords - keys.remove("LOWMEM"); + keys.remove("LOWMEM"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); } NumberOfLinks::NumberOfLinks(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // The weight of this does have derivatives weightHasDerivatives=true; // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" calculating number of links with atoms separation of %s\n",( switchingFunction.description() ).c_str() ); - std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); - setupMultiColvarBase( all_atoms ); setLinkCellCutoff( switchingFunction.get_dmax() ); + std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); + setupMultiColvarBase( all_atoms ); setLinkCellCutoff( switchingFunction.get_dmax() ); - for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); } @@ -139,36 +139,36 @@ double NumberOfLinks::calculateWeight( const unsigned& taskCode, const double& w Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc ); - if( !doNotCalculateDerivatives() ){ - addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); - addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); - myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); + if( !doNotCalculateDerivatives() ) { + addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); + addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); + myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); } return sw; } double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; + if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; - unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities(); + unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities(); - std::vector orient0( ncomp ), orient1( ncomp ); - getInputData( 0, true, myatoms, orient0 ); - getInputData( 1, true, myatoms, orient1 ); + std::vector orient0( ncomp ), orient1( ncomp ); + getInputData( 0, true, myatoms, orient0 ); + getInputData( 1, true, myatoms, orient1 ); - double dot=0; - for(unsigned k=2;k all_atoms; + int natoms=4; std::vector all_atoms; readAtomsLikeKeyword( "ATOMS", natoms, all_atoms ); setupMultiColvarBase( all_atoms ); - std::vector catom_ind(4, false); + std::vector catom_ind(4, false); catom_ind[1]=catom_ind[2]=true; setAtomsForCentralAtom( catom_ind ); // Read in the vessels - readVesselKeywords(); + readVesselKeywords(); // And check everything has been read in correctly checkRead(); } diff --git a/src/multicolvar/VolumeAround.cpp b/src/multicolvar/VolumeAround.cpp index 69bbfd62c4..bab79d8e0a 100644 --- a/src/multicolvar/VolumeAround.cpp +++ b/src/multicolvar/VolumeAround.cpp @@ -25,31 +25,31 @@ //+PLUMEDOC VOLUMES AROUND /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a particular, user-specified part of of the cell. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(x_i,y_i,z_i) }{ \sum_i w(x_i,y_i,z_i) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(x_i,y_i,z_i) }{ \sum_i w(x_i,y_i,z_i) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (x_i,y_i,z_i)\f$. The function \f$ w(x_i,y_i,z_i) \f$ measures whether or not the system is in the subregion of interest. It is equal to: \f[ -w(x_i,y_i,z_i) = \int_{xl}^{xu} \int_{yl}^{yu} \int_{zl}^{zu} \textrm{d}x\textrm{d}y\textrm{d}z K\left( \frac{x - x_i}{\sigma} \right)K\left( \frac{y - y_i}{\sigma} \right)K\left( \frac{z - z_i}{\sigma} \right) +w(x_i,y_i,z_i) = \int_{xl}^{xu} \int_{yl}^{yu} \int_{zl}^{zu} \textrm{d}x\textrm{d}y\textrm{d}z K\left( \frac{x - x_i}{\sigma} \right)K\left( \frac{y - y_i}{\sigma} \right)K\left( \frac{z - z_i}{\sigma} \right) \f] where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -When AROUND is used with the \ref DENSITY action the number of atoms in the specified region is calculated +When AROUND is used with the \ref DENSITY action the number of atoms in the specified region is calculated \par Examples @@ -79,11 +79,11 @@ class VolumeAround : public ActionVolume { explicit VolumeAround(const ActionOptions& ao); void setupRegions(); double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const ; -}; +}; PLUMED_REGISTER_ACTION(VolumeAround,"AROUND") -void VolumeAround::registerKeywords( Keywords& keys ){ +void VolumeAround::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOM","the atom whose vicinity we are interested in examining"); keys.add("compulsory","XLOWER","0.0","the lower boundary in x relative to the x coordinate of the atom (0 indicates use full extent of box)."); @@ -95,10 +95,10 @@ void VolumeAround::registerKeywords( Keywords& keys ){ } VolumeAround::VolumeAround(const ActionOptions& ao): -Action(ao), -ActionVolume(ao) + Action(ao), + ActionVolume(ao) { - std::vector atom; + std::vector atom; parseAtomList("ATOM",atom); if( atom.size()!=1 ) error("should only be one atom specified"); log.printf(" boundaries for region are calculated based on positions of atom : %d\n",atom[0].serial() ); @@ -108,13 +108,13 @@ ActionVolume(ao) doz=true; parse("ZLOWER",zlow); parse("ZUPPER",zhigh); if( xlow==0.0 && xhigh==0.0 ) dox=false; if( ylow==0.0 && yhigh==0.0 ) doy=false; - if( zlow==0.0 && zhigh==0.0 ) doz=false; + if( zlow==0.0 && zhigh==0.0 ) doz=false; if( !dox && !doy && !doz ) error("no subregion defined use XLOWER, XUPPER, YLOWER, YUPPER, ZLOWER, ZUPPER"); log.printf(" boundaries for region (region of interest about atom) : x %f %f, y %f %f, z %f %f \n",xlow,xhigh,ylow,yhigh,zlow,zhigh); - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); } -void VolumeAround::setupRegions(){ } +void VolumeAround::setupRegions() { } double VolumeAround::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const { // Setup the histogram bead @@ -122,27 +122,27 @@ double VolumeAround::calculateNumberInside( const Vector& cpos, Vector& derivati // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); - double xcontr, ycontr, zcontr, xder, yder, zder; - if( dox ){ - bead.set( xlow, xhigh, getSigma() ); - xcontr=bead.calculate( fpos[0], xder ); + double xcontr, ycontr, zcontr, xder, yder, zder; + if( dox ) { + bead.set( xlow, xhigh, getSigma() ); + xcontr=bead.calculate( fpos[0], xder ); } else { - xcontr=1.; xder=0.; + xcontr=1.; xder=0.; } - if( doy ){ - bead.set( ylow, yhigh, getSigma() ); - ycontr=bead.calculate( fpos[1], yder ); + if( doy ) { + bead.set( ylow, yhigh, getSigma() ); + ycontr=bead.calculate( fpos[1], yder ); } else { - ycontr=1.; yder=0.; + ycontr=1.; yder=0.; } - if( doz ){ - bead.set( zlow, zhigh, getSigma() ); - zcontr=bead.calculate( fpos[2], zder ); + if( doz ) { + bead.set( zlow, zhigh, getSigma() ); + zcontr=bead.calculate( fpos[2], zder ); } else { - zcontr=1.; zder=0.; + zcontr=1.; zder=0.; } - derivatives[0]=xder*ycontr*zcontr; - derivatives[1]=xcontr*yder*zcontr; + derivatives[0]=xder*ycontr*zcontr; + derivatives[1]=xcontr*yder*zcontr; derivatives[2]=xcontr*ycontr*zder; // Add derivatives wrt to position of origin atom refders[0] = -derivatives; diff --git a/src/multicolvar/VolumeCavity.cpp b/src/multicolvar/VolumeCavity.cpp index 65c232a90f..af14a2be05 100644 --- a/src/multicolvar/VolumeCavity.cpp +++ b/src/multicolvar/VolumeCavity.cpp @@ -28,22 +28,22 @@ //+PLUMEDOC VOLUMES CAVITY /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a box defined by the positions of four atoms. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (u_i,v_i,z_i)\f$. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ +Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation matrix as follows: \f[ @@ -63,23 +63,23 @@ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation m \right) \f] -where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the -refererence positions specified by the user. The first of these unit vectors points from the first reference atom to the second. -The second is then the normal to the plane containing atoms 1,2 and 3 and the the third is the unit vector orthogonal to -these first two vectors. \f$(x_o,y_o,z_o)\f$, meanwhile, specifies the position of the first reference atom. +where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the +refererence positions specified by the user. The first of these unit vectors points from the first reference atom to the second. +The second is then the normal to the plane containing atoms 1,2 and 3 and the the third is the unit vector orthogonal to +these first two vectors. \f$(x_o,y_o,z_o)\f$, meanwhile, specifies the position of the first reference atom. In the previous function \f$ w(u_i,v_i,w_i) \f$ measures whether or not the system is in the subregion of interest. It is equal to: \f[ -w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w - K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) +w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w + K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) \f] where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. -The vector connecting atom 1 to atom 4 is used to define the extent of the box in each of the \f$u\f$, \f$v\f$ and \f$w\f$ +The vector connecting atom 1 to atom 4 is used to define the extent of the box in each of the \f$u\f$, \f$v\f$ and \f$w\f$ directions. Essentially the vector connecting atom 1 to atom 4 is projected onto the three unit vectors -described above and the resulting projections determine the \f$u'\f$, \f$v'\f$ and \f$w'\f$ parameters in the above expression. +described above and the resulting projections determine the \f$u'\f$, \f$v'\f$ and \f$w'\f$ parameters in the above expression. \par Examples @@ -87,11 +87,11 @@ The following commands tell plumed to calculate the number of atoms in an ion ch The extent of the chanel is calculated from the positions of atoms 1, 4, 5 and 11. The final value will be labeled cav. \verbatim -d1: DENSITY SPECIES=20-500 +d1: DENSITY SPECIES=20-500 CAVITY DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 LABEL=cav \endverbatim -The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water +The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water molecules in the protein channel described above. The average coordination number and the number of coordination numbers more than 4 is then calculated. The values of these two quantities are given the labels cav.mean and cav.morethan @@ -127,7 +127,7 @@ class VolumeCavity : public ActionVolume { PLUMED_REGISTER_ACTION(VolumeCavity,"CAVITY") -void VolumeCavity::registerKeywords( Keywords& keys ){ +void VolumeCavity::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOMS","the positions of four atoms that define spatial extent of the cavity"); keys.addFlag("PRINT_BOX",false,"write out the positions of the corners of the box to an xyz file"); @@ -136,54 +136,54 @@ void VolumeCavity::registerKeywords( Keywords& keys ){ } VolumeCavity::VolumeCavity(const ActionOptions& ao): -Action(ao), -ActionVolume(ao), -boxout(false), -lenunit(1.0), -dlbi(4), -dlcross(4), -dlperp(4), -dbi(3), -dcross(3), -dperp(3) + Action(ao), + ActionVolume(ao), + boxout(false), + lenunit(1.0), + dlbi(4), + dlcross(4), + dlperp(4), + dbi(3), + dcross(3), + dperp(3) { std::vector atoms; parseAtomList("ATOMS",atoms); if( atoms.size()!=4 ) error("number of atoms should be equal to four"); log.printf(" boundaries for region are calculated based on positions of atoms : "); - for(unsigned i=0;i0 ){ - Units u; u.setLength(unitname); - lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); - } else { - unitname="nm"; - } - boxfile.link(*this); - boxfile.open( boxfname.c_str() ); - log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); - } + if(boxout) { + std::string boxfname; parse("FILE",boxfname); + if(boxfname.length()==0) error("no name for box file specified"); + std::string unitname; parse("UNITS",unitname); + if ( unitname.length()>0 ) { + Units u; u.setLength(unitname); + lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); + } else { + unitname="nm"; + } + boxfile.link(*this); + boxfile.open( boxfname.c_str() ); + log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); + } checkRead(); requestAtoms(atoms); // We have to readd the dependency because requestAtoms removes it - addDependency( getPntrToMultiColvar() ); + addDependency( getPntrToMultiColvar() ); } -VolumeCavity::~VolumeCavity(){ +VolumeCavity::~VolumeCavity() { } -void VolumeCavity::setupRegions(){ +void VolumeCavity::setupRegions() { // Make some space for things Vector d1, d2, d3; - + // Retrieve the sigma value sigma=getSigma(); // Set the position of the origin @@ -194,21 +194,21 @@ void VolumeCavity::setupRegions(){ double d1l=d1.modulo(); d2 = pbcDistance(origin,getPosition(2)); - // Find the vector connecting the origin to the top corner of + // Find the vector connecting the origin to the top corner of // the subregion d3 = pbcDistance(origin,getPosition(3)); // Create a set of unit vectors bi = d1 / d1l; len_bi=dotProduct( d3, bi ); - cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); + cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); cross = cross / crossmod; len_cross=dotProduct( d3, cross ); perp = crossProduct( cross, bi ); len_perp=dotProduct( d3, perp ); // Calculate derivatives of box shape with respect to atoms - double d1l3=d1l*d1l*d1l; + double d1l3=d1l*d1l*d1l; dbi[0](0,0) = ( -(d1[1]*d1[1]+d1[2]*d1[2])/d1l3 ); // dx/dx dbi[0](0,1) = ( d1[0]*d1[1]/d1l3 ); // dx/dy - dbi[0](0,2) = ( d1[0]*d1[2]/d1l3 ); // dx/dz + dbi[0](0,2) = ( d1[0]*d1[2]/d1l3 ); // dx/dz dbi[0](1,0) = ( d1[1]*d1[0]/d1l3 ); // dy/dx dbi[0](1,1) = ( -(d1[0]*d1[0]+d1[2]*d1[2])/d1l3 ); // dy/dy dbi[0](1,2) = ( d1[1]*d1[2]/d1l3 ); @@ -233,7 +233,7 @@ void VolumeCavity::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,-1.0) ) + crossProduct( Vector(0.0,0.0,-1.0), d2 ) ); dcross[0](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[0](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[0](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[0](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[0](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -246,7 +246,7 @@ void VolumeCavity::setupRegions(){ tcderiv.setCol( 2, crossProduct( Vector(0.0,0.0,1.0), d2 ) ); dcross[1](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[1](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[1](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[1](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[1](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -259,7 +259,7 @@ void VolumeCavity::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,1.0) ) ); dcross[2](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[2](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[2](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[2](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[2](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -280,33 +280,33 @@ void VolumeCavity::setupRegions(){ dperp[2].setCol( 2, ( crossProduct( dcross[2].getCol(2), bi ) ) ); // Ensure that all lengths are positive - if( len_bi<0 ){ - bi=-bi; len_bi=-len_bi; - for(unsigned i=0;i<3;++i) dbi[i]*=-1.0; + if( len_bi<0 ) { + bi=-bi; len_bi=-len_bi; + for(unsigned i=0; i<3; ++i) dbi[i]*=-1.0; } - if( len_cross<0 ){ - cross=-cross; len_cross=-len_cross; - for(unsigned i=0;i<3;++i) dcross[i]*=-1.0; + if( len_cross<0 ) { + cross=-cross; len_cross=-len_cross; + for(unsigned i=0; i<3; ++i) dcross[i]*=-1.0; + } + if( len_perp<0 ) { + perp=-perp; len_perp=-len_perp; + for(unsigned i=0; i<3; ++i) dperp[i]*=-1.0; } - if( len_perp<0 ){ - perp=-perp; len_perp=-len_perp; - for(unsigned i=0;i<3;++i) dperp[i]*=-1.0; - } if( len_bi<=0 || len_cross<=0 || len_bi<=0 ) plumed_merror("Invalid box coordinates"); // Now derivatives of lengths - Tensor dd3( Tensor::identity() ); - dlbi[0] = matmul(d3,dbi[0]) - matmul(bi,dd3); + Tensor dd3( Tensor::identity() ); + dlbi[0] = matmul(d3,dbi[0]) - matmul(bi,dd3); dlbi[1] = matmul(d3,dbi[1]); dlbi[2] = matmul(d3,dbi[2]); dlbi[3] = matmul(bi,dd3); - dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); + dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); dlcross[1] = matmul(d3,dcross[1]); dlcross[2] = matmul(d3,dcross[2]); dlcross[3] = matmul(cross,dd3); - dlperp[0] = matmul(d3,dperp[0]) - matmul(perp,dd3); + dlperp[0] = matmul(d3,dperp[0]) - matmul(perp,dd3); dlperp[1] = matmul(d3,dperp[1]); dlperp[2] = matmul(d3,dperp[2]); dlperp[3] = matmul(perp,dd3); @@ -319,39 +319,39 @@ void VolumeCavity::setupRegions(){ jacob_det = fabs( jacob.determinant() ); } -void VolumeCavity::update(){ - if(boxout){ - boxfile.printf("%d\n",8); - const Tensor & t(getPbc().getBox()); - if(getPbc().isOrthorombic()){ - boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ - boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); - } - boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); - Vector ut, vt, wt; - ut = origin + len_bi*bi; - vt = origin + len_cross*cross; - wt = origin + len_perp*perp; - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]) , lenunit*(ut[1]), lenunit*(ut[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]) , lenunit*(vt[1]), lenunit*(vt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]) , lenunit*(wt[1]), lenunit*(wt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_bi*bi[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), - lenunit*(ut[1]+len_perp*perp[1]), - lenunit*(ut[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), - lenunit*(vt[1]+len_perp*perp[1]), - lenunit*(vt[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); +void VolumeCavity::update() { + if(boxout) { + boxfile.printf("%d\n",8); + const Tensor & t(getPbc().getBox()); + if(getPbc().isOrthorombic()) { + boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); + } else { + boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); + } + boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); + Vector ut, vt, wt; + ut = origin + len_bi*bi; + vt = origin + len_cross*cross; + wt = origin + len_perp*perp; + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]), lenunit*(ut[1]), lenunit*(ut[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]), lenunit*(vt[1]), lenunit*(vt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]), lenunit*(wt[1]), lenunit*(wt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_bi*bi[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), + lenunit*(ut[1]+len_perp*perp[1]), + lenunit*(ut[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), + lenunit*(vt[1]+len_perp*perp[1]), + lenunit*(vt[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); } } @@ -367,8 +367,8 @@ double VolumeCavity::calculateNumberInside( const Vector& cpos, Vector& derivati bead.set( 0, len_bi, sigma ); double upos=dotProduct( datom, bi ); ucontr=bead.calculate( upos, uder ); - double udlen=bead.uboundDerivative( upos ); - double uder2 = bead.lboundDerivative( upos ) - udlen; + double udlen=bead.uboundDerivative( upos ); + double uder2 = bead.lboundDerivative( upos ) - udlen; // Calculate contribution from integral along cross bead.set( 0, len_cross, sigma ); @@ -388,24 +388,24 @@ double VolumeCavity::calculateNumberInside( const Vector& cpos, Vector& derivati derivatives[0] = (dfd[0]*bi[0]+dfd[1]*cross[0]+dfd[2]*perp[0]); derivatives[1] = (dfd[0]*bi[1]+dfd[1]*cross[1]+dfd[2]*perp[1]); derivatives[2] = (dfd[0]*bi[2]+dfd[1]*cross[2]+dfd[2]*perp[2]); - double tot = ucontr*vcontr*wcontr*jacob_det; + double tot = ucontr*vcontr*wcontr*jacob_det; // Add reference atom derivatives 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]) + - dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; - rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + + dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; + rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + dfld[0]*dlbi[1] + dfld[1]*dlcross[1] + dfld[2]*dlperp[1]; - rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + + rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + 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]; vir.zero(); vir-=Tensor( cpos,derivatives ); - for(unsigned i=0;i<4;++i){ - vir -= Tensor( getPosition(i), rderiv[i] ); + for(unsigned i=0; i<4; ++i) { + vir -= Tensor( getPosition(i), rderiv[i] ); } - + return tot; } diff --git a/src/multicolvar/VolumeGradientBase.cpp b/src/multicolvar/VolumeGradientBase.cpp index ffbda80d6f..db1b48f6ab 100644 --- a/src/multicolvar/VolumeGradientBase.cpp +++ b/src/multicolvar/VolumeGradientBase.cpp @@ -27,121 +27,121 @@ namespace PLMD { namespace multicolvar { -void VolumeGradientBase::registerKeywords( Keywords& keys ){ +void VolumeGradientBase::registerKeywords( Keywords& keys ) { BridgedMultiColvarFunction::registerKeywords( keys ); } VolumeGradientBase::VolumeGradientBase(const ActionOptions&ao): -Action(ao), -BridgedMultiColvarFunction(ao) + Action(ao), + BridgedMultiColvarFunction(ao) { } -void VolumeGradientBase::requestAtoms( const std::vector& atoms ){ +void VolumeGradientBase::requestAtoms( const std::vector& atoms ) { ActionAtomistic::requestAtoms(atoms); bridgeVariable=3*atoms.size(); - std::map checklabs; - for(const auto & p : getDependencies() ) checklabs.insert(std::pair(p->getLabel(),false)); - for(const auto & p : plumed.getActionSet() ){ - if( p->getLabel()==getPntrToMultiColvar()->getLabel() ) break; - if( checklabs.count(p->getLabel()) ) checklabs[p->getLabel()]=true; + std::map checklabs; + for(const auto & p : getDependencies() ) checklabs.insert(std::pair(p->getLabel(),false)); + for(const auto & p : plumed.getActionSet() ) { + if( p->getLabel()==getPntrToMultiColvar()->getLabel() ) break; + if( checklabs.count(p->getLabel()) ) checklabs[p->getLabel()]=true; } - for(const auto & p : checklabs ){ - if( !p.second ) error("the input for the virtual atoms used in the input for this action must appear in the input file before the input multicolvar"); + for(const auto & p : checklabs ) { + if( !p.second ) error("the input for the virtual atoms used in the input for this action must appear in the input file before the input multicolvar"); } - addDependency( getPntrToMultiColvar() ); + addDependency( getPntrToMultiColvar() ); tmpforces.resize( 3*atoms.size()+9 ); } -void VolumeGradientBase::doJobsRequiredBeforeTaskList(){ +void VolumeGradientBase::doJobsRequiredBeforeTaskList() { ActionWithValue::clearDerivatives(); retrieveAtoms(); setupRegions(); ActionWithVessel::doJobsRequiredBeforeTaskList(); } void VolumeGradientBase::completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const { - if( getPntrToMultiColvar()->isDensity() ){ - outvals.setValue(0, 1.0); outvals.setValue(1, 1.0); + if( getPntrToMultiColvar()->isDensity() ) { + outvals.setValue(0, 1.0); outvals.setValue(1, 1.0); } else { - // Copy derivatives of the colvar and the value of the colvar - invals.copyValues( outvals ); - if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); + // Copy derivatives of the colvar and the value of the colvar + invals.copyValues( outvals ); + if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); } - calculateAllVolumes( curr, outvals ); + calculateAllVolumes( curr, outvals ); } -void VolumeGradientBase::setNumberInVolume( const unsigned& ivol, const unsigned& curr, const double& weight, - const Vector& wdf, const Tensor& virial, const std::vector& refders, - MultiValue& outvals ) const { - MultiColvarBase* mcolv=getPntrToMultiColvar(); - if( !mcolv->weightHasDerivatives ){ - outvals.setValue(ivol, weight ); - if( derivativesAreRequired() ){ - CatomPack catom; mcolv->getCentralAtomPack( 0, curr, catom ); - for(unsigned i=0;igetNumberOfDerivatives(); - 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, + MultiValue& outvals ) const { + MultiColvarBase* mcolv=getPntrToMultiColvar(); + if( !mcolv->weightHasDerivatives ) { + outvals.setValue(ivol, weight ); + if( derivativesAreRequired() ) { + CatomPack catom; mcolv->getCentralAtomPack( 0, curr, catom ); + for(unsigned i=0; igetCentralAtomPack( 0, curr, catom ); - for(unsigned i=0;igetNumberOfDerivatives(); - 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;igetNumberOfDerivatives(); + 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; igetCentralAtomPack( 0, curr, catom ); + for(unsigned i=0; igetNumberOfDerivatives(); + 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; igetCentralAtomPack( 0, curr, catom ); - for(unsigned i=0;igetNumberOfDerivatives(); - 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;igetCentralAtomPack( 0, curr, catom ); + for(unsigned i=0; igetNumberOfDerivatives(); + 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& bb ){ +void VolumeGradientBase::addBridgeForces( const std::vector& bb ) { plumed_dbg_assert( bb.size()==tmpforces.size()-9 ); // Forces on local atoms - for(unsigned i=0;i tmpforces; @@ -41,10 +41,10 @@ friend class MultiColvarBase; Vector pbcDistance( const Vector& v1, const Vector& v2) const; /// Get position of atom Vector getPosition( int iatom ) const ; -/// Request the atoms +/// Request the atoms void requestAtoms( const std::vector& atoms ); /// Set the number in the volume - void setNumberInVolume( const unsigned& , const unsigned& , const double& , const Vector& , const Tensor& , const std::vector& , MultiValue& ) const ; + void setNumberInVolume( const unsigned&, const unsigned&, const double&, const Vector&, const Tensor&, const std::vector&, MultiValue& ) const ; public: static void registerKeywords( Keywords& keys ); explicit VolumeGradientBase(const ActionOptions&); @@ -54,40 +54,40 @@ friend class MultiColvarBase; void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const ; /// Calculate what is in the volumes virtual void calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const=0; -/// Setup the regions that this is based on +/// Setup the regions that this is based on virtual void setupRegions()=0; /// Forces here are applied through the bridge void addBridgeForces( const std::vector& bb ); }; inline -const Tensor & VolumeGradientBase::getBox()const{ +const Tensor & VolumeGradientBase::getBox()const { return getPntrToMultiColvar()->getBox(); -} +} inline const Pbc & VolumeGradientBase::getPbc() const { - return getPntrToMultiColvar()->getPbc(); + return getPntrToMultiColvar()->getPbc(); } inline Vector VolumeGradientBase::pbcDistance( const Vector& v1, const Vector& v2) const { - return getPntrToMultiColvar()->pbcDistance(v1,v2); + return getPntrToMultiColvar()->pbcDistance(v1,v2); } inline Vector VolumeGradientBase::getPosition( int iatom ) const { - if( !checkNumericalDerivatives() ) return ActionAtomistic::getPosition(iatom); - // This is for numerical derivatives of quantity wrt to the local atoms - Vector tmp_p = ActionAtomistic::getPosition(iatom); - if( bridgeVariable<3*getNumberOfAtoms() ){ + if( !checkNumericalDerivatives() ) return ActionAtomistic::getPosition(iatom); +// This is for numerical derivatives of quantity wrt to the local atoms + Vector tmp_p = ActionAtomistic::getPosition(iatom); + if( bridgeVariable<3*getNumberOfAtoms() ) { if( bridgeVariable>=3*iatom && bridgeVariable<(iatom+1)*3 ) tmp_p[bridgeVariable%3]+=sqrt(epsilon); - } - // This makes sure that numerical derivatives of virial are calculated correctly - tmp_p = ActionAtomistic::getPbc().realToScaled( tmp_p ); - tmp_p = getPbc().scaledToReal( tmp_p ); - return tmp_p; -} + } +// This makes sure that numerical derivatives of virial are calculated correctly + tmp_p = ActionAtomistic::getPbc().realToScaled( tmp_p ); + tmp_p = getPbc().scaledToReal( tmp_p ); + return tmp_p; +} } } diff --git a/src/multicolvar/VolumeInCylinder.cpp b/src/multicolvar/VolumeInCylinder.cpp index 3008bd156d..eb6bc611e4 100644 --- a/src/multicolvar/VolumeInCylinder.cpp +++ b/src/multicolvar/VolumeInCylinder.cpp @@ -26,33 +26,33 @@ //+PLUMEDOC VOLUMES INCYLINDER /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a particular, user-specified part of of the cell. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r_{xy}) }{ \sum_i \sigma(r_{xy}) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r_{xy}) }{ \sum_i \sigma(r_{xy}) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (x_i,y_i,z_i)\f$. -The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the -collective is located \f$(x_i,y_i,z_i)\f$ and the position of the atom that was specified using the ORIGIN keyword +The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the +collective is located \f$(x_i,y_i,z_i)\f$ and the position of the atom that was specified using the ORIGIN keyword projected in the xy plane if DIRECTION=z is used. In other words: \f[ r_{xy} = sqrt{ ( x_i - x_0)^2 + ( y_i - y_0)^2 } \f] -In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a cylinder that +In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a cylinder that runs along the axis specified using the DIRECTION keyword and that is centered on the position of the atom specified using ORIGIN. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated +When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated \par Examples @@ -60,7 +60,7 @@ The input below can be use to calculate the average coordination numbers for tho of radius 1.5 nm that is centered on the position of atom 101 and that has its long axis parallel to the z-axis. \verbatim -c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} +c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} d2: INCYLINDER ATOM=101 DATA=d1 DIRECTION=Z RADIUS={TANH R_0=1.5} SIGMA=0.1 LOWER=-0.1 UPPER=0.1 MEAN PRINT ARG=d2.* FILE=colvar \endverbatim @@ -76,18 +76,18 @@ class VolumeInCylinder : public ActionVolume { bool docylinder; Vector origin; HistogramBead bead; - std::vector dir; + std::vector dir; SwitchingFunction switchingFunction; public: static void registerKeywords( Keywords& keys ); explicit VolumeInCylinder (const ActionOptions& ao); void setupRegions(); double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const ; -}; +}; PLUMED_REGISTER_ACTION(VolumeInCylinder,"INCYLINDER") -void VolumeInCylinder::registerKeywords( Keywords& keys ){ +void VolumeInCylinder::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOM","the atom whose vicinity we are interested in examining"); keys.add("compulsory","DIRECTION","the direction of the long axis of the cylinder. Must be x, y or z"); @@ -98,21 +98,21 @@ void VolumeInCylinder::registerKeywords( Keywords& keys ){ } VolumeInCylinder::VolumeInCylinder(const ActionOptions& ao): -Action(ao), -ActionVolume(ao), -docylinder(false) + Action(ao), + ActionVolume(ao), + docylinder(false) { - std::vector atom; + std::vector atom; parseAtomList("ATOM",atom); if( atom.size()!=1 ) error("should only be one atom specified"); log.printf(" center of cylinder is at position of atom : %d\n",atom[0].serial() ); std::string sdir; parse("DIRECTION",sdir); - if( sdir=="X"){dir.push_back(1); dir.push_back(2); dir.push_back(0); } - else if( sdir=="Y"){dir.push_back(0); dir.push_back(2); dir.push_back(1); } - else if( sdir=="Z"){dir.push_back(0); dir.push_back(1); dir.push_back(2); } + if( sdir=="X") {dir.push_back(1); dir.push_back(2); dir.push_back(0); } + else if( sdir=="Y") {dir.push_back(0); dir.push_back(2); dir.push_back(1); } + else if( sdir=="Z") {dir.push_back(0); dir.push_back(1); dir.push_back(2); } else { error(sdir + "is not a valid direction. Should be X, Y or Z"); } - log.printf(" cylinder's long axis is along %s axis\n",sdir.c_str() ); + log.printf(" cylinder's long axis is along %s axis\n",sdir.c_str() ); std::string sw, errors; parse("RADIUS",sw); if(sw.length()==0) error("missing RADIUS keyword"); @@ -121,33 +121,33 @@ docylinder(false) log.printf(" radius of cylinder is given by %s \n", ( switchingFunction.description() ).c_str() ); double min, max; parse("LOWER",min); parse("UPPER",max); - if( min!=0.0 || max!=0.0 ){ - if( min>max ) error("minimum of cylinder should be less than maximum"); - docylinder=true; - log.printf(" cylinder extends from %f to %f along the %s axis\n",min,max,sdir.c_str() ); - bead.isNotPeriodic(); bead.setKernelType( getKernelType() ); bead.set( min, max, getSigma() ); + if( min!=0.0 || max!=0.0 ) { + if( min>max ) error("minimum of cylinder should be less than maximum"); + docylinder=true; + log.printf(" cylinder extends from %f to %f along the %s axis\n",min,max,sdir.c_str() ); + bead.isNotPeriodic(); bead.setKernelType( getKernelType() ); bead.set( min, max, getSigma() ); } - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); } -void VolumeInCylinder::setupRegions(){ } +void VolumeInCylinder::setupRegions() { } double VolumeInCylinder::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const { // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); - + double vcylinder, dcylinder; - if( docylinder ){ - vcylinder=bead.calculate( fpos[dir[2]], dcylinder ); + if( docylinder ) { + vcylinder=bead.calculate( fpos[dir[2]], dcylinder ); } else { - vcylinder=1.0; dcylinder=0.0; + vcylinder=1.0; dcylinder=0.0; } const double dd = fpos[dir[0]]*fpos[dir[0]] + fpos[dir[1]]*fpos[dir[1]]; double dfunc, vswitch = switchingFunction.calculateSqr( dd, dfunc ); derivatives.zero(); double value=vswitch*vcylinder; - derivatives[dir[0]]=vcylinder*dfunc*fpos[dir[0]]; + derivatives[dir[0]]=vcylinder*dfunc*fpos[dir[0]]; derivatives[dir[1]]=vcylinder*dfunc*fpos[dir[1]]; derivatives[dir[2]]=vswitch*dcylinder; // Add derivatives wrt to position of origin atom diff --git a/src/multicolvar/VolumeInSphere.cpp b/src/multicolvar/VolumeInSphere.cpp index 61badf5f35..632af88df5 100644 --- a/src/multicolvar/VolumeInSphere.cpp +++ b/src/multicolvar/VolumeInSphere.cpp @@ -26,40 +26,40 @@ //+PLUMEDOC VOLUMES INSPHERE /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a particular, user-specified part of of the cell. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r) }{ \sum_i \sigma(r) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r) }{ \sum_i \sigma(r) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (x_i,y_i,z_i)\f$. -The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the +The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the collective is located \f$(x_i,y_i,z_i)\f$ and the position of the atom that was specified using the ORIGIN keyword. In other words: \f[ r = sqrt{ ( x_i - x_0)^2 + ( y_i - y_0)^2 + ( z_i - z_0)^2} -\f] -In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a sphere that is +\f] +In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a sphere that is centered on the position of the atom specified using the keyword ORIGIN. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated +When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated \par Examples -The input below can be use to calculate the average coordination numbers for those atoms that are within a sphere +The input below can be use to calculate the average coordination numbers for those atoms that are within a sphere of radius 1.5 nm that is centered on the position of atom 101. \verbatim -c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} +c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} d2: INSPHERE ATOM=101 DATA=d1 RADIUS={TANH R_0=1.5} SIGMA=0.1 LOWER=-0.1 UPPER=0.1 MEAN PRINT ARG=d2.* FILE=colvar \endverbatim @@ -79,11 +79,11 @@ class VolumeInSphere : public ActionVolume { explicit VolumeInSphere(const ActionOptions& ao); void setupRegions(); double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const ; -}; +}; PLUMED_REGISTER_ACTION(VolumeInSphere,"INSPHERE") -void VolumeInSphere::registerKeywords( Keywords& keys ){ +void VolumeInSphere::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOM","the atom whose vicinity we are interested in examining"); keys.add("compulsory","RADIUS","the switching function that tells us the extent of the sphereical region of interest"); @@ -91,10 +91,10 @@ void VolumeInSphere::registerKeywords( Keywords& keys ){ } VolumeInSphere::VolumeInSphere(const ActionOptions& ao): -Action(ao), -ActionVolume(ao) + Action(ao), + ActionVolume(ao) { - std::vector atom; + std::vector atom; parseAtomList("ATOM",atom); if( atom.size()!=1 ) error("should only be one atom specified"); log.printf(" center of sphere is at position of atom : %d\n",atom[0].serial() ); @@ -105,15 +105,15 @@ ActionVolume(ao) if( errors.length()!=0 ) error("problem reading RADIUS keyword : " + errors ); log.printf(" radius of sphere is given by %s \n", ( switchingFunction.description() ).c_str() ); - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); } -void VolumeInSphere::setupRegions(){ } +void VolumeInSphere::setupRegions() { } double VolumeInSphere::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const { // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); - double dfunc, value = switchingFunction.calculateSqr( fpos.modulo2(), dfunc ); + double dfunc, value = switchingFunction.calculateSqr( fpos.modulo2(), dfunc ); derivatives.zero(); derivatives = dfunc*fpos; refders[0] = -derivatives; // Add a virial contribution vir -= Tensor(fpos,derivatives); diff --git a/src/multicolvar/VolumeTetrapore.cpp b/src/multicolvar/VolumeTetrapore.cpp index f2cb668b30..98fe915c33 100644 --- a/src/multicolvar/VolumeTetrapore.cpp +++ b/src/multicolvar/VolumeTetrapore.cpp @@ -26,24 +26,24 @@ #include "tools/Pbc.h" #include "ActionVolume.h" -//+PLUMEDOC VOLUMES TETRAHEDRALPORE +//+PLUMEDOC VOLUMES TETRAHEDRALPORE /* This quantity can be used to calculate functions of the distribution of collective variables for the atoms lie that lie in a box defined by the positions of four atoms at the corners of a tetrahedron. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (u_i,v_i,z_i)\f$. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ +Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation matrix as follows: \f[ @@ -63,10 +63,10 @@ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation m \right) \f] -where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the -refererence positions specified by the user. Initially unit vectors are found by calculating the bisector, \f$\mathbf{b}\f$, and -cross product, \f$\mathbf{c}\f$, of the vectors connecting atoms 1 and 2. A third unit vector, \f$\mathbf{p}\f$ is then found by taking the cross -product between the cross product calculated during the first step, \f$\mathbf{c}\f$ and the bisector, \f$\mathbf{b}\f$. From this +where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the +refererence positions specified by the user. Initially unit vectors are found by calculating the bisector, \f$\mathbf{b}\f$, and +cross product, \f$\mathbf{c}\f$, of the vectors connecting atoms 1 and 2. A third unit vector, \f$\mathbf{p}\f$ is then found by taking the cross +product between the cross product calculated during the first step, \f$\mathbf{c}\f$ and the bisector, \f$\mathbf{b}\f$. From this second cross product \f$\mathbf{p}\f$ and the bisector \f$\mathbf{b}\f$ two new vectors are calculated using: \f[ @@ -78,13 +78,13 @@ In the previous function \f$ w(u_i,v_i,w_i) \f$ measures whether or not the syst is equal to: \f[ -w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w - K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) +w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w + K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) \f] -where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. -The values of \f$u'\f$ and \f$v'\f$ are found by finding the projections of the vectors connecting atoms 1 and 2 and 1 -and 3 \f$v_1\f$ and \f$v_2\f$. This gives four projections: the largest two projections are used in the remainder of +where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. +The values of \f$u'\f$ and \f$v'\f$ are found by finding the projections of the vectors connecting atoms 1 and 2 and 1 +and 3 \f$v_1\f$ and \f$v_2\f$. This gives four projections: the largest two projections are used in the remainder of the calculations. \f$w'\f$ is calculated by taking the projection of the vector connecting atoms 1 and 4 on the vector \f$\mathbf{c}\f$. Notice that the manner by which this box is constructed differs from the way this is done in \ref CAVITY. This is in fact the only point of difference between these two actions. @@ -95,11 +95,11 @@ The following commands tell plumed to calculate the number of atom inside a tetr cavity is calculated from the positions of atoms 1, 4, 5, and 11, The final value will be labeled cav. \verbatim -d1: DENSITY SPECIES=20-500 +d1: DENSITY SPECIES=20-500 TETRAHEDRALPORE DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 LABEL=cav \endverbatim -The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water +The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water molecules in the tetrahedral cavity described above. The average coordination number and the number of coordination numbers more than 4 is then calculated. The values of these two quantities are given the labels cav.mean and cav.morethan @@ -135,7 +135,7 @@ class VolumeTetrapore : public ActionVolume { PLUMED_REGISTER_ACTION(VolumeTetrapore,"TETRAHEDRALPORE") -void VolumeTetrapore::registerKeywords( Keywords& keys ){ +void VolumeTetrapore::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOMS","the positions of four atoms that define spatial extent of the cavity"); keys.addFlag("PRINT_BOX",false,"write out the positions of the corners of the box to an xyz file"); @@ -144,54 +144,54 @@ void VolumeTetrapore::registerKeywords( Keywords& keys ){ } VolumeTetrapore::VolumeTetrapore(const ActionOptions& ao): -Action(ao), -ActionVolume(ao), -boxout(false), -lenunit(1.0), -dlbi(4), -dlcross(4), -dlperp(4), -dbi(3), -dcross(3), -dperp(3) + Action(ao), + ActionVolume(ao), + boxout(false), + lenunit(1.0), + dlbi(4), + dlcross(4), + dlperp(4), + dbi(3), + dcross(3), + dperp(3) { std::vector atoms; parseAtomList("ATOMS",atoms); if( atoms.size()!=4 ) error("number of atoms should be equal to four"); log.printf(" boundaries for region are calculated based on positions of atoms : "); - for(unsigned i=0;i0 ){ - Units u; u.setLength(unitname); - lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); - } else { - unitname="nm"; - } - boxfile.link(*this); - boxfile.open( boxfname.c_str() ); - log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); - } + if(boxout) { + std::string boxfname; parse("FILE",boxfname); + if(boxfname.length()==0) error("no name for box file specified"); + std::string unitname; parse("UNITS",unitname); + if ( unitname.length()>0 ) { + Units u; u.setLength(unitname); + lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); + } else { + unitname="nm"; + } + boxfile.link(*this); + boxfile.open( boxfname.c_str() ); + log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); + } checkRead(); requestAtoms(atoms); // We have to readd the dependency because requestAtoms removes it - addDependency( getPntrToMultiColvar() ); + addDependency( getPntrToMultiColvar() ); } -VolumeTetrapore::~VolumeTetrapore(){ +VolumeTetrapore::~VolumeTetrapore() { } -void VolumeTetrapore::setupRegions(){ +void VolumeTetrapore::setupRegions() { // Make some space for things Vector d1, d2, d3; - + // Retrieve the sigma value sigma=getSigma(); // Set the position of the origin @@ -201,7 +201,7 @@ void VolumeTetrapore::setupRegions(){ d1 = pbcDistance(origin,getPosition(1)); d2 = pbcDistance(origin,getPosition(2)); - // Find the vector connecting the origin to the top corner of + // Find the vector connecting the origin to the top corner of // the subregion d3 = pbcDistance(origin,getPosition(3)); @@ -209,19 +209,19 @@ void VolumeTetrapore::setupRegions(){ Vector bisector = d1 + d2; double bmod=bisector.modulo(); bisector=bisector/bmod; // bi = d1 / d1l; len_bi=dotProduct( d3, bi ); - cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); + cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); cross = cross / crossmod; len_cross=dotProduct( d3, cross ); - Vector truep = crossProduct( cross, bisector ); + Vector truep = crossProduct( cross, bisector ); // These are our true vectors 45 degrees from bisector bi = cos(pi/4.0)*bisector + sin(pi/4.0)*truep; - perp = cos(pi/4.0)*bisector - sin(pi/4.0)*truep; + perp = cos(pi/4.0)*bisector - sin(pi/4.0)*truep; // And the lengths of the various parts average distance to opposite corners of tetetrahedron len_bi = dotProduct( d1, bi ); double len_bi2 = dotProduct( d2, bi ); unsigned lbi=1; - if( len_bi2>len_bi ){ len_bi=len_bi2; lbi=2; } + if( len_bi2>len_bi ) { len_bi=len_bi2; lbi=2; } len_perp = dotProduct( d1, perp ); double len_perp2 = dotProduct( d2, perp ); unsigned lpi=1; - if( len_perp2>len_perp ){ len_perp=len_perp2; lpi=2; } + if( len_perp2>len_perp ) { len_perp=len_perp2; lpi=2; } plumed_assert( lbi!=lpi ); Tensor tcderiv; double cmod3=crossmod*crossmod*crossmod; Vector ucross=crossmod*cross; @@ -230,7 +230,7 @@ void VolumeTetrapore::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,-1.0) ) + crossProduct( Vector(0.0,0.0,-1.0), d2 ) ); dcross[0](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[0](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[0](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[0](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[0](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -243,7 +243,7 @@ void VolumeTetrapore::setupRegions(){ tcderiv.setCol( 2, crossProduct( Vector(0.0,0.0,1.0), d2 ) ); dcross[1](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[1](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[1](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[1](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[1](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -256,7 +256,7 @@ void VolumeTetrapore::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,1.0) ) ); dcross[2](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[2](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[2](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[2](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[2](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -310,38 +310,38 @@ void VolumeTetrapore::setupRegions(){ dtruep[2].setCol( 2, ( crossProduct( dcross[2].getCol(2), bisector ) + crossProduct( cross, dbisector[2].getCol(2) ) ) ); // Now convert these to the derivatives of the true axis - for(unsigned i=0;i<3;++i){ - dbi[i] = cos(pi/4.0)*dbisector[i] + sin(pi/4.0)*dtruep[i]; - dperp[i] = cos(pi/4.0)*dbisector[i] - sin(pi/4.0)*dtruep[i]; + for(unsigned i=0; i<3; ++i) { + dbi[i] = cos(pi/4.0)*dbisector[i] + sin(pi/4.0)*dtruep[i]; + dperp[i] = cos(pi/4.0)*dbisector[i] - sin(pi/4.0)*dtruep[i]; } // Ensure that all lengths are positive - if( len_bi<0 ){ - bi=-bi; len_bi=-len_bi; - for(unsigned i=0;i<3;++i) dbi[i]*=-1.0; + if( len_bi<0 ) { + bi=-bi; len_bi=-len_bi; + for(unsigned i=0; i<3; ++i) dbi[i]*=-1.0; + } + if( len_cross<0 ) { + cross=-cross; len_cross=-len_cross; + for(unsigned i=0; i<3; ++i) dcross[i]*=-1.0; } - if( len_cross<0 ){ - cross=-cross; len_cross=-len_cross; - for(unsigned i=0;i<3;++i) dcross[i]*=-1.0; + if( len_perp<0 ) { + perp=-perp; len_perp=-len_perp; + for(unsigned i=0; i<3; ++i) dperp[i]*=-1.0; } - if( len_perp<0 ){ - perp=-perp; len_perp=-len_perp; - for(unsigned i=0;i<3;++i) dperp[i]*=-1.0; - } if( len_bi<=0 || len_cross<=0 || len_bi<=0 ) plumed_merror("Invalid box coordinates"); // Now derivatives of lengths Tensor dd3( Tensor::identity() ); Vector ddb2=d1; if( lbi==2 ) ddb2=d2; dlbi[1].zero(); dlbi[2].zero(); dlbi[3].zero(); - dlbi[0] = matmul(ddb2,dbi[0]) - matmul(bi,dd3); + dlbi[0] = matmul(ddb2,dbi[0]) - matmul(bi,dd3); dlbi[lbi] = matmul(ddb2,dbi[lbi]) + matmul(bi,dd3); // Derivative wrt d1 - dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); + dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); dlcross[1] = matmul(d3,dcross[1]); dlcross[2] = matmul(d3,dcross[2]); dlcross[3] = matmul(cross,dd3); - ddb2=d1; if( lpi==2 ) ddb2=d2; + ddb2=d1; if( lpi==2 ) ddb2=d2; dlperp[1].zero(); dlperp[2].zero(); dlperp[3].zero(); dlperp[0] = matmul(ddb2,dperp[0]) - matmul( perp, dd3 ); dlperp[lpi] = matmul(ddb2,dperp[lpi]) + matmul(perp, dd3); @@ -354,39 +354,39 @@ void VolumeTetrapore::setupRegions(){ jacob_det = fabs( jacob.determinant() ); } -void VolumeTetrapore::update(){ - if(boxout){ - boxfile.printf("%d\n",8); - const Tensor & t(getPbc().getBox()); - if(getPbc().isOrthorombic()){ - boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ - boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); - } - boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); - Vector ut, vt, wt; - ut = origin + len_bi*bi; - vt = origin + len_cross*cross; - wt = origin + len_perp*perp; - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]) , lenunit*(ut[1]), lenunit*(ut[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]) , lenunit*(vt[1]), lenunit*(vt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]) , lenunit*(wt[1]), lenunit*(wt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_bi*bi[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), - lenunit*(ut[1]+len_perp*perp[1]), - lenunit*(ut[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), - lenunit*(vt[1]+len_perp*perp[1]), - lenunit*(vt[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); +void VolumeTetrapore::update() { + if(boxout) { + boxfile.printf("%d\n",8); + const Tensor & t(getPbc().getBox()); + if(getPbc().isOrthorombic()) { + boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); + } else { + boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); + } + boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); + Vector ut, vt, wt; + ut = origin + len_bi*bi; + vt = origin + len_cross*cross; + wt = origin + len_perp*perp; + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]), lenunit*(ut[1]), lenunit*(ut[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]), lenunit*(vt[1]), lenunit*(vt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]), lenunit*(wt[1]), lenunit*(wt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_bi*bi[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), + lenunit*(ut[1]+len_perp*perp[1]), + lenunit*(ut[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), + lenunit*(vt[1]+len_perp*perp[1]), + lenunit*(vt[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); } } @@ -402,8 +402,8 @@ double VolumeTetrapore::calculateNumberInside( const Vector& cpos, Vector& deriv bead.set( 0, len_bi, sigma ); double upos=dotProduct( datom, bi ); ucontr=bead.calculate( upos, uder ); - double udlen=bead.uboundDerivative( upos ); - double uder2 = bead.lboundDerivative( upos ) - udlen; + double udlen=bead.uboundDerivative( upos ); + double uder2 = bead.lboundDerivative( upos ) - udlen; // Calculate contribution from integral along cross bead.set( 0, len_cross, sigma ); @@ -423,22 +423,22 @@ double VolumeTetrapore::calculateNumberInside( const Vector& cpos, Vector& deriv derivatives[0] = (dfd[0]*bi[0]+dfd[1]*cross[0]+dfd[2]*perp[0]); derivatives[1] = (dfd[0]*bi[1]+dfd[1]*cross[1]+dfd[2]*perp[1]); derivatives[2] = (dfd[0]*bi[2]+dfd[1]*cross[2]+dfd[2]*perp[2]); - double tot = ucontr*vcontr*wcontr*jacob_det; + double tot = ucontr*vcontr*wcontr*jacob_det; // Add reference atom derivatives 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]) + - dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; - rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + + dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; + rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + dfld[0]*dlbi[1] + dfld[1]*dlcross[1] + dfld[2]*dlperp[1]; - rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + + rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + 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]; vir.zero(); vir-=Tensor( cpos,derivatives ); - for(unsigned i=0;i<4;++i){ - vir -= Tensor( getPosition(i), rderiv[i] ); + for(unsigned i=0; i<4; ++i) { + vir -= Tensor( getPosition(i), rderiv[i] ); } return tot; diff --git a/src/multicolvar/XAngle.cpp b/src/multicolvar/XAngle.cpp index 2e8791003b..fbc2ab1d71 100644 --- a/src/multicolvar/XAngle.cpp +++ b/src/multicolvar/XAngle.cpp @@ -30,17 +30,17 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XANGLES /* -Calculate the angles between the vector connecting two atoms and the x axis. +Calculate the angles between the vector connecting two atoms and the x axis. \par Examples The following input tells plumed to calculate the angles between the x-axis and the vector connecting atom 3 to atom 5 and between the x-axis -and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \verbatim XANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -51,12 +51,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YANGLES /* -Calculate the angles between the vector connecting two atoms and the y axis. +Calculate the angles between the vector connecting two atoms and the y axis. \par Examples The following input tells plumed to calculate the angles between the y-axis and the vector connecting atom 3 to atom 5 and between the y-axis -and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \verbatim YANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -67,12 +67,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR ZANGLES /* -Calculate the angles between the vector connecting two atoms and the z axis. +Calculate the angles between the vector connecting two atoms and the z axis. \par Examples The following input tells plumed to calculate the angles between the z-axis and the vector connecting atom 3 to atom 5 and between the z-axis -and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \verbatim ZANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -86,7 +86,7 @@ PRINT ARG=d1.min class XAngles : public MultiColvarBase { private: bool use_sf; - unsigned myc; + unsigned myc; SwitchingFunction sf1; public: static void registerKeywords( Keywords& keys ); @@ -95,38 +95,38 @@ class XAngles : public MultiColvarBase { virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; double calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(XAngles,"XANGLES") PLUMED_REGISTER_ACTION(XAngles,"YANGLES") PLUMED_REGISTER_ACTION(XAngles,"ZANGLES") -void XAngles::registerKeywords( Keywords& keys ){ +void XAngles::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MAX"); keys.use("ALT_MIN"); keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the angles you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one angle will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one angle will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); 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 " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); keys.add("optional","SWITCH","A switching function that ensures that only angles are only computed when atoms are within " - "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); + "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); } XAngles::XAngles(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao), -use_sf(false) + Action(ao), + MultiColvarBase(ao), + use_sf(false) { if( getName().find("X")!=std::string::npos) myc=0; else if( getName().find("Y")!=std::string::npos) myc=1; @@ -135,12 +135,12 @@ use_sf(false) // Read in switching function std::string sfinput, errors; parse("SWITCH",sfinput); - if( sfinput.length()>0 ){ - use_sf=true; weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); - setLinkCellCutoff( sf1.get_dmax() ); + if( sfinput.length()>0 ) { + use_sf=true; weightHasDerivatives=true; + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); + setLinkCellCutoff( sf1.get_dmax() ); } // Read in the atoms @@ -156,7 +156,7 @@ double XAngles::calculateWeight( const unsigned& taskCode, const double& weight, if(!use_sf) return 1.0; Vector distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); + double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); addAtomDerivatives( 0, 0, (-dw)*distance, myatoms ); addAtomDerivatives( 0, 1, (+dw)*distance, myatoms ); myatoms.addBoxDerivatives( 0, (-dw)*Tensor(distance,distance) ); @@ -164,14 +164,14 @@ double XAngles::calculateWeight( const unsigned& taskCode, const double& weight, } double XAngles::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector ddij, ddik, axis, distance; axis.zero(); axis[myc]=1; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - PLMD::Angle a; double angle=a.compute( distance, axis, ddij, ddik ); - - addAtomDerivatives( 1, 0, -ddij, myatoms ); - addAtomDerivatives( 1, 1, ddij, myatoms ); - myatoms.addBoxDerivatives( 1, -Tensor( distance,ddij ) ); - return angle; + Vector ddij, ddik, axis, distance; axis.zero(); axis[myc]=1; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + PLMD::Angle a; double angle=a.compute( distance, axis, ddij, ddik ); + + addAtomDerivatives( 1, 0, -ddij, myatoms ); + addAtomDerivatives( 1, 1, ddij, myatoms ); + myatoms.addBoxDerivatives( 1, -Tensor( distance,ddij ) ); + return angle; } } diff --git a/src/multicolvar/XDistances.cpp b/src/multicolvar/XDistances.cpp index 6bff7887e0..009b04de59 100644 --- a/src/multicolvar/XDistances.cpp +++ b/src/multicolvar/XDistances.cpp @@ -28,20 +28,20 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XDISTANCES /* -Calculate the x components of the vectors connecting one or many pairs of atoms. +Calculate the x components of the vectors connecting one or many pairs of atoms. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and -the x-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and +the x-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +printed \verbatim XDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -49,8 +49,8 @@ PRINT ARG=d1.min (See also \ref PRINT). -The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and -the x-component of the vector connecting atom 1 to atom 2. The number of values that are +The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and +the x-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. \verbatim XDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} @@ -58,8 +58,8 @@ PRINT ARG=d1.lt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction). -The following input tells plumed to calculate the x-components of all the distinct vectors that can be created -between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). +The following input tells plumed to calculate the x-components of all the distinct vectors that can be created +between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. \verbatim XDISTANCES GROUP=1-3 AVERAGE LABEL=d1 @@ -68,11 +68,11 @@ PRINT ARG=d1.average (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. -In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values +In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. \verbatim XDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) */ @@ -80,15 +80,15 @@ PRINT ARG=d1.gt0.1 //+PLUMEDOC MCOLVAR YDISTANCES /* -Calculate the y components of the vectors connecting one or many pairs of atoms. +Calculate the y components of the vectors connecting one or many pairs of atoms. You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and -the y-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and +the y-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +printed \verbatim YDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -96,8 +96,8 @@ PRINT ARG=d1.min (See also \ref PRINT). -The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and -the y-component of the vector connecting atom 1 to atom 2. The number of values that are +The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and +the y-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. \verbatim YDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} @@ -105,8 +105,8 @@ PRINT ARG=d1.lt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction). -The following input tells plumed to calculate the y-components of all the distinct vectors that can be created -between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). +The following input tells plumed to calculate the y-components of all the distinct vectors that can be created +between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. \verbatim YDISTANCES GROUP=1-3 AVERAGE LABEL=d1 @@ -115,11 +115,11 @@ PRINT ARG=d1.average (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. -In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values +In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. \verbatim YDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) @@ -128,15 +128,15 @@ PRINT ARG=d1.gt0.1 //+PLUMEDOC MCOLVAR ZDISTANCES /* -Calculate the z components of the vectors connecting one or many pairs of atoms. +Calculate the z components of the vectors connecting one or many pairs of atoms. You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and -the z-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and +the z-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +printed \verbatim ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -144,8 +144,8 @@ PRINT ARG=d1.min (See also \ref PRINT). -The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and -the z-component of the vector connecting atom 1 to atom 2. The number of values that are +The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and +the z-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. \verbatim ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} @@ -153,8 +153,8 @@ PRINT ARG=d1.lt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction). -The following input tells plumed to calculate the z-components of all the distinct vectors that can be created -between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). +The following input tells plumed to calculate the z-components of all the distinct vectors that can be created +between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. \verbatim ZDISTANCES GROUP=1-3 AVERAGE LABEL=d1 @@ -163,11 +163,11 @@ PRINT ARG=d1.average (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. -In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values +In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. \verbatim ZDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) @@ -184,35 +184,35 @@ class XDistances : public MultiColvarBase { // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(XDistances,"XDISTANCES") PLUMED_REGISTER_ACTION(XDistances,"YDISTANCES") PLUMED_REGISTER_ACTION(XDistances,"ZDISTANCES") -void XDistances::registerKeywords( Keywords& keys ){ +void XDistances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MAX"); keys.use("ALT_MIN"); keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the distances you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); 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 " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); } XDistances::XDistances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { if( getName().find("X")!=std::string::npos) myc=0; else if( getName().find("Y")!=std::string::npos) myc=1; @@ -229,16 +229,16 @@ MultiColvarBase(ao) } double XDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector distance; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - const double value=distance[myc]; - - Vector myvec; myvec.zero(); - // And finish the calculation - myvec[myc]=+1; addAtomDerivatives( 1, 1, myvec, myatoms ); - myvec[myc]=-1; addAtomDerivatives( 1, 0, myvec, myatoms ); - myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); - return value; + Vector distance; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + const double value=distance[myc]; + + Vector myvec; myvec.zero(); + // And finish the calculation + myvec[myc]=+1; addAtomDerivatives( 1, 1, myvec, myatoms ); + myvec[myc]=-1; addAtomDerivatives( 1, 0, myvec, myatoms ); + myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); + return value; } } diff --git a/src/multicolvar/XYDistances.cpp b/src/multicolvar/XYDistances.cpp index a6a2e978a9..767c64a86a 100644 --- a/src/multicolvar/XYDistances.cpp +++ b/src/multicolvar/XYDistances.cpp @@ -28,21 +28,21 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XYDISTANCES /* -Calculate distance between a pair of atoms neglecting the z-component. +Calculate distance between a pair of atoms neglecting the z-component. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 -to atom 5 projected in the xy-plane and the projection of the length of the vector -the vector connecting atom 1 to atom 2 in the xy-plane. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 +to atom 5 projected in the xy-plane and the projection of the length of the vector +the vector connecting atom 1 to atom 2 in the xy-plane. The minimum of these two quantities is then +printed \verbatim XYDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -54,16 +54,16 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR XZDISTANCES /* -Calculate distance between a pair of atoms neglecting the y-component. +Calculate distance between a pair of atoms neglecting the y-component. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 -to atom 5 projected in the xz-plane and the projection of the length of the vector -the vector connecting atom 1 to atom 2 in the xz-plane. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 +to atom 5 projected in the xz-plane and the projection of the length of the vector +the vector connecting atom 1 to atom 2 in the xz-plane. The minimum of these two quantities is then +printed \verbatim XZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -75,16 +75,16 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YZDISTANCES /* -Calculate distance between a pair of atoms neglecting the x-component. +Calculate distance between a pair of atoms neglecting the x-component. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 -to atom 5 in the yz-plane and the projection of the length of the vector -the vector connecting atom 1 to atom 2 in the yz-plane. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 +to atom 5 in the yz-plane and the projection of the length of the vector +the vector connecting atom 1 to atom 2 in the yz-plane. The minimum of these two quantities is then +printed \verbatim YZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -104,41 +104,41 @@ class XYDistances : public MultiColvarBase { // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(XYDistances,"XYDISTANCES") PLUMED_REGISTER_ACTION(XYDistances,"XZDISTANCES") PLUMED_REGISTER_ACTION(XYDistances,"YZDISTANCES") -void XYDistances::registerKeywords( Keywords& keys ){ +void XYDistances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); - keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the distances you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the incides of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the incides of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); 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 " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); } XYDistances::XYDistances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { - if( getName().find("XY")!=std::string::npos){ - myc1=0; myc2=1; - } else if( getName().find("XZ")!=std::string::npos){ - myc1=0; myc2=2; - } else if( getName().find("YZ")!=std::string::npos){ - myc1=1; myc2=2; + if( getName().find("XY")!=std::string::npos) { + myc1=0; myc2=1; + } else if( getName().find("XZ")!=std::string::npos) { + myc1=0; myc2=2; + } else if( getName().find("YZ")!=std::string::npos) { + myc1=1; myc2=2; } else plumed_error(); // Read in the atoms @@ -151,17 +151,17 @@ MultiColvarBase(ao) } double XYDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector distance; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - const double value=sqrt(distance[myc1]*distance[myc1] + distance[myc2]*distance[myc2] ); - const double invvalue=1.0/value; - - Vector myvec; myvec.zero(); - // And finish the calculation - myvec[myc1]=+invvalue*distance[myc1]; myvec[myc2]=+invvalue*distance[myc2]; addAtomDerivatives( 1, 1, myvec, myatoms ); - myvec[myc1]=-invvalue*distance[myc1]; myvec[myc2]=-invvalue*distance[myc2]; addAtomDerivatives( 1, 0, myvec, myatoms ); - myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); - return value; + Vector distance; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + const double value=sqrt(distance[myc1]*distance[myc1] + distance[myc2]*distance[myc2] ); + const double invvalue=1.0/value; + + Vector myvec; myvec.zero(); + // And finish the calculation + myvec[myc1]=+invvalue*distance[myc1]; myvec[myc2]=+invvalue*distance[myc2]; addAtomDerivatives( 1, 1, myvec, myatoms ); + myvec[myc1]=-invvalue*distance[myc1]; myvec[myc2]=-invvalue*distance[myc2]; addAtomDerivatives( 1, 0, myvec, myatoms ); + myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); + return value; } } diff --git a/src/multicolvar/XYTorsion.cpp b/src/multicolvar/XYTorsion.cpp index a263a2abdd..fd512799a4 100644 --- a/src/multicolvar/XYTorsion.cpp +++ b/src/multicolvar/XYTorsion.cpp @@ -30,17 +30,17 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XYTORSIONS /* -Calculate the torsional angle around the x axis from the positive y direction. +Calculate the torsional angle around the x axis from the positive y direction. \par Examples -The following input tells plumed to calculate the angle around the x direction between the positive y-axis and the vector connecting atom 3 to atom 5 and -the angle around the x direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the x direction between the positive y-axis and the vector connecting atom 3 to atom 5 and +the angle around the x direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim XYTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -51,12 +51,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR XZTORSIONS /* -Calculate the torsional angle around the x axis from the positive z direction. +Calculate the torsional angle around the x axis from the positive z direction. \par Examples -The following input tells plumed to calculate the angle around the x direction between the positive z-axis and the vector connecting atom 3 to atom 5 and -the angle around the x direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the x direction between the positive z-axis and the vector connecting atom 3 to atom 5 and +the angle around the x direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim XZTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -67,12 +67,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YXTORSIONS /* -Calculate the torsional angle around the y axis from the positive x direction. +Calculate the torsional angle around the y axis from the positive x direction. \par Examples -The following input tells plumed to calculate the angle around the y direction between the positive x-direction and the vector connecting atom 3 to atom 5 and -the angle around the y direction between the positive x axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the y direction between the positive x-direction and the vector connecting atom 3 to atom 5 and +the angle around the y direction between the positive x axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim YXTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -83,12 +83,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YZTORSIONS /* -Calculate the torsional angle around the y axis from the positive z direction. +Calculate the torsional angle around the y axis from the positive z direction. \par Examples -The following input tells plumed to calculate the angle around the y direction between the positive z-direction and the vector connecting atom 3 to atom 5 and -the angle around the y direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the y direction between the positive z-direction and the vector connecting atom 3 to atom 5 and +the angle around the y direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim YZTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -99,12 +99,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR ZXTORSIONS /* -Calculate the torsional angle around the z axis from the positive x direction. +Calculate the torsional angle around the z axis from the positive x direction. \par Examples -The following input tells plumed to calculate the angle around the z direction between the positive x-direction and the vector connecting atom 3 to atom 5 and -the angle around the z direction between the positive x-direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the z direction between the positive x-direction and the vector connecting atom 3 to atom 5 and +the angle around the z direction between the positive x-direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim ZXTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -115,12 +115,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR ZYTORSIONS /* -Calculate the torsional angle around the z axis from the positive y direction. +Calculate the torsional angle around the z axis from the positive y direction. \par Examples -The following input tells plumed to calculate the angle around the z direction between the positive y-axis and the vector connecting atom 3 to atom 5 and -the angle around the z direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the z direction between the positive y-axis and the vector connecting atom 3 to atom 5 and +the angle around the z direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim ZYTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -135,7 +135,7 @@ PRINT ARG=d1.min class XYTorsion : public MultiColvarBase { private: bool use_sf; - unsigned myc1, myc2; + unsigned myc1, myc2; SwitchingFunction sf1; public: static void registerKeywords( Keywords& keys ); @@ -144,8 +144,8 @@ class XYTorsion : public MultiColvarBase { virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; double calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return true; } - void retrieveDomain( std::string& min, std::string& max){ min="-pi"; max="pi"; } + bool isPeriodic() { return true; } + void retrieveDomain( std::string& min, std::string& max) { min="-pi"; max="pi"; } }; PLUMED_REGISTER_ACTION(XYTorsion,"XYTORSIONS") @@ -155,48 +155,48 @@ PLUMED_REGISTER_ACTION(XYTorsion,"YZTORSIONS") PLUMED_REGISTER_ACTION(XYTorsion,"ZXTORSIONS") PLUMED_REGISTER_ACTION(XYTorsion,"ZYTORSIONS") -void XYTorsion::registerKeywords( Keywords& keys ){ +void XYTorsion::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); - keys.use("MEAN"); keys.use("MIN"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MEAN"); keys.use("MIN"); + keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the torsions you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one torsion will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the incides of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one torsion will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the incides of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); 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 " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); keys.add("optional","SWITCH","A switching function that ensures that only angles are only computed when atoms are within " - "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); + "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); } XYTorsion::XYTorsion(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao), -use_sf(false) + Action(ao), + MultiColvarBase(ao), + use_sf(false) { - if( getName().find("XY")!=std::string::npos){ myc1=0; myc2=1; } - else if( getName().find("XZ")!=std::string::npos){ myc1=0; myc2=2; } - else if( getName().find("YX")!=std::string::npos){ myc1=1; myc2=0; } - else if( getName().find("YZ")!=std::string::npos){ myc1=1; myc2=2; } - else if( getName().find("ZX")!=std::string::npos){ myc1=2; myc2=0; } - else if( getName().find("ZY")!=std::string::npos){ myc1=2; myc2=1; } + if( getName().find("XY")!=std::string::npos) { myc1=0; myc2=1; } + else if( getName().find("XZ")!=std::string::npos) { myc1=0; myc2=2; } + else if( getName().find("YX")!=std::string::npos) { myc1=1; myc2=0; } + else if( getName().find("YZ")!=std::string::npos) { myc1=1; myc2=2; } + else if( getName().find("ZX")!=std::string::npos) { myc1=2; myc2=0; } + else if( getName().find("ZY")!=std::string::npos) { myc1=2; myc2=1; } else plumed_error(); // Read in switching function std::string sfinput, errors; parse("SWITCH",sfinput); - if( sfinput.length()>0 ){ - use_sf=true; weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); - setLinkCellCutoff( sf1.get_dmax() ); + if( sfinput.length()>0 ) { + use_sf=true; weightHasDerivatives=true; + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); + setLinkCellCutoff( sf1.get_dmax() ); } // Read in the atoms @@ -212,7 +212,7 @@ double XYTorsion::calculateWeight( const unsigned& taskCode, const double& weigh if(!use_sf) return 1.0; Vector distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); + double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); addAtomDerivatives( 0, 0, (-dw)*distance, myatoms ); addAtomDerivatives( 0, 1, (+dw)*distance, myatoms ); myatoms.addBoxDerivatives( 0, (-dw)*Tensor(distance,distance) ); @@ -220,15 +220,15 @@ double XYTorsion::calculateWeight( const unsigned& taskCode, const double& weigh } double XYTorsion::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector dd0, dd1, dd2, axis, rot, distance; - axis.zero(); rot.zero(); rot[myc1]=1; axis[myc2]=1; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - PLMD::Torsion t; double torsion=t.compute( distance, rot, axis, dd0, dd1, dd2 ); - - addAtomDerivatives( 1, 0, -dd0, myatoms ); - addAtomDerivatives( 1, 1, dd0, myatoms ); - myatoms.addBoxDerivatives( 1, -extProduct(distance,dd0) ); - return torsion; + Vector dd0, dd1, dd2, axis, rot, distance; + axis.zero(); rot.zero(); rot[myc1]=1; axis[myc2]=1; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + PLMD::Torsion t; double torsion=t.compute( distance, rot, axis, dd0, dd1, dd2 ); + + addAtomDerivatives( 1, 0, -dd0, myatoms ); + addAtomDerivatives( 1, 1, dd0, myatoms ); + myatoms.addBoxDerivatives( 1, -extProduct(distance,dd0) ); + return torsion; } } diff --git a/src/reference/ArgumentOnlyDistance.cpp b/src/reference/ArgumentOnlyDistance.cpp index 4664044af6..0e4a3e2aee 100644 --- a/src/reference/ArgumentOnlyDistance.cpp +++ b/src/reference/ArgumentOnlyDistance.cpp @@ -25,24 +25,24 @@ namespace PLMD { ArgumentOnlyDistance::ArgumentOnlyDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ReferenceArguments(ro) + ReferenceConfiguration(ro), + ReferenceArguments(ro) { } -void ArgumentOnlyDistance::read( const PDB& pdb ){ +void ArgumentOnlyDistance::read( const PDB& pdb ) { readArgumentsFromPDB( pdb ); } double ArgumentOnlyDistance::calculate( const std::vector& vals, ReferenceValuePack& myder, const bool& squared ) const { std::vector tmparg( vals.size() ); - for(unsigned i=0;iget(); + for(unsigned i=0; iget(); double d=calculateArgumentDistance( vals, tmparg, myder, squared ); if( !myder.updateComplete() ) myder.updateDynamicLists(); return d; } -double ArgumentOnlyDistance::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, +double ArgumentOnlyDistance::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( pos.size()==0 ); double d=calculateArgumentDistance( vals, arg, myder, squared ); diff --git a/src/reference/ArgumentOnlyDistance.h b/src/reference/ArgumentOnlyDistance.h index 67923c17b3..3636f0764e 100644 --- a/src/reference/ArgumentOnlyDistance.h +++ b/src/reference/ArgumentOnlyDistance.h @@ -35,8 +35,8 @@ class ArgumentOnlyDistance : public ReferenceArguments { public: explicit ArgumentOnlyDistance( const ReferenceConfigurationOptions& ro ); void read( const PDB& pdb ); - bool pcaIsEnabledForThisReference(){ return true; } - void setupPCAStorage( ReferenceValuePack& mypack ){ mypack.switchOnPCAOption(); } + bool pcaIsEnabledForThisReference() { return true; } + void setupPCAStorage( ReferenceValuePack& mypack ) { mypack.switchOnPCAOption(); } double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const ; double calculate( const std::vector& vals, ReferenceValuePack& myder, const bool& squared ) const ; }; diff --git a/src/reference/DRMSD.cpp b/src/reference/DRMSD.cpp index d9ee501a69..88183ac5de 100644 --- a/src/reference/DRMSD.cpp +++ b/src/reference/DRMSD.cpp @@ -28,84 +28,84 @@ namespace PLMD { PLUMED_REGISTER_METRIC(DRMSD,"DRMSD") DRMSD::DRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -SingleDomainRMSD( ro ), -nopbc(true), -bounds_were_set(false), -lower(0), -upper(std::numeric_limits::max( )) + ReferenceConfiguration( ro ), + SingleDomainRMSD( ro ), + nopbc(true), + bounds_were_set(false), + lower(0), + upper(std::numeric_limits::max( )) { } -void DRMSD::setBoundsOnDistances( bool dopbc, double lbound, double ubound ){ - bounds_were_set=true; nopbc=!dopbc; +void DRMSD::setBoundsOnDistances( bool dopbc, double lbound, double ubound ) { + bounds_were_set=true; nopbc=!dopbc; lower=lbound; upper=ubound; } -void DRMSD::readBounds(){ - parseFlag("NOPBC",nopbc); +void DRMSD::readBounds() { + parseFlag("NOPBC",nopbc); parse("LOWER_CUTOFF",lower,true); parse("UPPER_CUTOFF",upper,true); setBoundsOnDistances( !nopbc, lower, upper ); } -void DRMSD::read( const PDB& pdb ){ +void DRMSD::read( const PDB& pdb ) { readAtomsFromPDB( pdb ); readBounds(); setup_targets(); } -void DRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ){ +void DRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { SingleDomainRMSD::setReferenceAtoms( conf, align_in, displace_in ); setup_targets(); } -void DRMSD::setup_targets(){ +void DRMSD::setup_targets() { plumed_massert( bounds_were_set, "I am missing a call to DRMSD::setBoundsOnDistances"); unsigned natoms = getNumberOfReferencePositions(); - for(unsigned i=0;i lower ){ - targets[std::make_pair(i,j)] = distance; - } - } + for(unsigned i=0; i lower ) { + targets[std::make_pair(i,j)] = distance; + } + } } - if( targets.empty() ) error("drmsd will compare no distances - check upper and lower bounds are sensible"); + if( targets.empty() ) error("drmsd will compare no distances - check upper and lower bounds are sensible"); } double DRMSD::calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert(!targets.empty()); - Vector distance; - myder.clear(); - double drmsd=0.; - for(const auto & it : targets){ - - const unsigned i=getAtomIndex( it.first.first ); - const unsigned j=getAtomIndex( it.first.second ); - - if(nopbc) distance=delta( pos[i] , pos[j] ); - else distance=pbc.distance( pos[i] , pos[j] ); - - const double len = distance.modulo(); - const double diff = len - it.second; - const double der = diff / len; - - drmsd += diff * diff; - myder.addAtomDerivatives( i, -der * distance ); - myder.addAtomDerivatives( j, der * distance ); - myder.addBoxDerivatives( - der * Tensor(distance,distance) ); + Vector distance; + myder.clear(); + double drmsd=0.; + for(const auto & it : targets) { + + const unsigned i=getAtomIndex( it.first.first ); + const unsigned j=getAtomIndex( it.first.second ); + + if(nopbc) distance=delta( pos[i], pos[j] ); + else distance=pbc.distance( pos[i], pos[j] ); + + const double len = distance.modulo(); + const double diff = len - it.second; + const double der = diff / len; + + drmsd += diff * diff; + myder.addAtomDerivatives( i, -der * distance ); + myder.addAtomDerivatives( j, der * distance ); + myder.addBoxDerivatives( - der * Tensor(distance,distance) ); } const double inpairs = 1./static_cast(targets.size()); double idrmsd; - if(squared){ - drmsd = drmsd * inpairs; - idrmsd = 2.0 * inpairs; + if(squared) { + drmsd = drmsd * inpairs; + idrmsd = 2.0 * inpairs; } else { - drmsd = sqrt( drmsd * inpairs ); - idrmsd = inpairs / drmsd ; + drmsd = sqrt( drmsd * inpairs ); + idrmsd = inpairs / drmsd ; } myder.scaleAllDerivatives( idrmsd ); diff --git a/src/reference/DRMSD.h b/src/reference/DRMSD.h index 634d031626..e99f382f4e 100644 --- a/src/reference/DRMSD.h +++ b/src/reference/DRMSD.h @@ -35,12 +35,12 @@ class DRMSD : public SingleDomainRMSD { protected: bool bounds_were_set; double lower, upper; - std::map< std::pair , double> targets; + std::map< std::pair , double> targets; /// Read in NOPBC, LOWER_CUTOFF and UPPER_CUTOFF void readBounds(); public: explicit DRMSD( const ReferenceConfigurationOptions& ro ); -/// This sets upper and lower bounds on distances to be used in DRMSD +/// This sets upper and lower bounds on distances to be used in DRMSD void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits::max( ) ); /// Check that similar comparisons are being performed - perhaps this is needed ask Davide? GAT // void check( ReferenceConfiguration* , ReferenceConfiguration* ); diff --git a/src/reference/Direction.cpp b/src/reference/Direction.cpp index fa04b643da..5e50e9b333 100644 --- a/src/reference/Direction.cpp +++ b/src/reference/Direction.cpp @@ -27,47 +27,47 @@ namespace PLMD { PLUMED_REGISTER_METRIC(Direction,"DIRECTION") Direction::Direction( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ReferenceAtoms(ro), -ReferenceArguments(ro) + ReferenceConfiguration(ro), + ReferenceAtoms(ro), + ReferenceArguments(ro) { } -void Direction::read( const PDB& pdb ){ +void Direction::read( const PDB& pdb ) { readAtomsFromPDB( pdb ); readArgumentsFromPDB( pdb ); } -void Direction::setDirection( const std::vector& conf, const std::vector& args ){ +void Direction::setDirection( const std::vector& conf, const std::vector& args ) { std::vector sigma( args.size(), 1.0 ); setReferenceArguments( args, sigma ); reference_atoms.resize( conf.size() ); align.resize( conf.size() ); displace.resize( conf.size() ); atom_der_index.resize( conf.size() ); - for(unsigned i=0;i& pos, const Pbc& pbc, const std::vector& vals, const std::vector& args, ReferenceValuePack& myder, const bool& squared ) const { - plumed_merror("You should never be calling calc for a direction"); return 1.0; + plumed_merror("You should never be calling calc for a direction"); return 1.0; } void Direction::extractArgumentDisplacement( const std::vector& vals, const std::vector& arg, std::vector& dirout ) const { - for(unsigned i=0;i& pos, const bool& anflag, std::vector& dirout ) const { - for(unsigned i=0;i& conf, const std::vector& args ); void addDirection( const double& weight, const Direction& dir ); - void setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ){ plumed_error(); } -/// This allows us to extract the reference positions, which are the direction in this case + void setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { plumed_error(); } +/// This allows us to extract the reference positions, which are the direction in this case void extractArgumentDisplacement( const std::vector& vals, const std::vector& arg, std::vector& dirout ) const ; - void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& dirout ) const ; + void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& dirout ) const ; void zeroDirection(); }; diff --git a/src/reference/DotProductDistance.cpp b/src/reference/DotProductDistance.cpp index bfda1290c5..0b0f4eb73d 100644 --- a/src/reference/DotProductDistance.cpp +++ b/src/reference/DotProductDistance.cpp @@ -35,18 +35,18 @@ class DotProductDistance : public ArgumentOnlyDistance { PLUMED_REGISTER_METRIC(DotProductDistance,"DOTPRODUCT") DotProductDistance::DotProductDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ArgumentOnlyDistance(ro) + ReferenceConfiguration(ro), + ArgumentOnlyDistance(ro) { } -void DotProductDistance::read( const PDB& pdb ){ +void DotProductDistance::read( const PDB& pdb ) { readArgumentsFromPDB( pdb ); } -double DotProductDistance::calculateArgumentDistance( const std::vector & vals, const std::vector& arg, - ReferenceValuePack& myder, const bool& squared ) const { - double dot=0.0; +double DotProductDistance::calculateArgumentDistance( const std::vector & vals, const std::vector& arg, + ReferenceValuePack& myder, const bool& squared ) const { + double dot=0.0; for (unsigned long i=0; i& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { - plumed_merror("should not be called"); return 1.0; + void read( const PDB& ) { plumed_merror("should not be called"); } + double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { + plumed_merror("should not be called"); return 1.0; } }; diff --git a/src/reference/IntermolecularDRMSD.cpp b/src/reference/IntermolecularDRMSD.cpp index 223a43f3bf..6903c83522 100644 --- a/src/reference/IntermolecularDRMSD.cpp +++ b/src/reference/IntermolecularDRMSD.cpp @@ -31,37 +31,37 @@ class IntermolecularDRMSD : public DRMSD { public: explicit IntermolecularDRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& pdb ); - void setup_targets(); + void setup_targets(); }; PLUMED_REGISTER_METRIC(IntermolecularDRMSD,"INTER-DRMSD") IntermolecularDRMSD::IntermolecularDRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -DRMSD( ro ), -nblocks(0) + ReferenceConfiguration( ro ), + DRMSD( ro ), + nblocks(0) { } -void IntermolecularDRMSD::read( const PDB& pdb ){ +void IntermolecularDRMSD::read( const PDB& pdb ) { readAtomsFromPDB( pdb, true ); nblocks = pdb.getNumberOfAtomBlocks(); blocks.resize( nblocks+1 ); if( nblocks==1 ) error("Trying to compute intermolecular rmsd but found no TERs in input PDB"); - blocks[0]=0; for(unsigned i=0;i lower ) targets[std::make_pair(iatom,jatom)] = distance; - } - } + for(unsigned i=1; i lower ) targets[std::make_pair(iatom,jatom)] = distance; + } } + } } } diff --git a/src/reference/IntramolecularDRMSD.cpp b/src/reference/IntramolecularDRMSD.cpp index cd7b022c90..2a7b4b64ff 100644 --- a/src/reference/IntramolecularDRMSD.cpp +++ b/src/reference/IntramolecularDRMSD.cpp @@ -31,35 +31,35 @@ class IntramolecularDRMSD : public DRMSD { public: explicit IntramolecularDRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& pdb ); - void setup_targets(); + void setup_targets(); }; PLUMED_REGISTER_METRIC(IntramolecularDRMSD,"INTRA-DRMSD") IntramolecularDRMSD::IntramolecularDRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -DRMSD( ro ), -nblocks(0) + ReferenceConfiguration( ro ), + DRMSD( ro ), + nblocks(0) { } -void IntramolecularDRMSD::read( const PDB& pdb ){ +void IntramolecularDRMSD::read( const PDB& pdb ) { readAtomsFromPDB( pdb, true ); nblocks = pdb.getNumberOfAtomBlocks(); blocks.resize( nblocks+1 ); if( nblocks==1 ) error("Trying to compute intramolecular rmsd but found no TERs in input PDB"); - blocks[0]=0; for(unsigned i=0;i lower ) targets[std::make_pair(iatom,jatom)] = distance; - } + for(unsigned i=0; i lower ) targets[std::make_pair(iatom,jatom)] = distance; } + } } } diff --git a/src/reference/MahalanobisDistance.cpp b/src/reference/MahalanobisDistance.cpp index 7a50bf5e00..19a3e96697 100644 --- a/src/reference/MahalanobisDistance.cpp +++ b/src/reference/MahalanobisDistance.cpp @@ -32,8 +32,8 @@ class MahalanobisDistance : public ArgumentOnlyDistance { PLUMED_REGISTER_METRIC(MahalanobisDistance,"MAHALANOBIS") MahalanobisDistance::MahalanobisDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ArgumentOnlyDistance(ro) + ReferenceConfiguration(ro), + ArgumentOnlyDistance(ro) { hasmetric=true; } diff --git a/src/reference/MetricRegister.cpp b/src/reference/MetricRegister.cpp index 0c240fa0fb..dfff4d5e01 100644 --- a/src/reference/MetricRegister.cpp +++ b/src/reference/MetricRegister.cpp @@ -22,35 +22,35 @@ #include "MetricRegister.h" #include -namespace PLMD{ +namespace PLMD { -MetricRegister::~MetricRegister(){ - if(m.size()>0){ +MetricRegister::~MetricRegister() { + if(m.size()>0) { std::string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: ReferenceConfiguration "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -MetricRegister& metricRegister(){ +MetricRegister& metricRegister() { static MetricRegister ans; return ans; } -void MetricRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void MetricRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void MetricRegister::add( std::string type, creator_pointer f ){ +void MetricRegister::add( std::string type, creator_pointer f ) { plumed_massert(m.count(type)==0,"type has already been registered"); m.insert(std::pair(type,f)); } -bool MetricRegister::check(std::string type){ +bool MetricRegister::check(std::string type) { if( m.count(type)>0 ) return true; return false; } diff --git a/src/reference/MetricRegister.h b/src/reference/MetricRegister.h index 91b44a590f..64cb3424ef 100644 --- a/src/reference/MetricRegister.h +++ b/src/reference/MetricRegister.h @@ -31,11 +31,11 @@ #include "tools/PDB.h" #include "ReferenceConfiguration.h" -namespace PLMD{ +namespace PLMD { class PDB; -class MetricRegister{ +class MetricRegister { private: /// Pointer to a function which, given the type for a ReferenceConfiguration, creates it typedef ReferenceConfiguration*(*creator_pointer)(const ReferenceConfigurationOptions&); @@ -53,9 +53,9 @@ class MetricRegister{ /// Create a reference configuration and don't set a point of reference template T* create( const std::string& type ); -/// Create a reference configuration and set the point of reference from the pdb +/// Create a reference configuration and set the point of reference from the pdb template - T* create( const std::string& type , const PDB& pdb ); + T* create( const std::string& type, const PDB& pdb ); }; MetricRegister& metricRegister(); @@ -69,13 +69,13 @@ MetricRegister& metricRegister(); } classname##RegisterMeObject; template -T* MetricRegister::create( const std::string& type ){ +T* MetricRegister::create( const std::string& type ) { std::string ftype; - if( type.find("MULTI-")!=std::string::npos ){ - ftype="MULTI"; + if( type.find("MULTI-")!=std::string::npos ) { + ftype="MULTI"; } else { - std::size_t dash=type.find("-FAST"); // We must remove the fast label - ftype=type.substr(0,dash); + std::size_t dash=type.find("-FAST"); // We must remove the fast label + ftype=type.substr(0,dash); } plumed_massert( check(ftype), "metric " + ftype + " does not exist" ); ReferenceConfigurationOptions ro( type ); @@ -86,16 +86,16 @@ T* MetricRegister::create( const std::string& type ){ } template -T* MetricRegister::create( const std::string& type, const PDB& pdb ){ +T* MetricRegister::create( const std::string& type, const PDB& pdb ) { std::string rtype; - if( type.length()==0 ){ - std::vector remarks( pdb.getRemark() ); - bool found=Tools::parse( remarks, "TYPE", rtype ); - if(!found) plumed_merror("TYPE not specified in pdb input file"); + if( type.length()==0 ) { + std::vector remarks( pdb.getRemark() ); + bool found=Tools::parse( remarks, "TYPE", rtype ); + if(!found) plumed_merror("TYPE not specified in pdb input file"); } else { - rtype=type; - } - T* confout=create( rtype ); + rtype=type; + } + T* confout=create( rtype ); confout->set( pdb ); return confout; } diff --git a/src/reference/MultiDomainRMSD.cpp b/src/reference/MultiDomainRMSD.cpp index c6ef4ae7ec..fc0bcca62e 100644 --- a/src/reference/MultiDomainRMSD.cpp +++ b/src/reference/MultiDomainRMSD.cpp @@ -29,125 +29,125 @@ namespace PLMD { PLUMED_REGISTER_METRIC(MultiDomainRMSD,"MULTI") MultiDomainRMSD::MultiDomainRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ReferenceAtoms(ro), -ftype(ro.getMultiRMSDType()) + ReferenceConfiguration(ro), + ReferenceAtoms(ro), + ftype(ro.getMultiRMSDType()) { } -MultiDomainRMSD::~MultiDomainRMSD(){ - for(unsigned i=0;i positions; std::vector align, displace; - std::string num; blocks.resize( nblocks+1 ); blocks[0]=0; - for(unsigned i=0;i::max( ); - parse("LOWER_CUTOFF",lower,true); - parse("UPPER_CUTOFF",upper,true); - bool nopbc=false; parseFlag("NOPBC",nopbc); - - for(unsigned i=1;i<=nblocks;++i){ - Tools::convert(i,num); - if( ftype=="RMSD" ){ - parse("TYPE"+num, ftype ); - parse("LOWER_CUTOFF"+num,lower,true); - parse("UPPER_CUTOFF"+num,upper,true); - nopbc=false; parseFlag("NOPBC"+num,nopbc); - } - domains.push_back( metricRegister().create( ftype ) ); - positions.resize( blocks[i] - blocks[i-1] ); - align.resize( blocks[i] - blocks[i-1] ); - displace.resize( blocks[i] - blocks[i-1] ); - unsigned n=0; - for(unsigned j=blocks[i-1];jsetBoundsOnDistances( !nopbc, lower, upper ); - domains[i-1]->setReferenceAtoms( positions, align, displace ); - domains[i-1]->setupRMSDObject(); - - double ww=0; parse("WEIGHT"+num, ww, true ); - if( ww==0 ) weights.push_back( 1.0 ); - else weights.push_back( ww ); - } - // And set the atom numbers for this object - setAtomNumbers( pdb.getAtomNumbers() ); +void MultiDomainRMSD::read( const PDB& pdb ) { + unsigned nblocks = pdb.getNumberOfAtomBlocks(); + if( nblocks<2 ) error("multidomain RMSD only has one block of atoms"); + + std::vector positions; std::vector align, displace; + std::string num; blocks.resize( nblocks+1 ); blocks[0]=0; + for(unsigned i=0; i::max( ); + parse("LOWER_CUTOFF",lower,true); + parse("UPPER_CUTOFF",upper,true); + bool nopbc=false; parseFlag("NOPBC",nopbc); + + for(unsigned i=1; i<=nblocks; ++i) { + Tools::convert(i,num); + if( ftype=="RMSD" ) { + parse("TYPE"+num, ftype ); + parse("LOWER_CUTOFF"+num,lower,true); + parse("UPPER_CUTOFF"+num,upper,true); + nopbc=false; parseFlag("NOPBC"+num,nopbc); + } + domains.push_back( metricRegister().create( ftype ) ); + positions.resize( blocks[i] - blocks[i-1] ); + align.resize( blocks[i] - blocks[i-1] ); + displace.resize( blocks[i] - blocks[i-1] ); + unsigned n=0; + for(unsigned j=blocks[i-1]; jsetBoundsOnDistances( !nopbc, lower, upper ); + domains[i-1]->setReferenceAtoms( positions, align, displace ); + domains[i-1]->setupRMSDObject(); + + double ww=0; parse("WEIGHT"+num, ww, true ); + if( ww==0 ) weights.push_back( 1.0 ); + else weights.push_back( ww ); + } + // And set the atom numbers for this object + setAtomNumbers( pdb.getAtomNumbers() ); } -void MultiDomainRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ){ +void MultiDomainRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { plumed_error(); } double MultiDomainRMSD::calculate( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { - double totd=0.; Tensor tvirial; std::vector mypos; MultiValue tvals( 1, 3*pos.size()+9 ); + double totd=0.; Tensor tvirial; std::vector mypos; MultiValue tvals( 1, 3*pos.size()+9 ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); myder.clear(); - for(unsigned i=0;isetupPCAStorage( tder ); - unsigned n=0; for(unsigned j=blocks[i];jcalculate( mypos, pbc, tder, true ); - // Now merge the derivative - myder.copyScaledDerivatives( 0, weights[i], tvals ); - // If PCA copy PCA stuff - if( myder.calcUsingPCAOption() ){ - unsigned n=0; - if( tder.centeredpos.size()>0 ) myder.rot[i]=tder.rot[0]; - for(unsigned j=blocks[i];j0 ){ - myder.centeredpos[j]=tder.centeredpos[n]; - for(unsigned p=0;p<3;++p) for(unsigned q=0;q<3;++q) myder.DRotDPos(p,q)[j]=tder.DRotDPos(p,q)[n]; - } - n++; + for(unsigned i=0; isetupPCAStorage( tder ); + unsigned n=0; for(unsigned j=blocks[i]; jcalculate( mypos, pbc, tder, true ); + // Now merge the derivative + myder.copyScaledDerivatives( 0, weights[i], tvals ); + // If PCA copy PCA stuff + if( myder.calcUsingPCAOption() ) { + unsigned n=0; + if( tder.centeredpos.size()>0 ) myder.rot[i]=tder.rot[0]; + for(unsigned j=blocks[i]; j0 ) { + myder.centeredpos[j]=tder.centeredpos[n]; + for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) myder.DRotDPos(p,q)[j]=tder.DRotDPos(p,q)[n]; } - } - // Make sure virial status is set correctly in output derivative pack - // This is only done here so I do this by using class friendship - if( tder.virialWasSet() ) myder.boxWasSet=true; + n++; + } + } + // Make sure virial status is set correctly in output derivative pack + // This is only done here so I do this by using class friendship + if( tder.virialWasSet() ) myder.boxWasSet=true; } if( !myder.updateComplete() ) myder.updateDynamicLists(); - if( !squared ){ - totd=sqrt(totd); double xx=0.5/totd; - myder.scaleAllDerivatives( xx ); + if( !squared ) { + totd=sqrt(totd); double xx=0.5/totd; + myder.scaleAllDerivatives( xx ); } return totd; } -double MultiDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, +double MultiDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 ); return calculate( pos, pbc, myder, squared ); } -bool MultiDomainRMSD::pcaIsEnabledForThisReference(){ - bool enabled=true; - for(unsigned i=0;ipcaIsEnabledForThisReference() ) enabled=false; +bool MultiDomainRMSD::pcaIsEnabledForThisReference() { + bool enabled=true; + for(unsigned i=0; ipcaIsEnabledForThisReference() ) enabled=false; } return enabled; } -void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ){ +void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ) { plumed_dbg_assert( pcaIsEnabledForThisReference() ); mypack.switchOnPCAOption(); mypack.displacement.resize( getNumberOfAtoms() ); mypack.centeredpos.resize( getNumberOfAtoms() ); mypack.DRotDPos.resize(3,3); mypack.rot.resize( domains.size() ); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) mypack.DRotDPos(i,j).resize( getNumberOfAtoms() ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) mypack.DRotDPos(i,j).resize( getNumberOfAtoms() ); } // Vector MultiDomainRMSD::getAtomicDisplacement( const unsigned& iatom ){ @@ -161,47 +161,47 @@ void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ){ // } void MultiDomainRMSD::extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& direction ) const { - std::vector mypos, mydir; - for(unsigned i=0;iextractAtomicDisplacement( mypos, anflag, mydir ); - // Extract the direction - n=0; for(unsigned j=blocks[i];j mypos, mydir; + for(unsigned i=0; iextractAtomicDisplacement( mypos, anflag, mydir ); + // Extract the direction + n=0; for(unsigned j=blocks[i]; j& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { - double totd=0.; std::vector tvecs; std::vector mypos; mypack.clear(); - MultiValue tvals( 1, mypack.getNumberOfDerivatives() ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); - for(unsigned i=0;isetupPCAStorage( tder ); - if( tder.centeredpos.size()>0 ){ - for(unsigned p=0;p<3;++p) for(unsigned q=0;q<3;++q) tder.DRotDPos(p,q).resize( mypos.size() ); + double totd=0.; std::vector tvecs; std::vector mypos; mypack.clear(); + MultiValue tvals( 1, mypack.getNumberOfDerivatives() ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); + for(unsigned i=0; isetupPCAStorage( tder ); + if( tder.centeredpos.size()>0 ) { + for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) tder.DRotDPos(p,q).resize( mypos.size() ); + } + // Extract information from storage pack and put in local pack + if( tder.centeredpos.size()>0 ) tder.rot[0]=mypack.rot[i]; + unsigned n=0; + for(unsigned j=blocks[i]; j0 ) { + tder.centeredpos[n]=mypack.centeredpos[j]; + for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) tder.DRotDPos(p,q)[n]=mypack.DRotDPos(p,q)[j]; } - // Extract information from storage pack and put in local pack - if( tder.centeredpos.size()>0 ) tder.rot[0]=mypack.rot[i]; - unsigned n=0; - for(unsigned j=blocks[i];j0 ){ - tder.centeredpos[n]=mypack.centeredpos[j]; - for(unsigned p=0;p<3;++p) for(unsigned q=0;q<3;++q) tder.DRotDPos(p,q)[n]=mypack.DRotDPos(p,q)[j]; - } - n++; - } - for(unsigned k=n;kprojectAtomicDisplacementOnVector( tvecs, mypos, tder ); - - // And derivatives - mypack.copyScaledDerivatives( 0, weights[i], tvals ); + n++; + } + for(unsigned k=n; kprojectAtomicDisplacementOnVector( tvecs, mypos, tder ); + + // And derivatives + mypack.copyScaledDerivatives( 0, weights[i], tvals ); } if( !mypack.updateComplete() ) mypack.updateDynamicLists(); diff --git a/src/reference/MultiDomainRMSD.h b/src/reference/MultiDomainRMSD.h index ed2e5ad306..524f42f42b 100644 --- a/src/reference/MultiDomainRMSD.h +++ b/src/reference/MultiDomainRMSD.h @@ -51,8 +51,8 @@ class MultiDomainRMSD : public ReferenceAtoms { /// bool pcaIsEnabledForThisReference(); void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& direction ) const ; - double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; - void setupPCAStorage( ReferenceValuePack& mypack ); + double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; + void setupPCAStorage( ReferenceValuePack& mypack ); }; } diff --git a/src/reference/MultiReferenceBase.cpp b/src/reference/MultiReferenceBase.cpp index bdbe148d01..3468d1c137 100644 --- a/src/reference/MultiReferenceBase.cpp +++ b/src/reference/MultiReferenceBase.cpp @@ -26,25 +26,25 @@ namespace PLMD { MultiReferenceBase::MultiReferenceBase( const std::string& type, const bool& checksoff ): -wasSet(false), -skipchecks(checksoff), -mtype(type) + wasSet(false), + skipchecks(checksoff), + mtype(type) { if(checksoff) plumed_assert( mtype.length()==0 ); } -MultiReferenceBase::~MultiReferenceBase(){ - for(unsigned i=0;i( mtype, mypdb ); // Save everything @@ -55,11 +55,11 @@ void MultiReferenceBase::readFrame( PDB& mypdb ){ mymsd->checkRead(); } -void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector& atoms, std::vector& args ){ +void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector& atoms, std::vector& args ) { plumed_assert( atoms.size()==0 && args.size()==0 ); - for(unsigned i=0;igetAtomRequests( atoms ); - frames[i]->getArgumentRequests( args ); + for(unsigned i=0; igetAtomRequests( atoms ); + frames[i]->getArgumentRequests( args ); } } @@ -70,7 +70,7 @@ void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector // } // } -void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ){ +void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ) { // Create a reference configuration of the appropriate type ReferenceConfiguration* mymsd=metricRegister().create( frameToCopy->getName() ); // Copy names of arguments and and indexes @@ -80,25 +80,25 @@ void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ){ // Copy weight mymsd->setWeight( frameToCopy->getWeight() ); // Easy bit - copy the frame - frames.push_back( mymsd ); + frames.push_back( mymsd ); // This resizes the low dim array resizeRestOfFrame(); } -void MultiReferenceBase::setWeights( const std::vector& weights ){ - plumed_assert( weights.size()==frames.size() ); - for(unsigned i=0;isetWeight( weights[i] ); +void MultiReferenceBase::setWeights( const std::vector& weights ) { + plumed_assert( weights.size()==frames.size() ); + for(unsigned i=0; isetWeight( weights[i] ); } -void MultiReferenceBase::calculateAllDistances( const Pbc& pbc, const std::vector & vals, Communicator& comm, Matrix& distances, const bool& squared ){ +void MultiReferenceBase::calculateAllDistances( const Pbc& pbc, const std::vector & vals, Communicator& comm, Matrix& distances, const bool& squared ) { distances=0.0; - unsigned k=0, size=comm.Get_size(), rank=comm.Get_rank(); - for(unsigned i=1;i frames; /// Read something from the last frame template - void parse(const std::string& key, T& val ); + void parse(const std::string& key, T& val ); public: MultiReferenceBase( const std::string& type, const bool& checksoff ); /// Destructor deletes all polymorphic pointers virtual ~MultiReferenceBase(); /// Delete all the data in the reference object void clearFrames(); - virtual void clearRestOfData(){}; + virtual void clearRestOfData() {}; /// Read a frame from the input - void readFrame( PDB& pdb ); + void readFrame( PDB& pdb ); /// Find what is required of us from the reference frames void getAtomAndArgumentRequirements( std::vector& atoms, std::vector& args ); /// Finish setup of frames // void setNumberOfAtomsAndArguments( const unsigned& natoms, const unsigned& nargs ); /// Do additional reading required by derived class - virtual void readRestOfFrame(){} + virtual void readRestOfFrame() {} /// Do additional resizing required by derived class - virtual void resizeRestOfFrame(){} + virtual void resizeRestOfFrame() {} /// Return the size of the frames vector - unsigned getNumberOfReferenceFrames() const ; + unsigned getNumberOfReferenceFrames() const ; /// Calculate the distance from one of the reference points double calcDistanceFromConfiguration( const unsigned& ifunc, const std::vector& pos, const Pbc& pbc, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const ; @@ -68,7 +68,7 @@ class MultiReferenceBase { /// Return a reference to all the reference frames std::vector& getReferenceConfigurations(); /// Copy a reference configuration into the multi reference object - void copyFrame( ReferenceConfiguration* frameToCopy ); + void copyFrame( ReferenceConfiguration* frameToCopy ); /// Set the weight of the ith frame void setWeights( const std::vector& ww ); /// Retrieve the weight of one of the frames @@ -78,37 +78,37 @@ class MultiReferenceBase { }; template -void MultiReferenceBase::parse(const std::string& key, T& val ){ +void MultiReferenceBase::parse(const std::string& key, T& val ) { frames[frames.size()-1]->parse(key,val); } inline double MultiReferenceBase::calcDistanceFromConfiguration( const unsigned& ifunc, const std::vector& pos, const Pbc& pbc, - const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { - return frames[ifunc]->calculate( pos, pbc, arg, myder, squared ); + const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { + return frames[ifunc]->calculate( pos, pbc, arg, myder, squared ); } inline unsigned MultiReferenceBase::getNumberOfReferenceFrames() const { - return frames.size(); + return frames.size(); } inline -double MultiReferenceBase::getWeight( const unsigned& ifram ) const { +double MultiReferenceBase::getWeight( const unsigned& ifram ) const { plumed_dbg_assert( iframgetWeight(); } inline -ReferenceConfiguration* MultiReferenceBase::getFrame( const unsigned& iframe ){ - plumed_dbg_assert( iframe& MultiReferenceBase::getReferenceConfigurations(){ +std::vector& MultiReferenceBase::getReferenceConfigurations() { return frames; -} +} } #endif diff --git a/src/reference/NormalizedEuclideanDistance.cpp b/src/reference/NormalizedEuclideanDistance.cpp index 0fa8eb7547..9b4d14a321 100644 --- a/src/reference/NormalizedEuclideanDistance.cpp +++ b/src/reference/NormalizedEuclideanDistance.cpp @@ -32,8 +32,8 @@ class NormalizedEuclideanDistance : public ArgumentOnlyDistance { PLUMED_REGISTER_METRIC(NormalizedEuclideanDistance,"NORM-EUCLIDEAN") NormalizedEuclideanDistance::NormalizedEuclideanDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ArgumentOnlyDistance(ro) + ReferenceConfiguration(ro), + ArgumentOnlyDistance(ro) { hasweights=true; } diff --git a/src/reference/OptimalRMSD.cpp b/src/reference/OptimalRMSD.cpp index 6d3ca828a7..dc4d7f31b4 100644 --- a/src/reference/OptimalRMSD.cpp +++ b/src/reference/OptimalRMSD.cpp @@ -24,7 +24,7 @@ #include "tools/Matrix.h" #include "tools/RMSD.h" -namespace PLMD{ +namespace PLMD { class OptimalRMSD : public RMSDBase { private: @@ -34,45 +34,45 @@ class OptimalRMSD : public RMSDBase { explicit OptimalRMSD(const ReferenceConfigurationOptions& ro); void read( const PDB& ); double calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; - bool pcaIsEnabledForThisReference(){ return true; } - void setupRMSDObject(){ myrmsd.clear(); myrmsd.set(getAlign(),getDisplace(),getReferencePositions(),"OPTIMAL"); } - void setupPCAStorage( ReferenceValuePack& mypack ){ - mypack.switchOnPCAOption(); - mypack.centeredpos.resize( getNumberOfAtoms() ); - mypack.displacement.resize( getNumberOfAtoms() ); - mypack.DRotDPos.resize(3,3); mypack.rot.resize(1); + bool pcaIsEnabledForThisReference() { return true; } + void setupRMSDObject() { myrmsd.clear(); myrmsd.set(getAlign(),getDisplace(),getReferencePositions(),"OPTIMAL"); } + void setupPCAStorage( ReferenceValuePack& mypack ) { + mypack.switchOnPCAOption(); + mypack.centeredpos.resize( getNumberOfAtoms() ); + mypack.displacement.resize( getNumberOfAtoms() ); + mypack.DRotDPos.resize(3,3); mypack.rot.resize(1); } - void extractAtomicDisplacement( const std::vector& pos, const bool & anflag, std::vector& direction ) const ; - double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; + void extractAtomicDisplacement( const std::vector& pos, const bool & anflag, std::vector& direction ) const ; + double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; }; PLUMED_REGISTER_METRIC(OptimalRMSD,"OPTIMAL") OptimalRMSD::OptimalRMSD(const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -RMSDBase(ro) + ReferenceConfiguration(ro), + RMSDBase(ro) { fast=ro.usingFastOption(); } -void OptimalRMSD::read( const PDB& pdb ){ - readReference( pdb ); setupRMSDObject(); +void OptimalRMSD::read( const PDB& pdb ) { + readReference( pdb ); setupRMSDObject(); } double OptimalRMSD::calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const { - double d; - if( myder.calcUsingPCAOption() ){ - std::vector centeredreference( getNumberOfAtoms () ); - d=myrmsd.calc_PCAelements(pos,myder.getAtomVector(),myder.rot[0],myder.DRotDPos,myder.getAtomsDisplacementVector(),myder.centeredpos,centeredreference,squared); - unsigned nat = pos.size(); for(unsigned i=0;i(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); - else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + double d; + if( myder.calcUsingPCAOption() ) { + std::vector centeredreference( getNumberOfAtoms () ); + d=myrmsd.calc_PCAelements(pos,myder.getAtomVector(),myder.rot[0],myder.DRotDPos,myder.getAtomsDisplacementVector(),myder.centeredpos,centeredreference,squared); + unsigned nat = pos.size(); for(unsigned i=0; i(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); } else { - if( getAlign()==getDisplace() ) d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); - else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + if( getAlign()==getDisplace() ) d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); } - myder.clear(); for(unsigned i=0;i& pos, con std::vector centeredreference( getNumberOfAtoms() ), centeredpos( getNumberOfAtoms() ), avector( getNumberOfAtoms() ); double d=myrmsd.calc_PCAelements(pos,avector,rot[0],DRotDPos,direction,centeredpos,centeredreference,true); unsigned nat = pos.size(); double scale=1.0; if( anflag ) scale = 1.0 / static_cast( nat ); - for(unsigned i=0;i& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { plumed_dbg_assert( mypack.calcUsingPCAOption() ); double proj=0.0; mypack.clear(); - for(unsigned i=0;i( getNumberOfAtoms() ); - for(unsigned n=0;n& prop, const bool isp ){ +void PointWiseMapping::setPropertyNames( const std::vector& prop, const bool isp ) { property.resize( prop.size() ); ispath=isp; - for(unsigned i=0;i( getFrame( getNumberOfReferenceFrames() - 1 ) ); if( tdir ) plumed_merror("cannot use directions in mapping"); plumed_dbg_assert( property.size()>0 ); std::vector labelvals; - if( !ispath ){ - labelvals.resize( property.size() ); - for(unsigned i=0;i( frames.size() ); + labelvals.resize(1); + labelvals[0]=static_cast( frames.size() ); } - low_dim.push_back( labelvals ); + low_dim.push_back( labelvals ); plumed_dbg_assert( low_dim.size()==getNumberOfReferenceFrames() ); } -void PointWiseMapping::clearRestOfData(){ +void PointWiseMapping::clearRestOfData() { low_dim.resize(0); -} +} -void PointWiseMapping::resizeRestOfFrame(){ +void PointWiseMapping::resizeRestOfFrame() { plumed_dbg_assert( property.size()>0 ); std::vector labelvals( property.size() ); low_dim.push_back( labelvals ); plumed_dbg_assert( low_dim.size()==getNumberOfReferenceFrames() ); } -void PointWiseMapping::duplicateFrameList(){ +void PointWiseMapping::duplicateFrameList() { unsigned nframes=frames.size(); - for(unsigned i=0;igetWeight(), property[0].c_str(), low_dim[i][0] ); - for(unsigned j=1;jprint( afile, fmt, lunits ); + for(unsigned i=0; igetWeight(), property[0].c_str(), low_dim[i][0] ); + for(unsigned j=1; jprint( afile, fmt, lunits ); } -} +} } diff --git a/src/reference/PointWiseMapping.h b/src/reference/PointWiseMapping.h index 1345e62fc4..a530d3492b 100644 --- a/src/reference/PointWiseMapping.h +++ b/src/reference/PointWiseMapping.h @@ -35,7 +35,7 @@ class PointWiseMapping : public MultiReferenceBase { /// The names of the projection coordinates std::vector property; /// These are where the reference configurations should be projected - std::vector< std::vector > low_dim; + std::vector< std::vector > low_dim; public: PointWiseMapping( const std::string& type, const bool& checksoff ); /// Set the names of the low dimensional properties @@ -44,11 +44,11 @@ class PointWiseMapping : public MultiReferenceBase { bool mappingNeedsSetup() const; /// Delete the low dimensional projections void clearRestOfData(); -/// Read in the data from a file +/// Read in the data from a file void readRestOfFrame(); /// Resize everything else from a file void resizeRestOfFrame(); -/// Make a second copy of the frame list +/// Make a second copy of the frame list void duplicateFrameList(); /// Get the number of points we are mapping into the lower dimensional space unsigned getNumberOfMappedPoints() const ; @@ -71,7 +71,7 @@ class PointWiseMapping : public MultiReferenceBase { /// Get a pointer to the matrix of pairwise distances Matrix& modifyDmat(); /// Print out the low dimensional mapping - void print( const std::string& method, const double & time, OFile& afile, + void print( const std::string& method, const double & time, OFile& afile, const std::string& fmt, const double& lunits ); /// Get the low dimensional embedding coordinate double getProjectionCoordinate( const unsigned& iframe, const unsigned& jcoord ) const ; @@ -86,7 +86,7 @@ bool PointWiseMapping::mappingNeedsSetup() const { } inline -void PointWiseMapping::copyFrameDerivatives( const unsigned& from, const unsigned& to ){ +void PointWiseMapping::copyFrameDerivatives( const unsigned& from, const unsigned& to ) { plumed_dbg_assert( to>=frames.size()/2 && fromcopyDerivatives( frames[from] ); } @@ -117,7 +117,7 @@ double PointWiseMapping::getPropertyValue( const unsigned& iframe, const unsigne // Vector PointWiseMapping::getAtomDerivatives( const unsigned& iframe, const unsigned& jatom ){ // return frames[iframe]->getAtomDerivative(jatom); // } -// +// // inline // bool PointWiseMapping::getVirial( const unsigned& iframe, Tensor& vir ){ // return frames[iframe]->getVirial( vir ); @@ -129,7 +129,7 @@ double PointWiseMapping::getPropertyValue( const unsigned& iframe, const unsigne // } inline -Matrix& PointWiseMapping::modifyDmat(){ +Matrix& PointWiseMapping::modifyDmat() { if( dmat.nrows()!=frames.size() || dmat.ncols()!=frames.size() ) dmat.resize( frames.size(), frames.size() ); return dmat; } @@ -141,10 +141,10 @@ double PointWiseMapping::getProjectionCoordinate( const unsigned& iframe, const } inline -void PointWiseMapping::setProjectionCoordinate( const unsigned& iframe, const unsigned& jcoord, const double& coord ){ +void PointWiseMapping::setProjectionCoordinate( const unsigned& iframe, const unsigned& jcoord, const double& coord ) { plumed_dbg_assert( iframe& pos, ReferenceValuePack& myder, const bool& squared ) const { -// clearDerivatives(); +// clearDerivatives(); return calc( pos, myder, squared ); -} +} double RMSDBase::calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( pos.size()==getNumberOfAtoms() ); diff --git a/src/reference/RMSDBase.h b/src/reference/RMSDBase.h index 9a59d1f1c8..e1fb621e26 100644 --- a/src/reference/RMSDBase.h +++ b/src/reference/RMSDBase.h @@ -36,7 +36,7 @@ class RMSDBase : public SingleDomainRMSD { public: explicit RMSDBase( const ReferenceConfigurationOptions& ro ); double calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const; - double calculate( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; + double calculate( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; virtual double calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const=0; }; diff --git a/src/reference/ReferenceArguments.cpp b/src/reference/ReferenceArguments.cpp index 20c6cb5b5c..e051f1d7b2 100644 --- a/src/reference/ReferenceArguments.cpp +++ b/src/reference/ReferenceArguments.cpp @@ -27,204 +27,204 @@ namespace PLMD { ReferenceArguments::ReferenceArguments( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -hasweights(false), -hasmetric(false) + ReferenceConfiguration(ro), + hasweights(false), + hasmetric(false) { } -void ReferenceArguments::readArgumentsFromPDB( const PDB& pdb ){ +void ReferenceArguments::readArgumentsFromPDB( const PDB& pdb ) { ReferenceAtoms* aref=dynamic_cast( this ); if( !aref ) parseVector( "ARG", arg_names ); else parseVector( "ARG", arg_names, true ); reference_args.resize( arg_names.size() ); - for(unsigned i=0;i& arg_vals ){ - reference_args.resize( arg_vals.size() ); - arg_names.resize( arg_vals.size() ); +void ReferenceArguments::setArgumentNames( const std::vector& arg_vals ) { + reference_args.resize( arg_vals.size() ); + arg_names.resize( arg_vals.size() ); arg_der_index.resize( arg_vals.size() ); - for(unsigned i=0;i& arg_vals, const std::vector& sigma ){ +void ReferenceArguments::setReferenceArguments( const std::vector& arg_vals, const std::vector& sigma ) { moveReferenceArguments( arg_vals ); - - if( hasmetric ){ - unsigned k=0; - for(unsigned i=0;i& arg_vals ){ +void ReferenceArguments::moveReferenceArguments( const std::vector& arg_vals ) { plumed_dbg_assert( reference_args.size()==arg_vals.size() ); - for(unsigned i=0;i& argout, bool disable_checks ){ +void ReferenceArguments::getArgumentRequests( std::vector& argout, bool disable_checks ) { arg_der_index.resize( arg_names.size() ); - if( argout.size()==0 ){ - for(unsigned i=0;i0 ){ - ofile.printf("REMARK ARG=%s", arg_names[0].c_str() ); - for(unsigned i=1;i0 ) { + ofile.printf("REMARK ARG=%s", arg_names[0].c_str() ); + for(unsigned i=1; i& ReferenceArguments::getReferenceMetric(){ - if( hasmetric ){ - unsigned ntot=(reference_args.size() / 2 )*(reference_args.size()+1); - if( trig_metric.size()!=ntot ) trig_metric.resize( ntot ); - unsigned k=0; - for(unsigned i=0;i& ReferenceArguments::getReferenceMetric() { + if( hasmetric ) { + unsigned ntot=(reference_args.size() / 2 )*(reference_args.size()+1); + if( trig_metric.size()!=ntot ) trig_metric.resize( ntot ); + unsigned k=0; + for(unsigned i=0; i & vals, const std::vector& arg, - ReferenceValuePack& myder, const bool& squared ) const { +double ReferenceArguments::calculateArgumentDistance( const std::vector & vals, const std::vector& arg, + ReferenceValuePack& myder, const bool& squared ) const { double r=0; std::vector arg_ders( vals.size() ); - if( hasmetric ){ - for(unsigned i=0;idifference( reference_args[i], arg[ik] ); - for(unsigned j=0;jdifference( reference_args[j], arg[jk] ); - - arg_ders[ ik ]+=2.0*metric(i,j)*dp_j; // Factor of two for off diagonal terms as you have terms from ij and ji - r+=dp_i*dp_j*metric(i,j); - } + if( hasmetric ) { + for(unsigned i=0; idifference( reference_args[i], arg[ik] ); + for(unsigned j=0; jdifference( reference_args[j], arg[jk] ); + + arg_ders[ ik ]+=2.0*metric(i,j)*dp_j; // Factor of two for off diagonal terms as you have terms from ij and ji + r+=dp_i*dp_j*metric(i,j); } + } } else { - for(unsigned i=0;idifference( reference_args[i], arg[ik] ); - r+=weights[i]*dp_i*dp_i; arg_ders[ik]=2.0*weights[i]*dp_i; - } + for(unsigned i=0; idifference( reference_args[i], arg[ik] ); + r+=weights[i]*dp_i*dp_i; arg_ders[ik]=2.0*weights[i]*dp_i; + } } - if(!squared){ - r=sqrt(r); double ir=1.0/(2.0*r); - for(unsigned i=0;i& vals, const std::vector& arg, std::vector& dirout ) const { - if( hasmetric ){ - plumed_error(); + if( hasmetric ) { + plumed_error(); } else { - for(unsigned j=0;jdifference( reference_args[j], arg[jk] ); - } + for(unsigned j=0; jdifference( reference_args[j], arg[jk] ); + } } } double ReferenceArguments::projectArgDisplacementOnVector( const std::vector& eigv, const std::vector& vals, const std::vector& arg, ReferenceValuePack& mypack ) const { - if( hasmetric ){ - plumed_error(); + if( hasmetric ) { + plumed_error(); } else { - double proj=0; - for(unsigned j=0;jdifference( reference_args[j], arg[jk] ); - mypack.setArgumentDerivatives( jk, eigv[j]*sqrtweight[j] ); - } - return proj; + double proj=0; + for(unsigned j=0; jdifference( reference_args[j], arg[jk] ); + mypack.setArgumentDerivatives( jk, eigv[j]*sqrtweight[j] ); + } + return proj; } } -void ReferenceArguments::displaceReferenceArguments( const double& weight, const std::vector& displace ){ +void ReferenceArguments::displaceReferenceArguments( const double& weight, const std::vector& displace ) { plumed_dbg_assert( displace.size()==getNumberOfReferenceArguments() ); - for(unsigned i=0;i weights, sqrtweight; @@ -60,7 +60,7 @@ friend class ReferenceConfiguration; protected: /// Are we reading weights from input bool hasweights; -/// Are we calculating a Malanobius distance +/// Are we calculating a Malanobius distance bool hasmetric; /// Read in the atoms from the pdb file void readArgumentsFromPDB( const PDB& pdb ); @@ -70,7 +70,7 @@ friend class ReferenceConfiguration; explicit ReferenceArguments( const ReferenceConfigurationOptions& ro ); /// Get the number of reference arguments unsigned getNumberOfReferenceArguments() const ; -/// Get the arguments required +/// Get the arguments required void getArgumentRequests( std::vector&, bool disable_checks=false ); /// Set the names of the arguments void setArgumentNames( const std::vector& arg_vals ); @@ -110,7 +110,7 @@ const std::vector& ReferenceArguments::getReferenceArguments() const { } inline -const std::vector& ReferenceArguments::getArgumentNames(){ +const std::vector& ReferenceArguments::getArgumentNames() { return arg_names; } diff --git a/src/reference/ReferenceAtoms.cpp b/src/reference/ReferenceAtoms.cpp index e2d2ad05ed..7120786f3c 100644 --- a/src/reference/ReferenceAtoms.cpp +++ b/src/reference/ReferenceAtoms.cpp @@ -26,100 +26,100 @@ namespace PLMD { ReferenceAtoms::ReferenceAtoms( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -checks_were_disabled(false) + ReferenceConfiguration(ro), + checks_were_disabled(false) { } -void ReferenceAtoms::readAtomsFromPDB( const PDB& pdb, const bool allowblocks ){ - if( !allowblocks && pdb.getNumberOfAtomBlocks()!=1 ) error("found multi-atom-block pdb format but expecting only one block of atoms"); +void ReferenceAtoms::readAtomsFromPDB( const PDB& pdb, const bool allowblocks ) { + if( !allowblocks && pdb.getNumberOfAtomBlocks()!=1 ) error("found multi-atom-block pdb format but expecting only one block of atoms"); - for(unsigned i=0;i& numbers ){ +void ReferenceAtoms::setAtomNumbers( const std::vector& numbers ) { reference_atoms.resize( numbers.size() ); align.resize( numbers.size() ); displace.resize( numbers.size() ); atom_der_index.resize( numbers.size() ); indices.resize( numbers.size() ); - for(unsigned i=0;i& numbers ){ +bool ReferenceAtoms::parseAtomList( const std::string& key, std::vector& numbers ) { plumed_assert( numbers.size()==0 ); - std::vector strings; + std::vector strings; if( !parseVector(key,strings,true) ) return false; - Tools::interpretRanges(strings); - - numbers.resize( strings.size() ); - for(unsigned i=0;i& numbers, bool disable_checks ){ +void ReferenceAtoms::getAtomRequests( std::vector& numbers, bool disable_checks ) { singleDomainRequests(numbers,disable_checks); } -void ReferenceAtoms::singleDomainRequests( std::vector& numbers, bool disable_checks ){ +void ReferenceAtoms::singleDomainRequests( std::vector& numbers, bool disable_checks ) { checks_were_disabled=disable_checks; atom_der_index.resize( indices.size() ); - if( numbers.size()==0 ){ - for(unsigned i=0;i& dir ){ +void ReferenceAtoms::displaceReferenceAtoms( const double& weight, const std::vector& dir ) { plumed_dbg_assert( dir.size()==reference_atoms.size() ); - for(unsigned i=0;i& atomnumbers ); /// Read a list of atoms from the pdb input file - bool parseAtomList( const std::string& , std::vector& ); + bool parseAtomList( const std::string&, std::vector& ); /// Get the vector of alignment weights const std::vector & getAlign() const ; /// Get the vector of displacement weights const std::vector & getDisplace() const ; /// Get the position of the ith atom - Vector getReferencePosition( const unsigned& iatom ) const ; + Vector getReferencePosition( const unsigned& iatom ) const ; /// Add derivatives to iatom th atom in list // void addAtomicDerivatives( const unsigned& , const Vector& ); /// Get the atomic derivatives on the ith atom in the list @@ -105,14 +105,14 @@ friend class ReferenceConfiguration; /// This returns how many atoms there should be unsigned getNumberOfAtoms() const ; /// Displace the positions of the reference atoms a bit - void displaceReferenceAtoms( const double& weight, const std::vector& dir ); + void displaceReferenceAtoms( const double& weight, const std::vector& dir ); /// Extract a displacement from a position in space virtual void extractAtomicDisplacement( const std::vector& pos, const bool & anflag, std::vector& direction ) const { - plumed_error(); + plumed_error(); } /// Project the displacement on a vector virtual double projectAtomicDisplacementOnVector( const std::vector& eigv, const std::vector& pos, ReferenceValuePack& mypack ) const { - plumed_error(); return 1; + plumed_error(); return 1; } }; @@ -171,7 +171,7 @@ const std::vector & ReferenceAtoms::getReferencePositions() const { // } inline -const std::vector& ReferenceAtoms::getAbsoluteIndexes(){ +const std::vector& ReferenceAtoms::getAbsoluteIndexes() { return indices; } diff --git a/src/reference/ReferenceConfiguration.cpp b/src/reference/ReferenceConfiguration.cpp index 1df1bc694d..61d554a205 100644 --- a/src/reference/ReferenceConfiguration.cpp +++ b/src/reference/ReferenceConfiguration.cpp @@ -27,10 +27,10 @@ #include "tools/OFile.h" #include "tools/PDB.h" -namespace PLMD{ +namespace PLMD { ReferenceConfigurationOptions::ReferenceConfigurationOptions( const std::string& type ): -tt(type) + tt(type) { } @@ -41,11 +41,11 @@ bool ReferenceConfigurationOptions::usingFastOption() const { std::string ReferenceConfigurationOptions::getMultiRMSDType() const { plumed_assert( tt.find("MULTI-")!=std::string::npos ); std::size_t dot=tt.find_first_of("MULTI-"); - return tt.substr(dot+6); + return tt.substr(dot+6); } ReferenceConfiguration::ReferenceConfiguration( const ReferenceConfigurationOptions& ro ): -name(ro.tt) + name(ro.tt) // arg_ders(0), // atom_ders(0) { @@ -60,11 +60,11 @@ std::string ReferenceConfiguration::getName() const { return name; } -void ReferenceConfiguration::set( const PDB& pdb ){ - line=pdb.getRemark(); - std::string ignore; - if( parse("TYPE",ignore,true) ){ - if(ignore!=name) error("mismatch for name"); +void ReferenceConfiguration::set( const PDB& pdb ) { + line=pdb.getRemark(); + std::string ignore; + if( parse("TYPE",ignore,true) ) { + if(ignore!=name) error("mismatch for name"); } if( !parse("WEIGHT",weight,true) ) weight=1.0; read( pdb ); @@ -83,66 +83,66 @@ void ReferenceConfiguration::set( const PDB& pdb ){ // return virialWasSet; // } -void ReferenceConfiguration::parseFlag( const std::string&key, bool&t ){ +void ReferenceConfiguration::parseFlag( const std::string&key, bool&t ) { Tools::parseFlag(line,key,t); } -void ReferenceConfiguration::error(const std::string& msg){ +void ReferenceConfiguration::error(const std::string& msg) { plumed_merror("error reading reference configuration of type " + name + " : " + msg ); } -void ReferenceConfiguration::setNamesAndAtomNumbers( const std::vector& numbers, const std::vector& arg ){ - ReferenceAtoms* atoms=dynamic_cast( this ); - if(!atoms){ - plumed_massert( numbers.size()==0, "expecting no atomic positions"); - //setNumberOfAtoms( 0 ); - } else { - atoms->setAtomNumbers( numbers ); - // setNumberOfAtoms( numbers.size() ); +void ReferenceConfiguration::setNamesAndAtomNumbers( const std::vector& numbers, const std::vector& arg ) { + ReferenceAtoms* atoms=dynamic_cast( this ); + if(!atoms) { + plumed_massert( numbers.size()==0, "expecting no atomic positions"); + //setNumberOfAtoms( 0 ); + } else { + atoms->setAtomNumbers( numbers ); + // setNumberOfAtoms( numbers.size() ); } // Copy the arguments to the reference ReferenceArguments* args=dynamic_cast( this ); - if(!args){ - plumed_massert( arg.size()==0, "expecting no arguments"); - // setNumberOfArguments(0); + if(!args) { + plumed_massert( arg.size()==0, "expecting no arguments"); + // setNumberOfArguments(0); } else { - args->setArgumentNames( arg ); - // setNumberOfArguments( arg.size() ); + args->setArgumentNames( arg ); + // setNumberOfArguments( arg.size() ); } } -void ReferenceConfiguration::setReferenceConfig( const std::vector& pos, const std::vector& arg, const std::vector& metric ){ +void ReferenceConfiguration::setReferenceConfig( const std::vector& pos, const std::vector& arg, const std::vector& metric ) { // plumed_dbg_assert( pos.size()==atom_ders.size() && arg.size()==arg_ders.size() ); // Copy the atomic positions to the reference ReferenceAtoms* atoms=dynamic_cast( this ); - if(!atoms){ - plumed_massert( pos.size()==0, "expecting no atomic positions"); - } else { - std::vector align_in( pos.size(), 1.0 ), displace_in( pos.size(), 1.0 ); - atoms->setReferenceAtoms( pos, align_in, displace_in ); + if(!atoms) { + plumed_massert( pos.size()==0, "expecting no atomic positions"); + } else { + std::vector align_in( pos.size(), 1.0 ), displace_in( pos.size(), 1.0 ); + atoms->setReferenceAtoms( pos, align_in, displace_in ); } // Copy the arguments to the reference ReferenceArguments* args=dynamic_cast( this ); - if(!args){ - plumed_massert( arg.size()==0 && metric.size()==0, "expecting no arguments"); + if(!args) { + plumed_massert( arg.size()==0 && metric.size()==0, "expecting no arguments"); } else { - args->setReferenceArguments( arg, metric ); + args->setReferenceArguments( arg, metric ); } } -void ReferenceConfiguration::checkRead(){ - if(!line.empty()){ +void ReferenceConfiguration::checkRead() { + if(!line.empty()) { std::string msg="cannot understand the following words from the input line : "; - for(unsigned i=0;i& pos, const Pbc& pbc, const std::vector& vals, - ReferenceValuePack& myder, const bool& squared ) const { +double ReferenceConfiguration::calculate( const std::vector& pos, const Pbc& pbc, const std::vector& vals, + ReferenceValuePack& myder, const bool& squared ) const { // clearDerivatives(); std::vector tmparg( vals.size() ); - for(unsigned i=0;iget(); + for(unsigned i=0; iget(); return calc( pos, pbc, vals, tmparg, myder, squared ); } @@ -153,12 +153,12 @@ double ReferenceConfiguration::calculate( const std::vector& pos, const // virialWasSet=ref->virialWasSet; virial=ref->virial; // } -void ReferenceConfiguration::print( OFile& ofile, const double& time, const double& weight, const double& lunits, const double& old_norm ){ +void ReferenceConfiguration::print( OFile& ofile, const double& time, const double& weight, const double& lunits, const double& old_norm ) { ofile.printf("REMARK TIME=%f LOG_WEIGHT=%f OLD_NORM=%f\n",time, weight, old_norm ); print( ofile, "%f", lunits ); // HARD CODED FORMAT HERE AS THIS IS FOR CHECKPOINT FILE } -void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt, const double& lunits ){ +void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt, const double& lunits ) { ofile.printf("REMARK TYPE=%s\n",getName().c_str() ); ReferenceArguments* args=dynamic_cast(this); if(args) args->printArguments( ofile, fmt ); @@ -167,61 +167,61 @@ void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt, const ofile.printf("END\n"); } -void ReferenceConfiguration::displaceReferenceConfiguration( const double& weight, Direction& dir ){ +void ReferenceConfiguration::displaceReferenceConfiguration( const double& weight, Direction& dir ) { ReferenceArguments* args=dynamic_cast(this); if( args ) args->displaceReferenceArguments( weight, dir.getReferenceArguments() ); ReferenceAtoms* atoms=dynamic_cast(this); if( atoms ) atoms->displaceReferenceAtoms( weight, dir.getReferencePositions() ); } -void ReferenceConfiguration::extractDisplacementVector( const std::vector& pos, const std::vector& vals, - const std::vector& arg, const bool & anflag, const bool& nflag, - Direction& mydir ) const { +void ReferenceConfiguration::extractDisplacementVector( const std::vector& pos, const std::vector& vals, + const std::vector& arg, const bool & anflag, const bool& nflag, + Direction& mydir ) const { const ReferenceAtoms* atoms=dynamic_cast( this ); if( atoms ) atoms->extractAtomicDisplacement( pos, anflag, mydir.reference_atoms ); const ReferenceArguments* args=dynamic_cast( this ); if( args ) args->extractArgumentDisplacement( vals, arg, mydir.reference_args ); // Normalize direction if required - if( nflag ){ - // Calculate length of vector - double tmp, norm=0; - for(unsigned i=0;i& pos, - const std::vector& vals, const std::vector& arg, - ReferenceValuePack& mypack ) const { + const std::vector& vals, const std::vector& arg, + ReferenceValuePack& mypack ) const { double proj=0; const ReferenceAtoms* atoms=dynamic_cast( this ); if( atoms ) proj += atoms->projectAtomicDisplacementOnVector( mydir.getReferencePositions(), pos, mypack ); const ReferenceArguments* args=dynamic_cast( this ); if( args ) proj += args->projectArgDisplacementOnVector( mydir.getReferenceArguments(), vals, arg, mypack ); return proj; -} +} -double distance( const Pbc& pbc, const std::vector & vals, ReferenceConfiguration* ref1, ReferenceConfiguration* ref2, const bool& squared ){ +double distance( const Pbc& pbc, const std::vector & vals, ReferenceConfiguration* ref1, ReferenceConfiguration* ref2, const bool& squared ) { unsigned nder; if( ref1->getReferencePositions().size()>0 ) nder=ref1->getReferenceArguments().size() + 3*ref1->getReferencePositions().size() + 9; else nder=ref1->getReferenceArguments().size(); - MultiValue myvals( 1, nder ); ReferenceValuePack myder( ref1->getReferenceArguments().size() , ref1->getReferencePositions().size() , myvals ); + MultiValue myvals( 1, nder ); ReferenceValuePack myder( ref1->getReferenceArguments().size(), ref1->getReferencePositions().size(), myvals ); double dist1=ref1->calc( ref2->getReferencePositions(), pbc, vals, ref2->getReferenceArguments(), myder, squared ); #ifndef NDEBUG // Check that A - B = B - A double dist2=ref2->calc( ref1->getReferencePositions(), pbc, vals, ref1->getReferenceArguments(), myder, squared ); plumed_dbg_assert( fabs(dist1-dist2) & vals, ReferenceConfiguration*, ReferenceConfiguration*, const bool& squared ); + friend class SingleDomainRMSD; + friend double distance( const Pbc& pbc, const std::vector & vals, ReferenceConfiguration*, ReferenceConfiguration*, const bool& squared ); private: /// The name of this particular config std::string name; @@ -81,14 +81,14 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere protected: /// Derivatives wrt to the arguments // std::vector arg_ders; -/// The virial contribution has to be stored +/// The virial contribution has to be stored // bool virialWasSet; // Tensor virial; /// Derivatives wrt to the atoms // std::vector atom_ders; /// Crash with an error void error(const std::string& msg); -/// Clear the derivatives +/// Clear the derivatives // void clearDerivatives(); public: explicit ReferenceConfiguration( const ReferenceConfigurationOptions& ro ); @@ -100,16 +100,16 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere virtual unsigned getNumberOfReferencePositions() const ; virtual unsigned getNumberOfReferenceArguments() const ; /// Retrieve the atoms that are required for this guy - virtual void getAtomRequests( std::vector&, bool disable_checks=false ){} + virtual void getAtomRequests( std::vector&, bool disable_checks=false ) {} /// Retrieve the arguments that are required for this guy - virtual void getArgumentRequests( std::vector&, bool disable_checks=false ){} + virtual void getArgumentRequests( std::vector&, bool disable_checks=false ) {} /// Set the final number of arguments // virtual void setNumberOfArguments( const unsigned& ); /// Set the final number of atoms // virtual void setNumberOfAtoms( const unsigned& ); -/// Set the reference configuration using a PDB +/// Set the reference configuration using a PDB virtual void set( const PDB& ); -/// Do all local business for setting the configuration +/// Do all local business for setting the configuration virtual void read( const PDB& )=0; /// Set the weight for this frame void setWeight( const double& ww ); @@ -118,16 +118,16 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere /// Calculate the distance from the reference configuration double calculate( const std::vector& pos, const Pbc& pbc, const std::vector& vals, ReferenceValuePack& myder, const bool& squared=false ) const ; /// Calculate the distance from the reference configuration - virtual double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& args, + virtual double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& args, ReferenceValuePack& myder, const bool& squared ) const=0; // /// Return the derivative wrt to the ith atom // Vector getAtomDerivative( const unsigned& ) const ; // /// Return the derivative wrt to the ith argument // double getArgumentDerivative( const unsigned& ) const ; /// Return the derivatives of the distance wrt the cell vectors. This returns false -/// for everything other than DRMSD as these sort of calculations have to be done -/// separately when you use RMSD -// bool getVirial( Tensor& virout ) const ; +/// for everything other than DRMSD as these sort of calculations have to be done +/// separately when you use RMSD +// bool getVirial( Tensor& virout ) const ; /// Parse something from the pdb remarks template bool parse( const std::string&key, T&t, bool ignore_missing=false ); @@ -149,24 +149,24 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere void print( OFile& ofile, const std::string& fmt, const double& lunits ); /// Get one of the referene arguments virtual double getReferenceArgument( const unsigned& i ) const { plumed_error(); return 0.0; } -/// These are overwritten in ReferenceArguments and ReferenceAtoms but are required here +/// These are overwritten in ReferenceArguments and ReferenceAtoms but are required here /// to make PLMD::distance work - virtual const std::vector& getReferencePositions() const ; - virtual const std::vector& getReferenceArguments() const ; + virtual const std::vector& getReferencePositions() const ; + virtual const std::vector& getReferenceArguments() const ; virtual const std::vector& getReferenceMetric(); /// These are overwritten in ReferenceArguments and ReferenceAtoms to make frame copying work virtual const std::vector& getAbsoluteIndexes(); virtual const std::vector& getArgumentNames(); /// Extract a Direction giving you the displacement from some position void extractDisplacementVector( const std::vector& pos, const std::vector& vals, - const std::vector& arg, const bool& anflag, const bool& nflag, + const std::vector& arg, const bool& anflag, const bool& nflag, Direction& mydir ) const ; /// Stuff for pca - virtual bool pcaIsEnabledForThisReference(){ return false; } - double projectDisplacementOnVector( const Direction& mydir, const std::vector& pos, const std::vector& vals, + virtual bool pcaIsEnabledForThisReference() { return false; } + double projectDisplacementOnVector( const Direction& mydir, const std::vector& pos, const std::vector& vals, const std::vector& arg, ReferenceValuePack& mypack ) const ; /// Stuff to setup pca - virtual void setupPCAStorage( ReferenceValuePack& mypack ){ plumed_error(); } + virtual void setupPCAStorage( ReferenceValuePack& mypack ) { plumed_error(); } /// Move the reference configuration by an ammount specified using a Direction void displaceReferenceConfiguration( const double& weight, Direction& dir ); }; @@ -184,7 +184,7 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere // } inline -void ReferenceConfiguration::setWeight( const double& ww ){ +void ReferenceConfiguration::setWeight( const double& ww ) { weight=ww; } @@ -194,21 +194,21 @@ double ReferenceConfiguration::getWeight() const { } template -bool ReferenceConfiguration::parse(const std::string&key, T&t, bool ignore_missing ){ +bool ReferenceConfiguration::parse(const std::string&key, T&t, bool ignore_missing ) { bool found=Tools::parse(line,key,t); - if(!ignore_missing && !found) error(key + " is missing"); + if(!ignore_missing && !found) error(key + " is missing"); return found; } template -bool ReferenceConfiguration::parseVector(const std::string&key,std::vector&t, bool ignore_missing){ +bool ReferenceConfiguration::parseVector(const std::string&key,std::vector&t, bool ignore_missing) { bool found=Tools::parseVector(line,key,t); if(!ignore_missing && !found) error(key + " is missing"); return found; } inline -const std::vector& ReferenceConfiguration::getReferencePositions() const { +const std::vector& ReferenceConfiguration::getReferencePositions() const { return fake_refatoms; } @@ -218,17 +218,17 @@ const std::vector& ReferenceConfiguration::getReferenceArguments() const } inline -const std::vector& ReferenceConfiguration::getReferenceMetric(){ +const std::vector& ReferenceConfiguration::getReferenceMetric() { return fake_metric; } inline -const std::vector& ReferenceConfiguration::getAbsoluteIndexes(){ +const std::vector& ReferenceConfiguration::getAbsoluteIndexes() { return fake_atom_numbers; } inline -const std::vector& ReferenceConfiguration::getArgumentNames(){ +const std::vector& ReferenceConfiguration::getArgumentNames() { return fake_arg_names; } diff --git a/src/reference/ReferenceValuePack.cpp b/src/reference/ReferenceValuePack.cpp index 9fd9fc6f8e..106e1f1487 100644 --- a/src/reference/ReferenceValuePack.cpp +++ b/src/reference/ReferenceValuePack.cpp @@ -24,72 +24,72 @@ namespace PLMD { ReferenceValuePack::ReferenceValuePack( const unsigned& nargs, const unsigned& natoms, MultiValue& vals ): -boxWasSet(false), -numberOfArgs(nargs), -oind_set(false), -myvals(vals), -atom_indices(myvals.getIndices()), -pca(false) + boxWasSet(false), + numberOfArgs(nargs), + oind_set(false), + myvals(vals), + atom_indices(myvals.getIndices()), + pca(false) { - if( atom_indices.size()!=natoms ){ atom_indices.resize( natoms ); myvals.getAtomVector().resize( natoms ); } - if( vals.getNumberOfValues()==1 ){ oind=0; oind_set=true; } + if( atom_indices.size()!=natoms ) { atom_indices.resize( natoms ); myvals.getAtomVector().resize( natoms ); } + if( vals.getNumberOfValues()==1 ) { oind=0; oind_set=true; } } -void ReferenceValuePack::resize( const unsigned& nargs, const unsigned& natoms ){ - numberOfArgs=nargs; atom_indices.resize( natoms ); +void ReferenceValuePack::resize( const unsigned& nargs, const unsigned& natoms ) { + numberOfArgs=nargs; atom_indices.resize( natoms ); myvals.getAtomVector().resize( natoms ); } -void ReferenceValuePack::updateDynamicLists(){ +void ReferenceValuePack::updateDynamicLists() { myvals.emptyActiveMembers(); - for(unsigned i=0;i0 ){ - for(unsigned i=0;i<9;++i){ - myvals.addDerivative( oind, nbase+i, 0.0 ); - myvals.putIndexInActiveArray( nbase+i ); - } - } + if( atom_indices.size()>0 ) { + for(unsigned i=0; i<9; ++i) { + myvals.addDerivative( oind, nbase+i, 0.0 ); + myvals.putIndexInActiveArray( nbase+i ); + } + } myvals.completeUpdate(); } -void ReferenceValuePack::clear(){ +void ReferenceValuePack::clear() { if( !myvals.updateComplete() ) updateDynamicLists(); myvals.clearAll(); boxWasSet=false; } -void ReferenceValuePack::scaleAllDerivatives( const double& scalef ){ +void ReferenceValuePack::scaleAllDerivatives( const double& scalef ) { if( !myvals.updateComplete() ) updateDynamicLists(); - for(unsigned i=0;i& atom_indices; -/// Are we using pca +/// Are we using pca bool pca; /// A vector of vectors to save us some overhead for vector resizes std::vector centeredpos; @@ -79,7 +79,7 @@ friend class OptimalRMSD; void addAtomDerivatives( const unsigned& iatom, const Vector& der ); /// void addBoxDerivatives( const Tensor& vir ); -/// +/// bool updateComplete() const ; /// void updateDynamicLists(); @@ -123,23 +123,23 @@ unsigned ReferenceValuePack::getNumberOfAtoms() const { } inline -void ReferenceValuePack::setAtomIndex( const unsigned& iatom, const unsigned& jindex ){ +void ReferenceValuePack::setAtomIndex( const unsigned& iatom, const unsigned& jindex ) { plumed_dbg_assert( iatom0 ); boxWasSet=true; unsigned nbase = myvals.getNumberOfDerivatives() - 9; - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addDerivative( oind, nbase + 3*i + j , vir(i,j) ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addDerivative( oind, nbase + 3*i + j, vir(i,j) ); } inline -void ReferenceValuePack::setValIndex( const unsigned& ind ){ +void ReferenceValuePack::setValIndex( const unsigned& ind ) { oind=ind; oind_set=true; } @@ -186,7 +186,7 @@ Vector ReferenceValuePack::getAtomDerivative( const unsigned& iatom ) const { Vector tmp; plumed_dbg_assert( oind_set && iatom& ReferenceValuePack::getAtomVector(){ +std::vector& ReferenceValuePack::getAtomVector() { return myvals.getAtomVector(); } inline -std::vector& ReferenceValuePack::getAtomsDisplacementVector(){ +std::vector& ReferenceValuePack::getAtomsDisplacementVector() { return displacement; } diff --git a/src/reference/SimpleRMSD.cpp b/src/reference/SimpleRMSD.cpp index 9b06563edf..4c0d825326 100644 --- a/src/reference/SimpleRMSD.cpp +++ b/src/reference/SimpleRMSD.cpp @@ -23,7 +23,7 @@ #include "MetricRegister.h" #include "tools/RMSD.h" -namespace PLMD{ +namespace PLMD { class SimpleRMSD : public RMSDBase { private: @@ -32,30 +32,30 @@ class SimpleRMSD : public RMSDBase { explicit SimpleRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& ); double calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; - bool pcaIsEnabledForThisReference(){ return true; } - void setupPCAStorage( ReferenceValuePack& mypack ){ - mypack.switchOnPCAOption(); mypack.getAtomsDisplacementVector().resize( getNumberOfAtoms() ); + bool pcaIsEnabledForThisReference() { return true; } + void setupPCAStorage( ReferenceValuePack& mypack ) { + mypack.switchOnPCAOption(); mypack.getAtomsDisplacementVector().resize( getNumberOfAtoms() ); } void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& direction ) const ; - double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; + double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; }; PLUMED_REGISTER_METRIC(SimpleRMSD,"SIMPLE") SimpleRMSD::SimpleRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -RMSDBase( ro ) + ReferenceConfiguration( ro ), + RMSDBase( ro ) { } -void SimpleRMSD::read( const PDB& pdb ){ +void SimpleRMSD::read( const PDB& pdb ) { readReference( pdb ); } double SimpleRMSD::calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const { if( myder.getAtomsDisplacementVector().size()!=pos.size() ) myder.getAtomsDisplacementVector().resize( pos.size() ); double d=myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), myder.getAtomVector(), myder.getAtomsDisplacementVector(), squared ); - myder.clear(); for(unsigned i=0;i& pos, cons std::vector tder( getNumberOfAtoms() ); double d=myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), tder, direction, true ); double scale=1.0; if( anflag ) scale = 1.0 / static_cast( pos.size() ); - for(unsigned i=0;i& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { +double SimpleRMSD::projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { plumed_dbg_assert( mypack.calcUsingPCAOption() ); Vector comder; comder.zero(); - for(unsigned j=0;j& conf, const std::vector& align_in, const std::vector& displace_in ){ - reference_atoms.resize( conf.size() ); align.resize( conf.size() ); +void SingleDomainRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { + reference_atoms.resize( conf.size() ); align.resize( conf.size() ); displace.resize( conf.size() ); atom_der_index.resize( conf.size() ); - double wa=0, wd=0; - for(unsigned i=0;i& pos, const Pbc& p return calc( pos, pbc, myder, squared ); } -double SingleDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, +double SingleDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 ); return calc( pos, pbc, myder, squared ); diff --git a/src/reference/SingleDomainRMSD.h b/src/reference/SingleDomainRMSD.h index 9c6369e55a..9ecf96123d 100644 --- a/src/reference/SingleDomainRMSD.h +++ b/src/reference/SingleDomainRMSD.h @@ -36,14 +36,14 @@ class SingleDomainRMSD : public ReferenceAtoms { /// Set the reference structure virtual void setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ); /// Calculate - double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const; + double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const; double calculate( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const; /// Calculate the distance using the input position virtual double calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const=0; /// This sets upper and lower bounds on distances to be used in DRMSD (here it does nothing) - virtual void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits::max( ) ){}; + virtual void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits::max( ) ) {}; /// This is used by MultiDomainRMSD to setup the RMSD object in Optimal RMSD type - virtual void setupRMSDObject(){}; + virtual void setupRMSDObject() {}; }; } diff --git a/src/secondarystructure/AlphaRMSD.cpp b/src/secondarystructure/AlphaRMSD.cpp index 0f29dc024c..6c9b49083e 100644 --- a/src/secondarystructure/AlphaRMSD.cpp +++ b/src/secondarystructure/AlphaRMSD.cpp @@ -34,13 +34,13 @@ Probe the alpha helical content of a protein structure. Any chain of six contiguous residues in a protein chain can form an alpha helix. This colvar thus generates the set of all possible six residue sections and calculates the RMSD distance between the configuration in which the residues find themselves -and an idealized alpha helical structure. These distances can be calculated by either +and an idealized alpha helical structure. These distances can be calculated by either aligning the instantaneous structure with the reference structure and measuring each atomic displacement or by calculating differences between the set of interatomic -distances in the reference and instantaneous structures. +distances in the reference and instantaneous structures. -This colvar is based on the following reference \cite pietrucci09jctc. The authors of -this paper use the set of distances from the alpha helix configurations to measure +This colvar is based on the following reference \cite pietrucci09jctc. The authors of +this paper use the set of distances from the alpha helix configurations to measure the number of segments that have an alpha helical configuration. This is done by calculating the following sum of functions of the rmsd distances: @@ -48,24 +48,24 @@ the following sum of functions of the rmsd distances: s = \sum_i \frac{ 1 - \left(\frac{r_i-d_0}{r_0}\right)^n } { 1 - \left(\frac{r_i-d_0}{r_0}\right)^m } \f] -where the sum runs over all possible segments of alpha helix. By default the +where the sum runs over all possible segments of alpha helix. By default the NN, MM and D_0 parameters are set equal to those used in \cite pietrucci09jctc. The R_0 parameter must be set by the user - the value used in \cite pietrucci09jctc was 0.08 nm. If you change the function in the above sum you can calculate quantities such as the average -distance from a purely the alpha helical configuration or the distance between the set of -residues that is closest to an alpha helix and the reference configuration. To do these sorts of +distance from a purely the alpha helical configuration or the distance between the set of +residues that is closest to an alpha helix and the reference configuration. To do these sorts of calculations you can use the AVERAGE and MIN keywords. In addition you can use the LESS_THAN keyword if you would like to change the form of the switching function. If you use any of these -options you no longer need to specify NN, R_0, MM and D_0. +options you no longer need to specify NN, R_0, MM and D_0. -Please be aware that for codes like gromacs you must ensure that plumed +Please be aware that for codes like gromacs you must ensure that plumed reconstructs the chains involved in your CV when you calculate this CV using anthing other than TYPE=DRMSD. For more details as to how to do this see \ref WHOLEMOLECULES. \par Examples -The following input calculates the number of six residue segments of +The following input calculates the number of six residue segments of protein that are in an alpha helical configuration. \verbatim @@ -81,33 +81,33 @@ class AlphaRMSD : public SecondaryStructureRMSD { public: static void registerKeywords( Keywords& keys ); explicit AlphaRMSD(const ActionOptions&); -}; +}; PLUMED_REGISTER_ACTION(AlphaRMSD,"ALPHARMSD") -void AlphaRMSD::registerKeywords( Keywords& keys ){ +void AlphaRMSD::registerKeywords( Keywords& keys ) { SecondaryStructureRMSD::registerKeywords( keys ); } AlphaRMSD::AlphaRMSD(const ActionOptions&ao): -Action(ao), -SecondaryStructureRMSD(ao) + Action(ao), + SecondaryStructureRMSD(ao) { // read in the backbone atoms std::vector chains; readBackboneAtoms( "protein", chains); // This constructs all conceivable sections of alpha helix in the backbone of the chains unsigned nres, nprevious=0; std::vector nlist(30); - for(unsigned i=0;i chains; readBackboneAtoms( "protein", chains ); - bool intra_chain(false), inter_chain(false); + bool intra_chain(false), inter_chain(false); std::string style; parse("STYLE",style); - if( style=="all" ){ - intra_chain=true; inter_chain=true; - } else if( style=="inter"){ - intra_chain=false; inter_chain=true; - } else if( style=="intra"){ - intra_chain=true; inter_chain=false; + if( style=="all" ) { + intra_chain=true; inter_chain=true; + } else if( style=="inter") { + intra_chain=false; inter_chain=true; + } else if( style=="intra") { + intra_chain=true; inter_chain=false; } else { - error( style + " is not a valid directive for the STYLE keyword"); + error( style + " is not a valid directive for the STYLE keyword"); } - + // Align the atoms based on the positions of these two atoms setAtomsFromStrands( 6, 21 ); // This constructs all conceivable sections of antibeta sheet in the backbone of the chains - if( intra_chain ){ + if( intra_chain ) { unsigned nres, nprevious=0; std::vector nlist(30); - for(unsigned i=0;i nlist(30); - for(unsigned ichain=1;ichain nlist(30); + for(unsigned ichain=1; ichain chains; readBackboneAtoms( "protein", chains ); - bool intra_chain(false), inter_chain(false); + bool intra_chain(false), inter_chain(false); std::string style; parse("STYLE",style); - if( style=="all" ){ - intra_chain=true; inter_chain=true; - } else if( style=="inter"){ - intra_chain=false; inter_chain=true; - } else if( style=="intra"){ - intra_chain=true; inter_chain=false; + if( style=="all" ) { + intra_chain=true; inter_chain=true; + } else if( style=="inter") { + intra_chain=false; inter_chain=true; + } else if( style=="intra") { + intra_chain=true; inter_chain=false; } else { - error( style + " is not a valid directive for the STYLE keyword"); + error( style + " is not a valid directive for the STYLE keyword"); } // Align the atoms based on the positions of these two atoms setAtomsFromStrands( 6, 21 ); // This constructs all conceivable sections of antibeta sheet in the backbone of the chains - if( intra_chain ){ + if( intra_chain ) { unsigned nres, nprevious=0; std::vector nlist(30); - for(unsigned i=0;i nlist(30); - for(unsigned ichain=1;ichain nlist(30); + for(unsigned ichain=1; ichainlabel.lessthan-1, label.lessthan-2 and so on unless you " "exploit the fact that these labels are customizable. In particular, by using the LABEL keyword in the " - "description of you LESS_THAN function you can set name of the component that you are calculating"); + "description of you LESS_THAN function you can set name of the component that you are calculating"); } SecondaryStructureRMSD::SecondaryStructureRMSD(const ActionOptions&ao): -Action(ao), -ActionAtomistic(ao), -ActionWithValue(ao), -ActionWithVessel(ao), -align_strands(false), -s_cutoff2(0), -align_atom_1(0), -align_atom_2(0) + Action(ao), + ActionAtomistic(ao), + ActionWithValue(ao), + ActionWithVessel(ao), + align_strands(false), + s_cutoff2(0), + align_atom_1(0), + align_atom_2(0) { parse("TYPE",alignType); log.printf(" distances from secondary structure elements are calculated using %s algorithm\n",alignType.c_str() ); log<<" Bibliography "<0) log.printf(" ignoring contributions from strands that are more than %f apart\n",s_cutoff); @@ -93,95 +93,95 @@ align_atom_2(0) } } -SecondaryStructureRMSD::~SecondaryStructureRMSD(){ - for(unsigned i=0;i& chain_lengths ){ +void SecondaryStructureRMSD::readBackboneAtoms( const std::string& moltype, std::vector& chain_lengths ) { std::vector moldat=plumed.getActionSet().select(); if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); std::vector resstrings; parseVector( "RESIDUES", resstrings ); - if( !verbose_output ){ - if(resstrings[0]=="all"){ - log.printf(" examining all possible secondary structure combinations\n"); - } else { - log.printf(" examining secondary structure in residue positions : %s \n",resstrings[0].c_str() ); - for(unsigned i=1;i > backatoms; moldat[0]->getBackbone( resstrings, moltype, backatoms ); chain_lengths.resize( backatoms.size() ); - for(unsigned i=0;i& newatoms ){ +void SecondaryStructureRMSD::addColvar( const std::vector& newatoms ) { if( colvar_atoms.size()>0 ) plumed_assert( colvar_atoms[0].size()==newatoms.size() ); - if( verbose_output ){ - log.printf(" Secondary structure segment %u contains atoms : ", static_cast(colvar_atoms.size()+1)); - for(unsigned i=0;i(colvar_atoms.size()+1)); + for(unsigned i=0; i& structure, double bondlength, double units ){ +void SecondaryStructureRMSD::setSecondaryStructure( std::vector& structure, double bondlength, double units ) { // If we are in natural units get conversion factor from nm into natural length units - if( plumed.getAtoms().usingNaturalUnits() ){ - error("cannot use this collective variable when using natural units"); + if( plumed.getAtoms().usingNaturalUnits() ) { + error("cannot use this collective variable when using natural units"); } - plumed_massert( !(align_strands && align_atom_1==0 && align_atom_2==0), "you must use setAtomsFromStrands with strands cutoff"); + plumed_massert( !(align_strands && align_atom_1==0 && align_atom_2==0), "you must use setAtomsFromStrands with strands cutoff"); // Convert into correct units - for(unsigned i=0;i( alignType ) ); + references.push_back( metricRegister().create( alignType ) ); unsigned nn=references.size()-1; std::vector align( structure.size(), 1.0 ), displace( structure.size(), 1.0 ); - references[nn]->setBoundsOnDistances( true , bondlength ); // We always use pbc + references[nn]->setBoundsOnDistances( true, bondlength ); // We always use pbc references[nn]->setReferenceAtoms( structure, align, displace ); // references[nn]->setNumberOfAtoms( structure.size() ); // And prepare the task list deactivateAllTasks(); - for(unsigned i=0;i pos( references[0]->getNumberOfAtoms() ); const unsigned n=pos.size(); - for(unsigned i=0;i0 ){ - if( distance.modulo2()>s_cutoff2 ){ - myvals.setValue( 0, 0.0 ); - return; - } + Vector distance=pbcDistance( pos[align_atom_1],pos[align_atom_2] ); + if( s_cutoff2>0 ) { + if( distance.modulo2()>s_cutoff2 ) { + myvals.setValue( 0, 0.0 ); + return; + } } // This aligns the two strands if this is required - if( alignType!="DRMSD" && align_strands ){ - Vector origin_old, origin_new; origin_old=pos[align_atom_2]; - origin_new=pos[align_atom_1]+distance; - for(unsigned i=15;i<30;++i){ - pos[i]+=( origin_new - origin_old ); - } + if( alignType!="DRMSD" && align_strands ) { + Vector origin_old, origin_new; origin_old=pos[align_atom_2]; + origin_new=pos[align_atom_1]+distance; + for(unsigned i=15; i<30; ++i) { + pos[i]+=( origin_new - origin_old ); + } } // Create a holder for the derivatives ReferenceValuePack mypack( 0, pos.size(), myvals ); mypack.setValIndex( 1 ); - for(unsigned i=0;icalculate( pos, pbc, mypack, false ); const unsigned rs = references.size(); - for(unsigned i=1;icalculate( pos, pbc, mypack, false ); - if( nr0 ) mypack.moveDerivatives( closest+1, 1 ); - if( !mypack.virialWasSet() ){ + if( !mypack.virialWasSet() ) { Tensor vir; const unsigned cacs = colvar_atoms[current].size(); - for(unsigned i=0;i -namespace PLMD{ +namespace PLMD { -double Angle::compute(const Vector& v1,const Vector& v2)const{ - return std::acos(dotProduct(v1,v2)/(v1.modulo()*v2.modulo())); +double Angle::compute(const Vector& v1,const Vector& v2)const { + return std::acos(dotProduct(v1,v2)/(v1.modulo()*v2.modulo())); } -double Angle::compute(const Vector& v1,const Vector& v2,Vector& d1,Vector& d2)const{ - const double dp(dotProduct(v1,v2)); - const Vector& dp_dv1(v2); - const Vector& dp_dv2(v1); - const double sv1(v1.modulo2()); - const double sv2(v2.modulo2()); - const Vector dsv1_dv1(2*v1); - const Vector dsv2_dv2(2*v2); - const double nn(1.0/sqrt(sv1*sv2)); - const Vector dnn_dv1(-0.5*nn/sv1*dsv1_dv1); - const Vector dnn_dv2(-0.5*nn/sv2*dsv2_dv2); +double Angle::compute(const Vector& v1,const Vector& v2,Vector& d1,Vector& d2)const { + const double dp(dotProduct(v1,v2)); + const Vector& dp_dv1(v2); + const Vector& dp_dv2(v1); + const double sv1(v1.modulo2()); + const double sv2(v2.modulo2()); + const Vector dsv1_dv1(2*v1); + const Vector dsv2_dv2(2*v2); + const double nn(1.0/sqrt(sv1*sv2)); + const Vector dnn_dv1(-0.5*nn/sv1*dsv1_dv1); + const Vector dnn_dv2(-0.5*nn/sv2*dsv2_dv2); - const double dpnn(dp*nn); + const double dpnn(dp*nn); - if(dpnn>=1.0-epsilon){ - d1=Vector(0.0,0.0,0.0); - d2=Vector(0.0,0.0,0.0); - return 0.0; - } - if(dpnn<=-1.0+epsilon){ - d1=Vector(0.0,0.0,0.0); - d2=Vector(0.0,0.0,0.0); - return pi; - } - const Vector ddpnn_dv1(dp*dnn_dv1+dp_dv1*nn); - const Vector ddpnn_dv2(dp*dnn_dv2+dp_dv2*nn); + if(dpnn>=1.0-epsilon) { + d1=Vector(0.0,0.0,0.0); + d2=Vector(0.0,0.0,0.0); + return 0.0; + } + if(dpnn<=-1.0+epsilon) { + d1=Vector(0.0,0.0,0.0); + d2=Vector(0.0,0.0,0.0); + return pi; + } + const Vector ddpnn_dv1(dp*dnn_dv1+dp_dv1*nn); + const Vector ddpnn_dv2(dp*dnn_dv2+dp_dv2*nn); - const double x(-1.0/sqrt(1-dpnn*dpnn)); + const double x(-1.0/sqrt(1-dpnn*dpnn)); - d1=x*ddpnn_dv1; - d2=x*ddpnn_dv2; + d1=x*ddpnn_dv1; + d2=x*ddpnn_dv2; - return std::acos(dpnn); + return std::acos(dpnn); } } diff --git a/src/tools/Angle.h b/src/tools/Angle.h index 9a9f2b2000..1d6a58e520 100644 --- a/src/tools/Angle.h +++ b/src/tools/Angle.h @@ -24,7 +24,7 @@ #include "Vector.h" -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX /// Class to compute angles. @@ -36,7 +36,7 @@ namespace PLMD{ /// I know it is a bit misleading. If we really do not need to store "options" /// inside the Angle class, we can remove it later and write compute as /// a static function. -class Angle{ +class Angle { // still empty, but may accomodate some options in the future public: /// Compute the angle between vectors v1 and v2 diff --git a/src/tools/AtomNumber.h b/src/tools/AtomNumber.h index b150189306..60eb9ca775 100644 --- a/src/tools/AtomNumber.h +++ b/src/tools/AtomNumber.h @@ -25,7 +25,7 @@ #include "Exception.h" #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -36,7 +36,7 @@ namespace PLMD{ no ambiguity about using the "from 0" (index) or "from 1" (serial) numbering (names as in VMD convention). */ -class AtomNumber{ +class AtomNumber { unsigned index_; /// Construct with a given index. /// This constructor is kept private to avoid implicit cast. @@ -71,27 +71,27 @@ class AtomNumber{ }; inline -AtomNumber::AtomNumber(){ +AtomNumber::AtomNumber() { index_=0; } inline -AtomNumber::AtomNumber(unsigned i){ +AtomNumber::AtomNumber(unsigned i) { index_=i; } inline -unsigned AtomNumber::serial()const{ +unsigned AtomNumber::serial()const { return index_+1; } inline -unsigned AtomNumber::index()const{ +unsigned AtomNumber::index()const { return index_; } inline -AtomNumber & AtomNumber::setSerial(unsigned i){ +AtomNumber & AtomNumber::setSerial(unsigned i) { plumed_massert(i>0,"serial of an atom cannot be zero"); plumed_massert(i::max()/2,"serial cannot be negative"); index_=i-1; @@ -99,50 +99,50 @@ AtomNumber & AtomNumber::setSerial(unsigned i){ } inline -AtomNumber & AtomNumber::setIndex(unsigned i){ +AtomNumber & AtomNumber::setIndex(unsigned i) { index_=i; return *this; } inline -AtomNumber AtomNumber::serial(unsigned i){ +AtomNumber AtomNumber::serial(unsigned i) { plumed_massert(i>0,"serial of an atom cannot be zero"); plumed_massert(i::max()/2,"serial cannot be negative"); return AtomNumber(i-1); } inline -AtomNumber AtomNumber::index(unsigned i){ +AtomNumber AtomNumber::index(unsigned i) { return AtomNumber(i); } inline -bool operator<(const AtomNumber&a,const AtomNumber&b){ +bool operator<(const AtomNumber&a,const AtomNumber&b) { return a.index_(const AtomNumber&a,const AtomNumber&b){ +bool operator>(const AtomNumber&a,const AtomNumber&b) { return a.index_>b.index_; } inline -bool operator<=(const AtomNumber&a,const AtomNumber&b){ +bool operator<=(const AtomNumber&a,const AtomNumber&b) { return a.index_<=b.index_; } inline -bool operator>=(const AtomNumber&a,const AtomNumber&b){ +bool operator>=(const AtomNumber&a,const AtomNumber&b) { return a.index_>=b.index_; } inline -bool operator==(const AtomNumber&a,const AtomNumber&b){ +bool operator==(const AtomNumber&a,const AtomNumber&b) { return a.index_==b.index_; } inline -bool operator!=(const AtomNumber&a,const AtomNumber&b){ +bool operator!=(const AtomNumber&a,const AtomNumber&b) { return a.index_!=b.index_; } diff --git a/src/tools/BiasRepresentation.cpp b/src/tools/BiasRepresentation.cpp index 89ae941a56..d37be2916f 100644 --- a/src/tools/BiasRepresentation.cpp +++ b/src/tools/BiasRepresentation.cpp @@ -29,247 +29,247 @@ namespace PLMD { using namespace std; /// the constructor here -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc ):hasgrid(false),rescaledToBias(false),mycomm(cc),BiasGrid_(NULL){ - lowI_=0.0; - uppI_=0.0; - doInt_=false; - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc ):hasgrid(false),rescaledToBias(false),mycomm(cc),BiasGrid_(NULL) { + lowI_=0.0; + uppI_=0.0; + doInt_=false; + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } +} +/// overload the constructor: add the sigma at constructor time +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & sigma ):hasgrid(false), rescaledToBias(false), histosigma(sigma),mycomm(cc),BiasGrid_(NULL) { + lowI_=0.0; + uppI_=0.0; + doInt_=false; + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } +} +/// overload the constructor: add the grid at constructor time +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & gmin, const vector & gmax, + const vector & nbin, bool doInt, double lowI, double uppI ):hasgrid(false), rescaledToBias(false), mycomm(cc), BiasGrid_(NULL) { + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } + doInt_=doInt; + lowI_=lowI; + uppI_=uppI; + // initialize the grid + addGrid(gmin,gmax,nbin); } -/// overload the constructor: add the sigma at constructor time -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & sigma ):hasgrid(false), rescaledToBias(false), histosigma(sigma),mycomm(cc),BiasGrid_(NULL){ - lowI_=0.0; - uppI_=0.0; - doInt_=false; - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } -} -/// overload the constructor: add the grid at constructor time -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc , const vector & gmin, const vector & gmax, - const vector & nbin, bool doInt, double lowI, double uppI ):hasgrid(false), rescaledToBias(false), mycomm(cc), BiasGrid_(NULL){ - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } - doInt_=doInt; - lowI_=lowI; - uppI_=uppI; - // initialize the grid - addGrid(gmin,gmax,nbin); -} /// overload the constructor with some external sigmas: needed for histogram -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc , const vector & gmin, const vector & gmax, const vector & nbin , const vector & sigma):hasgrid(false), rescaledToBias(false),histosigma(sigma),mycomm(cc),BiasGrid_(NULL){ - lowI_=0.0; - uppI_=0.0; - doInt_=false; - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } - // initialize the grid - addGrid(gmin,gmax,nbin); +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & gmin, const vector & gmax, const vector & nbin, const vector & sigma):hasgrid(false), rescaledToBias(false),histosigma(sigma),mycomm(cc),BiasGrid_(NULL) { + lowI_=0.0; + uppI_=0.0; + doInt_=false; + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } + // initialize the grid + addGrid(gmin,gmax,nbin); } -BiasRepresentation::~BiasRepresentation(){ +BiasRepresentation::~BiasRepresentation() { if(BiasGrid_) delete BiasGrid_; - for(unsigned i=0;i & gmin, const vector & gmax, const vector & nbin ){ - plumed_massert(hills.size()==0,"you can set the grid before loading the hills"); - plumed_massert(hasgrid==false,"to build the grid you should not having the grid in this bias representation"); - string ss; ss="file.free"; - vector vv;for(unsigned i=0;i & gmin, const vector & gmax, const vector & nbin ) { + plumed_massert(hills.size()==0,"you can set the grid before loading the hills"); + plumed_massert(hasgrid==false,"to build the grid you should not having the grid in this bias representation"); + string ss; ss="file.free"; + vector vv; for(unsigned i=0; i BiasRepresentation::getNames(){ - return names; -} -const string & BiasRepresentation::getName(unsigned i){ - return names[i]; -} +unsigned BiasRepresentation::getNumberOfDimensions() { + return values.size(); +} +vector BiasRepresentation::getNames() { + return names; +} +const string & BiasRepresentation::getName(unsigned i) { + return names[i]; +} -const vector& BiasRepresentation::getPtrToValues(){ - return values; -} -Value* BiasRepresentation::getPtrToValue(unsigned i){ - return values[i]; -} +const vector& BiasRepresentation::getPtrToValues() { + return values; +} +Value* BiasRepresentation::getPtrToValue(unsigned i) { + return values[i]; +} -KernelFunctions* BiasRepresentation::readFromPoint(IFile *ifile){ - vector cc( names.size() ); - for(unsigned i=0;iscanField(names[i],cc[i]); - } - double h=1.0; - return new KernelFunctions(cc,histosigma,"gaussian",false,h,false); +KernelFunctions* BiasRepresentation::readFromPoint(IFile *ifile) { + vector cc( names.size() ); + for(unsigned i=0; iscanField(names[i],cc[i]); + } + double h=1.0; + return new KernelFunctions(cc,histosigma,"gaussian",false,h,false); } -void BiasRepresentation::pushKernel( IFile *ifile ){ - KernelFunctions *kk=NULL; - // here below the reading of the kernel is completely hidden - if(histosigma.size()==0){ - ifile->allowIgnoredFields(); - kk=KernelFunctions::read(ifile,names) ; - }else{ - // when doing histogram assume gaussian with a given diagonal sigma - // and neglect all the rest - kk=readFromPoint(ifile) ; - } - hills.push_back(kk); - // the bias factor is not something about the kernels but - // must be stored to keep the bias/free energy duality - string dummy; double dummyd; - if(ifile->FieldExist("biasf")){ - ifile->scanField("biasf",dummy); - Tools::convert(dummy,dummyd); - }else{dummyd=1.0;} - biasf.push_back(dummyd); - // the domain does not pertain to the kernel but to the values here defined - string mins,maxs,minv,maxv,mini,maxi;mins="min_";maxs="max_"; - for(int i=0 ; iisPeriodic()){ - ifile->scanField(mins+names[i],minv); - ifile->scanField(maxs+names[i],maxv); - // verify that the domain is correct - values[i]->getDomain(mini,maxi); - plumed_massert(mini==minv,"the input periodicity in hills and in value definition does not match" ); - plumed_massert(maxi==maxv,"the input periodicity in hills and in value definition does not match" ); - } +void BiasRepresentation::pushKernel( IFile *ifile ) { + KernelFunctions *kk=NULL; + // here below the reading of the kernel is completely hidden + if(histosigma.size()==0) { + ifile->allowIgnoredFields(); + kk=KernelFunctions::read(ifile,names) ; + } else { + // when doing histogram assume gaussian with a given diagonal sigma + // and neglect all the rest + kk=readFromPoint(ifile) ; + } + hills.push_back(kk); + // the bias factor is not something about the kernels but + // must be stored to keep the bias/free energy duality + string dummy; double dummyd; + if(ifile->FieldExist("biasf")) { + ifile->scanField("biasf",dummy); + Tools::convert(dummy,dummyd); + } else {dummyd=1.0;} + biasf.push_back(dummyd); + // the domain does not pertain to the kernel but to the values here defined + string mins,maxs,minv,maxv,mini,maxi; mins="min_"; maxs="max_"; + for(int i=0 ; iisPeriodic()) { + ifile->scanField(mins+names[i],minv); + ifile->scanField(maxs+names[i],maxv); + // verify that the domain is correct + values[i]->getDomain(mini,maxi); + plumed_massert(mini==minv,"the input periodicity in hills and in value definition does not match" ); + plumed_massert(maxi==maxv,"the input periodicity in hills and in value definition does not match" ); + } + } + // if grid is defined then it should be added on the grid + //cerr<<"now with "< nneighb; + if(doInt_&&(kk->getCenter()[0]+kk->getContinuousSupport()[0] > uppI_ || kk->getCenter()[0]-kk->getContinuousSupport()[0] < lowI_ )) { + nneighb=BiasGrid_->getNbin(); + } else nneighb=kk->getSupport(BiasGrid_->getDx()); + vector neighbors=BiasGrid_->getNeighbors(kk->getCenter(),nneighb); + vector der(ndim); + vector xx(ndim); + if(mycomm.Get_size()==1) { + for(unsigned i=0; igetPoint(ineigh,xx); + // assign xx to a new vector of values + for(int j=0; jset(xx[j]);} + double bias; + if(doInt_) bias=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); + else bias=kk->evaluate(values,der,true); + if(rescaledToBias) { + double f=(biasf.back()-1.)/(biasf.back()); + bias*=f; + for(int j=0; j nneighb; - if(doInt_&&(kk->getCenter()[0]+kk->getContinuousSupport()[0] > uppI_ || kk->getCenter()[0]-kk->getContinuousSupport()[0] < lowI_ )) { - nneighb=BiasGrid_->getNbin(); - } else nneighb=kk->getSupport(BiasGrid_->getDx()); - vector neighbors=BiasGrid_->getNeighbors(kk->getCenter(),nneighb); - vector der(ndim); - vector xx(ndim); - if(mycomm.Get_size()==1){ - for(unsigned i=0;igetPoint(ineigh,xx); - // assign xx to a new vector of values - for(int j=0;jset(xx[j]);} - double bias; - if(doInt_) bias=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); - else bias=kk->evaluate(values,der,true); - if(rescaledToBias){ - double f=(biasf.back()-1.)/(biasf.back()); - bias*=f; - for(int j=0;jaddValueAndDerivatives(ineigh,bias,der); - } - } else { - unsigned stride=mycomm.Get_size(); - unsigned rank=mycomm.Get_rank(); - vector allder(ndim*neighbors.size(),0.0); - vector allbias(neighbors.size(),0.0); - vector tmpder(ndim); - for(unsigned i=rank;igetPoint(ineigh,xx); - for(int j=0;jset(xx[j]);} - if(doInt_) allbias[i]=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); - else allbias[i]=kk->evaluate(values,der,true); - if(rescaledToBias){ - double f=(biasf.back()-1.)/(biasf.back()); - allbias[i]*=f; - for(int j=0;jaddValueAndDerivatives(ineigh,allbias[i],der); - } - } + BiasGrid_->addValueAndDerivatives(ineigh,bias,der); + } + } else { + unsigned stride=mycomm.Get_size(); + unsigned rank=mycomm.Get_rank(); + vector allder(ndim*neighbors.size(),0.0); + vector allbias(neighbors.size(),0.0); + vector tmpder(ndim); + for(unsigned i=rank; igetPoint(ineigh,xx); + for(int j=0; jset(xx[j]);} + if(doInt_) allbias[i]=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); + else allbias[i]=kk->evaluate(values,der,true); + if(rescaledToBias) { + double f=(biasf.back()-1.)/(biasf.back()); + allbias[i]*=f; + for(int j=0; jaddValueAndDerivatives(ineigh,allbias[i],der); + } + } + } } -int BiasRepresentation::getNumberOfKernels(){ - return hills.size(); +int BiasRepresentation::getNumberOfKernels() { + return hills.size(); } -Grid* BiasRepresentation::getGridPtr(){ - plumed_massert(hasgrid,"if you want the grid pointer then you should have defined a grid before"); - return BiasGrid_; +Grid* BiasRepresentation::getGridPtr() { + plumed_massert(hasgrid,"if you want the grid pointer then you should have defined a grid before"); + return BiasGrid_; } -void BiasRepresentation::getMinMaxBin(vector &vmin, vector &vmax, vector &vbin){ - vector ss,cc,binsize; - vmin.clear();vmin.resize(ndim,10.e20); - vmax.clear();vmax.resize(ndim,-10.e20); - vbin.clear();vbin.resize(ndim); - binsize.clear();binsize.resize(ndim,10.e20); - int ndiv=10; // adjustable parameter: division per support - for(unsigned i=0;igetContinuousSupport(); - } - cc=hills[i]->getCenter(); - for(int j=0;jvmax[j])vmax[j]=dmax; - if(ddivisPeriodic()){ - double minv,maxv; - values[j]->getDomain(minv,maxv); - if(minv>vmin[j])vmin[j]=minv; - if(maxv(ceil((vmax[j]-vmin[j])/binsize[j]) ); - } +void BiasRepresentation::getMinMaxBin(vector &vmin, vector &vmax, vector &vbin) { + vector ss,cc,binsize; + vmin.clear(); vmin.resize(ndim,10.e20); + vmax.clear(); vmax.resize(ndim,-10.e20); + vbin.clear(); vbin.resize(ndim); + binsize.clear(); binsize.resize(ndim,10.e20); + int ndiv=10; // adjustable parameter: division per support + for(unsigned i=0; igetContinuousSupport(); + } + cc=hills[i]->getCenter(); + for(int j=0; jvmax[j])vmax[j]=dmax; + if(ddivisPeriodic()) { + double minv,maxv; + values[j]->getDomain(minv,maxv); + if(minv>vmin[j])vmin[j]=minv; + if(maxv(ceil((vmax[j]-vmin[j])/binsize[j]) ); + } } -void BiasRepresentation::clear(){ - // clear the hills - for(const auto & it : hills) - { - delete it; - } - hills.clear(); - // clear the grid - if(hasgrid){ - BiasGrid_->clear(); - } +void BiasRepresentation::clear() { + // clear the hills + for(const auto & it : hills) + { + delete it; + } + hills.clear(); + // clear the grid + if(hasgrid) { + BiasGrid_->clear(); + } } diff --git a/src/tools/BiasRepresentation.h b/src/tools/BiasRepresentation.h index a66bf3778e..9533e53c49 100644 --- a/src/tools/BiasRepresentation.h +++ b/src/tools/BiasRepresentation.h @@ -27,75 +27,75 @@ #include "File.h" #include "Grid.h" -namespace PLMD{ +namespace PLMD { -//+PLUMEDOC INTERNAL biasrepresentation +//+PLUMEDOC INTERNAL biasrepresentation /* */ //+ENDPLUMEDOC -/// this class implements a general purpose class that aims to -/// provide a Grid/list -/// transparently add gaussians to a bias +/// this class implements a general purpose class that aims to +/// provide a Grid/list +/// transparently add gaussians to a bias class BiasRepresentation { - public: - /// create a bias representation from a list of pointer to values - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc ); - /// create a bias using explicit sigma in input (needed for histogram building) - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc , const std::vector & sigma); - /// create a bias containing a grid representation - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc , const std::vector & gmin, const std::vector & gmax, - const std::vector & nbin, bool doInt, double lowI_, double uppI_); - /// create a histogram with grid representation and sigmas in input - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc , const std::vector & gmin, const std::vector & gmax, const std::vector & nbin , const std::vector & sigma); - /// destructor - ~BiasRepresentation(); - /// retrieve the number of dimension of the representation - unsigned getNumberOfDimensions(); - /// add the grid to the representation - void addGrid(const std::vector & gmin, const std::vector & gmax, const std::vector & nbin ); - /// push a kernel on the representation (includes widths and height) - void pushKernel( IFile * ff); - /// set the flag that rescales the free energy to the bias - void setRescaledToBias(bool rescaled); - /// check if the representation is rescaled to the bias - const bool & isRescaledToBias(); - /// check if the sigma values are already provided (in case of a histogram representation with input sigmas) - bool hasSigmaInInput(); - /// get the names of the variables - std::vector getNames(); - /// get the pointer to the values - const std::vector & getPtrToValues(); - /// get the number of kernels contained in the representation - int getNumberOfKernels(); - /// get the name of the i-th value - const std::string & getName(unsigned i); - /// get a pointer to a specific value - Value* getPtrToValue(unsigned i); - /// get the pointer to the grid - Grid* getGridPtr(); - /// get a new histogram point from a file - KernelFunctions* readFromPoint(IFile *ifile); - /// get an automatic min/max from the set so to know how to configure the grid - void getMinMaxBin(std::vector &vmin, std::vector &vmax, std::vector &vbin); - /// clear the representation (grid included) - void clear(); - private: - int ndim; - bool hasgrid; - bool rescaledToBias; - bool doInt_; - double lowI_; - double uppI_; - std::vector values; - std::vector names; - std::vector hills; - std::vector biasf; - std::vector histosigma; - Communicator& mycomm; - Grid* BiasGrid_; +public: + /// create a bias representation from a list of pointer to values + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc ); + /// create a bias using explicit sigma in input (needed for histogram building) + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc, const std::vector & sigma); + /// create a bias containing a grid representation + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc, const std::vector & gmin, const std::vector & gmax, + const std::vector & nbin, bool doInt, double lowI_, double uppI_); + /// create a histogram with grid representation and sigmas in input + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc, const std::vector & gmin, const std::vector & gmax, const std::vector & nbin, const std::vector & sigma); + /// destructor + ~BiasRepresentation(); + /// retrieve the number of dimension of the representation + unsigned getNumberOfDimensions(); + /// add the grid to the representation + void addGrid(const std::vector & gmin, const std::vector & gmax, const std::vector & nbin ); + /// push a kernel on the representation (includes widths and height) + void pushKernel( IFile * ff); + /// set the flag that rescales the free energy to the bias + void setRescaledToBias(bool rescaled); + /// check if the representation is rescaled to the bias + const bool & isRescaledToBias(); + /// check if the sigma values are already provided (in case of a histogram representation with input sigmas) + bool hasSigmaInInput(); + /// get the names of the variables + std::vector getNames(); + /// get the pointer to the values + const std::vector & getPtrToValues(); + /// get the number of kernels contained in the representation + int getNumberOfKernels(); + /// get the name of the i-th value + const std::string & getName(unsigned i); + /// get a pointer to a specific value + Value* getPtrToValue(unsigned i); + /// get the pointer to the grid + Grid* getGridPtr(); + /// get a new histogram point from a file + KernelFunctions* readFromPoint(IFile *ifile); + /// get an automatic min/max from the set so to know how to configure the grid + void getMinMaxBin(std::vector &vmin, std::vector &vmax, std::vector &vbin); + /// clear the representation (grid included) + void clear(); +private: + int ndim; + bool hasgrid; + bool rescaledToBias; + bool doInt_; + double lowI_; + double uppI_; + std::vector values; + std::vector names; + std::vector hills; + std::vector biasf; + std::vector histosigma; + Communicator& mycomm; + Grid* BiasGrid_; }; } diff --git a/src/tools/Brent1DRootSearch.h b/src/tools/Brent1DRootSearch.h index 39ccdfcc4e..138760737c 100644 --- a/src/tools/Brent1DRootSearch.h +++ b/src/tools/Brent1DRootSearch.h @@ -27,7 +27,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /// A class for doing parabolic interpolation and minimisation of /// 1D functions using Brent's method. @@ -40,7 +40,7 @@ class Brent1DRootSearch { double tol; /// Maximum number of interactions in line minimiser const unsigned ITMAX; -/// A small number that protects against trying to achieve fractional +/// A small number that protects against trying to achieve fractional /// accuracy for a minimum that happens to be exactly zero const double EPS; /// The factor by which to expand the range when bracketing @@ -53,67 +53,67 @@ class Brent1DRootSearch { FCLASS myclass_func; public: explicit Brent1DRootSearch( const FCLASS& pf, const double& t=3.0E-8 ); -/// Bracket the minium +/// Bracket the minium void bracket( const double& ax, const double& xx, eng_pointer eng ); /// Find the minimum between two brackets - double search( eng_pointer eng ); + double search( eng_pointer eng ); }; template Brent1DRootSearch::Brent1DRootSearch( const FCLASS& pf, const double& t ): -bracketed(false), -tol(t), -ITMAX(100), -EPS(3.0E-8), -EXPAND(1.6), -ax(0), bx(0), -fa(0), fb(0), -myclass_func(pf) + bracketed(false), + tol(t), + ITMAX(100), + EPS(3.0E-8), + EXPAND(1.6), + ax(0), bx(0), + fa(0), fb(0), + myclass_func(pf) { } template -void Brent1DRootSearch::bracket( const double& a, const double& b, eng_pointer eng ){ - plumed_assert( a!=b ); ax=a; bx=b; fa=(myclass_func.*eng)(a); fb=(myclass_func.*eng)(b); - if ((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0)) plumed_merror("input points do not bracket root"); - bracketed=true; +void Brent1DRootSearch::bracket( const double& a, const double& b, eng_pointer eng ) { + plumed_assert( a!=b ); ax=a; bx=b; fa=(myclass_func.*eng)(a); fb=(myclass_func.*eng)(b); + if ((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0)) plumed_merror("input points do not bracket root"); + bracketed=true; } template -double Brent1DRootSearch::search( eng_pointer eng ){ - plumed_dbg_assert( bracketed ); +double Brent1DRootSearch::search( eng_pointer eng ) { + plumed_dbg_assert( bracketed ); - double cx=bx, d, e, min1, min2, fc=fb, p, q, r, s, tol1, xm; - for(unsigned iter=0;iter0.0 && fc>0.0) || (fb<0.0 && fc<0.0) ){ cx=ax; fc=fa; e=d=bx-ax; } - if( fabs(fc) < fabs(fb) ){ ax=bx; bx=cx; cx=ax; fa=fb; fb=fc; fc=fa; } - tol1=2*EPS*fabs(bx)+0.5*tol; xm=0.5*(cx-bx); - if( fabs(xm) <= tol1 || fb == 0.0 ) return bx; - if( fabs(e) >= tol1 && fabs(fa) > fabs(fb) ){ - s=fb/fa; - if( ax==cx ){ - p=2.0*xm*s; q=1.0-s; - } else { - q=fa/fc; r=fb/fc; p=s*(2.0*xm*q*(q-r)-(bx-ax)*(r-1.0)); q=(q-1.0)*(r-1.0)*(s-1.0); - } - if (p > 0.0) q = -q; - p=fabs(p); min1=3.0*xm*q-fabs(tol1*q); min2=fabs(e*q); - if (2.0*p < (min1 < min2 ? min1 : min2)) { - e=d; d=p/q; - } else { - d=xm; e=d; - } + double cx=bx, d, e, min1, min2, fc=fb, p, q, r, s, tol1, xm; + for(unsigned iter=0; iter0.0 && fc>0.0) || (fb<0.0 && fc<0.0) ) { cx=ax; fc=fa; e=d=bx-ax; } + if( fabs(fc) < fabs(fb) ) { ax=bx; bx=cx; cx=ax; fa=fb; fb=fc; fc=fa; } + tol1=2*EPS*fabs(bx)+0.5*tol; xm=0.5*(cx-bx); + if( fabs(xm) <= tol1 || fb == 0.0 ) return bx; + if( fabs(e) >= tol1 && fabs(fa) > fabs(fb) ) { + s=fb/fa; + if( ax==cx ) { + p=2.0*xm*s; q=1.0-s; } else { - d=xm; e=d; + q=fa/fc; r=fb/fc; p=s*(2.0*xm*q*(q-r)-(bx-ax)*(r-1.0)); q=(q-1.0)*(r-1.0)*(s-1.0); } - ax=bx; fa=fb; - if( fabs(d) > tol1 ) bx+=d; - else if(xm<0 ) bx -= fabs(tol1); // SIGN(tol1,xm); - else bx += tol1; - fb = (myclass_func.*eng)(bx); - } + if (p > 0.0) q = -q; + p=fabs(p); min1=3.0*xm*q-fabs(tol1*q); min2=fabs(e*q); + if (2.0*p < (min1 < min2 ? min1 : min2)) { + e=d; d=p/q; + } else { + d=xm; e=d; + } + } else { + d=xm; e=d; + } + ax=bx; fa=fb; + if( fabs(d) > tol1 ) bx+=d; + else if(xm<0 ) bx -= fabs(tol1); // SIGN(tol1,xm); + else bx += tol1; + fb = (myclass_func.*eng)(bx); + } - plumed_merror("Too many interactions in zbrent"); + plumed_merror("Too many interactions in zbrent"); } } diff --git a/src/tools/Citations.cpp b/src/tools/Citations.cpp index 0c320d4e91..508255c2c5 100644 --- a/src/tools/Citations.cpp +++ b/src/tools/Citations.cpp @@ -25,11 +25,11 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { -std::string Citations::cite(const std::string & item){ +std::string Citations::cite(const std::string & item) { unsigned i; - for(i=0;i #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -51,7 +51,7 @@ int main(int argc,char**argv){ \endverbatim */ -class Citations{ +class Citations { std::vector items; public: /// Add a citation. diff --git a/src/tools/Communicator.cpp b/src/tools/Communicator.cpp index e53b1db4df..ac10f3931a 100644 --- a/src/tools/Communicator.cpp +++ b/src/tools/Communicator.cpp @@ -25,11 +25,11 @@ using namespace std; -namespace PLMD{ +namespace PLMD { Communicator::Communicator() #ifdef __PLUMED_HAS_MPI -: communicator(MPI_COMM_SELF) + : communicator(MPI_COMM_SELF) #endif { } @@ -38,7 +38,7 @@ Communicator::Communicator() // Member variable 'Communicator::communicator' is not initialized in the constructor // this is a false positive so I suppress it // cppcheck-suppress uninitMemberVar -Communicator::Communicator(const Communicator&pc){ +Communicator::Communicator(const Communicator&pc) { Set_comm(pc.communicator); } @@ -48,14 +48,14 @@ Communicator::Status Communicator::StatusIgnore; // Member variable 'Communicator::communicator' is not assigned a value in 'Communicator::operator=' // this is a false positive so I suppress it // cppcheck-suppress operatorEqVarError -Communicator& Communicator::operator=(const Communicator&pc){ - if (this != &pc){ - Set_comm(pc.communicator); +Communicator& Communicator::operator=(const Communicator&pc) { + if (this != &pc) { + Set_comm(pc.communicator); } return *this; } -int Communicator::Get_rank()const{ +int Communicator::Get_rank()const { int r=0; #ifdef __PLUMED_HAS_MPI if(initialized()) MPI_Comm_rank(communicator,&r); @@ -63,7 +63,7 @@ int Communicator::Get_rank()const{ return r; } -Communicator& Communicator::Get_world(){ +Communicator& Communicator::Get_world() { static Communicator c; #ifdef __PLUMED_HAS_MPI if(initialized()) c.communicator=MPI_COMM_WORLD; @@ -72,7 +72,7 @@ Communicator& Communicator::Get_world(){ } -int Communicator::Get_size()const{ +int Communicator::Get_size()const { int s=1; #ifdef __PLUMED_HAS_MPI if(initialized()) MPI_Comm_size(communicator,&s); @@ -80,9 +80,9 @@ int Communicator::Get_size()const{ return s; } -void Communicator::Set_comm(MPI_Comm c){ +void Communicator::Set_comm(MPI_Comm c) { #ifdef __PLUMED_HAS_MPI - if(initialized()){ + if(initialized()) { if(communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator); if(c!=MPI_COMM_SELF) MPI_Comm_dup(c,&communicator); } @@ -91,26 +91,26 @@ void Communicator::Set_comm(MPI_Comm c){ #endif } -Communicator::~Communicator(){ +Communicator::~Communicator() { #ifdef __PLUMED_HAS_MPI if(initialized() && communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator); #endif } -void Communicator::Set_comm(void*val){ +void Communicator::Set_comm(void*val) { #ifdef __PLUMED_HAS_MPI - plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); - if(val) Set_comm(*(MPI_Comm*)val); + plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); + if(val) Set_comm(*(MPI_Comm*)val); #else - (void) val; - plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support"); + (void) val; + plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support"); #endif } -void Communicator::Set_fcomm(void*val){ +void Communicator::Set_fcomm(void*val) { #ifdef __PLUMED_HAS_MPI - plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); - if(val){ + plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); + if(val) { MPI_Comm comm=MPI_Comm_f2c(*(MPI_Fint*)val); Set_comm(comm); } @@ -120,9 +120,9 @@ void Communicator::Set_fcomm(void*val){ #endif } -void Communicator::Abort(int errorcode){ +void Communicator::Abort(int errorcode) { #ifdef __PLUMED_HAS_MPI - if(initialized()){ + if(initialized()) { MPI_Abort(communicator,errorcode); } std::exit(errorcode); @@ -133,7 +133,7 @@ void Communicator::Abort(int errorcode){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Bcast(Data data,int root){ +void Communicator::Bcast(Data data,int root) { #if defined(__PLUMED_HAS_MPI) if(initialized()) MPI_Bcast(data.pointer,data.size,data.type,root,communicator); #else @@ -144,7 +144,7 @@ void Communicator::Bcast(Data data,int root){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Sum(Data data){ +void Communicator::Sum(Data data) { #if defined(__PLUMED_HAS_MPI) if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_SUM,communicator); #else @@ -154,7 +154,7 @@ void Communicator::Sum(Data data){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -Communicator::Request Communicator::Isend(ConstData data,int source,int tag){ +Communicator::Request Communicator::Isend(ConstData data,int source,int tag) { Request req; #ifdef __PLUMED_HAS_MPI plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); @@ -171,7 +171,7 @@ Communicator::Request Communicator::Isend(ConstData data,int source,int tag){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs){ +void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs) { #if defined(__PLUMED_HAS_MPI) plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); void*s=const_cast((const void*)in.pointer); @@ -191,7 +191,7 @@ void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const i // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Allgather(ConstData in,Data out){ +void Communicator::Allgather(ConstData in,Data out) { #if defined(__PLUMED_HAS_MPI) plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); void*s=const_cast((const void*)in.pointer); @@ -207,7 +207,7 @@ void Communicator::Allgather(ConstData in,Data out){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Recv(Data data,int source,int tag,Status&status){ +void Communicator::Recv(Data data,int source,int tag,Status&status) { #ifdef __PLUMED_HAS_MPI plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); if(&status==&StatusIgnore) MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,MPI_STATUS_IGNORE); @@ -225,17 +225,17 @@ void Communicator::Recv(Data data,int source,int tag,Status&status){ -void Communicator::Barrier()const{ +void Communicator::Barrier()const { #ifdef __PLUMED_HAS_MPI if(initialized()) MPI_Barrier(communicator); #endif } -MPI_Comm & Communicator::Get_comm(){ - return communicator; +MPI_Comm & Communicator::Get_comm() { + return communicator; } -bool Communicator::initialized(){ +bool Communicator::initialized() { int flag=false; #if defined(__PLUMED_HAS_MPI) MPI_Initialized(&flag); @@ -244,9 +244,9 @@ bool Communicator::initialized(){ else return false; } -void Communicator::Request::wait(Status&s){ +void Communicator::Request::wait(Status&s) { #ifdef __PLUMED_HAS_MPI - plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); + plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); if(&s==&StatusIgnore) MPI_Wait(&r,MPI_STATUS_IGNORE); else MPI_Wait(&r,&s.s); #else @@ -256,23 +256,23 @@ void Communicator::Request::wait(Status&s){ } #ifdef __PLUMED_HAS_MPI -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_FLOAT;} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_DOUBLE;} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_FLOAT;} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_DOUBLE;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_INT;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_CHAR;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_UNSIGNED;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_UNSIGNED_LONG;} #else -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} #endif -void Communicator::Split(int color,int key,Communicator&pc)const{ +void Communicator::Split(int color,int key,Communicator&pc)const { #ifdef __PLUMED_HAS_MPI MPI_Comm_split(communicator,color,key,&pc.communicator); #else @@ -283,7 +283,7 @@ void Communicator::Split(int color,int key,Communicator&pc)const{ #endif } -int Communicator::Status::Get_count(MPI_Datatype type)const{ +int Communicator::Status::Get_count(MPI_Datatype type)const { int i; #ifdef __PLUMED_HAS_MPI plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); diff --git a/src/tools/Communicator.h b/src/tools/Communicator.h index d7be6e7cf8..86ef8314d6 100644 --- a/src/tools/Communicator.h +++ b/src/tools/Communicator.h @@ -32,23 +32,23 @@ #include "Tensor.h" #include "Matrix.h" -namespace PLMD{ +namespace PLMD { #ifndef __PLUMED_HAS_MPI /// Surrogate of MPI_Comm when MPI library is not available - class MPI_Comm {}; +class MPI_Comm {}; /// Surrogate of MPI_Datatype when MPI library is not available - class MPI_Datatype {}; +class MPI_Datatype {}; /// Surrogate of MPI_Status when MPI library is not available - class MPI_Status {}; +class MPI_Status {}; /// Surrogate of MPI_Request when MPI library is not available - class MPI_Request {}; +class MPI_Request {}; #endif /// \ingroup TOOLBOX /// Class containing wrappers to MPI. /// All the MPI related stuff is relegated here. -class Communicator{ +class Communicator { /// Communicator MPI_Comm communicator; /// Function returning the MPI type. @@ -62,7 +62,7 @@ class Communicator{ /// is grouped into a single object. It can be built starting from /// different kinds of data. To implement compatibility of MPI wrappers /// with e.g. vectors, add constructors here. - struct Data{ + struct Data { void*pointer; int size; MPI_Datatype type; @@ -71,32 +71,32 @@ class Communicator{ /// Init from reference template explicit Data(T&p): pointer(&p), size(1), type(getMPIType()) {} /// Init from pointer to VectorGeneric - template explicit Data(VectorGeneric *p,int s): pointer(p), size(n*s), type(getMPIType()) {} + template explicit Data(VectorGeneric *p,int s): pointer(p), size(n*s), type(getMPIType()) {} /// Init from reference to VectorGeneric - template explicit Data(VectorGeneric &p): pointer(&p), size(n), type(getMPIType()) {} + template explicit Data(VectorGeneric &p): pointer(&p), size(n), type(getMPIType()) {} /// Init from pointer to TensorGeneric - template explicit Data(TensorGeneric *p,int s): pointer(p), size(n*m*s), type(getMPIType()) {} + template explicit Data(TensorGeneric *p,int s): pointer(p), size(n*m*s), type(getMPIType()) {} /// Init from reference to TensorGeneric - template explicit Data(TensorGeneric &p): pointer(&p), size(n*m), type(getMPIType()) {} + template explicit Data(TensorGeneric &p): pointer(&p), size(n*m), type(getMPIType()) {} /// Init from reference to std::vector - template explicit Data(std::vector&v){ - if(v.size()>0){ Data d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } + template explicit Data(std::vector&v) { + if(v.size()>0) { Data d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } /// Init from reference to PLMD::Matrix - template explicit Data(Matrix&m ){ - if(m.nrows()*m.ncols()>0){ Data d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } - else{ pointer=NULL; size=0; } + template explicit Data(Matrix&m ) { + if(m.nrows()*m.ncols()>0) { Data d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } + else { pointer=NULL; size=0; } } /// Init from reference to std::string - explicit Data(std::string&s){ - if(s.size()>0){ Data d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } + explicit Data(std::string&s) { + if(s.size()>0) { Data d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } }; /// Const version of Communicator::Data /// See Communicator::Data documentation - struct ConstData{ + struct ConstData { const void*pointer; int size; MPI_Datatype type; @@ -106,27 +106,27 @@ class Communicator{ template explicit ConstData(const VectorGeneric &p): pointer(&p), size(n), type(getMPIType()) {} template explicit ConstData(const TensorGeneric *p,int s): pointer(p), size(n*m*s), type(getMPIType()) {} template explicit ConstData(const TensorGeneric &p): pointer(&p), size(n*m), type(getMPIType()) {} - template explicit ConstData(const std::vector&v){ - if(v.size()>0){ ConstData d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } + template explicit ConstData(const std::vector&v) { + if(v.size()>0) { ConstData d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } - template explicit ConstData(const Matrix&m ){ - if(m.nrows()*m.ncols()>0){ ConstData d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } - else{ pointer=NULL; size=0; } + template explicit ConstData(const Matrix&m ) { + if(m.nrows()*m.ncols()>0) { ConstData d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } + else { pointer=NULL; size=0; } } - explicit ConstData(const std::string&s){ - if(s.size()>0){ ConstData d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } + explicit ConstData(const std::string&s) { + if(s.size()>0) { ConstData d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } }; public: /// Wrapper class for MPI_Status - class Status{ + class Status { int Get_count(MPI_Datatype)const; public: MPI_Status s; template - int Get_count()const{return Get_count(getMPIType());} + int Get_count()const {return Get_count(getMPIType());} }; /// Special status used when status should be ignored. /// E.g. `Recv(a,0,1,Communicator::StatusIgnore);` @@ -134,7 +134,7 @@ class Communicator{ /// `Recv(a,0,1);` static Status StatusIgnore; /// Wrapper class for MPI_Request - class Request{ + class Request { public: MPI_Request r; void wait(Status&s=StatusIgnore); @@ -178,50 +178,52 @@ class Communicator{ /// Wrapper for MPI_Allreduce with MPI_SUM (data struct) void Sum(Data); /// Wrapper for MPI_Allreduce with MPI_SUM (pointer) - template void Sum(T*buf,int count){Sum(Data(buf,count));} + template void Sum(T*buf,int count) {Sum(Data(buf,count));} /// Wrapper for MPI_Allreduce with MPI_SUM (reference) - template void Sum(T&buf){Sum(Data(buf));} + template void Sum(T&buf) {Sum(Data(buf));} /// Wrapper for MPI_Bcast (data struct) void Bcast(Data,int); /// Wrapper for MPI_Bcast (pointer) - template void Bcast(T*buf,int count,int root){Bcast(Data(buf,count),root);} + template void Bcast(T*buf,int count,int root) {Bcast(Data(buf,count),root);} /// Wrapper for MPI_Bcast (reference) - template void Bcast(T&buf,int root){Bcast(Data(buf),root);} + template void Bcast(T&buf,int root) {Bcast(Data(buf),root);} /// Wrapper for MPI_Isend (data struct) Request Isend(ConstData,int,int); /// Wrapper for MPI_Isend (pointer) - template Request Isend(const T*buf,int count,int source,int tag){return Isend(ConstData(buf,count),source,tag);} + template Request Isend(const T*buf,int count,int source,int tag) {return Isend(ConstData(buf,count),source,tag);} /// Wrapper for MPI_Isend (reference) - template Request Isend(const T&buf,int source,int tag){return Isend(ConstData(buf),source,tag);} + template Request Isend(const T&buf,int source,int tag) {return Isend(ConstData(buf),source,tag);} /// Wrapper for MPI_Allgatherv (data struct) void Allgatherv(ConstData in,Data out,const int*,const int*); /// Wrapper for MPI_Allgatherv (pointer) - template void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs){ - Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs);} + template void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs) { + Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs); + } /// Wrapper for MPI_Allgatherv (reference) - template void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs){ - Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs);} + template void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs) { + Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs); + } /// Wrapper for MPI_Allgather (data struct) void Allgather(ConstData in,Data out); /// Wrapper for MPI_Allgatherv (pointer) - template void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount){ + template void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount) { Allgather(ConstData(sendbuf,sendcount),Data(recvbuf,recvcount*Get_size())); } /// Wrapper for MPI_Allgatherv (reference) - template void Allgather(const T&sendbuf,S&recvbuf){ + template void Allgather(const T&sendbuf,S&recvbuf) { Allgather(ConstData(sendbuf),Data(recvbuf)); } /// Wrapper for MPI_Recv (data struct) void Recv(Data,int,int,Status&s=StatusIgnore); /// Wrapper for MPI_Recv (pointer) - template void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore){Recv(Data(buf,count),source,tag,s);} + template void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf,count),source,tag,s);} /// Wrapper for MPI_Recv (reference) - template void Recv(T&buf,int source,int tag,Status&s=StatusIgnore){Recv(Data(buf),source,tag,s);} + template void Recv(T&buf,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf),source,tag,s);} /// Wrapper to MPI_Comm_split void Split(int,int,Communicator&)const; diff --git a/src/tools/CubicInterpolation.cpp b/src/tools/CubicInterpolation.cpp index e52ba8b626..fd35339bd5 100644 --- a/src/tools/CubicInterpolation.cpp +++ b/src/tools/CubicInterpolation.cpp @@ -23,208 +23,209 @@ namespace PLMD { -CInterpolation::CInterpolation( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : -bold(0) +CInterpolation::CInterpolation( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : + bold(0) { plumed_assert( fmin.size()==dd.size() && fmax.size()==dd.size() ); - + np.resize( dd.size() ); stride.resize( dd.size() ); unsigned totalp=1; - for(unsigned i=0;i delr( np.size() ); - for(unsigned j=0;j(np[j]-1); - - for(unsigned i=0;i(np[j]-1); + + for(unsigned i=0; i& nspline ) const { nspline.resize( np.size() ); - for(unsigned i=0;i& pos ){ +unsigned CInterpolation::findBox( const std::vector& pos ) { plumed_dbg_massert( pos.size()==np.size(), "position size does not match the size of the grid"); unsigned jold, ccf_box, bnew=0; - for(unsigned i=0;i( std::floor( double(bold)/double(stride[i]) ) ); - bold-=jold*stride[i]; - ccf_box=search1( i, pos[i], jold ); - bnew+=ccf_box; + for(unsigned i=0; i( std::floor( double(bold)/double(stride[i]) ) ); + bold-=jold*stride[i]; + ccf_box=search1( i, pos[i], jold ); + bnew+=ccf_box; } plumed_dbg_assert( bold==0 ); bold=bnew; - for(unsigned i=0;i=splinepoints(jl,kk) && x=splinepoints(jl, kk ) ){ - while(true){ - ju=jl+inc; - if( x=(np[kk]-1)*inc ){ju=(np[kk]-1)*inc; break; } - jl=ju; - } - } - else{ - ju=jl; - while(true){ - jl=jl-inc; - if( x>=splinepoints( jl, kk ) ) break; - else if( jl<=0 ){ jl=0; break; } - ju=jl; - } - } + int inc=stride[kk], jl=jold*stride[kk], ju=(jold+1)*stride[kk], jm; + if ( x>=splinepoints(jl,kk) && x=splinepoints(jl, kk ) ) { + while(true) { + ju=jl+inc; + if( x=(np[kk]-1)*inc ) {ju=(np[kk]-1)*inc; break; } + jl=ju; + } } - while( ju-jl>inc ){ - jm = (ju+jl) / (2*inc) ; - if ( x>splinepoints(jm*inc,kk) ) jl=jm*inc; else ju=jm*inc; + else { + ju=jl; + while(true) { + jl=jl-inc; + if( x>=splinepoints( jl, kk ) ) break; + else if( jl<=0 ) { jl=0; break; } + ju=jl; + } } - plumed_dbg_assert( jl%stride[kk]==0 && ju==jl+stride[kk] ); - return jl; + } + while( ju-jl>inc ) { + jm = (ju+jl) / (2*inc) ; + if ( x>splinepoints(jm*inc,kk) ) jl=jm*inc; else ju=jm*inc; + } + plumed_dbg_assert( jl%stride[kk]==0 && ju==jl+stride[kk] ); + return jl; } InterpolateCubic::InterpolateCubic( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : -CInterpolation(dd,fmin,fmax) + CInterpolation(dd,fmin,fmax) { plumed_massert(np.size()==1,"should be one dimensional data"); clist.resize( 4*np[0] ); } -void InterpolateCubic::set_table( const std::vector& ff ){ - plumed_assert( getNumberOfSplinePoints()==ff.size() ); +void InterpolateCubic::set_table( const std::vector& ff ) { + plumed_assert( getNumberOfSplinePoints()==ff.size() ); plumed_assert( ff[0].getNumberOfDerivatives()==1 ); double d1, norm; unsigned pij; - for(unsigned i=0;i& pos ){ +double InterpolateCubic::get_fdf( const std::vector& pos ) { plumed_dbg_assert( pos.size()==1 ); - + unsigned mybox=findBox( pos ); - double d1=ub[0] - lb[0]; + double d1=ub[0] - lb[0]; double b=( pos[0] - lb[0] ) / d1, a=( ub[0] - pos[0] ) / d1; - + double *cbase=&clist[(mybox*4)+3], *c3=cbase-1, *c2=c3-1, *c1=c2-1; double f=a*(*c1) + b*(*c2) + (a*a*a-a)*(*c3) + (b*b*b-b)*(*cbase); - return f; + return f; } InterpolateBicubic::InterpolateBicubic( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : -CInterpolation(dd,fmin,fmax) + CInterpolation(dd,fmin,fmax) { plumed_massert(np.size()==2,"should be two dimensional data"); static int wt_d[16*16]= - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - -3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, 0, 0, 0, 0, - 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0,-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, - 0, 0, 0, 0, 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, - -3, 3, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0, - 9,-9, 9,-9, 6, 3,-3,-6, 6,-6,-3, 3, 4, 2, 1, 2, - -6, 6,-6, 6,-4,-2, 2, 4,-3, 3, 3,-3,-2,-1,-1,-2, - 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, - -6, 6,-6, 6,-3,-3, 3, 3,-4, 4, 2,-2,-2,-2,-1,-1, - 4,-4, 4,-4, 2, 2,-2,-2, 2,-2,-2, 2, 1, 1, 1, 1}; + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + -3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, 0, 0, 0, 0, + 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0,-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, + 0, 0, 0, 0, 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, + -3, 3, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0, + 9,-9, 9,-9, 6, 3,-3,-6, 6,-6,-3, 3, 4, 2, 1, 2, + -6, 6,-6, 6,-4,-2, 2, 4,-3, 3, 3,-3,-2,-1,-1,-2, + 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, + -6, 6,-6, 6,-3,-3, 3, 3,-4, 4, 2,-2,-2,-2,-1,-1, + 4,-4, 4,-4, 2, 2,-2,-2, 2,-2,-2, 2, 1, 1, 1, 1 + }; // This is to set up the coefficient matrix unsigned l=0; wt.resize(16,16); t1.resize(16); t2.resize(16); - for (unsigned i=0;i<16;i++) for (unsigned j=0;j<16;j++){ wt(i,j)=wt_d[l++]; } + for (unsigned i=0; i<16; i++) for (unsigned j=0; j<16; j++) { wt(i,j)=wt_d[l++]; } // Resize everything dcross.resize( np[0], np[1] ); clist.resize( np[0] * np[1] * 4 * 4 ); } -void InterpolateBicubic::set_table( const std::vector& ff ){ - plumed_assert( getNumberOfSplinePoints()==ff.size() ); +void InterpolateBicubic::set_table( const std::vector& ff ) { + plumed_assert( getNumberOfSplinePoints()==ff.size() ); plumed_assert( ff[0].getNumberOfDerivatives()==2 ); dcross=0.0; unsigned iplus, iminus; - for(unsigned i=1;i tc(4,4); std::vector y(4), dy1(4), dy2(4), d2y12(4); unsigned pij=0; unsigned ipos; - for (unsigned i=0;i& y, const std::vector& dy1, const std::vector& dy2, - const std::vector& d2y12, const double& d1, const double& d2, Matrix& c ){ +void InterpolateBicubic::IBicCoeff( const std::vector& y, const std::vector& dy1, const std::vector& dy2, + const std::vector& d2y12, const double& d1, const double& d2, Matrix& c ) { double xx, d1d2=d1*d2; - for(unsigned i=0;i<4;i++){ t1[i] = y[i]; t1[i+4] = dy1[i]*d1; t1[i+8] = dy2[i]*d2; t1[i+12] = d2y12[i]*d1d2; } - for(unsigned i=0;i<16;i++){ xx=0.0; for(unsigned k=0;k<16;k++){ xx += wt(i,k)*t1[k]; } t2[i]=xx; } - unsigned l=0; for(unsigned i=0;i<4;i++){ for(unsigned j=0;j<4;j++){ c(i,j)=t2[l++]; } } + for(unsigned i=0; i<4; i++) { t1[i] = y[i]; t1[i+4] = dy1[i]*d1; t1[i+8] = dy2[i]*d2; t1[i+12] = d2y12[i]*d1d2; } + for(unsigned i=0; i<16; i++) { xx=0.0; for(unsigned k=0; k<16; k++) { xx += wt(i,k)*t1[k]; } t2[i]=xx; } + unsigned l=0; for(unsigned i=0; i<4; i++) { for(unsigned j=0; j<4; j++) { c(i,j)=t2[l++]; } } } -double InterpolateBicubic::get_fdf( const std::vector& pos ){ +double InterpolateBicubic::get_fdf( const std::vector& pos ) { - plumed_dbg_assert( pos.size()==2 ); - unsigned mybox=findBox( pos ); - double d1 = ub[0] - lb[0], d2 = ub[1] - lb[1]; - double t = (pos[0] - lb[0]) / d1, u = (pos[1] - lb[1]) / d2; + plumed_dbg_assert( pos.size()==2 ); + unsigned mybox=findBox( pos ); + double d1 = ub[0] - lb[0], d2 = ub[1] - lb[1]; + double t = (pos[0] - lb[0]) / d1, u = (pos[1] - lb[1]) / d2; - //faster access by pointer arithmetic (dirty dirty dirty) - double *cbase=&clist[(mybox+1)*16-1], *c3, *c2, *c1, *c0; + //faster access by pointer arithmetic (dirty dirty dirty) + double *cbase=&clist[(mybox+1)*16-1], *c3, *c2, *c1, *c0; - double f=0.; - for (int i=3; i>=0; i--) { // Note to self - this has to be an int as unsigned cannot be less than zero - duh!! - c3=cbase; c2=c3-1; c1=c2-1; c0=c1-1; cbase=c0-1; - f= t*f + ( ( (*c3)*u + (*c2) )*u + (*c1) )*u + (*c0); - } - delete cbase; delete c3; delete c2; delete c1; delete c0; - return f; + double f=0.; + for (int i=3; i>=0; i--) { // Note to self - this has to be an int as unsigned cannot be less than zero - duh!! + c3=cbase; c2=c3-1; c1=c2-1; c0=c1-1; cbase=c0-1; + f= t*f + ( ( (*c3)*u + (*c2) )*u + (*c1) )*u + (*c0); + } + delete cbase; delete c3; delete c2; delete c1; delete c0; + return f; } } diff --git a/src/tools/CubicInterpolation.h b/src/tools/CubicInterpolation.h index 39ecca9684..fdbdcc3615 100644 --- a/src/tools/CubicInterpolation.h +++ b/src/tools/CubicInterpolation.h @@ -59,13 +59,13 @@ unsigned CInterpolation::getNumberOfSplinePoints() const { inline void CInterpolation::getSplinePoint( const unsigned nn, std::vector& pp ) const { plumed_dbg_assert( nn #endif -namespace PLMD{ +namespace PLMD { -bool DLLoader::installed(){ +bool DLLoader::installed() { #ifdef __PLUMED_HAS_DLOPEN return true; #else @@ -36,10 +36,10 @@ bool DLLoader::installed(){ } -void* DLLoader::load(const std::string&s){ +void* DLLoader::load(const std::string&s) { #ifdef __PLUMED_HAS_DLOPEN void* p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL); - if(!p){ + if(!p) { lastError=dlerror(); } else { lastError=""; @@ -51,20 +51,20 @@ void* DLLoader::load(const std::string&s){ #endif } -const std::string & DLLoader::error(){ +const std::string & DLLoader::error() { return lastError; } -DLLoader::~DLLoader(){ +DLLoader::~DLLoader() { #ifdef __PLUMED_HAS_DLOPEN - while(!handles.empty()){ + while(!handles.empty()) { dlclose(handles.top()); handles.pop(); } #endif } -DLLoader::DLLoader(){ +DLLoader::DLLoader() { // do nothing } diff --git a/src/tools/DLLoader.h b/src/tools/DLLoader.h index f2f76d0faf..fdad73f2a1 100644 --- a/src/tools/DLLoader.h +++ b/src/tools/DLLoader.h @@ -25,7 +25,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX /// Class taking care of dynamic loading. @@ -37,7 +37,7 @@ namespace PLMD{ /// means that they are not accessible from outside. Still, if they /// contain self-registering classes, they will register themselves /// to the ActionRegister object. -class DLLoader{ +class DLLoader { std::stack handles; std::string lastError; /// Private copy constructor diff --git a/src/tools/DynamicList.h b/src/tools/DynamicList.h index 2f006dcf57..c5252de5b0 100644 --- a/src/tools/DynamicList.h +++ b/src/tools/DynamicList.h @@ -30,7 +30,7 @@ namespace PLMD { /** \ingroup TOOLBOX A class for storing a list that changes which members are active as a function of time. It also -contains friends method that allows you to link two dynamic lists so that you can request +contains friends method that allows you to link two dynamic lists so that you can request stuff from list2 in list1 A PLMD::DynamicList can be used to change what elements in a list should be looped over at any given time. This class is, for the most part, used in tandem with PLMD::NeighbourList. For complex reasons @@ -56,10 +56,10 @@ aa to do at a given time. This is done by: \verbatim DynamicList list; std::vector aa; unsigned kk; for(unsigned i=0;i class DynamicList { /// This gathers data split across nodes list of Dynamic lists -template -friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList >& ); + template + friend void mpi_gatherActiveMembers(Communicator&, std::vector< DynamicList >& ); private: /// This is the list of all the relevent members std::vector all; @@ -155,14 +155,14 @@ friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList /// Constructor DynamicList():nactive(0),nprocessors(1),rank(0),allWereActivated(false),allWereDeactivated(false) {} /// An operator that returns the element from the current active list - inline T operator [] (const unsigned& i) const { - plumed_dbg_assert( i /// Find the index of in the list which has value t int getIndexOfElement( const T& t ) const ; /// Make a particular element inactive - void deactivate( const T& t ); + void deactivate( const T& t ); /// Make everything in the list inactive void deactivateAll(); /// Make something active @@ -204,19 +204,19 @@ friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList /// This sorts the elements in the active list void sortActiveList(); /// Retriee the list of active objects - std::vector retrieveActiveList(); + std::vector retrieveActiveList(); }; template -std::vector DynamicList::retrieveActiveList(){ +std::vector DynamicList::retrieveActiveList() { std::vector this_active(nactive); - for(unsigned k=0;k void DynamicList::clear() { - all.resize(0); + all.resize(0); onoff.resize(0); active.resize(0); } @@ -236,105 +236,105 @@ unsigned DynamicList::getNumberActive() const { } template -void DynamicList::addIndexToList( const T & ii ){ - all.push_back(ii); active.resize( all.size() ); onoff.push_back(0); +void DynamicList::addIndexToList( const T & ii ) { + all.push_back(ii); active.resize( all.size() ); onoff.push_back(0); } template -void DynamicList::createIndexListFromVector( const std::vector& myind ){ +void DynamicList::createIndexListFromVector( const std::vector& myind ) { plumed_dbg_assert( all.size()==0 ); onoff.resize( myind.size(), 0 ); - active.resize( myind.size() ); + active.resize( myind.size() ); all.insert( all.end(), myind.begin(), myind.end() ); } template -void DynamicList::setupMPICommunication( Communicator& comm ){ +void DynamicList::setupMPICommunication( Communicator& comm ) { nprocessors=comm.Get_size(); rank=comm.Get_rank(); } template int DynamicList::getIndexOfElement( const T& t ) const { - for(unsigned i=0;i -void DynamicList::deactivate( const T& t ){ +void DynamicList::deactivate( const T& t ) { plumed_dbg_assert( allWereActivated ); unsigned ii=getIndexOfElement( t ); if( onoff[ii]==0 || onoff[ii]%nprocessors!=0 ) return; // Deactivates the component if( rank==0 ) onoff[ii]=nprocessors-1; - else onoff[ii]=nprocessors-rank; + else onoff[ii]=nprocessors-rank; } template -void DynamicList::deactivateAll(){ +void DynamicList::deactivateAll() { allWereDeactivated=true; allWereActivated=false; - for(unsigned i=0;i -void DynamicList::activate( const unsigned ii ){ +void DynamicList::activate( const unsigned ii ) { plumed_dbg_massert(ii -void DynamicList::activateAll(){ - for(unsigned i=0;i::activateAll() { + for(unsigned i=0; i -void DynamicList::mpi_gatherActiveMembers(Communicator& comm){ +void DynamicList::mpi_gatherActiveMembers(Communicator& comm) { plumed_massert( comm.Get_size()==nprocessors, "error missing a call to DynamicList::setupMPICommunication"); comm.Sum(&onoff[0],onoff.size()); // When we mpi gather onoff to be on it should be active on ALL nodes - for(unsigned i=0;i0 && onoff[i]%nprocessors==0 ){ onoff[i]=nprocessors; } + for(unsigned i=0; i0 && onoff[i]%nprocessors==0 ) { onoff[i]=nprocessors; } updateActiveMembers(); } template -void DynamicList::updateActiveMembers(){ +void DynamicList::updateActiveMembers() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); unsigned kk=0; allWereActivated=allWereDeactivated=false; - for(unsigned i=0;i0 && onoff[i]%nprocessors==0 ){ active[kk]=i; kk++; } + for(unsigned i=0; i0 && onoff[i]%nprocessors==0 ) { active[kk]=i; kk++; } } - nactive=kk; + nactive=kk; } template -void DynamicList::emptyActiveMembers(){ +void DynamicList::emptyActiveMembers() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); nactive=0; } template -void DynamicList::putIndexInActiveArray( const unsigned& ii ){ +void DynamicList::putIndexInActiveArray( const unsigned& ii ) { plumed_dbg_assert( allWereActivated || allWereDeactivated ); plumed_dbg_assert( onoff[ii]>0 && onoff[ii]%nprocessors==0 ); active[nactive]=ii; nactive++; } template -void DynamicList::completeUpdate(){ +void DynamicList::completeUpdate() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); allWereActivated=allWereDeactivated=false; } template -void DynamicList::sortActiveList(){ +void DynamicList::sortActiveList() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); allWereActivated=allWereDeactivated=false; std::sort( active.begin(), active.begin()+nactive ); @@ -347,31 +347,31 @@ bool DynamicList::updateComplete() const { } template -void mpi_gatherActiveMembers(Communicator& comm, std::vector< DynamicList >& ll ){ +void mpi_gatherActiveMembers(Communicator& comm, std::vector< DynamicList >& ll ) { // Setup an array to hold all data unsigned bufsize=0; unsigned size=comm.Get_size(); - for(unsigned i=0;i buffer( bufsize ); // Gather all onoff data into a single array bufsize=0; - for(unsigned i=0;i0 && buffer[bufsize]%size==0 ) ll[i].onoff[j]=size; - else ll[i].onoff[j]=size-1; - bufsize++; - } + bufsize=0; + for(unsigned i=0; i0 && buffer[bufsize]%size==0 ) ll[i].onoff[j]=size; + else ll[i].onoff[j]=size-1; + bufsize++; + } } - for(unsigned i=0;i & positions, vector &) +void ERMSD::clear() { + reference_mat.clear(); +} - void ERMSD::setReference(const vector & reference, const std::vector & pairs_vec, double mycutoff){ +//void ERMSD::calcLcs(const vector & positions, vector &) - - natoms = reference.size(); - nresidues = natoms/3; - unsigned npairs = pairs_vec.size()/2; - pairs.resize(npairs); - //for(unsigned i=0;i<2*npairs;++i) { - // std::cout << "CCC " << pairs_vec[i] << " "; - //} - for(unsigned i=0;i & reference, const std::vector & pairs_vec, double mycutoff) { - pairs[i].first = pairs_vec[2*i]; - pairs[i].second = pairs_vec[2*i+1]; - } - cutoff = mycutoff; - std::vector > deri; - deri.resize(natoms*natoms); - reference_mat.resize(nresidues*nresidues); - Pbc fake_pbc; - - - calcMat(reference,fake_pbc,reference_mat,deri); - - } - - - bool ERMSD::inPair(unsigned i, unsigned j){ - - //return true; - if(pairs.size()==0) return true; - for(unsigned idx=0;idx > deri; + deri.resize(natoms*natoms); + reference_mat.resize(nresidues*nresidues); + Pbc fake_pbc; + + + calcMat(reference,fake_pbc,reference_mat,deri); + +} + + +bool ERMSD::inPair(unsigned i, unsigned j) { + + //return true; + if(pairs.size()==0) return true; + for(unsigned idx=0; idx & positions, // std::vector &derivatives, Tensor& virial) const { // Pbc fake_pbc; // return ERMSD::calculate(positions,fake_pbc,derivatives,virial,false); // } - - - - void ERMSD::calcMat(const std::vector & positions,const Pbc& pbc, std::vector &mat, std::vector > &Gderi) { - - std::vector pos; - pos.resize(3*nresidues); - - std::vector deri; - deri.resize(nresidues*9); - - std::vector centers; - centers.resize(nresidues); - - unsigned idx_deri = 0; - - Tensor da_dxa = (2./3.)*Tensor::identity(); - Tensor da_dxb = -(1./3.)*Tensor::identity(); - Tensor da_dxc = -(1./3.)*Tensor::identity(); - - Tensor db_dxa = -(1./3.)*Tensor::identity(); - Tensor db_dxb = (2./3.)*Tensor::identity(); - Tensor db_dxc = -(1./3.)*Tensor::identity(); - - // Form factors - should this be somewhere else? - - double w = 1./3.; - Vector form_factor = Vector(2.0,2.0,1.0/0.3); - - for(unsigned res_idx=0;res_idx drtilde_dx; - drtilde_dx.resize(6); - unsigned pos_idx = 3*i; - unsigned deri_idx = 9*i; - for (unsigned at=0;at<3;at++){ - for (unsigned l=0;l<3;l++){ - Vector3d rvec = form_factor[l]*((pos[pos_idx+l])/3.); - Vector3d vvec = form_factor[l]*(matmul(deri[deri_idx+3*at+l],diff)); - drtilde_dx[at].setRow(l,vvec-rvec); - drtilde_dx[at+3].setRow(l,rvec); - } - } - - //std::vector > dG_dx; - //dG_dx.resize(6); - - double dummy1 = (cos(gamma*rtilde_norm) - dummy); - - idx1 = i*nresidues*6 + j*6; - - for (unsigned l=0;l<6;l++){ - //std::cout << i << " " << j << " " << idx1 << " " << idx1+l << "\n"; - - // components 1,2,3 - // sin(gamma*|rtilde|)/gamma*|rtilde|*d_rtilde + - // + ((d_rtilde*r_tilde/r_tilde^2) out r_tilde)* - // (cos(gamma*|rtilde| - sin(gamma*|rtilde|)/gamma*|rtilde|)) - Vector3d rdr = matmul(rtilde,drtilde_dx[l]); - Tensor tt = dummy*drtilde_dx[l] + (dummy1*irnorm*irnorm)*Tensor(rtilde,rdr); - for (unsigned m=0;m<3;m++){ - // Transpose here - //dG_dx[l].setRow(m,tt.getRow(m)); - Gderi[idx1+l].setRow(m,tt.getRow(m)); - } - // component 4 - // - sin(gamma*|rtilde|)/|rtilde|*(r_tilde*d_rtilde) - //dG_dx[l].setRow(3,-dummy*gamma*rdr); - Gderi[idx1+l].setRow(3,-dummy*gamma*rdr); - } - - - - - } - } - } - - } +void ERMSD::calcMat(const std::vector & positions,const Pbc& pbc, std::vector &mat, std::vector > &Gderi) { + + std::vector pos; + pos.resize(3*nresidues); + + std::vector deri; + deri.resize(nresidues*9); + + std::vector centers; + centers.resize(nresidues); + + unsigned idx_deri = 0; + + Tensor da_dxa = (2./3.)*Tensor::identity(); + Tensor da_dxb = -(1./3.)*Tensor::identity(); + Tensor da_dxc = -(1./3.)*Tensor::identity(); + + Tensor db_dxa = -(1./3.)*Tensor::identity(); + Tensor db_dxb = (2./3.)*Tensor::identity(); + Tensor db_dxc = -(1./3.)*Tensor::identity(); + + // Form factors - should this be somewhere else? + + double w = 1./3.; + Vector form_factor = Vector(2.0,2.0,1.0/0.3); + + for(unsigned res_idx=0; res_idx & positions,const Pbc& pbc,\ - std::vector &derivatives, Tensor& virial) { - - - double ermsd=0.; - std::vector mat; - mat.resize(nresidues*nresidues); - - std::vector > Gderi; - Gderi.resize(natoms*natoms); - - calcMat(positions,pbc,mat,Gderi); - - unsigned idx1 = 0; - for(unsigned i=0;i0.0 && i!=j){ - - for(unsigned k=0;k<3;k++){ - idx1 = i*nresidues*6 + j*6 + k; - - derivatives[3*i+k] += matmul(dd,Gderi[idx1]); - derivatives[3*j+k] += matmul(dd,Gderi[idx1+3]); - } - ermsd += val; - } + double rtilde_norm = rtilde.modulo(); + + double irnorm = 1./rtilde_norm; + + // ellipsoidal cutoff + if(rtilde_norm < cutoff) { + idx = i*nresidues + j; + //std::cout << i << " " << j << " " << rtilde_norm << " " << idx <<"\n"; + + + // fill 4d matrix + double dummy = sin(gamma*rtilde_norm)/(rtilde_norm*gamma); + mat[idx][0] = dummy*rtilde[0]; + mat[idx][1] = dummy*rtilde[1]; + mat[idx][2] = dummy*rtilde[2]; + mat[idx][3] = (1.+ cos(gamma*rtilde_norm))/gamma; + + // Derivative (drtilde_dx) + std::vector drtilde_dx; + drtilde_dx.resize(6); + unsigned pos_idx = 3*i; + unsigned deri_idx = 9*i; + for (unsigned at=0; at<3; at++) { + for (unsigned l=0; l<3; l++) { + Vector3d rvec = form_factor[l]*((pos[pos_idx+l])/3.); + Vector3d vvec = form_factor[l]*(matmul(deri[deri_idx+3*at+l],diff)); + drtilde_dx[at].setRow(l,vvec-rvec); + drtilde_dx[at+3].setRow(l,rvec); + } + } + + //std::vector > dG_dx; + //dG_dx.resize(6); + + double dummy1 = (cos(gamma*rtilde_norm) - dummy); + + idx1 = i*nresidues*6 + j*6; + + for (unsigned l=0; l<6; l++) { + //std::cout << i << " " << j << " " << idx1 << " " << idx1+l << "\n"; + + // components 1,2,3 + // sin(gamma*|rtilde|)/gamma*|rtilde|*d_rtilde + + // + ((d_rtilde*r_tilde/r_tilde^2) out r_tilde)* + // (cos(gamma*|rtilde| - sin(gamma*|rtilde|)/gamma*|rtilde|)) + Vector3d rdr = matmul(rtilde,drtilde_dx[l]); + Tensor tt = dummy*drtilde_dx[l] + (dummy1*irnorm*irnorm)*Tensor(rtilde,rdr); + for (unsigned m=0; m<3; m++) { + // Transpose here + //dG_dx[l].setRow(m,tt.getRow(m)); + Gderi[idx1+l].setRow(m,tt.getRow(m)); + } + // component 4 + // - sin(gamma*|rtilde|)/|rtilde|*(r_tilde*d_rtilde) + //dG_dx[l].setRow(3,-dummy*gamma*rdr); + Gderi[idx1+l].setRow(3,-dummy*gamma*rdr); + } + + + + } - } - - //std::cout << ermsd << " "; - //if(pairs.size()!=0) nresidues=pairs.size(); - //std::cout << ermsd << " " << nresidues; - ermsd = sqrt(ermsd/nresidues); - double iermsd = 1.0/(ermsd*nresidues); - for(unsigned i=0;i & positions,const Pbc& pbc,\ + std::vector &derivatives, Tensor& virial) { + + + double ermsd=0.; + std::vector mat; + mat.resize(nresidues*nresidues); + + std::vector > Gderi; + Gderi.resize(natoms*natoms); + + calcMat(positions,pbc,mat,Gderi); + + unsigned idx1 = 0; + for(unsigned i=0; i0.0 && i!=j) { + + for(unsigned k=0; k<3; k++) { + idx1 = i*nresidues*6 + j*6 + k; + + derivatives[3*i+k] += matmul(dd,Gderi[idx1]); + derivatives[3*j+k] += matmul(dd,Gderi[idx1+3]); + } + ermsd += val; + } + } + } + + //std::cout << ermsd << " "; + //if(pairs.size()!=0) nresidues=pairs.size(); + //std::cout << ermsd << " " << nresidues; + ermsd = sqrt(ermsd/nresidues); + double iermsd = 1.0/(ermsd*nresidues); + for(unsigned i=0; i #include -namespace PLMD{ +namespace PLMD { class PDB; class Pbc; /// A class that implements ERMSD calculations class ERMSD { - //std::map< std::pair , double> targets; - //unsigned natoms; - std::vector reference_mat; - unsigned natoms; - unsigned nresidues; - std::vector > pairs; - double cutoff; - - public: + //std::map< std::pair , double> targets; + //unsigned natoms; + std::vector reference_mat; + unsigned natoms; + unsigned nresidues; + std::vector > pairs; + double cutoff; + +public: /// Constructor - ERMSD(): natoms(0),nresidues(0), cutoff(0.0) {} + ERMSD(): natoms(0),nresidues(0), cutoff(0.0) {} /// clear the structure - void clear(); + void clear(); - bool inPair(unsigned i, unsigned j); + bool inPair(unsigned i, unsigned j); /// set reference coordinates - void setReference(const std::vector & reference, const std::vector & pairs_vec,double mycutoff=0.24); + void setReference(const std::vector & reference, const std::vector & pairs_vec,double mycutoff=0.24); - void calcMat(const std::vector & positions, const Pbc& pbc,std::vector &mat,std::vector > & Gderivatives); + void calcMat(const std::vector & positions, const Pbc& pbc,std::vector &mat,std::vector > & Gderivatives); /// Compute ermsd ( no pbc ) // double calculate(const std::vector & positions, // std::vector &derivatives, Tensor& virial) const ; /// Compute ermsd ( with pbc ) - double calculate(const std::vector& positions, const Pbc& pbc,std::vector &derivatives, Tensor& virial); + double calculate(const std::vector& positions, const Pbc& pbc,std::vector &derivatives, Tensor& virial); }; - + } #endif diff --git a/src/tools/Exception.cpp b/src/tools/Exception.cpp index 06a989c82e..223b4b1417 100644 --- a/src/tools/Exception.cpp +++ b/src/tools/Exception.cpp @@ -21,7 +21,7 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "Exception.h" -#if defined(__PLUMED_HAS_EXECINFO) +#if defined(__PLUMED_HAS_EXECINFO) #include #endif @@ -29,12 +29,12 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { -std::string Exception::format(const std::string&msg,const std::string&file,unsigned line,const std::string&function){ +std::string Exception::format(const std::string&msg,const std::string&file,unsigned line,const std::string&function) { std::string message; message="\n+++ Internal PLUMED error"; - if(file.length()>0){ + if(file.length()>0) { char cline[1000]; sprintf(cline,"%u",line); message += "\n+++ file "+file+", line "+cline; @@ -63,7 +63,7 @@ Exception::Exception(const std::string&msg,const std::string&file,unsigned line, abortIfExceptionsAreDisabled(); } -void Exception::abortIfExceptionsAreDisabled(){ +void Exception::abortIfExceptionsAreDisabled() { #if ! defined(__PLUMED_HAS_EXCEPTIONS) #ifdef __PLUMED_HAS_EXECINFO @@ -72,7 +72,7 @@ void Exception::abortIfExceptionsAreDisabled(){ int i, frames = backtrace(callstack, 128); char** strs = backtrace_symbols(callstack, frames); for (i = 0; i < frames; ++i) { - fprintf(stderr,"%s\n", strs[i]); + fprintf(stderr,"%s\n", strs[i]); } fprintf(stderr,"******** END STACK DUMP ********\n"); free(strs); diff --git a/src/tools/Exception.h b/src/tools/Exception.h index 9ed4f1afdb..9e3c6dcf2f 100644 --- a/src/tools/Exception.h +++ b/src/tools/Exception.h @@ -25,7 +25,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -45,7 +45,7 @@ or better add an error message to that if(something_bad) throw Exception("describe the error here); \endverbatim -Even better, you can use the predefined macros +Even better, you can use the predefined macros plumed_error(), plumed_assert(), plumed_merror() and plumed_massert(), which add information about the exact location of the error in the file (filename, line and, for g++, function name). Macros ending in "error" unconditionally throw @@ -108,9 +108,9 @@ class Exception : public std::exception /// With message plus file, line and function (meant to be used through a preprocessor macro) Exception(const std::string&,const std::string&,unsigned,const std::string&); /// Returns the error message - virtual const char* what() const throw(){return msg.c_str();} + virtual const char* what() const throw() {return msg.c_str();} /// Destructor should be defined and should not throw other exceptions - virtual ~Exception() throw(){} + virtual ~Exception() throw() {} }; // With GNU compiler, we can use __PRETTY_FUNCTION__ to get the function name @@ -132,7 +132,7 @@ class Exception : public std::exception #define plumed_massert(test,msg) if(!(test)) throw PLMD::Exception("assertion failed " #test ", " msg,__FILE__,__LINE__,__PRETTY_FUNCTION__) #ifdef NDEBUG -#define plumed_dbg_assert(test) +#define plumed_dbg_assert(test) #define plumed_dbg_massert(test,msg) #else /// \relates PLMD::Exception diff --git a/src/tools/FileBase.cpp b/src/tools/FileBase.cpp index fbcd97d86a..cc38ceebfe 100644 --- a/src/tools/FileBase.cpp +++ b/src/tools/FileBase.cpp @@ -37,62 +37,62 @@ #include #endif -namespace PLMD{ +namespace PLMD { -FileBase& FileBase::link(FILE*fp){ +FileBase& FileBase::link(FILE*fp) { plumed_massert(!this->fp,"cannot link an already open file"); this->fp=fp; cloned=true; return *this; } -FileBase& FileBase::flush(){ +FileBase& FileBase::flush() { if(fp) fflush(fp); return *this; } -FileBase& FileBase::link(Communicator&comm){ +FileBase& FileBase::link(Communicator&comm) { plumed_massert(!fp,"cannot link an already open file"); this->comm=&comm; return *this; } -FileBase& FileBase::link(PlumedMain&plumed){ +FileBase& FileBase::link(PlumedMain&plumed) { plumed_massert(!fp,"cannot link an already open file"); this->plumed=&plumed; link(plumed.comm); return *this; } -FileBase& FileBase::link(Action&action){ +FileBase& FileBase::link(Action&action) { plumed_massert(!fp,"cannot link an already open file"); this->action=&action; link(action.plumed); return *this; } -bool FileBase::FileExist(const std::string& path){ +bool FileBase::FileExist(const std::string& path) { bool do_exist=false; this->path=appendSuffix(path,getSuffix()); mode="r"; FILE *ff=std::fopen(const_cast(this->path.c_str()),"r"); - if(!ff){ + if(!ff) { this->path=path; ff=std::fopen(const_cast(this->path.c_str()),"r"); mode="r"; } if(ff) {do_exist=true; fclose(ff);} if(comm) comm->Barrier(); - return do_exist; + return do_exist; } -bool FileBase::isOpen(){ +bool FileBase::isOpen() { bool isopen=false; if(fp) isopen=true; - return isopen; + return isopen; } -void FileBase::close(){ +void FileBase::close() { plumed_assert(!cloned); eof=false; err=false; @@ -127,11 +127,11 @@ FileBase::~FileBase() #endif } -FileBase::operator bool()const{ +FileBase::operator bool()const { return !eof; } -std::string FileBase::appendSuffix(const std::string&path,const std::string&suffix){ +std::string FileBase::appendSuffix(const std::string&path,const std::string&suffix) { if(path=="/dev/null") return path; // do not append a suffix to /dev/null std::string ret=path; std::string ext=Tools::extension(path); @@ -144,7 +144,7 @@ std::string FileBase::appendSuffix(const std::string&path,const std::string&suff // Removing this line, any extension recognized by Tools::extension() would be considered // if(ext!="gz" && ext!="xtc" && ext!="trr") ext=""; - if(ext.length()>0){ + if(ext.length()>0) { int l=path.length()-(ext.length()+1); plumed_assert(l>=0); ret=ret.substr(0,l); @@ -154,13 +154,13 @@ std::string FileBase::appendSuffix(const std::string&path,const std::string&suff return ret; } -FileBase& FileBase::enforceSuffix(const std::string&suffix){ +FileBase& FileBase::enforceSuffix(const std::string&suffix) { enforcedSuffix_=true; enforcedSuffix=suffix; return *this; } -std::string FileBase::getSuffix()const{ +std::string FileBase::getSuffix()const { if(enforcedSuffix_) return enforcedSuffix; if(plumed) return plumed->getSuffix(); return ""; diff --git a/src/tools/FileBase.h b/src/tools/FileBase.h index f9715511e9..e205aa2cb2 100644 --- a/src/tools/FileBase.h +++ b/src/tools/FileBase.h @@ -24,7 +24,7 @@ #include -namespace PLMD{ +namespace PLMD { class Communicator; class PlumedMain; @@ -36,7 +36,7 @@ Base class for dealing with files. This class just provides things which are common among OFile and IFile */ -class FileBase{ +class FileBase { /// Copy constructor is disabled (private and unimplemented) explicit FileBase(const FileBase&); /// Assignment operator is disabled (private and unimplemented) @@ -44,13 +44,13 @@ class FileBase{ protected: /// Internal tool. /// Base for IFile::Field and OFile::Field - class FieldBase{ + class FieldBase { // everything is public to simplify usage public: std::string name; std::string value; bool constant; - FieldBase(): constant(false){} + FieldBase(): constant(false) {} }; /// file pointer @@ -113,7 +113,7 @@ class FileBase{ /// Check for error/eof. operator bool () const; /// Set heavyFlush flag - void setHeavyFlush(){ heavyFlush=true;} + void setHeavyFlush() { heavyFlush=true;} /// Opens the file virtual FileBase& open(const std::string&name)=0; /// Check if the file exists @@ -129,12 +129,12 @@ class FileBase{ }; inline -std::string FileBase::getPath()const{ +std::string FileBase::getPath()const { return path; } inline -std::string FileBase::getMode()const{ +std::string FileBase::getMode()const { return mode; } diff --git a/src/tools/Grid.cpp b/src/tools/Grid.cpp index 72533567a5..472ae2936d 100644 --- a/src/tools/Grid.cpp +++ b/src/tools/Grid.cpp @@ -37,913 +37,913 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { -Grid::Grid(const std::string& funcl, const std::vector & args, const vector & gmin, - const vector & gmax, const vector & nbin, bool dospline, bool usederiv, bool doclear){ +Grid::Grid(const std::string& funcl, const std::vector & args, const vector & gmin, + const vector & gmax, const vector & nbin, bool dospline, bool usederiv, bool doclear) { // various checks - plumed_massert(args.size()==gmin.size(),"grid min dimensions in input do not match number of arguments"); - plumed_massert(args.size()==nbin.size(),"number of bins on input do not match number of arguments"); - plumed_massert(args.size()==gmax.size(),"grid max dimensions in input do not match number of arguments"); - unsigned dim=gmax.size(); - std::vector names; - std::vector isperiodic; - std::vector pmin,pmax; - names.resize( dim ); - isperiodic.resize( dim ); - pmin.resize( dim ); - pmax.resize( dim ); - for(unsigned int i=0;igetName(); - if( args[i]->isPeriodic() ){ - isperiodic[i]=true; + plumed_massert(args.size()==gmin.size(),"grid min dimensions in input do not match number of arguments"); + plumed_massert(args.size()==nbin.size(),"number of bins on input do not match number of arguments"); + plumed_massert(args.size()==gmax.size(),"grid max dimensions in input do not match number of arguments"); + unsigned dim=gmax.size(); + std::vector names; + std::vector isperiodic; + std::vector pmin,pmax; + names.resize( dim ); + isperiodic.resize( dim ); + pmin.resize( dim ); + pmax.resize( dim ); + for(unsigned int i=0; igetName(); + if( args[i]->isPeriodic() ) { + isperiodic[i]=true; args[i]->getDomain( pmin[i], pmax[i] ); - } else { + } else { isperiodic[i]=false; pmin[i]="0."; pmax[i]="0."; + } } - } - // this is a value-independent initializator - Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); +// this is a value-independent initializator + Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); } -Grid::Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, - const vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ){ - // this calls the initializator - Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); +Grid::Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, + const vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ) { +// this calls the initializator + Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); } -void Grid::Init(const std::string& funcl, const std::vector &names, const vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, - const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ){ - contour_location=0.0; fmt_="%14.9f"; +void Grid::Init(const std::string& funcl, const std::vector &names, const vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, + const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ) { + contour_location=0.0; fmt_="%14.9f"; // various checks - plumed_massert(names.size()==gmin.size(),"grid dimensions in input do not match number of arguments"); - plumed_massert(names.size()==nbin.size(),"grid dimensions in input do not match number of arguments"); - plumed_massert(names.size()==gmax.size(),"grid dimensions in input do not match number of arguments"); - dimension_=gmax.size(); - str_min_=gmin; str_max_=gmax; - argnames.resize( dimension_ ); - min_.resize( dimension_ ); - max_.resize( dimension_ ); - pbc_.resize( dimension_ ); - for(unsigned int i=0;imin_[i],"maximum in grid must be larger than minimum"); + plumed_massert(nbin[i]>0,"number of grid points must be greater than zero"); + } + nbin_=nbin; + dospline_=dospline; + usederiv_=usederiv; + if(dospline_) plumed_assert(dospline_==usederiv_); + maxsize_=1; + for(unsigned int i=0; i( nbin_[i] ) ); + if( !pbc_[i] ) { max_[i] += dx_[i]; nbin_[i] += 1; } + maxsize_*=nbin_[i]; + } + if(doclear) clear(); +} + +void Grid::clear() { + grid_.resize(maxsize_); + if(usederiv_) der_.resize(maxsize_); + for(index_t i=0; imin_[i],"maximum in grid must be larger than minimum"); - plumed_massert(nbin[i]>0,"number of grid points must be greater than zero"); - } - nbin_=nbin; - dospline_=dospline; - usederiv_=usederiv; - if(dospline_) plumed_assert(dospline_==usederiv_); - maxsize_=1; - for(unsigned int i=0;i( nbin_[i] ) ); - if( !pbc_[i] ){ max_[i] += dx_[i]; nbin_[i] += 1; } - maxsize_*=nbin_[i]; - } - if(doclear) clear(); -} - -void Grid::clear(){ - grid_.resize(maxsize_); - if(usederiv_) der_.resize(maxsize_); - for(index_t i=0;i Grid::getMin() const { - return str_min_; + return str_min_; } vector Grid::getMax() const { - return str_max_; + return str_max_; } vector Grid::getDx() const { - return dx_; + return dx_; } double Grid::getBinVolume() const { - double vol=1.; - for(unsigned i=0;i Grid::getIsPeriodic() const { - return pbc_; + return pbc_; } vector Grid::getNbin() const { - return nbin_; + return nbin_; } vector Grid::getArgNames() const { - return argnames; + return argnames; } Grid::index_t Grid::getSize() const { - return maxsize_; + return maxsize_; } unsigned Grid::getDimension() const { - return dimension_; + return dimension_; } // we are flattening arrays using a column-major order Grid::index_t Grid::getIndex(const vector & indices) const { - plumed_dbg_assert(indices.size()==dimension_); - for(unsigned int i=0;i=nbin_[i]) { - std::string is; - Tools::convert(i,is); - std::string msg="ERROR: the system is looking for a value outside the grid along the " + is + " ("+getArgNames()[i]+")"; - plumed_merror(msg+" index!"); + plumed_dbg_assert(indices.size()==dimension_); + for(unsigned int i=0; i=nbin_[i]) { + std::string is; + Tools::convert(i,is); + std::string msg="ERROR: the system is looking for a value outside the grid along the " + is + " ("+getArgNames()[i]+")"; + plumed_merror(msg+" index!"); + } + index_t index=indices[dimension_-1]; + for(unsigned int i=dimension_-1; i>0; --i) { + index=index*nbin_[i-1]+indices[i-1]; } - index_t index=indices[dimension_-1]; - for(unsigned int i=dimension_-1;i>0;--i){ - index=index*nbin_[i-1]+indices[i-1]; - } - return index; + return index; } Grid::index_t Grid::getIndex(const vector & x) const { - plumed_dbg_assert(x.size()==dimension_); - return getIndex(getIndices(x)); + plumed_dbg_assert(x.size()==dimension_); + return getIndex(getIndices(x)); } // we are flattening arrays using a column-major order vector Grid::getIndices(index_t index) const { - vector indices(dimension_); - index_t kk=index; - indices[0]=(index%nbin_[0]); - for(unsigned int i=1;i=2){ - indices[dimension_-1]=((kk-indices[dimension_-2])/nbin_[dimension_-2]); - } - return indices; + vector indices(dimension_); + index_t kk=index; + indices[0]=(index%nbin_[0]); + for(unsigned int i=1; i=2) { + indices[dimension_-1]=((kk-indices[dimension_-2])/nbin_[dimension_-2]); + } + return indices; } vector Grid::getIndices(const vector & x) const { - plumed_dbg_assert(x.size()==dimension_); - vector indices; - for(unsigned int i=0;i indices; + for(unsigned int i=0; i Grid::getPoint(const vector & indices) const { - plumed_dbg_assert(indices.size()==dimension_); - vector x; - for(unsigned int i=0;i x; + for(unsigned int i=0; i Grid::getPoint(index_t index) const { - plumed_dbg_assert(index Grid::getPoint(const vector & x) const { - plumed_dbg_assert(x.size()==dimension_); - return getPoint(getIndices(x)); + plumed_dbg_assert(x.size()==dimension_); + return getPoint(getIndices(x)); } -void Grid::getPoint(index_t index,std::vector & point) const{ - plumed_dbg_assert(index & point) const { + plumed_dbg_assert(index & indices,std::vector & point) const{ - plumed_dbg_assert(indices.size()==dimension_); - plumed_dbg_assert(point.size()==dimension_); - for(unsigned int i=0;i & indices,std::vector & point) const { + plumed_dbg_assert(indices.size()==dimension_); + plumed_dbg_assert(point.size()==dimension_); + for(unsigned int i=0; i & x,std::vector & point) const{ - plumed_dbg_assert(x.size()==dimension_); - getPoint(getIndices(x),point); +void Grid::getPoint(const std::vector & x,std::vector & point) const { + plumed_dbg_assert(x.size()==dimension_); + getPoint(getIndices(x),point); } vector Grid::getNeighbors - (const vector &indices,const vector &nneigh)const{ - plumed_dbg_assert(indices.size()==dimension_ && nneigh.size()==dimension_); - - vector neighbors; - vector small_bin(dimension_); - - unsigned small_nbin=1; - for(unsigned j=0;j small_indices(dimension_); - vector tmp_indices; - for(unsigned index=0;index=2){ - small_indices[dimension_-1]=((kk-small_indices[dimension_-2])/small_bin[dimension_-2]); - } - unsigned ll=0; - for(unsigned i=0;i=nbin_[i]) continue; - if( pbc_[i] && i0<0) i0=nbin_[i]-(-i0)%nbin_[i]; - if( pbc_[i] && i0>=nbin_[i]) i0%=nbin_[i]; - tmp_indices[ll]=((unsigned)i0); - ll++; - } - tmp_indices.resize(ll); - if(tmp_indices.size()==dimension_){neighbors.push_back(getIndex(tmp_indices));} - } - return neighbors; -} - +(const vector &indices,const vector &nneigh)const { + plumed_dbg_assert(indices.size()==dimension_ && nneigh.size()==dimension_); + + vector neighbors; + vector small_bin(dimension_); + + unsigned small_nbin=1; + for(unsigned j=0; j small_indices(dimension_); + vector tmp_indices; + for(unsigned index=0; index=2) { + small_indices[dimension_-1]=((kk-small_indices[dimension_-2])/small_bin[dimension_-2]); + } + unsigned ll=0; + for(unsigned i=0; i=nbin_[i]) continue; + if( pbc_[i] && i0<0) i0=nbin_[i]-(-i0)%nbin_[i]; + if( pbc_[i] && i0>=nbin_[i]) i0%=nbin_[i]; + tmp_indices[ll]=((unsigned)i0); + ll++; + } + tmp_indices.resize(ll); + if(tmp_indices.size()==dimension_) {neighbors.push_back(getIndex(tmp_indices));} + } + return neighbors; +} + vector Grid::getNeighbors - (const vector & x,const vector & nneigh)const{ - plumed_dbg_assert(x.size()==dimension_ && nneigh.size()==dimension_); - return getNeighbors(getIndices(x),nneigh); +(const vector & x,const vector & nneigh)const { + plumed_dbg_assert(x.size()==dimension_ && nneigh.size()==dimension_); + return getNeighbors(getIndices(x),nneigh); } vector Grid::getNeighbors - (index_t index,const vector & nneigh)const{ - plumed_dbg_assert(index Grid::getSplineNeighbors(const vector & indices)const{ - plumed_dbg_assert(indices.size()==dimension_); - vector neighbors; - unsigned nneigh=unsigned(pow(2.0,int(dimension_))); - - for(unsigned int i=0;i nindices; - for(unsigned int j=0;j & nneigh)const { + plumed_dbg_assert(index Grid::getSplineNeighbors(const vector & indices)const { + plumed_dbg_assert(indices.size()==dimension_); + vector neighbors; + unsigned nneigh=unsigned(pow(2.0,int(dimension_))); + + for(unsigned int i=0; i nindices; + for(unsigned int j=0; j nneighb=kernel.getSupport( dx_ ); std::vector neighbors=getNeighbors( kernel.getCenter(), nneighb ); std::vector xx( dimension_ ); std::vector vv( dimension_ ); std::string str_min, str_max; - for(unsigned i=0;isetDomain( str_min, str_max ); - } else { - vv[i]->setNotPeriodic(); - } + for(unsigned i=0; isetDomain( str_min, str_max ); + } else { + vv[i]->setNotPeriodic(); + } } std::vector der( dimension_ ); - for(unsigned i=0;iset(xx[j]); - double newval = kernel.evaluate( vv, der, usederiv_ ); - if( usederiv_ ) addValueAndDerivatives( ineigh, newval, der ); - else addValue( ineigh, newval ); + for(unsigned i=0; iset(xx[j]); + double newval = kernel.evaluate( vv, der, usederiv_ ); + if( usederiv_ ) addValueAndDerivatives( ineigh, newval, der ); + else addValue( ineigh, newval ); } - for(unsigned i=0;imaxval)maxval=grid_[i]; - } - return maxval; + double maxval; + maxval=DBL_MIN; + for(index_t i=0; imaxval)maxval=grid_[i]; + } + return maxval; } double Grid::getValue(const vector & indices) const { - return getValue(getIndex(indices)); + return getValue(getIndex(indices)); } double Grid::getValue(const vector & x) const { - if(!dospline_){ - return getValue(getIndex(x)); - } else { - vector der(dimension_); - return getValueAndDerivatives(x,der); - } + if(!dospline_) { + return getValue(getIndex(x)); + } else { + vector der(dimension_); + return getValueAndDerivatives(x,der); + } } double Grid::getValueAndDerivatives - (index_t index, vector& der) const{ - plumed_dbg_assert(index& der) const { + plumed_dbg_assert(index & indices, vector& der) const{ - return getValueAndDerivatives(getIndex(indices),der); +(const vector & indices, vector& der) const { + return getValueAndDerivatives(getIndex(indices),der); } double Grid::getValueAndDerivatives (const vector & x, vector& der) const { - plumed_dbg_assert(der.size()==dimension_ && usederiv_); - - if(dospline_){ - double X,X2,X3,value; - vector fd(dimension_); - vector C(dimension_); - vector D(dimension_); - vector dder(dimension_); + plumed_dbg_assert(der.size()==dimension_ && usederiv_); + + if(dospline_) { + double X,X2,X3,value; + vector fd(dimension_); + vector C(dimension_); + vector D(dimension_); + vector dder(dimension_); // reset - value=0.0; - for(unsigned int i=0;i indices=getIndices(x); - vector neigh=getSplineNeighbors(indices); - vector xfloor=getPoint(x); + vector indices=getIndices(x); + vector neigh=getSplineNeighbors(indices); + vector xfloor=getPoint(x); // loop over neighbors - for(unsigned int ipoint=0;ipoint nindices=getIndices(neigh[ipoint]); - double ff=1.0; - - for(unsigned j=0;j nindices=getIndices(neigh[ipoint]); + double ff=1.0; + + for(unsigned j=0; j & indices, double value){ - setValue(getIndex(indices),value); +void Grid::setValue(const vector & indices, double value) { + setValue(getIndex(indices),value); } void Grid::setValueAndDerivatives - (index_t index, double value, vector& der){ - plumed_dbg_assert(index& der) { + plumed_dbg_assert(index & indices, double value, vector& der){ - setValueAndDerivatives(getIndex(indices),value,der); +(const vector & indices, double value, vector& der) { + setValueAndDerivatives(getIndex(indices),value,der); } -void Grid::addValue(index_t index, double value){ - plumed_dbg_assert(index & indices, double value){ - addValue(getIndex(indices),value); +void Grid::addValue(const vector & indices, double value) { + addValue(getIndex(indices),value); } void Grid::addValueAndDerivatives - (index_t index, double value, vector& der){ - plumed_dbg_assert(index& der) { + plumed_dbg_assert(index & indices, double value, vector& der){ - addValueAndDerivatives(getIndex(indices),value,der); +(const vector & indices, double value, vector& der) { + addValueAndDerivatives(getIndex(indices),value,der); } -void Grid::scaleAllValuesAndDerivatives( const double& scalef ){ - if(usederiv_){ - for(index_t i=0;i xx(dimension_); - vector der(dimension_); - double f; - writeHeader(ofile); - for(index_t i=0;i0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); - for(unsigned j=0;j(nbin_[j]) ); - if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); - else ofile.printField("periodic_" + argnames[j], "false" ); - } - for(unsigned j=0;j xx(dimension_); + vector der(dimension_); + double f; + writeHeader(ofile); + for(index_t i=0; i0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); + for(unsigned j=0; j(nbin_[j]) ); + if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); + else ofile.printField("periodic_" + argnames[j], "false" ); + } + for(unsigned j=0; j pp(3); - for(pp[0]=0;pp[0] & args, IFile& ifile, - const vector & gmin,const vector & gmax, - const vector & nbin,bool dosparse, bool dospline, bool doder){ +Grid* Grid::create(const std::string& funcl, const std::vector & args, IFile& ifile, + const vector & gmin,const vector & gmax, + const vector & nbin,bool dosparse, bool dospline, bool doder) { Grid* grid=Grid::create(funcl,args,ifile,dosparse,dospline,doder); std::vector cbin( grid->getNbin() ); std::vector cmin( grid->getMin() ), cmax( grid->getMax() ); - for(unsigned i=0;iisPeriodic() ){ - plumed_massert( cbin[i]==nbin[i], "mismatched grid nbins" ); - } else { - plumed_massert( (cbin[i]-1)==nbin[i], "mismatched grid nbins"); - } + for(unsigned i=0; iisPeriodic() ) { + plumed_massert( cbin[i]==nbin[i], "mismatched grid nbins" ); + } else { + plumed_massert( (cbin[i]-1)==nbin[i], "mismatched grid nbins"); + } } return grid; } Grid* Grid::create(const std::string& funcl, const std::vector & args, IFile& ifile, bool dosparse, bool dospline, bool doder) { - Grid* grid=NULL; - unsigned nvar=args.size(); bool hasder=false; std::string pstring; - std::vector gbin1(nvar); std::vector gbin(nvar); - std::vector labels(nvar),gmin(nvar),gmax(nvar); - std::vector fieldnames; ifile.scanFieldList( fieldnames ); - // Retrieve names for fields - for(unsigned i=0;igetName(); - // And read the stuff from the header - plumed_massert( ifile.FieldExist( funcl ) , "no column labelled " + funcl + " in in grid input"); - for(unsigned i=0;i0 ); - if( args[i]->isPeriodic() ){ - plumed_massert( pstring=="true", "input value is periodic but grid is not"); - std::string pmin, pmax; - args[i]->getDomain( pmin, pmax ); gbin[i]=gbin1[i]; - if( pmin!=gmin[i] || pmax!=gmax[i] ) plumed_merror("mismatch between grid boundaries and periods of values"); - } else { - gbin[i]=gbin1[i]-1; // Note header in grid file indicates one more bin that there should be when data is not periodic - plumed_massert( pstring=="false", "input value is not periodic but grid is"); - } - hasder=ifile.FieldExist( "der_" + args[i]->getName() ); - if( doder && !hasder ) plumed_merror("missing derivatives from grid file"); - for(unsigned j=0;j xx(nvar),dder(nvar); - vector dx=grid->getDx(); - double f,x; - while( ifile.scanField(funcl,f) ){ - for(unsigned i=0;igetName(), dder[i] ); } } - index_t index=grid->getIndex(xx); - if(doder){grid->setValueAndDerivatives(index,f,dder);} - else{grid->setValue(index,f);} - ifile.scanField(); - } - return grid; + Grid* grid=NULL; + unsigned nvar=args.size(); bool hasder=false; std::string pstring; + std::vector gbin1(nvar); std::vector gbin(nvar); + std::vector labels(nvar),gmin(nvar),gmax(nvar); + std::vector fieldnames; ifile.scanFieldList( fieldnames ); +// Retrieve names for fields + for(unsigned i=0; igetName(); +// And read the stuff from the header + plumed_massert( ifile.FieldExist( funcl ), "no column labelled " + funcl + " in in grid input"); + for(unsigned i=0; i0 ); + if( args[i]->isPeriodic() ) { + plumed_massert( pstring=="true", "input value is periodic but grid is not"); + std::string pmin, pmax; + args[i]->getDomain( pmin, pmax ); gbin[i]=gbin1[i]; + if( pmin!=gmin[i] || pmax!=gmax[i] ) plumed_merror("mismatch between grid boundaries and periods of values"); + } else { + gbin[i]=gbin1[i]-1; // Note header in grid file indicates one more bin that there should be when data is not periodic + plumed_massert( pstring=="false", "input value is not periodic but grid is"); + } + hasder=ifile.FieldExist( "der_" + args[i]->getName() ); + if( doder && !hasder ) plumed_merror("missing derivatives from grid file"); + for(unsigned j=0; j xx(nvar),dder(nvar); + vector dx=grid->getDx(); + double f,x; + while( ifile.scanField(funcl,f) ) { + for(unsigned i=0; igetName(), dder[i] ); } } + index_t index=grid->getIndex(xx); + if(doder) {grid->setValueAndDerivatives(index,f,dder);} + else {grid->setValue(index,f);} + ifile.scanField(); + } + return grid; } // Sparse version of grid with map -void SparseGrid::clear(){ - map_.clear(); +void SparseGrid::clear() { + map_.clear(); } -Grid::index_t SparseGrid::getSize() const{ - return map_.size(); +Grid::index_t SparseGrid::getSize() const { + return map_.size(); } Grid::index_t SparseGrid::getMaxSize() const { - return maxsize_; + return maxsize_; } double Grid::getDifferenceFromContour( const std::vector& x, std::vector& der ) const { - return getValueAndDerivatives( x, der ) - contour_location; + return getValueAndDerivatives( x, der ) - contour_location; } void Grid::findSetOfPointsOnContour(const double& target, const std::vector& nosearch, - unsigned& npoints, std::vector >& points ){ - // Set contour location for function - contour_location=target; - // Resize points to maximum possible value - points.resize( dimension_*maxsize_ ); - - // Two points for search - std::vector ind(dimension_); - std::vector direction( dimension_, 0 ); - - // Run over whole grid - npoints=0; RootFindingBase mymin( this ); - for(unsigned i=0;isecond; - return value; + unsigned& npoints, std::vector >& points ) { +// Set contour location for function + contour_location=target; +// Resize points to maximum possible value + points.resize( dimension_*maxsize_ ); + +// Two points for search + std::vector ind(dimension_); + std::vector direction( dimension_, 0 ); + +// Run over whole grid + npoints=0; RootFindingBase mymin( this ); + for(unsigned i=0; isecond; + return value; } double SparseGrid::getValueAndDerivatives - (index_t index, vector& der)const{ - plumed_assert(indexsecond; - const auto itder=der_.find(index); - if(itder!=der_.end()) der=itder->second; - return value; +(index_t index, vector& der)const { + plumed_assert(indexsecond; + const auto itder=der_.find(index); + if(itder!=der_.end()) der=itder->second; + return value; } -void SparseGrid::setValue(index_t index, double value){ - plumed_assert(index& der){ - plumed_assert(index& der) { + plumed_assert(index& der){ - plumed_assert(index xx(dimension_); - vector der(dimension_); - double f; - writeHeader(ofile); - ofile.fmtField(" "+fmt_); - for(const auto & it : map_){ - index_t i=it.first; - xx=getPoint(i); - if(usederiv_){f=getValueAndDerivatives(i,der);} - else{f=getValue(i);} - if(i>0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); - for(unsigned j=0;j(nbin_[j]) ); - if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); - else ofile.printField("periodic_" + argnames[j], "false" ); - } - for(unsigned j=0;j &vHigh, WeightBase * ptr2obj ){ - unsigned i=0; - for(i=0;i& der) { + plumed_assert(index xx(dimension_); + vector der(dimension_); + double f; + writeHeader(ofile); + ofile.fmtField(" "+fmt_); + for(const auto & it : map_) { + index_t i=it.first; + xx=getPoint(i); + if(usederiv_) {f=getValueAndDerivatives(i,der);} + else {f=getValue(i);} + if(i>0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); + for(unsigned j=0; j(nbin_[j]) ); + if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); + else ofile.printField("periodic_" + argnames[j], "false" ); + } + for(unsigned j=0; j &vHigh, WeightBase * ptr2obj ) { + unsigned i=0; + for(i=0; i vv(vHigh.size()); + for(unsigned j=0; jprojectInnerLoop(val,myv) ; + // to be added: bias (same as before without negative sign) + //std::cerr<<" VAL: "< & proj, WeightBase *ptr2obj ) { + // find extrema only for the projection + vector smallMin,smallMax; + vector smallBin; + vector dimMapping; + vector smallIsPeriodic; + vector smallName; + + // check if the two key methods are there + WeightBase* pp = dynamic_cast(ptr2obj); + if (!pp)plumed_merror("This WeightBase is not complete: you need a projectInnerLoop and projectOuterLoop "); + + for(unsigned j=0; j vv(vHigh.size()); - for(unsigned j=0;jprojectInnerLoop(val,myv) ; - // to be added: bias (same as before without negative sign) - //std::cerr<<" VAL: "< toBeIntegrated; + for(unsigned i=0; i v; + v=smallgrid.getIndices(i); + std::vector vHigh((getArgNames()).size(),-1); + for(unsigned j=0; j(ptr2obj)){ + // // smallgrid.addValue(i,vmin);// go to 1 + // //} + double vv=smallgrid.getValue(i); + smallgrid.setValue(i,ptr2obj->projectOuterLoop(vv)); + // //if(dynamic_cast(ptr2obj)){ + // // smallgrid.addValue(i,-vmin);// bring back to the value + // //} + } + + return smallgrid; } -Grid Grid::project(const std::vector & proj , WeightBase *ptr2obj ){ - // find extrema only for the projection - vector smallMin,smallMax; - vector smallBin; - vector dimMapping; - vector smallIsPeriodic; - vector smallName; - - // check if the two key methods are there - WeightBase* pp = dynamic_cast(ptr2obj); - if (!pp)plumed_merror("This WeightBase is not complete: you need a projectInnerLoop and projectOuterLoop "); - - for(unsigned j=0;j toBeIntegrated; - for(unsigned i=0;i v; - v=smallgrid.getIndices(i); - std::vector vHigh((getArgNames()).size(),-1); - for(unsigned j=0;j(ptr2obj)){ - // // smallgrid.addValue(i,vmin);// go to 1 - // //} - double vv=smallgrid.getValue(i); - smallgrid.setValue(i,ptr2obj->projectOuterLoop(vv)); - // //if(dynamic_cast(ptr2obj)){ - // // smallgrid.addValue(i,-vmin);// bring back to the value - // //} - } - - return smallgrid; -} - -double Grid::integrate( std::vector& npoints ){ +double Grid::integrate( std::vector& npoints ) { plumed_dbg_assert( npoints.size()==dimension_ ); plumed_assert( dospline_ ); unsigned ntotgrid=1; double box_vol=1.0; std::vector ispacing( npoints.size() ); - for(unsigned j=0;j( npoints[j] ); - npoints[j]+=1; - } else { - ispacing[j] = ( max_[j] - min_[j] ) / static_cast( npoints[j] ); - } - ntotgrid*=npoints[j]; box_vol*=ispacing[j]; + for(unsigned j=0; j( npoints[j] ); + npoints[j]+=1; + } else { + ispacing[j] = ( max_[j] - min_[j] ) / static_cast( npoints[j] ); + } + ntotgrid*=npoints[j]; box_vol*=ispacing[j]; } std::vector vals( dimension_ ); std::vector t_index( dimension_ ); double integral=0.0; - for(unsigned i=0;i=2 ) t_index[dimension_-1]=((kk-t_index[dimension_-1])/npoints[dimension_-2]); + for(unsigned i=0; i=2 ) t_index[dimension_-1]=((kk-t_index[dimension_-1])/npoints[dimension_-2]); - for(unsigned j=0;j #include -namespace PLMD{ +namespace PLMD { // simple function to enable various weighting -class WeightBase{ - public: - virtual double projectInnerLoop(double &input, double &v)=0; - virtual double projectOuterLoop(double &v)=0; - virtual ~WeightBase(){} +class WeightBase { +public: + virtual double projectInnerLoop(double &input, double &v)=0; + virtual double projectOuterLoop(double &v)=0; + virtual ~WeightBase() {} }; -class BiasWeight:public WeightBase{ - public: - double beta,invbeta; - explicit BiasWeight(double v){beta=v;invbeta=1./beta;} - double projectInnerLoop(double &input, double &v){return input+exp(beta*v);} - double projectOuterLoop(double &v){return -invbeta*std::log(v);} +class BiasWeight:public WeightBase { +public: + double beta,invbeta; + explicit BiasWeight(double v) {beta=v; invbeta=1./beta;} + double projectInnerLoop(double &input, double &v) {return input+exp(beta*v);} + double projectOuterLoop(double &v) {return -invbeta*std::log(v);} }; -class ProbWeight:public WeightBase{ - public: - double beta,invbeta; - explicit ProbWeight(double v){beta=v;invbeta=1./beta;} - double projectInnerLoop(double &input, double &v){return input+v;} - double projectOuterLoop(double &v){return -invbeta*std::log(v);} +class ProbWeight:public WeightBase { +public: + double beta,invbeta; + explicit ProbWeight(double v) {beta=v; invbeta=1./beta;} + double projectInnerLoop(double &input, double &v) {return input+v;} + double projectOuterLoop(double &v) {return -invbeta*std::log(v);} }; @@ -67,200 +67,200 @@ class KernelFunctions; class Communicator; /// \ingroup TOOLBOX -class Grid +class Grid { public: // we use a size_t here // should be 8 bytes on all 64-bit machines // and more portable than "unsigned long long" - typedef size_t index_t; + typedef size_t index_t; // to restore old implementation (unsigned) use the following instead: // typedef unsigned index_t; private: - double contour_location; - std::vector grid_; - std::vector< std::vector > der_; + double contour_location; + std::vector grid_; + std::vector< std::vector > der_; protected: - std::string funcname; - std::vector argnames; - std::vector str_min_, str_max_; - std::vector min_,max_,dx_; - std::vector nbin_; - std::vector pbc_; - index_t maxsize_; - unsigned dimension_; - bool dospline_, usederiv_; - std::string fmt_; // format for output - /// get "neighbors" for spline - std::vector getSplineNeighbors(const std::vector & indices)const; + std::string funcname; + std::vector argnames; + std::vector str_min_, str_max_; + std::vector min_,max_,dx_; + std::vector nbin_; + std::vector pbc_; + index_t maxsize_; + unsigned dimension_; + bool dospline_, usederiv_; + std::string fmt_; // format for output +/// get "neighbors" for spline + std::vector getSplineNeighbors(const std::vector & indices)const; public: - /// clear grid - virtual void clear(); - /// this constructor here is Value-aware - Grid(const std::string& funcl, const std::vector & args, const std::vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, - bool usederiv, bool doclear=true); - /// this constructor here is not Value-aware - Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, - bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, - const std::vector &pmax ); - /// this is the real initializator - void Init(const std::string & funcl, const std::vector &names, const std::vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, - bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax); +/// clear grid + virtual void clear(); +/// this constructor here is Value-aware + Grid(const std::string& funcl, const std::vector & args, const std::vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, + bool usederiv, bool doclear=true); +/// this constructor here is not Value-aware + Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, + bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, + const std::vector &pmax ); +/// this is the real initializator + void Init(const std::string & funcl, const std::vector &names, const std::vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, + bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax); /// get lower boundary - std::vector getMin() const; + std::vector getMin() const; /// get upper boundary - std::vector getMax() const; + std::vector getMax() const; /// get bin size - std::vector getDx() const; + std::vector getDx() const; /// get bin volume - double getBinVolume() const; + double getBinVolume() const; /// get number of bins - std::vector getNbin() const; + std::vector getNbin() const; /// get if periodic - std::vector getIsPeriodic() const; + std::vector getIsPeriodic() const; /// get grid dimension - unsigned getDimension() const; -/// get argument names of this grid - std::vector getArgNames() const; - -/// methods to handle grid indices - std::vector getIndices(index_t index) const; - std::vector getIndices(const std::vector & x) const; - index_t getIndex(const std::vector & indices) const; - index_t getIndex(const std::vector & x) const; - std::vector getPoint(index_t index) const; - std::vector getPoint(const std::vector & indices) const; - std::vector getPoint(const std::vector & x) const; + unsigned getDimension() const; +/// get argument names of this grid + std::vector getArgNames() const; + +/// methods to handle grid indices + std::vector getIndices(index_t index) const; + std::vector getIndices(const std::vector & x) const; + index_t getIndex(const std::vector & indices) const; + index_t getIndex(const std::vector & x) const; + std::vector getPoint(index_t index) const; + std::vector getPoint(const std::vector & indices) const; + std::vector getPoint(const std::vector & x) const; /// faster versions relying on preallocated vectors - void getPoint(index_t index,std::vector & point) const; - void getPoint(const std::vector & indices,std::vector & point) const; - void getPoint(const std::vector & x,std::vector & point) const; + void getPoint(index_t index,std::vector & point) const; + void getPoint(const std::vector & indices,std::vector & point) const; + void getPoint(const std::vector & x,std::vector & point) const; /// get neighbors - std::vector getNeighbors(index_t index,const std::vector & neigh) const; - std::vector getNeighbors(const std::vector & indices,const std::vector & neigh) const; - std::vector getNeighbors(const std::vector & x,const std::vector & neigh) const; + std::vector getNeighbors(index_t index,const std::vector & neigh) const; + std::vector getNeighbors(const std::vector & indices,const std::vector & neigh) const; + std::vector getNeighbors(const std::vector & x,const std::vector & neigh) const; /// write header for grid file - void writeHeader(OFile& file); + void writeHeader(OFile& file); /// read grid from file - static Grid* create(const std::string&,const std::vector&,IFile&,bool,bool,bool); + static Grid* create(const std::string&,const std::vector&,IFile&,bool,bool,bool); /// read grid from file and check boundaries are what is expected from input - static Grid* create(const std::string&,const std::vector&, IFile&, - const std::vector&,const std::vector&, - const std::vector&,bool,bool,bool); + static Grid* create(const std::string&,const std::vector&, IFile&, + const std::vector&,const std::vector&, + const std::vector&,bool,bool,bool); /// get grid size - virtual index_t getSize() const; + virtual index_t getSize() const; /// get grid value - virtual double getValue(index_t index) const; - virtual double getValue(const std::vector & indices) const; - virtual double getValue(const std::vector & x) const; + virtual double getValue(index_t index) const; + virtual double getValue(const std::vector & indices) const; + virtual double getValue(const std::vector & x) const; /// get minimum value virtual double getMinValue() const; /// get maximum value virtual double getMaxValue() const; /// get grid value and derivatives - virtual double getValueAndDerivatives(index_t index, std::vector& der) const ; - virtual double getValueAndDerivatives(const std::vector & indices, std::vector& der) const; - virtual double getValueAndDerivatives(const std::vector & x, std::vector& der) const; + virtual double getValueAndDerivatives(index_t index, std::vector& der) const ; + virtual double getValueAndDerivatives(const std::vector & indices, std::vector& der) const; + virtual double getValueAndDerivatives(const std::vector & x, std::vector& der) const; /// Get the difference from the contour - double getDifferenceFromContour(const std::vector & x, std::vector& der) const ; + double getDifferenceFromContour(const std::vector & x, std::vector& der) const ; /// Find a set of points on a contour in the function - void findSetOfPointsOnContour(const double& target, const std::vector& nosearch, unsigned& npoints, std::vector >& points ); + void findSetOfPointsOnContour(const double& target, const std::vector& nosearch, unsigned& npoints, std::vector >& points ); -/// set grid value - virtual void setValue(index_t index, double value); - virtual void setValue(const std::vector & indices, double value); +/// set grid value + virtual void setValue(index_t index, double value); + virtual void setValue(const std::vector & indices, double value); /// set grid value and derivatives - virtual void setValueAndDerivatives(index_t index, double value, std::vector& der); - virtual void setValueAndDerivatives(const std::vector & indices, double value, std::vector& der); + virtual void setValueAndDerivatives(index_t index, double value, std::vector& der); + virtual void setValueAndDerivatives(const std::vector & indices, double value, std::vector& der); /// add to grid value - virtual void addValue(index_t index, double value); - virtual void addValue(const std::vector & indices, double value); + virtual void addValue(index_t index, double value); + virtual void addValue(const std::vector & indices, double value); /// add to grid value and derivatives - virtual void addValueAndDerivatives(index_t index, double value, std::vector& der); - virtual void addValueAndDerivatives(const std::vector & indices, double value, std::vector& der); + virtual void addValueAndDerivatives(index_t index, double value, std::vector& der); + virtual void addValueAndDerivatives(const std::vector & indices, double value, std::vector& der); /// Scale all grid values and derivatives by a constant factor - virtual void scaleAllValuesAndDerivatives( const double& scalef ); -/// Takes the scalef times the logarithm of all grid values and derivatives - virtual void logAllValuesAndDerivatives( const double& scalef ); + virtual void scaleAllValuesAndDerivatives( const double& scalef ); +/// Takes the scalef times the logarithm of all grid values and derivatives + virtual void logAllValuesAndDerivatives( const double& scalef ); /// Set the minimum value of the grid to zero and translates accordingly - virtual void setMinToZero(); -/// apply function: takes pointer to function that accepts a double and apply - virtual void applyFunctionAllValuesAndDerivatives( double (*func)(double val), double (*funcder)(double valder) ); + virtual void setMinToZero(); +/// apply function: takes pointer to function that accepts a double and apply + virtual void applyFunctionAllValuesAndDerivatives( double (*func)(double val), double (*funcder)(double valder) ); /// add a kernel function to the grid - void addKernel( const KernelFunctions& kernel ); + void addKernel( const KernelFunctions& kernel ); /// dump grid on file - virtual void writeToFile(OFile&); + virtual void writeToFile(OFile&); /// dump grid to gaussian cube file - void writeCubeFile(OFile&, const double& lunit); + void writeCubeFile(OFile&, const double& lunit); - virtual ~Grid(){} + virtual ~Grid() {} -/// project a high dimensional grid onto a low dimensional one: this should be changed at some time +/// project a high dimensional grid onto a low dimensional one: this should be changed at some time /// to enable many types of weighting - Grid project( const std::vector & proj , WeightBase *ptr2obj ); - void projectOnLowDimension(double &val , std::vector &varHigh, WeightBase* ptr2obj ); + Grid project( const std::vector & proj, WeightBase *ptr2obj ); + void projectOnLowDimension(double &val, std::vector &varHigh, WeightBase* ptr2obj ); /// set output format - void setOutputFmt(const std::string & ss){fmt_=ss;} + void setOutputFmt(const std::string & ss) {fmt_=ss;} /// Integrate the function calculated on the grid - double integrate( std::vector& npoints ); + double integrate( std::vector& npoints ); /// - void mpiSumValuesAndDerivatives( Communicator& comm ); + void mpiSumValuesAndDerivatives( Communicator& comm ); }; - + class SparseGrid : public Grid { - std::map map_; - std::map< index_t,std::vector > der_; - - protected: - void clear(); - - public: - SparseGrid(const std::string& funcl, const std::vector & args, const std::vector & gmin, - const std::vector & gmax, - const std::vector & nbin, bool dospline, bool usederiv): - Grid(funcl,args,gmin,gmax,nbin,dospline,usederiv,false){} - - index_t getSize() const; - index_t getMaxSize() const; + std::map map_; + std::map< index_t,std::vector > der_; + +protected: + void clear(); + +public: + SparseGrid(const std::string& funcl, const std::vector & args, const std::vector & gmin, + const std::vector & gmax, + const std::vector & nbin, bool dospline, bool usederiv): + Grid(funcl,args,gmin,gmax,nbin,dospline,usederiv,false) {} + + index_t getSize() const; + index_t getMaxSize() const; /// this is to access to Grid:: version of these methods (allowing overloading of virtual methods) - using Grid::getValue; - using Grid::getValueAndDerivatives; - using Grid::setValue; - using Grid::setValueAndDerivatives; - using Grid::addValue; - using Grid::addValueAndDerivatives; - - /// get grid value - double getValue(index_t index) const; + using Grid::getValue; + using Grid::getValueAndDerivatives; + using Grid::setValue; + using Grid::setValueAndDerivatives; + using Grid::addValue; + using Grid::addValueAndDerivatives; + +/// get grid value + double getValue(index_t index) const; /// get grid value and derivatives - double getValueAndDerivatives(index_t index, std::vector& der) const; + double getValueAndDerivatives(index_t index, std::vector& der) const; -/// set grid value - void setValue(index_t index, double value); +/// set grid value + void setValue(index_t index, double value); /// set grid value and derivatives - void setValueAndDerivatives(index_t index, double value, std::vector& der); + void setValueAndDerivatives(index_t index, double value, std::vector& der); /// add to grid value - void addValue(index_t index, double value); + void addValue(index_t index, double value); /// add to grid value and derivatives - void addValueAndDerivatives(index_t index, double value, std::vector& der); + void addValueAndDerivatives(index_t index, double value, std::vector& der); /// dump grid on file - void writeToFile(OFile&); + void writeToFile(OFile&); - virtual ~SparseGrid(){} + virtual ~SparseGrid() {} }; } diff --git a/src/tools/HistogramBead.cpp b/src/tools/HistogramBead.cpp index c3bd83199d..bdef4556f6 100644 --- a/src/tools/HistogramBead.cpp +++ b/src/tools/HistogramBead.cpp @@ -25,9 +25,9 @@ #include "Tools.h" #include "Keywords.h" -namespace PLMD{ +namespace PLMD { -//+PLUMEDOC INTERNAL histogrambead +//+PLUMEDOC INTERNAL histogrambead /* A function that can be used to calculate whether quantities are between fixed upper and lower bounds. @@ -36,32 +36,32 @@ for that variable using a process called kernel density estimation: \f[ P(s) = \sum_i K\left( \frac{s - s_i}{w} \right) -\f] +\f] In this equation \f$K\f$ is a symmetric funciton that must integrate to one that is often -called a kernel function and \f$w\f$ is a smearing parameter. From a pdf calculated using +called a kernel function and \f$w\f$ is a smearing parameter. From a pdf calculated using kernel density estimation we can calculate the number/fraction of values between an upper and lower bound using: \f[ w(s) = \int_a^b \sum_i K\left( \frac{s - s_i}{w} \right) -\f] +\f] -All the input to calculate a quantity like \f$w(s)\f$ is generally provided through a single +All the input to calculate a quantity like \f$w(s)\f$ is generally provided through a single keyword that will have the following form: KEYWORD={TYPE UPPER=\f$a\f$ LOWER=\f$b\f$ SMEAR=\f$\frac{w}{b-a}\f$} This will calculate the number of values between \f$a\f$ and \f$b\f$. To calculate -the fraction of values you add the word NORM to the input specification. If the +the fraction of values you add the word NORM to the input specification. If the function keyword SMEAR is not present \f$w\f$ is set equal to \f$0.5(b-a)\f$. Finally, type should specify one of the kernel types that is present in plumed. These are listed in the table below: - - - + + + @@ -74,34 +74,34 @@ is to say the number of values between \f$a\f$ and \f$b\f$, the number of values something like KEYWORD={TYPE UPPER=\f$a\f$ LOWER=\f$b\f$ NBINS=\f$n\f$ SMEAR=\f$\frac{w}{n(b-a)}\f$} - -This specification would calculate the following vector of quantities: + +This specification would calculate the following vector of quantities: \f[ -w_j(s) = \int_{a + \frac{j-1}{n}(b-a)}^{a + \frac{j}{n}(b-a)} \sum_i K\left( \frac{s - s_i}{w} \right) +w_j(s) = \int_{a + \frac{j-1}{n}(b-a)}^{a + \frac{j}{n}(b-a)} \sum_i K\left( \frac{s - s_i}{w} \right) \f] */ //+ENDPLUMEDOC -void HistogramBead::registerKeywords( Keywords& keys ){ +void HistogramBead::registerKeywords( Keywords& keys ) { keys.add("compulsory","LOWER","the lower boundary for this particular bin"); keys.add("compulsory","UPPER","the upper boundary for this particular bin"); keys.add("compulsory","SMEAR","0.5","the ammount to smear the Gaussian for each value in the distribution"); } HistogramBead::HistogramBead(): -init(false), -lowb(0.0), -highb(0.0), -width(0.0), -cutoff(std::numeric_limits::max()), -type(gaussian), -periodicity(unset), -min(0.0), -max(0.0), -max_minus_min(0.0), -inv_max_minus_min(0.0) + init(false), + lowb(0.0), + highb(0.0), + width(0.0), + cutoff(std::numeric_limits::max()), + type(gaussian), + periodicity(unset), + min(0.0), + max(0.0), + max_minus_min(0.0), + inv_max_minus_min(0.0) { } @@ -111,7 +111,7 @@ std::string HistogramBead::description() const { return ostr.str(); } -void HistogramBead::generateBins( const std::string& params, std::vector& bins ){ +void HistogramBead::generateBins( const std::string& params, std::vector& bins ) { std::vector data=Tools::getWords(params); plumed_massert(data.size()>=1,"There is no input for this keyword"); @@ -124,78 +124,78 @@ void HistogramBead::generateBins( const std::string& params, std::vector( nbins ); - for(unsigned i=0;i=highb ) errormsg="Lower bound is higher than upper bound"; - + if( !found_r ) errormsg="Upper bound has not been specified use UPPER"; + if( lowb>=highb ) errormsg="Lower bound is higher than upper bound"; + smear=0.5; Tools::parse(data,"SMEAR",smear); width=smear*(highb-lowb); init=true; } -void HistogramBead::set( double l, double h, double w){ - init=true; lowb=l; highb=h; width=w; +void HistogramBead::set( double l, double h, double w) { + init=true; lowb=l; highb=h; width=w; const double DP2CUTOFF=6.25; if( type==gaussian ) cutoff=sqrt(2.0*DP2CUTOFF); else if( type==triangular ) cutoff=1.; else plumed_error(); -} +} -void HistogramBead::setKernelType( const std::string& ktype ){ +void HistogramBead::setKernelType( const std::string& ktype ) { if(ktype=="gaussian") type=gaussian; else if(ktype=="triangular") type=triangular; - else plumed_merror("cannot understand kernel type " + ktype ); -} + else plumed_merror("cannot understand kernel type " + ktype ); +} double HistogramBead::calculate( double x, double& df ) const { - plumed_dbg_assert(init && periodicity!=unset ); + plumed_dbg_assert(init && periodicity!=unset ); double lowB, upperB, f; - if( type==gaussian ){ - lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); - upperB = difference( x, highb ) / ( sqrt(2.0) * width ); - df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); - f = 0.5*( erf( upperB ) - erf( lowB ) ); - } else if( type==triangular ){ - lowB = ( difference( x, lowb ) / width ); - upperB = ( difference( x, highb ) / width ); - df=0; - if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; - if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; - if (upperB<=-1. || lowB >=1.){ - f=0.; - } else { - double ia, ib; - if( lowB>-1.0 ){ ia=lowB; }else{ ia=-1.0; } - if( upperB<1.0 ){ ib=upperB; } else{ ib=1.0; } - f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; - } + if( type==gaussian ) { + lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); + upperB = difference( x, highb ) / ( sqrt(2.0) * width ); + df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); + f = 0.5*( erf( upperB ) - erf( lowB ) ); + } else if( type==triangular ) { + lowB = ( difference( x, lowb ) / width ); + upperB = ( difference( x, highb ) / width ); + df=0; + if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; + if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; + if (upperB<=-1. || lowB >=1.) { + f=0.; + } else { + double ia, ib; + if( lowB>-1.0 ) { ia=lowB; } else { ia=-1.0; } + if( upperB<1.0 ) { ib=upperB; } else { ib=1.0; } + f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; + } } else { - plumed_merror("function type does not exist"); - } + plumed_merror("function type does not exist"); + } return f; } @@ -204,59 +204,59 @@ double HistogramBead::calculateWithCutoff( double x, double& df ) const { double lowB, upperB, f; lowB = difference( x, lowb ) / width ; upperB = difference( x, highb ) / width; - if( upperB<=-cutoff || lowB>=cutoff ){ df=0; return 0; } - - if( type==gaussian ){ - lowB /= sqrt(2.0); upperB /= sqrt(2.0); - df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); - f = 0.5*( erf( upperB ) - erf( lowB ) ); - } else if( type==triangular ){ - df=0; - if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; - if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; - if (upperB<=-1. || lowB >=1.){ - f=0.; - } else { - double ia, ib; - if( lowB>-1.0 ){ ia=lowB; }else{ ia=-1.0; } - if( upperB<1.0 ){ ib=upperB; } else{ ib=1.0; } - f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; - } + if( upperB<=-cutoff || lowB>=cutoff ) { df=0; return 0; } + + if( type==gaussian ) { + lowB /= sqrt(2.0); upperB /= sqrt(2.0); + df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); + f = 0.5*( erf( upperB ) - erf( lowB ) ); + } else if( type==triangular ) { + df=0; + if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; + if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; + if (upperB<=-1. || lowB >=1.) { + f=0.; + } else { + double ia, ib; + if( lowB>-1.0 ) { ia=lowB; } else { ia=-1.0; } + if( upperB<1.0 ) { ib=upperB; } else { ib=1.0; } + f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; + } } else { - plumed_merror("function type does not exist"); + plumed_merror("function type does not exist"); } return f; } double HistogramBead::lboundDerivative( const double& x ) const { double lowB; - if( type==gaussian ){ - lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); - return exp( -lowB*lowB ) / ( sqrt(2*pi)*width ); - } else if ( type==triangular ){ - plumed_error(); + if( type==gaussian ) { + lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); + return exp( -lowB*lowB ) / ( sqrt(2*pi)*width ); + } else if ( type==triangular ) { + plumed_error(); // lowB = fabs( difference( x, lowb ) / width ); // if( lowB<1 ) return ( 1 - (lowB) ) / 2*width; // else return 0; } else { - plumed_merror("function type does not exist"); + plumed_merror("function type does not exist"); } return 0; } -double HistogramBead::uboundDerivative( const double& x ) const { +double HistogramBead::uboundDerivative( const double& x ) const { plumed_dbg_assert(init && periodicity!=unset ); double upperB; - if( type==gaussian ){ - upperB = difference( x, highb ) / ( sqrt(2.0) * width ); - return exp( -upperB*upperB ) / ( sqrt(2*pi)*width ); - } else if ( type==triangular ){ - plumed_error(); + if( type==gaussian ) { + upperB = difference( x, highb ) / ( sqrt(2.0) * width ); + return exp( -upperB*upperB ) / ( sqrt(2*pi)*width ); + } else if ( type==triangular ) { + plumed_error(); // upperB = fabs( difference( x, highb ) / width ); -// if( upperB<1 ) return ( 1 - (upperB) ) / 2*width; +// if( upperB<1 ) return ( 1 - (upperB) ) / 2*width; // else return 0; } else { - plumed_merror("function type does not exist"); + plumed_merror("function type does not exist"); } return 0; } diff --git a/src/tools/HistogramBead.h b/src/tools/HistogramBead.h index 44fe12054f..aae33470c5 100644 --- a/src/tools/HistogramBead.h +++ b/src/tools/HistogramBead.h @@ -34,39 +34,39 @@ class Log; /** \ingroup TOOLBOX -A class for calculating whether or not values are within a given range using : \f$ \sum_i \int_a^b G( s_i, \sigma*(b-a) ) \f$ -*/ - -class HistogramBead{ -private: - bool init; - double lowb; - double highb; - double width; - double cutoff; - enum {gaussian,triangular} type; - enum {unset,periodic,notperiodic} periodicity; - double min, max, max_minus_min, inv_max_minus_min; - double difference( const double& d1, const double& d2 ) const ; +A class for calculating whether or not values are within a given range using : \f$ \sum_i \int_a^b G( s_i, \sigma*(b-a) ) \f$ +*/ + +class HistogramBead { +private: + bool init; + double lowb; + double highb; + double width; + double cutoff; + enum {gaussian,triangular} type; + enum {unset,periodic,notperiodic} periodicity; + double min, max, max_minus_min, inv_max_minus_min; + double difference( const double& d1, const double& d2 ) const ; public: - static void registerKeywords( Keywords& keys ); - static void generateBins( const std::string& params, std::vector& bins ); - HistogramBead(); - std::string description() const ; - bool hasBeenSet() const; - void isNotPeriodic(); - void isPeriodic( const double& mlow, const double& mhigh ); - void setKernelType( const std::string& ktype ); - void set(const std::string& params, std::string& errormsg); - void set(double l, double h, double w); - double calculate(double x, double&df) const; - double calculateWithCutoff( double x, double& df ) const; - double lboundDerivative( const double& x ) const; - double uboundDerivative( const double& x ) const; - double getlowb() const ; - double getbigb() const ; - double getCutoff() const ; -}; + static void registerKeywords( Keywords& keys ); + static void generateBins( const std::string& params, std::vector& bins ); + HistogramBead(); + std::string description() const ; + bool hasBeenSet() const; + void isNotPeriodic(); + void isPeriodic( const double& mlow, const double& mhigh ); + void setKernelType( const std::string& ktype ); + void set(const std::string& params, std::string& errormsg); + void set(double l, double h, double w); + double calculate(double x, double&df) const; + double calculateWithCutoff( double x, double& df ) const; + double lboundDerivative( const double& x ) const; + double uboundDerivative( const double& x ) const; + double getlowb() const ; + double getbigb() const ; + double getCutoff() const ; +}; inline bool HistogramBead::hasBeenSet() const { @@ -74,12 +74,12 @@ bool HistogramBead::hasBeenSet() const { } inline -void HistogramBead::isNotPeriodic(){ +void HistogramBead::isNotPeriodic() { periodicity=notperiodic; } inline -void HistogramBead::isPeriodic( const double& mlow, const double& mhigh ){ +void HistogramBead::isPeriodic( const double& mlow, const double& mhigh ) { periodicity=periodic; min=mlow; max=mhigh; max_minus_min=max-min; plumed_massert(max_minus_min>0, "your function has a very strange domain?"); @@ -88,7 +88,7 @@ void HistogramBead::isPeriodic( const double& mlow, const double& mhigh ){ inline double HistogramBead::getlowb() const { return lowb; } - + inline double HistogramBead::getbigb() const { return highb; } @@ -97,9 +97,9 @@ double HistogramBead::getCutoff() const { return cutoff*width; } inline double HistogramBead::difference( const double& d1, const double& d2 ) const { - if(periodicity==notperiodic){ + if(periodicity==notperiodic) { return d2-d1; - } else if(periodicity==periodic){ + } else if(periodicity==periodic) { // Make sure the point is in the target range double newx=d1*inv_max_minus_min; newx=Tools::pbc(newx); diff --git a/src/tools/IFile.cpp b/src/tools/IFile.cpp index c1334fb5cf..5cd3261350 100644 --- a/src/tools/IFile.cpp +++ b/src/tools/IFile.cpp @@ -36,12 +36,12 @@ #include #endif -namespace PLMD{ +namespace PLMD { -size_t IFile::llread(char*ptr,size_t s){ +size_t IFile::llread(char*ptr,size_t s) { plumed_assert(fp); size_t r; - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB int rr=gzread(gzFile(gzfp),ptr,s); if(rr==0) eof=true; @@ -58,22 +58,22 @@ size_t IFile::llread(char*ptr,size_t s){ return r; } -IFile& IFile::advanceField(){ +IFile& IFile::advanceField() { plumed_assert(!inMiddleOfField); std::string line; bool done=false; - while(!done){ + while(!done) { getline(line); - if(!*this){return *this;} + if(!*this) {return *this;} std::vector words=Tools::getWords(line); - if(words.size()>=2 && words[0]=="#!" && words[1]=="FIELDS"){ + if(words.size()>=2 && words[0]=="#!" && words[1]=="FIELDS") { fields.clear(); - for(unsigned i=2;i(this->path.c_str()),"r"); - if(Tools::extension(this->path)=="gz"){ + if(Tools::extension(this->path)=="gz") { #ifdef __PLUMED_HAS_ZLIB gzfp=(void*)gzopen(const_cast(this->path.c_str()),"r"); #else @@ -122,24 +122,24 @@ IFile& IFile::open(const std::string&path){ return *this; } -IFile& IFile::scanFieldList(std::vector&s){ +IFile& IFile::scanFieldList(std::vector&s) { if(!inMiddleOfField) advanceField(); if(!*this) return *this; s.clear(); - for(unsigned i=0;i slist; - scanFieldList(slist); - int mycount = (int) std::count(slist.begin(), slist.end(), s); - if(mycount>0) return true; - else return false; +bool IFile::FieldExist(const std::string& s) { + std::vector slist; + scanFieldList(slist); + int mycount = (int) std::count(slist.begin(), slist.end(), s); + if(mycount>0) return true; + else return false; } -IFile& IFile::scanField(const std::string&name,std::string&str){ +IFile& IFile::scanField(const std::string&name,std::string&str) { if(!inMiddleOfField) advanceField(); if(!*this) return *this; unsigned i=findField(name); @@ -148,40 +148,40 @@ IFile& IFile::scanField(const std::string&name,std::string&str){ return *this; } -IFile& IFile::scanField(const std::string&name,double &x){ +IFile& IFile::scanField(const std::string&name,double &x) { std::string str; scanField(name,str); if(*this) Tools::convert(str,x); return *this; } -IFile& IFile::scanField(const std::string&name,int &x){ +IFile& IFile::scanField(const std::string&name,int &x) { std::string str; scanField(name,str); if(*this) Tools::convert(str,x); return *this; } -IFile& IFile::scanField(Value* val){ +IFile& IFile::scanField(Value* val) { double ff=NAN; // this is to be sure a NAN value is replaced upon failure scanField( val->getName(), ff ); val->set( ff ); - if( FieldExist("min_" + val->getName() ) ){ - std::string min, max; - scanField("min_" + val->getName(), min ); - scanField("max_" + val->getName(), max ); - val->setDomain( min, max ); + if( FieldExist("min_" + val->getName() ) ) { + std::string min, max; + scanField("min_" + val->getName(), min ); + scanField("max_" + val->getName(), max ); + val->setDomain( min, max ); } else { - val->setNotPeriodic(); + val->setNotPeriodic(); } return *this; } -IFile& IFile::scanField(){ - if(!ignoreFields){ - for(unsigned i=0;i0) eof=false; - } else if(eof || err || tmp!='\n'){ + if(eof && noEOL) { + if(str.length()>0) eof=false; + } else if(eof || err || tmp!='\n') { eof = true; str=""; if(!err) fsetpos(fp,&pos); @@ -227,28 +227,28 @@ IFile& IFile::getline(std::string &str){ return *this; } -unsigned IFile::findField(const std::string&name)const{ +unsigned IFile::findField(const std::string&name)const { unsigned i; - for(i=0;i=fields.size()) plumed_merror(name); return i; } -void IFile::reset(bool reset){ - eof = reset; - err = reset; - if(!reset && fp) clearerr(fp); +void IFile::reset(bool reset) { + eof = reset; + err = reset; + if(!reset && fp) clearerr(fp); #ifdef __PLUMED_HAS_ZLIB - if(!reset && gzfp) gzclearerr(gzFile(gzfp)); + if(!reset && gzfp) gzclearerr(gzFile(gzfp)); #endif - return; -} + return; +} -void IFile::allowIgnoredFields(){ +void IFile::allowIgnoredFields() { ignoreFields=true; } -void IFile::allowNoEOL(){ +void IFile::allowNoEOL() { noEOL=true; } diff --git a/src/tools/IFile.h b/src/tools/IFile.h index 222f4a8ead..2d54338df6 100644 --- a/src/tools/IFile.h +++ b/src/tools/IFile.h @@ -25,7 +25,7 @@ #include "FileBase.h" #include -namespace PLMD{ +namespace PLMD { class Value; @@ -39,9 +39,9 @@ but only for sequential input. See OFile for sequential output. */ class IFile: /// Class identifying a single field for fielded output -public virtual FileBase{ + public virtual FileBase { class Field: - public FieldBase{ + public FieldBase { public: bool read; Field(): read(false) {} @@ -66,7 +66,7 @@ public virtual FileBase{ IFile(); /// Destructor ~IFile(); -/// Opens the file +/// Opens the file IFile& open(const std::string&name); /// Gets the list of all fields IFile& scanFieldList(std::vector&); @@ -76,20 +76,20 @@ public virtual FileBase{ IFile& scanField(const std::string&,int&); /// Read a string field IFile& scanField(const std::string&,std::string&); -/** - Ends a field-formatted line. + /** + Ends a field-formatted line. -Typically used as -\verbatim - if.scanField("a",a).scanField("b",b).scanField(); -\endverbatim -*/ + Typically used as + \verbatim + if.scanField("a",a).scanField("b",b).scanField(); + \endverbatim + */ IFile& scanField(); /// Get a full line as a string IFile& getline(std::string&); -/// Reset end of file +/// Reset end of file void reset(bool); -/// Check if a field exist +/// Check if a field exist bool FieldExist(const std::string& s); /// Read in a value IFile& scanField(Value* val); diff --git a/src/tools/KernelFunctions.cpp b/src/tools/KernelFunctions.cpp index 43714d9a96..d5da1a3872 100644 --- a/src/tools/KernelFunctions.cpp +++ b/src/tools/KernelFunctions.cpp @@ -21,7 +21,7 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "KernelFunctions.h" #include "IFile.h" -#include +#include #include namespace PLMD { @@ -30,21 +30,21 @@ namespace PLMD { /* Functions that are used to construct histograms -Constructing histograms is something you learnt to do relatively early in life. You perform an experiment a number of times, -count the number of times each result comes up and then draw a bar graph that describes how often each of the results came up. -This only works when there are a finite number of possible results. If the result a number between 0 and 1 the bar chart is -less easy to draw as there are as many possible results as there are numbers between zero and one - an infinite number. -To resolve this problem we replace probability, \f$P\f$ with probability density, \f$\pi\f$, and write the probability of getting +Constructing histograms is something you learnt to do relatively early in life. You perform an experiment a number of times, +count the number of times each result comes up and then draw a bar graph that describes how often each of the results came up. +This only works when there are a finite number of possible results. If the result a number between 0 and 1 the bar chart is +less easy to draw as there are as many possible results as there are numbers between zero and one - an infinite number. +To resolve this problem we replace probability, \f$P\f$ with probability density, \f$\pi\f$, and write the probability of getting a number between \f$a\f$ and \f$b\f$ as: \f[ -P = \int_{a}^b \textrm{d}x \pi(x) +P = \int_{a}^b \textrm{d}x \pi(x) \f] -To calculate probability densities from a set of results we use a process called kernel density estimation. +To calculate probability densities from a set of results we use a process called kernel density estimation. Histograms are accumulated by adding up kernel functions, \f$K\f$, with finite spatial extent, that integrate to one. These functions are centered on each of the \f$n\f$-dimensional data points, \f$\mathbf{x}_i\f$. The overall effect of this -is that each result we obtain in our experiments contributes to the probability density in a finite sized region of the space. +is that each result we obtain in our experiments contributes to the probability density in a finite sized region of the space. Expressing all this mathematically in kernel density estimation we write the probability density as: @@ -52,17 +52,17 @@ Expressing all this mathematically in kernel density estimation we write the pro \pi(\mathbf{x}) = \sum_i K\left[ (\mathbf{x} - \mathbf{x}_i)^T \Sigma (\mathbf{x} - \mathbf{x}_i) \right] \f] -where \f$\Sigma\f$ is an \f$n \times n\f$ matrix called the bandwidth that controls the spatial extent of -the kernel. Whenever we accumulate a histogram (e.g. in \ref HISTOGRAM or in \ref METAD) we use this -technique. +where \f$\Sigma\f$ is an \f$n \times n\f$ matrix called the bandwidth that controls the spatial extent of +the kernel. Whenever we accumulate a histogram (e.g. in \ref HISTOGRAM or in \ref METAD) we use this +technique. There is thus some flexibility in the particular function we use for \f$K[\mathbf{r}]\f$ in the above. The following variants are available.
TYPE FUNCTION
TYPE FUNCTION
GAUSSIAN \f$\frac{1}{\sqrt{2\pi}w} \exp\left( -\frac{(s-s_i)^2}{2w^2} \right)\f$
TRIANGULAR \f$ \frac{1}{2w} \left( 1. - \left| \frac{s-s_i}{w} \right| \right) \quad \frac{s-s_i}{w}<1 \f$
- - - + + + @@ -79,28 +79,28 @@ space which is given by: \f{eqnarray*}{ V &=& | \Sigma^{-1} | \frac{ \pi^{\frac{n}{2}} }{\left( \frac{n}{2} \right)! } \qquad \textrm{for even} \quad n \\ -V &=& | \Sigma^{-1} | \frac{ 2^{\frac{n+1}{2}} \pi^{\frac{n-1}{2}} }{ n!! } +V &=& | \Sigma^{-1} | \frac{ 2^{\frac{n+1}{2}} \pi^{\frac{n-1}{2}} }{ n!! } \f} In \ref METAD the normalization constants are ignored so that the value of the function at \f$r=0\f$ is equal -to one. In addition in \ref METAD we must be able to differentiate the bias in order to get forces. This limits -the kernels we can use in this method. Notice also that Gaussian kernels should have infinite support. When used -with grids, however, they are assumed to only be non-zero over a finite range. The difference between the +to one. In addition in \ref METAD we must be able to differentiate the bias in order to get forces. This limits +the kernels we can use in this method. Notice also that Gaussian kernels should have infinite support. When used +with grids, however, they are assumed to only be non-zero over a finite range. The difference between the truncated-gaussian and regular gaussian is that the trucated gaussian is scaled so that its integral over the grid -is equal to one when it is normalised. The integral of a regular gaussian when it is evaluated on a grid will be -slightly less that one because of the truncation of a function that should have infinite support. +is equal to one when it is normalised. The integral of a regular gaussian when it is evaluated on a grid will be +slightly less that one because of the truncation of a function that should have infinite support. */ //+ENDPLUMEDOC -KernelFunctions::KernelFunctions( const std::string& input, const bool& normed ){ +KernelFunctions::KernelFunctions( const std::string& input, const bool& normed ) { std::vector data=Tools::getWords(input); std::string name=data[0]; data.erase(data.begin()); - std::vector at; + std::vector at; bool foundc = Tools::parseVector(data,"CENTER",at); if(!foundc) plumed_merror("failed to find center keyword in definition of kernel"); - std::vector sig; + std::vector sig; bool founds = Tools::parseVector(data,"SIGMA",sig); if(!founds) plumed_merror("failed to find sigma keyword in definition of kernel"); @@ -111,68 +111,68 @@ KernelFunctions::KernelFunctions( const std::string& input, const bool& normed ) if( !multi && center.size()>1 && sig.size()!=center.size() ) plumed_merror("size mismatch between center size and sigma size"); double h; - bool foundh = Tools::parse(data,"HEIGHT",h); + bool foundh = Tools::parse(data,"HEIGHT",h); if( !foundh) h=1.0; setData( at, sig, name, multi, h, normed ); } -KernelFunctions::KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ){ +KernelFunctions::KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ) { setData( at, sig, type, multivariate, w, norm ); } -void KernelFunctions::setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ){ +void KernelFunctions::setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ) { - center.resize( at.size() ); for(unsigned i=0;i mymatrix( getMatrix() ), myinv( ncv, ncv ); - Invert(mymatrix,myinv); double logd; - logdet( myinv, logd ); - det=std::exp(logd); + Matrix mymatrix( getMatrix() ), myinv( ncv, ncv ); + Invert(mymatrix,myinv); double logd; + logdet( myinv, logd ); + det=std::exp(logd); } double volume; - if( ktype==gaussian ){ - if( type=="GAUSSIAN" || type=="gaussian" ) volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ); - else { - // This makes it so the gaussian integrates to one over the range over which it has support - const double DP2CUTOFF=sqrt(6.25); - volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ) * pow( 0.5 * ( erf(DP2CUTOFF) - erf(-DP2CUTOFF) ), ncv); - } - } else if( ktype==uniform || ktype==triangular ){ - if( ncv%2==1 ){ - double dfact=1; - for(unsigned i=1;i(i); - volume=( pow( pi, (ncv-1)/2 ) ) * ( pow( 2., (ncv+1)/2 ) ) / dfact; - } else { - double fact=1.; - for(unsigned i=1;i(i); - volume=pow( pi,ncv/2 ) / fact; - } - if(ktype==uniform) volume*=det; - else if(ktype==triangular) volume*=det / 3.; + if( ktype==gaussian ) { + if( type=="GAUSSIAN" || type=="gaussian" ) volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ); + else { + // This makes it so the gaussian integrates to one over the range over which it has support + const double DP2CUTOFF=sqrt(6.25); + volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ) * pow( 0.5 * ( erf(DP2CUTOFF) - erf(-DP2CUTOFF) ), ncv); + } + } else if( ktype==uniform || ktype==triangular ) { + if( ncv%2==1 ) { + double dfact=1; + for(unsigned i=1; i(i); + volume=( pow( pi, (ncv-1)/2 ) ) * ( pow( 2., (ncv+1)/2 ) ) / dfact; + } else { + double fact=1.; + for(unsigned i=1; i(i); + volume=pow( pi,ncv/2 ) / fact; + } + if(ktype==uniform) volume*=det; + else if(ktype==triangular) volume*=det / 3.; } else { - plumed_merror("not a valid kernel type"); - } - height=w / volume; + plumed_merror("not a valid kernel type"); + } + height=w / volume; } else { height=w; } @@ -188,126 +188,126 @@ double KernelFunctions::getCutoff( const double& width ) const { } std::vector KernelFunctions::getContinuousSupport( ) const { - unsigned ncv=ndim(); + unsigned ncv=ndim(); std::vector support( ncv ); - if(diagonal){ - for(unsigned i=0;i mymatrix( getMatrix() ), myinv( ncv,ncv ); - Invert(mymatrix,myinv); - Matrix myautovec(ncv,ncv); std::vector myautoval(ncv); - diagMat(myinv,myautoval,myautovec); - double maxautoval;maxautoval=0.; - unsigned ind_maxautoval; - for (unsigned i=0;imaxautoval){maxautoval=myautoval[i];ind_maxautoval=i;} - } - for(unsigned i=0;i mymatrix( getMatrix() ), myinv( ncv,ncv ); + Invert(mymatrix,myinv); + Matrix myautovec(ncv,ncv); std::vector myautoval(ncv); + diagMat(myinv,myautoval,myautovec); + double maxautoval; maxautoval=0.; + unsigned ind_maxautoval; + for (unsigned i=0; imaxautoval) {maxautoval=myautoval[i]; ind_maxautoval=i;} + } + for(unsigned i=0; i KernelFunctions::getSupport( const std::vector& dx ) const { plumed_assert( ndim()==dx.size() ); std::vector support( dx.size() ); std::vector vv=getContinuousSupport( ); - for(unsigned i=0;i(ceil( vv[i]/dx[i] )); + for(unsigned i=0; i(ceil( vv[i]/dx[i] )); return support; } double KernelFunctions::evaluate( const std::vector& pos, std::vector& derivatives, bool usederiv, bool doInt, double lowI_, double uppI_) const { plumed_dbg_assert( pos.size()==ndim() && derivatives.size()==ndim() ); #ifndef NDEBUG - if( usederiv ) plumed_massert( ktype!=uniform, "step function can not be differentiated" ); + if( usederiv ) plumed_massert( ktype!=uniform, "step function can not be differentiated" ); #endif - if(doInt){ + if(doInt) { plumed_dbg_assert(center.size()==1); if(pos[0]->get()set(lowI_); if(pos[0]->get()>uppI_) pos[0]->set(uppI_); } double r2=0; - if(diagonal){ - for(unsigned i=0;idifference( center[i] ) / width[i]; - r2+=derivatives[i]*derivatives[i]; - derivatives[i] /= width[i]; - } + if(diagonal) { + for(unsigned i=0; idifference( center[i] ) / width[i]; + r2+=derivatives[i]*derivatives[i]; + derivatives[i] /= width[i]; + } } else { - Matrix mymatrix( getMatrix() ); - for(unsigned i=0;idifference( center[i] ); - for(unsigned j=0;jdifference( center[j] ); - - derivatives[i]+=mymatrix(i,j)*dp_j; - r2+=dp_i*dp_j*mymatrix(i,j); - } - } + Matrix mymatrix( getMatrix() ); + for(unsigned i=0; idifference( center[i] ); + for(unsigned j=0; jdifference( center[j] ); + + derivatives[i]+=mymatrix(i,j)*dp_j; + r2+=dp_i*dp_j*mymatrix(i,j); + } + } } double kderiv, kval; - if(ktype==gaussian){ - kval=height*std::exp(-0.5*r2); kderiv=-kval; + if(ktype==gaussian) { + kval=height*std::exp(-0.5*r2); kderiv=-kval; } else { - double r=sqrt(r2); - if(ktype==triangular){ - if( r<1.0 ){ - if(r==0) kderiv=0; - kderiv=-1; kval=height*( 1. - fabs(r) ); - } else { - kval=0.; kderiv=0.; - } - } else if(ktype==uniform){ - kderiv=0.; - if(r<1.0) kval=height; - else kval=0; - } else { - plumed_merror("Not a valid kernel type"); - } - kderiv*=height / r ; - } - for(unsigned i=0;iget() <= lowI_ || pos[0]->get() >= uppI_) && usederiv ) for(unsigned i=0;iget() <= lowI_ || pos[0]->get() >= uppI_) && usederiv ) for(unsigned i=0; i& valnames ){ +KernelFunctions* KernelFunctions::read( IFile* ifile, const std::vector& valnames ) { std::string sss; ifile->scanField("multivariate",sss); std::vector cc( valnames.size() ), sig; bool multivariate; - if( sss=="false" ){ - multivariate=false; - sig.resize( valnames.size() ); - for(unsigned i=0;iscanField(valnames[i],cc[i]); - ifile->scanField("sigma_"+valnames[i],sig[i]); - } - } else if( sss=="true" ){ - multivariate=true; - unsigned ncv=valnames.size(); - sig.resize( (ncv*(ncv+1))/2 ); - Matrix upper(ncv,ncv), lower(ncv,ncv); - for(unsigned i=0;iscanField(valnames[i],cc[i]); - for(unsigned j=0;jscanField("sigma_" +valnames[j+i] + "_" + valnames[j], lower(j+i,j) ); upper(j,j+i)=lower(j+i,j); } - } - Matrix mymult( ncv, ncv ), invmatrix(ncv,ncv); - mult(lower,upper,mymult); Invert( mymult, invmatrix ); - unsigned k=0; - for(unsigned i=0;iscanField(valnames[i],cc[i]); + ifile->scanField("sigma_"+valnames[i],sig[i]); + } + } else if( sss=="true" ) { + multivariate=true; + unsigned ncv=valnames.size(); + sig.resize( (ncv*(ncv+1))/2 ); + Matrix upper(ncv,ncv), lower(ncv,ncv); + for(unsigned i=0; iscanField(valnames[i],cc[i]); + for(unsigned j=0; jscanField("sigma_" +valnames[j+i] + "_" + valnames[j], lower(j+i,j) ); upper(j,j+i)=lower(j+i,j); } + } + Matrix mymult( ncv, ncv ), invmatrix(ncv,ncv); + mult(lower,upper,mymult); Invert( mymult, invmatrix ); + unsigned k=0; + for(unsigned i=0; iscanField("height",h); - return new KernelFunctions( cc, sig, "gaussian", multivariate ,h, false); + return new KernelFunctions( cc, sig, "gaussian", multivariate,h, false); } } diff --git a/src/tools/KernelFunctions.h b/src/tools/KernelFunctions.h index 381b831d50..a7535e0b28 100644 --- a/src/tools/KernelFunctions.h +++ b/src/tools/KernelFunctions.h @@ -42,23 +42,23 @@ class KernelFunctions { /// The height of the kernel double height; /// Used to set all the data in the kernel during construction - avoids double coding as this has two constructors - void setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate ,const double& w, const bool norm ); + void setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate,const double& w, const bool norm ); /// Convert the width into matrix form Matrix getMatrix() const; public: KernelFunctions( const std::string& input, const bool& normed ); - KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate ,const double& w, const bool norm ); + KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate,const double& w, const bool norm ); /// Get the dimensionality of the kernel unsigned ndim() const; /// Get the cutoff for a kernel double getCutoff( const double& width ) const ; -/// Get the position of the center +/// Get the position of the center std::vector getCenter() const; /// Get the support - std::vector getSupport( const std::vector& dx ) const; + std::vector getSupport( const std::vector& dx ) const; /// get it in continuous form - std::vector getContinuousSupport( ) const; -/// Evaluate the kernel function with constant intervals + std::vector getContinuousSupport( ) const; +/// Evaluate the kernel function with constant intervals double evaluate( const std::vector& pos, std::vector& derivatives, bool usederiv=true, bool doInt=false, double lowI_=-1, double uppI_=-1 ) const; /// Read a kernel function from a file static KernelFunctions* read( IFile* ifile, const std::vector& valnames ); @@ -66,11 +66,11 @@ class KernelFunctions { inline Matrix KernelFunctions::getMatrix() const { - unsigned k=0, ncv=ndim(); Matrix mymatrix(ncv,ncv); - for(unsigned i=0;i mymatrix(ncv,ncv); + for(unsigned i=0; i -namespace PLMD{ - -Keywords::KeyType::KeyType( const std::string& type ){ - if( type=="compulsory" ){ - style=compulsory; - } else if( type=="flag" ){ - style=flag; - } else if( type=="optional" ){ - style=optional; - } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ){ - style=atoms; - } else if( type=="hidden" ){ - style=hidden; - } else if( type=="vessel" ){ - style=vessel; +namespace PLMD { + +Keywords::KeyType::KeyType( const std::string& type ) { + if( type=="compulsory" ) { + style=compulsory; + } else if( type=="flag" ) { + style=flag; + } else if( type=="optional" ) { + style=optional; + } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) { + style=atoms; + } else if( type=="hidden" ) { + style=hidden; + } else if( type=="vessel" ) { + style=vessel; } else { - plumed_massert(false,"invalid keyword specifier " + type); - } -} - -void Keywords::KeyType::setStyle( const std::string& type ){ - if( type=="compulsory" ){ - style=compulsory; - } else if( type=="flag" ){ - style=flag; - } else if( type=="optional" ){ - style=optional; - } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ){ - style=atoms; - } else if( type=="hidden" ){ - style=hidden; - } else if( type=="vessel" ){ - style=vessel; + plumed_massert(false,"invalid keyword specifier " + type); + } +} + +void Keywords::KeyType::setStyle( const std::string& type ) { + if( type=="compulsory" ) { + style=compulsory; + } else if( type=="flag" ) { + style=flag; + } else if( type=="optional" ) { + style=optional; + } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) { + style=atoms; + } else if( type=="hidden" ) { + style=hidden; + } else if( type=="vessel" ) { + style=vessel; } else { - plumed_massert(false,"invalid keyword specifier " + type); - } + plumed_massert(false,"invalid keyword specifier " + type); + } } -void Keywords::add( const Keywords& newkeys ){ - newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs ); +void Keywords::add( const Keywords& newkeys ) { + newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs ); } -void Keywords::copyData( std::vector& kk, std::vector& rk, std::map& tt, std::map& am, +void Keywords::copyData( std::vector& kk, std::vector& rk, std::map& tt, std::map& am, std::map& docs, std::map& bools, std::map& nums, std::map& atags, std::vector& cnam, std::map& ck, std::map& cd ) const { - for(unsigned i=0;i( thiskey,types.find(thiskey)->second) ); - if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); - plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); - am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); - plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); - docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); - if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); - if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); - } - for(unsigned i=0;i( thiskey,types.find(thiskey)->second) ); - if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); - plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); - am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); - plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); - docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); - if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); - if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); - } - for(unsigned i=0;i( thisnam, ckey.find(thisnam)->second) ); - plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" ); - cd.insert( std::pair( thisnam, cdocs.find(thisnam)->second) ); - } -} - -void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ){ + for(unsigned i=0; i( thiskey,types.find(thiskey)->second) ); + if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); + plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); + am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); + plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); + docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); + if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); + if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); + } + for(unsigned i=0; i( thiskey,types.find(thiskey)->second) ); + if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); + plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); + am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); + plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); + docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); + if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); + if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); + } + for(unsigned i=0; i( thisnam, ckey.find(thisnam)->second) ); + plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" ); + cd.insert( std::pair( thisnam, cdocs.find(thisnam)->second) ); + } +} + +void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ) { plumed_assert( !exists(k) && !reserved(k) ); std::string fd, lowkey=k; // Convert to lower case std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower); - // Remove any underscore characters - for(unsigned i=0;;++i){ - std::size_t num=lowkey.find_first_of("_"); - if( num==std::string::npos ) break; - lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 ); - } - if( t=="vessel" ){ - fd = d + " The final value can be referenced using label." + lowkey; - if(d.find("flag")==std::string::npos) fd += ". You can use multiple instances of this keyword i.e. " + - k +"1, " + k + "2, " + k + "3... The corresponding values are then " - "referenced using label."+ lowkey +"-1, label." + lowkey + - "-2, label." + lowkey + "-3..."; - allowmultiple.insert( std::pair(k,true) ); - types.insert( std::pair(k,KeyType("vessel")) ); - } else if( t=="numbered" ){ - fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; - allowmultiple.insert( std::pair(k,true) ); - types.insert( std::pair(k,KeyType("optional")) ); +// Remove any underscore characters + for(unsigned i=0;; ++i) { + std::size_t num=lowkey.find_first_of("_"); + if( num==std::string::npos ) break; + lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 ); + } + if( t=="vessel" ) { + fd = d + " The final value can be referenced using label." + lowkey; + if(d.find("flag")==std::string::npos) fd += ". You can use multiple instances of this keyword i.e. " + + k +"1, " + k + "2, " + k + "3... The corresponding values are then " + "referenced using label."+ lowkey +"-1, label." + lowkey + + "-2, label." + lowkey + "-3..."; + allowmultiple.insert( std::pair(k,true) ); + types.insert( std::pair(k,KeyType("vessel")) ); + } else if( t=="numbered" ) { + fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; + allowmultiple.insert( std::pair(k,true) ); + types.insert( std::pair(k,KeyType("optional")) ); } else { - fd = d; - if( t=="atoms" && isaction ) fd = d + ". For more information on how to specify lists of atoms see \\ref Group"; - allowmultiple.insert( std::pair(k,false) ); - types.insert( std::pair(k,KeyType(t)) ); - if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); + fd = d; + if( t=="atoms" && isaction ) fd = d + ". For more information on how to specify lists of atoms see \\ref Group"; + allowmultiple.insert( std::pair(k,false) ); + types.insert( std::pair(k,KeyType(t)) ); + if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); } - documentation.insert( std::pair(k,fd) ); - reserved_keys.push_back(k); + documentation.insert( std::pair(k,fd) ); + reserved_keys.push_back(k); } -void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ){ - plumed_assert( !exists(k) && !reserved(k) ); +void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ) { + plumed_assert( !exists(k) && !reserved(k) ); std::string defstr; if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; } types.insert( std::pair(k,KeyType("flag")) ); std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower); fd=defstr + d; - documentation.insert( std::pair(k,fd) ); + documentation.insert( std::pair(k,fd) ); allowmultiple.insert( std::pair(k,false) ); - booldefs.insert( std::pair(k,def) ); - reserved_keys.push_back(k); + booldefs.insert( std::pair(k,def) ); + reserved_keys.push_back(k); } -void Keywords::use( const std::string & k ){ +void Keywords::use( const std::string & k ) { plumed_massert( reserved(k), "the " + k + " keyword is not reserved"); - for(unsigned i=0;isecond).setStyle(style); - if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true; + if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true; if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,style) ); } -void Keywords::add( const std::string & t, const std::string & k, const std::string & d ){ - plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel" , "keyword " + k + " has already been registered"); +void Keywords::add( const std::string & t, const std::string & k, const std::string & d ) { + plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel", "keyword " + k + " has already been registered"); std::string fd; - if( t=="numbered" ){ - fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; - allowmultiple.insert( std::pair(k,true) ); - types.insert( std::pair(k, KeyType("optional")) ); - } else { - fd=d; - allowmultiple.insert( std::pair(k,false) ); - types.insert( std::pair(k,KeyType(t)) ); - if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); + if( t=="numbered" ) { + fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; + allowmultiple.insert( std::pair(k,true) ); + types.insert( std::pair(k, KeyType("optional")) ); + } else { + fd=d; + allowmultiple.insert( std::pair(k,false) ); + types.insert( std::pair(k,KeyType(t)) ); + if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); } if( t=="atoms" && isaction ) fd = d + ". For more information on how to specify lists of atoms see \\ref Group"; documentation.insert( std::pair(k,fd) ); - keys.push_back(k); + keys.push_back(k); } -void Keywords::add( const std::string & t, const std::string & k, const std::string & def, const std::string & d ){ +void Keywords::add( const std::string & t, const std::string & k, const std::string & def, const std::string & d ) { plumed_assert( !exists(k) && !reserved(k) && (t=="compulsory" || t=="hidden" )); // An optional keyword can't have a default - types.insert( std::pair(k, KeyType(t)) ); + types.insert( std::pair(k, KeyType(t)) ); documentation.insert( std::pair(k,"( default=" + def + " ) " + d) ); allowmultiple.insert( std::pair(k,false) ); numdefs.insert( std::pair(k,def) ); - keys.push_back(k); -} + keys.push_back(k); +} -void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ){ - plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered"); +void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ) { + plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered"); std::string defstr; if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; } types.insert( std::pair(k,KeyType("flag")) ); documentation.insert( std::pair(k,defstr + d) ); allowmultiple.insert( std::pair(k,false) ); - booldefs.insert( std::pair(k,def) ); - keys.push_back(k); -} + booldefs.insert( std::pair(k,def) ); + keys.push_back(k); +} -void Keywords::remove( const std::string & k ){ +void Keywords::remove( const std::string & k ) { bool found=false; unsigned j=0, n=0; - while(true){ - for(j=0;jsecond).toString()==t ) return true; - return false; + return false; } unsigned Keywords::size() const { @@ -252,15 +252,15 @@ std::string Keywords::getKeyword( const unsigned i ) const { } bool Keywords::exists( const std::string & k ) const { - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if( nkeys>0 ){ + if( nkeys>0 ) { std::string prevtag="start"; - for(unsigned i=0;isecond).isAtomList() ){ - plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); - if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break; - if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=", keys[i].c_str() ); - else printf(" %s=", keys[i].c_str() ); - prevtag=atomtags.find(keys[i])->second; - } + for(unsigned i=0; isecond).isAtomList() ) { + plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); + if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break; + if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=", keys[i].c_str() ); + else printf(" %s=", keys[i].c_str() ); + prevtag=atomtags.find(keys[i])->second; + } } } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; - } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isCompulsory() ){ - std::string def; - if( getDefaultValue( keys[i], def) ){ - printf(" %s=%s ", keys[i].c_str(), def.c_str() ); - } else { - printf(" %s= ", keys[i].c_str() ); - } - } else if (include_optional) { - // TG no defaults for optional keywords? - printf(" [%s]", keys[i].c_str() ); - } - } + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; + } + if( nkeys>0 ) { + for(unsigned i=0; isecond).isCompulsory() ) { + std::string def; + if( getDefaultValue( keys[i], def) ) { + printf(" %s=%s ", keys[i].c_str(), def.c_str() ); + } else { + printf(" %s= ", keys[i].c_str() ); + } + } else if (include_optional) { + // TG no defaults for optional keywords? + printf(" [%s]", keys[i].c_str() ); + } + } } printf("\n"); } void Keywords::print_vim() const { - for(unsigned i=0;isecond).isFlag() ){ - printf( ",flag:%s", keys[i].c_str() ); - } else { - if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() ); - else printf(",option:%s",keys[i].c_str() ); - } + for(unsigned i=0; isecond).isFlag() ) { + printf( ",flag:%s", keys[i].c_str() ); + } else { + if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() ); + else printf(",option:%s",keys[i].c_str() ); + } } fprintf(stdout,"\n"); print(stdout); @@ -322,171 +322,171 @@ void Keywords::print_vim() const { void Keywords::print_html() const { // This is the part that outputs the details of the components - if( cnames.size()>0 ){ - unsigned ndef=0; - for(unsigned i=0;isecond=="default") ndef++; - } + if( cnames.size()>0 ) { + unsigned ndef=0; + for(unsigned i=0; isecond=="default") ndef++; + } - if( ndef>0 ){ - std::cout<<"\\par Description of components\n\n"; - std::cout< \n"; - printf("\n"); - unsigned nndef=0; - for(unsigned i=0;isecond=="default" ); - if( ckey.find(cnames[i])->second!="default" ){ nndef++; continue; } + if( ndef>0 ) { + std::cout<<"\\par Description of components\n\n"; + std::cout< \n"; + printf("\n"); + unsigned nndef=0; + for(unsigned i=0; isecond=="default" ); + if( ckey.find(cnames[i])->second!="default" ) { nndef++; continue; } + printf("\n"); + printf("\n",cnames[i].c_str() ); + printf("\n",(cdocs.find(cnames[i])->second).c_str() ); + printf("\n"); + } + std::cout<<"
TYPE FUNCTION
TYPE FUNCTION
gaussian \f$f(r) = \frac{1}{(2 \pi)^{n} \sqrt{|\Sigma^{-1}|}} \exp\left(-0.5 r^2 \right)\f$
truncated-gaussian \f$f(r) = \frac{1}{(2 \pi)^{n} \sqrt{|\Sigma^{-1}|} \left(\frac{\erf(-6.25/sqrt{2}) - \erf(-6.25/sqrt{2})}{2}\right)^n} \exp\left(-0.5 r^2 \right)\f$
Quantity Description
Quantity Description
%s %s
\n\n"; + if( nndef>0 ) { + std::cout<<"In addition the following quantities can be calculated by employing the keywords listed below"< \n"; + printf(" Quantity Keyword Description \n"); + for(unsigned i=0; isecond!="default") { printf("\n"); - printf(" %s \n",cnames[i].c_str() ); + printf(" %s %s \n", + cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); printf("\n"); - } - std::cout<<"\n\n"; - if( nndef>0 ){ - std::cout<<"In addition the following quantities can be calculated by employing the keywords listed below"< \n"; - printf(" Quantity Keyword Description \n"); - for(unsigned i=0;isecond!="default"){ - printf("\n"); - printf(" %s %s \n", - cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); - printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); - printf("\n"); - } - } - std::cout<<"\n\n"; - } - } else { - unsigned nregs=0; - for(unsigned i=0;isecond) ) nregs++; - } - if( nregs>0 ){ - std::cout<<"\\par Description of components\n\n"; - std::cout< \n"; - printf(" Quantity Keyword Description \n"); - for(unsigned i=0;isecond) ){ - printf("\n"); - printf(" %s %s \n", - cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); - printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); - printf("\n"); - } - } - std::cout<<"\n\n"; - } + } + } + std::cout<<"\n\n"; + } + } else { + unsigned nregs=0; + for(unsigned i=0; isecond) ) nregs++; + } + if( nregs>0 ) { + std::cout<<"\\par Description of components\n\n"; + std::cout< \n"; + printf(" Quantity Keyword Description \n"); + for(unsigned i=0; isecond) ) { + printf("\n"); + printf(" %s %s \n", + cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); + printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); + printf("\n"); + } + } + std::cout<<"\n\n"; } + } } unsigned nkeys=0; - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if( nkeys>0 ){ + if( nkeys>0 ) { if(isaction) std::cout<<"\\par The atoms involved can be specified using\n\n"; else std::cout<<"\\par The input trajectory is specified using one of the following\n\n"; std::cout<<" \n"; std::string prevtag="start"; - for(unsigned i=0;isecond).isAtomList() ){ - plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); - if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ){ - std::cout<<"
\n\n"; - std::cout<<"\\par Or alternatively by using\n\n"; - std::cout<<" \n"; - } - print_html_item( keys[i] ); - prevtag=atomtags.find(keys[i])->second; + for(unsigned i=0; isecond).isAtomList() ) { + plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); + if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ) { + std::cout<<"
\n\n"; + std::cout<<"\\par Or alternatively by using\n\n"; + std::cout<<" \n"; } + print_html_item( keys[i] ); + prevtag=atomtags.find(keys[i])->second; + } } std::cout<<"
\n\n"; } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; - } - if( nkeys>0 ){ - if(isaction) std::cout<< "\\par Compulsory keywords\n\n"; - else std::cout<<"\\par The following must be present\n\n"; - std::cout<<" \n"; - for(unsigned i=0;isecond).isCompulsory() ) print_html_item( keys[i] ); - } - std::cout<<"
\n\n"; + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; + } + if( nkeys>0 ) { + if(isaction) std::cout<< "\\par Compulsory keywords\n\n"; + else std::cout<<"\\par The following must be present\n\n"; + std::cout<<" \n"; + for(unsigned i=0; isecond).isCompulsory() ) print_html_item( keys[i] ); + } + std::cout<<"
\n\n"; } nkeys=0; - for(unsigned i=0;isecond).isFlag() || (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; - } - if( nkeys>0 ){ - if(isaction) std::cout<<"\\par Options\n\n"; - else std::cout<<"\\par The following options are available\n\n"; - std::cout<<" \n"; - for(unsigned i=0;isecond).isFlag() ) print_html_item( keys[i] ); - } - std::cout<<"\n"; + for(unsigned i=0; isecond).isFlag() || (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; + } + if( nkeys>0 ) { + if(isaction) std::cout<<"\\par Options\n\n"; + else std::cout<<"\\par The following options are available\n\n"; + std::cout<<"
\n"; + for(unsigned i=0; isecond).isFlag() ) print_html_item( keys[i] ); + } + std::cout<<"\n"; } nkeys=0; - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) print_html_item( keys[i] ); - } - std::cout<<"\n"; + if( nkeys>0 ) { + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) print_html_item( keys[i] ); + } + std::cout<<"\n"; } std::cout<<"
\n\n"; } void Keywords::print( FILE* out ) const { unsigned nkeys=0; - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if( nkeys>0 ){ - fprintf(out,"The input trajectory can be in any of the following formats: \n\n"); - for(unsigned i=0;isecond).isAtomList() ) printKeyword( keys[i], out ); - } + if( nkeys>0 ) { + fprintf(out,"The input trajectory can be in any of the following formats: \n\n"); + for(unsigned i=0; isecond).isAtomList() ) printKeyword( keys[i], out ); + } } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; } unsigned ncompulsory=nkeys; - if( nkeys>0 ){ - fprintf(out,"\nThe following arguments are compulsory: \n\n"); - for(unsigned i=0;isecond).isCompulsory() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); - } - } - nkeys=0; - for(unsigned i=0;isecond).isFlag() ) nkeys++; - } - if( nkeys>0 ){ - if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n"); - else fprintf( out,"\nThe following options are available\n\n"); - for(unsigned i=0;isecond).isFlag() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); - } + if( nkeys>0 ) { + fprintf(out,"\nThe following arguments are compulsory: \n\n"); + for(unsigned i=0; isecond).isCompulsory() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + } + nkeys=0; + for(unsigned i=0; isecond).isFlag() ) nkeys++; + } + if( nkeys>0 ) { + if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n"); + else fprintf( out,"\nThe following options are available\n\n"); + for(unsigned i=0; isecond).isFlag() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } } nkeys=0; - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); - } - fprintf(out,"\n"); + if( nkeys>0 ) { + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + fprintf(out,"\n"); } } @@ -495,59 +495,59 @@ void Keywords::printKeyword( const std::string& key, FILE* out ) const { std::vector w=Tools::getWords( documentation.find(key)->second ); fprintf(out,"%23s - ", key.c_str() ); unsigned nl=0; std::string blank=" "; - for(unsigned i=0;i60 ){ - fprintf(out,"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; - } else { - fprintf(out,"%s ", w[i].c_str() ); - } - if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot + for(unsigned i=0; i60 ) { + fprintf(out,"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; + } else { + fprintf(out,"%s ", w[i].c_str() ); + } + if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot } fprintf(out,"\n"); } void Keywords::print( Log& log ) const { unsigned nkeys=0; - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if (nkeys>0 ){ - log.printf( "The input for this keyword can be specified using one of the following \n\n"); - for(unsigned i=0;isecond).isAtomList() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } + if (nkeys>0 ) { + log.printf( "The input for this keyword can be specified using one of the following \n\n"); + for(unsigned i=0; isecond).isAtomList() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; } - if( nkeys>0 ){ - log.printf( "\n The compulsory keywords for this action are: \n\n"); - for(unsigned i=0;isecond).isCompulsory() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } + if( nkeys>0 ) { + log.printf( "\n The compulsory keywords for this action are: \n\n"); + for(unsigned i=0; isecond).isCompulsory() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } } nkeys=0; - for(unsigned i=0;isecond).isFlag() ) nkeys++; + for(unsigned i=0; isecond).isFlag() ) nkeys++; } - if( nkeys>0 ){ - log.printf( "\n The following options are available: \n\n"); - for(unsigned i=0;isecond).isFlag() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } - log.printf("\n"); + if( nkeys>0 ) { + log.printf( "\n The following options are available: \n\n"); + for(unsigned i=0; isecond).isFlag() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } + log.printf("\n"); } nkeys=0; - for(unsigned i=0;isecond).isOptional() ) nkeys++; + for(unsigned i=0; isecond).isOptional() ) nkeys++; } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isOptional() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } - log.printf("\n"); + if( nkeys>0 ) { + for(unsigned i=0; isecond).isOptional() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } + log.printf("\n"); } } @@ -556,14 +556,14 @@ void Keywords::printKeyword( const std::string& key, Log& log ) const { std::vector w=Tools::getWords( documentation.find(key)->second ); log.printf("%23s - ", key.c_str() ); unsigned nl=0; std::string blank=" "; - for(unsigned i=0;i60 ){ - log.printf("\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; - } else { - log.printf("%s ", w[i].c_str() ); - } - if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot + for(unsigned i=0; i60 ) { + log.printf("\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; + } else { + log.printf("%s ", w[i].c_str() ); + } + if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot } log.printf("\n"); } @@ -581,42 +581,42 @@ std::string Keywords::get( const unsigned k ) const { } bool Keywords::getLogicalDefault( std::string key, bool& def ) const { - if( booldefs.find(key)!=booldefs.end() ){ - def=booldefs.find(key)->second; - return true; - } else { - return false; - } + if( booldefs.find(key)!=booldefs.end() ) { + def=booldefs.find(key)->second; + return true; + } else { + return false; + } } bool Keywords::getDefaultValue( std::string key, std::string& def ) const { - plumed_assert( style(key,"compulsory") || style(key,"hidden") ); + plumed_assert( style(key,"compulsory") || style(key,"hidden") ); - if( numdefs.find(key)!=numdefs.end() ){ - def=numdefs.find(key)->second; - return true; - } else { - return false; - } + if( numdefs.find(key)!=numdefs.end() ) { + def=numdefs.find(key)->second; + return true; + } else { + return false; + } } -void Keywords::destroyData(){ - keys.clear(); reserved_keys.clear(); types.clear(); - allowmultiple.clear(); documentation.clear(); - booldefs.clear(); numdefs.clear(); atomtags.clear(); - ckey.clear(); cdocs.clear(); ckey.clear(); +void Keywords::destroyData() { + keys.clear(); reserved_keys.clear(); types.clear(); + allowmultiple.clear(); documentation.clear(); + booldefs.clear(); numdefs.clear(); atomtags.clear(); + ckey.clear(); cdocs.clear(); ckey.clear(); } -void Keywords::setComponentsIntroduction( const std::string& instr ){ +void Keywords::setComponentsIntroduction( const std::string& instr ) { cstring = instr; } -void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ){ +void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ) { plumed_assert( !outputComponentExists( name, false ) ); plumed_massert( name.find("-")==std::string::npos,"dash is reseved character in component names" ); std::size_t num2=name.find_first_of("_"); - if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning"); + if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning"); ckey.insert( std::pair(name,key) ); cdocs.insert( std::pair(name,descr) ); @@ -629,15 +629,15 @@ bool Keywords::outputComponentExists( const std::string& name, const bool& custo std::string sname; std::size_t num=name.find_first_of("-"); if( num!=std::string::npos ) sname=name.substr(0,num); else { - std::size_t num2=name.find_first_of("_"); - if( num2!=std::string::npos ) sname=name.substr(num2); - else sname=name; + std::size_t num2=name.find_first_of("_"); + if( num2!=std::string::npos ) sname=name.substr(num2); + else sname=name; } - for(unsigned i=0;i documentation; /// The default values for the flags (are they on or of) - std::map booldefs; + std::map booldefs; /// The default values (if there are default values) for compulsory keywords std::map numdefs; /// The tags for atoms - we use this so the manual can differentiate between different ways of specifying atoms @@ -94,12 +94,12 @@ friend class Action; /// Constructor Keywords() : isaction(true) {} /// - void isDriver(){ isaction=false; } + void isDriver() { isaction=false; } /// find out whether flag key is on or off by default. bool getLogicalDefault( std::string key, bool& def ) const ; /// Get the value of the default for the keyword named key bool getDefaultValue( std::string key, std::string& def ) const ; -/// Return the number of defined keywords +/// Return the number of defined keywords unsigned size() const; /// Check if numbered keywords are allowed for this action bool numbered( const std::string & k ) const ; @@ -109,7 +109,7 @@ friend class Action; void print( Log& log ) const ; /// Print the documentation to a file (use by PLUMED::CLTool::readCommandLineArgs) void print( FILE* out ) const ; -/// Reserve a keyword +/// Reserve a keyword void reserve( const std::string & t, const std::string & k, const std::string & d ); /// Reserve a flag void reserveFlag( const std::string & k, const bool def, const std::string & d ); @@ -143,9 +143,9 @@ friend class Action; void add( const Keywords& keys ); /// Copy the keywords data void copyData( std::vector& kk, std::vector& rk, std::map& tt, std::map& am, - std::map& docs, std::map& bools, std::map& nums, - std::map& atags, std::vector& cnam, std::map& ck, - std::map& cd ) const ; + std::map& docs, std::map& bools, std::map& nums, + std::map& atags, std::vector& cnam, std::map& ck, + std::map& cd ) const ; /// Clear everything from the keywords object void destroyData(); /// Set the text that introduces how the components for this action are introduced diff --git a/src/tools/LatticeReduction.cpp b/src/tools/LatticeReduction.cpp index e8658025d2..c0bc6b1d03 100644 --- a/src/tools/LatticeReduction.cpp +++ b/src/tools/LatticeReduction.cpp @@ -23,26 +23,26 @@ #include "Exception.h" #include -namespace PLMD{ +namespace PLMD { using namespace std; const double epsilon=1e-14; -void LatticeReduction::sort(Vector v[3]){ +void LatticeReduction::sort(Vector v[3]) { const double onePlusEpsilon=(1.0+epsilon); - for(int i=0;i<3;i++) for(int j=i+1;j<3;j++) if(modulo2(v[i])>modulo2(v[j])){ - Vector x=v[i]; v[i]=v[j]; v[j]=x; - } - for(int i=0;i<2;i++) plumed_assert(modulo2(v[i])<=modulo2(v[i+1])*onePlusEpsilon); + for(int i=0; i<3; i++) for(int j=i+1; j<3; j++) if(modulo2(v[i])>modulo2(v[j])) { + Vector x=v[i]; v[i]=v[j]; v[j]=x; + } + for(int i=0; i<2; i++) plumed_assert(modulo2(v[i])<=modulo2(v[i+1])*onePlusEpsilon); } -void LatticeReduction::reduce(Vector&a,Vector&b){ +void LatticeReduction::reduce(Vector&a,Vector&b) { double ma=modulo2(a); double mb=modulo2(b); unsigned counter=0; - while(true){ - if(mb>ma){ + while(true) { + if(mb>ma) { Vector t(a); a=b; b=t; double mt(ma); ma=mb; mb=mt; } @@ -56,16 +56,16 @@ void LatticeReduction::reduce(Vector&a,Vector&b){ Vector t(a); a=b; b=t; } -void LatticeReduction::reduce2(Vector&a,Vector&b,Vector&c){ +void LatticeReduction::reduce2(Vector&a,Vector&b,Vector&c) { Vector v[3]; v[0]=a; v[1]=b; v[2]=c; int iter=0; int ok=0; - while(ok<3){ + while(ok<3) { int i,j; - if(iter%3==0){ + if(iter%3==0) { i=0; j=1; - } else if(iter%3==1){ + } else if(iter%3==1) { i=0; j=2; } else { i=1; j=2; @@ -80,15 +80,15 @@ void LatticeReduction::reduce2(Vector&a,Vector&b,Vector&c){ a=v[0]; b=v[1]; c=v[2]; } -bool LatticeReduction::isReduced(const Vector&a,const Vector&b){ +bool LatticeReduction::isReduced(const Vector&a,const Vector&b) { const int cut=5; - for(int i=-cut;i<=cut;i++){ + for(int i=-cut; i<=cut; i++) { if(modulo2(b+i*a)=modulo2(v[2])) break; counter++; if(counter%10000==0) fprintf(stderr,"WARNING: LatticeReduction::reduceFast stuck after %u iterations\n",counter); @@ -148,7 +148,7 @@ void LatticeReduction::reduceFast(Tensor&t){ } -void LatticeReduction::reduceSlow(Tensor&t){ +void LatticeReduction::reduceSlow(Tensor&t) { Vector v[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); @@ -157,14 +157,14 @@ void LatticeReduction::reduceSlow(Tensor&t){ double e01=dotProduct(v[0],v[1]); double e02=dotProduct(v[0],v[2]); double e12=dotProduct(v[1],v[2]); - if(e01*e02*e12<0){ + if(e01*e02*e12<0) { int eps01=0; if(e01>0.0) eps01=1; else if(e01<0.0) eps01=-1; int eps02=0; if(e02>0.0) eps02=1; else if(e02<0.0) eps02=-1; Vector n=v[0]-eps01*v[1]-eps02*v[2]; int i=0; double mx=modulo2(v[i]); - for(int j=1;j<3;j++){ + for(int j=1; j<3; j++) { double f=modulo2(v[j]); - if(f>mx){ + if(f>mx) { i=j; mx=f; } @@ -177,23 +177,23 @@ void LatticeReduction::reduceSlow(Tensor&t){ t.setRow(2,v[2]); } -bool LatticeReduction::isReduced2(const Vector&a,const Vector&b,const Vector &c){ +bool LatticeReduction::isReduced2(const Vector&a,const Vector&b,const Vector &c) { return isReduced(a,b) && isReduced(a,b) && isReduced(b,c); } -bool LatticeReduction::isReduced(const Tensor&t){ +bool LatticeReduction::isReduced(const Tensor&t) { Vector v[3]; double m[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); v[2]=t.getRow(2); - for(int i=0;i<3;i++) m[i]=modulo2(v[i]); + for(int i=0; i<3; i++) m[i]=modulo2(v[i]); if(!((m[0]<=m[1]) && m[1]<=m[2])) return false; const int cut=5; - for(int i=-cut;i<=cut;i++){ + for(int i=-cut; i<=cut; i++) { double mm=modulo2(v[1]+i*v[0]); if(mm& pos, const std::vector& indices, const Pbc& pbc ){ +void LinkCells::buildCellLists( const std::vector& pos, const std::vector& indices, const Pbc& pbc ) { plumed_assert( cutoffwasset && pos.size()==indices.size() ); // Must be able to check that pbcs are not nonsensical in some way?? -- GAT @@ -51,54 +51,54 @@ void LinkCells::buildCellLists( const std::vector& pos, const std::vecto mypbc.setBox( pbc.getBox() ); // Setup the lists - if( pos.size()!=allcells.size() ){ - allcells.resize( pos.size() ); lcell_lists.resize( pos.size() ); + if( pos.size()!=allcells.size() ) { + allcells.resize( pos.size() ); lcell_lists.resize( pos.size() ); } - { + { // This is the reciprocal lattice // notice that reciprocal.getRow(0) is a vector that is orthogonal to b and c // This allows to use linked cells in non orthorhomic boxes - Tensor reciprocal(transpose(mypbc.getInvBox())); - ncells[0] = std::floor( 1.0/ reciprocal.getRow(0).modulo() / link_cutoff ); - if( ncells[0]==0 ) ncells[0]=1; - ncells[1] = std::floor( 1.0/ reciprocal.getRow(1).modulo() / link_cutoff ); - if( ncells[1]==0 ) ncells[1]=1; - ncells[2] = std::floor( 1.0/ reciprocal.getRow(2).modulo() / link_cutoff ); - if( ncells[2]==0 ) ncells[2]=1; + Tensor reciprocal(transpose(mypbc.getInvBox())); + ncells[0] = std::floor( 1.0/ reciprocal.getRow(0).modulo() / link_cutoff ); + if( ncells[0]==0 ) ncells[0]=1; + ncells[1] = std::floor( 1.0/ reciprocal.getRow(1).modulo() / link_cutoff ); + if( ncells[1]==0 ) ncells[1]=1; + ncells[2] = std::floor( 1.0/ reciprocal.getRow(2).modulo() / link_cutoff ); + if( ncells[2]==0 ) ncells[2]=1; } // Setup the strides nstride[0]=1; nstride[1]=ncells[0]; nstride[2]=ncells[0]*ncells[1]; // Setup the storage for link cells unsigned ncellstot=ncells[0]*ncells[1]*ncells[2]; - if( lcell_tots.size()!=ncellstot ){ - lcell_tots.resize( ncellstot ); lcell_starts.resize( ncellstot ); + if( lcell_tots.size()!=ncellstot ) { + lcell_tots.resize( ncellstot ); lcell_starts.resize( ncellstot ); } // Clear nlcells - for(unsigned i=0;i& pos, const std::vecto void LinkCells::addRequiredCells( const std::vector& celn, unsigned& ncells_required, std::vector& cells_required ) const { unsigned nnew_cells=0; - for(int nx=LINKC_MIN(ncells[0]);nx& cell_list, - unsigned& natomsper, std::vector& atoms ) const { +void LinkCells::retrieveNeighboringAtoms( const Vector& pos, std::vector& cell_list, + unsigned& natomsper, std::vector& atoms ) const { if( cell_list.size()!=getNumberOfCells() ) cell_list.resize( getNumberOfCells() ); unsigned ncellt=0; addRequiredCells( findMyCell( pos ), ncellt, cell_list ); - retrieveAtomsInCells( ncellt, cell_list, natomsper, atoms ); + retrieveAtomsInCells( ncellt, cell_list, natomsper, atoms ); } -void LinkCells::retrieveAtomsInCells( const unsigned& ncells_required, - const std::vector& cells_required, +void LinkCells::retrieveAtomsInCells( const unsigned& ncells_required, + const std::vector& cells_required, unsigned& natomsper, std::vector& atoms ) const { plumed_assert( natomsper==1 || natomsper==2 ); // This is really a bug. If you are trying to reuse this ask GAT for help - for(unsigned i=0;i LinkCells::findMyCell( const Vector& pos ) const { Vector fpos=mypbc.realToScaled( pos ); std::vector celn(3); - for(unsigned j=0;j<3;++j){ - celn[j] = std::floor( ( Tools::pbc(fpos[j]) + 0.5 ) * ncells[j] ); - plumed_assert( celn[j]>=0 && celn[j]=0 && celn[j] findMyCell( const Vector& pos ) const ; + std::vector findMyCell( const Vector& pos ) const ; /// Get the list of cells we need to surround the a particular cell void addRequiredCells( const std::vector& celn, unsigned& ncells_required, std::vector& cells_required ) const ; @@ -81,7 +81,7 @@ class LinkCells { const std::vector& cells_required, unsigned& natomsper, std::vector& atoms ) const ; /// Retrieve the atoms we need to consider - void retrieveNeighboringAtoms( const Vector& pos, std::vector& cell_list, unsigned& natomsper, std::vector& atoms ) const ; + void retrieveNeighboringAtoms( const Vector& pos, std::vector& cell_list, unsigned& natomsper, std::vector& atoms ) const ; }; inline diff --git a/src/tools/Log.h b/src/tools/Log.h index c0a378fe61..c25ca3f383 100644 --- a/src/tools/Log.h +++ b/src/tools/Log.h @@ -24,7 +24,7 @@ #include "OFile.h" -namespace PLMD{ +namespace PLMD { /// Class containing the log stream. /// diff --git a/src/tools/LoopUnroller.h b/src/tools/LoopUnroller.h index 87e8f5298c..83f33ed700 100644 --- a/src/tools/LoopUnroller.h +++ b/src/tools/LoopUnroller.h @@ -22,7 +22,7 @@ #ifndef __PLUMED_tools_LoopUnroller_h #define __PLUMED_tools_LoopUnroller_h -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -48,7 +48,7 @@ Here xxx is any of the methods of the class. */ template -class LoopUnroller{ +class LoopUnroller { public: /// Set to zero. /// Same as `for(unsigned i=0;i -void LoopUnroller::_zero(double*d){ +void LoopUnroller::_zero(double*d) { LoopUnroller::_zero(d); d[n-1]=0.0; } template<> inline -void LoopUnroller<1>::_zero(double*d){ +void LoopUnroller<1>::_zero(double*d) { d[0]=0.0; } template -void LoopUnroller::_add(double*d,const double*a){ +void LoopUnroller::_add(double*d,const double*a) { LoopUnroller::_add(d,a); d[n-1]+=a[n-1]; } template<> inline -void LoopUnroller<1>::_add(double*d,const double*a){ +void LoopUnroller<1>::_add(double*d,const double*a) { d[0]+=a[0]; } template -void LoopUnroller::_sub(double*d,const double*a){ +void LoopUnroller::_sub(double*d,const double*a) { LoopUnroller::_sub(d,a); d[n-1]-=a[n-1]; } template<> inline -void LoopUnroller<1>::_sub(double*d,const double*a){ +void LoopUnroller<1>::_sub(double*d,const double*a) { d[0]-=a[0]; } template -void LoopUnroller::_mul(double*d,const double s){ +void LoopUnroller::_mul(double*d,const double s) { LoopUnroller::_mul(d,s); d[n-1]*=s; } template<> inline -void LoopUnroller<1>::_mul(double*d,const double s){ +void LoopUnroller<1>::_mul(double*d,const double s) { d[0]*=s; } template -void LoopUnroller::_neg(double*d,const double*a ){ +void LoopUnroller::_neg(double*d,const double*a ) { LoopUnroller::_neg(d,a); d[n-1]=-a[n-1]; } template<> inline -void LoopUnroller<1>::_neg(double*d,const double*a){ +void LoopUnroller<1>::_neg(double*d,const double*a) { d[0]=-a[0]; } template -double LoopUnroller::_sum2(const double*d){ +double LoopUnroller::_sum2(const double*d) { return LoopUnroller::_sum2(d)+d[n-1]*d[n-1]; } template<> inline -double LoopUnroller<1>::_sum2(const double*d){ +double LoopUnroller<1>::_sum2(const double*d) { return d[0]*d[0]; } template -double LoopUnroller::_dot(const double*d,const double*v){ +double LoopUnroller::_dot(const double*d,const double*v) { return LoopUnroller::_dot(d,v)+d[n-1]*v[n-1]; } template<> inline -double LoopUnroller<1>::_dot(const double*d,const double*v){ +double LoopUnroller<1>::_dot(const double*d,const double*v) { return d[0]*v[0]; } diff --git a/src/tools/Matrix.h b/src/tools/Matrix.h index 1bfc5ee1b5..fd1e35d6d9 100644 --- a/src/tools/Matrix.h +++ b/src/tools/Matrix.h @@ -31,234 +31,234 @@ #include "Log.h" #include "lapack/lapack.h" -namespace PLMD{ +namespace PLMD { -/// Calculate the dot product between two vectors -template T dotProduct( const std::vector& A, const std::vector& B ){ - plumed_assert( A.size()==B.size() ); - T val; for(unsigned i=0;i T dotProduct( const std::vector& A, const std::vector& B ) { + plumed_assert( A.size()==B.size() ); + T val; for(unsigned i=0; i T norm( const std::vector& A ){ - T val; for(unsigned i=0;i T norm( const std::vector& A ) { + T val; for(unsigned i=0; i class Matrix: public MatrixSquareBracketsAccess,T> - { - /// Multiply matrix by scalar - template friend Matrix operator*(U&, const Matrix& ); - /// Matrix matrix multiply - template friend void mult( const Matrix& , const Matrix& , Matrix& ); - /// Matrix times a std::vector - template friend void mult( const Matrix&, const std::vector& , std::vector& ); - /// std::vector times a Matrix - template friend void mult( const std::vector&, const Matrix&, std::vector& ); - /// Matrix transpose - template friend void transpose( const Matrix&, Matrix& ); - /// Output the entire matrix on a single line - template friend Log& operator<<(Log&, const Matrix& ); - /// Output the Matrix in matrix form - template friend void matrixOut( Log&, const Matrix& ); - /// Diagonalize a symmetric matrix - returns zero if diagonalization worked - template friend int diagMat( const Matrix& , std::vector& , Matrix& ); - /// Calculate the Moore-Penrose Pseudoinverse of a matrix - template friend int pseudoInvert( const Matrix& , Matrix& ); - /// Calculate the logarithm of the determinant of a symmetric matrix - returns zero if succesfull - template friend int logdet( const Matrix& , double& ); - /// Invert a matrix (works for both symmetric and assymetric matrices) - returns zero if sucesfull - template friend int Invert( const Matrix& , Matrix& ); - /// Do a cholesky decomposition of a matrix - template friend void cholesky( const Matrix& , Matrix& ); - /// Solve a system of equations using the cholesky decomposition - template friend void chol_elsolve( const Matrix& , const std::vector& , std::vector& ); +{ + /// Multiply matrix by scalar + template friend Matrix operator*(U&, const Matrix& ); + /// Matrix matrix multiply + template friend void mult( const Matrix&, const Matrix&, Matrix& ); + /// Matrix times a std::vector + template friend void mult( const Matrix&, const std::vector&, std::vector& ); + /// std::vector times a Matrix + template friend void mult( const std::vector&, const Matrix&, std::vector& ); + /// Matrix transpose + template friend void transpose( const Matrix&, Matrix& ); + /// Output the entire matrix on a single line + template friend Log& operator<<(Log&, const Matrix& ); + /// Output the Matrix in matrix form + template friend void matrixOut( Log&, const Matrix& ); + /// Diagonalize a symmetric matrix - returns zero if diagonalization worked + template friend int diagMat( const Matrix&, std::vector&, Matrix& ); + /// Calculate the Moore-Penrose Pseudoinverse of a matrix + template friend int pseudoInvert( const Matrix&, Matrix& ); + /// Calculate the logarithm of the determinant of a symmetric matrix - returns zero if succesfull + template friend int logdet( const Matrix&, double& ); + /// Invert a matrix (works for both symmetric and assymetric matrices) - returns zero if sucesfull + template friend int Invert( const Matrix&, Matrix& ); + /// Do a cholesky decomposition of a matrix + template friend void cholesky( const Matrix&, Matrix& ); + /// Solve a system of equations using the cholesky decomposition + template friend void chol_elsolve( const Matrix&, const std::vector&, std::vector& ); private: - /// Number of elements in matrix (nrows*ncols) - unsigned sz; - /// Number of rows in matrix - unsigned rw; - /// Number of columns in matrix - unsigned cl; - /// The data in the matrix - std::vector data; + /// Number of elements in matrix (nrows*ncols) + unsigned sz; + /// Number of rows in matrix + unsigned rw; + /// Number of columns in matrix + unsigned cl; + /// The data in the matrix + std::vector data; public: - Matrix(const unsigned nr=0, const unsigned nc=0 ) : sz(nr*nc), rw(nr), cl(nc), data(nr*nc) {} - Matrix(const Matrix& t) : sz(t.sz), rw(t.rw), cl(t.cl), data(t.data) {} - /// Resize the matrix - void resize( const unsigned nr, const unsigned nc ){ rw=nr; cl=nc; sz=nr*nc; data.resize(sz); } - /// Return the number of rows - inline unsigned nrows() const { return rw; } - /// Return the number of columns - inline unsigned ncols() const { return cl; } - /// Return element i,j of the matrix - inline T operator () (const unsigned& i, const unsigned& j) const { return data[j+i*cl]; } - /// Return a referenre to element i,j of the matrix - inline T& operator () (const unsigned& i, const unsigned& j) { return data[j+i*cl]; } - /// Set all elements of the matrix equal to the value of v - Matrix& operator=(const T& v){ - for(unsigned i=0;i& operator=(const Matrix& m){ - sz=m.sz; - rw=m.rw; - cl=m.cl; - data=m.data; - return *this; - } - /// Set the Matrix equal to the value of a standard vector - used for readin - Matrix& operator=(const std::vector& v){ - plumed_dbg_assert( v.size()==sz ); - for(unsigned i=0;i operator+=(const T& v){ - for(unsigned i=0;i operator*=(const T& v){ - for(unsigned i=0;i& operator+=(const Matrix& m){ + Matrix(const unsigned nr=0, const unsigned nc=0 ) : sz(nr*nc), rw(nr), cl(nc), data(nr*nc) {} + Matrix(const Matrix& t) : sz(t.sz), rw(t.rw), cl(t.cl), data(t.data) {} + /// Resize the matrix + void resize( const unsigned nr, const unsigned nc ) { rw=nr; cl=nc; sz=nr*nc; data.resize(sz); } + /// Return the number of rows + inline unsigned nrows() const { return rw; } + /// Return the number of columns + inline unsigned ncols() const { return cl; } + /// Return element i,j of the matrix + inline T operator () (const unsigned& i, const unsigned& j) const { return data[j+i*cl]; } + /// Return a referenre to element i,j of the matrix + inline T& operator () (const unsigned& i, const unsigned& j) { return data[j+i*cl]; } + /// Set all elements of the matrix equal to the value of v + Matrix& operator=(const T& v) { + for(unsigned i=0; i& operator=(const Matrix& m) { + sz=m.sz; + rw=m.rw; + cl=m.cl; + data=m.data; + return *this; + } + /// Set the Matrix equal to the value of a standard vector - used for readin + Matrix& operator=(const std::vector& v) { + plumed_dbg_assert( v.size()==sz ); + for(unsigned i=0; i operator+=(const T& v) { + for(unsigned i=0; i operator*=(const T& v) { + for(unsigned i=0; i& operator+=(const Matrix& m) { plumed_dbg_assert( m.rw==rw && m.cl==cl ); data+=m.data; return *this; } /// Subtract v from all elements of the Matrix - Matrix operator-=(const T& v){ - for(unsigned i=0;i operator-=(const T& v) { + for(unsigned i=0; i& operator-=(const Matrix& m){ + Matrix& operator-=(const Matrix& m) { plumed_dbg_assert( m.rw==rw && m.cl==cl ); - data-=m.data; + data-=m.data; return *this; } /// Test if the matrix is symmetric or not - unsigned isSymmetric() const { - if (rw!=cl){ return 0; } - unsigned sym=1; - for(unsigned i=1;i1.e-10 ){ sym=0; break; } - return sym; + unsigned isSymmetric() const { + if (rw!=cl) { return 0; } + unsigned sym=1; + for(unsigned i=1; i1.e-10 ) { sym=0; break; } + return sym; } }; /// Multiply matrix by scalar -template Matrix operator*(T& v, const Matrix& m ){ +template Matrix operator*(T& v, const Matrix& m ) { Matrix new_m(m); new_m*=v; - return new_m; + return new_m; } -template void mult( const Matrix& A , const Matrix& B , Matrix& C ){ +template void mult( const Matrix& A, const Matrix& B, Matrix& C ) { plumed_assert(A.cl==B.rw); - if( A.rw !=C.rw || B.cl !=C.cl ){ C.resize( A.rw , B.cl ); } C=static_cast( 0 ); - for(unsigned i=0;i( 0 ); + for(unsigned i=0; i void mult( const Matrix& A, const std::vector& B, std::vector& C){ +template void mult( const Matrix& A, const std::vector& B, std::vector& C) { plumed_assert( A.cl==B.size() ); - if( C.size()!=A.rw ){ C.resize(A.rw); } - for(unsigned i=0;i( 0 ); } - for(unsigned i=0;i( 0 ); } + for(unsigned i=0; i void mult( const std::vector& A, const Matrix& B, std::vector& C){ +template void mult( const std::vector& A, const Matrix& B, std::vector& C) { plumed_assert( B.rw==A.size() ); - if( C.size()!=B.cl ){C.resize( B.cl );} - for(unsigned i=0;i( 0 ); } - for(unsigned i=0;i( 0 ); } + for(unsigned i=0; i void transpose( const Matrix& A, Matrix& AT ){ - if( A.rw!=AT.cl || A.cl!=AT.rw ) AT.resize( A.cl , A.rw ); - for(unsigned i=0;i void transpose( const Matrix& A, Matrix& AT ) { + if( A.rw!=AT.cl || A.cl!=AT.rw ) AT.resize( A.cl, A.rw ); + for(unsigned i=0; i Log& operator<<(Log& ostr, const Matrix& mat){ - for(unsigned i=0;i Log& operator<<(Log& ostr, const Matrix& mat) { + for(unsigned i=0; i void matrixOut( Log& ostr, const Matrix& mat){ - for(unsigned i=0;i void matrixOut( Log& ostr, const Matrix& mat) { + for(unsigned i=0; i int diagMat( const Matrix& A, std::vector& eigenvals, Matrix& eigenvecs ){ - - // Check matrix is square and symmetric - plumed_assert( A.rw==A.cl ); plumed_assert( A.isSymmetric()==1 ); - double *da=new double[A.sz]; unsigned k=0; double *evals=new double[ A.cl ]; - // Transfer the matrix to the local array - for (unsigned i=0; i( A(j,i) ); - - int n=A.cl; int lwork=-1, liwork=-1, m, info, one=1; - double *work=new double[A.cl]; int *iwork=new int[A.cl]; - double vl, vu, abstol=0.0; - int* isup=new int[2*A.cl]; double *evecs=new double[A.sz]; - - plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; - - // Retrieve correct sizes for work and iwork then reallocate - liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; - lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; - - plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; - - if( eigenvals.size()!=A.cl ){ eigenvals.resize( A.cl ); } - if( eigenvecs.rw!=A.rw || eigenvecs.cl!=A.cl ){ eigenvecs.resize( A.rw, A.cl ); } - k=0; - for(unsigned i=0;i1e-14) break; - if(j int diagMat( const Matrix& A, std::vector& eigenvals, Matrix& eigenvecs ) { + + // Check matrix is square and symmetric + plumed_assert( A.rw==A.cl ); plumed_assert( A.isSymmetric()==1 ); + double *da=new double[A.sz]; unsigned k=0; double *evals=new double[ A.cl ]; + // Transfer the matrix to the local array + for (unsigned i=0; i( A(j,i) ); + + int n=A.cl; int lwork=-1, liwork=-1, m, info, one=1; + double *work=new double[A.cl]; int *iwork=new int[A.cl]; + double vl, vu, abstol=0.0; + int* isup=new int[2*A.cl]; double *evecs=new double[A.sz]; + + plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; + + // Retrieve correct sizes for work and iwork then reallocate + liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; + lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; + + plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; + + if( eigenvals.size()!=A.cl ) { eigenvals.resize( A.cl ); } + if( eigenvecs.rw!=A.rw || eigenvecs.cl!=A.cl ) { eigenvecs.resize( A.rw, A.cl ); } + k=0; + for(unsigned i=0; i1e-14) break; + if(j int pseudoInvert( const Matrix& A, Matrix& pseudoinverse ){ - double *da=new double[A.sz]; unsigned k=0; +template int pseudoInvert( const Matrix& A, Matrix& pseudoinverse ) { + double *da=new double[A.sz]; unsigned k=0; // Transfer the matrix to the local array for (unsigned i=0; i( A(j,i) ); - int nsv, info, nrows=A.rw, ncols=A.cl; - if(A.rw>A.cl){nsv=A.cl;}else{nsv=A.rw;} + int nsv, info, nrows=A.rw, ncols=A.cl; + if(A.rw>A.cl) {nsv=A.cl;} else {nsv=A.rw;} // Create some containers for stuff from single value decomposition double *S=new double[nsv]; double *U=new double[nrows*nrows]; @@ -274,19 +274,19 @@ template int pseudoInvert( const Matrix& A, Matrix& pseu // This does the singular value decomposition plumed_lapack_dgesdd( "A", &nrows, &ncols, da, &nrows, S, U, &nrows, VT, &ncols, work, &lwork, iwork, &info ); - if(info!=0) return info; + if(info!=0) return info; // Compute the tolerance on the singular values ( machine epsilon * number of singular values * maximum singular value ) - double tol; tol=S[0]; for(int i=1;itol ){ tol=S[i]; } } tol*=nsv*epsilon; + double tol; tol=S[0]; for(int i=1; itol ) { tol=S[i]; } } tol*=nsv*epsilon; // Get the inverses of the singlular values Matrix Si( ncols, nrows ); Si=0.0; - for(int i=0;itol ){ Si(i,i)=1./S[i]; }else{ Si(i,i)=0.0; } } + for(int i=0; itol ) { Si(i,i)=1./S[i]; } else { Si(i,i)=0.0; } } // Now extract matrices for pseudoinverse - Matrix V( ncols, ncols ), UT( nrows, nrows ), tmp( ncols, nrows ); - k=0; for(int i=0;i V( ncols, ncols ), UT( nrows, nrows ), tmp( ncols, nrows ); + k=0; for(int i=0; i int pseudoInvert( const Matrix& A, Matrix& pseu return 0; } -template int Invert( const Matrix& A, Matrix& inverse ){ - - if( A.isSymmetric()==1 ){ - // GAT -- I only ever use symmetric matrices so I can invert them like this. - // I choose to do this as I have had problems with the more general way of doing this that - // is implemented below. - std::vector eval(A.rw); Matrix evec(A.rw,A.cl), tevec(A.rw,A.cl); - int err; err=diagMat( A, eval, evec ); - if(err!=0) return err; - for (unsigned i=0; i int Invert( const Matrix& A, Matrix& inverse ) { + + if( A.isSymmetric()==1 ) { + // GAT -- I only ever use symmetric matrices so I can invert them like this. + // I choose to do this as I have had problems with the more general way of doing this that + // is implemented below. + std::vector eval(A.rw); Matrix evec(A.rw,A.cl), tevec(A.rw,A.cl); + int err; err=diagMat( A, eval, evec ); + if(err!=0) return err; + for (unsigned i=0; i( A(j,i) ); + double *da=new double[A.sz]; int *ipiv=new int[A.cl]; + unsigned k=0; int n=A.rw, info; + for(unsigned i=0; i( A(j,i) ); - plumed_lapack_dgetrf(&n,&n,da,&n,ipiv,&info); - if(info!=0) return info; + plumed_lapack_dgetrf(&n,&n,da,&n,ipiv,&info); + if(info!=0) return info; - int lwork=-1; double* work=new double[A.cl]; - plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); - if(info!=0) return info; + int lwork=-1; double* work=new double[A.cl]; + plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); + if(info!=0) return info; - lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; - plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); - if(info!=0) return info; + lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; + plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); + if(info!=0) return info; - if( inverse.cl!=A.cl || inverse.rw!=A.rw ){ inverse.resize(A.rw,A.cl); } - k=0; for(unsigned i=0;i void cholesky( const Matrix& A, Matrix& B ){ +template void cholesky( const Matrix& A, Matrix& B ) { - plumed_assert( A.rw==A.cl && A.isSymmetric() ); - Matrix L(A.rw ,A.cl); L=0.; - std::vector D(A.rw,0.); - for(unsigned i=0; i L(A.rw,A.cl); L=0.; + std::vector D(A.rw,0.); + for(unsigned i=0; i( 1 ); - for (unsigned j=0; j( 0 ); - } - D[i]=A(i,i); - for (unsigned k=0; k0.?sqrt(D[i]):0.); - if( B.rw!=A.rw || B.cl!=A.cl ){ B.resize( A.rw, A.cl); } - B=0.; for(unsigned i=0; i( 1 ); + for (unsigned j=0; j( 0 ); + } + D[i]=A(i,i); + for (unsigned k=0; k0.?sqrt(D[i]):0.); + if( B.rw!=A.rw || B.cl!=A.cl ) { B.resize( A.rw, A.cl); } + B=0.; for(unsigned i=0; i void chol_elsolve( const Matrix& M, const std::vector& b, std::vector& y ){ +template void chol_elsolve( const Matrix& M, const std::vector& b, std::vector& y ) { - plumed_assert( M.rw==M.cl && M(0,1)==0.0 && b.size()==M.rw ); - if( y.size()!=M.rw ){ y.resize( M.rw ); } - for(unsigned i=0;i int logdet( const Matrix& M, double& ldet ){ - // Check matrix is square and symmetric - plumed_assert( M.rw==M.cl || M.isSymmetric() ); +template int logdet( const Matrix& M, double& ldet ) { + // Check matrix is square and symmetric + plumed_assert( M.rw==M.cl || M.isSymmetric() ); - double *da=new double[M.sz]; unsigned k=0; double *evals=new double[M.cl]; - // Transfer the matrix to the local array - for (unsigned i=0; i( M(j,i) ); + double *da=new double[M.sz]; unsigned k=0; double *evals=new double[M.cl]; + // Transfer the matrix to the local array + for (unsigned i=0; i( M(j,i) ); - int n=M.cl; int lwork=-1, liwork=-1, info, m, one=1; - double *work=new double[M.rw]; int *iwork=new int[M.rw]; - double vl, vu, abstol=0.0; - int* isup=new int[2*M.rw]; double *evecs=new double[M.sz]; - plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; + int n=M.cl; int lwork=-1, liwork=-1, info, m, one=1; + double *work=new double[M.rw]; int *iwork=new int[M.rw]; + double vl, vu, abstol=0.0; + int* isup=new int[2*M.rw]; double *evecs=new double[M.sz]; + plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; - // Retrieve correct sizes for work and iwork then reallocate - lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; - liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; + // Retrieve correct sizes for work and iwork then reallocate + lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; + liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; - plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; + plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; - // Transfer the eigenvalues and eigenvectors to the output - ldet=0; for(unsigned i=0;i -class MatrixSquareBracketsAccess{ +class MatrixSquareBracketsAccess { /// Small utility class which just contains a pointer to the T and the row number - class Const_row{ + class Const_row { friend class MatrixSquareBracketsAccess; // this so as to allow only T to instantiate Const_row - // the user should not manipulate it directly + // the user should not manipulate it directly const MatrixSquareBracketsAccess& t; const I i; Const_row(const MatrixSquareBracketsAccess&t,I i); // constructor is private and cannot be manipulated by the user public: - /// access element + /// access element const C & operator[] (J j)const; }; /// Small utility class which just contains a pointer to the T and the row number - class Row{ + class Row { friend class MatrixSquareBracketsAccess; // this so as to allow only T to instantiate Const_row - // the user should not manipulate it directly + // the user should not manipulate it directly MatrixSquareBracketsAccess& t; const I i; Row(MatrixSquareBracketsAccess&t,I i); // constructor is private and cannot be manipulated by the user public: - /// access element + /// access element C & operator[] (J j); }; public: @@ -98,29 +98,29 @@ class MatrixSquareBracketsAccess{ template MatrixSquareBracketsAccess::Const_row::Const_row(const MatrixSquareBracketsAccess&t,I i): - t(t),i(i){} + t(t),i(i) {} template MatrixSquareBracketsAccess::Row::Row(MatrixSquareBracketsAccess&t,I i): - t(t),i(i){} + t(t),i(i) {} template -const C & MatrixSquareBracketsAccess::Const_row::operator[] (J j)const{ +const C & MatrixSquareBracketsAccess::Const_row::operator[] (J j)const { return (*static_cast(&t))(i,j); } template -C & MatrixSquareBracketsAccess::Row::operator[] (J j){ +C & MatrixSquareBracketsAccess::Row::operator[] (J j) { return (*static_cast(&t))(i,j); } template -typename MatrixSquareBracketsAccess::Row MatrixSquareBracketsAccess::operator[] (I i){ +typename MatrixSquareBracketsAccess::Row MatrixSquareBracketsAccess::operator[] (I i) { return Row(*this,i); } template -typename MatrixSquareBracketsAccess::Const_row MatrixSquareBracketsAccess::operator[] (I i)const{ +typename MatrixSquareBracketsAccess::Const_row MatrixSquareBracketsAccess::operator[] (I i)const { return Const_row(*this,i); } diff --git a/src/tools/Minimise1DBrent.h b/src/tools/Minimise1DBrent.h index dca7800e91..097a05b444 100644 --- a/src/tools/Minimise1DBrent.h +++ b/src/tools/Minimise1DBrent.h @@ -27,7 +27,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /// A class for doing parabolic interpolation and minimisation of /// 1D functions using Brent's method. @@ -50,7 +50,7 @@ class Minimise1DBrent { const unsigned ITMAX; /// The value of the golden ratio const double CGOLD; -/// A small number that protects against trying to achieve fractional +/// A small number that protects against trying to achieve fractional /// accuracy for a minimum that happens to be exactly zero const double ZEPS; /// This is the type specifier for the function to minimise @@ -61,128 +61,128 @@ class Minimise1DBrent { FCLASS myclass_func; public: explicit Minimise1DBrent( const FCLASS& pf, const double& t=3.0E-8 ); -/// Bracket the minium +/// Bracket the minium void bracket( const double& ax, const double& xx, eng_pointer eng ); /// Find the minimum between two brackets - double minimise( eng_pointer eng ); + double minimise( eng_pointer eng ); /// Return the value of the function at the minimum double getMinimumValue() const ; }; template Minimise1DBrent::Minimise1DBrent( const FCLASS& pf, const double& t ): -bracketed(false), -minimised(false), -tol(t), -GOLD(1.618034), -GLIMIT(100.0), -TINY(1.0E-20), -ITMAX(100), -CGOLD(0.3819660), -ZEPS(epsilon*1.0E-3), -ax(0),bx(0),cx(0), -fa(0),fb(0),fc(0), -fmin(0), -myclass_func(pf) + bracketed(false), + minimised(false), + tol(t), + GOLD(1.618034), + GLIMIT(100.0), + TINY(1.0E-20), + ITMAX(100), + CGOLD(0.3819660), + ZEPS(epsilon*1.0E-3), + ax(0),bx(0),cx(0), + fa(0),fb(0),fc(0), + fmin(0), + myclass_func(pf) { } template -void Minimise1DBrent::bracket( const double& a, const double& b, eng_pointer eng ){ - ax=a; bx=b; double fu; - fa=(myclass_func.*eng)(ax); fb=(myclass_func.*eng)(bx); - if( fb>fa ){ - double tmp; - tmp=ax; ax=bx; bx=tmp; - tmp=fa; fa=fb; fb=tmp; - } - cx=bx+GOLD*(bx-ax); - fc=(myclass_func.*eng)(cx); - while ( fb > fc ){ - double r=(bx-ax)*(fb-fc); - double q=(bx-cx)*(fb-fa); - double u=bx-((bx-cx)*q-(bx-ax)*r)/(2.0*(fabs(q-r)>TINY?fabs(q-r):TINY)*(q-r>=0?1:-1)); - double ulim=bx+GLIMIT*(cx-bx); - if((bx-u)*(u-cx) > 0.0 ){ - fu=(myclass_func.*eng)(u); - if( fu < fc ){ - ax=bx; bx=u; fa=fb; fb=fu; bracketed=true; return; - } else if( fu > fb ){ - cx=u; fc=fu; bracketed=true; return; - } - u=cx+GOLD*(cx-bx); fu=(myclass_func.*eng)(u); - } else if((cx-u)*(u-ulim) > 0.0 ){ - fu=(myclass_func.*eng)(u); - if( fu= 0.0 ){ - u=ulim; - fu=(myclass_func.*eng)(u); - } else { - u=cx+GOLD*(cx-bx); - fu=(myclass_func.*eng)(u); - } - ax=bx; bx=cx; cx=u; - fa=fb; fb=fc; fc=fu; - } - bracketed=true; +void Minimise1DBrent::bracket( const double& a, const double& b, eng_pointer eng ) { + ax=a; bx=b; double fu; + fa=(myclass_func.*eng)(ax); fb=(myclass_func.*eng)(bx); + if( fb>fa ) { + double tmp; + tmp=ax; ax=bx; bx=tmp; + tmp=fa; fa=fb; fb=tmp; + } + cx=bx+GOLD*(bx-ax); + fc=(myclass_func.*eng)(cx); + while ( fb > fc ) { + double r=(bx-ax)*(fb-fc); + double q=(bx-cx)*(fb-fa); + double u=bx-((bx-cx)*q-(bx-ax)*r)/(2.0*(fabs(q-r)>TINY?fabs(q-r):TINY)*(q-r>=0?1:-1)); + double ulim=bx+GLIMIT*(cx-bx); + if((bx-u)*(u-cx) > 0.0 ) { + fu=(myclass_func.*eng)(u); + if( fu < fc ) { + ax=bx; bx=u; fa=fb; fb=fu; bracketed=true; return; + } else if( fu > fb ) { + cx=u; fc=fu; bracketed=true; return; + } + u=cx+GOLD*(cx-bx); fu=(myclass_func.*eng)(u); + } else if((cx-u)*(u-ulim) > 0.0 ) { + fu=(myclass_func.*eng)(u); + if( fu= 0.0 ) { + u=ulim; + fu=(myclass_func.*eng)(u); + } else { + u=cx+GOLD*(cx-bx); + fu=(myclass_func.*eng)(u); + } + ax=bx; bx=cx; cx=u; + fa=fb; fb=fc; fc=fu; + } + bracketed=true; } template -double Minimise1DBrent::minimise( eng_pointer eng ){ - plumed_dbg_assert( bracketed ); - - double a,b,d=0.0,etemp,fu,fv,fw,fx; - double p,q,r,tol1,tol2,u,v,w,x,xm; - double e=0.0; - - a=(ax < cx ? ax : cx ); - b=(ax >= cx ? ax : cx ); - x=w=v=bx; - fw=fv=fx=(myclass_func.*eng)(x); - for(unsigned iter=0;iter tol1 ){ - r=(x-w)*(fx-fv); - q=(x-v)*(fx-fw); - p=(x-v)*q-(x-w)*r; - q=2.0*(q-r); - if( q > 0.0 ) p = -p; - q=fabs(q); - etemp=e; - e=d; - if( fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x) ){ - d = CGOLD*(e=(x >= xm ? a-x : b-x )); - } else { - d=p/q; u=x+d; - if(u-a < tol2 || b-u < tol2 ) d=(xm-x>=0?fabs(tol1):-fabs(tol1)); - } +double Minimise1DBrent::minimise( eng_pointer eng ) { + plumed_dbg_assert( bracketed ); + + double a,b,d=0.0,etemp,fu,fv,fw,fx; + double p,q,r,tol1,tol2,u,v,w,x,xm; + double e=0.0; + + a=(ax < cx ? ax : cx ); + b=(ax >= cx ? ax : cx ); + x=w=v=bx; + fw=fv=fx=(myclass_func.*eng)(x); + for(unsigned iter=0; iter tol1 ) { + r=(x-w)*(fx-fv); + q=(x-v)*(fx-fw); + p=(x-v)*q-(x-w)*r; + q=2.0*(q-r); + if( q > 0.0 ) p = -p; + q=fabs(q); + etemp=e; + e=d; + if( fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x) ) { + d = CGOLD*(e=(x >= xm ? a-x : b-x )); } else { - d=CGOLD*(e=( x >= xm ? a-x : b-x )); + d=p/q; u=x+d; + if(u-a < tol2 || b-u < tol2 ) d=(xm-x>=0?fabs(tol1):-fabs(tol1)); } - if( fabs(d)>=tol1) u=x+d; else u=x+(d>=0?fabs(tol1):-fabs(tol1)); - fu=(myclass_func.*eng)(u); - if( fu <= fx ){ - if( u >= x ) a=x; else b=x; - v=w; fv=fw; - w=x; fw=fx; - x=u; fx=fu; - } else { - if( u < x ) a=u; else b=u; - if( fu <=fw || w==x ){ - v=w; w=u; fv=fw; fw=fu; - } else if( fu <= fv || v==x || v==w ){ - v=u; fv=fu; - } + } else { + d=CGOLD*(e=( x >= xm ? a-x : b-x )); + } + if( fabs(d)>=tol1) u=x+d; else u=x+(d>=0?fabs(tol1):-fabs(tol1)); + fu=(myclass_func.*eng)(u); + if( fu <= fx ) { + if( u >= x ) a=x; else b=x; + v=w; fv=fw; + w=x; fw=fx; + x=u; fx=fu; + } else { + if( u < x ) a=u; else b=u; + if( fu <=fw || w==x ) { + v=w; w=u; fv=fw; fw=fu; + } else if( fu <= fv || v==x || v==w ) { + v=u; fv=fu; } - } - plumed_merror("Too many interactions in brent"); + } + } + plumed_merror("Too many interactions in brent"); } template diff --git a/src/tools/MinimiseBase.h b/src/tools/MinimiseBase.h index 80cfcc02e5..27714da7ca 100644 --- a/src/tools/MinimiseBase.h +++ b/src/tools/MinimiseBase.h @@ -47,7 +47,7 @@ class F1dim { engf_pointer calc; /// Member of class that calcualtes the energy we are trying to minimise engfnc_pointer calc2; -public: +public: explicit F1dim( const std::vector& pp, const std::vector& dd, FCLASS* ff, engf_pointer cc, engfnc_pointer cc2 ); /// Calculate the energy at \f$\mathbf{p} + xt*\mathbf{dir}\f$ double getEng( const double& xt ); @@ -55,21 +55,21 @@ class F1dim { template F1dim::F1dim( const std::vector& pp, const std::vector& dd, FCLASS* ff, engf_pointer cc, engfnc_pointer cc2 ): -p(pp), -dir(dd), -pt(pp.size()), -fake_der(pp.size()), -func(ff), -calc(cc), -calc2(cc2) + p(pp), + dir(dd), + pt(pp.size()), + fake_der(pp.size()), + func(ff), + calc(cc), + calc2(cc2) { plumed_assert( calc || calc2 ); } template -double F1dim::getEng( const double& xt ){ - for(unsigned j=0;j*calc)(pt,fake_der); +double F1dim::getEng( const double& xt ) { + for(unsigned j=0; j*calc)(pt,fake_der); return (func->*calc2)(pt,fake_der); } @@ -82,7 +82,7 @@ class MinimiseBase { /// The class that calculates the energy given a position FCLASS* myclass_func; protected: -/// This calculates the derivatives at a point +/// This calculates the derivatives at a point double calcDerivatives( const std::vector& p, std::vector& der, engf_pointer myfunc ); public: explicit MinimiseBase( FCLASS* funcc ) : myclass_func(funcc) {} @@ -91,8 +91,8 @@ class MinimiseBase { }; template -double MinimiseBase::linemin( const std::vector& dir, std::vector& p, engf_pointer myfunc ){ - // Construct the object that turns points on a line into vectors +double MinimiseBase::linemin( const std::vector& dir, std::vector& p, engf_pointer myfunc ) { + // Construct the object that turns points on a line into vectors F1dim f1dim( p, dir, myclass_func, NULL, myfunc ); // Construct an object that will do the line search for the minimum @@ -100,14 +100,14 @@ double MinimiseBase::linemin( const std::vector& dir, std::vecto // This does the actual line minimisation double ax=0.0, xx=1.0; - bb.bracket( ax, xx, &F1dim::getEng ); + bb.bracket( ax, xx, &F1dim::getEng ); double xmin=bb.minimise( &F1dim::getEng ); - for(unsigned i=0;i -double MinimiseBase::calcDerivatives( const std::vector& p, std::vector& der, engf_pointer myfunc ){ +double MinimiseBase::calcDerivatives( const std::vector& p, std::vector& der, engf_pointer myfunc ) { return (myclass_func->*myfunc)( p, der ); } diff --git a/src/tools/MolDataClass.cpp b/src/tools/MolDataClass.cpp index 49f0e0fac0..310267d5ac 100644 --- a/src/tools/MolDataClass.cpp +++ b/src/tools/MolDataClass.cpp @@ -26,156 +26,156 @@ namespace PLMD { -unsigned MolDataClass::numberOfAtomsPerResidueInBackbone( const std::string& type ){ +unsigned MolDataClass::numberOfAtomsPerResidueInBackbone( const std::string& type ) { if( type=="protein" ) return 5; else if( type=="dna" ) return 6; - else if( type=="rna" ) return 6; + else if( type=="rna" ) return 6; else return 0; } -bool MolDataClass::allowedResidue( const std::string& type, const std::string& residuename ){ - if( type=="protein" ){ - if(residuename=="ALA") return true; - else if(residuename=="ARG") return true; - else if(residuename=="ASN") return true; - else if(residuename=="ASP") return true; - else if(residuename=="CYS") return true; - else if(residuename=="GLN") return true; - else if(residuename=="GLU") return true; - else if(residuename=="GLY") return true; - else if(residuename=="HIS") return true; - else if(residuename=="ILE") return true; - else if(residuename=="LEU") return true; - else if(residuename=="LYS") return true; - else if(residuename=="MET") return true; - else if(residuename=="PHE") return true; - else if(residuename=="PRO") return true; - else if(residuename=="SER") return true; - else if(residuename=="THR") return true; - else if(residuename=="TRP") return true; - else if(residuename=="TYR") return true; - else if(residuename=="VAL") return true; +bool MolDataClass::allowedResidue( const std::string& type, const std::string& residuename ) { + if( type=="protein" ) { + if(residuename=="ALA") return true; + else if(residuename=="ARG") return true; + else if(residuename=="ASN") return true; + else if(residuename=="ASP") return true; + else if(residuename=="CYS") return true; + else if(residuename=="GLN") return true; + else if(residuename=="GLU") return true; + else if(residuename=="GLY") return true; + else if(residuename=="HIS") return true; + else if(residuename=="ILE") return true; + else if(residuename=="LEU") return true; + else if(residuename=="LYS") return true; + else if(residuename=="MET") return true; + else if(residuename=="PHE") return true; + else if(residuename=="PRO") return true; + else if(residuename=="SER") return true; + else if(residuename=="THR") return true; + else if(residuename=="TRP") return true; + else if(residuename=="TYR") return true; + else if(residuename=="VAL") return true; // Terminal groups - else if(residuename=="ACE") return true; - else if(residuename=="NME") return true; -// Alternative residue names in common force fiels - else if(residuename=="GLH") return true; // neutral GLU - else if(residuename=="ASH") return true; // neutral ASP - else if(residuename=="HID") return true; // HIS-D amber - else if(residuename=="HSD") return true; // HIS-D charmm - else if(residuename=="HIE") return true; // HIS-E amber - else if(residuename=="HSE") return true; // HIS-E charmm - else if(residuename=="HIP") return true; // HIS-P amber - else if(residuename=="HSP") return true; // HIS-P charmm - else return false; - } else if( type=="dna" ){ - if(residuename=="DA") return true; - else if(residuename=="DG") return true; - else if(residuename=="DT") return true; - else if(residuename=="DC") return true; - else if(residuename=="DA5") return true; - else if(residuename=="DA3") return true; - else if(residuename=="DAN") return true; - else if(residuename=="DG5") return true; - else if(residuename=="DG3") return true; - else if(residuename=="DGN") return true; - else if(residuename=="DT5") return true; - else if(residuename=="DT3") return true; - else if(residuename=="DTN") return true; - else if(residuename=="DC5") return true; - else if(residuename=="DC3") return true; - else if(residuename=="DCN") return true; - else return false; - } else if( type=="rna" ){ - if(residuename=="A") return true; - else if(residuename=="A5") return true; - else if(residuename=="A3") return true; - else if(residuename=="AN") return true; - else if(residuename=="G") return true; - else if(residuename=="G5") return true; - else if(residuename=="G3") return true; - else if(residuename=="GN") return true; - else if(residuename=="U") return true; - else if(residuename=="U5") return true; - else if(residuename=="U3") return true; - else if(residuename=="UN") return true; - else if(residuename=="C") return true; - else if(residuename=="C5") return true; - else if(residuename=="C3") return true; - else if(residuename=="CN") return true; - else if(residuename=="RA") return true; - else if(residuename=="RA5") return true; - else if(residuename=="RA3") return true; - else if(residuename=="RAN") return true; - else if(residuename=="RG") return true; - else if(residuename=="RG5") return true; - else if(residuename=="RG3") return true; - else if(residuename=="RGN") return true; - else if(residuename=="RU") return true; - else if(residuename=="RU5") return true; - else if(residuename=="RU3") return true; - else if(residuename=="RUN") return true; - else if(residuename=="RC") return true; - else if(residuename=="RC5") return true; - else if(residuename=="RC3") return true; - else if(residuename=="RCN") return true; - else return false; - } + else if(residuename=="ACE") return true; + else if(residuename=="NME") return true; +// Alternative residue names in common force fiels + else if(residuename=="GLH") return true; // neutral GLU + else if(residuename=="ASH") return true; // neutral ASP + else if(residuename=="HID") return true; // HIS-D amber + else if(residuename=="HSD") return true; // HIS-D charmm + else if(residuename=="HIE") return true; // HIS-E amber + else if(residuename=="HSE") return true; // HIS-E charmm + else if(residuename=="HIP") return true; // HIS-P amber + else if(residuename=="HSP") return true; // HIS-P charmm + else return false; + } else if( type=="dna" ) { + if(residuename=="DA") return true; + else if(residuename=="DG") return true; + else if(residuename=="DT") return true; + else if(residuename=="DC") return true; + else if(residuename=="DA5") return true; + else if(residuename=="DA3") return true; + else if(residuename=="DAN") return true; + else if(residuename=="DG5") return true; + else if(residuename=="DG3") return true; + else if(residuename=="DGN") return true; + else if(residuename=="DT5") return true; + else if(residuename=="DT3") return true; + else if(residuename=="DTN") return true; + else if(residuename=="DC5") return true; + else if(residuename=="DC3") return true; + else if(residuename=="DCN") return true; + else return false; + } else if( type=="rna" ) { + if(residuename=="A") return true; + else if(residuename=="A5") return true; + else if(residuename=="A3") return true; + else if(residuename=="AN") return true; + else if(residuename=="G") return true; + else if(residuename=="G5") return true; + else if(residuename=="G3") return true; + else if(residuename=="GN") return true; + else if(residuename=="U") return true; + else if(residuename=="U5") return true; + else if(residuename=="U3") return true; + else if(residuename=="UN") return true; + else if(residuename=="C") return true; + else if(residuename=="C5") return true; + else if(residuename=="C3") return true; + else if(residuename=="CN") return true; + else if(residuename=="RA") return true; + else if(residuename=="RA5") return true; + else if(residuename=="RA3") return true; + else if(residuename=="RAN") return true; + else if(residuename=="RG") return true; + else if(residuename=="RG5") return true; + else if(residuename=="RG3") return true; + else if(residuename=="RGN") return true; + else if(residuename=="RU") return true; + else if(residuename=="RU5") return true; + else if(residuename=="RU3") return true; + else if(residuename=="RUN") return true; + else if(residuename=="RC") return true; + else if(residuename=="RC5") return true; + else if(residuename=="RC3") return true; + else if(residuename=="RCN") return true; + else return false; + } return false; } -void MolDataClass::getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ){ +void MolDataClass::getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ) { std::string residuename=mypdb.getResidueName( residuenum ); plumed_massert( MolDataClass::allowedResidue( type, residuename ), "residue " + residuename + " unrecognized for molecule type " + type ); - if( type=="protein" ){ - if( residuename=="GLY"){ - atoms.resize(5); - atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); - atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); - atoms[2]=mypdb.getNamedAtomFromResidue("HA1",residuenum); - atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); - atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); - } else if( residuename=="ACE"){ - atoms.resize(1); - atoms[0]=mypdb.getNamedAtomFromResidue("C",residuenum); - } else if( residuename=="NME"){ - atoms.resize(1); - atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); - } else { - atoms.resize(5); - atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); - atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); - atoms[2]=mypdb.getNamedAtomFromResidue("CB",residuenum); - atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); - atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); - } - } else if( type=="dna" || type=="rna" ){ - atoms.resize(6); - atoms[0]=mypdb.getNamedAtomFromResidue("P",residuenum); - atoms[1]=mypdb.getNamedAtomFromResidue("O5\'",residuenum); - atoms[2]=mypdb.getNamedAtomFromResidue("C5\'",residuenum); - atoms[3]=mypdb.getNamedAtomFromResidue("C4\'",residuenum); - atoms[4]=mypdb.getNamedAtomFromResidue("C3\'",residuenum); - atoms[5]=mypdb.getNamedAtomFromResidue("O3\'",residuenum); - } + if( type=="protein" ) { + if( residuename=="GLY") { + atoms.resize(5); + atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); + atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); + atoms[2]=mypdb.getNamedAtomFromResidue("HA1",residuenum); + atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); + atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); + } else if( residuename=="ACE") { + atoms.resize(1); + atoms[0]=mypdb.getNamedAtomFromResidue("C",residuenum); + } else if( residuename=="NME") { + atoms.resize(1); + atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); + } else { + atoms.resize(5); + atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); + atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); + atoms[2]=mypdb.getNamedAtomFromResidue("CB",residuenum); + atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); + atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); + } + } else if( type=="dna" || type=="rna" ) { + atoms.resize(6); + atoms[0]=mypdb.getNamedAtomFromResidue("P",residuenum); + atoms[1]=mypdb.getNamedAtomFromResidue("O5\'",residuenum); + atoms[2]=mypdb.getNamedAtomFromResidue("C5\'",residuenum); + atoms[3]=mypdb.getNamedAtomFromResidue("C4\'",residuenum); + atoms[4]=mypdb.getNamedAtomFromResidue("C3\'",residuenum); + atoms[5]=mypdb.getNamedAtomFromResidue("O3\'",residuenum); + } else { - plumed_merror(type + " is not a valid molecule type"); + plumed_merror(type + " is not a valid molecule type"); } } -bool MolDataClass::isTerminalGroup( const std::string& type, const std::string& residuename ){ - if( type=="protein" ){ - if( residuename=="ACE" ) return true; - else if( residuename=="NME" ) return true; - else return false; +bool MolDataClass::isTerminalGroup( const std::string& type, const std::string& residuename ) { + if( type=="protein" ) { + if( residuename=="ACE" ) return true; + else if( residuename=="NME" ) return true; + else return false; } else { - plumed_merror(type + " is not a valid molecule type"); - } + plumed_merror(type + " is not a valid molecule type"); + } return false; } -void MolDataClass::specialSymbol( const std::string& type, const std::string& symbol, const PDB& mypdb, std::vector& numbers ){ - if(type=="protein" || type=="rna" || type=="dna"){ +void MolDataClass::specialSymbol( const std::string& type, const std::string& symbol, const PDB& mypdb, std::vector& numbers ) { + if(type=="protein" || type=="rna" || type=="dna") { // symbol should be something like // phi-123 i.e. phi torsion of residue 123 of first chain // psi-A321 i.e. psi torsion of residue 321 of chain A @@ -186,7 +186,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy unsigned resnum; std::string resname; std::string chainid; - if(firstnum==dash+1){ + if(firstnum==dash+1) { Tools::convert( symbol.substr(dash+1), resnum ); resname= mypdb.getResidueName(resnum); chainid="*"; // this is going to match the first chain @@ -197,23 +197,23 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy } resname= mypdb.getResidueName(resnum,chainid); Tools::stripLeadingAndTrailingBlanks(resname); - if(allowedResidue("protein",resname)){ - if( name=="phi" && !isTerminalGroup("protein",resname) ){ + if(allowedResidue("protein",resname)) { + if( name=="phi" && !isTerminalGroup("protein",resname) ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum-1,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum,chainid)); - } else if( name=="psi" && !isTerminalGroup("protein",resname) ){ + } else if( name=="psi" && !isTerminalGroup("protein",resname) ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum+1,chainid)); - } else if( name=="omega" && !isTerminalGroup("protein",resname) ){ + } else if( name=="omega" && !isTerminalGroup("protein",resname) ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum+1,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum+1,chainid)); - } else if( name=="chi1" && !isTerminalGroup("protein",resname) ){ + } else if( name=="chi1" && !isTerminalGroup("protein",resname) ) { if ( resname=="GLY" || resname=="ALA" ) plumed_merror("chi-1 is not defined for Alanine and Glycine"); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); @@ -229,7 +229,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy else numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CG",resnum,chainid)); } else numbers.push_back(mypdb.getNamedAtomFromResidueAndChain(name,resnum,chainid)); - } else if( allowedResidue("rna",resname) || allowedResidue("dna",resname)){ + } else if( allowedResidue("rna",resname) || allowedResidue("dna",resname)) { std::string basetype; if(resname.find_first_of("A")!=std::string::npos) basetype+="A"; if(resname.find_first_of("U")!=std::string::npos) basetype+="U"; @@ -240,10 +240,10 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy if( name=="chi" ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O4\'",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C1\'",resnum,chainid)); - if(basetype=="T" || basetype=="U" || basetype=="C"){ + if(basetype=="T" || basetype=="U" || basetype=="C") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); - } else if(basetype=="G" || basetype=="A"){ + } else if(basetype=="G" || basetype=="A") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N9",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); } else plumed_error(); @@ -316,7 +316,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2\'",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C3\'",resnum,chainid)); } else if( name=="base" ) { - if(basetype=="C"){ + if(basetype=="C") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O2",resnum,chainid)); @@ -325,7 +325,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="U"){ + } else if(basetype=="U") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O2",resnum,chainid)); @@ -334,7 +334,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="T"){ + } else if(basetype=="T") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O2",resnum,chainid)); @@ -344,7 +344,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C7",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="G"){ + } else if(basetype=="G") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N9",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N3",resnum,chainid)); @@ -356,7 +356,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N7",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C8",resnum,chainid)); - } else if(basetype=="A"){ + } else if(basetype=="A") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N9",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); @@ -370,19 +370,19 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy } else plumed_error(); } else if( name=="lcs" ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); - if(basetype=="T" || basetype=="U" || basetype=="C"){ + if(basetype=="T" || basetype=="U" || basetype=="C") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="G" || basetype=="A"){ + } else if(basetype=="G" || basetype=="A") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); - } else plumed_error(); + } else plumed_error(); } else numbers.push_back(mypdb.getNamedAtomFromResidueAndChain(name,resnum,chainid)); } } else { - plumed_merror(type + " is not a valid molecule type"); + plumed_merror(type + " is not a valid molecule type"); } -} +} } diff --git a/src/tools/MolDataClass.h b/src/tools/MolDataClass.h index 7ffb6c425e..e3ee323356 100644 --- a/src/tools/MolDataClass.h +++ b/src/tools/MolDataClass.h @@ -26,12 +26,12 @@ #include #include "AtomNumber.h" -namespace PLMD{ +namespace PLMD { class PDB; /// This class provides information on various kinds of molecules -/// for instance the kinds of residues that are in a protein +/// for instance the kinds of residues that are in a protein /// the atoms involved in the backbone of a particular residue etc class MolDataClass { public: @@ -40,7 +40,7 @@ class MolDataClass { /// Return the number of atoms in the backbone per residue e.g. 5 for proteins static unsigned numberOfAtomsPerResidueInBackbone( const std::string& type ); /// Return the names of the atoms in the backbone e.g. N, CA, CB, C, O for most protein residues - static void getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ); + static void getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ); /// Return true if the residue is a terminal group e.g. ACE, NME for proteins static bool isTerminalGroup( const std::string& type, const std::string& residuename ); /// Used to interpret special symbols - currently phi and psi and omega diff --git a/src/tools/MultiValue.cpp b/src/tools/MultiValue.cpp index 80a8f6b865..cdf2421659 100644 --- a/src/tools/MultiValue.cpp +++ b/src/tools/MultiValue.cpp @@ -21,98 +21,98 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "MultiValue.h" -namespace PLMD{ +namespace PLMD { MultiValue::MultiValue( const unsigned& nvals, const unsigned& nder ): -values(nvals), -nderivatives(nder), -derivatives(nvals*nder), -tmpval(0), -tmpder(nder), -atLeastOneSet(false) + values(nvals), + nderivatives(nder), + derivatives(nvals*nder), + tmpval(0), + tmpder(nder), + atLeastOneSet(false) { std::vector myind( nder ); - for(unsigned i=0;i myind( nder ); - for(unsigned i=0;i myind( nder ); + for(unsigned i=0; i& buffer ){ +void MultiValue::chainRule( const unsigned& ival, const unsigned& iout, const unsigned& stride, const unsigned& off, + const double& df, const unsigned& bufstart, std::vector& buffer ) { if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); plumed_dbg_assert( offepsilon ){ wpref=1.0/tmpval; } - else{ wpref=1.0; } + if( fabs(tmpval)>epsilon ) { wpref=1.0/tmpval; } + else { wpref=1.0; } double pref = values[nder]*wpref*wpref; - for(unsigned j=0;j indices, sort_indices; std::vector tmp_atoms; public: - MultiValue( const unsigned& , const unsigned& ); - void resize( const unsigned& , const unsigned& ); + MultiValue( const unsigned&, const unsigned& ); + void resize( const unsigned&, const unsigned& ); /// std::vector& getIndices(); std::vector& getSortIndices(); std::vector& getAtomVector(); /// Get the number of values in the stash - unsigned getNumberOfValues() const ; + unsigned getNumberOfValues() const ; /// Get the number of derivatives in the stash unsigned getNumberOfDerivatives() const ; /// Set value numbered @@ -63,7 +63,7 @@ class MultiValue { /// Add value numbered void addValue( const unsigned&, const double& ); /// Add derivative - void addDerivative( const unsigned& , const unsigned& , const double& ); + void addDerivative( const unsigned&, const unsigned&, const double& ); /// Add to the tempory value void addTemporyValue( const double& val ); /// Add tempory derivatives - this is used for calculating quotients @@ -75,7 +75,7 @@ class MultiValue { /// Return a derivative value double getDerivative( const unsigned&, const unsigned& ) const ; /// Get one of the tempory derivatives - double getTemporyDerivative( const unsigned& jder ) const ; + double getTemporyDerivative( const unsigned& jder ) const ; /// Clear all values void clearAll(); /// Clear the tempory derivatives @@ -96,7 +96,7 @@ class MultiValue { /// 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& buffer ); + void chainRule( const unsigned&, const unsigned&, const unsigned&, const unsigned&, const double&, const unsigned&, std::vector& buffer ); /// void copyValues( MultiValue& ) const ; /// @@ -122,37 +122,37 @@ double MultiValue::get( const unsigned& ival ) const { } inline -void MultiValue::setValue( const unsigned& ival, const double& val){ +void MultiValue::setValue( const unsigned& ival, const double& val) { plumed_dbg_assert( ival<=values.size() ); values[ival]=val; } inline -void MultiValue::addValue( const unsigned& ival, const double& val){ +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){ +void MultiValue::addDerivative( const unsigned& ival, const unsigned& jder, const double& der) { plumed_dbg_assert( ival<=values.size() && jder& MultiValue::getIndices(){ +std::vector& MultiValue::getIndices() { return indices; } inline -std::vector& MultiValue::getSortIndices(){ +std::vector& MultiValue::getSortIndices() { return sort_indices; } inline -std::vector& MultiValue::getAtomVector(){ +std::vector& MultiValue::getAtomVector() { return tmp_atoms; } diff --git a/src/tools/NeighborList.cpp b/src/tools/NeighborList.cpp index 038aefd70d..8ce8fafd72 100644 --- a/src/tools/NeighborList.cpp +++ b/src/tools/NeighborList.cpp @@ -27,142 +27,142 @@ #include #include -namespace PLMD{ +namespace PLMD { using namespace std; NeighborList::NeighborList(const vector& list0, const vector& list1, const bool& do_pair, const bool& do_pbc, const Pbc& pbc, const double& distance, const unsigned& stride): reduced(false), - do_pair_(do_pair), do_pbc_(do_pbc), pbc_(&pbc), - distance_(distance), stride_(stride) + do_pair_(do_pair), do_pbc_(do_pbc), pbc_(&pbc), + distance_(distance), stride_(stride) { // store full list of atoms needed - fullatomlist_=list0; - fullatomlist_.insert(fullatomlist_.end(),list1.begin(),list1.end()); - nlist0_=list0.size(); - nlist1_=list1.size(); - twolists_=true; - if(!do_pair){ - nallpairs_=nlist0_*nlist1_; - }else{ - plumed_assert(nlist0_==nlist1_); - nallpairs_=nlist0_; - } - initialize(); - lastupdate_=0; + fullatomlist_=list0; + fullatomlist_.insert(fullatomlist_.end(),list1.begin(),list1.end()); + nlist0_=list0.size(); + nlist1_=list1.size(); + twolists_=true; + if(!do_pair) { + nallpairs_=nlist0_*nlist1_; + } else { + plumed_assert(nlist0_==nlist1_); + nallpairs_=nlist0_; + } + initialize(); + lastupdate_=0; } NeighborList::NeighborList(const vector& list0, const bool& do_pbc, const Pbc& pbc, const double& distance, const unsigned& stride): reduced(false), - do_pbc_(do_pbc), pbc_(&pbc), - distance_(distance), stride_(stride){ - fullatomlist_=list0; - nlist0_=list0.size(); - twolists_=false; - nallpairs_=nlist0_*(nlist0_-1)/2; - initialize(); - lastupdate_=0; + do_pbc_(do_pbc), pbc_(&pbc), + distance_(distance), stride_(stride) { + fullatomlist_=list0; + nlist0_=list0.size(); + twolists_=false; + nallpairs_=nlist0_*(nlist0_-1)/2; + initialize(); + lastupdate_=0; } void NeighborList::initialize() { - neighbors_.clear(); - for(unsigned int i=0;i& NeighborList::getFullAtomList() { - return fullatomlist_; + return fullatomlist_; } pair NeighborList::getIndexPair(unsigned ipair) { - pair index; - if(twolists_ && do_pair_){ - index=pair(ipair,ipair+nlist0_); - }else if (twolists_ && !do_pair_){ - index=pair(ipair/nlist1_,ipair%nlist1_+nlist0_); - }else if (!twolists_){ - unsigned ii = nallpairs_-1-ipair; - unsigned K = unsigned(floor((sqrt(double(8*ii+1))+1)/2)); - unsigned jj = ii-K*(K-1)/2; - index=pair(nlist0_-1-K,nlist0_-1-jj); - } - return index; + pair index; + if(twolists_ && do_pair_) { + index=pair(ipair,ipair+nlist0_); + } else if (twolists_ && !do_pair_) { + index=pair(ipair/nlist1_,ipair%nlist1_+nlist0_); + } else if (!twolists_) { + unsigned ii = nallpairs_-1-ipair; + unsigned K = unsigned(floor((sqrt(double(8*ii+1))+1)/2)); + unsigned jj = ii-K*(K-1)/2; + index=pair(nlist0_-1-K,nlist0_-1-jj); + } + return index; } void NeighborList::update(const vector& positions) { - neighbors_.clear(); - const double d2=distance_*distance_; -// check if positions array has the correct length - plumed_assert(positions.size()==fullatomlist_.size()); - for(unsigned int i=0;i index=getIndexPair(i); - unsigned index0=index.first; - unsigned index1=index.second; - Vector distance; - if(do_pbc_){ - distance=pbc_->distance(positions[index0],positions[index1]); - } else { - distance=delta(positions[index0],positions[index1]); - } - double value=modulo2(distance); - if(value<=d2) {neighbors_.push_back(index);} - } - setRequestList(); + neighbors_.clear(); + const double d2=distance_*distance_; +// check if positions array has the correct length + plumed_assert(positions.size()==fullatomlist_.size()); + for(unsigned int i=0; i index=getIndexPair(i); + unsigned index0=index.first; + unsigned index1=index.second; + Vector distance; + if(do_pbc_) { + distance=pbc_->distance(positions[index0],positions[index1]); + } else { + distance=delta(positions[index0],positions[index1]); + } + double value=modulo2(distance); + if(value<=d2) {neighbors_.push_back(index);} + } + setRequestList(); } void NeighborList::setRequestList() { - requestlist_.clear(); - for(unsigned int i=0;i& NeighborList::getReducedAtomList() { - if(!reduced)for(unsigned int i=0;i(newindex0,newindex1); - } - reduced=true; - return requestlist_; + auto p = std::find(requestlist_.begin(), requestlist_.end(), index0); plumed_assert(p!=requestlist_.end()); newindex0=p-requestlist_.begin(); + p = std::find(requestlist_.begin(), requestlist_.end(), index1); plumed_assert(p!=requestlist_.end()); newindex1=p-requestlist_.begin(); + neighbors_[i]=pair(newindex0,newindex1); + } + reduced=true; + return requestlist_; } unsigned NeighborList::getStride() const { - return stride_; + return stride_; } unsigned NeighborList::getLastUpdate() const { - return lastupdate_; + return lastupdate_; } void NeighborList::setLastUpdate(unsigned step) { - lastupdate_=step; + lastupdate_=step; } unsigned NeighborList::size() const { - return neighbors_.size(); + return neighbors_.size(); } - pair NeighborList::getClosePair(unsigned i) const { - return neighbors_[i]; +pair NeighborList::getClosePair(unsigned i) const { + return neighbors_[i]; } vector NeighborList::getNeighbors(unsigned index) { - vector neighbors; - for(unsigned int i=0;i neighbors; + for(unsigned int i=0; i -namespace PLMD{ +namespace PLMD { class Pbc; /// \ingroup TOOLBOX /// A class that implements neighbor lists from two lists or a single list of atoms -class NeighborList +class NeighborList { bool reduced; bool do_pair_,do_pbc_,twolists_; @@ -45,30 +45,30 @@ class NeighborList /// Initialize the neighbor list with all possible pairs void initialize(); /// Return the pair of indexes in the positions array -/// of the two atoms forming the i-th pair among all possible pairs +/// of the two atoms forming the i-th pair among all possible pairs std::pair getIndexPair(unsigned i); /// Extract the list of atoms from the current list of close pairs void setRequestList(); public: NeighborList(const std::vector& list0, const std::vector& list1, - const bool& do_pair, const bool& do_pbc, const PLMD::Pbc& pbc, + const bool& do_pair, const bool& do_pbc, const PLMD::Pbc& pbc, const double& distance=1.0e+30, const unsigned& stride=0); NeighborList(const std::vector& list0, const bool& do_pbc, const PLMD::Pbc& pbc, const double& distance=1.0e+30, const unsigned& stride=0); -/// Return the list of all atoms. These are needed to rebuild the neighbor list. +/// Return the list of all atoms. These are needed to rebuild the neighbor list. std::vector& getFullAtomList(); /// Update the indexes in the neighbor list to match the /// ordering in the new positions array /// and return the new list of atoms that must be requested to the main code std::vector& getReducedAtomList(); /// Update the neighbor list and prepare the new -/// list of atoms that will be requested to the main code +/// list of atoms that will be requested to the main code void update(const std::vector& positions); /// Get the update stride of the neighbor list unsigned getStride() const; -/// Get the last step in which the neighbor list was updated +/// Get the last step in which the neighbor list was updated unsigned getLastUpdate() const; /// Set the step of the last update void setLastUpdate(unsigned step); @@ -78,7 +78,7 @@ class NeighborList std::pair getClosePair(unsigned i) const; /// Get the list of neighbors of the i-th atom std::vector getNeighbors(unsigned i); - ~NeighborList(){} + ~NeighborList() {} }; } diff --git a/src/tools/OFile.cpp b/src/tools/OFile.cpp index dcadbd6ca4..92108a1321 100644 --- a/src/tools/OFile.cpp +++ b/src/tools/OFile.cpp @@ -38,14 +38,14 @@ #include #endif -namespace PLMD{ +namespace PLMD { -size_t OFile::llwrite(const char*ptr,size_t s){ +size_t OFile::llwrite(const char*ptr,size_t s) { size_t r; if(linked) return linked->llwrite(ptr,s); - if(! (comm && comm->Get_rank()>0)){ + if(! (comm && comm->Get_rank()>0)) { if(!fp) plumed_merror("writing on uninitilized File"); - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB r=gzwrite(gzFile(gzfp),ptr,s); #else @@ -57,7 +57,7 @@ size_t OFile::llwrite(const char*ptr,size_t s){ } // This barrier is apparently useless since it comes // just before a Bcast. -// +// // Anyway, it looks like it is solving an issue that appeared on // TRAVIS (at least on my laptop) so I add it here. // GB @@ -80,40 +80,40 @@ OFile::OFile(): actual_buffer_length=0; buffer=new char[buflen]; // these are set to zero to avoid valgrind errors - for(unsigned i=0;i=buflen-actual_buffer_length){ + if(r>=buflen-actual_buffer_length) { int newlen=buflen; while(newlen<=r+actual_buffer_length) newlen*=2; char* newbuf=new char [newlen]; memmove(newbuf,buffer,buflen); - for(int k=buflen;k0) llwrite(linePrefix.c_str(),linePrefix.length()); llwrite(p1,p2-p1+1); actual_buffer_length-=(p2-p1)+1; @@ -141,7 +141,7 @@ int OFile::printf(const char*fmt,...){ return r; } -OFile& OFile::addConstantField(const std::string&name){ +OFile& OFile::addConstantField(const std::string&name) { Field f; f.name=name; const_fields.push_back(f); @@ -149,39 +149,39 @@ OFile& OFile::addConstantField(const std::string&name){ } -OFile& OFile::clearFields(){ +OFile& OFile::clearFields() { fields.clear(); const_fields.clear(); previous_fields.clear(); return *this; } -OFile& OFile::fmtField(const std::string&fmt){ +OFile& OFile::fmtField(const std::string&fmt) { this->fieldFmt=fmt; return *this; } -OFile& OFile::fmtField(){ +OFile& OFile::fmtField() { this->fieldFmt="%23.16lg"; return *this; } -OFile& OFile::printField(const std::string&name,double v){ +OFile& OFile::printField(const std::string&name,double v) { sprintf(buffer_string,fieldFmt.c_str(),v); printField(name,buffer_string); return *this; } -OFile& OFile::printField(const std::string&name,int v){ +OFile& OFile::printField(const std::string&name,int v) { sprintf(buffer_string," %d",v); printField(name,buffer_string); return *this; } -OFile& OFile::printField(const std::string&name,const std::string & v){ +OFile& OFile::printField(const std::string&name,const std::string & v) { unsigned i; - for(i=0;i=const_fields.size()){ + for(i=0; i=const_fields.size()) { Field field; field.name=name; field.value=v; @@ -193,45 +193,45 @@ OFile& OFile::printField(const std::string&name,const std::string & v){ return *this; } -OFile& OFile::setupPrintValue( Value *val ){ - if( val->isPeriodic() ){ - addConstantField("min_" + val->getName() ); - addConstantField("max_" + val->getName() ); +OFile& OFile::setupPrintValue( Value *val ) { + if( val->isPeriodic() ) { + addConstantField("min_" + val->getName() ); + addConstantField("max_" + val->getName() ); } return *this; } -OFile& OFile::printField( Value* val, const double& v ){ +OFile& OFile::printField( Value* val, const double& v ) { printField( val->getName(), v ); - if( val->isPeriodic() ){ - std::string min, max; val->getDomain( min, max ); - printField( "min_" + val->getName(), min ); - printField("max_" + val->getName(), max ); - } + if( val->isPeriodic() ) { + std::string min, max; val->getDomain( min, max ); + printField( "min_" + val->getName(), min ); + printField("max_" + val->getName(), max ); + } return *this; } -OFile& OFile::printField(){ +OFile& OFile::printField() { bool reprint=false; - if(fieldChanged || fields.size()!=previous_fields.size()){ + if(fieldChanged || fields.size()!=previous_fields.size()) { reprint=true; - } else for(unsigned i=0;i0 && (!comm || comm->Get_rank()==0)){ - FILE* ff=std::fopen(const_cast(fname.c_str()),"r"); - if(ff){ - std::fclose(ff); - std::string backup; - size_t found=fname.find_last_of("/\\"); - std::string directory=fname.substr(0,found+1); - std::string file=fname.substr(found+1); - for(int i=0;;i++){ - std::string num; - Tools::convert(i,num); - if(i>maxbackup) plumed_merror("cannot backup file "+file+" maximum number of backup is "+num+"\n"); - backup=directory+bstring +"."+num+"."+file; - FILE* fff=std::fopen(backup.c_str(),"r"); - if(!fff) break; - else std::fclose(fff); - } - int check=rename(fname.c_str(),backup.c_str()); - plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for reason: "+strerror(errno)); - } - } +void OFile::backupFile( const std::string& bstring, const std::string& fname ) { + if(fname=="/dev/null") return; + int maxbackup=100; + if(std::getenv("PLUMED_MAXBACKUP")) Tools::convert(std::getenv("PLUMED_MAXBACKUP"),maxbackup); + if(maxbackup>0 && (!comm || comm->Get_rank()==0)) { + FILE* ff=std::fopen(const_cast(fname.c_str()),"r"); + if(ff) { + std::fclose(ff); + std::string backup; + size_t found=fname.find_last_of("/\\"); + std::string directory=fname.substr(0,found+1); + std::string file=fname.substr(found+1); + for(int i=0;; i++) { + std::string num; + Tools::convert(i,num); + if(i>maxbackup) plumed_merror("cannot backup file "+file+" maximum number of backup is "+num+"\n"); + backup=directory+bstring +"."+num+"."+file; + FILE* fff=std::fopen(backup.c_str(),"r"); + if(!fff) break; + else std::fclose(fff); + } + int check=rename(fname.c_str(),backup.c_str()); + plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for reason: "+strerror(errno)); + } + } } -OFile& OFile::open(const std::string&path){ +OFile& OFile::open(const std::string&path) { plumed_assert(!cloned); eof=false; err=false; @@ -294,26 +294,26 @@ OFile& OFile::open(const std::string&path){ gzfp=NULL; this->path=path; this->path=appendSuffix(path,getSuffix()); - if(checkRestart()){ - fp=std::fopen(const_cast(this->path.c_str()),"a"); - mode="a"; - if(Tools::extension(this->path)=="gz"){ + if(checkRestart()) { + fp=std::fopen(const_cast(this->path.c_str()),"a"); + mode="a"; + if(Tools::extension(this->path)=="gz") { #ifdef __PLUMED_HAS_ZLIB - gzfp=(void*)gzopen(const_cast(this->path.c_str()),"a9"); + gzfp=(void*)gzopen(const_cast(this->path.c_str()),"a9"); #else - plumed_merror("trying to use a gz file without zlib being linked"); + plumed_merror("trying to use a gz file without zlib being linked"); #endif - } + } } else { - backupFile( backstring, this->path ); - if(comm)comm->Barrier(); - fp=std::fopen(const_cast(this->path.c_str()),"w"); - mode="w"; - if(Tools::extension(this->path)=="gz"){ + backupFile( backstring, this->path ); + if(comm)comm->Barrier(); + fp=std::fopen(const_cast(this->path.c_str()),"w"); + mode="w"; + if(Tools::extension(this->path)=="gz") { #ifdef __PLUMED_HAS_ZLIB - gzfp=(void*)gzopen(const_cast(this->path.c_str()),"w9"); + gzfp=(void*)gzopen(const_cast(this->path.c_str()),"w9"); #else - plumed_merror("trying to use a gz file without zlib being linked"); + plumed_merror("trying to use a gz file without zlib being linked"); #endif } } @@ -321,18 +321,18 @@ OFile& OFile::open(const std::string&path){ return *this; } -OFile& OFile::rewind(){ +OFile& OFile::rewind() { // we use here "hard" rewind, which means close/reopen // the reason is that normal rewind does not work when in append mode // moreover, we can take a backup of the file plumed_assert(fp); clearFields(); - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB gzclose((gzFile)gzfp); #endif } else fclose(fp); - if(!comm || comm->Get_rank()==0){ + if(!comm || comm->Get_rank()==0) { std::string fname=this->path; size_t found=fname.find_last_of("/\\"); std::string directory=fname.substr(0,found+1); @@ -341,7 +341,7 @@ OFile& OFile::rewind(){ int check=rename(fname.c_str(),backup.c_str()); plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for reason: "+strerror(errno)); } - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB gzfp=(void*)gzopen(const_cast(this->path.c_str()),"w9"); #endif @@ -349,14 +349,14 @@ OFile& OFile::rewind(){ return *this; } -FileBase& OFile::flush(){ - if(heavyFlush){ - if(gzfp){ +FileBase& OFile::flush() { + if(heavyFlush) { + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB gzclose(gzFile(gzfp)); gzfp=(void*)gzopen(const_cast(path.c_str()),"a"); #endif - } else{ + } else { fclose(fp); fp=std::fopen(const_cast(path.c_str()),"a"); } @@ -372,7 +372,7 @@ FileBase& OFile::flush(){ return *this; } -bool OFile::checkRestart()const{ +bool OFile::checkRestart()const { if(enforceRestart_) return true; else if(enforceBackup_) return false; else if(action) return action->getRestart(); @@ -380,13 +380,13 @@ bool OFile::checkRestart()const{ else return false; } -OFile& OFile::enforceRestart(){ +OFile& OFile::enforceRestart() { enforceRestart_=true; enforceBackup_=false; return *this; } -OFile& OFile::enforceBackup(){ +OFile& OFile::enforceBackup() { enforceBackup_=true; enforceRestart_=false; return *this; diff --git a/src/tools/OFile.h b/src/tools/OFile.h index 106d88b6be..84f044a94d 100644 --- a/src/tools/OFile.h +++ b/src/tools/OFile.h @@ -26,7 +26,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class Value; @@ -90,7 +90,7 @@ the enforceRestart() method before opening a file. To have all files managed consistently, it is important to use OFile in the proper way. This should allow multi-replica plumed, restart and backups to work in -the expected way. For this reason all the operations in OFile and IFile +the expected way. For this reason all the operations in OFile and IFile are synchronizing all the processors of the group, so call to OFile functions should always be performed by all processes; for this reason is also not usefull to use Log for debugging because only master threads will actually write. @@ -129,7 +129,7 @@ int main(){ snp.flush(); // the only difference is that snp is rewound // notice that it should be rewound just before writing -// because rewind is going to move the file out of the way +// because rewind is going to move the file out of the way // to have a safe copy of the file ("bck.last.filename") // Also notice that snapshots should be flushed // for this reason, it is better to write them only @@ -145,7 +145,7 @@ int main(){ */ class OFile: -public virtual FileBase{ + public virtual FileBase { /// Pointer to a linked OFile. /// see link(OFile&) OFile* linked; @@ -159,7 +159,7 @@ public virtual FileBase{ unsigned actual_buffer_length; /// Class identifying a single field for fielded output class Field: - public FieldBase{ + public FieldBase { }; /// Low-level write size_t llwrite(const char*,size_t); @@ -208,13 +208,13 @@ public virtual FileBase{ /// Backup a file by giving it a different name void backupFile( const std::string& bstring, const std::string& fname ); /// This backs up all the files that would have been created with the -/// name str. It is used in analysis when you are not restarting. Analysis +/// name str. It is used in analysis when you are not restarting. Analysis /// output files at different times, which are names analysis.0., /// analysis.1. and , are backed up to bck.0.analysis.0., /// bck.0.analysis.1. and bck.0. void backupAllFiles( const std::string& str ); /// Opens the file using automatic append/backup - OFile& open(const std::string&name); + OFile& open(const std::string&name); /// Set the prefix for output. /// Typically "PLUMED: ". Notice that lines with a prefix cannot /// be parsed using fields in a IFile. @@ -235,18 +235,18 @@ public virtual FileBase{ OFile& setupPrintValue( Value *val ); /// Print a value OFile& printField( Value* val, const double& v ); -/** Close a line. -Typically used as -\verbatim - of.printField("a",a).printField("b",b).printField(); -\endverbatim -*/ + /** Close a line. + Typically used as + \verbatim + of.printField("a",a).printField("b",b).printField(); + \endverbatim + */ OFile& printField(); -/** -Resets the list of fields. -As it is only possible to add new constant fields (addConstantField()), -this method can be used to clean the field list. -*/ + /** + Resets the list of fields. + As it is only possible to add new constant fields (addConstantField()), + this method can be used to clean the field list. + */ OFile& clearFields(); /// Formatted output with explicit format - a la printf int printf(const char*fmt,...); @@ -266,7 +266,7 @@ this method can be used to clean the field list. /// Write using << syntax template -OFile& operator<<(OFile&of,const T &t){ +OFile& operator<<(OFile&of,const T &t) { of.oss< -namespace PLMD{ +namespace PLMD { -unsigned OpenMP::getCachelineSize(){ +unsigned OpenMP::getCachelineSize() { static unsigned cachelineSize=512; if(std::getenv("PLUMED_CACHELINE_SIZE")) Tools::convert(std::getenv("PLUMED_CACHELINE_SIZE"),cachelineSize); return cachelineSize; } -unsigned OpenMP::getNumThreads(){ +unsigned OpenMP::getNumThreads() { static unsigned numThreads=1; if(std::getenv("PLUMED_NUM_THREADS")) Tools::convert(std::getenv("PLUMED_NUM_THREADS"),numThreads); return numThreads; diff --git a/src/tools/OpenMP.h b/src/tools/OpenMP.h index 418451c176..c79258ff76 100644 --- a/src/tools/OpenMP.h +++ b/src/tools/OpenMP.h @@ -24,30 +24,30 @@ #include -namespace PLMD{ +namespace PLMD { -class OpenMP{ +class OpenMP { public: /// Get number of threads that can be used by openMP -static unsigned getNumThreads(); + static unsigned getNumThreads(); /// get cacheline size -static unsigned getCachelineSize(); + static unsigned getCachelineSize(); /// Get a reasonable number of threads so as to access to an array of size s located at x -template -static unsigned getGoodNumThreads(const T*x,unsigned s); + template + static unsigned getGoodNumThreads(const T*x,unsigned s); /// Get a reasonable number of threads so as to access to vector v; -template -static unsigned getGoodNumThreads(const std::vector & v); + template + static unsigned getGoodNumThreads(const std::vector & v); }; template -unsigned OpenMP::getGoodNumThreads(const T*x,unsigned n){ +unsigned OpenMP::getGoodNumThreads(const T*x,unsigned n) { unsigned long p=(unsigned long) x; (void) p; // this is not to have warnings. notice that the pointer location is not used actually. // a factor two is necessary since there is no guarantee that x is aligned @@ -61,7 +61,7 @@ unsigned OpenMP::getGoodNumThreads(const T*x,unsigned n){ template -unsigned OpenMP::getGoodNumThreads(const std::vector & v){ +unsigned OpenMP::getGoodNumThreads(const std::vector & v) { if(v.size()==0) return 1; else return getGoodNumThreads(&v[0],v.size()); } diff --git a/src/tools/PDB.cpp b/src/tools/PDB.cpp index ba50805c22..82852ce064 100644 --- a/src/tools/PDB.cpp +++ b/src/tools/PDB.cpp @@ -27,74 +27,74 @@ using namespace std; -namespace PLMD{ +namespace PLMD { -unsigned PDB::getNumberOfAtomBlocks()const{ +unsigned PDB::getNumberOfAtomBlocks()const { return block_ends.size(); } -const std::vector & PDB::getAtomBlockEnds()const{ +const std::vector & PDB::getAtomBlockEnds()const { return block_ends; } -const std::vector & PDB::getPositions()const{ +const std::vector & PDB::getPositions()const { return positions; } -void PDB::setPositions(const std::vector &v ){ - plumed_assert( v.size()==positions.size() ); - positions=v; +void PDB::setPositions(const std::vector &v ) { + plumed_assert( v.size()==positions.size() ); + positions=v; } -const std::vector & PDB::getOccupancy()const{ +const std::vector & PDB::getOccupancy()const { return occupancy; } -const std::vector & PDB::getBeta()const{ +const std::vector & PDB::getBeta()const { return beta; } -const std::vector & PDB::getRemark()const{ +const std::vector & PDB::getRemark()const { return remark; } -void PDB::addRemark( const std::vector& v1 ){ +void PDB::addRemark( const std::vector& v1 ) { remark.insert(remark.begin(),v1.begin(),v1.end()); } -const std::vector & PDB::getAtomNumbers()const{ +const std::vector & PDB::getAtomNumbers()const { return numbers; } -std::string PDB::getAtomName(AtomNumber a)const{ +std::string PDB::getAtomName(AtomNumber a)const { const auto p=number2index.find(a); if(p==number2index.end()) return ""; else return atomsymb[p->second]; } -unsigned PDB::getResidueNumber(AtomNumber a)const{ +unsigned PDB::getResidueNumber(AtomNumber a)const { const auto p=number2index.find(a); if(p==number2index.end()) return 0; else return residue[p->second]; } -std::string PDB::getResidueName(AtomNumber a) const{ +std::string PDB::getResidueName(AtomNumber a) const { const auto p=number2index.find(a); if(p==number2index.end()) return ""; else return residuenames[p->second]; } -unsigned PDB::size()const{ +unsigned PDB::size()const { return positions.size(); } -bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale){ +bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale) { //cerr< v1; v1=Tools::getWords(line.substr(6)); - addRemark( v1 ); + if(record=="TER") { between_ters=false; block_ends.push_back( positions.size() ); } + if(record=="END") { file_is_alive=true; break;} + if(record=="ENDMDL") { file_is_alive=true; break;} + if(record=="REMARK") { + vector v1; v1=Tools::getWords(line.substr(6)); + addRemark( v1 ); } - if(record=="ATOM" || record=="HETATM"){ + if(record=="ATOM" || record=="HETATM") { between_ters=true; AtomNumber a; unsigned resno; double o,b; @@ -148,17 +148,17 @@ bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale){ return file_is_alive; } -void PDB::setArgKeyword( const std::string& new_args ){ +void PDB::setArgKeyword( const std::string& new_args ) { bool replaced=false; - for(unsigned i=0;i& chains ) const { chains.resize(0); chains.push_back( chain[0] ); - for(unsigned i=1;i PDB::getAtomsInResidue(const unsigned& resnum,const std::string& chainid)const { std::vector tmp; - for(unsigned i=0;i PDB::getAtomsInResidue(const unsigned& resnum,const std: std::vector PDB::getAtomsInChain(const std::string& chainid)const { std::vector tmp; - for(unsigned i=0;i PDB::getAtomsInChain(const std::string& chainid)const { } std::string PDB::getChainID(const unsigned& resnumber) const { - for(unsigned i=0;isecond]; +Vector PDB::getPosition(AtomNumber a)const { + const auto p=number2index.find(a); + if(p==number2index.end()) plumed_merror("atom not available"); + else return positions[p->second]; } diff --git a/src/tools/PDB.h b/src/tools/PDB.h index 059ea4f6c1..05cee0a8a6 100644 --- a/src/tools/PDB.h +++ b/src/tools/PDB.h @@ -29,14 +29,14 @@ #include -namespace PLMD{ +namespace PLMD { class Log; /// Minimalistic pdb parser. /// Contain positions, atomic indexes, occupancy and beta. /// We should also add other info (e.g. residue name etc). -class PDB{ +class PDB { std::vector block_ends; std::vector atomsymb, chain; std::vector residue; @@ -59,11 +59,11 @@ class PDB{ /// Access to the beta array const std::vector & getBeta()const; /// This is used to set the keyword ARG - this is so we -/// we can use a1.* in the input for reference configurations +/// we can use a1.* in the input for reference configurations void setArgKeyword( const std::string& new_args ); /// Add information to the remark void addRemark( const std::vector& v1 ); -/// Access to the lines of REMARK +/// Access to the lines of REMARK const std::vector & getRemark()const; /// Access to the indexes const std::vector & getAtomNumbers()const; @@ -73,11 +73,11 @@ class PDB{ void getChainNames( std::vector& chains ) const; /// Get the residues in each of the chains void getResidueRange( const std::string& chainname, unsigned& res_start, unsigned& res_end, std::string& errmsg ) const; -/// Get the atoms in each of the chains +/// Get the atoms in each of the chains void getAtomRange( const std::string& chainname, AtomNumber& a_start, AtomNumber& a_end, std::string& errmsg ) const; /// Get the chain ID that a particular residue is a part of std::string getChainID(const unsigned& resnumber) const; -///use the log to dump information +///use the log to dump information friend Log& operator<<(Log& ostr, const PDB& pdb); /// return the name of a specific atom std::string getAtomName(AtomNumber a) const; @@ -99,9 +99,9 @@ class PDB{ /// Return the atom named aname from residue number resnum and chain. /// Chain=="*" matches any chain and makes it equivalent to getNamedAtomFromResidue. AtomNumber getNamedAtomFromResidueAndChain( const std::string& aname, const unsigned& resnum, const std::string& chain ) const; -/// Access to the atoms of a residue +/// Access to the atoms of a residue std::vector getAtomsInResidue(const unsigned& resnum,const std::string& chainid)const; -/// Access to the atoms of a chain +/// Access to the atoms of a chain std::vector getAtomsInChain(const std::string& chainid)const; /// Get the extents of the blocks containing the atoms const std::vector & getAtomBlockEnds() const ; diff --git a/src/tools/Pbc.cpp b/src/tools/Pbc.cpp index 025a2fa447..ff0ac18b0e 100644 --- a/src/tools/Pbc.cpp +++ b/src/tools/Pbc.cpp @@ -27,7 +27,7 @@ #include "Random.h" #include -namespace PLMD{ +namespace PLMD { Pbc::Pbc(): type(unset) @@ -36,83 +36,83 @@ Pbc::Pbc(): invBox.zero(); } -void Pbc::buildShifts(std::vector shifts[2][2][2])const{ +void Pbc::buildShifts(std::vector shifts[2][2][2])const { const double small=1e-28; // clear all shifts - for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) shifts[i][j][k].clear(); + for(int i=0; i<2; i++) for(int j=0; j<2; j++) for(int k=0; k<2; k++) shifts[i][j][k].clear(); // enumerate all possible shifts // since box is reduced, only 27 shifts have to be attempted - for(int l=-1;l<=1;l++) for(int m=-1;m<=1;m++) for(int n=-1;n<=1;n++){ + for(int l=-1; l<=1; l++) for(int m=-1; m<=1; m++) for(int n=-1; n<=1; n++) { // int/double shift vectors - int ishift[3]={l,m,n}; - Vector dshift(l,m,n); + int ishift[3]= {l,m,n}; + Vector dshift(l,m,n); // count how many components are != 0 - unsigned count=0; - for(int s=0;s<3;s++) if(ishift[s]!=0) count++; + unsigned count=0; + for(int s=0; s<3; s++) if(ishift[s]!=0) count++; // skips trivial (0,0,0) and cases with three shifts // only 18 shifts survive past this point - if(count==0 || count==3) continue; + if(count==0 || count==3) continue; // check if that Wigner-Seitz face is perpendicular to the axis. // this allows to eliminate shifts in symmetric cells. // e.g., if one lactice vector is orthogonal to the plane spanned // by the other two vectors, that shift should never be tried - Vector cosdir=matmul(reduced,transpose(reduced),dshift); - double dp=dotProduct(dshift,cosdir); - double ref=modulo2(dshift)*modulo2(cosdir); - if(std::fabs(ref-dp*dp)0) skip=true; - if(skip) continue; - skip=true; - for(int s=0;s<3;s++){ + bool skip=false; + for(int s=0; s<3; s++) if(ishift[s]*block[s]>0) skip=true; + if(skip) continue; + skip=true; + for(int s=0; s<3; s++) { // check that the components of cosdir along the non-shifted directions // have the proper sign - if(((1-ishift[s]*ishift[s])*block[s])*cosdir[s]<-small) skip=false; - } - if(skip)continue; + if(((1-ishift[s]*ishift[s])*block[s])*cosdir[s]<-small) skip=false; + } + if(skip)continue; // if we arrive to this point, shift is eligible and is added to the list - shifts[i][j][k].push_back(matmul(transpose(reduced),dshift)); - } - } + shifts[i][j][k].push_back(matmul(transpose(reduced),dshift)); + } + } } -void Pbc::fullSearch(Vector&d)const{ - if(type==unset) return; - Vector s=matmul(invReduced.transpose(),d); - for(int i=0;i<3;i++) s[i]=Tools::pbc(s[i]); - d=matmul(reduced.transpose(),s); - const int smax=4; - Vector a0(reduced.getRow(0)); - Vector a1(reduced.getRow(1)); - Vector a2(reduced.getRow(2)); - Vector best(d); - double lbest=d.modulo2(); - for(int i=-smax;i<=smax;i++) for(int j=-smax;j<=smax;j++) for(int k=-smax;k<=smax;k++){ - Vector trial=d+i*a0+j*a1+k*a2; - double ltrial=trial.modulo2(); - if(ltrial& dlist, unsigned max_index) const { - if (max_index==0) max_index=dlist.size(); - if(type==unset){ + if (max_index==0) max_index=dlist.size(); + if(type==unset) { } else if(type==orthorombic) { #ifdef __PLUMED_PBC_WHILE - for(unsigned k=0;khdiag[0]) dlist[k][0]-=diag[0]; while(dlist[k][0]<=mdiag[0]) dlist[k][0]+=diag[0]; while(dlist[k][1]>hdiag[1]) dlist[k][1]-=diag[1]; while(dlist[k][1]<=mdiag[1]) dlist[k][1]+=diag[1]; while(dlist[k][2]>hdiag[2]) dlist[k][2]-=diag[2]; - while(dlist[k][2]<=mdiag[2]) dlist[k][2]+=diag[2]; - } + while(dlist[k][2]<=mdiag[2]) dlist[k][2]+=diag[2]; + } #else - for(unsigned k=0;khdiag[i]) d[i]-=diag[i]; while(d[i]<=mdiag[i]) d[i]+=diag[i]; } #else - for(int i=0;i<3;i++) d[i]=Tools::pbc(d[i]*invBox(i,i))*box(i,i); + for(int i=0; i<3; i++) d[i]=Tools::pbc(d[i]*invBox(i,i))*box(i,i); #endif } else if(type==generic) { Vector s=matmul(d,invReduced); @@ -195,22 +195,22 @@ Vector Pbc::distance(const Vector&v1,const Vector&v2,int*nshifts)const{ // NOTICE: the check in the previous line, albeit correct, is breaking many regtest // since it does not apply Tools::pbc in many cases. Moreover, it does not // introduce a significant gain. I thus leave it out for the moment. - if(true){ + if(true) { // bring to -0.5,+0.5 region in scaled coordinates: - for(int i=0;i<3;i++) s[i]=Tools::pbc(s[i]); + for(int i=0; i<3; i++) s[i]=Tools::pbc(s[i]); d=matmul(s,reduced); // check if shifts have to be attempted: - if((std::fabs(s[0])+std::fabs(s[1])+std::fabs(s[2])>0.5)){ + if((std::fabs(s[0])+std::fabs(s[1])+std::fabs(s[2])>0.5)) { // list of shifts is specific for that "octant" (depends on signs of s[i]): const std::vector & myshifts(shifts[(s[0]>0?1:0)][(s[1]>0?1:0)][(s[2]>0?1:0)]); Vector best(d); double lbest(modulo2(best)); // loop over possible shifts: if(nshifts) *nshifts+=myshifts.size(); - for(unsigned i=0;i #include -namespace PLMD{ +namespace PLMD { /* Tool to deal with periodic boundary conditions. @@ -35,7 +35,7 @@ Tool to deal with periodic boundary conditions. This class is useful to apply periodic boundary conditions on interatomic distances. It stores privately information about reduced lattice vectors */ -class Pbc{ +class Pbc { /// Type of box enum {unset,orthorombic,generic} type; /// Box @@ -98,12 +98,12 @@ class Pbc{ }; inline -Vector Pbc::distance(const Vector& v1,const Vector& v2)const{ +Vector Pbc::distance(const Vector& v1,const Vector& v2)const { return distance(v1,v2,NULL); } inline -bool Pbc::isSet()const{ +bool Pbc::isSet()const { return type!=unset; } diff --git a/src/tools/RMSD.cpp b/src/tools/RMSD.cpp index 4818576700..0bc2eff548 100644 --- a/src/tools/RMSD.cpp +++ b/src/tools/RMSD.cpp @@ -27,45 +27,45 @@ #include #include "Tools.h" using namespace std; -namespace PLMD{ +namespace PLMD { RMSD::RMSD() : alignmentMethod(SIMPLE),reference_center_is_calculated(false),reference_center_is_removed(false),positions_center_is_calculated(false),positions_center_is_removed(false) {} /// -/// general method to set all the rmsd property at once by using a pdb where occupancy column sets the weights for the atoms involved in the -/// alignment and beta sets the weight that are used for calculating the displacement. +/// general method to set all the rmsd property at once by using a pdb where occupancy column sets the weights for the atoms involved in the +/// alignment and beta sets the weight that are used for calculating the displacement. /// -void RMSD::set(const PDB&pdb, const string & mytype, bool remove_center, bool normalize_weights ){ +void RMSD::set(const PDB&pdb, const string & mytype, bool remove_center, bool normalize_weights ) { - set(pdb.getOccupancy(),pdb.getBeta(),pdb.getPositions(),mytype,remove_center,normalize_weights); + set(pdb.getOccupancy(),pdb.getBeta(),pdb.getPositions(),mytype,remove_center,normalize_weights); } -void RMSD::set(const std::vector & align, const std::vector & displace, const std::vector & reference , const string & mytype, bool remove_center, bool normalize_weights ){ +void RMSD::set(const std::vector & align, const std::vector & displace, const std::vector & reference, const string & mytype, bool remove_center, bool normalize_weights ) { - setReference(reference); // this by default remove the com and assumes uniform weights - setAlign(align, normalize_weights, remove_center); // this recalculates the com with weights. If remove_center=false then it restore the center back - setDisplace(displace, normalize_weights); // this is does not affect any calculation of the weights - setType(mytype); + setReference(reference); // this by default remove the com and assumes uniform weights + setAlign(align, normalize_weights, remove_center); // this recalculates the com with weights. If remove_center=false then it restore the center back + setDisplace(displace, normalize_weights); // this is does not affect any calculation of the weights + setType(mytype); } -void RMSD::setType(const string & mytype){ +void RMSD::setType(const string & mytype) { - alignmentMethod=SIMPLE; // initialize with the simplest case: no rotation - if (mytype=="SIMPLE"){ - alignmentMethod=SIMPLE; - } - else if (mytype=="OPTIMAL"){ - alignmentMethod=OPTIMAL; - } - else if (mytype=="OPTIMAL-FAST"){ - alignmentMethod=OPTIMAL_FAST; - } - else plumed_merror("unknown RMSD type" + mytype); + alignmentMethod=SIMPLE; // initialize with the simplest case: no rotation + if (mytype=="SIMPLE") { + alignmentMethod=SIMPLE; + } + else if (mytype=="OPTIMAL") { + alignmentMethod=OPTIMAL; + } + else if (mytype=="OPTIMAL-FAST") { + alignmentMethod=OPTIMAL_FAST; + } + else plumed_merror("unknown RMSD type" + mytype); } -void RMSD::clear(){ +void RMSD::clear() { reference.clear(); reference_center_is_calculated=false; reference_center_is_removed=false; @@ -75,98 +75,98 @@ void RMSD::clear(){ positions_center_is_removed=false; } -string RMSD::getMethod(){ - string mystring; - switch(alignmentMethod){ - case SIMPLE: mystring.assign("SIMPLE");break; - case OPTIMAL: mystring.assign("OPTIMAL");break; - case OPTIMAL_FAST: mystring.assign("OPTIMAL-FAST");break; - } - return mystring; +string RMSD::getMethod() { + string mystring; + switch(alignmentMethod) { + case SIMPLE: mystring.assign("SIMPLE"); break; + case OPTIMAL: mystring.assign("OPTIMAL"); break; + case OPTIMAL_FAST: mystring.assign("OPTIMAL-FAST"); break; + } + return mystring; } /// /// this calculates the center of mass for the reference and removes it from the reference itself /// considering uniform weights for alignment /// -void RMSD::setReference(const vector & reference){ +void RMSD::setReference(const vector & reference) { unsigned n=reference.size(); this->reference=reference; plumed_massert(align.empty(),"you should first clear() an RMSD object, then set a new reference"); plumed_massert(displace.empty(),"you should first clear() an RMSD object, then set a new reference"); align.resize(n,1.0/n); displace.resize(n,1.0/n); - for(unsigned i=0;ireference[i]*align[i]; - for(unsigned i=0;ireference[i]-=reference_center; + for(unsigned i=0; ireference[i]*align[i]; + for(unsigned i=0; ireference[i]-=reference_center; reference_center_is_calculated=true; reference_center_is_removed=true; } /// /// the alignment weights are here normalized to 1 and the center of the reference is removed accordingly /// -void RMSD::setAlign(const vector & align, bool normalize_weights, bool remove_center){ +void RMSD::setAlign(const vector & align, bool normalize_weights, bool remove_center) { unsigned n=reference.size(); plumed_massert(this->align.size()==align.size(),"mismatch in dimension of align/displace arrays"); this->align=align; - if(normalize_weights){ - double w=0.0; - for(unsigned i=0;ialign[i]; - double inv=1.0/w; - for(unsigned i=0;ialign[i]*=inv; + if(normalize_weights) { + double w=0.0; + for(unsigned i=0; ialign[i]; + double inv=1.0/w; + for(unsigned i=0; ialign[i]*=inv; } // recalculate the center anyway // just remove the center if that is asked // if the center was removed before, then add it and store the new one - if(reference_center_is_removed){ - plumed_massert(reference_center_is_calculated," seems that the reference center has been removed but not calculated and stored!"); - addCenter(reference,reference_center); + if(reference_center_is_removed) { + plumed_massert(reference_center_is_calculated," seems that the reference center has been removed but not calculated and stored!"); + addCenter(reference,reference_center); } reference_center=calculateCenter(reference,this->align); reference_center_is_calculated=true; - if(remove_center){ - removeCenter(reference,reference_center); - reference_center_is_removed=true; + if(remove_center) { + removeCenter(reference,reference_center); + reference_center_is_removed=true; } else { - reference_center_is_removed=false; + reference_center_is_removed=false; } } /// /// here the weigth for normalized weighths are normalized and set /// -void RMSD::setDisplace(const vector & displace, bool normalize_weights){ +void RMSD::setDisplace(const vector & displace, bool normalize_weights) { unsigned n=reference.size(); plumed_massert(this->displace.size()==displace.size(),"mismatch in dimension of align/displace arrays"); this->displace=displace; double w=0.0; - for(unsigned i=0;idisplace[i]; + for(unsigned i=0; idisplace[i]; double inv=1.0/w; - if(normalize_weights){for(unsigned i=0;idisplace[i]*=inv;} + if(normalize_weights) {for(unsigned i=0; idisplace[i]*=inv;} } /// /// This is the main workhorse for rmsd that decides to use specific optimal alignment versions /// -double RMSD::calculate(const std::vector & positions,std::vector &derivatives, bool squared)const{ +double RMSD::calculate(const std::vector & positions,std::vector &derivatives, bool squared)const { double ret=0.; - switch(alignmentMethod){ - case SIMPLE : { - // do a simple alignment without rotation - std::vector displacement( derivatives.size() ); - ret=simpleAlignment(align,displace,positions,reference,derivatives,displacement,squared); - break; - } case OPTIMAL_FAST : { - // this is calling the fastest option: - if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - break; - - } case OPTIMAL : { - // this is the fast routine but in the "safe" mode, which gives less numerical error: - if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - break; - } - } + switch(alignmentMethod) { + case SIMPLE : { + // do a simple alignment without rotation + std::vector displacement( derivatives.size() ); + ret=simpleAlignment(align,displace,positions,reference,derivatives,displacement,squared); + break; + } case OPTIMAL_FAST : { + // this is calling the fastest option: + if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + break; + + } case OPTIMAL : { + // this is the fast routine but in the "safe" mode, which gives less numerical error: + if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + break; + } + } return ret; @@ -174,116 +174,116 @@ double RMSD::calculate(const std::vector & positions,std::vector /// convenience method for calculating the standard derivatives and the derivative of the rmsd respect to the reference position -double RMSD::calc_DDistDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef , const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef, squared); - else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); - else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - } +double RMSD::calc_DDistDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef, squared); + else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); + else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + } return ret; } /// convenience method for calculating the standard derivatives and the derivative of the rmsd respect to the reference position without the matrix contribution /// as required by SOMA -double RMSD::calc_SOMA( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef , const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef, squared); - else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); - else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - } +double RMSD::calc_SOMA( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef, squared); + else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); + else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + } return ret; } -double RMSD::calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - break; - } +double RMSD::calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + break; + } return ret; } -double RMSD::calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, Matrix > &DRotDRef, const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - break; - } +double RMSD::calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, Matrix > &DRotDRef, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + break; + } return ret; } double RMSD::calc_PCAelements( const std::vector& positions, std::vector &DDistDPos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & alignedpositions, std::vector & centeredpositions, std::vector ¢eredreference, const bool& squared ) const { - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - break; - } + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + break; + } return ret; } -double RMSD::calc_FitElements( const std::vector& positions, Tensor & Rotation, Matrix > & DRotDPos, std::vector & centeredpositions, Vector ¢er_positions, const bool& squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); - else ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); - break; - case OPTIMAL: - if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); - else ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); - break; - } +double RMSD::calc_FitElements( const std::vector& positions, Tensor & Rotation, Matrix > & DRotDPos, std::vector & centeredpositions, Vector ¢er_positions, const bool& squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); + else ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); + break; + case OPTIMAL: + if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); + else ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); + break; + } return ret; } @@ -293,58 +293,58 @@ double RMSD::calc_FitElements( const std::vector& positions, Tensor & Ro double RMSD::simpleAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & displacement, - bool squared)const{ - - double dist(0); - unsigned n=reference.size(); - - Vector apositions; - Vector areference; - Vector dpositions; - Vector dreference; - - for(unsigned i=0;i & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & displacement, + bool squared)const { - Vector shift=((apositions-areference)-(dpositions-dreference)); - for(unsigned i=0;i double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const{ + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const { double dist(0); const unsigned n=reference.size(); // This is the trace of positions*positions + reference*reference @@ -358,13 +358,13 @@ double RMSD::optimalAlignment(const std::vector & align, Vector cpositions; // first expensive loop: compute centers - for(unsigned iat=0;iat & align, m[3][2] = m[2][3]; Tensor dm_drr01[4][4]; - if(!alEqDis){ + if(!alEqDis) { dm_drr01[0][0] = 2.0*Tensor(-1.0, 0.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0,-1.0); dm_drr01[1][1] = 2.0*Tensor(-1.0, 0.0, 0.0, 0.0,+1.0, 0.0, 0.0, 0.0,+1.0); dm_drr01[2][2] = 2.0*Tensor(+1.0, 0.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0,+1.0); @@ -413,7 +413,7 @@ double RMSD::optimalAlignment(const std::vector & align, Matrix eigenvecs; int diagerror=diagMat(m, eigenvals, eigenvecs ); - if (diagerror!=0){ + if (diagerror!=0) { string sdiagerror; Tools::convert(diagerror,sdiagerror); string msg="DIAGONALIZATION FAILED WITH ERROR CODE "+sdiagerror; @@ -427,20 +427,20 @@ double RMSD::optimalAlignment(const std::vector & align, Vector4d q(eigenvecs[0][0],eigenvecs[0][1],eigenvecs[0][2],eigenvecs[0][3]); Tensor dq_drr01[4]; - if(!alEqDis){ + if(!alEqDis) { double dq_dm[4][4][4]; - for(unsigned i=0;i<4;i++) for(unsigned j=0;j<4;j++) for(unsigned k=0;k<4;k++){ - double tmp=0.0; + for(unsigned i=0; i<4; i++) for(unsigned j=0; j<4; j++) for(unsigned k=0; k<4; k++) { + double tmp=0.0; // perturbation theory for matrix m - for(unsigned l=1;l<4;l++) tmp+=eigenvecs[l][j]*eigenvecs[l][i]/(eigenvals[0]-eigenvals[l])*eigenvecs[0][k]; - dq_dm[i][j][k]=tmp; - } + for(unsigned l=1; l<4; l++) tmp+=eigenvecs[l][j]*eigenvecs[l][i]/(eigenvals[0]-eigenvals[l])*eigenvecs[0][k]; + dq_dm[i][j][k]=tmp; + } // propagation to _drr01 - for(unsigned i=0;i<4;i++){ + for(unsigned i=0; i<4; i++) { Tensor tmp; - for(unsigned j=0;j<4;j++) for(unsigned k=0;k<4;k++) { - tmp+=dq_dm[i][j][k]*dm_drr01[j][k]; - } + for(unsigned j=0; j<4; j++) for(unsigned k=0; k<4; k++) { + tmp+=dq_dm[i][j][k]*dm_drr01[j][k]; + } dq_drr01[i]=tmp; } } @@ -459,9 +459,9 @@ double RMSD::optimalAlignment(const std::vector & align, rotation[2][0]=2*(+q[0]*q[2]+q[1]*q[3]); rotation[2][1]=2*(-q[0]*q[1]+q[2]*q[3]); - + Tensor drotation_drr01[3][3]; - if(!alEqDis){ + if(!alEqDis) { drotation_drr01[0][0]=2*q[0]*dq_drr01[0]+2*q[1]*dq_drr01[1]-2*q[2]*dq_drr01[2]-2*q[3]*dq_drr01[3]; drotation_drr01[1][1]=2*q[0]*dq_drr01[0]-2*q[1]*dq_drr01[1]+2*q[2]*dq_drr01[2]-2*q[3]*dq_drr01[3]; drotation_drr01[2][2]=2*q[0]*dq_drr01[0]-2*q[1]*dq_drr01[1]-2*q[2]*dq_drr01[2]+2*q[3]*dq_drr01[3]; @@ -488,13 +488,13 @@ double RMSD::optimalAlignment(const std::vector & align, Vector ddist_dcpositions; // third expensive loop: derivatives - for(unsigned iat=0;iat & align, } } - if(!alEqDis){ + if(!alEqDis) { Tensor ddist_drr01; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) ddist_drr01+=ddist_drotation[i][j]*drotation_drr01[i][j]; - for(unsigned iat=0;iat double RMSD::optimalAlignment(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, + const std::vector & reference, + std::vector & derivatives, bool squared) const { - //std::cerr<<"setting up the core data \n"; - RMSDCoreData cd(align,displace,positions,reference); - - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - return dist; + //std::cerr<<"setting up the core data \n"; + RMSDCoreData cd(align,displace,positions,reference); + + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + return dist; } #endif template double RMSD::optimalAlignment_DDistDRef(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReference(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReference(); + return dist; } template double RMSD::optimalAlignment_SOMA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReferenceSOMA(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReferenceSOMA(); + return dist; } template double RMSD::optimalAlignment_DDistDRef_Rot_DRotDPos(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - Tensor & Rotation, - Matrix > &DRotDPos, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReference(); - // get the rotation matrix - Rotation=cd.getRotationMatrixReferenceToPositions(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + Tensor & Rotation, + Matrix > &DRotDPos, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReference(); + // get the rotation matrix + Rotation=cd.getRotationMatrixReferenceToPositions(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(); + return dist; } template double RMSD::optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - Tensor & Rotation, - Matrix > &DRotDPos, - Matrix > &DRotDRef, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReference(); - // get the rotation matrix - Rotation=cd.getRotationMatrixReferenceToPositions(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(); - DRotDRef=cd.getDRotationDReference(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + Tensor & Rotation, + Matrix > &DRotDPos, + Matrix > &DRotDRef, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReference(); + // get the rotation matrix + Rotation=cd.getRotationMatrixReferenceToPositions(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(); + DRotDRef=cd.getDRotationDReference(); + return dist; } template double RMSD::optimalAlignment_PCA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - std::vector & alignedpositions, - std::vector & centeredpositions, - std::vector & centeredreference, - Tensor & Rotation, - std::vector & DDistDPos, - Matrix > & DRotDPos, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); - // make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - DDistDPos=cd.getDDistanceDPositions(); - // get the rotation matrix - Rotation=cd.getRotationMatrixPositionsToReference(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse - // get aligned positions - alignedpositions=cd.getAlignedPositionsToReference(); - // get centered positions - centeredpositions=cd.getCenteredPositions(); - // get centered reference - centeredreference=cd.getCenteredReference(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & alignedpositions, + std::vector & centeredpositions, + std::vector & centeredreference, + Tensor & Rotation, + std::vector & DDistDPos, + Matrix > & DRotDPos, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); + // make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + DDistDPos=cd.getDDistanceDPositions(); + // get the rotation matrix + Rotation=cd.getRotationMatrixPositionsToReference(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse + // get aligned positions + alignedpositions=cd.getAlignedPositionsToReference(); + // get centered positions + centeredpositions=cd.getCenteredPositions(); + // get centered reference + centeredreference=cd.getCenteredReference(); + return dist; } template double RMSD::optimalAlignment_Fit(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - Tensor & Rotation, - Matrix > & DRotDPos, - std::vector & centeredpositions, - Vector & center_positions, - bool squared){ - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); - // get the rotation matrix - Rotation=cd.getRotationMatrixPositionsToReference(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse - // get centered positions - centeredpositions=cd.getCenteredPositions(); + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + Tensor & Rotation, + Matrix > & DRotDPos, + std::vector & centeredpositions, + Vector & center_positions, + bool squared) { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); + // get the rotation matrix + Rotation=cd.getRotationMatrixPositionsToReference(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse + // get centered positions + centeredpositions=cd.getCenteredPositions(); // get center - center_positions=cd.getPositionsCenter(); - return dist; + center_positions=cd.getPositionsCenter(); + return dist; } @@ -786,27 +786,27 @@ double RMSD::optimalAlignment_Fit(const std::vector & align, /// This calculates the elements needed by the quaternion to calculate everything that is needed /// additional calls retrieve different components -/// note that this considers that the centers of both reference and positions are already setted -/// but automatically should properly account for non removed components: if not removed then it -/// removes prior to calculation of the alignment -void RMSDCoreData::doCoreCalc(bool safe,bool alEqDis, bool only_rotation){ +/// note that this considers that the centers of both reference and positions are already setted +/// but automatically should properly account for non removed components: if not removed then it +/// removes prior to calculation of the alignment +void RMSDCoreData::doCoreCalc(bool safe,bool alEqDis, bool only_rotation) { retrieve_only_rotation=only_rotation; const unsigned n=static_cast(reference.size()); - - plumed_massert(creference_is_calculated,"the center of the reference frame must be already provided at this stage"); - plumed_massert(cpositions_is_calculated,"the center of the positions frame must be already provided at this stage"); + + plumed_massert(creference_is_calculated,"the center of the reference frame must be already provided at this stage"); + plumed_massert(cpositions_is_calculated,"the center of the positions frame must be already provided at this stage"); // This is the trace of positions*positions + reference*reference rr00=0.; rr11=0.; // This is positions*reference Tensor rr01; -// center of mass managing: must subtract the center from the position or not? +// center of mass managing: must subtract the center from the position or not? Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; // second expensive loop: compute second moments wrt centers - for(unsigned iat=0;iatalEqDis=alEqDis; - this->safe=safe; + this->alEqDis=alEqDis; + this->safe=safe; isInitialized=true; } /// just retrieve the distance already calculated -double RMSDCoreData::getDistance( bool squared){ +double RMSDCoreData::getDistance( bool squared) { if(!isInitialized)plumed_merror("getDistance cannot calculate the distance without being initialized first by doCoreCalc "); dist=eigenvals[0]+rr00+rr11; - + if(safe || !alEqDis) dist=0.0; const unsigned n=static_cast(reference.size()); - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDPositions(){ +std::vector RMSDCoreData::getDDistanceDPositions() { std::vector derivatives; const unsigned n=static_cast(reference.size()); Vector ddist_dcpositions; @@ -972,8 +972,8 @@ std::vector RMSDCoreData::getDDistanceDPositions(){ if(!isInitialized)plumed_merror("getDPositionsDerivatives needs to initialize the coreData first!"); Vector csum; Vector tmp1,tmp2; - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDPositions(){ // derivative of cpositions ddist_dcpositions+=-tmp1; // these needed for com corrections - tmp2=matmul(ddist_drr01,reference[iat]-creference)*align[iat]; - derivatives[iat]+=tmp2; + tmp2=matmul(ddist_drr01,reference[iat]-creference)*align[iat]; + derivatives[iat]+=tmp2; csum+=tmp2; } } - if(!alEqDis) for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReference(){ +std::vector RMSDCoreData::getDDistanceDReference() { std::vector derivatives; const unsigned n=static_cast(reference.size()); Vector ddist_dcreference; @@ -1009,14 +1009,14 @@ std::vector RMSDCoreData::getDDistanceDReference(){ if(!isInitialized)plumed_merror("getDDistanceDReference to initialize the coreData first!"); // get the transpose rotation Tensor t_rotation=rotation.transpose(); - Tensor t_ddist_drr01=ddist_drr01.transpose(); - + Tensor t_ddist_drr01=ddist_drr01.transpose(); + // third expensive loop: derivatives - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReference(){ ddist_dcreference+=tmp1; // these below are needed for com correction tmp2=matmul(t_ddist_drr01,positions[iat]-cpositions)*align[iat]; - derivatives[iat]+=tmp2; - csum+=tmp2; + derivatives[iat]+=tmp2; + csum+=tmp2; } } - if(!alEqDis) for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReferenceSOMA(){ +std::vector RMSDCoreData::getDDistanceDReferenceSOMA() { std::vector derivatives; const unsigned n=static_cast(reference.size()); Vector ddist_dcreference; @@ -1051,13 +1051,13 @@ std::vector RMSDCoreData::getDDistanceDReferenceSOMA(){ if(!isInitialized)plumed_merror("getDDistanceDReference to initialize the coreData first!"); // get the transpose rotation Tensor t_rotation=rotation.transpose(); - + // third expensive loop: derivatives - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReferenceSOMA(){ } } - if(!alEqDis) for(unsigned iat=0;iat > RMSDCoreData::getDRotationDPositions( bool inverseTransform ){ +Matrix > RMSDCoreData::getDRotationDPositions( bool inverseTransform ) { const unsigned n=static_cast(reference.size()); plumed_massert(!retrieve_only_rotation,"You used only_rotation=true in doCoreCalc therefore you cannot retrieve this information now"); if(!isInitialized)plumed_merror("getDRotationDPosition to initialize the coreData first!"); - Matrix > DRotDPos=Matrix >(3,3); + Matrix > DRotDPos=Matrix >(3,3); // remember drotation_drr01 is Tensor drotation_drr01[3][3] - // (3x3 rot) (3x3 components of rr01) + // (3x3 rot) (3x3 components of rr01) std::vector v(n); Vector csum; // these below could probably be calculated in the main routine Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; - for(unsigned iat=0;iat > RMSDCoreData::getDRotationDReference( bool inverseTransform ){ +Matrix > RMSDCoreData::getDRotationDReference( bool inverseTransform ) { const unsigned n=static_cast(reference.size()); plumed_massert(!retrieve_only_rotation,"You used only_rotation=true in doCoreCalc therefore you cannot retrieve this information now"); if(!isInitialized)plumed_merror("getDRotationDPositions to initialize the coreData first!"); - Matrix > DRotDRef=Matrix >(3,3); + Matrix > DRotDRef=Matrix >(3,3); // remember drotation_drr01 is Tensor drotation_drr01[3][3] - // (3x3 rot) (3x3 components of rr01) + // (3x3 rot) (3x3 components of rr01) std::vector v(n); Vector csum; // these below could probably be calculated in the main routine Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; - for(unsigned iat=0;iat RMSDCoreData::getAlignedReferenceToPositions(){ - std::vector alignedref; - const unsigned n=static_cast(reference.size()); - alignedref.resize(n); - if(!isInitialized)plumed_merror("getAlignedReferenceToPostions needs to initialize the coreData first!"); - // avoid to calculate matrix element but use the sum of what you have - Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; - for(unsigned iat=0;iat RMSDCoreData::getAlignedReferenceToPositions() { + std::vector alignedref; + const unsigned n=static_cast(reference.size()); + alignedref.resize(n); + if(!isInitialized)plumed_merror("getAlignedReferenceToPostions needs to initialize the coreData first!"); + // avoid to calculate matrix element but use the sum of what you have + Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; + for(unsigned iat=0; iat RMSDCoreData::getAlignedPositionsToReference(){ - std::vector alignedpos; - if(!isInitialized)plumed_merror("getAlignedPostionsToReference needs to initialize the coreData first!"); - const unsigned n=static_cast(positions.size()); - alignedpos.resize(n); - Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; - // avoid to calculate matrix element but use the sum of what you have - for(unsigned iat=0;iat RMSDCoreData::getAlignedPositionsToReference() { + std::vector alignedpos; + if(!isInitialized)plumed_merror("getAlignedPostionsToReference needs to initialize the coreData first!"); + const unsigned n=static_cast(positions.size()); + alignedpos.resize(n); + Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; + // avoid to calculate matrix element but use the sum of what you have + for(unsigned iat=0; iat RMSDCoreData::getCenteredPositions(){ - std::vector centeredpos; - const unsigned n=static_cast(reference.size()); - centeredpos.resize(n); - if(!isInitialized)plumed_merror("getCenteredPositions needs to initialize the coreData first!"); - // avoid to calculate matrix element but use the sum of what you have - for(unsigned iat=0;iat RMSDCoreData::getCenteredPositions() { + std::vector centeredpos; + const unsigned n=static_cast(reference.size()); + centeredpos.resize(n); + if(!isInitialized)plumed_merror("getCenteredPositions needs to initialize the coreData first!"); + // avoid to calculate matrix element but use the sum of what you have + for(unsigned iat=0; iat RMSDCoreData::getCenteredReference(){ - std::vector centeredref; - const unsigned n=static_cast(reference.size()); - centeredref.resize(n); - if(!isInitialized)plumed_merror("getCenteredReference needs to initialize the coreData first!"); - // avoid to calculate matrix element but use the sum of what you have - Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; - for(unsigned iat=0;iat RMSDCoreData::getCenteredReference() { + std::vector centeredref; + const unsigned n=static_cast(reference.size()); + centeredref.resize(n); + if(!isInitialized)plumed_merror("getCenteredReference needs to initialize the coreData first!"); + // avoid to calculate matrix element but use the sum of what you have + Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; + for(unsigned iat=0; iat(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; template double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; template double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; template double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; diff --git a/src/tools/RMSD.h b/src/tools/RMSD.h index 8e1a8851a1..b7c80bfa4a 100644 --- a/src/tools/RMSD.h +++ b/src/tools/RMSD.h @@ -28,17 +28,17 @@ #include #include -namespace PLMD{ +namespace PLMD { class Log; class PDB; /** \ingroup TOOLBOX A class that implements RMSD calculations -This is a class that implements the various infrastructure to calculate the +This is a class that implements the various infrastructure to calculate the RMSD or MSD respect a given frame. It can be done through an optimal alignment scheme -as Kearsley or, more simply, by resetting the center of mass. -This is the class that decides this. A very simple use is +as Kearsley or, more simply, by resetting the center of mass. +This is the class that decides this. A very simple use is \verbatim #include "tools/PDB.h" #include "tools/RMSD.h" @@ -50,11 +50,11 @@ PDB pdb; pdb.read("file.pdb",true,1.0); string type; type.assign("OPTIMAL"); -// set the reference and the type +// set the reference and the type rmsd.set(pdb,type); // this calculates the rmsd and the derivatives vector derivs; -double val; +double val; val=rmsd.calculate(getPositions(),derivs,true); \endverbatim @@ -70,39 +70,39 @@ class RMSD std::vector align; // Weights for deviation std::vector displace; -// Center for reference and flag for its calculation +// Center for reference and flag for its calculation Vector reference_center; bool reference_center_is_calculated; - bool reference_center_is_removed; + bool reference_center_is_removed; // Center for running position (not used in principle but here to reflect reference/positio symmetry Vector positions_center; - bool positions_center_is_calculated; - bool positions_center_is_removed; + bool positions_center_is_calculated; + bool positions_center_is_removed; // calculates the center from the position provided - Vector calculateCenter(std::vector &p,std::vector &w){ - plumed_massert(p.size()==w.size(),"mismatch in dimension of position/align arrays while calculating the center"); - unsigned n; n=p.size(); - Vector c; c.zero(); - for(unsigned i=0;i &p,std::vector &w) { + plumed_massert(p.size()==w.size(),"mismatch in dimension of position/align arrays while calculating the center"); + unsigned n; n=p.size(); + Vector c; c.zero(); + for(unsigned i=0; i &p, Vector &c){ - unsigned n; n=p.size(); - for(unsigned i=0;i &p, Vector &c) { + unsigned n; n=p.size(); + for(unsigned i=0; i &p, Vector &c){Vector cc=c*-1.;removeCenter(p,cc);}; + void addCenter(std::vector &p, Vector &c) {Vector cc=c*-1.; removeCenter(p,cc);}; public: /// Constructor RMSD(); /// clear the structure void clear(); -/// set reference, align and displace from input pdb structure: evtl remove com from the initial structure and normalize the input weights from the pdb +/// set reference, align and displace from input pdb structure: evtl remove com from the initial structure and normalize the input weights from the pdb void set(const PDB&,const std::string & mytype, bool remove_center=true, bool normalize_weights=true); /// set align displace reference and type from input vectors - void set(const std::vector & align, const std::vector & displace, const std::vector & reference ,const std::string & mytype, bool remove_center=true , bool normalize_weights=true ); + void set(const std::vector & align, const std::vector & displace, const std::vector & reference,const std::string & mytype, bool remove_center=true, bool normalize_weights=true ); /// set the type of alignment we are doing void setType(const std::string & mytype); /// set reference coordinates, remove the com by using uniform weights @@ -111,215 +111,219 @@ class RMSD void setAlign(const std::vector & align, bool normalize_weights=true, bool remove_center=true); /// set align void setDisplace(const std::vector & displace, bool normalize_weights=true); -/// - std::string getMethod(); +/// + std::string getMethod(); /// workhorses double simpleAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & displacement, - bool squared=false)const; -template + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & displacement, + bool squared=false)const; + template double optimalAlignment(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , + const std::vector & reference, std::vector & DDistDPos, bool squared=false)const; -template -double optimalAlignment_DDistDRef(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - bool squared=false) const; + template + double optimalAlignment_DDistDRef(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + bool squared=false) const; -template -double optimalAlignment_SOMA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - bool squared=false) const; + template + double optimalAlignment_SOMA(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + bool squared=false) const; + + template + double optimalAlignment_DDistDRef_Rot_DRotDPos(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + Tensor & Rotation, + Matrix > &DRotDPos, + bool squared=false) const; -template -double optimalAlignment_DDistDRef_Rot_DRotDPos(const std::vector & align, + template + double optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + Tensor & Rotation, + Matrix > &DRotDPos, + Matrix > &DRotDRef, + bool squared=false) const; + + template + double optimalAlignment_PCA(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - Tensor & Rotation, - Matrix > &DRotDPos, - bool squared=false) const; + const std::vector & reference, + std::vector & alignedpositions, + std::vector & centeredpositions, + std::vector & centeredreference, + Tensor & Rotation, + std::vector & DDistDPos, + Matrix > & DRotDPos, + bool squared=false) const ; -template -double optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const std::vector & align, + template + double optimalAlignment_Fit(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - Tensor & Rotation, - Matrix > &DRotDPos, - Matrix > &DRotDRef, - bool squared=false) const; - -template -double optimalAlignment_PCA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - std::vector & alignedpositions, - std::vector & centeredpositions, - std::vector & centeredreference, - Tensor & Rotation, - std::vector & DDistDPos, - Matrix > & DRotDPos, - bool squared=false) const ; - -template -double optimalAlignment_Fit(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - Tensor & Rotation, - Matrix > & DRotDPos, - std::vector & centeredpositions, - Vector & center_positions, - bool squared=false); + const std::vector & reference, + Tensor & Rotation, + Matrix > & DRotDPos, + std::vector & centeredpositions, + Vector & center_positions, + bool squared=false); -/// Compute rmsd: note that this is an intermediate layer which is kept in order to evtl expand with more alignment types/user options to be called while keeping the workhorses separated +/// Compute rmsd: note that this is an intermediate layer which is kept in order to evtl expand with more alignment types/user options to be called while keeping the workhorses separated double calculate(const std::vector & positions,std::vector &derivatives, bool squared=false)const; /// Other convenience methods: -/// calculate the derivative of distance respect to position(DDistDPos) and reference (DDistDPos) - double calc_DDistDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , const bool squared=false ); +/// calculate the derivative of distance respect to position(DDistDPos) and reference (DDistDPos) + double calc_DDistDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, const bool squared=false ); /// calculate the derivative for SOMA (i.e. derivative respect to reference frame without the matrix derivative) - double calc_SOMA( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , const bool squared=false ); + double calc_SOMA( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, const bool squared=false ); /// - double calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , Tensor & Rotation,Matrix > &DRotDPos, const bool squared=false ); - double calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , Tensor & Rotation,Matrix > &DRotDPos,Matrix > &DRotDRef, const bool squared=false ); - /// convenience method to retrieve all the bits and pieces for PCA - double calc_PCAelements( const std::vector& pos, std::vector &DDistDPos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & alignedpositions, std::vector & centeredpositions, std::vector ¢eredreference, const bool& squared=false) const ; - /// convenience method to retrieve all the bits and pieces needed by FitToTemplate - double calc_FitElements( const std::vector& pos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & centeredpositions ,Vector & center_positions, const bool& squared=false ); - /// static convenience method to get the matrix i,a from drotdpos (which is a bit tricky) - static Tensor getMatrixFromDRot(Matrix< std::vector > &drotdpos, const unsigned &i, const unsigned &a){ - Tensor t; - t[0][0]=drotdpos[0][0][i][a]; t[0][1]=drotdpos[0][1][i][a]; t[0][2]=drotdpos[0][2][i][a]; - t[1][0]=drotdpos[1][0][i][a]; t[1][1]=drotdpos[1][1][i][a]; t[1][2]=drotdpos[1][2][i][a]; - t[2][0]=drotdpos[2][0][i][a]; t[2][1]=drotdpos[2][1][i][a]; t[2][2]=drotdpos[2][2][i][a]; - return t; - }; + double calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, Tensor & Rotation,Matrix > &DRotDPos, const bool squared=false ); + double calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, Tensor & Rotation,Matrix > &DRotDPos,Matrix > &DRotDRef, const bool squared=false ); +/// convenience method to retrieve all the bits and pieces for PCA + double calc_PCAelements( const std::vector& pos, std::vector &DDistDPos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & alignedpositions, std::vector & centeredpositions, std::vector ¢eredreference, const bool& squared=false) const ; +/// convenience method to retrieve all the bits and pieces needed by FitToTemplate + double calc_FitElements( const std::vector& pos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & centeredpositions,Vector & center_positions, const bool& squared=false ); +/// static convenience method to get the matrix i,a from drotdpos (which is a bit tricky) + static Tensor getMatrixFromDRot(Matrix< std::vector > &drotdpos, const unsigned &i, const unsigned &a) { + Tensor t; + t[0][0]=drotdpos[0][0][i][a]; t[0][1]=drotdpos[0][1][i][a]; t[0][2]=drotdpos[0][2][i][a]; + t[1][0]=drotdpos[1][0][i][a]; t[1][1]=drotdpos[1][1][i][a]; t[1][2]=drotdpos[1][2][i][a]; + t[2][0]=drotdpos[2][0][i][a]; t[2][1]=drotdpos[2][1][i][a]; t[2][2]=drotdpos[2][2][i][a]; + return t; + }; }; /// this is a class which is needed to share information across the various non-threadsafe routines -/// so that the public function of rmsd are threadsafe while the inner core can safely share information +/// so that the public function of rmsd are threadsafe while the inner core can safely share information class RMSDCoreData { - private: - bool alEqDis; - bool distanceIsMSD; // default is RMSD but can deliver the MSD - bool hasDistance; // distance is already calculated - bool isInitialized; - bool safe; +private: + bool alEqDis; + bool distanceIsMSD; // default is RMSD but can deliver the MSD + bool hasDistance; // distance is already calculated + bool isInitialized; + bool safe; - // this need to be copied and they are small, should not affect the performance - Vector creference; - bool creference_is_calculated; - bool creference_is_removed; - Vector cpositions; - bool cpositions_is_calculated; - bool cpositions_is_removed; - bool retrieve_only_rotation; + // this need to be copied and they are small, should not affect the performance + Vector creference; + bool creference_is_calculated; + bool creference_is_removed; + Vector cpositions; + bool cpositions_is_calculated; + bool cpositions_is_removed; + bool retrieve_only_rotation; - // use reference assignment to speed up instead of copying - const std::vector &positions; - const std::vector &reference; - const std::vector &align; - const std::vector &displace; + // use reference assignment to speed up instead of copying + const std::vector &positions; + const std::vector &reference; + const std::vector &align; + const std::vector &displace; - // the needed stuff for distance and more (one could use eigenvecs components and eigenvals for some reason) - double dist; - std::vector eigenvals; - Matrix eigenvecs; - double rr00; // sum of positions squared (needed for dist calc) - double rr11; // sum of reference squared (needed for dist calc) - Tensor rotation; // rotation derived from the eigenvector having the smallest eigenvalue - Tensor drotation_drr01[3][3]; // derivative of the rotation only available when align!=displace - Tensor ddist_drr01; - Tensor ddist_drotation; - std::vector d; // difference of components - public: - /// the constructor (note: only references are passed, therefore is rather fast) - /// note: this aligns the reference onto the positions - /// - /// this method assumes that the centers are already calculated and subtracted - RMSDCoreData(const std::vector &a ,const std::vector &d,const std::vector &p, const std::vector &r, Vector &cp, Vector &cr ): - alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), - creference(cr),creference_is_calculated(true),creference_is_removed(true), - cpositions(cp),cpositions_is_calculated(true),cpositions_is_removed(true),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0){}; + // the needed stuff for distance and more (one could use eigenvecs components and eigenvals for some reason) + double dist; + std::vector eigenvals; + Matrix eigenvecs; + double rr00; // sum of positions squared (needed for dist calc) + double rr11; // sum of reference squared (needed for dist calc) + Tensor rotation; // rotation derived from the eigenvector having the smallest eigenvalue + Tensor drotation_drr01[3][3]; // derivative of the rotation only available when align!=displace + Tensor ddist_drr01; + Tensor ddist_drotation; + std::vector d; // difference of components +public: + /// the constructor (note: only references are passed, therefore is rather fast) + /// note: this aligns the reference onto the positions + /// + /// this method assumes that the centers are already calculated and subtracted + RMSDCoreData(const std::vector &a,const std::vector &d,const std::vector &p, const std::vector &r, Vector &cp, Vector &cr ): + alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), + creference(cr),creference_is_calculated(true),creference_is_removed(true), + cpositions(cp),cpositions_is_calculated(true),cpositions_is_removed(true),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) {}; - // this constructor does not assume that the positions and reference have the center subtracted - RMSDCoreData(const std::vector &a ,const std::vector &d,const std::vector &p, const std::vector &r): - alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), - creference_is_calculated(false),creference_is_removed(false), - cpositions_is_calculated(false),cpositions_is_removed(false),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) - {cpositions.zero();creference.zero();}; + // this constructor does not assume that the positions and reference have the center subtracted + RMSDCoreData(const std::vector &a,const std::vector &d,const std::vector &p, const std::vector &r): + alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), + creference_is_calculated(false),creference_is_removed(false), + cpositions_is_calculated(false),cpositions_is_removed(false),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) + {cpositions.zero(); creference.zero();}; - // set the center on the fly without subtracting - void calcPositionsCenter(){plumed_massert(!cpositions_is_calculated,"the center was already calculated"); - cpositions.zero();for(unsigned i=0;i getDDistanceDPositions(); - // retrieve the derivative of the distance respect to the reference - std::vector getDDistanceDReference(); - // specific version for SOMA calculation (i.e. does not need derivative respect to rotation matrix) - std::vector getDDistanceDReferenceSOMA(); - // get aligned reference onto position - std::vector getAlignedReferenceToPositions(); - // get aligned position onto reference - std::vector getAlignedPositionsToReference(); - // get centered positions - std::vector getCenteredPositions(); - // get centered reference - std::vector getCenteredReference(); - // get center of positions - Vector getPositionsCenter(); - // get center of reference - Vector getReferenceCenter(); - // get rotation matrix (reference ->positions) - Tensor getRotationMatrixReferenceToPositions(); - // get rotation matrix (positions -> reference) - Tensor getRotationMatrixPositionsToReference(); - // get the derivative of the rotation matrix respect to positions - // note that the this transformation overlap the reference onto position - // if inverseTransform=true then aligns the positions onto reference - Matrix > getDRotationDPositions( bool inverseTransform=false ); - // get the derivative of the rotation matrix respect to reference - // note that the this transformation overlap the reference onto position - // if inverseTransform=true then aligns the positions onto reference - Matrix > getDRotationDReference(bool inverseTransform=false ); + // set the center on the fly without subtracting + void calcPositionsCenter() { + plumed_massert(!cpositions_is_calculated,"the center was already calculated"); + cpositions.zero(); for(unsigned i=0; i getDDistanceDPositions(); + // retrieve the derivative of the distance respect to the reference + std::vector getDDistanceDReference(); + // specific version for SOMA calculation (i.e. does not need derivative respect to rotation matrix) + std::vector getDDistanceDReferenceSOMA(); + // get aligned reference onto position + std::vector getAlignedReferenceToPositions(); + // get aligned position onto reference + std::vector getAlignedPositionsToReference(); + // get centered positions + std::vector getCenteredPositions(); + // get centered reference + std::vector getCenteredReference(); + // get center of positions + Vector getPositionsCenter(); + // get center of reference + Vector getReferenceCenter(); + // get rotation matrix (reference ->positions) + Tensor getRotationMatrixReferenceToPositions(); + // get rotation matrix (positions -> reference) + Tensor getRotationMatrixPositionsToReference(); + // get the derivative of the rotation matrix respect to positions + // note that the this transformation overlap the reference onto position + // if inverseTransform=true then aligns the positions onto reference + Matrix > getDRotationDPositions( bool inverseTransform=false ); + // get the derivative of the rotation matrix respect to reference + // note that the this transformation overlap the reference onto position + // if inverseTransform=true then aligns the positions onto reference + Matrix > getDRotationDReference(bool inverseTransform=false ); }; } diff --git a/src/tools/Random.cpp b/src/tools/Random.cpp index 8d5cac5d28..7d03b9da3d 100644 --- a/src/tools/Random.cpp +++ b/src/tools/Random.cpp @@ -25,7 +25,7 @@ #include #include -namespace PLMD{ +namespace PLMD { const double Random::fact=5.9604644775390625e-8; /* 1 / 2^24 */ const double Random::EPS=3.0e-16; @@ -43,92 +43,92 @@ Random::Random(const std::string & name): // static constructors. name(&name!=&noname?name:"noname") { - iy=0; - iv[0]=0; - setSeed(0); + iy=0; + iv[0]=0; + setSeed(0); } -void Random::setSeed(int idum_){ - idum=idum_; - incPrec=false; +void Random::setSeed(int idum_) { + idum=idum_; + incPrec=false; } double Random::RandU01 () { - if (incPrec) - return U01d(); - else - return U01(); + if (incPrec) + return U01d(); + else + return U01(); } double Random::U01d () { - double u; - u = U01(); - u += U01() * fact; - return (u < 1.0) ? u : (u - 1.0); + double u; + u = U01(); + u += U01() * fact; + return (u < 1.0) ? u : (u - 1.0); } -double Random::U01(){ - int j,k; - double temp; - if (idum <= 0 || !iy) { - if (-idum < 1) idum=1; - else idum = -idum; - for (j=NTAB+7;j>=0;j--) { - k=idum/IQ; - idum=IA*(idum-k*IQ)-IR*k; - if (idum < 0) idum += IM; - if (j < NTAB) iv[j] = idum; - } - iy=iv[0]; - } - k=idum/IQ; - idum=IA*(idum-k*IQ)-IR*k; - if (idum < 0) idum += IM; - j=iy/NDIV; - iy=iv[j]; - iv[j] = idum; - if ((temp=AM*iy) > RNMX) return RNMX; - else return temp; +double Random::U01() { + int j,k; + double temp; + if (idum <= 0 || !iy) { + if (-idum < 1) idum=1; + else idum = -idum; + for (j=NTAB+7; j>=0; j--) { + k=idum/IQ; + idum=IA*(idum-k*IQ)-IR*k; + if (idum < 0) idum += IM; + if (j < NTAB) iv[j] = idum; + } + iy=iv[0]; + } + k=idum/IQ; + idum=IA*(idum-k*IQ)-IR*k; + if (idum < 0) idum += IM; + j=iy/NDIV; + iy=iv[j]; + iv[j] = idum; + if ((temp=AM*iy) > RNMX) return RNMX; + else return temp; } -void Random::WriteStateFull(std::ostream & out)const{ - out<>idum>>iy; - for (int i = 0; i < NTAB; i++) in>>iv[i]; - in>>switchGaussian; - in>>saveGaussian; +void Random::ReadStateFull (std::istream & in) { + getline(in,name); + in>>idum>>iy; + for (int i = 0; i < NTAB; i++) in>>iv[i]; + in>>switchGaussian; + in>>saveGaussian; } -void Random::toString(std::string & str)const{ - std::ostringstream ostr; - ostr<>idum>>iy; - for (int i = 0; i < NTAB; i++) istr>>iv[i]; +void Random::fromString(const std::string & str) { + std::string s=str; + for(unsigned i=0; i>idum>>iy; + for (int i = 0; i < NTAB; i++) istr>>iv[i]; } // This allows to have the same stream of random numbers @@ -137,22 +137,22 @@ void Random::fromString(const std::string & str){ #pragma intel optimization_level 0 #endif -double Random::Gaussian(){ - double v1,v2,rsq; - if(switchGaussian){ - switchGaussian=false; - return saveGaussian; - } - while(true){ - v1=2.0*RandU01()-1.0; - v2=2.0*RandU01()-1.0; - rsq=v1*v1+v2*v2; - if(rsq<1.0 && rsq>0.0) break; - } - double fac=sqrt(-2.*std::log(rsq)/rsq); - saveGaussian=v1*fac; - switchGaussian=true; - return v2*fac; +double Random::Gaussian() { + double v1,v2,rsq; + if(switchGaussian) { + switchGaussian=false; + return saveGaussian; + } + while(true) { + v1=2.0*RandU01()-1.0; + v2=2.0*RandU01()-1.0; + rsq=v1*v1+v2*v2; + if(rsq<1.0 && rsq>0.0) break; + } + double fac=sqrt(-2.*std::log(rsq)/rsq); + saveGaussian=v1*fac; + switchGaussian=true; + return v2*fac; } } diff --git a/src/tools/Random.h b/src/tools/Random.h index 043b3bfe94..49e7a3b442 100644 --- a/src/tools/Random.h +++ b/src/tools/Random.h @@ -25,42 +25,42 @@ #include #include -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX -class Random{ - static const int IA=16807,IM=2147483647,IQ=127773,IR=2836,NTAB=32; - static const int NDIV=(1+(IM-1)/NTAB); - static const double EPS; - static const double AM; - static const double RNMX; - static const double fact; - static const std::string noname; - bool incPrec; - bool switchGaussian; - double saveGaussian; - int iy; - int iv[NTAB]; - int idum; - std::string name; +class Random { + static const int IA=16807,IM=2147483647,IQ=127773,IR=2836,NTAB=32; + static const int NDIV=(1+(IM-1)/NTAB); + static const double EPS; + static const double AM; + static const double RNMX; + static const double fact; + static const std::string noname; + bool incPrec; + bool switchGaussian; + double saveGaussian; + int iy; + int iv[NTAB]; + int idum; + std::string name; public: - explicit Random(const std::string & name=noname); - void setSeed(int idum); - double RandU01(); - double U01(); - double U01d(); - void WriteStateFull(std::ostream &)const; - void ReadStateFull (std::istream &); - void fromString(const std::string & str); - void toString(std::string & str)const; - friend std::ostream & operator<<(std::ostream & out,const Random & rng){ - rng.WriteStateFull(out); return out; - } - friend std::istream & operator>>(std::istream & in,Random & rng){ - rng.ReadStateFull(in); return in; - } - double Gaussian(); - void IncreasedPrecis(bool i){incPrec=i;} + explicit Random(const std::string & name=noname); + void setSeed(int idum); + double RandU01(); + double U01(); + double U01d(); + void WriteStateFull(std::ostream &)const; + void ReadStateFull (std::istream &); + void fromString(const std::string & str); + void toString(std::string & str)const; + friend std::ostream & operator<<(std::ostream & out,const Random & rng) { + rng.WriteStateFull(out); return out; + } + friend std::istream & operator>>(std::istream & in,Random & rng) { + rng.ReadStateFull(in); return in; + } + double Gaussian(); + void IncreasedPrecis(bool i) {incPrec=i;} }; } diff --git a/src/tools/RootFindingBase.h b/src/tools/RootFindingBase.h index 5f125a7c1e..b737455605 100644 --- a/src/tools/RootFindingBase.h +++ b/src/tools/RootFindingBase.h @@ -54,20 +54,20 @@ void RootFindingBase::doSearch( const std::vector& dir, std::vec double ax=0.0, xx=1.0; bb.bracket( ax, xx, &F1dim::getEng ); double xmin=bb.search( &F1dim::getEng ); - for(unsigned i=0;i void RootFindingBase::linesearch( const std::vector& dir, std::vector& p, engf_pointer myfunc ) const { - // Construct the object that turns points on a line into vectors + // Construct the object that turns points on a line into vectors F1dim f1dim( p, dir, myclass_func, myfunc, NULL ); // Actually do the search - doSearch( dir, p, f1dim ); + doSearch( dir, p, f1dim ); } template void RootFindingBase::lsearch( const std::vector& dir, std::vector& p, engfnc_pointer myfunc ) const { - // Construct the object that turns points on a line into vectors + // Construct the object that turns points on a line into vectors F1dim f1dim( p, dir, myclass_func, NULL, myfunc ); // Actually do the search doSearch( dir, p, f1dim ); diff --git a/src/tools/Stopwatch.cpp b/src/tools/Stopwatch.cpp index c0d93e0e11..4393a75449 100644 --- a/src/tools/Stopwatch.cpp +++ b/src/tools/Stopwatch.cpp @@ -30,52 +30,52 @@ using namespace std; -namespace PLMD{ +namespace PLMD { // this is needed for friend operators -std::ostream& operator<<(std::ostream&os,const Stopwatch&sw){ +std::ostream& operator<<(std::ostream&os,const Stopwatch&sw) { return sw.log(os); } -void Stopwatch::Watch::start(){ +void Stopwatch::Watch::start() { running++; lastStart=std::chrono::high_resolution_clock::now(); } -void Stopwatch::Watch::stop(){ +void Stopwatch::Watch::stop() { pause(); cycles++; total+=lap; if(lap>max)max=lap; if(min>lap || cycles==1)min=lap; lap=0; -} +} -void Stopwatch::Watch::pause(){ +void Stopwatch::Watch::pause() { plumed_assert(running>0); running--; if(running!=0) return; auto t=std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-lastStart); lap+=t.count(); -} +} -void Stopwatch::start(const std::string & name){ +void Stopwatch::start(const std::string & name) { watches[name].start(); } -void Stopwatch::stop(const std::string & name){ +void Stopwatch::stop(const std::string & name) { watches[name].stop(); } -void Stopwatch::pause(const std::string & name){ +void Stopwatch::pause(const std::string & name) { watches[name].pause(); } -std::ostream& Stopwatch::log(std::ostream&os)const{ +std::ostream& Stopwatch::log(std::ostream&os)const { char buffer[1000]; buffer[0]=0; - for(unsigned i=0;i<40;i++) os<<" "; + for(unsigned i=0; i<40; i++) os<<" "; os<<" Cycles Total Average Minumum Maximum\n"; std::vector names; @@ -84,10 +84,10 @@ std::ostream& Stopwatch::log(std::ostream&os)const{ const double frac=1.0/1000000000.0; - for(const auto & name : names){ + for(const auto & name : names) { const Watch&t(watches.find(name)->second); os< #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -96,10 +96,10 @@ int main(){ */ -class Stopwatch{ +class Stopwatch { /// Class to store a single stopwatch. /// Class Stopwatch contains a collection of them - class Watch{ + class Watch { public: std::chrono::time_point lastStart; long long int total = 0; @@ -129,17 +129,17 @@ class Stopwatch{ }; inline -void Stopwatch::start(){ +void Stopwatch::start() { start(""); } inline -void Stopwatch::stop(){ +void Stopwatch::stop() { stop(""); } inline -void Stopwatch::pause(){ +void Stopwatch::pause() { pause(""); } diff --git a/src/tools/SwitchingFunction.cpp b/src/tools/SwitchingFunction.cpp index fa685d1b0f..fcbe3bb37f 100644 --- a/src/tools/SwitchingFunction.cpp +++ b/src/tools/SwitchingFunction.cpp @@ -30,9 +30,9 @@ #endif using namespace std; -namespace PLMD{ +namespace PLMD { -//+PLUMEDOC INTERNAL switchingfunction +//+PLUMEDOC INTERNAL switchingfunction /* Functions that measure whether values are less than a certain quantity. @@ -40,24 +40,24 @@ Switching functions \f$s(r)\f$ take a minimum of one input parameter \f$d_0\f$. For \f$r \le d_0 \quad s(r)=1.0\f$ while for \f$r > d_0\f$ the function decays smoothly to 0. The various switching functions available in plumed differ in terms of how this decay is performed. -Where there is an accepted convention in the literature (e.g. \ref COORDINATION) on the form of the +Where there is an accepted convention in the literature (e.g. \ref COORDINATION) on the form of the switching function we use the convention as the default. However, the flexibility to use different -switching functions is always present generally through a single keyword. This keyword generally +switching functions is always present generally through a single keyword. This keyword generally takes an input with the following form: \verbatim KEYWORD={TYPE } -\endverbatim +\endverbatim The following table contains a list of the various switching functions that are available in plumed 2 together with an example input. - + @@ -76,9 +76,9 @@ s(r)=\exp\left(-\frac{ r - d_0 }{ r_0 }\right) s(r)=\exp\left(-\frac{ (r - d_0)^2 }{ 2r_0^2 }\right) \f$ - + - + - + - + - +
TYPE FUNCTION EXAMPLE INPUT DEFAULT PARAMETERS
RATIONAL \f$ -s(r)=\frac{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{n} }{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{m} } +s(r)=\frac{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{n} }{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{m} } \f$ {RATIONAL R_0=\f$r_0\f$ D_0=\f$d_0\f$ NN=\f$n\f$ MM=\f$m\f$} @@ -67,7 +67,7 @@ s(r)=\frac{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{n} }{ 1 - \left(\frac{ r - \f$ s(r)=\exp\left(-\frac{ r - d_0 }{ r_0 }\right) \f$ - + {EXP R_0=\f$r_0\f$ D_0=\f$d_0\f$} \f$d_0=0.0\f$
-{GAUSSIAN R_0=\f$r_0\f$ D_0=\f$d_0\f$} +{GAUSSIAN R_0=\f$r_0\f$ D_0=\f$d_0\f$} \f$d_0=0.0\f$
SMAP \f$ s(r) = \left[ 1 + ( 2^{a/b} -1 )\left( \frac{r-d_0}{r_0} \right)^a \right]^{-b/a} @@ -86,7 +86,7 @@ s(r) = \left[ 1 + ( 2^{a/b} -1 )\left( \frac{r-d_0}{r_0} \right)^a \right]^{-b/a {SMAP R_0=\f$r_0\f$ D_0=\f$d_0\f$ A=\f$a\f$ B=\f$b\f$} \f$d_0=0.0\f$
Q \f$ s(r) = \frac{1}{1 + \exp(\beta(r_{ij} - \lambda r_{ij}^0))} @@ -94,7 +94,7 @@ s(r) = \frac{1}{1 + \exp(\beta(r_{ij} - \lambda r_{ij}^0))} {Q REF=\f$r_{ij}^0\f$ BETA=\f$\beta\f$ LAMBDA=\f$\lambda\f$ } \f$\lambda=1.8\f$, \f$\beta=50 nm^-1\f$ (all-atom)
\f$\lambda=1.5\f$, \f$\beta=50 nm^-1\f$ (coarse-grained)
CUBIC \f$ s(r) = (y-1)^2(1+2y) \qquad \textrm{where} \quad y = \frac{r - r_1}{r_0-r_1} @@ -102,15 +102,15 @@ s(r) = (y-1)^2(1+2y) \qquad \textrm{where} \quad y = \frac{r - r_1}{r_0-r_1} {CUBIC D_0=\f$r_1\f$ D_MAX=\f$r_0\f$}
TANH \f$ -s(r) = 1 - \tanh\left( \frac{ r - d_0 }{ r_0 } \right) +s(r) = 1 - \tanh\left( \frac{ r - d_0 }{ r_0 } \right) \f$ {TANH R_0=\f$r_0\f$ D_0=\f$d_0\f$}
MATHEVAL \f$ s(r) = FUNC @@ -122,7 +122,7 @@ s(r) = FUNC
\attention -Similarly to the \ref MATHEVAL function, the MATHEVAL switching function +Similarly to the \ref MATHEVAL function, the MATHEVAL switching function only works if libmatheval is installed on the system and PLUMED has been linked to it Also notice that using MATHEVAL is much slower than using e.g. RATIONAL. @@ -131,7 +131,7 @@ tests on switching functions with arbitrary form before proceeding to their implementation in C++. For all the switching functions in the above table one can also specify a further (optional) parameter using the parameter -keyword D_MAX to assert that for \f$r>d_{\textrm{max}}\f$ the switching function can be assumed equal to zero. +keyword D_MAX to assert that for \f$r>d_{\textrm{max}}\f$ the switching function can be assumed equal to zero. In this case the function is brought smoothly to zero by stretching and shifting it. \verbatim KEYWORD={RATIONAL R_0=1 D_MAX=3} @@ -154,19 +154,19 @@ for backward compatibility. This might change in the future. */ //+ENDPLUMEDOC -void SwitchingFunction::registerKeywords( Keywords& keys ){ +void SwitchingFunction::registerKeywords( Keywords& keys ) { keys.add("compulsory","R_0","the value of R_0 in the switching function"); keys.add("compulsory","D_0","0.0","the value of D_0 in the switching function"); keys.add("optional","D_MAX","the value at which the switching function can be assumed equal to zero"); keys.add("compulsory","NN","6","the value of n in the switching function (only needed for TYPE=RATIONAL)"); keys.add("compulsory","MM","0","the value of m in the switching function (only needed for TYPE=RATIONAL); 0 implies 2*NN"); keys.add("compulsory","A","the value of a in the switching funciton (only needed for TYPE=SMAP)"); - keys.add("compulsory","B","the value of b in the switching funciton (only needed for TYPE=SMAP)"); + keys.add("compulsory","B","the value of b in the switching funciton (only needed for TYPE=SMAP)"); } -void SwitchingFunction::set(const std::string & definition,std::string& errormsg){ +void SwitchingFunction::set(const std::string & definition,std::string& errormsg) { vector data=Tools::getWords(definition); - if( data.size()<1 ) errormsg="missing all input for switching function"; + if( data.size()<1 ) errormsg="missing all input for switching function"; string name=data[0]; data.erase(data.begin()); invr0=0.0; @@ -193,16 +193,16 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg Tools::parseFlag(data,"NOSTRETCH",dontstretch); // this is ignored now if(dontstretch) dostretch=false; double r0; - if(name=="CUBIC"){ - r0 = dmax - d0; + if(name=="CUBIC") { + r0 = dmax - d0; } else { - bool found_r0=Tools::parse(data,"R_0",r0); - if(!found_r0) errormsg="R_0 is required"; + bool found_r0=Tools::parse(data,"R_0",r0); + if(!found_r0) errormsg="R_0 is required"; } invr0=1.0/r0; invr0_2=invr0*invr0; - if(name=="RATIONAL"){ + if(name=="RATIONAL") { type=rational; nn=6; mm=0; @@ -211,17 +211,17 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg present=Tools::findKeyword(data,"MM"); if(present && !Tools::parse(data,"MM",mm)) errormsg="could not parse MM"; if(mm==0) mm=2*nn; - } else if(name=="SMAP"){ + } else if(name=="SMAP") { type=smap; present=Tools::findKeyword(data,"A"); if(present && !Tools::parse(data,"A",a)) errormsg="could not parse A"; present=Tools::findKeyword(data,"B"); if(present && !Tools::parse(data,"B",b)) errormsg="could not parse B"; - c=pow(2., static_cast(a)/static_cast(b) ) - 1; + c=pow(2., static_cast(a)/static_cast(b) ) - 1; d = -static_cast(b) / static_cast(a); - } + } else if(name=="Q") { - type=nativeq; + type=nativeq; beta = 50.0; // nm-1 lambda = 1.8; // unitless present=Tools::findKeyword(data,"BETA"); @@ -237,7 +237,7 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg else if(name=="CUBIC") type=cubic; else if(name=="TANH") type=tanh; #ifdef __PLUMED_HAS_MATHEVAL - else if(name=="MATHEVAL"){ + else if(name=="MATHEVAL") { type=matheval; std::string func; Tools::parse(data,"FUNC",func); @@ -245,11 +245,11 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg char **check_names; int check_count; evaluator_get_variables(evaluator,&check_names,&check_count); - if(check_count!=1){ + if(check_count!=1) { errormsg="wrong number of arguments in MATHEVAL switching function"; return; - } - if(std::string(check_names[0])!="x"){ + } + if(std::string(check_names[0])!="x") { errormsg ="argument should be named 'x'"; return; } @@ -257,12 +257,12 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg } #endif else errormsg="cannot understand switching function type '"+name+"'"; - if( !data.empty() ){ - errormsg="found the following rogue keywords in switching function input : "; - for(unsigned i=0;i::max()){ + if(dostretch && dmax!=std::numeric_limits::max()) { double dummy; double s0=calculate(0.0,dummy); double sd=calculate(dmax,dummy); @@ -274,73 +274,73 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg std::string SwitchingFunction::description() const { std::ostringstream ostr; ostr<<1./invr0<<". Using "; - if(type==rational){ - ostr<<"rational"; - } else if(type==exponential){ - ostr<<"exponential"; - } else if(type==nativeq){ - ostr<<"nativeq"; - } else if(type==gaussian){ - ostr<<"gaussian"; - } else if(type==smap){ - ostr<<"smap"; - } else if(type==cubic){ - ostr<<"cubic"; - } else if(type==tanh){ - ostr<<"tanh"; + if(type==rational) { + ostr<<"rational"; + } else if(type==exponential) { + ostr<<"exponential"; + } else if(type==nativeq) { + ostr<<"nativeq"; + } else if(type==gaussian) { + ostr<<"gaussian"; + } else if(type==smap) { + ostr<<"smap"; + } else if(type==cubic) { + ostr<<"cubic"; + } else if(type==tanh) { + ostr<<"tanh"; #ifdef __PLUMED_HAS_MATHEVAL - } else if(type==matheval){ - ostr<<"matheval"; + } else if(type==matheval) { + ostr<<"matheval"; #endif - } else{ - plumed_merror("Unknown switching function type"); + } else { + plumed_merror("Unknown switching function type"); } ostr<<" swiching function with parameters d0="<dmax){ + if(distance>dmax) { dfunc=0.0; return 0.0; } const double rdist = (distance-d0)*invr0; double result; - if(rdist<=0.){ - result=1.; - dfunc=0.0; - }else{ - if(type==smap){ - double sx=c*pow( rdist, a ); - result=pow( 1.0 + sx, d ); - dfunc=-b*sx/rdist*result/(1.0+sx); - } else if(type==rational){ + if(rdist<=0.) { + result=1.; + dfunc=0.0; + } else { + if(type==smap) { + double sx=c*pow( rdist, a ); + result=pow( 1.0 + sx, d ); + dfunc=-b*sx/rdist*result/(1.0+sx); + } else if(type==rational) { result=do_rational(rdist,dfunc,nn,mm); - }else if(type==exponential){ + } else if(type==exponential) { result=exp(-rdist); dfunc=-result; - }else if(type==nativeq){ + } else if(type==nativeq) { double rdist2 = beta*(distance - lambda * ref); double exprdist=exp(rdist2); result=1./(1.+exprdist); dfunc=-exprdist/(1.+exprdist)/(1.+exprdist); - }else if(type==gaussian){ + } else if(type==gaussian) { result=exp(-0.5*rdist*rdist); dfunc=-rdist*result; - }else if(type==cubic){ + } else if(type==cubic) { double tmp1=rdist-1, tmp2=(1+2*rdist); result=tmp1*tmp1*tmp2; dfunc=2*tmp1*tmp2 + 2*tmp1*tmp1; - }else if(type==tanh){ + } else if(type==tanh) { double tmp1=std::tanh(rdist); result = 1.0 - tmp1; dfunc=-(1-tmp1*tmp1); #ifdef __PLUMED_HAS_MATHEVAL - }else if(type==matheval){ + } else if(type==matheval) { result=evaluator_evaluate_x(evaluator,rdist); dfunc=evaluator_evaluate_x(evaluator_deriv,rdist); #endif - }else plumed_merror("Unknown switching function type"); + } else plumed_merror("Unknown switching function type"); // this is for the chain rule: dfunc*=invr0; // this is because calculate() sets dfunc to the derivative divided times the distance. @@ -467,7 +467,7 @@ SwitchingFunction::SwitchingFunction(const SwitchingFunction&sf): #endif } -SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf){ +SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf) { if(&sf==this) return *this; init=sf.init; type=sf.type; @@ -497,7 +497,7 @@ SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf){ } -void SwitchingFunction::set(int nn,int mm,double r0,double d0){ +void SwitchingFunction::set(int nn,int mm,double r0,double d0) { init=true; type=rational; if(mm==0) mm=2*nn; @@ -526,7 +526,7 @@ double SwitchingFunction::get_dmax2() const { return dmax_2; } -SwitchingFunction::~SwitchingFunction(){ +SwitchingFunction::~SwitchingFunction() { #ifdef __PLUMED_HAS_MATHEVAL if(evaluator) evaluator_destroy(evaluator); if(evaluator_deriv) evaluator_destroy(evaluator_deriv); diff --git a/src/tools/SwitchingFunction.h b/src/tools/SwitchingFunction.h index 4bcf27926a..379280da4a 100644 --- a/src/tools/SwitchingFunction.h +++ b/src/tools/SwitchingFunction.h @@ -37,7 +37,7 @@ class Keywords; /// the second all (calculateSqr()) allows to skip the calculation /// of a square root in some case, thus potentially increasing /// performances. -class SwitchingFunction{ +class SwitchingFunction { /// This is to check that switching function has been initialized bool init; /// Type of function @@ -81,7 +81,7 @@ class SwitchingFunction{ SwitchingFunction & operator=(const SwitchingFunction&); /// Set a "rational" switching function. /// Notice that a d_max is set automatically to a value such that -/// f(d_max)=0.00001. +/// f(d_max)=0.00001. void set(int nn,int mm,double r_0,double d_0); /// Set an arbitrary switching function. /// Parse the string in definition and possibly returns errors @@ -104,7 +104,7 @@ class SwitchingFunction{ double get_d0() const; /// Returns r0 double get_r0() const; -/// Return dmax +/// Return dmax double get_dmax() const; /// Return dmax squared double get_dmax2() const; diff --git a/src/tools/Tensor.cpp b/src/tools/Tensor.cpp index ad8f2ae6d4..d063e28cf9 100644 --- a/src/tools/Tensor.cpp +++ b/src/tools/Tensor.cpp @@ -22,15 +22,15 @@ #include "Tensor.h" #include "Exception.h" -namespace PLMD{ +namespace PLMD { /// Small auxiliary class. /// I use it to test a few things that I am scary of and could introduce bugs. /// It checks at startup that Tensor satifies some requirement so as to allow /// accessing a vector of tensors as a 9 times longer array of doubles. -static class TensorChecks{ +static class TensorChecks { public: - TensorChecks(){ + TensorChecks() { if(sizeof(Tensor)==9*sizeof(double)) return; plumed_merror("sizeof(Tensor)!=9*sizeof(double). PLUMED cannot work properly in these conditions."); } diff --git a/src/tools/Tensor.h b/src/tools/Tensor.h index 8e95e21b93..7cd6515c86 100644 --- a/src/tools/Tensor.h +++ b/src/tools/Tensor.h @@ -30,7 +30,7 @@ #include "Exception.h" #endif -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -182,18 +182,18 @@ class TensorGeneric: }; template -TensorGeneric::TensorGeneric(){ +TensorGeneric::TensorGeneric() { LoopUnroller::_zero(d); } template -TensorGeneric::TensorGeneric(const VectorGeneric&v1,const VectorGeneric&v2){ - for(unsigned i=0;i::TensorGeneric(const VectorGeneric&v1,const VectorGeneric&v2) { + for(unsigned i=0; i inline -TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11){ +TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11) { d[0]=d00; d[1]=d01; d[2]=d10; @@ -202,7 +202,7 @@ TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11){ template<> inline -TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,double d11,double d12,double d20,double d21,double d22){ +TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,double d11,double d12,double d20,double d21,double d22) { d[0]=d00; d[1]=d01; d[2]=d02; @@ -215,12 +215,12 @@ TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,do } template -void TensorGeneric::zero(){ +void TensorGeneric::zero() { LoopUnroller::_zero(d); } template -double & TensorGeneric::operator() (unsigned i,unsigned j){ +double & TensorGeneric::operator() (unsigned i,unsigned j) { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator() (unsigned i,unsigned j){ } template -const double & TensorGeneric::operator() (unsigned i,unsigned j)const{ +const double & TensorGeneric::operator() (unsigned i,unsigned j)const { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator() (unsigned i,unsigned j)const{ } template -TensorGeneric& TensorGeneric::operator +=(const TensorGeneric& b){ +TensorGeneric& TensorGeneric::operator +=(const TensorGeneric& b) { LoopUnroller::_add(d,b.d); return *this; } template -TensorGeneric& TensorGeneric::operator -=(const TensorGeneric& b){ +TensorGeneric& TensorGeneric::operator -=(const TensorGeneric& b) { LoopUnroller::_sub(d,b.d); return *this; } template -TensorGeneric& TensorGeneric::operator *=(double s){ +TensorGeneric& TensorGeneric::operator *=(double s) { LoopUnroller::_mul(d,s); return *this; } template -TensorGeneric& TensorGeneric::operator /=(double s){ +TensorGeneric& TensorGeneric::operator /=(double s) { LoopUnroller::_mul(d,1.0/s); return *this; } template -TensorGeneric TensorGeneric::operator+()const{ +TensorGeneric TensorGeneric::operator+()const { return *this; } template -TensorGeneric TensorGeneric::operator-()const{ +TensorGeneric TensorGeneric::operator-()const { TensorGeneric r; LoopUnroller::_neg(r.d,d); return r; } template -TensorGeneric& TensorGeneric::setCol(unsigned j,const VectorGeneric & c){ - for(unsigned i=0;i& TensorGeneric::setCol(unsigned j,const VectorGeneric & c) { + for(unsigned i=0; i -TensorGeneric& TensorGeneric::setRow(unsigned i,const VectorGeneric & r){ - for(unsigned j=0;j& TensorGeneric::setRow(unsigned i,const VectorGeneric & r) { + for(unsigned j=0; j -VectorGeneric TensorGeneric::getCol(unsigned j)const{ +VectorGeneric TensorGeneric::getCol(unsigned j)const { VectorGeneric v; - for(unsigned i=0;i -VectorGeneric TensorGeneric::getRow(unsigned i)const{ +VectorGeneric TensorGeneric::getRow(unsigned i)const { VectorGeneric v; - for(unsigned j=0;j -TensorGeneric operator+(const TensorGeneric&t1,const TensorGeneric&t2){ +TensorGeneric operator+(const TensorGeneric&t1,const TensorGeneric&t2) { TensorGeneric t(t1); t+=t2; return t; } template -TensorGeneric operator-(const TensorGeneric&t1,const TensorGeneric&t2){ +TensorGeneric operator-(const TensorGeneric&t1,const TensorGeneric&t2) { TensorGeneric t(t1); t-=t2; return t; } template -TensorGeneric operator*(const TensorGeneric&t1,double s){ +TensorGeneric operator*(const TensorGeneric&t1,double s) { TensorGeneric t(t1); t*=s; return t; } template -TensorGeneric operator*(double s,const TensorGeneric&t1){ +TensorGeneric operator*(double s,const TensorGeneric&t1) { return t1*s; } template -TensorGeneric operator/(const TensorGeneric&t1,double s){ +TensorGeneric operator/(const TensorGeneric&t1,double s) { return t1*(1.0/s); } template<> inline -double TensorGeneric<3,3>::determinant()const{ +double TensorGeneric<3,3>::determinant()const { return - d[0]*d[4]*d[8] - + d[1]*d[5]*d[6] - + d[2]*d[3]*d[7] - - d[0]*d[5]*d[7] - - d[1]*d[3]*d[8] - - d[2]*d[4]*d[6]; + d[0]*d[4]*d[8] + + d[1]*d[5]*d[6] + + d[2]*d[3]*d[7] + - d[0]*d[5]*d[7] + - d[1]*d[3]*d[8] + - d[2]*d[4]*d[6]; } template inline -TensorGeneric TensorGeneric::identity(){ +TensorGeneric TensorGeneric::identity() { TensorGeneric t; - for(unsigned i=0;i -TensorGeneric TensorGeneric::transpose()const{ +TensorGeneric TensorGeneric::transpose()const { TensorGeneric t; - for(unsigned i=0;i inline -TensorGeneric<3,3> TensorGeneric<3,3>::inverse()const{ +TensorGeneric<3,3> TensorGeneric<3,3>::inverse()const { TensorGeneric t; double invdet=1.0/determinant(); - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) - t(j,i)=invdet*( (*this)((i+1)%3,(j+1)%3)*(*this)((i+2)%3,(j+2)%3) - -(*this)((i+1)%3,(j+2)%3)*(*this)((i+2)%3,(j+1)%3)); + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) + t(j,i)=invdet*( (*this)((i+1)%3,(j+1)%3)*(*this)((i+2)%3,(j+2)%3) + -(*this)((i+1)%3,(j+2)%3)*(*this)((i+2)%3,(j+1)%3)); return t; } template -TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b){ +TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b) { TensorGeneric t; - for(unsigned i=0;i -VectorGeneric matmul(const TensorGeneric&a,const VectorGeneric&b){ +VectorGeneric matmul(const TensorGeneric&a,const VectorGeneric&b) { VectorGeneric t; - for(unsigned i=0;i -VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b){ +VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b) { VectorGeneric t; - for(unsigned i=0;i -double matmul(const VectorGeneric&a,const VectorGeneric&b){ +double matmul(const VectorGeneric&a,const VectorGeneric&b) { return dotProduct(a,b); } template -TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const TensorGeneric&c){ +TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const TensorGeneric&c) { return matmul(matmul(a,b),c); } template -VectorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const VectorGeneric&c){ +VectorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const VectorGeneric&c) { return matmul(matmul(a,b),c); } -template -VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b,const TensorGeneric&c){ +template +VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b,const TensorGeneric&c) { return matmul(matmul(a,b),c); } template -double matmul(const VectorGeneric&a,const TensorGeneric&b,const VectorGeneric&c){ +double matmul(const VectorGeneric&a,const TensorGeneric&b,const VectorGeneric&c) { return matmul(matmul(a,b),c); } inline -double determinant(const TensorGeneric<3,3>&t){ +double determinant(const TensorGeneric<3,3>&t) { return t.determinant(); } inline -TensorGeneric<3,3> inverse(const TensorGeneric<3,3>&t){ +TensorGeneric<3,3> inverse(const TensorGeneric<3,3>&t) { return t.inverse(); } template -TensorGeneric transpose(const TensorGeneric&t){ +TensorGeneric transpose(const TensorGeneric&t) { return t.transpose(); } template -TensorGeneric extProduct(const VectorGeneric&v1,const VectorGeneric&v2){ +TensorGeneric extProduct(const VectorGeneric&v1,const VectorGeneric&v2) { return TensorGeneric(v1,v2); } inline -TensorGeneric<3,3> dcrossDv1(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2){ +TensorGeneric<3,3> dcrossDv1(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2) { (void) v1; // this is to avoid warnings. still the syntax of this function is a bit dummy... return TensorGeneric<3,3>( - 0.0, v2[2],-v2[1], - -v2[2], 0.0, v2[0], - v2[1],-v2[0], 0.0); + 0.0, v2[2],-v2[1], + -v2[2], 0.0, v2[0], + v2[1],-v2[0], 0.0); } inline -TensorGeneric<3,3> dcrossDv2(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2){ +TensorGeneric<3,3> dcrossDv2(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2) { (void) v2; // this is to avoid warnings. still the syntax of this function is a bit dummy... return TensorGeneric<3,3>( - 0.0,-v1[2],v1[1], - v1[2],0.0,-v1[0], - -v1[1],v1[0],0.0); + 0.0,-v1[2],v1[1], + v1[2],0.0,-v1[0], + -v1[1],v1[0],0.0); } template -std::ostream & operator<<(std::ostream &os, const TensorGeneric& t){ - for(unsigned i=0;i& t) { + for(unsigned i=0; i Tensor4d; typedef Tensor3d Tensor; inline -TensorGeneric<3,3> VcrossTensor(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2){ +TensorGeneric<3,3> VcrossTensor(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2) { - TensorGeneric<3,3> t; - for(unsigned i=0;i<3;i++){ - t.setRow(i,matmul(dcrossDv2(v1,v1),v2.getRow(i))); - } - return t; + TensorGeneric<3,3> t; + for(unsigned i=0; i<3; i++) { + t.setRow(i,matmul(dcrossDv2(v1,v1),v2.getRow(i))); + } + return t; } inline -TensorGeneric<3,3> VcrossTensor(const TensorGeneric<3,3>&v2,const VectorGeneric<3>&v1){ - TensorGeneric<3,3> t; - for(unsigned i=0;i<3;i++){ - t.setRow(i,-matmul(dcrossDv2(v1,v1),v2.getRow(i))); - } - return t; +TensorGeneric<3,3> VcrossTensor(const TensorGeneric<3,3>&v2,const VectorGeneric<3>&v1) { + TensorGeneric<3,3> t; + for(unsigned i=0; i<3; i++) { + t.setRow(i,-matmul(dcrossDv2(v1,v1),v2.getRow(i))); + } + return t; } inline -TensorGeneric<3,3> deriNorm(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2){ +TensorGeneric<3,3> deriNorm(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2) { // delta(v) = delta(v1/v1.norm) = 1/v1.norm*(delta(v1) - (v.delta(v1))cross v; double over_norm = 1./v1.modulo(); return over_norm*(v2 - over_norm*over_norm*(extProduct(matmul(v2,v1),v1))); } - + diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp index 02256a1f11..f5af5a9036 100644 --- a/src/tools/Tools.cpp +++ b/src/tools/Tools.cpp @@ -28,31 +28,31 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { template -bool Tools::convertToAny(const string & str,T & t){ - istringstream istr(str.c_str()); - bool ok=static_cast(istr>>t); - if(!ok) return false; - string remaining; - istr>>remaining; - return remaining.length()==0; +bool Tools::convertToAny(const string & str,T & t) { + istringstream istr(str.c_str()); + bool ok=static_cast(istr>>t); + if(!ok) return false; + string remaining; + istr>>remaining; + return remaining.length()==0; } -bool Tools::convert(const string & str,int & t){ - return convertToAny(str,t); +bool Tools::convert(const string & str,int & t) { + return convertToAny(str,t); } -bool Tools::convert(const string & str,long int & t){ - return convertToAny(str,t); +bool Tools::convert(const string & str,long int & t) { + return convertToAny(str,t); } -bool Tools::convert(const string & str,unsigned & t){ - return convertToAny(str,t); +bool Tools::convert(const string & str,unsigned & t) { + return convertToAny(str,t); } -bool Tools::convert(const string & str,AtomNumber &a){ +bool Tools::convert(const string & str,AtomNumber &a) { unsigned i; bool r=convert(str,i); if(r) a.setSerial(i); @@ -60,57 +60,57 @@ bool Tools::convert(const string & str,AtomNumber &a){ } template -bool Tools::convertToReal(const string & str,T & t){ - if(str=="PI" || str=="+PI" || str=="+pi" || str=="pi"){ - t=pi; return true; - } else if(str=="-PI" || str=="-pi"){ - t=-pi; return true; - } else if( str.find("PI")!=std::string::npos ){ - std::size_t pi_start=str.find_first_of("PI"); - if(str.substr(pi_start)!="PI") return false; - istringstream nstr(str.substr(0,pi_start)); - T ff=0.0; bool ok=static_cast(nstr>>ff); - if(!ok) return false; - t=ff*pi; - std::string remains; nstr>>remains; - return remains.length()==0; - } else if( str.find("pi")!=std::string::npos ){ - std::size_t pi_start=str.find_first_of("pi"); - if(str.substr(pi_start)!="pi") return false; - istringstream nstr(str.substr(0,pi_start)); - T ff=0.0; bool ok=static_cast(nstr>>ff); - if(!ok) return false; - t=ff*pi; - std::string remains; nstr>>remains; - return remains.length()==0; - } else if(str=="NAN"){ - t=NAN; - return true; - } - return convertToAny(str,t); +bool Tools::convertToReal(const string & str,T & t) { + if(str=="PI" || str=="+PI" || str=="+pi" || str=="pi") { + t=pi; return true; + } else if(str=="-PI" || str=="-pi") { + t=-pi; return true; + } else if( str.find("PI")!=std::string::npos ) { + std::size_t pi_start=str.find_first_of("PI"); + if(str.substr(pi_start)!="PI") return false; + istringstream nstr(str.substr(0,pi_start)); + T ff=0.0; bool ok=static_cast(nstr>>ff); + if(!ok) return false; + t=ff*pi; + std::string remains; nstr>>remains; + return remains.length()==0; + } else if( str.find("pi")!=std::string::npos ) { + std::size_t pi_start=str.find_first_of("pi"); + if(str.substr(pi_start)!="pi") return false; + istringstream nstr(str.substr(0,pi_start)); + T ff=0.0; bool ok=static_cast(nstr>>ff); + if(!ok) return false; + t=ff*pi; + std::string remains; nstr>>remains; + return remains.length()==0; + } else if(str=="NAN") { + t=NAN; + return true; + } + return convertToAny(str,t); } -bool Tools::convert(const string & str,float & t){ - return convertToReal(str,t); +bool Tools::convert(const string & str,float & t) { + return convertToReal(str,t); } -bool Tools::convert(const string & str,double & t){ - return convertToReal(str,t); +bool Tools::convert(const string & str,double & t) { + return convertToReal(str,t); } -bool Tools::convert(const string & str,long double & t){ - return convertToReal(str,t); +bool Tools::convert(const string & str,long double & t) { + return convertToReal(str,t); } -bool Tools::convert(const string & str,string & t){ - t=str; - return true; +bool Tools::convert(const string & str,string & t) { + t=str; + return true; } -vector Tools::getWords(const string & line,const char* separators,int * parlevel,const char* parenthesis){ +vector Tools::getWords(const string & line,const char* separators,int * parlevel,const char* parenthesis) { plumed_massert(strlen(parenthesis)==1,"multiple parenthesis type not available"); plumed_massert(parenthesis[0]=='(' || parenthesis[0]=='[' || parenthesis[0]=='{', - "only ( [ { allowed as parenthesis"); + "only ( [ { allowed as parenthesis"); if(!separators) separators=" \t\n"; const string sep(separators); char openpar=parenthesis[0]; @@ -122,25 +122,25 @@ vector Tools::getWords(const string & line,const char* separators,int * string word; int parenthesisLevel=0; if(parlevel) parenthesisLevel=*parlevel; - for(unsigned i=0;i=0,"Extra closed parenthesis in '" + line + "'"); } - if(parenthesisLevel==0) for(unsigned j=0;j0){ + if(found && word.length()>0) { if(!parlevel) plumed_massert(parenthesisLevel==0,"Unmatching parenthesis in '" + line + "'"); words.push_back(word); word.clear(); } } - if(word.length()>0){ + if(word.length()>0) { if(!parlevel) plumed_massert(parenthesisLevel==0,"Unmatching parenthesis in '" + line + "'"); words.push_back(word); } @@ -148,34 +148,34 @@ vector Tools::getWords(const string & line,const char* separators,int * return words; } -bool Tools::getParsedLine(IFile& ifile,vector & words){ +bool Tools::getParsedLine(IFile& ifile,vector & words) { string line(""); words.clear(); bool stat; bool inside=false; int parlevel=0; bool mergenext=false; - while((stat=ifile.getline(line))){ + while((stat=ifile.getline(line))) { trimComments(line); trim(line); if(line.length()==0) continue; vector w=getWords(line,NULL,&parlevel); if(w.empty()) continue; - if(inside && *(w.begin())=="..."){ + if(inside && *(w.begin())=="...") { inside=false; if(w.size()==2) plumed_massert(w[1]==words[0],"second word in terminating \"...\" lines, if present, should be equal to first word of directive"); plumed_massert(w.size()<=2,"terminating \"...\" lines cannot consist of more than two words"); w.clear(); - }else if(*(w.end()-1)=="..."){ + } else if(*(w.end()-1)=="...") { inside=true; w.erase(w.end()-1); }; int i0=0; - if(mergenext && words.size()>0 && w.size()>0){ + if(mergenext && words.size()>0 && w.size()>0) { words[words.size()-1]+=" "+w[0]; i0=1; } - for(unsigned i=i0;i0); if(!inside)break; } @@ -185,13 +185,13 @@ bool Tools::getParsedLine(IFile& ifile,vector & words){ } -bool Tools::getline(FILE* fp,string & line){ +bool Tools::getline(FILE* fp,string & line) { line=""; const int bufferlength=1024; char buffer[bufferlength]; bool ret; - for(int i=0;i0) if(buffer[ss-1]=='\n') break; @@ -201,28 +201,28 @@ bool Tools::getline(FILE* fp,string & line){ return ret; } -void Tools::trim(string & s){ +void Tools::trim(string & s) { size_t n=s.find_last_not_of(" \t"); s=s.substr(0,n+1); } -void Tools::trimComments(string & s){ +void Tools::trimComments(string & s) { size_t n=s.find_first_of("#"); s=s.substr(0,n); } -bool Tools::getKey(vector& line,const string & key,string & s,int rep){ +bool Tools::getKey(vector& line,const string & key,string & s,int rep) { s.clear(); - for(auto p=line.begin();p!=line.end();++p){ + for(auto p=line.begin(); p!=line.end(); ++p) { if((*p).length()==0) continue; string x=(*p).substr(0,key.length()); - if(x==key){ + if(x==key) { if((*p).length()==key.length())return false; string tmp=(*p).substr(key.length(),(*p).length()); line.erase(p); s=tmp; const std::string multi("@replicas:"); - if(rep>=0 && startWith(s,multi)){ + if(rep>=0 && startWith(s,multi)) { s=s.substr(multi.length(),s.length()); std::vector words=getWords(s,"\t\n ,"); plumed_assert(rep& line,const string & key,string & s,int rep){ return false; } -void Tools::interpretRanges(std::vector&s){ +void Tools::interpretRanges(std::vector&s) { vector news; - for(const auto & p :s){ + for(const auto & p :s) { news.push_back(p); size_t dash=p.find("-"); if(dash==string::npos) continue; @@ -245,23 +245,23 @@ void Tools::interpretRanges(std::vector&s){ int stride=1; int second; size_t colon=p.substr(dash+1).find(":"); - if(colon!=string::npos){ + if(colon!=string::npos) { if(!Tools::convert(p.substr(dash+1).substr(0,colon),second) || - !Tools::convert(p.substr(dash+1).substr(colon+1),stride)) continue; + !Tools::convert(p.substr(dash+1).substr(colon+1),stride)) continue; } else { if(!Tools::convert(p.substr(dash+1),second)) continue; } news.resize(news.size()-1); - if(first<=second){ + if(first<=second) { plumed_massert(stride>0,"interpreting ranges "+ p + ", stride should be positive"); - for(int i=first;i<=second;i+=stride){ + for(int i=first; i<=second; i+=stride) { string ss; convert(i,ss); news.push_back(ss); } } else { plumed_massert(stride<0,"interpreting ranges "+ p + ", stride should be positive"); - for(int i=first;i>=second;i+=stride){ + for(int i=first; i>=second; i+=stride) { string ss; convert(i,ss); news.push_back(ss); @@ -271,25 +271,25 @@ void Tools::interpretRanges(std::vector&s){ s=news; } -void Tools::interpretLabel(vector&s){ +void Tools::interpretLabel(vector&s) { if(s.size()<2)return; string s0=s[0]; unsigned l=s0.length(); if(l<1) return; - if(s0[l-1]==':'){ + if(s0[l-1]==':') { s[0]=s[1]; s[1]="LABEL="+s0.substr(0,l-1); } } -vector Tools::ls(const string&d){ +vector Tools::ls(const string&d) { DIR*dir; vector result; - if ((dir=opendir(d.c_str()))){ + if ((dir=opendir(d.c_str()))) { #if defined(__PLUMED_HAS_READDIR_R) struct dirent ent; #endif - while(true){ + while(true) { struct dirent *res; #if defined(__PLUMED_HAS_READDIR_R) readdir_r(dir,&ent,&res); @@ -309,16 +309,16 @@ vector Tools::ls(const string&d){ return result; } -void Tools::stripLeadingAndTrailingBlanks( std::string& str ){ +void Tools::stripLeadingAndTrailingBlanks( std::string& str ) { std::size_t first=str.find_first_not_of(' '); std::size_t last=str.find_last_not_of(' '); if( first<=last && first!=std::string::npos) str=str.substr(first,last+1); } -std::string Tools::extension(const std::string&s){ +std::string Tools::extension(const std::string&s) { size_t n=s.find_last_of("."); std::string ext; - if(n!=std::string::npos && n+1=s.length()){ + if(n!=std::string::npos && n+1=s.length()) { ext=s.substr(n+1); if(ext.find("/")!=std::string::npos) ext=""; string base=s.substr(0,n); @@ -328,13 +328,13 @@ std::string Tools::extension(const std::string&s){ return ext; } -bool Tools::startWith(const std::string & full,const std::string &start){ +bool Tools::startWith(const std::string & full,const std::string &start) { return (full.substr(0,start.length())==start); } -bool Tools::findKeyword(const std::vector&line,const std::string&key){ +bool Tools::findKeyword(const std::vector&line,const std::string&key) { const std::string search(key+"="); - for(const auto & p : line){ + for(const auto & p : line) { if(startWith(p,search)) return true; } return false; diff --git a/src/tools/Tools.h b/src/tools/Tools.h index 27d894530b..74ca0bec01 100644 --- a/src/tools/Tools.h +++ b/src/tools/Tools.h @@ -31,7 +31,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class IFile; @@ -49,7 +49,7 @@ const double pi(3.14159265358979323846264338327950288419716939937510582097494459 /// \ingroup TOOLBOX /// Empty class which just contains several (static) tools -class Tools{ +class Tools { /// class to convert a string to a generic type T template static bool convertToAny(const std::string & str,T &t); @@ -114,7 +114,7 @@ class Tools{ static bool findKeyword(const std::vector&line,const std::string&key); /// Interpret atom ranges static void interpretRanges(std::vector&); -/// Remove duplicates from a vector of type T +/// Remove duplicates from a vector of type T template static void removeDuplicates(std::vector& vec); /// interpret ":" syntax for labels @@ -127,7 +127,7 @@ class Tools{ /// E.g.: extension("pippo.xyz")="xyz". /// It only returns extensions with a length between 1 and 4 /// E.g.: extension("pippo.12345")="" whereas extenion("pippo.1234")="1234"; -/// It is also smart enough to detect "/", so that +/// It is also smart enough to detect "/", so that /// extension("pippo/.t")="" whereas extension("pippo/a.t")="t" static std::string extension(const std::string&); /// Fast int power @@ -138,7 +138,7 @@ class Tools{ }; template -bool Tools::parse(std::vector&line,const std::string&key,T&val,int rep){ +bool Tools::parse(std::vector&line,const std::string&key,T&val,int rep) { std::string s; if(!getKey(line,key+"=",s,rep)) return false; if(s.length()>0 && !convert(s,val))return false; @@ -146,17 +146,17 @@ bool Tools::parse(std::vector&line,const std::string&key,T&val,int } template -bool Tools::parseVector(std::vector&line,const std::string&key,std::vector&val,int rep){ +bool Tools::parseVector(std::vector&line,const std::string&key,std::vector&val,int rep) { std::string s; if(!getKey(line,key+"=",s,rep)) return false; // if(s.length()==0) return true; val.clear(); std::vector words=getWords(s,"\t\n ,"); - for(unsigned i=0;i=0 && startWith(s,multi)){ + if(rep>=0 && startWith(s,multi)) { s=s.substr(multi.length(),s.length()); std::vector words=getWords(s,"\t\n ,"); plumed_assert(rep&line,const std::string&key,std: template void Tools::removeDuplicates(std::vector& vec) { - std::sort(vec.begin(), vec.end()); - vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); + std::sort(vec.begin(), vec.end()); + vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); } inline -bool Tools::parseFlag(std::vector&line,const std::string&key,bool&val){ - for(auto p=line.begin();p!=line.end();++p){ - if(key==*p){ +bool Tools::parseFlag(std::vector&line,const std::string&key,bool&val) { + for(auto p=line.begin(); p!=line.end(); ++p) { + if(key==*p) { val=true; line.erase(p); return true; @@ -189,7 +189,7 @@ bool Tools::parseFlag(std::vector&line,const std::string&key,bool&v /// beware: this brings any number into a pbc that ranges from -0.5 to 0.5 inline -double Tools::pbc(double x){ +double Tools::pbc(double x) { #ifdef __PLUMED_PBC_WHILE while (x>0.5) x-=1.0; while (x<-0.5) x+=1.0; @@ -207,29 +207,29 @@ double Tools::pbc(double x){ } template -void Tools::convert(T i,std::string & str){ - std::ostringstream ostr; - ostr<>= 1; - base *= base; - } + if(exp<0) { + exp=-exp; + base=1.0/base; + } + double result = 1.0; + while (exp) + { + if (exp & 1) + result *= base; + exp >>= 1; + base *= base; + } - return result; + return result; } } diff --git a/src/tools/Torsion.cpp b/src/tools/Torsion.cpp index d124986007..4464e1bd17 100644 --- a/src/tools/Torsion.cpp +++ b/src/tools/Torsion.cpp @@ -25,18 +25,18 @@ #include #include -namespace PLMD{ - -double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3)const{ - const Vector nv2(v2*(1.0/v2.modulo())); - const Vector a(crossProduct(nv2,v1)); - const Vector b(crossProduct(v3,nv2)); - const double cosangle=dotProduct(a,b); - const double sinangle=dotProduct(crossProduct(a,b),nv2); - return std::atan2(-sinangle,cosangle); +namespace PLMD { + +double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3)const { + const Vector nv2(v2*(1.0/v2.modulo())); + const Vector a(crossProduct(nv2,v1)); + const Vector b(crossProduct(v3,nv2)); + const double cosangle=dotProduct(a,b); + const double sinangle=dotProduct(crossProduct(a,b),nv2); + return std::atan2(-sinangle,cosangle); } -double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3,Vector& d1,Vector& d2,Vector& d3)const{ +double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3,Vector& d1,Vector& d2,Vector& d3)const { const double modv2(1./v2.modulo()); const Vector nv2(v2*modv2); diff --git a/src/tools/Torsion.h b/src/tools/Torsion.h index b8ac740412..b898a99ccd 100644 --- a/src/tools/Torsion.h +++ b/src/tools/Torsion.h @@ -24,7 +24,7 @@ #include "Vector.h" -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX /// Class to compute torsional angles. @@ -36,7 +36,7 @@ namespace PLMD{ /// I know it is a bit misleading. If we really do not need to store "options" /// inside the Torsion class, we can remove it later and write compute as /// a static function. -class Torsion{ +class Torsion { // still empty, but may accomodate some options in the future public: /// Compute the angle between the projections of v1 and v3 on the plane orthogonal diff --git a/src/tools/Units.cpp b/src/tools/Units.cpp index 3bb5c8886c..48737c9d08 100644 --- a/src/tools/Units.cpp +++ b/src/tools/Units.cpp @@ -24,7 +24,7 @@ using namespace std; -namespace PLMD{ +namespace PLMD { Units::Units(): energy(1.0), @@ -40,15 +40,15 @@ Units::Units(): { } -void Units::setEnergy(const std::string &s){ +void Units::setEnergy(const std::string &s) { energyString=s; - if(s=="kj/mol"){ + if(s=="kj/mol") { energy=1.0; - } else if(s=="kcal/mol"){ + } else if(s=="kcal/mol") { energy=4.184; - } else if(s=="j/mol"){ + } else if(s=="j/mol") { energy=0.001; - } else if(s=="eV"){ + } else if(s=="eV") { energy=96.48530749925792; } else { energy=-1.0; @@ -58,13 +58,13 @@ void Units::setEnergy(const std::string &s){ } } -void Units::setLength(const std::string &s){ +void Units::setLength(const std::string &s) { lengthString=s; - if(s=="nm"){ + if(s=="nm") { length=1.0; - } else if(s=="A"){ + } else if(s=="A") { length=0.1; - } else if(s=="um"){ + } else if(s=="um") { length=1000.0; } else { length=-1.0; @@ -74,13 +74,13 @@ void Units::setLength(const std::string &s){ } } -void Units::setTime(const std::string &s){ +void Units::setTime(const std::string &s) { timeString=s; - if(s=="ps"){ + if(s=="ps") { time=1.0; - } else if(s=="ns"){ + } else if(s=="ns") { time=1000.0; - } else if(s=="fs"){ + } else if(s=="fs") { time=0.001; } else { time=-1.0; @@ -90,9 +90,9 @@ void Units::setTime(const std::string &s){ } } -void Units::setCharge(const std::string &s){ +void Units::setCharge(const std::string &s) { chargeString=s; - if(s=="e"){ + if(s=="e") { charge=1.0; } else { charge=-1.0; @@ -102,9 +102,9 @@ void Units::setCharge(const std::string &s){ } } -void Units::setMass(const std::string &s){ +void Units::setMass(const std::string &s) { massString=s; - if(s=="amu"){ + if(s=="amu") { mass=1.0; } else { mass=-1.0; @@ -114,27 +114,27 @@ void Units::setMass(const std::string &s){ } } -void Units::setEnergy(const double s){ +void Units::setEnergy(const double s) { energyString=""; energy=s; } -void Units::setLength(const double s){ +void Units::setLength(const double s) { lengthString=""; length=s; } -void Units::setTime(const double s){ +void Units::setTime(const double s) { timeString=""; time=s; } -void Units::setCharge(const double s){ +void Units::setCharge(const double s) { chargeString=""; charge=s; } -void Units::setMass(const double s){ +void Units::setMass(const double s) { massString=""; mass=s; } diff --git a/src/tools/Units.h b/src/tools/Units.h index e7f5c63350..12074cc211 100644 --- a/src/tools/Units.h +++ b/src/tools/Units.h @@ -24,7 +24,7 @@ #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -38,7 +38,7 @@ one can also use strings such as kcal/mol. */ -class Units{ +class Units { /// Units for energy, expressed in kj/mol (e.g. 4.184 means kcal/mol) double energy; std::string energyString; @@ -111,52 +111,52 @@ class Units{ }; inline -const double & Units::getEnergy()const{ +const double & Units::getEnergy()const { return energy; } inline -const double & Units::getLength()const{ +const double & Units::getLength()const { return length; } inline -const double & Units::getTime()const{ +const double & Units::getTime()const { return time; } inline -const double & Units::getCharge()const{ +const double & Units::getCharge()const { return charge; } inline -const double & Units::getMass()const{ +const double & Units::getMass()const { return mass; } inline -const std::string & Units::getEnergyString()const{ +const std::string & Units::getEnergyString()const { return energyString; } inline -const std::string & Units::getLengthString()const{ +const std::string & Units::getLengthString()const { return lengthString; } inline -const std::string & Units::getTimeString()const{ +const std::string & Units::getTimeString()const { return timeString; } inline -const std::string & Units::getChargeString()const{ +const std::string & Units::getChargeString()const { return chargeString; } inline -const std::string & Units::getMassString()const{ +const std::string & Units::getMassString()const { return massString; } diff --git a/src/tools/Vector.cpp b/src/tools/Vector.cpp index f868a1aba5..8f2883acb8 100644 --- a/src/tools/Vector.cpp +++ b/src/tools/Vector.cpp @@ -23,18 +23,18 @@ #include "Exception.h" #include -namespace PLMD{ +namespace PLMD { /// Small auxiliary class. /// I use it to test a few things that I am scary of and could introduce bugs. /// It checks at startup that Vector satifies some requirement so as to allow /// accessing a vector of tensors as a 3 times longer array of doubles. -static class VectorChecks{ +static class VectorChecks { public: - VectorChecks(){ + VectorChecks() { if( sizeof(VectorGeneric<2>)==2*sizeof(double) - && sizeof(VectorGeneric<3>)==3*sizeof(double) - && sizeof(VectorGeneric<4>)==4*sizeof(double)) return; + && sizeof(VectorGeneric<3>)==3*sizeof(double) + && sizeof(VectorGeneric<4>)==4*sizeof(double)) return; plumed_merror("sizeof(VectorGeneric)!=x*sizeof(double). PLUMED cannot work properly in these conditions."); } } checks; diff --git a/src/tools/Vector.h b/src/tools/Vector.h index 8c3422c2f0..133ff4a194 100644 --- a/src/tools/Vector.h +++ b/src/tools/Vector.h @@ -31,7 +31,7 @@ #endif -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -43,7 +43,7 @@ This class implements a vector of doubles with size fixed at compile time. It is useful for small fixed size objects (e.g. 3d vectors) as it does not waste space to store the vector size. Moreover, as the compiler knows the size, it can be completely -opimized inline. +opimized inline. All the methods are inlined for better optimization and all the loops are explicitly unrolled using PLMD::LoopUnroller class. Vector elements are initialized to zero by default. Notice that @@ -80,7 +80,7 @@ int main(){ template -class VectorGeneric{ +class VectorGeneric { double d[n]; public: /// Create it with preassigned components. @@ -155,14 +155,14 @@ class VectorGeneric{ template<> inline -VectorGeneric<2>:: VectorGeneric(double x0,double x1){ +VectorGeneric<2>:: VectorGeneric(double x0,double x1) { d[0]=x0; d[1]=x1; } template<> inline -VectorGeneric<3>:: VectorGeneric(double x0,double x1,double x2){ +VectorGeneric<3>:: VectorGeneric(double x0,double x1,double x2) { d[0]=x0; d[1]=x1; d[2]=x2; @@ -170,7 +170,7 @@ VectorGeneric<3>:: VectorGeneric(double x0,double x1,double x2){ template<> inline -VectorGeneric<4>:: VectorGeneric(double x0,double x1,double x2,double x3){ +VectorGeneric<4>:: VectorGeneric(double x0,double x1,double x2,double x3) { d[0]=x0; d[1]=x1; d[2]=x2; @@ -178,17 +178,17 @@ VectorGeneric<4>:: VectorGeneric(double x0,double x1,double x2,double x3){ } template -void VectorGeneric::zero(){ +void VectorGeneric::zero() { LoopUnroller::_zero(d); } template -VectorGeneric::VectorGeneric(){ +VectorGeneric::VectorGeneric() { LoopUnroller::_zero(d); } template -double & VectorGeneric::operator[](unsigned i){ +double & VectorGeneric::operator[](unsigned i) { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator[](unsigned i){ } template -const double & VectorGeneric::operator[](unsigned i)const{ +const double & VectorGeneric::operator[](unsigned i)const { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator[](unsigned i)const{ } template -double & VectorGeneric::operator()(unsigned i){ +double & VectorGeneric::operator()(unsigned i) { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator()(unsigned i){ } template -const double & VectorGeneric::operator()(unsigned i)const{ +const double & VectorGeneric::operator()(unsigned i)const { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator()(unsigned i)const{ } template -VectorGeneric& VectorGeneric::operator +=(const VectorGeneric& b){ +VectorGeneric& VectorGeneric::operator +=(const VectorGeneric& b) { LoopUnroller::_add(d,b.d); return *this; } template -VectorGeneric& VectorGeneric::operator -=(const VectorGeneric& b){ +VectorGeneric& VectorGeneric::operator -=(const VectorGeneric& b) { LoopUnroller::_sub(d,b.d); return *this; } template -VectorGeneric& VectorGeneric::operator *=(double s){ +VectorGeneric& VectorGeneric::operator *=(double s) { LoopUnroller::_mul(d,s); return *this; } template -VectorGeneric& VectorGeneric::operator /=(double s){ +VectorGeneric& VectorGeneric::operator /=(double s) { LoopUnroller::_mul(d,1.0/s); return *this; } template -VectorGeneric VectorGeneric::operator +()const{ +VectorGeneric VectorGeneric::operator +()const { return *this; } template -VectorGeneric VectorGeneric::operator -()const{ +VectorGeneric VectorGeneric::operator -()const { VectorGeneric r; LoopUnroller::_neg(r.d,d); return r; } template -VectorGeneric operator+(const VectorGeneric&v1,const VectorGeneric&v2){ +VectorGeneric operator+(const VectorGeneric&v1,const VectorGeneric&v2) { VectorGeneric v(v1); return v+=v2; } template -VectorGeneric operator-(const VectorGeneric&v1,const VectorGeneric&v2){ +VectorGeneric operator-(const VectorGeneric&v1,const VectorGeneric&v2) { VectorGeneric v(v1); return v-=v2; } template -VectorGeneric operator*(double s,const VectorGeneric&v){ +VectorGeneric operator*(double s,const VectorGeneric&v) { VectorGeneric vv(v); return vv*=s; } template -VectorGeneric operator*(const VectorGeneric&v,double s){ +VectorGeneric operator*(const VectorGeneric&v,double s) { return s*v; } template -VectorGeneric operator/(const VectorGeneric&v,double s){ +VectorGeneric operator/(const VectorGeneric&v,double s) { return v*(1.0/s); } template -VectorGeneric delta(const VectorGeneric&v1,const VectorGeneric&v2){ +VectorGeneric delta(const VectorGeneric&v1,const VectorGeneric&v2) { return v2-v1; } template -double VectorGeneric::modulo2()const{ +double VectorGeneric::modulo2()const { return LoopUnroller::_sum2(d); } template -double dotProduct(const VectorGeneric& v1,const VectorGeneric& v2){ +double dotProduct(const VectorGeneric& v1,const VectorGeneric& v2) { return LoopUnroller::_dot(v1.d,v2.d); } inline -VectorGeneric<3> crossProduct(const VectorGeneric<3>& v1,const VectorGeneric<3>& v2){ - return VectorGeneric<3>( - v1[1]*v2[2]-v1[2]*v2[1], - v1[2]*v2[0]-v1[0]*v2[2], - v1[0]*v2[1]-v1[1]*v2[0]); +VectorGeneric<3> crossProduct(const VectorGeneric<3>& v1,const VectorGeneric<3>& v2) { + return VectorGeneric<3>( + v1[1]*v2[2]-v1[2]*v2[1], + v1[2]*v2[0]-v1[0]*v2[2], + v1[0]*v2[1]-v1[1]*v2[0]); } template -double VectorGeneric::modulo()const{ +double VectorGeneric::modulo()const { return sqrt(modulo2()); } template -double modulo2(const VectorGeneric&v){ +double modulo2(const VectorGeneric&v) { return v.modulo2(); } template -double modulo(const VectorGeneric&v){ +double modulo(const VectorGeneric&v) { return v.modulo(); } template -std::ostream & operator<<(std::ostream &os, const VectorGeneric& v){ - for(unsigned i=0;i& v) { + for(unsigned i=0; i deriv(getNumberOfAtoms()); - for(unsigned i=0;i deriv(getNumberOfAtoms()); - for(unsigned i=0;i deriv(getNumberOfAtoms()); - if(scaled_components){ + if(scaled_components) { setPosition(getPbc().scaledToReal(coord)); } else { setPosition(coord); diff --git a/src/vatom/Ghost.cpp b/src/vatom/Ghost.cpp index e14f6db7aa..fcd7893775 100644 --- a/src/vatom/Ghost.cpp +++ b/src/vatom/Ghost.cpp @@ -26,13 +26,13 @@ using namespace std; -namespace PLMD{ -namespace vatom{ +namespace PLMD { +namespace vatom { -//+PLUMEDOC VATOM GHOST +//+PLUMEDOC VATOM GHOST /* Calculate the absolute position of a ghost atom with fixed coordinates -in the local reference frame formed by three atoms. +in the local reference frame formed by three atoms. The computed ghost atom is stored as a virtual atom that can be accessed in an atom list through the the label for the GHOST action that creates it. @@ -63,7 +63,7 @@ class Ghost: PLUMED_REGISTER_ACTION(Ghost,"GHOST") -void Ghost::registerKeywords(Keywords& keys){ +void Ghost::registerKeywords(Keywords& keys) { ActionWithVirtualAtom::registerKeywords(keys); keys.add("atoms","COORDINATES","coordinates of the ghost atom in the local reference frame"); } @@ -81,35 +81,35 @@ Ghost::Ghost(const ActionOptions&ao): checkRead(); log.printf(" of atoms"); - for(unsigned i=0;i deriv(getNumberOfAtoms()); vector n; -// first versor +// first versor Vector n01 = delta(getPosition(0), getPosition(1)); n.push_back(n01/n01.modulo()); // auxiliary vector Vector n02 = delta(getPosition(0), getPosition(2)); -// second versor +// second versor Vector n03 = crossProduct(n[0],n02); double n03_norm = n03.modulo(); n.push_back(n03/n03_norm); -// third versor +// third versor n.push_back(crossProduct(n[0],n[1])); // origin of the reference system pos = getPosition(0); - for(unsigned i=0;i<3;++i){ + for(unsigned i=0; i<3; ++i) { pos += coord[i] * n[i]; } @@ -117,7 +117,7 @@ void Ghost::calculate(){ setMass(1.0); setCharge(0.0); -// some useful tensors for derivatives +// some useful tensors for derivatives Tensor dn0d0 = (-Tensor::identity()+Tensor(n[0],n[0]))/n01.modulo(); Tensor dn0d1 = (+Tensor::identity()-Tensor(n[0],n[0]))/n01.modulo(); Tensor dn02d0 = -Tensor::identity(); @@ -125,50 +125,50 @@ void Ghost::calculate(){ // derivative of n1 = n0 x n02 Tensor dn1d0, dn1d1, dn1d2; - Vector aux0, aux1, aux2; + Vector aux0, aux1, aux2; - for(unsigned j=0;j<3;++j){ + for(unsigned j=0; j<3; ++j) { // derivative of n0 x n02 with respect to point 0, coordinate j - Vector tmp00 = Vector( dn0d0(j,0), dn0d0(j,1), dn0d0(j,2)); - Vector tmp020 = Vector(dn02d0(j,0), dn02d0(j,1), dn02d0(j,2)); - Vector tmp0 = crossProduct(tmp00,n02) + crossProduct(n[0],tmp020); - aux0[j] = dotProduct(tmp0,n[1]); + Vector tmp00 = Vector( dn0d0(j,0), dn0d0(j,1), dn0d0(j,2)); + Vector tmp020 = Vector(dn02d0(j,0), dn02d0(j,1), dn02d0(j,2)); + Vector tmp0 = crossProduct(tmp00,n02) + crossProduct(n[0],tmp020); + aux0[j] = dotProduct(tmp0,n[1]); // derivative of n0 x n02 with respect to point 1, coordinate j - Vector tmp01 = Vector( dn0d1(j,0), dn0d1(j,1), dn0d1(j,2)); - Vector tmp1 = crossProduct(tmp01,n02); - aux1[j] = dotProduct(tmp1,n[1]); + Vector tmp01 = Vector( dn0d1(j,0), dn0d1(j,1), dn0d1(j,2)); + Vector tmp1 = crossProduct(tmp01,n02); + aux1[j] = dotProduct(tmp1,n[1]); // derivative of n0 x n02 with respect to point 2, coordinate j - Vector tmp022 = Vector(dn02d2(j,0), dn02d2(j,1), dn02d2(j,2)); - Vector tmp2 = crossProduct(n[0],tmp022); - aux2[j] = dotProduct(tmp2,n[1]); + Vector tmp022 = Vector(dn02d2(j,0), dn02d2(j,1), dn02d2(j,2)); + Vector tmp2 = crossProduct(n[0],tmp022); + aux2[j] = dotProduct(tmp2,n[1]); // derivative of n1 = (n0 x n02) / || (n0 x n02) || - for(unsigned i=0;i<3;++i) { - dn1d0(j,i) = ( tmp0[i] - aux0[j] * n[1][i] ) / n03_norm; - dn1d1(j,i) = ( tmp1[i] - aux1[j] * n[1][i] ) / n03_norm; - dn1d2(j,i) = ( tmp2[i] - aux2[j] * n[1][i] ) / n03_norm; - } + for(unsigned i=0; i<3; ++i) { + dn1d0(j,i) = ( tmp0[i] - aux0[j] * n[1][i] ) / n03_norm; + dn1d1(j,i) = ( tmp1[i] - aux1[j] * n[1][i] ) / n03_norm; + dn1d2(j,i) = ( tmp2[i] - aux2[j] * n[1][i] ) / n03_norm; + } } // Derivative of the last versor n2 = n0 x n1 = ( n0( n0 n02 ) - n02 ) / || n0 x n02 || // Scalar product and derivatives - double n0_n02 = dotProduct(n[0],n02); + double n0_n02 = dotProduct(n[0],n02); Vector dn0_n02d0, dn0_n02d1, dn0_n02d2; - for(unsigned j=0;j<3;++j){ - for(unsigned i=0;i<3;++i){ - dn0_n02d0[j] += dn0d0(j,i)*n02[i] + n[0][i]*dn02d0(j,i); - dn0_n02d1[j] += dn0d1(j,i)*n02[i]; - dn0_n02d2[j] += n[0][i]*dn02d2(j,i); - } + for(unsigned j=0; j<3; ++j) { + for(unsigned i=0; i<3; ++i) { + dn0_n02d0[j] += dn0d0(j,i)*n02[i] + n[0][i]*dn02d0(j,i); + dn0_n02d1[j] += dn0d1(j,i)*n02[i]; + dn0_n02d2[j] += n[0][i]*dn02d2(j,i); + } } Tensor dn2d0, dn2d1, dn2d2; - for(unsigned j=0;j<3;++j){ - for(unsigned i=0;i<3;++i){ - dn2d0(j,i) = ( dn0d0(j,i) * n0_n02 + n[0][i] * dn0_n02d0[j] - dn02d0(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux0[j] / n03_norm ) / n03_norm; - dn2d1(j,i) = ( dn0d1(j,i) * n0_n02 + n[0][i] * dn0_n02d1[j] - ( n[0][i] * n0_n02 - n02[i] ) * aux1[j] / n03_norm ) / n03_norm; - dn2d2(j,i) = ( n[0][i] * dn0_n02d2[j] - dn02d2(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux2[j] / n03_norm ) / n03_norm; - } + for(unsigned j=0; j<3; ++j) { + for(unsigned i=0; i<3; ++i) { + dn2d0(j,i) = ( dn0d0(j,i) * n0_n02 + n[0][i] * dn0_n02d0[j] - dn02d0(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux0[j] / n03_norm ) / n03_norm; + dn2d1(j,i) = ( dn0d1(j,i) * n0_n02 + n[0][i] * dn0_n02d1[j] - ( n[0][i] * n0_n02 - n02[i] ) * aux1[j] / n03_norm ) / n03_norm; + dn2d2(j,i) = ( n[0][i] * dn0_n02d2[j] - dn02d2(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux2[j] / n03_norm ) / n03_norm; + } } // Finally, the derivative tensor diff --git a/src/vesselbase/ActionWithAveraging.cpp b/src/vesselbase/ActionWithAveraging.cpp index e6111a7690..a470f6f5f8 100644 --- a/src/vesselbase/ActionWithAveraging.cpp +++ b/src/vesselbase/ActionWithAveraging.cpp @@ -26,104 +26,104 @@ namespace PLMD { namespace vesselbase { -void ActionWithAveraging::registerKeywords( Keywords& keys ){ - Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); +void ActionWithAveraging::registerKeywords( Keywords& keys ) { + Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionWithArguments::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionWithVessel::registerKeywords( keys ); keys.add("compulsory","STRIDE","1","the frequency with which the data should be collected and added to the quantity being averaged"); keys.add("compulsory","CLEAR","0","the frequency with which to clear all the accumulated data. The default value " - "of 0 implies that all the data will be used and that the grid will never be cleared"); + "of 0 implies that all the data will be used and that the grid will never be cleared"); keys.add("optional","LOGWEIGHTS","list of actions that calculates log weights that should be used to weight configurations when calculating averages"); keys.addFlag("UNORMALIZED",false,"output the unaveraged quantity/quantities."); keys.remove("NUMERICAL_DERIVATIVES"); } ActionWithAveraging::ActionWithAveraging( const ActionOptions& ao ): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao), -ActionWithArguments(ao), -ActionWithValue(ao), -ActionWithVessel(ao), -myaverage(NULL), -useRunAllTasks(false), -clearstride(0), -lweight(0),cweight(0) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao), + ActionWithArguments(ao), + ActionWithValue(ao), + ActionWithVessel(ao), + myaverage(NULL), + useRunAllTasks(false), + clearstride(0), + lweight(0),cweight(0) { - if( keywords.exists("CLEAR") ){ - parse("CLEAR",clearstride); - if( clearstride>0 ){ - if( clearstride%getStride()!=0 ) error("CLEAR parameter must be a multiple of STRIDE"); - log.printf(" clearing grid every %u steps \n",clearstride); - } + if( keywords.exists("CLEAR") ) { + parse("CLEAR",clearstride); + if( clearstride>0 ) { + if( clearstride%getStride()!=0 ) error("CLEAR parameter must be a multiple of STRIDE"); + log.printf(" clearing grid every %u steps \n",clearstride); + } } - if( keywords.exists("LOGWEIGHTS") ){ - std::vector wwstr; parseVector("LOGWEIGHTS",wwstr); - if( wwstr.size()>0 ) log.printf(" reweighting using weights from "); - std::vector arg( getArguments() ); - for(unsigned i=0;i(wwstr[i]); - if( !val ) error("could not find value named"); - weights.push_back( val->copyOutput(val->getLabel()) ); - arg.push_back( val->copyOutput(val->getLabel()) ); - log.printf("%s ",wwstr[i].c_str() ); - } - if( wwstr.size()>0 ) log.printf("\n"); - else log.printf(" weights are all equal to one\n"); - requestArguments( arg ); + if( keywords.exists("LOGWEIGHTS") ) { + std::vector wwstr; parseVector("LOGWEIGHTS",wwstr); + if( wwstr.size()>0 ) log.printf(" reweighting using weights from "); + std::vector arg( getArguments() ); + for(unsigned i=0; i(wwstr[i]); + if( !val ) error("could not find value named"); + weights.push_back( val->copyOutput(val->getLabel()) ); + arg.push_back( val->copyOutput(val->getLabel()) ); + log.printf("%s ",wwstr[i].c_str() ); + } + if( wwstr.size()>0 ) log.printf("\n"); + else log.printf(" weights are all equal to one\n"); + requestArguments( arg ); } if( keywords.exists("UNORMALIZED") ) parseFlag("UNORMALIZED",unormalised); } -void ActionWithAveraging::setAveragingAction( AveragingVessel* av_vessel, const bool& usetasks ){ - myaverage=av_vessel; addVessel( myaverage ); +void ActionWithAveraging::setAveragingAction( AveragingVessel* av_vessel, const bool& usetasks ) { + myaverage=av_vessel; addVessel( myaverage ); useRunAllTasks=usetasks; resizeFunctions(); } -void ActionWithAveraging::lockRequests(){ +void ActionWithAveraging::lockRequests() { ActionAtomistic::lockRequests(); ActionWithArguments::lockRequests(); } -void ActionWithAveraging::unlockRequests(){ +void ActionWithAveraging::unlockRequests() { ActionAtomistic::unlockRequests(); ActionWithArguments::unlockRequests(); } -void ActionWithAveraging::calculateNumericalDerivatives(PLMD::ActionWithValue*){ +void ActionWithAveraging::calculateNumericalDerivatives(PLMD::ActionWithValue*) { error("not possible to compute numerical derivatives for this action"); } -void ActionWithAveraging::update(){ +void ActionWithAveraging::update() { if( (clearstride!=1 && getStep()==0) || !onStep() ) return; // Clear if it is time to reset - if( myaverage ){ - if( myaverage->wasreset() ) clearAverage(); + if( myaverage ) { + if( myaverage->wasreset() ) clearAverage(); } // Calculate the weight for all reweighting - if ( weights.size()>0 ){ - double sum=0; for(unsigned i=0;iget(); - lweight=sum; cweight = exp( sum ); + if ( weights.size()>0 ) { + double sum=0; for(unsigned i=0; iget(); + lweight=sum; cweight = exp( sum ); } else { - lweight=0; cweight=1.0; + lweight=0; cweight=1.0; } // Prepare to do the averaging prepareForAveraging(); // Run all the tasks (if required - if( useRunAllTasks ) runAllTasks(); + if( useRunAllTasks ) runAllTasks(); // This the averaging if it is not done using task list else performOperations( true ); - // Update the norm + // Update the norm if( myaverage ) myaverage->setNorm( cweight + myaverage->getNorm() ); // Finish the averaging finishAveraging(); // By resetting here we are ensuring that the grid will be cleared at the start of the next step - if( myaverage ){ - if( getStride()==0 || (clearstride>0 && getStep()%clearstride==0) ) myaverage->reset(); + if( myaverage ) { + if( getStride()==0 || (clearstride>0 && getStep()%clearstride==0) ) myaverage->reset(); } } -void ActionWithAveraging::clearAverage(){ plumed_assert( myaverage->wasreset() ); myaverage->clear(); } +void ActionWithAveraging::clearAverage() { plumed_assert( myaverage->wasreset() ); myaverage->clear(); } -void ActionWithAveraging::performOperations( const bool& from_update ){ plumed_error(); } +void ActionWithAveraging::performOperations( const bool& from_update ) { plumed_error(); } } diff --git a/src/vesselbase/ActionWithAveraging.h b/src/vesselbase/ActionWithAveraging.h index fe33827e76..62b5642fb6 100644 --- a/src/vesselbase/ActionWithAveraging.h +++ b/src/vesselbase/ActionWithAveraging.h @@ -35,8 +35,8 @@ namespace vesselbase { /** \ingroup INHERIT -This abstract base class should be used if you are writing some method that calculates an "average" from a set of -trajectory frames. Notice that we use the word average very broadly here and state that even dimensionality +This abstract base class should be used if you are writing some method that calculates an "average" from a set of +trajectory frames. Notice that we use the word average very broadly here and state that even dimensionality reduction algorithms calculate an "average." In other words, what we mean by average is that the method is going to take in data from each trajectory frame and only calculate the final quantity once a certain amount of data has been collected. @@ -49,7 +49,7 @@ class ActionWithAveraging : public ActionWithValue, public ActionWithVessel { -friend class AveragingVessel; + friend class AveragingVessel; private: /// The vessel which is used to compute averages AveragingVessel* myaverage; @@ -74,19 +74,19 @@ friend class AveragingVessel; void lockRequests(); void unlockRequests(); void calculateNumericalDerivatives(PLMD::ActionWithValue*); - virtual unsigned getNumberOfDerivatives(){ return 0; } + virtual unsigned getNumberOfDerivatives() { return 0; } unsigned getNumberOfArguments() const ; /// Overwrite ActionWithArguments getArguments() so that we don't return the bias - std::vector getArguments(); + std::vector getArguments(); void update(); /// This does the clearing of the action virtual void clearAverage(); /// This is done before the averaging comences - virtual void prepareForAveraging(){} + virtual void prepareForAveraging() {} /// This does the averaging operation virtual void performOperations( const bool& from_update ); /// This is done once the averaging is finished - virtual void finishAveraging(){} + virtual void finishAveraging() {} }; inline @@ -95,9 +95,9 @@ unsigned ActionWithAveraging::getNumberOfArguments() const { } inline -std::vector ActionWithAveraging::getArguments(){ +std::vector ActionWithAveraging::getArguments() { std::vector arg_vals( ActionWithArguments::getArguments() ); - for(unsigned i=0;i(mlab); if(!mves) error("action labelled " + mlab + " does not exist or does not have vessels"); addDependency(mves); ActionWithValue* aval=dynamic_cast( this ); - if(aval){ - if( aval->checkNumericalDerivatives() ){ - ActionWithValue* aval2=dynamic_cast( mves ); - plumed_assert( aval2 ); aval2->useNumericalDerivatives(); - } + if(aval) { + if( aval->checkNumericalDerivatives() ) { + ActionWithValue* aval2=dynamic_cast( mves ); + plumed_assert( aval2 ); aval2->useNumericalDerivatives(); + } } - if( type=="bridge" ){ - ActionWithVessel* aves=dynamic_cast( this ); - plumed_assert(aves); myBridgeVessel = mves->addBridgingVessel( aves ); - arguments = dynamic_cast( myBridgeVessel ); - } else if( type=="store" ){ - arguments = dynamic_cast( mves->buildDataStashes( NULL ) ); + if( type=="bridge" ) { + ActionWithVessel* aves=dynamic_cast( this ); + plumed_assert(aves); myBridgeVessel = mves->addBridgingVessel( aves ); + arguments = dynamic_cast( myBridgeVessel ); + } else if( type=="store" ) { + arguments = dynamic_cast( mves->buildDataStashes( NULL ) ); } else { - plumed_error(); + plumed_error(); } } -void ActionWithInputVessel::calculateNumericalDerivatives( ActionWithValue* a ){ - if(!a){ +void ActionWithInputVessel::calculateNumericalDerivatives( ActionWithValue* a ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"cannot compute numerical derivatives for an action without values"); } - if( myBridgeVessel ){ - myBridgeVessel->completeNumericalDerivatives(); + if( myBridgeVessel ) { + myBridgeVessel->completeNumericalDerivatives(); } else { - error("numerical derivatives are not implemented"); + error("numerical derivatives are not implemented"); } } -void ActionWithInputVessel::applyBridgeForces( const std::vector& bb ){ - plumed_dbg_assert( myBridgeVessel ); addBridgeForces( bb ); +void ActionWithInputVessel::applyBridgeForces( const std::vector& bb ) { + plumed_dbg_assert( myBridgeVessel ); addBridgeForces( bb ); } } diff --git a/src/vesselbase/ActionWithInputVessel.h b/src/vesselbase/ActionWithInputVessel.h index ac278768d3..09d888f45f 100644 --- a/src/vesselbase/ActionWithInputVessel.h +++ b/src/vesselbase/ActionWithInputVessel.h @@ -48,19 +48,19 @@ class ActionWithInputVessel : public virtual Action { /// Registers the list of keywords static void registerKeywords( Keywords& keys ); explicit ActionWithInputVessel(const ActionOptions&); - virtual ~ActionWithInputVessel(){} + virtual ~ActionWithInputVessel() {} /// Calculate the numerical derivatives -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. The default will be correct for the vast majority of cases virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); /// Apply forces from the bridge void applyBridgeForces( const std::vector& bb ); /// Apply forces from the bridge - virtual void addBridgeForces( const std::vector& bb ){} + virtual void addBridgeForces( const std::vector& bb ) {} }; inline -Vessel* ActionWithInputVessel::getPntrToArgument(){ +Vessel* ActionWithInputVessel::getPntrToArgument() { return arguments; } diff --git a/src/vesselbase/ActionWithVessel.cpp b/src/vesselbase/ActionWithVessel.cpp index 02eb060f06..ebbe511a4f 100644 --- a/src/vesselbase/ActionWithVessel.cpp +++ b/src/vesselbase/ActionWithVessel.cpp @@ -32,16 +32,16 @@ #include "tools/Stopwatch.h" using namespace std; -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -void ActionWithVessel::registerKeywords(Keywords& keys){ +void ActionWithVessel::registerKeywords(Keywords& keys) { keys.add("hidden","TOL","this keyword can be used to speed up your calculation. When accumulating sums in which the individual " - "terms are numbers inbetween zero and one it is assumed that terms less than a certain tolerance " - "make only a small contribution to the sum. They can thus be safely ignored as can the the derivatives " - "wrt these small quantities."); + "terms are numbers inbetween zero and one it is assumed that terms less than a certain tolerance " + "make only a small contribution to the sum. They can thus be safely ignored as can the the derivatives " + "wrt these small quantities."); keys.add("hidden","MAXDERIVATIVES","The maximum number of derivatives that can be used when storing data. This controls when " - "we have to start using lowmem"); + "we have to start using lowmem"); keys.addFlag("SERIAL",false,"do the calculation in serial. Do not parallelize"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); keys.addFlag("TIMINGS",false,"output information on the timings of the various parts of the calculation"); @@ -67,77 +67,77 @@ ActionWithVessel::ActionWithVessel(const ActionOptions&ao): if( keywords.exists("SERIAL") ) parseFlag("SERIAL",serial); else serial=true; if(serial)log.printf(" doing calculation in serial\n"); - if( keywords.exists("LOWMEM") ){ - plumed_assert( !keywords.exists("HIGHMEM") ); - parseFlag("LOWMEM",lowmem); - if(lowmem){ - log.printf(" lowering memory requirements\n"); - dertime_can_be_off=true; - } - } - if( keywords.exists("HIGHMEM") ){ - plumed_assert( !keywords.exists("LOWMEM") ); - bool highmem; parseFlag("HIGHMEM",highmem); - lowmem=!highmem; - if(!lowmem) log.printf(" increasing the memory requirements\n"); + if( keywords.exists("LOWMEM") ) { + plumed_assert( !keywords.exists("HIGHMEM") ); + parseFlag("LOWMEM",lowmem); + if(lowmem) { + log.printf(" lowering memory requirements\n"); + dertime_can_be_off=true; + } + } + if( keywords.exists("HIGHMEM") ) { + plumed_assert( !keywords.exists("LOWMEM") ); + bool highmem; parseFlag("HIGHMEM",highmem); + lowmem=!highmem; + if(!lowmem) log.printf(" increasing the memory requirements\n"); } - tolerance=nl_tolerance=epsilon; + tolerance=nl_tolerance=epsilon; if( keywords.exists("TOL") ) parse("TOL",tolerance); - if( tolerance>epsilon){ - log.printf(" Ignoring contributions less than %f \n",tolerance); + if( tolerance>epsilon) { + log.printf(" Ignoring contributions less than %f \n",tolerance); } parseFlag("TIMINGS",timers); stopwatch.start(); stopwatch.pause(); } -ActionWithVessel::~ActionWithVessel(){ - for(unsigned i=0;i(vv); - if( fv ){ - std::string mylabel=Vessel::transformName( name ); - plumed_massert( keywords.outputComponentExists(mylabel,false), "a description of the value calculated by vessel " + name + " has not been added to the manual"); - } + if( fv ) { + std::string mylabel=Vessel::transformName( name ); + plumed_massert( keywords.outputComponentExists(mylabel,false), "a description of the value calculated by vessel " + name + " has not been added to the manual"); + } addVessel(vv); } -void ActionWithVessel::addVessel( Vessel* vv ){ +void ActionWithVessel::addVessel( Vessel* vv ) { ShortcutVessel* sv=dynamic_cast(vv); - if(!sv){ vv->checkRead(); functions.push_back(vv); } + if(!sv) { vv->checkRead(); functions.push_back(vv); } else { delete sv; return; } StoreDataVessel* mm=dynamic_cast( vv ); if( mydata && mm ) error("cannot have more than one StoreDataVessel in one action"); else if( mm ) mydata=mm; - else dertime_can_be_off=false; + else dertime_can_be_off=false; } -BridgeVessel* ActionWithVessel::addBridgingVessel( ActionWithVessel* tome ){ - VesselOptions da("","",0,"",this); +BridgeVessel* ActionWithVessel::addBridgingVessel( ActionWithVessel* tome ) { + VesselOptions da("","",0,"",this); BridgeVessel* bv=new BridgeVessel(da); bv->setOutputAction( tome ); tome->actionIsBridged=true; dertime_can_be_off=false; functions.push_back( dynamic_cast(bv) ); resizeFunctions(); - return bv; + return bv; } -StoreDataVessel* ActionWithVessel::buildDataStashes( ActionWithVessel* actionThatUses ){ - if(mydata){ - if( actionThatUses ) mydata->addActionThatUses( actionThatUses ); - return mydata; - } - +StoreDataVessel* ActionWithVessel::buildDataStashes( ActionWithVessel* actionThatUses ) { + if(mydata) { + if( actionThatUses ) mydata->addActionThatUses( actionThatUses ); + return mydata; + } + VesselOptions da("","",0,"",this); StoreDataVessel* mm=new StoreDataVessel(da); if( actionThatUses ) mm->addActionThatUses( actionThatUses ); @@ -149,86 +149,86 @@ StoreDataVessel* ActionWithVessel::buildDataStashes( ActionWithVessel* actionTha return mydata; } -void ActionWithVessel::addTaskToList( const unsigned& taskCode ){ - fullTaskList.push_back( taskCode ); taskFlags.push_back(0); +void ActionWithVessel::addTaskToList( const unsigned& taskCode ) { + fullTaskList.push_back( taskCode ); taskFlags.push_back(0); plumed_assert( fullTaskList.size()==taskFlags.size() ); } -void ActionWithVessel::readVesselKeywords(){ +void ActionWithVessel::readVesselKeywords() { // Set maxderivatives if it is too big if( maxderivatives>getNumberOfDerivatives() ) maxderivatives=getNumberOfDerivatives(); // Loop over all keywords find the vessels and create appropriate functions - for(unsigned i=0;i0 ) resizeFunctions(); } -void ActionWithVessel::resizeFunctions(){ - for(unsigned i=0;iresize(); +void ActionWithVessel::resizeFunctions() { + for(unsigned i=0; iresize(); } -void ActionWithVessel::needsDerivatives(){ +void ActionWithVessel::needsDerivatives() { // Turn on the derivatives and resize - noderiv=false; resizeFunctions(); + noderiv=false; resizeFunctions(); // Setting contributors unlocked here ensures that link cells are ignored contributorsAreUnlocked=true; contributorsAreUnlocked=false; // And turn on the derivatives in all actions on which we are dependent - for(unsigned i=0;i( getDependencies()[i] ); - if(vv) vv->needsDerivatives(); + for(unsigned i=0; i( getDependencies()[i] ); + if(vv) vv->needsDerivatives(); } } -void ActionWithVessel::lockContributors(){ +void ActionWithVessel::lockContributors() { nactive_tasks = 0; - for(unsigned i=0;i0 ) nactive_tasks++; + for(unsigned i=0; i0 ) nactive_tasks++; } unsigned n=0; partialTaskList.resize( nactive_tasks ); - indexOfTaskInFullList.resize( nactive_tasks ); - for(unsigned i=0;i0 ){ - partialTaskList[n] = fullTaskList[i]; - indexOfTaskInFullList[n]=i; - n++; - } + indexOfTaskInFullList.resize( nactive_tasks ); + for(unsigned i=0; i0 ) { + partialTaskList[n] = fullTaskList[i]; + indexOfTaskInFullList[n]=i; + n++; + } } plumed_dbg_assert( n==nactive_tasks ); - for(unsigned i=0;i( functions[i] ); - if( bb ) bb->copyTaskFlags(); + for(unsigned i=0; i( functions[i] ); + if( bb ) bb->copyTaskFlags(); } // Resize mydata to accomodate all active tasks if( mydata ) mydata->resize(); contributorsAreUnlocked=false; } -void ActionWithVessel::deactivateAllTasks(){ +void ActionWithVessel::deactivateAllTasks() { contributorsAreUnlocked=true; nactive_tasks = 0; taskFlags.assign(taskFlags.size(),0); } @@ -237,26 +237,26 @@ bool ActionWithVessel::taskIsCurrentlyActive( const unsigned& index ) const { plumed_dbg_assert( index0); } -void ActionWithVessel::doJobsRequiredBeforeTaskList(){ +void ActionWithVessel::doJobsRequiredBeforeTaskList() { // Do any preparatory stuff for functions - for(unsigned j=0;jprepare(); + for(unsigned j=0; jprepare(); } -unsigned ActionWithVessel::getSizeOfBuffer( unsigned& bufsize ){ - for(unsigned i=0;isetBufferStart( bufsize ); +unsigned ActionWithVessel::getSizeOfBuffer( unsigned& bufsize ) { + for(unsigned i=0; isetBufferStart( bufsize ); if( buffer.size()!=bufsize ) buffer.resize( bufsize ); - if( mydata ){ - unsigned dsize=mydata->getSizeOfDerivativeList(); - if( der_list.size()!=dsize ) der_list.resize( dsize ); + if( mydata ) { + unsigned dsize=mydata->getSizeOfDerivativeList(); + if( der_list.size()!=dsize ) der_list.resize( dsize ); } return bufsize; } -void ActionWithVessel::runAllTasks(){ +void ActionWithVessel::runAllTasks() { plumed_massert( !contributorsAreUnlocked && functions.size()>0, "you must have a call to readVesselKeywords somewhere" ); unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); - if(serial){ stride=1; rank=0; } + if(serial) { stride=1; rank=0; } // Make sure jobs are done if(timers) stopwatch.start("1 Prepare Tasks"); @@ -269,55 +269,55 @@ void ActionWithVessel::runAllTasks(){ if( nt==0 || !threadSafe() ) nt=1; // Get size for buffer - unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); + unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); // Clear buffer buffer.assign( buffer.size(), 0.0 ); // Switch off calculation of derivatives in main loop if( dertime_can_be_off ) dertime=false; // std::vector der_list; - // if( mydata ) der_list.resize( mydata->getSizeOfDerivativeList(), 0 ); + // if( mydata ) der_list.resize( mydata->getSizeOfDerivativeList(), 0 ); // Build storage stuff for loop // std::vector buffer( bufsize, 0.0 ); if(timers) stopwatch.start("2 Loop over tasks"); -#pragma omp parallel num_threads(nt) -{ - std::vector omp_buffer; - if( nt>1 ) omp_buffer.resize( bufsize, 0.0 ); - MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); - MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); - myvals.clearAll(); bvals.clearAll(); - -#pragma omp for nowait - for(unsigned i=rank;i omp_buffer; + if( nt>1 ) omp_buffer.resize( bufsize, 0.0 ); + MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + myvals.clearAll(); bvals.clearAll(); + + #pragma omp for nowait + for(unsigned i=rank; i1 ){ - calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, omp_buffer, der_list ); + if( nt>1 ) { + calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, omp_buffer, der_list ); } else { - calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer, der_list ); + calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer, der_list ); } // Clear the value myvals.clearAll(); + } + #pragma omp critical + if(nt>1) for(unsigned i=0; i1) for(unsigned i=0;i0 ) comm.Sum( buffer ); // MPI Gather index stores - if( mydata && !lowmem && !noderiv ){ - comm.Sum( der_list ); mydata->setActiveValsAndDerivatives( der_list ); + if( mydata && !lowmem && !noderiv ) { + comm.Sum( der_list ); mydata->setActiveValsAndDerivatives( der_list ); } // Update the elements that are makign contributions to the sum here // this causes problems if we do it in prepare @@ -342,22 +342,22 @@ void ActionWithVessel::transformBridgedDerivatives( const unsigned& current, Mul plumed_error(); } -void ActionWithVessel::calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector& buffer, std::vector& der_list ){ - for(unsigned j=0;jcalculate( taskCode, functions[j]->transformDerivatives(taskCode, myvals, bvals), buffer, der_list ); - if( !actionIsBridged ) bvals.clearAll(); +void ActionWithVessel::calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector& buffer, std::vector& der_list ) { + for(unsigned j=0; jcalculate( taskCode, functions[j]->transformDerivatives(taskCode, myvals, bvals), buffer, der_list ); + if( !actionIsBridged ) bvals.clearAll(); } return; } -void ActionWithVessel::finishComputations( const std::vector& buffer ){ +void ActionWithVessel::finishComputations( const std::vector& buffer ) { // Set the final value of the function - for(unsigned j=0;jfinish( buffer ); + for(unsigned j=0; jfinish( buffer ); } -bool ActionWithVessel::getForcesFromVessels( std::vector& forcesToApply ){ +bool ActionWithVessel::getForcesFromVessels( std::vector& forcesToApply ) { #ifndef NDEBUG if( forcesToApply.size()>0 ) plumed_dbg_assert( forcesToApply.size()==getNumberOfDerivatives() ); #endif @@ -365,26 +365,26 @@ bool ActionWithVessel::getForcesFromVessels( std::vector& forcesToApply forcesToApply.assign( forcesToApply.size(),0.0 ); bool wasforced=false; - for(unsigned i=0;iapplyForce( tmpforces )) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforces )) ) { + wasforced=true; + for(unsigned j=0; jgetName().find(mynam)!=std::string::npos ){ - if( target<0 ) target=i; - else error("found more than one " + mynam + " object in action"); - } + for(unsigned i=0; igetName().find(mynam)!=std::string::npos ) { + if( target<0 ) target=i; + else error("found more than one " + mynam + " object in action"); + } } return functions[target]; } diff --git a/src/vesselbase/ActionWithVessel.h b/src/vesselbase/ActionWithVessel.h index a20954804f..8134037649 100644 --- a/src/vesselbase/ActionWithVessel.h +++ b/src/vesselbase/ActionWithVessel.h @@ -29,11 +29,11 @@ #include "tools/MultiValue.h" #include -namespace PLMD{ +namespace PLMD { class Value; class Stopwatch; -namespace vesselbase{ +namespace vesselbase { class Vessel; class BridgeVessel; @@ -46,13 +46,13 @@ times. This is used in PLMD::MultiColvar. */ class ActionWithVessel : public virtual Action { -friend class Vessel; -friend class ShortcutVessel; -friend class FunctionVessel; -friend class StoreDataVessel; -friend class BridgeVessel; -friend class ActionWithInputVessel; -friend class OrderingVessel; + friend class Vessel; + friend class ShortcutVessel; + friend class FunctionVessel; + friend class StoreDataVessel; + friend class BridgeVessel; + friend class ActionWithInputVessel; + friend class OrderingVessel; private: /// Do all calculations in serial bool serial; @@ -64,7 +64,7 @@ friend class OrderingVessel; bool actionIsBridged; /// The maximum number of derivatives we can use before we need to invoke lowmem unsigned maxderivatives; -/// The tolerance on the accumulators +/// The tolerance on the accumulators double tolerance; /// Tolerance for quantities being put in neighbor lists double nl_tolerance; @@ -120,7 +120,7 @@ friend class OrderingVessel; void runAllTasks(); /// Resize all the functions when the number of derivatives change void resizeFunctions(); -/// This loops over all the vessels calculating them and also +/// This loops over all the vessels calculating them and also /// sets all the element derivatives equal to zero void calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector& buffer, std::vector& der_list ); /// Retrieve the forces from all the vessels (used in apply) @@ -156,14 +156,14 @@ friend class OrderingVessel; virtual bool isPeriodic()=0; /// What are the domains of the base quantities virtual void retrieveDomain( std::string& min, std::string& max); -/// Get the number of derivatives for final calculated quantity +/// Get the number of derivatives for final calculated quantity virtual unsigned getNumberOfDerivatives()=0; /// Get the number of quantities that are calculated during each task virtual unsigned getNumberOfQuantities() const ; /// Get the number of vessels unsigned getNumberOfVessels() const; /// Get a pointer to the ith vessel - Vessel* getPntrToVessel( const unsigned& i ); + Vessel* getPntrToVessel( const unsigned& i ); /// Do any jobs that are required before the task list is undertaken virtual void doJobsRequiredBeforeTaskList(); /// Get the full size of the taskList dynamic list @@ -175,13 +175,13 @@ friend class OrderingVessel; /// Get the ith of the currently active tasks unsigned getActiveTask( const unsigned& ii ) const ; /// Calculate one of the functions in the distribution - virtual void performTask( const unsigned& , const unsigned& , MultiValue& ) const=0; + virtual void performTask( const unsigned&, const unsigned&, MultiValue& ) const=0; /// Do the task if we have a bridge virtual void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const; /// Ensure that data required in other vessels is stored StoreDataVessel* buildDataStashes( ActionWithVessel* actionThatUses ); /// Apply forces from bridge vessel - this is rarely used - currently only in ActionVolume - virtual void applyBridgeForces( const std::vector& bb ){ plumed_error(); } + virtual void applyBridgeForces( const std::vector& bb ) { plumed_error(); } /// These are overwritten in MultiColvarFunction // virtual void activateIndexes( const unsigned&, const unsigned&, const std::vector& ){} /// Return a particular named vessel @@ -216,7 +216,7 @@ unsigned ActionWithVessel::getNumberOfQuantities() const { } inline -Vessel* ActionWithVessel::getPntrToVessel( const unsigned& i ){ +Vessel* ActionWithVessel::getPntrToVessel( const unsigned& i ) { plumed_dbg_assert( iisPeriodic() ) error("MIN is not a meaningful option for periodic variables"); parse("BETA",beta); usetol=true; } -std::string AltMin::value_descriptor(){ +std::string AltMin::value_descriptor() { std::string str_beta; Tools::convert( beta, str_beta ); return "the minimum value. Beta is equal to " + str_beta; } @@ -69,9 +69,9 @@ double AltMin::calcTransform( const double& val, double& dv ) const { double f = exp( -beta*val ); dv = -beta*f; return f; } -double AltMin::finalTransform( const double& val, double& dv ){ - dv = - 1.0 /(beta*val); return -std::log( val ) / beta; -} +double AltMin::finalTransform( const double& val, double& dv ) { + dv = - 1.0 /(beta*val); return -std::log( val ) / beta; +} } } diff --git a/src/vesselbase/AveragingVessel.cpp b/src/vesselbase/AveragingVessel.cpp index 7d8933bd6c..a3bbb4fd79 100644 --- a/src/vesselbase/AveragingVessel.cpp +++ b/src/vesselbase/AveragingVessel.cpp @@ -25,35 +25,35 @@ namespace PLMD { namespace vesselbase { -void AveragingVessel::registerKeywords( Keywords& keys ){ +void AveragingVessel::registerKeywords( Keywords& keys ) { Vessel::registerKeywords( keys ); } AveragingVessel::AveragingVessel( const vesselbase::VesselOptions& vo ): -Vessel(vo), -wascleared(true) + Vessel(vo), + wascleared(true) { ActionWithAveraging* myav = dynamic_cast( getAction() ); plumed_assert( myav ); unormalised = myav->unormalised; } -void AveragingVessel::finish( const std::vector& buffer ){ - wascleared=false; for(unsigned i=1;i& buffer ) { + wascleared=false; for(unsigned i=1; i data; + std::vector data; protected: /// Set the size of the data vector - void setDataSize( const unsigned& size ); + void setDataSize( const unsigned& size ); /// Set an element of the data array - void setDataElement( const unsigned& myelem, const double& value ); + void setDataElement( const unsigned& myelem, const double& value ); /// Add some value to an element of the data array - void addDataElement( const unsigned& myelem, const double& value ); + void addDataElement( const unsigned& myelem, const double& value ); /// Get the value of one of the data element - double getDataElement( const unsigned& myelem ) const ; + double getDataElement( const unsigned& myelem ) const ; /// Are we averaging the data - bool noAverage() const { return unormalised; } + bool noAverage() const { return unormalised; } public: /// keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Constructor - explicit AveragingVessel( const vesselbase::VesselOptions& ); + explicit AveragingVessel( const vesselbase::VesselOptions& ); /// Copy data from an accumulated buffer into the grid - virtual void finish( const std::vector& ); + virtual void finish( const std::vector& ); /// Was the grid cleared on the last step - bool wasreset() const ; + bool wasreset() const ; /// Clear all the data stored on the grid - virtual void clear(); + virtual void clear(); /// Reset the grid so that it is cleared at start of next time it is calculated - virtual void reset(); + virtual void reset(); /// Functions for dealing with normalisation constant - void setNorm( const double& snorm ); - double getNorm() const ; - virtual bool applyForce( std::vector& forces ){ return false; } + void setNorm( const double& snorm ); + double getNorm() const ; + virtual bool applyForce( std::vector& forces ) { return false; } }; inline -void AveragingVessel::setDataElement( const unsigned& myelem, const double& value ){ - plumed_dbg_assert( myelem<1+data.size() ); - wascleared=false; data[1+myelem]=value; +void AveragingVessel::setDataElement( const unsigned& myelem, const double& value ) { + plumed_dbg_assert( myelem<1+data.size() ); + wascleared=false; data[1+myelem]=value; } inline -void AveragingVessel::addDataElement( const unsigned& myelem, const double& value ){ - plumed_dbg_assert( myelem<1+data.size() ); - wascleared=false; data[1+myelem]+=value; +void AveragingVessel::addDataElement( const unsigned& myelem, const double& value ) { + plumed_dbg_assert( myelem<1+data.size() ); + wascleared=false; data[1+myelem]+=value; } inline double AveragingVessel::getDataElement( const unsigned& myelem ) const { - plumed_dbg_assert( myelem0 ); data[0]=snorm; } diff --git a/src/vesselbase/Between.cpp b/src/vesselbase/Between.cpp index 3a00b2fa70..ac02823d0f 100644 --- a/src/vesselbase/Between.cpp +++ b/src/vesselbase/Between.cpp @@ -28,52 +28,52 @@ namespace vesselbase { PLUMED_REGISTER_VESSEL(Between,"BETWEEN") -void Between::registerKeywords( Keywords& keys ){ +void Between::registerKeywords( Keywords& keys ) { FunctionVessel::registerKeywords( keys ); HistogramBead::registerKeywords( keys ); keys.addFlag("NORM",false,"calculate the fraction of values rather than the number"); } -void Between::reserveKeyword( Keywords& keys ){ +void Between::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","BETWEEN","calculate the number of values that are within a certain range. " - "These quantities are calculated using kernel density estimation as described on " - "\\ref histogrambead."); + "These quantities are calculated using kernel density estimation as described on " + "\\ref histogrambead."); keys.addOutputComponent("between","BETWEEN","the number/fraction of values within a certain range. This is calculated using one of the " - "formula described in the description of the keyword so as to make it continuous. " - "You can calculate this quantity multiple times using different parameters."); + "formula described in the description of the keyword so as to make it continuous. " + "You can calculate this quantity multiple times using different parameters."); } Between::Between( const VesselOptions& da ) : -FunctionVessel(da) -{ + FunctionVessel(da) +{ usetol=true; bool isPeriodic=getAction()->isPeriodic(); double min, max; std::string str_min, str_max; - if( isPeriodic ){ - getAction()->retrieveDomain( str_min, str_max ); - Tools::convert(str_min,min); Tools::convert(str_max,max); + if( isPeriodic ) { + getAction()->retrieveDomain( str_min, str_max ); + Tools::convert(str_min,min); Tools::convert(str_max,max); } - parseFlag("NORM",norm); std::string errormsg; + parseFlag("NORM",norm); std::string errormsg; hist.set( getAllInput(),errormsg ); if( !isPeriodic ) hist.isNotPeriodic(); - else hist.isPeriodic( min, max ); + else hist.isPeriodic( min, max ); if( errormsg.size()!=0 ) error( errormsg ); } -std::string Between::value_descriptor(){ +std::string Between::value_descriptor() { if(norm) return "the fraction of values " + hist.description(); return "the number of values " + hist.description(); } double Between::calcTransform( const double& val, double& dv ) const { - double f = hist.calculate(val, dv); return f; + double f = hist.calculate(val, dv); return f; } -double Between::getCutoff(){ +double Between::getCutoff() { return std::numeric_limits::max(); -} +} } } diff --git a/src/vesselbase/BridgeVessel.cpp b/src/vesselbase/BridgeVessel.cpp index 18ba59adb8..043f684405 100644 --- a/src/vesselbase/BridgeVessel.cpp +++ b/src/vesselbase/BridgeVessel.cpp @@ -28,31 +28,31 @@ namespace PLMD { namespace vesselbase { BridgeVessel::BridgeVessel( const VesselOptions& da ): -Vessel(da), -inum(0), + Vessel(da), + inum(0), // in_normal_calculate(false) -myOutputAction(NULL), -myOutputValues(NULL), -my_tmp_val(0,0) + myOutputAction(NULL), + myOutputValues(NULL), + my_tmp_val(0,0) { } -void BridgeVessel::resize(){ - if( myOutputAction->checkNumericalDerivatives() ){ - mynumerical_values.resize( getAction()->getNumberOfDerivatives()*myOutputValues->getNumberOfComponents() ); - inum=0; +void BridgeVessel::resize() { + if( myOutputAction->checkNumericalDerivatives() ) { + mynumerical_values.resize( getAction()->getNumberOfDerivatives()*myOutputValues->getNumberOfComponents() ); + inum=0; } // This bit ensures that we can store data in a bridge function if needs be // Notice we need to resize der_list in the underlying action as this is called // from a bridge - if( myOutputAction->mydata ){ - unsigned dsize=(myOutputAction->mydata)->getSizeOfDerivativeList(); - if( getAction()->der_list.size()!=dsize ) getAction()->der_list.resize( dsize ); + if( myOutputAction->mydata ) { + unsigned dsize=(myOutputAction->mydata)->getSizeOfDerivativeList(); + if( getAction()->der_list.size()!=dsize ) getAction()->der_list.resize( dsize ); } unsigned tmp=0; resizeBuffer( myOutputAction->getSizeOfBuffer( tmp ) ); } -void BridgeVessel::setOutputAction( ActionWithVessel* myact ){ +void BridgeVessel::setOutputAction( ActionWithVessel* myact ) { ActionWithValue* checkme=dynamic_cast( getAction() ); plumed_massert( checkme, "vessel in bridge must inherit from ActionWithValue"); @@ -61,22 +61,22 @@ void BridgeVessel::setOutputAction( ActionWithVessel* myact ){ plumed_massert( myOutputValues, "bridging vessel must inherit from ActionWithValue"); } -std::string BridgeVessel::description(){ +std::string BridgeVessel::description() { plumed_merror("I shouldn't end up here"); } -void BridgeVessel::prepare(){ +void BridgeVessel::prepare() { myOutputAction->doJobsRequiredBeforeTaskList(); } -void BridgeVessel::setBufferStart( unsigned& start ){ +void BridgeVessel::setBufferStart( unsigned& start ) { unsigned tmp=myOutputAction->getSizeOfBuffer( start ); } -MultiValue& BridgeVessel::transformDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ){ +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() ); + outvals.getNumberOfDerivatives()!=myOutputAction->getNumberOfDerivatives() ) { + outvals.resize( myOutputAction->getNumberOfQuantities(), myOutputAction->getNumberOfDerivatives() ); } myOutputAction->transformBridgedDerivatives( current, invals, outvals ); return outvals; @@ -85,64 +85,64 @@ MultiValue& BridgeVessel::transformDerivatives( const unsigned& current, MultiVa void BridgeVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { // in_normal_calculate=true; if( myvals.get(0)getTolerance() ) return; - myOutputAction->calculateAllVessels( current, myvals, myvals, buffer, der_list ); - return; + myOutputAction->calculateAllVessels( current, myvals, myvals, buffer, der_list ); + return; } -void BridgeVessel::finish( const std::vector& buffer ){ +void BridgeVessel::finish( const std::vector& buffer ) { myOutputAction->finishComputations( buffer ); - if( myOutputAction->checkNumericalDerivatives() ){ - if ( inumgetNumberOfComponents();++i){ - mynumerical_values[inum]=myOutputValues->getOutputQuantity(i); - inum++; - } - plumed_dbg_assert( inum<=mynumerical_values.size() ); - } else { - plumed_assert( inum==mynumerical_values.size() ); - } - } + if( myOutputAction->checkNumericalDerivatives() ) { + if ( inumgetNumberOfComponents(); ++i) { + mynumerical_values[inum]=myOutputValues->getOutputQuantity(i); + inum++; + } + plumed_dbg_assert( inum<=mynumerical_values.size() ); + } else { + plumed_assert( inum==mynumerical_values.size() ); + } + } } -void BridgeVessel::completeNumericalDerivatives(){ +void BridgeVessel::completeNumericalDerivatives() { unsigned nextra = myOutputAction->getNumberOfDerivatives() - getAction()->getNumberOfDerivatives(); Matrix tmpder( myOutputValues->getNumberOfComponents(), nextra ); ActionWithVessel* vval=dynamic_cast( myOutputAction ); - for(unsigned i=0;ibridgeVariable=i; getAction()->calculate(); - for(int j=0;jgetNumberOfComponents();++j) tmpder(j,i) = myOutputValues->getOutputQuantity(j); + for(unsigned i=0; ibridgeVariable=i; getAction()->calculate(); + for(int j=0; jgetNumberOfComponents(); ++j) tmpder(j,i) = myOutputValues->getOutputQuantity(j); } - vval->bridgeVariable=nextra; getAction()->calculate(); + vval->bridgeVariable=nextra; getAction()->calculate(); plumed_assert( inum==mynumerical_values.size() ); inum=0; // Reset inum now that we have finished calling calculate std::vector base( myOutputValues->getNumberOfComponents() ); - for(int j=0;jgetNumberOfComponents();++j) base[j] = myOutputValues->getOutputQuantity(j); + for(int j=0; jgetNumberOfComponents(); ++j) base[j] = myOutputValues->getOutputQuantity(j); const double delta=sqrt(epsilon); ActionAtomistic* aa=dynamic_cast( getAction() ); unsigned nvals=myOutputValues->getNumberOfComponents(); - for(unsigned j=0;jcopyOutput(j) )->clearDerivatives(); - - if( aa ){ - ActionWithArguments* aarg=dynamic_cast( getAction() ); - plumed_assert( !aarg ); Tensor box=aa->getBox(); - unsigned natoms=aa->getNumberOfAtoms(); - for(unsigned j=0;jcopyOutput(j) )->get(); - if( ( myOutputValues->copyOutput(j) )->getNumberOfDerivatives()>0 ){ - for(unsigned i=0;i<3*natoms;++i){ - double d=( mynumerical_values[i*nvals+j] - ref)/delta; - ( myOutputValues->copyOutput(j) )->addDerivative(i,d); - } - Tensor virial; - for(int i=0;i<3;i++) for(int k=0;k<3;k++){ - virial(i,k)=( mynumerical_values[ nvals*(3*natoms + 3*i + k) + j ]-ref)/delta; - } - virial=-matmul(box.transpose(),virial); - for(int i=0;i<3;i++) for(int k=0;k<3;k++) ( myOutputValues->copyOutput(j) )->addDerivative(3*natoms+3*k+i,virial(k,i)); + for(unsigned j=0; jcopyOutput(j) )->clearDerivatives(); + + if( aa ) { + ActionWithArguments* aarg=dynamic_cast( getAction() ); + plumed_assert( !aarg ); Tensor box=aa->getBox(); + unsigned natoms=aa->getNumberOfAtoms(); + for(unsigned j=0; jcopyOutput(j) )->get(); + if( ( myOutputValues->copyOutput(j) )->getNumberOfDerivatives()>0 ) { + for(unsigned i=0; i<3*natoms; ++i) { + double d=( mynumerical_values[i*nvals+j] - ref)/delta; + ( myOutputValues->copyOutput(j) )->addDerivative(i,d); + } + Tensor virial; + for(int i=0; i<3; i++) for(int k=0; k<3; k++) { + virial(i,k)=( mynumerical_values[ nvals*(3*natoms + 3*i + k) + j ]-ref)/delta; } + virial=-matmul(box.transpose(),virial); + for(int i=0; i<3; i++) for(int k=0; k<3; k++) ( myOutputValues->copyOutput(j) )->addDerivative(3*natoms+3*k+i,virial(k,i)); } + } } else { - plumed_merror("not implemented or tested yet"); + plumed_merror("not implemented or tested yet"); // unsigned nder=myOutputAction->getNumberOfDerivatives(); // for(unsigned j=0;jcopyOutput(j) )->get(); @@ -154,37 +154,37 @@ void BridgeVessel::completeNumericalDerivatives(){ // } } // Add the derivatives wrt to the local quantities we are working with - for(unsigned j=0;jgetNumberOfDerivatives();igetNumberOfDerivatives();++i){ - ( myOutputValues->copyOutput(j) )->addDerivative( i, (tmpder(j,k)-base[j])/sqrt(epsilon) ); k++; - } + for(unsigned j=0; jgetNumberOfDerivatives(); igetNumberOfDerivatives(); ++i) { + ( myOutputValues->copyOutput(j) )->addDerivative( i, (tmpder(j,k)-base[j])/sqrt(epsilon) ); k++; + } } } -bool BridgeVessel::applyForce( std::vector& outforces ){ +bool BridgeVessel::applyForce( std::vector& outforces ) { bool hasforce=false; outforces.assign(outforces.size(),0.0); unsigned ndertot = myOutputAction->getNumberOfDerivatives(); unsigned nextra = ndertot - getAction()->getNumberOfDerivatives(); std::vector forces( ndertot ), eforces( nextra, 0.0 ); - for(unsigned i=0;igetNumberOfVessels();++i){ - if( ( myOutputAction->getPntrToVessel(i) )->applyForce( forces ) ){ - hasforce=true; - for(unsigned j=0;jgetNumberOfVessels(); ++i) { + if( ( myOutputAction->getPntrToVessel(i) )->applyForce( forces ) ) { + hasforce=true; + for(unsigned j=0; japplyBridgeForces( eforces ); return hasforce; } -void BridgeVessel::copyTaskFlags(){ +void BridgeVessel::copyTaskFlags() { myOutputAction->deactivateAllTasks(); - for(unsigned i=0;inactive_tasks;++i) myOutputAction->taskFlags[ getAction()->indexOfTaskInFullList[i] ] = 1; + for(unsigned i=0; inactive_tasks; ++i) myOutputAction->taskFlags[ getAction()->indexOfTaskInFullList[i] ] = 1; myOutputAction->lockContributors(); } -MultiValue& BridgeVessel::getTemporyMultiValue(){ +MultiValue& BridgeVessel::getTemporyMultiValue() { return my_tmp_val; } diff --git a/src/vesselbase/BridgeVessel.h b/src/vesselbase/BridgeVessel.h index 6e0d4f6856..2ae248c838 100644 --- a/src/vesselbase/BridgeVessel.h +++ b/src/vesselbase/BridgeVessel.h @@ -35,7 +35,7 @@ namespace vesselbase { /** \ingroup TOOLBOX This class allows you to calculate the vessel in one ActionWithVessel. The user thinks -it is created in a different Action however. At the moment this is used for region +it is created in a different Action however. At the moment this is used for region */ class BridgeVessel : public Vessel { @@ -57,13 +57,13 @@ class BridgeVessel : public Vessel { ActionWithVessel* getOutputAction(); /// Setup the action we are outputting to void setOutputAction( ActionWithVessel* myOutputAction ); -/// Apply some force +/// Apply some force bool applyForce( std::vector& forces ); /// Should not be called std::string description(); /// Jobs to do before the task list starts void prepare(); -/// Set the start of the buffer +/// 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 ); @@ -76,11 +76,11 @@ class BridgeVessel : public Vessel { /// Set the task flags in the bridged class the same as in the original class void copyTaskFlags(); /// Return a tempory multi value - we do this so as to avoid vector resizing - MultiValue& getTemporyMultiValue(); + MultiValue& getTemporyMultiValue(); }; inline -ActionWithVessel* BridgeVessel::getOutputAction(){ +ActionWithVessel* BridgeVessel::getOutputAction() { return myOutputAction; } diff --git a/src/vesselbase/FunctionVessel.cpp b/src/vesselbase/FunctionVessel.cpp index 11dd055a60..13b84e6156 100644 --- a/src/vesselbase/FunctionVessel.cpp +++ b/src/vesselbase/FunctionVessel.cpp @@ -22,80 +22,80 @@ #include "FunctionVessel.h" #include "core/ActionWithValue.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -void FunctionVessel::registerKeywords( Keywords& keys ){ +void FunctionVessel::registerKeywords( Keywords& keys ) { ValueVessel::registerKeywords( keys ); } FunctionVessel::FunctionVessel( const VesselOptions& da ): -ValueVessel(da), -norm(false), -usetol(false) + ValueVessel(da), + norm(false), + usetol(false) { diffweight=getAction()->weightHasDerivatives; } -void FunctionVessel::resize(){ - if( getAction()->derivativesAreRequired() ){ - unsigned nderivatives=getAction()->getNumberOfDerivatives(); - getFinalValue()->resizeDerivatives( nderivatives ); - resizeBuffer( (1+nderivatives)*2 ); - diffweight=getAction()->weightHasDerivatives; +void FunctionVessel::resize() { + if( getAction()->derivativesAreRequired() ) { + unsigned nderivatives=getAction()->getNumberOfDerivatives(); + getFinalValue()->resizeDerivatives( nderivatives ); + resizeBuffer( (1+nderivatives)*2 ); + diffweight=getAction()->weightHasDerivatives; } else { - resizeBuffer(2); - diffweight=false; // Don't need to worry about differentiable weights if no derivatives + resizeBuffer(2); + diffweight=false; // Don't need to worry about differentiable weights if no derivatives } } void FunctionVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { unsigned nderivatives=getFinalValue()->getNumberOfDerivatives(); - double weight=myvals.get(0); - plumed_dbg_assert( weight>=getTolerance() ); + double weight=myvals.get(0); + plumed_dbg_assert( weight>=getTolerance() ); // This deals with the value double dval, f=calcTransform( myvals.get(mycomp), dval ); - if( norm ){ - if( usetol && weightderivativesAreRequired() && fabs(dval)>0.0 ) myvals.chainRule( mycomp, 0, 1, 0, weight*dval, bufstart, buffer ); return; } -double FunctionVessel::calcTransform( const double& , double& ) const { - plumed_error(); return 1.0; +double FunctionVessel::calcTransform( const double&, double& ) const { + plumed_error(); return 1.0; } -void FunctionVessel::finish( const std::vector& buffer ){ +void FunctionVessel::finish( const std::vector& buffer ) { unsigned nderivatives=getFinalValue()->getNumberOfDerivatives(); - if( norm && diffweight ){ - double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; - getFinalValue()->set( val / weight ); - for(unsigned i=0;iaddDerivative( i, buffer[bufstart+1+i]/weight - val*buffer[bufstart+1+nderivatives+1+i]/(weight*weight) ); - } - } else if( norm ){ - double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; - getFinalValue()->set( val / weight ); - for(unsigned i=0;iaddDerivative( i, buffer[bufstart+1+i]/weight ); + if( norm && diffweight ) { + double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; + getFinalValue()->set( val / weight ); + for(unsigned i=0; iaddDerivative( i, buffer[bufstart+1+i]/weight - val*buffer[bufstart+1+nderivatives+1+i]/(weight*weight) ); + } + } else if( norm ) { + double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; + getFinalValue()->set( val / weight ); + for(unsigned i=0; iaddDerivative( i, buffer[bufstart+1+i]/weight ); } else { - double dv, val=finalTransform( buffer[bufstart], dv); getFinalValue()->set( val ); - for(unsigned i=0;iaddDerivative( i, dv*buffer[bufstart+1+i] ); + double dv, val=finalTransform( buffer[bufstart], dv); getFinalValue()->set( val ); + for(unsigned i=0; iaddDerivative( i, dv*buffer[bufstart+1+i] ); } } -double FunctionVessel::finalTransform( const double& val, double& dv ){ +double FunctionVessel::finalTransform( const double& val, double& dv ) { dv=1.0; return val; } diff --git a/src/vesselbase/FunctionVessel.h b/src/vesselbase/FunctionVessel.h index 920d668b4c..b6fd05d559 100644 --- a/src/vesselbase/FunctionVessel.h +++ b/src/vesselbase/FunctionVessel.h @@ -29,13 +29,13 @@ #include "core/Value.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { /** \ingroup TOOLBOX Objects that inherit from FunctionVessel can be used (in tandem with PLMD::vesselbase::ActionWithVessel) to calculate functions of the form \f$\prod_k H_k[ \sum_j \prod_i g_i(x) ]\f$. They should take in a series of values -and return one single value. +and return one single value. */ class FunctionVessel : public ValueVessel { diff --git a/src/vesselbase/Highest.cpp b/src/vesselbase/Highest.cpp index 727a9fd950..437f681ec7 100644 --- a/src/vesselbase/Highest.cpp +++ b/src/vesselbase/Highest.cpp @@ -23,7 +23,7 @@ #include "VesselRegister.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class Highest : public OrderingVessel { public: @@ -31,30 +31,30 @@ class Highest : public OrderingVessel { static void reserveKeyword( Keywords& keys ); explicit Highest( const VesselOptions& da ); std::string value_descriptor(); - bool compare( const double& , const double& ); + bool compare( const double&, const double& ); }; PLUMED_REGISTER_VESSEL(Highest,"HIGHEST") -void Highest::registerKeywords( Keywords& keys ){ +void Highest::registerKeywords( Keywords& keys ) { OrderingVessel::registerKeywords( keys ); } -void Highest::reserveKeyword( Keywords& keys ){ +void Highest::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","HIGHEST","this flag allows you to recover the highest of these variables."); keys.addOutputComponent("highest","HIGHEST","the lowest of the quantitities calculated by this action"); } Highest::Highest( const VesselOptions& da ) : -OrderingVessel(da) + OrderingVessel(da) { } -std::string Highest::value_descriptor(){ +std::string Highest::value_descriptor() { return "the highest of the individual colvar values"; } -bool Highest::compare( const double& val1, const double& val2 ){ +bool Highest::compare( const double& val1, const double& val2 ) { return val1>val2; } diff --git a/src/vesselbase/Histogram.cpp b/src/vesselbase/Histogram.cpp index 2e3fae75d2..eb91f0ce2a 100644 --- a/src/vesselbase/Histogram.cpp +++ b/src/vesselbase/Histogram.cpp @@ -23,8 +23,8 @@ #include "VesselRegister.h" #include "ShortcutVessel.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { class Histogram : public ShortcutVessel { public: @@ -35,25 +35,25 @@ class Histogram : public ShortcutVessel { PLUMED_REGISTER_VESSEL(Histogram,"HISTOGRAM") -void Histogram::registerKeywords( Keywords& keys ){ +void Histogram::registerKeywords( Keywords& keys ) { ShortcutVessel::registerKeywords( keys ); HistogramBead::registerKeywords( keys ); keys.add("compulsory","NBINS","The number of equal width bins you want to divide the range into"); - keys.addFlag("NORM",false,"calculate the fraction of values rather than the number"); + keys.addFlag("NORM",false,"calculate the fraction of values rather than the number"); } -void Histogram::reserveKeyword( Keywords& keys ){ +void Histogram::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","HISTOGRAM","calculate a discretized histogram of the distribution of values. " - "This shortcut allows you to calculates NBIN quantites like BETWEEN."); + "This shortcut allows you to calculates NBIN quantites like BETWEEN."); } Histogram::Histogram( const VesselOptions& da ): -ShortcutVessel(da) + ShortcutVessel(da) { bool norm; parseFlag("NORM",norm); std::string normstr=""; if(norm) normstr=" NORM"; std::vector bins; HistogramBead::generateBins( getAllInput(), bins ); - for(unsigned i=0;iisPeriodic() ) error("LESS_THAN is not a meaningful option for periodic variables"); - std::string errormsg; sf.set( getAllInput(), errormsg ); - if( errormsg.size()!=0 ) error( errormsg ); + std::string errormsg; sf.set( getAllInput(), errormsg ); + if( errormsg.size()!=0 ) error( errormsg ); } -std::string LessThan::value_descriptor(){ +std::string LessThan::value_descriptor() { return "the number of values less than " + sf.description(); } @@ -58,7 +58,7 @@ double LessThan::calcTransform( const double& val, double& dv ) const { double f = sf.calculate(val, dv); dv*=val; return f; } -double LessThan::getCutoff(){ +double LessThan::getCutoff() { return sf.get_dmax(); } diff --git a/src/vesselbase/LessThan.h b/src/vesselbase/LessThan.h index 3a624788e1..f276f6e4a7 100644 --- a/src/vesselbase/LessThan.h +++ b/src/vesselbase/LessThan.h @@ -27,14 +27,14 @@ #include "ActionWithVessel.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class LessThan : public FunctionVessel { private: SwitchingFunction sf; public: static void registerKeywords( Keywords& keys ); - static void reserveKeyword( Keywords& keys ); + static void reserveKeyword( Keywords& keys ); explicit LessThan( const VesselOptions& da ); std::string value_descriptor(); double calcTransform( const double& val, double& dv ) const ; diff --git a/src/vesselbase/Lowest.cpp b/src/vesselbase/Lowest.cpp index bf8c5e63a6..9121543b78 100644 --- a/src/vesselbase/Lowest.cpp +++ b/src/vesselbase/Lowest.cpp @@ -23,7 +23,7 @@ #include "VesselRegister.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class Lowest : public OrderingVessel { public: @@ -31,30 +31,30 @@ class Lowest : public OrderingVessel { static void reserveKeyword( Keywords& keys ); explicit Lowest( const VesselOptions& da ); std::string value_descriptor(); - bool compare( const double& , const double& ); + bool compare( const double&, const double& ); }; PLUMED_REGISTER_VESSEL(Lowest,"LOWEST") -void Lowest::registerKeywords( Keywords& keys ){ +void Lowest::registerKeywords( Keywords& keys ) { OrderingVessel::registerKeywords( keys ); } -void Lowest::reserveKeyword( Keywords& keys ){ +void Lowest::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","LOWEST","this flag allows you to recover the lowest of these variables."); keys.addOutputComponent("lowest","LOWEST","the lowest of the quantitities calculated by this action"); } Lowest::Lowest( const VesselOptions& da ) : -OrderingVessel(da) + OrderingVessel(da) { } -std::string Lowest::value_descriptor(){ +std::string Lowest::value_descriptor() { return "the lowest of the individual colvar values"; } -bool Lowest::compare( const double& val1, const double& val2 ){ +bool Lowest::compare( const double& val1, const double& val2 ) { return val1isPeriodic() ) error("max is not a meaningful option for periodic variables"); parse("BETA",beta); @@ -64,7 +64,7 @@ FunctionVessel(da) if( diffweight ) error("can't calculate max if weight is differentiable"); } -std::string Max::value_descriptor(){ +std::string Max::value_descriptor() { std::string str_beta; Tools::convert( beta, str_beta ); return "the maximum value. Beta is equal to " + str_beta; } @@ -73,7 +73,7 @@ double Max::calcTransform( const double& val, double& dv ) const { double f = exp(val/beta); dv=f/beta; return f; } -double Max::finalTransform( const double& val, double& dv ){ +double Max::finalTransform( const double& val, double& dv ) { double dist=beta*std::log( val ); dv = beta/val; return dist; } diff --git a/src/vesselbase/Mean.cpp b/src/vesselbase/Mean.cpp index 9bcfe1aa79..d2979761b9 100644 --- a/src/vesselbase/Mean.cpp +++ b/src/vesselbase/Mean.cpp @@ -37,24 +37,24 @@ class Mean : public FunctionVessel { PLUMED_REGISTER_VESSEL(Mean,"MEAN") -void Mean::registerKeywords( Keywords& keys ){ +void Mean::registerKeywords( Keywords& keys ) { FunctionVessel::registerKeywords(keys); } -void Mean::reserveKeyword( Keywords& keys ){ +void Mean::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","MEAN","take the mean of these variables."); keys.addOutputComponent("mean","MEAN","the mean value. The output component can be refererred to elsewhere in the input " - "file by using the label.mean"); + "file by using the label.mean"); } Mean::Mean( const vesselbase::VesselOptions& da ) : -FunctionVessel(da) + FunctionVessel(da) { if( getAction()->isPeriodic() ) error("MEAN cannot be used with periodic variables"); norm=true; // Makes sure we calculate the average } -std::string Mean::value_descriptor(){ +std::string Mean::value_descriptor() { return "the mean value"; } diff --git a/src/vesselbase/Min.cpp b/src/vesselbase/Min.cpp index 73230f9c41..989ee34c61 100644 --- a/src/vesselbase/Min.cpp +++ b/src/vesselbase/Min.cpp @@ -24,7 +24,7 @@ #include "ActionWithVessel.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class Min : public FunctionVessel { private: @@ -40,22 +40,22 @@ class Min : public FunctionVessel { PLUMED_REGISTER_VESSEL(Min,"MIN") -void Min::registerKeywords( Keywords& keys ){ +void Min::registerKeywords( Keywords& keys ) { FunctionVessel::registerKeywords( keys ); keys.add("compulsory","BETA","the value of beta for the equation in the manual"); } -void Min::reserveKeyword( Keywords& keys ){ +void Min::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","MIN","calculate the minimum value. " - "To make this quantity continuous the minimum is calculated using " - "\\f$ \\textrm{min} = \\frac{\\beta}{ \\log \\sum_i \\exp\\left( \\frac{\\beta}{s_i} \\right) } \\f$ " - "The value of \\f$\\beta\\f$ in this function is specified using (BETA=\\f$\\beta\\f$)"); + "To make this quantity continuous the minimum is calculated using " + "\\f$ \\textrm{min} = \\frac{\\beta}{ \\log \\sum_i \\exp\\left( \\frac{\\beta}{s_i} \\right) } \\f$ " + "The value of \\f$\\beta\\f$ in this function is specified using (BETA=\\f$\\beta\\f$)"); keys.addOutputComponent("min","MIN","the minimum value. This is calculated using the formula described in the description of the " - "keyword so as to make it continuous."); + "keyword so as to make it continuous."); } Min::Min( const VesselOptions& da ) : -FunctionVessel(da) + FunctionVessel(da) { if( getAction()->isPeriodic() ) error("min is not a meaningful option for periodic variables"); parse("BETA",beta); @@ -63,17 +63,17 @@ FunctionVessel(da) if( diffweight ) error("can't calculate min if weight is differentiable"); } -std::string Min::value_descriptor(){ +std::string Min::value_descriptor() { std::string str_beta; Tools::convert( beta, str_beta ); return "the minimum value. Beta is equal to " + str_beta; } double Min::calcTransform( const double& val, double& dv ) const { double f = exp(beta/val); dv=f/(val*val); - return f; + return f; } -double Min::finalTransform( const double& val, double& dv ){ +double Min::finalTransform( const double& val, double& dv ) { double dist=beta/std::log( val ); dv = dist*dist/val; return dist; } diff --git a/src/vesselbase/Moments.cpp b/src/vesselbase/Moments.cpp index dc449b57f9..84d7e39190 100644 --- a/src/vesselbase/Moments.cpp +++ b/src/vesselbase/Moments.cpp @@ -24,10 +24,10 @@ #include "ActionWithVessel.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { -// This is not the most efficient implementation -// The calculation of all the colvars is parallelized +// This is not the most efficient implementation +// 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 StoreDataVessel { @@ -46,109 +46,109 @@ class Moments : public StoreDataVessel { PLUMED_REGISTER_VESSEL(Moments,"MOMENTS") -void Moments::registerKeywords( Keywords& keys ){ +void Moments::registerKeywords( Keywords& keys ) { StoreDataVessel::registerKeywords( keys ); } -void Moments::reserveKeyword( Keywords& keys ){ - keys.reserve("optional","MOMENTS","calculate the moments of the distribution of collective variables. " - "The \\f$m\\f$th moment of a distribution is calculated using \\f$\\frac{1}{N} \\sum_{i=1}^N ( s_i - \\overline{s} )^m \\f$, where \\f$\\overline{s}\\f$ is " - "the average for the distribution. The moments keyword takes a lists of integers as input or a range. Each integer is a value of \\f$m\\f$. The final " - "calculated values can be referenced using moment-\\f$m\\f$."); +void Moments::reserveKeyword( Keywords& keys ) { + keys.reserve("optional","MOMENTS","calculate the moments of the distribution of collective variables. " + "The \\f$m\\f$th moment of a distribution is calculated using \\f$\\frac{1}{N} \\sum_{i=1}^N ( s_i - \\overline{s} )^m \\f$, where \\f$\\overline{s}\\f$ is " + "the average for the distribution. The moments keyword takes a lists of integers as input or a range. Each integer is a value of \\f$m\\f$. The final " + "calculated values can be referenced using moment-\\f$m\\f$."); keys.reset_style("MOMENTS","vessel"); keys.addOutputComponent("moment","MOMENTS","the central moments of the distribution of values. The second moment " - "would be referenced elsewhere in the input file using " - "label.moment-2, the third as label.moment-3, etc."); + "would be referenced elsewhere in the input file using " + "label.moment-2, the third as label.moment-3, etc."); } Moments::Moments( const vesselbase::VesselOptions& da) : -StoreDataVessel(da) + StoreDataVessel(da) { - ActionWithValue* a=dynamic_cast( getAction() ); - plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); - - std::vector moments=Tools::getWords(getAllInput(),"\t\n ,"); - Tools::interpretRanges(moments); unsigned nn; - for(unsigned i=0;iaddComponentWithDerivatives( "moment-" + moments[i] ); - a->componentIsNotPeriodic( "moment-" + moments[i] ); - value_out.push_back( a->copyOutput( a->getNumberOfComponents()-1 ) ); - Tools::convert( moments[i], nn ); - if( nn<2 ) error("moments are only possible for m>=2" ); - powers.push_back( nn ); std::string num; Tools::convert(powers[i],num); - } + ActionWithValue* a=dynamic_cast( getAction() ); + plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); + + std::vector moments=Tools::getWords(getAllInput(),"\t\n ,"); + Tools::interpretRanges(moments); unsigned nn; + for(unsigned i=0; iaddComponentWithDerivatives( "moment-" + moments[i] ); + a->componentIsNotPeriodic( "moment-" + moments[i] ); + value_out.push_back( a->copyOutput( a->getNumberOfComponents()-1 ) ); + Tools::convert( moments[i], nn ); + if( nn<2 ) error("moments are only possible for m>=2" ); + powers.push_back( nn ); std::string num; Tools::convert(powers[i],num); + } } -void Moments::resize(){ - StoreDataVessel::resize(); +void Moments::resize() { + StoreDataVessel::resize(); } -std::string Moments::description(){ - std::string descri, num; - Tools::convert(powers[0],num); - descri = "value " + getAction()->getLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; - for(unsigned i=1;igetLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; - } - return descri; +std::string Moments::description() { + std::string descri, num; + Tools::convert(powers[0],num); + descri = "value " + getAction()->getLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; + for(unsigned i=1; igetLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; + } + return descri; } -void Moments::finish( const std::vector& buffer ){ +void Moments::finish( const std::vector& buffer ) { StoreDataVessel::finish( buffer ); const double pi=3.141592653589793238462643383279502884197169399375105820974944592307; - unsigned nvals=getAction()->getFullNumberOfTasks(); + unsigned nvals=getAction()->getFullNumberOfTasks(); double mean=0; Value myvalue; - if( getAction()->isPeriodic() ){ - std::string str_min, str_max; getAction()->retrieveDomain( str_min, str_max ); - 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 ) , cossum / static_cast( nvals ) ) / (2*pi); - mean = min + (max-min)*mean; + if( getAction()->isPeriodic() ) { + std::string str_min, str_max; getAction()->retrieveDomain( str_min, str_max ); + 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 ), cossum / static_cast( nvals ) ) / (2*pi); + mean = min + (max-min)*mean; } else { - for(unsigned i=0;i( nvals ); myvalue.setNotPeriodic(); + for(unsigned i=0; i( nvals ); myvalue.setNotPeriodic(); } - for(unsigned npow=0;npowgetNumberOfDerivatives()>0 ){ - for(unsigned i=0;i( nvals ); - } - - double moment=0; - MultiValue myvals( getNumberOfComponents(), getAction()->getNumberOfDerivatives() ); myvals.clearAll(); - for(unsigned i=0;igetNumberOfDerivatives() ){ - double pref=pow( tmp, powers[npow] - 1 ) - dev1; - retrieveDerivatives( i, false, myvals ); - for(unsigned j=0;jaddDerivative(jatom, pref*myvals.getDerivative( 1, jatom ) ); - } - myvals.clearAll(); - } - } - if( value_out[npow]->getNumberOfDerivatives()>0 ) value_out[npow]->chainRule( powers[npow] / static_cast( nvals ) ); - value_out[npow]->set( moment / static_cast( nvals ) ); + for(unsigned npow=0; npowgetNumberOfDerivatives()>0 ) { + for(unsigned i=0; i( nvals ); + } + + double moment=0; + MultiValue myvals( getNumberOfComponents(), getAction()->getNumberOfDerivatives() ); myvals.clearAll(); + for(unsigned i=0; igetNumberOfDerivatives() ) { + double pref=pow( tmp, powers[npow] - 1 ) - dev1; + retrieveDerivatives( i, false, myvals ); + for(unsigned j=0; jaddDerivative(jatom, pref*myvals.getDerivative( 1, jatom ) ); + } + myvals.clearAll(); + } + } + if( value_out[npow]->getNumberOfDerivatives()>0 ) value_out[npow]->chainRule( powers[npow] / static_cast( nvals ) ); + value_out[npow]->set( moment / static_cast( nvals ) ); } } -bool Moments::applyForce( std::vector& forces ){ +bool Moments::applyForce( std::vector& forces ) { std::vector tmpforce( forces.size() ); forces.assign(forces.size(),0.0); bool wasforced=false; - for(unsigned i=0;iapplyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; jisPeriodic() ) error("more than is not a meaningful option for periodic variables"); std::string errormsg; sf.set( getAllInput(), errormsg ); if( errormsg.size()!=0 ) error( errormsg ); } -std::string MoreThan::value_descriptor(){ +std::string MoreThan::value_descriptor() { return "the number of values more than " + sf.description(); } double MoreThan::calcTransform( const double& val, double& dv ) const { - double f = 1.0 - sf.calculate(val, dv); dv*=-val; return f; + double f = 1.0 - sf.calculate(val, dv); dv*=-val; return f; } } diff --git a/src/vesselbase/OrderingVessel.cpp b/src/vesselbase/OrderingVessel.cpp index 952dcb85d8..4eab917887 100644 --- a/src/vesselbase/OrderingVessel.cpp +++ b/src/vesselbase/OrderingVessel.cpp @@ -23,47 +23,47 @@ #include "core/ActionWithValue.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { -void OrderingVessel::registerKeywords( Keywords& keys ){ +void OrderingVessel::registerKeywords( Keywords& keys ) { ValueVessel::registerKeywords( keys ); } OrderingVessel::OrderingVessel( const VesselOptions& da ) : -ValueVessel(da) + ValueVessel(da) { mydata = getAction()->buildDataStashes( NULL ); - for(unsigned i=0;igetNumberOfVessels();++i){ - if( getAction()->getPntrToVessel(i)->getName()==getName() ) - error("calculating lowest/highest value multiple times serves no purpose"); + for(unsigned i=0; igetNumberOfVessels(); ++i) { + if( getAction()->getPntrToVessel(i)->getName()==getName() ) + error("calculating lowest/highest value multiple times serves no purpose"); } } -void OrderingVessel::resize(){ - resizeBuffer( 0 ); +void OrderingVessel::resize() { + resizeBuffer( 0 ); if( getAction()->derivativesAreRequired() ) getFinalValue()->resizeDerivatives( getAction()->getNumberOfDerivatives() ); } -void OrderingVessel::finish( const std::vector& buffer ){ +void OrderingVessel::finish( const std::vector& buffer ) { std::vector values( getAction()->getNumberOfQuantities() ); mydata->retrieveSequentialValue( 0, false, values ); double min=values[mycomp]; unsigned mini=getAction()->getPositionInFullTaskList(0); - for(unsigned i=1;igetNumberOfStoredValues();++i){ - mydata->retrieveSequentialValue( i, false, values ); - double newval = values[mycomp]; - if( compare( newval, min ) ){ min=newval; mini=getAction()->getPositionInFullTaskList(i); } + for(unsigned i=1; igetNumberOfStoredValues(); ++i) { + mydata->retrieveSequentialValue( i, false, values ); + double newval = values[mycomp]; + if( compare( newval, min ) ) { min=newval; mini=getAction()->getPositionInFullTaskList(i); } } setOutputValue( min ); - if( getAction()->derivativesAreRequired() ){ - MultiValue myvals( getAction()->getNumberOfQuantities(), getAction()->getNumberOfDerivatives() ); - mydata->retrieveDerivatives( mini, false, myvals ); Value* fval=getFinalValue(); - for(unsigned i=0;isetDerivative( ider, myvals.getDerivative(mycomp,ider) ); - } + if( getAction()->derivativesAreRequired() ) { + MultiValue myvals( getAction()->getNumberOfQuantities(), getAction()->getNumberOfDerivatives() ); + mydata->retrieveDerivatives( mini, false, myvals ); Value* fval=getFinalValue(); + for(unsigned i=0; isetDerivative( ider, myvals.getDerivative(mycomp,ider) ); + } } } diff --git a/src/vesselbase/OrderingVessel.h b/src/vesselbase/OrderingVessel.h index c3ec6d13c0..6e8fb93cc5 100644 --- a/src/vesselbase/OrderingVessel.h +++ b/src/vesselbase/OrderingVessel.h @@ -30,7 +30,7 @@ #include "core/Value.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class OrderingVessel : public ValueVessel { private: @@ -41,7 +41,7 @@ class OrderingVessel : public ValueVessel { void resize(); void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const {} void finish( const std::vector& buffer ); - virtual bool compare( const double& , const double& )=0; + virtual bool compare( const double&, const double& )=0; }; } diff --git a/src/vesselbase/ShortcutVessel.cpp b/src/vesselbase/ShortcutVessel.cpp index 41e64a5490..fc3be38c6f 100644 --- a/src/vesselbase/ShortcutVessel.cpp +++ b/src/vesselbase/ShortcutVessel.cpp @@ -22,23 +22,23 @@ #include "ShortcutVessel.h" #include "ActionWithVessel.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -void ShortcutVessel::registerKeywords( Keywords& keys ){ +void ShortcutVessel::registerKeywords( Keywords& keys ) { Vessel::registerKeywords( keys ); keys.remove("LABEL"); plumed_assert( keys.size()==0 ); } ShortcutVessel::ShortcutVessel( const VesselOptions& da): -Vessel(da) + Vessel(da) { } -void ShortcutVessel::addVessel( const std::string& name, const std::string& input ){ +void ShortcutVessel::addVessel( const std::string& name, const std::string& input ) { unsigned numlab=1; - for(unsigned i=0;i<(getAction()->functions).size();++i){ - if( (getAction()->functions[i])->getName()==name ) numlab++; + for(unsigned i=0; i<(getAction()->functions).size(); ++i) { + if( (getAction()->functions[i])->getName()==name ) numlab++; } getAction()->addVessel( name, input, numlab ); } diff --git a/src/vesselbase/ShortcutVessel.h b/src/vesselbase/ShortcutVessel.h index f84555205e..c6e66d76cf 100644 --- a/src/vesselbase/ShortcutVessel.h +++ b/src/vesselbase/ShortcutVessel.h @@ -29,19 +29,19 @@ #include "core/Value.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class ShortcutVessel : public Vessel { protected: - void addVessel( const std::string& name, const std::string& intput ); + void addVessel( const std::string& name, const std::string& intput ); public: static void registerKeywords( Keywords& keys ); explicit ShortcutVessel( const VesselOptions& ); - std::string description(){ return ""; } - void resize(){ plumed_error(); } + std::string description() { return ""; } + void resize() { plumed_error(); } void calculate( const unsigned& taskCode, MultiValue& myvals, std::vector& buffer, std::vector& der_index ) const { plumed_error(); } - void finish( const std::vector& buffer ){ plumed_error(); } - bool applyForce( std::vector& forces ){ plumed_error(); } + void finish( const std::vector& buffer ) { plumed_error(); } + bool applyForce( std::vector& forces ) { plumed_error(); } }; } diff --git a/src/vesselbase/StoreDataVessel.cpp b/src/vesselbase/StoreDataVessel.cpp index 13f4c9ab6f..a89c50d149 100644 --- a/src/vesselbase/StoreDataVessel.cpp +++ b/src/vesselbase/StoreDataVessel.cpp @@ -24,38 +24,38 @@ namespace PLMD { namespace vesselbase { -void StoreDataVessel::registerKeywords( Keywords& keys ){ +void StoreDataVessel::registerKeywords( Keywords& keys ) { Vessel::registerKeywords(keys); keys.remove("LABEL"); } StoreDataVessel::StoreDataVessel( const VesselOptions& da ): -Vessel(da), -max_lowmem_stash(3), -vecsize(0), -nspace(0) + Vessel(da), + max_lowmem_stash(3), + vecsize(0), + nspace(0) { ActionWithValue* myval=dynamic_cast( getAction() ); if( !myval ) hasderiv=false; else hasderiv=!myval->doNotCalculateDerivatives(); } -void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ){ +void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) { userActions.push_back( actionThatUses ); } -void StoreDataVessel::resize(){ +void StoreDataVessel::resize() { vecsize=getAction()->getNumberOfQuantities(); plumed_dbg_assert( vecsize>0 ); - if( getAction()->lowmem || !getAction()->derivativesAreRequired() ){ - nspace = 1; - active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); + if( getAction()->lowmem || !getAction()->derivativesAreRequired() ) { + nspace = 1; + active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); } else { - if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ){ - error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option"); - } - nspace = 1 + getAction()->maxderivatives; - active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); + if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ) { + error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option"); + } + nspace = 1 + getAction()->maxderivatives; + active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); } resizeBuffer( getNumberOfStoredValues()*vecsize*nspace ); local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace ); @@ -64,9 +64,9 @@ void StoreDataVessel::resize(){ void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector& buffer ) const { plumed_dbg_assert( vecsize>0 ); unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); plumed_dbg_assert( jelem0 && getAction()->derivativesAreRequired() && myelemgetFullNumberOfTasks() ); unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); - if( getAction()->getFullNumberOfTasks()==getNumberOfStoredValues() ){ - der_list[jelem]=myvals.getNumberActive(); - unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); - for(unsigned j=0;jgetFullNumberOfTasks()==getNumberOfStoredValues() ) { + der_list[jelem]=myvals.getNumberActive(); + unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); + for(unsigned j=0; j& values ) const { plumed_assert( values.size()==vecsize ); unsigned ibuf = jelem * vecsize * nspace; - for(unsigned i=0;i2 ) getAction()->normalizeVector( values ); + for(unsigned i=0; i2 ) getAction()->normalizeVector( values ); } void StoreDataVessel::retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector& values ) const { @@ -119,60 +119,60 @@ double StoreDataVessel::retrieveWeightWithIndex( const unsigned& myelem ) const unsigned jelem = getStoreIndex( myelem ); unsigned ibuf = jelem * vecsize * nspace; return local_buffer[ibuf]; } -void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ){ +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 ){ - recalculateStoredQuantity( myelem, myvals ); - if( normed ) getAction()->normalizeVectorDerivatives( myvals ); + if( getAction()->lowmem ) { + recalculateStoredQuantity( myelem, myvals ); + if( normed ) getAction()->normalizeVectorDerivatives( myvals ); } else { - unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); - // Retrieve the derivatives for elements 0 and 1 - weight and norm - for(unsigned icomp=0;icompnormalizeVectorDerivatives( myvals ); - // Now ensure appropriate parts of list are activated - myvals.emptyActiveMembers(); + unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); + // Retrieve the derivatives for elements 0 and 1 - weight and norm + for(unsigned icomp=0; icompnormalizeVectorDerivatives( myvals ); + // Now ensure appropriate parts of list are activated + myvals.emptyActiveMembers(); + unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); + for(unsigned j=0; j& buffer, std::vector& der_list ) const { - if( myvals.get(0)>epsilon ){ - storeValues( current, myvals, buffer ); - if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer, der_list ); - } + if( myvals.get(0)>epsilon ) { + storeValues( current, myvals, buffer ); + if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer, der_list ); + } return; } -void StoreDataVessel::finish( const std::vector& buffer ){ +void StoreDataVessel::finish( const std::vector& buffer ) { // Store the buffer locally - for(unsigned i=0;i& der_index ){ - if( !getAction()->lowmem && getAction()->derivativesAreRequired() ){ - for(unsigned i=0;i& der_index ) { + if( !getAction()->lowmem && getAction()->derivativesAreRequired() ) { + for(unsigned i=0; i active_val; /// The active derivative elements std::vector active_der; /// The buffer - std::vector local_buffer; + std::vector local_buffer; /// The actions that are going to use the stored data - std::vector userActions; -/// We create a vector of tempory MultiValues here so as to avoid + std::vector userActions; +/// We create a vector of tempory MultiValues here so as to avoid /// lots of vector resizing - unsigned tmp_index; - std::vector my_tmp_vals; + unsigned tmp_index; + std::vector my_tmp_vals; protected: /// Is the weight differentiable bool weightHasDerivatives(); @@ -69,13 +69,13 @@ friend class Moments; bool usingLowMem(); /// Finish the setup of the storage object by setting how much /// data has to be stored - void completeSetup( const unsigned& , const unsigned& ); + void completeSetup( const unsigned&, const unsigned& ); /// Return value of nspace unsigned getNumberOfDerivativeSpacesPerComponent() const ; /// Retrieve the values from the underlying ActionWithVessel - void storeValues( const unsigned& , MultiValue& , std::vector& ) const ; + void storeValues( const unsigned&, MultiValue&, std::vector& ) const ; /// This stores the data we get from the calculation - void storeDerivatives( const unsigned& , MultiValue& myvals, std::vector&, std::vector& ) const ; + void storeDerivatives( const unsigned&, MultiValue& myvals, std::vector&, std::vector& ) const ; /// Get the ibuf'th local derivative value double getLocalDerivative( const unsigned& ibuf ); /// Set the ibuf'th local derivative value @@ -93,7 +93,7 @@ friend class Moments; void recalculateStoredQuantity( const unsigned& myelm, MultiValue& myvals ); /// Set a hard cutoff on the weight of an element void setHardCutoffOnWeight( const double& mytol ); -/// Add an action that uses this data +/// Add an action that uses this data void addActionThatUses( ActionWithVessel* actionThatUses ); /// Return the number of components in the vector unsigned getNumberOfComponents() const { return vecsize; } @@ -106,7 +106,7 @@ friend class Moments; /// Do all resizing of data virtual void resize(); /// - virtual std::string description(){ return ""; } + virtual std::string description() { return ""; } /// Get the number of derivatives for the ith value unsigned getNumberOfDerivatives( const unsigned& ); /// Get the size of the derivative list @@ -116,13 +116,13 @@ friend class Moments; /// Final step in gathering data virtual void finish( const std::vector& buffer ); /// Is a particular stored value active at the present time - bool storedValueIsActive( const unsigned& iatom ) const ; + bool storedValueIsActive( const unsigned& iatom ) const ; /// Set the active values void setActiveValsAndDerivatives( const std::vector& der_index ); /// Activate indexes (this is used at end of chain rule) - virtual void activateIndices( ActionWithVessel* ){} + virtual void activateIndices( ActionWithVessel* ) {} /// Forces on vectors should always be applied elsewhere - virtual bool applyForce(std::vector&){ return false; } + virtual bool applyForce(std::vector&) { return false; } /// Get the number of data users unsigned getNumberOfDataUsers() const ; /// Get one of the ith data user @@ -134,12 +134,12 @@ friend class Moments; }; inline -bool StoreDataVessel::weightHasDerivatives(){ +bool StoreDataVessel::weightHasDerivatives() { return getAction()->weightHasDerivatives; } inline -bool StoreDataVessel::usingLowMem(){ +bool StoreDataVessel::usingLowMem() { return getAction()->lowmem; } @@ -153,7 +153,7 @@ bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ) const { if( !getAction()->taskIsCurrentlyActive( iatom ) ) return false; unsigned jatom = getStoreIndex( iatom ); plumed_dbg_assert( jatomepsilon; + return local_buffer[jatom*vecsize*nspace]>epsilon; } inline @@ -172,12 +172,12 @@ unsigned StoreDataVessel::getStoreIndex( const unsigned& ind ) const { // Binary search for required element - faster scaling than sequential search unsigned l=0, r=getAction()->nactive_tasks-1; - for(unsigned i=0;inactive_tasks;++i){ - plumed_assert( l<=r ); - unsigned m = std::floor( (l + r)/2 ); - if( ind==getAction()->indexOfTaskInFullList[m] ) return m; - else if( getAction()->indexOfTaskInFullList[m]indexOfTaskInFullList[m]>ind ) r=m-1; + for(unsigned i=0; inactive_tasks; ++i) { + plumed_assert( l<=r ); + unsigned m = std::floor( (l + r)/2 ); + if( ind==getAction()->indexOfTaskInFullList[m] ) return m; + else if( getAction()->indexOfTaskInFullList[m]indexOfTaskInFullList[m]>ind ) r=m-1; } plumed_merror("requested task is not active"); } @@ -188,7 +188,7 @@ unsigned StoreDataVessel::getTrueIndex( const unsigned& ind ) const { } inline -void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ){ +void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ) { getAction()->performTask( myelem, getAction()->getTaskCode(myelem), myvals ); } @@ -198,7 +198,7 @@ unsigned StoreDataVessel::getNumberOfDataUsers() const { } inline -ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ){ +ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ) { plumed_dbg_assert( idata( getAction() ); plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); int numval = getNumericalLabel(); - if( numval<0 && a->getNumberOfComponents()==0 ){ // This allows us to make multicolvars pretend to be colvars - this is used in AlphaRMSD etc - a->addValueWithDerivatives(); - a->setNotPeriodic(); - final_value=a->copyOutput( a->getNumberOfComponents()-1 ); - } else if( numval<0 ){ - no_output_value=true; final_value=new Value(); final_value->setNotPeriodic(); + if( numval<0 && a->getNumberOfComponents()==0 ) { // This allows us to make multicolvars pretend to be colvars - this is used in AlphaRMSD etc + a->addValueWithDerivatives(); + a->setNotPeriodic(); + final_value=a->copyOutput( a->getNumberOfComponents()-1 ); + } else if( numval<0 ) { + no_output_value=true; final_value=new Value(); final_value->setNotPeriodic(); } else { - plumed_massert( !a->exists(getAction()->getLabel() + "." + getLabel() ), "you can't create the name multiple times"); - a->addComponentWithDerivatives( getLabel() ); - a->componentIsNotPeriodic( getLabel() ); - final_value=a->copyOutput( a->getNumberOfComponents()-1 ); + plumed_massert( !a->exists(getAction()->getLabel() + "." + getLabel() ), "you can't create the name multiple times"); + a->addComponentWithDerivatives( getLabel() ); + a->componentIsNotPeriodic( getLabel() ); + final_value=a->copyOutput( a->getNumberOfComponents()-1 ); } } -ValueVessel::~ValueVessel(){ +ValueVessel::~ValueVessel() { if( no_output_value ) delete final_value; } -std::string ValueVessel::description(){ +std::string ValueVessel::description() { if( final_value->getName()==getAction()->getLabel() ) return "value " + getAction()->getLabel() + " contains " + value_descriptor(); return "value " + getAction()->getLabel() + "." + getLabel() + " contains " + value_descriptor(); } -bool ValueVessel::applyForce( std::vector& forces ){ +bool ValueVessel::applyForce( std::vector& forces ) { std::vector tmpforce( forces.size() ); forces.assign(forces.size(),0.0); bool wasforced=false; - if( final_value->applyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; j& forces ); @@ -63,7 +63,7 @@ double ValueVessel::getOutputValue() const { } inline -void ValueVessel::setOutputValue( const double& val ){ +void ValueVessel::setOutputValue( const double& val ) { final_value->set( val ); } diff --git a/src/vesselbase/Vessel.cpp b/src/vesselbase/Vessel.cpp index deec8b036d..4ce9e10a05 100644 --- a/src/vesselbase/Vessel.cpp +++ b/src/vesselbase/Vessel.cpp @@ -26,66 +26,66 @@ #include "tools/Log.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { Keywords VesselOptions::emptyKeys; VesselOptions::VesselOptions(const std::string& thisname, const std::string& thislab, const unsigned& nlab, const std::string& params, ActionWithVessel* aa ): -myname(thisname), -mylabel(thislab), -numlab(nlab), -action(aa), -keywords(emptyKeys), -parameters(params) + myname(thisname), + mylabel(thislab), + numlab(nlab), + action(aa), + keywords(emptyKeys), + parameters(params) { } VesselOptions::VesselOptions(const VesselOptions& da, const Keywords& keys ): -myname(da.myname), -mylabel(da.mylabel), -numlab(da.numlab), -action(da.action), -keywords(keys), -parameters(da.parameters) + myname(da.myname), + mylabel(da.mylabel), + numlab(da.numlab), + action(da.action), + keywords(keys), + parameters(da.parameters) { } -void Vessel::registerKeywords( Keywords& keys ){ +void Vessel::registerKeywords( Keywords& keys ) { plumed_assert( keys.size()==0 ); keys.add("optional","LABEL","the label used to reference this particular quantity"); } -std::string Vessel::transformName( const std::string& name ){ - std::string tlabel=name; - // Convert to lower case - std::transform( tlabel.begin(), tlabel.end(), tlabel.begin(), tolower ); - // Remove any underscore characters (as these are reserved) - for(unsigned i=0;;++i){ - std::size_t num=tlabel.find_first_of("_"); - if( num==std::string::npos ) break; - tlabel.erase( tlabel.begin() + num, tlabel.begin() + num + 1 ); - } - return tlabel; +std::string Vessel::transformName( const std::string& name ) { + std::string tlabel=name; + // Convert to lower case + std::transform( tlabel.begin(), tlabel.end(), tlabel.begin(), tolower ); + // Remove any underscore characters (as these are reserved) + for(unsigned i=0;; ++i) { + std::size_t num=tlabel.find_first_of("_"); + if( num==std::string::npos ) break; + tlabel.erase( tlabel.begin() + num, tlabel.begin() + num + 1 ); + } + return tlabel; } Vessel::Vessel( const VesselOptions& da ): -myname(da.myname), -numlab(da.numlab), -action(da.action), -line(Tools::getWords( da.parameters )), -keywords(da.keywords), -finished_read(false), -comm(da.action->comm), -log((da.action)->log) + myname(da.myname), + numlab(da.numlab), + action(da.action), + line(Tools::getWords( da.parameters )), + keywords(da.keywords), + finished_read(false), + comm(da.action->comm), + log((da.action)->log) { - if( da.mylabel.length()>0){ - mylabel=da.mylabel; + if( da.mylabel.length()>0) { + mylabel=da.mylabel; } else { - if( keywords.exists("LABEL") ) parse("LABEL",mylabel); - if( mylabel.length()==0 && numlab>=0 ){ - mylabel=transformName( myname ); std::string nn; - if(numlab>0){ Tools::convert( numlab, nn ); mylabel = mylabel + "-" + nn; } - } + if( keywords.exists("LABEL") ) parse("LABEL",mylabel); + if( mylabel.length()==0 && numlab>=0 ) { + mylabel=transformName( myname ); std::string nn; + if(numlab>0) { Tools::convert( numlab, nn ); mylabel = mylabel + "-" + nn; } + } } } @@ -97,37 +97,37 @@ std::string Vessel::getLabel() const { return mylabel; } -std::string Vessel::getAllInput(){ +std::string Vessel::getAllInput() { std::string fullstring; - for(unsigned i=0;i0 ) log.printf(" %s\n", describe.c_str() ); } -void Vessel::error( const std::string& msg ){ +void Vessel::error( const std::string& msg ) { action->log.printf("ERROR for keyword %s in action %s with label %s : %s \n \n",myname.c_str(), (action->getName()).c_str(), (action->getLabel()).c_str(), msg.c_str() ); if(finished_read) keywords.print( log ); plumed_merror("ERROR for keyword " + myname + " in action " + action->getName() + " with label " + action->getLabel() + " : " + msg ); diff --git a/src/vesselbase/Vessel.h b/src/vesselbase/Vessel.h index f193e264c0..ab96f3f41a 100644 --- a/src/vesselbase/Vessel.h +++ b/src/vesselbase/Vessel.h @@ -30,26 +30,26 @@ #include "tools/Keywords.h" #include "ActionWithVessel.h" -namespace PLMD{ +namespace PLMD { class Communicator; class Log; -namespace vesselbase{ +namespace vesselbase { /** \ingroup TOOLBOX Vessels are an important component of class PLMD::ActionWithVessel. This class contains a large buffer array of doubles. The various elements of this array can be accessed through vessels which are used to structure the elements of the -double array. As the buffer array is just a vector of doubles it can be easily -mpi gathered or passed to another node. +double array. As the buffer array is just a vector of doubles it can be easily +mpi gathered or passed to another node. */ //class ActionWithVessel; class Vessel; -/// This class is used to pass the input to Vessels +/// This class is used to pass the input to Vessels class VesselOptions { friend class Vessel; private: @@ -67,13 +67,13 @@ class VesselOptions { public: /// The parameters that are read into the function std::string parameters; -/// The constructor +/// The constructor VesselOptions( const std::string& thisname, const std::string& thislab, const unsigned& nlab, const std::string& params, ActionWithVessel* aa ); VesselOptions(const VesselOptions& da, const Keywords& keys ); }; class Vessel { -friend class ActionWithVessel; + friend class ActionWithVessel; private: /// The keyword for the vessel in the input file std::string myname; @@ -100,7 +100,7 @@ friend class ActionWithVessel; Communicator& comm; /// Return the numerical label int getNumericalLabel() const ; -/// Report an error +/// Report an error void error(const std::string& errmsg); /// Parse something from the input template @@ -111,7 +111,7 @@ friend class ActionWithVessel; /// Parse one keyword as boolean flag void parseFlag(const std::string&key,bool&t); /// This returns the whole input line (it is used for less_than/more_than/between) - std::string getAllInput(); + std::string getAllInput(); /// Return a pointer to the action we are working in ActionWithVessel* getAction() const ; /// Return the value of the tolerance @@ -125,14 +125,14 @@ friend class ActionWithVessel; public: /// Reference to the log on which to output details Log& log; -/// Reserve any keywords for this particular vessel +/// Reserve any keywords for this particular vessel static void registerKeywords( Keywords& keys ); /// Convert the name to the label of the component static std::string transformName( const std::string& name ); /// The constructor explicit Vessel( const VesselOptions& da ); /// Virtual destructor needed for proper inheritance - virtual ~Vessel(){} + virtual ~Vessel() {} /// Return the name std::string getName() const ; /// Return the label @@ -142,9 +142,9 @@ friend class ActionWithVessel; /// Return a description of the vessel contents virtual std::string description()=0; /// Set the start of the buffer - virtual void setBufferStart( unsigned& start ); + virtual void setBufferStart( unsigned& start ); /// Do something before the loop - virtual void prepare(){} + 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 @@ -158,22 +158,22 @@ friend class ActionWithVessel; }; template -void Vessel::parse(const std::string&key, T&t ){ +void Vessel::parse(const std::string&key, T&t ) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); // Now try to read the keyword bool found=Tools::parse(line,key,t); std::string def; - if ( !found && keywords.style(key,"compulsory") ){ - if( keywords.getDefaultValue(key,def) ){ - plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious"); - } else { - error("keyword " + key + " is comulsory for this vessel"); - } + if ( !found && keywords.style(key,"compulsory") ) { + if( keywords.getDefaultValue(key,def) ) { + plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious"); + } else { + error("keyword " + key + " is comulsory for this vessel"); + } } } template -void Vessel::parseVector(const std::string&key,std::vector&t){ +void Vessel::parseVector(const std::string&key,std::vector&t) { // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); unsigned size=t.size(); bool skipcheck=false; @@ -184,23 +184,23 @@ void Vessel::parseVector(const std::string&key,std::vector&t){ found=Tools::parseVector(line,key,t); // Check vectors size is correct (not if this is atoms or ARG) - if( !keywords.style(key,"atoms") && found ){ - if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); + if( !keywords.style(key,"atoms") && found ) { + if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); } - // If it isn't read and it is compulsory see if a default value was specified - if ( !found && keywords.style(key,"compulsory") ){ - if( keywords.getDefaultValue(key,def) ){ - if( def.length()==0 || !Tools::convert(def,val) ){ - plumed_merror("weird default value for keyword " + key ); - } else { - for(unsigned i=0;i -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -VesselRegister::~VesselRegister(){ - if(m.size()>0){ +VesselRegister::~VesselRegister() { + if(m.size()>0) { std::string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: Vessel "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -VesselRegister& vesselRegister(){ +VesselRegister& vesselRegister() { static VesselRegister ans; return ans; } -void VesselRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void VesselRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void VesselRegister::add(std::string keyword,creator_pointer f,keyword_pointer k,keyword_pointer ik){ +void VesselRegister::add(std::string keyword,creator_pointer f,keyword_pointer k,keyword_pointer ik) { plumed_massert(m.count(keyword)==0,"keyword has already been registered"); m.insert(std::pair(keyword,f)); k( keywords ); // Store the keywords for all the things @@ -57,24 +57,24 @@ void VesselRegister::add(std::string keyword,creator_pointer f,keyword_pointer k mk.insert(std::pair(keyword,ik)); } -bool VesselRegister::check(std::string key){ +bool VesselRegister::check(std::string key) { if( m.count(key)>0 ) return true; return false; } -Vessel* VesselRegister::create(std::string keyword, const VesselOptions&da){ +Vessel* VesselRegister::create(std::string keyword, const VesselOptions&da) { Vessel* df; - if(check(keyword)){ - Keywords keys; mk[keyword](keys); - VesselOptions nda( da,keys ); - df=m[keyword](nda); - keys.destroyData(); + if(check(keyword)) { + Keywords keys; mk[keyword](keys); + VesselOptions nda( da,keys ); + df=m[keyword](nda); + keys.destroyData(); } else df=NULL; return df; } -Keywords VesselRegister::getKeywords(){ +Keywords VesselRegister::getKeywords() { return keywords; } diff --git a/src/vesselbase/VesselRegister.h b/src/vesselbase/VesselRegister.h index 4aea38e0b9..a2bd24a20c 100644 --- a/src/vesselbase/VesselRegister.h +++ b/src/vesselbase/VesselRegister.h @@ -29,13 +29,13 @@ #include "tools/Exception.h" #include "tools/Keywords.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { class Vessel; class VesselOptions; -class VesselRegister{ +class VesselRegister { private: /// Pointer to a function which, given the keyword for a distribution function, creates it typedef Vessel*(*creator_pointer)(const VesselOptions&); diff --git a/src/wrapper/Plumed.c b/src/wrapper/Plumed.c index 7aa2b20eb1..75d9a9280b 100644 --- a/src/wrapper/Plumed.c +++ b/src/wrapper/Plumed.c @@ -32,7 +32,7 @@ /* DECLARATION USED ONLY IN THIS FILE */ #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -62,7 +62,7 @@ void plumed_dummy_finalize(void*); #endif #ifdef __cplusplus - } +} #endif /* END OF DECLARATION USED ONLY IN THIS FILE */ @@ -79,11 +79,11 @@ static int installed=0; static int dummy; -void*plumed_dummy_create(void){ +void*plumed_dummy_create(void) { return (void*)&dummy; } -void plumed_dummy_cmd(void*p,const char*key,const void*val){ +void plumed_dummy_cmd(void*p,const char*key,const void*val) { (void) p; /* avoid warning on unused parameter */ (void) key; /* avoid warning on unused parameter */ (void) val; /* avoid warning on unused parameter */ @@ -92,59 +92,59 @@ void plumed_dummy_cmd(void*p,const char*key,const void*val){ exit(1); } -void plumed_dummy_finalize(void*p){ +void plumed_dummy_finalize(void*p) { (void) p; /* avoid warning on unused parameter */ } #endif -plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f){ +plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f) { #ifdef __PLUMED_STATIC_KERNEL -/* - When __PLUMED_STATIC_KERNEL is defined, the function holder is initialized - to statically bound plumedmain_create,plumedmain_cmd,plumedmain_finalize and - cannot be changed. This saves from mis-set values for PLUMED_KERNEL -*/ - static plumed_plumedmain_function_holder g={plumedmain_create,plumedmain_cmd,plumedmain_finalize}; + /* + When __PLUMED_STATIC_KERNEL is defined, the function holder is initialized + to statically bound plumedmain_create,plumedmain_cmd,plumedmain_finalize and + cannot be changed. This saves from mis-set values for PLUMED_KERNEL + */ + static plumed_plumedmain_function_holder g= {plumedmain_create,plumedmain_cmd,plumedmain_finalize}; (void) f; /* avoid warning on unused parameter */ return &g; #else -/* - On the other hand, for runtime binding, we allow to reset the function holder on the - first call to plumed_kernel_register. - Notice that in principle plumed_kernel_register is entered *twice*: one for the first - plumed usage, and then from the PlumedMainInitializer object of the shared library. - This is why we set "first=0" only *after* loading the shared library. - Also notice that we should put some guard here for safe multithread calculations. -*/ - static plumed_plumedmain_function_holder g={plumed_dummy_create,plumed_dummy_cmd,plumed_dummy_finalize}; + /* + On the other hand, for runtime binding, we allow to reset the function holder on the + first call to plumed_kernel_register. + Notice that in principle plumed_kernel_register is entered *twice*: one for the first + plumed usage, and then from the PlumedMainInitializer object of the shared library. + This is why we set "first=0" only *after* loading the shared library. + Also notice that we should put some guard here for safe multithread calculations. + */ + static plumed_plumedmain_function_holder g= {plumed_dummy_create,plumed_dummy_cmd,plumed_dummy_finalize}; static int first=1; #ifdef __PLUMED_HAS_DLOPEN char* path; void* p; - if(first && f==NULL){ + if(first && f==NULL) { path=getenv("PLUMED_KERNEL"); #ifdef __PLUMED_DEFAULT_KERNEL -/* - This variable allows a default path for the kernel to be hardcoded. - Can be useful for hardcoding the predefined plumed location - still allowing the user to override this choice setting PLUMED_KERNEL. - The path should be chosen at compile time adding e.g. - -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib -*/ -/* This is required to add quotes */ + /* + This variable allows a default path for the kernel to be hardcoded. + Can be useful for hardcoding the predefined plumed location + still allowing the user to override this choice setting PLUMED_KERNEL. + The path should be chosen at compile time adding e.g. + -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib + */ + /* This is required to add quotes */ #define PLUMED_QUOTE_DIRECT(name) #name #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro) if(! (path && (*path) )) path=PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL); #endif - if(path && (*path)){ + if(path && (*path)) { fprintf(stderr,"+++ Loading the PLUMED kernel runtime +++\n"); fprintf(stderr,"+++ PLUMED_KERNEL=\"%s\" +++\n",path); p=dlopen(path,RTLD_NOW|RTLD_GLOBAL); - if(p){ + if(p) { fprintf(stderr,"+++ PLUMED kernel successfully loaded +++\n"); installed=1; - } else{ + } else { fprintf(stderr,"+++ PLUMED kernel not found ! +++\n"); fprintf(stderr,"+++ error message from dlopen(): %s\n",dlerror()); } @@ -159,7 +159,7 @@ plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmai /* C wrappers: */ -plumed plumed_create(void){ +plumed plumed_create(void) { plumed p; plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL); assert(h); @@ -169,7 +169,7 @@ plumed plumed_create(void){ return p; } -void plumed_cmd(plumed p,const char*key,const void*val){ +void plumed_cmd(plumed p,const char*key,const void*val) { plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL); assert(p.p); assert(h); @@ -177,7 +177,7 @@ void plumed_cmd(plumed p,const char*key,const void*val){ (*(h->cmd))(p.p,key,val); } -void plumed_finalize(plumed p){ +void plumed_finalize(plumed p) { plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL); assert(p.p); assert(h); @@ -186,63 +186,63 @@ void plumed_finalize(plumed p){ p.p=NULL; } -int plumed_installed(void){ +int plumed_installed(void) { plumed_kernel_register(NULL); return installed; } /* we declare a Plumed_g_main object here, in such a way that it is always available */ -static plumed gmain={NULL}; +static plumed gmain= {NULL}; -plumed plumed_global(void){ +plumed plumed_global(void) { return gmain; } -void plumed_gcreate(void){ +void plumed_gcreate(void) { assert(gmain.p==NULL); gmain=plumed_create(); } -void plumed_gcmd(const char*key,const void*val){ +void plumed_gcmd(const char*key,const void*val) { assert(gmain.p); plumed_cmd(gmain,key,val); } -void plumed_gfinalize(void){ +void plumed_gfinalize(void) { assert(gmain.p); plumed_finalize(gmain); gmain.p=NULL; } -int plumed_ginitialized(void){ +int plumed_ginitialized(void) { if(gmain.p) return 1; else return 0; } -void plumed_c2f(plumed p,char*c){ +void plumed_c2f(plumed p,char*c) { unsigned i; unsigned char* cc; -/* - Convert the address stored in p.p into a proper FORTRAN string - made of only ASCII characters. For this to work, the two following - assertions should be satisfied: -*/ + /* + Convert the address stored in p.p into a proper FORTRAN string + made of only ASCII characters. For this to work, the two following + assertions should be satisfied: + */ assert(CHAR_BIT<=12); assert(sizeof(p.p)<=16); assert(c); cc=(unsigned char*)&p.p; - for(i=0;i 199711L - but not supporting move semantics. Hopefully will not happen! -*/ + /* + PLUMED 2.4 requires a C++11 compiler. + Anyway, since Plumed.h file might be redistributed with other codes + and it should be possible to combine it with earlier PLUMED versions, + we here explicitly check if C+11 is available before enabling move semantics. + This could still create problems if a compiler 'cheats', setting __cplusplus > 199711L + but not supporting move semantics. Hopefully will not happen! + */ #if __cplusplus > 199711L -/** Move constructor. - Only if move semantics is enabled. - It allows storing PLMD::Plumed objects in STL containers. -*/ + /** Move constructor. + Only if move semantics is enabled. + It allows storing PLMD::Plumed objects in STL containers. + */ Plumed(Plumed&&); -/** Move assignment. - Only if move semantics is enabled. -*/ + /** Move assignment. + Only if move semantics is enabled. + */ Plumed& operator=(Plumed&&); #endif -/** - Retrieve the C plumed structure for this object -*/ + /** + Retrieve the C plumed structure for this object + */ operator plumed()const; -/** - Retrieve a FORTRAN handler for this object - \param c The FORTRAN handler (a char[32]). -*/ + /** + Retrieve a FORTRAN handler for this object + \param c The FORTRAN handler (a char[32]). + */ void toFortran(char*c)const; -/** - Send a command to this plumed object - \param key The name of the command to be executed - \param val The argument. It is declared as const to allow calls like p.cmd("A","B"), - but for some choice of key it can change the content - \note Equivalent to plumed_cmd() -*/ + /** + Send a command to this plumed object + \param key The name of the command to be executed + \param val The argument. It is declared as const to allow calls like p.cmd("A","B"), + but for some choice of key it can change the content + \note Equivalent to plumed_cmd() + */ void cmd(const char*key,const void*val=NULL); -/** - Destructor - - Destructor is virtual so as to allow correct inheritance from Plumed object. - To avoid linking problems with g++, I specify "inline" also here (in principle - it should be enough to specify it down in the definition of the function, but - for some reason that I do not understand g++ does not inline it properly in that - case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the - way it is done here seems to work properly). -*/ + /** + Destructor + + Destructor is virtual so as to allow correct inheritance from Plumed object. + To avoid linking problems with g++, I specify "inline" also here (in principle + it should be enough to specify it down in the definition of the function, but + for some reason that I do not understand g++ does not inline it properly in that + case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the + way it is done here seems to work properly). + */ inline virtual ~Plumed(); }; /* All methods are inlined so as to avoid the compilation of an extra c++ file */ inline -bool Plumed::installed(){ +bool Plumed::installed() { return plumed_installed(); } @@ -517,7 +517,7 @@ Plumed::Plumed(Plumed&& p): {} inline -Plumed& Plumed::operator=(Plumed&& p){ +Plumed& Plumed::operator=(Plumed&& p) { main=p.main; reference=p.reference; return *this; @@ -525,47 +525,47 @@ Plumed& Plumed::operator=(Plumed&& p){ #endif inline -Plumed::operator plumed()const{ +Plumed::operator plumed()const { return main; } inline -void Plumed::toFortran(char*c)const{ +void Plumed::toFortran(char*c)const { plumed_c2f(main,c); } inline -void Plumed::cmd(const char*key,const void*val){ +void Plumed::cmd(const char*key,const void*val) { plumed_cmd(main,key,val); } inline -Plumed::~Plumed(){ +Plumed::~Plumed() { if(!reference)plumed_finalize(main); } inline -bool Plumed::ginitialized(){ +bool Plumed::ginitialized() { return plumed_ginitialized(); } inline -void Plumed::gcreate(){ +void Plumed::gcreate() { plumed_gcreate(); } inline -void Plumed::gcmd(const char* key,const void* val){ +void Plumed::gcmd(const char* key,const void* val) { plumed_gcmd(key,val); } inline -void Plumed::gfinalize(){ +void Plumed::gfinalize() { plumed_gfinalize(); } inline -Plumed Plumed::global(){ +Plumed Plumed::global() { return plumed_global(); }