From 7db807933c692a2d87ec0783f67b9b375cadb2d0 Mon Sep 17 00:00:00 2001 From: Daniele Rapetti <5535617+Iximiel@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:01:52 +0200 Subject: [PATCH] Applying the new style to adjmat --- src/adjmat/ActionWithInputMatrix.cpp | 54 ++++++++----- src/adjmat/ActionWithInputMatrix.h | 8 +- src/adjmat/AdjacencyMatrixBase.cpp | 105 +++++++++++++++++-------- src/adjmat/AdjacencyMatrixBase.h | 11 ++- src/adjmat/AdjacencyMatrixVessel.cpp | 77 +++++++++++++------ src/adjmat/AlignedMatrixBase.cpp | 36 ++++++--- src/adjmat/ClusterAnalysisBase.cpp | 24 ++++-- src/adjmat/ClusterAnalysisBase.h | 4 +- src/adjmat/ClusterDiameter.cpp | 22 ++++-- src/adjmat/ClusterDistribution.cpp | 49 ++++++++---- src/adjmat/ClusterProperties.cpp | 48 ++++++++---- src/adjmat/ClusterSize.cpp | 23 ++++-- src/adjmat/ClusterWithSurface.cpp | 45 +++++++---- src/adjmat/ClusteringBase.cpp | 28 +++++-- src/adjmat/ContactAlignedMatrix.cpp | 21 +++-- src/adjmat/ContactMatrix.cpp | 22 ++++-- src/adjmat/DFSClustering.cpp | 35 ++++++--- src/adjmat/DumpGraph.cpp | 38 ++++++--- src/adjmat/HbondMatrix.cpp | 62 ++++++++++----- src/adjmat/MatrixColumnSums.cpp | 41 +++++++--- src/adjmat/MatrixRowSums.cpp | 34 +++++--- src/adjmat/OutputCluster.cpp | 96 ++++++++++++++++------- src/adjmat/SMACMatrix.cpp | 42 +++++++--- src/adjmat/Sprint.cpp | 34 +++++--- src/adjmat/TopologyMatrix.cpp | 111 ++++++++++++++++++--------- src/astyle.sh | 1 - src/config/Config.inc.in | 24 +++--- 27 files changed, 756 insertions(+), 339 deletions(-) diff --git a/src/adjmat/ActionWithInputMatrix.cpp b/src/adjmat/ActionWithInputMatrix.cpp index 449240d64a..41dd1d3241 100644 --- a/src/adjmat/ActionWithInputMatrix.cpp +++ b/src/adjmat/ActionWithInputMatrix.cpp @@ -43,20 +43,29 @@ ActionWithInputMatrix::ActionWithInputMatrix(const ActionOptions& ao): 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"); + 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 ) + 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 ) ); + if( !mymatrix ) + error( mybasemulticolvars[0]->getLabel() + " does not calculate an adjacency matrix"); + + // Delete all the atom labels that have been created + atom_lab.resize(0); + unsigned nnodes; + 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 ) ); } } @@ -77,7 +86,8 @@ AtomNumber ActionWithInputMatrix::getAbsoluteIndexOfCentralAtom(const unsigned& } double ActionWithInputMatrix::retrieveConnectionValue( const unsigned& i, const unsigned& j, std::vector& vals ) const { - if( !mymatrix->matrixElementIsActive( i, j ) ) return 0; + if( !mymatrix->matrixElementIsActive( i, j ) ) + return 0; unsigned myelem = mymatrix->getStoreIndexFromMatrixIndices( i, j ); // unsigned vi; double df; @@ -87,18 +97,22 @@ double ActionWithInputMatrix::retrieveConnectionValue( const unsigned& i, const 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); + std::vector tvals( mymatrix->getNumberOfComponents() ); + orient0.assign(orient0.size(),0); for(unsigned i=0; igetNumberOfColumns(); ++i) { - if( mymatrix->undirectedGraph() && ind==i ) continue; + if( mymatrix->undirectedGraph() && ind==i ) + continue; orient0[1]+=retrieveConnectionValue( ind, i, tvals ); } - orient0[0]=1.0; return; + orient0[0]=1.0; + return; } (mymatrix->function)->getInputData( ind, normed, myatoms, orient0 ); } void ActionWithInputMatrix::addConnectionDerivatives( const unsigned& i, const unsigned& j, MultiValue& myvals, MultiValue& myvout ) const { - if( !mymatrix->matrixElementIsActive( i, j ) ) return; + if( !mymatrix->matrixElementIsActive( i, j ) ) + return; unsigned myelem = mymatrix->getStoreIndexFromMatrixIndices( i, j ); // Get derivatives and add mymatrix->retrieveDerivatives( myelem, false, myvals ); @@ -117,22 +131,26 @@ MultiValue& ActionWithInputMatrix::getInputDerivatives( const unsigned& ind, con myder.clearAll(); MultiValue myvals( (mymatrix->function)->getNumberOfQuantities(), (mymatrix->function)->getNumberOfDerivatives() ); for(unsigned i=0; igetNumberOfColumns(); ++i) { - if( mymatrix->undirectedGraph() && ind==i ) continue; + if( mymatrix->undirectedGraph() && ind==i ) + continue; addConnectionDerivatives( ind, i, myvals, myder ); } - myder.updateDynamicList(); return 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; + if( size==0 ) + return 1; return size; } unsigned ActionWithInputMatrix::getNumberOfQuantities() const { - if( (mymatrix->function)->mybasemulticolvars.size()==0 ) return 2; + if( (mymatrix->function)->mybasemulticolvars.size()==0 ) + return 2; return (mymatrix->function)->mybasemulticolvars[0]->getNumberOfQuantities(); } diff --git a/src/adjmat/ActionWithInputMatrix.h b/src/adjmat/ActionWithInputMatrix.h index 9d5c44dcdd..e21270468b 100644 --- a/src/adjmat/ActionWithInputMatrix.h +++ b/src/adjmat/ActionWithInputMatrix.h @@ -57,12 +57,16 @@ class ActionWithInputMatrix : public multicolvar::MultiColvarBase { unsigned getNumberOfDerivatives() override; /// Get the number of rows/cols in the adjacency matrix vessel virtual unsigned getNumberOfNodes() const; - bool isPeriodic() override { return false; } + bool isPeriodic() override { + return false; + } unsigned getNumberOfQuantities() const override; /// AtomNumber getAbsoluteIndexOfCentralAtom(const unsigned& i) const override; /// No loop over tasks for ActionWithInputMatrix - double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const override { plumed_error(); } + double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const override { + plumed_error(); + } /// Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const override; }; diff --git a/src/adjmat/AdjacencyMatrixBase.cpp b/src/adjmat/AdjacencyMatrixBase.cpp index 87c47ca732..5a1acaf62c 100644 --- a/src/adjmat/AdjacencyMatrixBase.cpp +++ b/src/adjmat/AdjacencyMatrixBase.cpp @@ -31,7 +31,8 @@ namespace adjmat { void AdjacencyMatrixBase::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); - keys.remove("LOWMEM"); keys.use("HIGHMEM"); + keys.remove("LOWMEM"); + keys.use("HIGHMEM"); } AdjacencyMatrixBase::AdjacencyMatrixBase(const ActionOptions& ao): @@ -48,23 +49,28 @@ void AdjacencyMatrixBase::parseConnectionDescriptions( const std::string& key, c 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"); + 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; + if( !parseNumbered(key, i, input ) ) + break; sw.push_back( input ); } } setupConnector( connect_id, 0, 0, sw ); } else { - if( multiple ) error("keyword " + key + " does not work with multiple input strings"); + 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; + nr=nrow_t; + nc = getNumberOfNodeTypes() - nr; } for(unsigned i=0; i sw(1); parseNumbered(key,ibase+j+1,sw[0]); + std::vector sw(1); + parseNumbered(key,ibase+j+1,sw[0]); if(sw[0].length()==0) { - std::string num; Tools::convert(ibase+j+1,num); + 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 ); @@ -91,18 +99,21 @@ void AdjacencyMatrixBase::parseConnectionDescriptions( const std::string& key, c } 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"); + if( mybasemulticolvars[i]->getNumberOfQuantities()!=nq ) + error("mismatch between vectors in base colvars"); } return nq; } unsigned AdjacencyMatrixBase::getNumberOfNodeTypes() const { unsigned size=mybasemulticolvars.size(); - if( size==0 ) return 1; + if( size==0 ) + return 1; return size; } @@ -110,57 +121,85 @@ void AdjacencyMatrixBase::retrieveTypeDimensions( unsigned& nrows, unsigned& nco 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; + //this could directly be intialized like std::vector types={atom_lab[ablocks[0][0]].first}; faster, and clearer + std::vector 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; + std::vector types(1); + types[0]=atom_lab[ablocks[0][0]].first; for(unsigned i=1; i& all_atoms ) { std::string param; - if( symmetric && ablocks[0].size()==ablocks[1].size() ) param="SYMMETRIC"; + 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(da2); addVessel( std::move( ves ) ); @@ -168,12 +207,14 @@ void AdjacencyMatrixBase::finishMatrixSetup( const bool& symmetric, const std::v } void AdjacencyMatrixBase::readMaxTwoSpeciesMatrix( const std::string& key0, const std::string& key1, const std::string& key2, const bool& symmetric ) { - std::vector all_atoms; readTwoGroups( key0, key1, key2, all_atoms ); + std::vector 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 ) { - std::vector all_atoms; readGroupKeywords( key0, key1, key2, keym, true, symmetric, all_atoms ); + std::vector all_atoms; + readGroupKeywords( key0, key1, key2, keym, true, symmetric, all_atoms ); finishMatrixSetup( symmetric, all_atoms ); } @@ -185,10 +226,12 @@ void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, co // } void AdjacencyMatrixBase::recalculateMatrixElement( const unsigned& myelem, MultiValue& myvals ) { - std::vector myatoms; decodeIndexToAtoms( getTaskCode( myelem ), myatoms ); + std::vector 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"); } + bool isPeriodic() { + return false; + } + Vector getCentralAtom() { + plumed_merror("cannot find central atoms for adjacency matrix actions"); + } /// Get the atom number AtomNumber getAbsoluteIndexOfCentralAtom( const unsigned& i ) const ; }; @@ -86,7 +90,8 @@ AdjacencyMatrixVessel* AdjacencyMatrixBase::getAdjacencyVessel() { 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; } diff --git a/src/adjmat/AdjacencyMatrixVessel.cpp b/src/adjmat/AdjacencyMatrixVessel.cpp index b4136f0f53..fd3b581f85 100644 --- a/src/adjmat/AdjacencyMatrixVessel.cpp +++ b/src/adjmat/AdjacencyMatrixVessel.cpp @@ -37,10 +37,14 @@ AdjacencyMatrixVessel::AdjacencyMatrixVessel( const vesselbase::VesselOptions& d { function=dynamic_cast( getAction() ); plumed_assert( function ); - parseFlag("SYMMETRIC",symmetric); parseFlag("HBONDS",hbonds); - if( symmetric && hbonds ) error("matrix should be either symmetric or hbonds"); - if( symmetric && function->ablocks[0].size()!=function->ablocks[1].size() ) error("matrix is supposed to be symmetric but nrows!=ncols"); - if( hbonds && function->ablocks[0].size()!=function->ablocks[1].size() ) error("matrix is supposed to be hbonds but nrows!=ncols"); + parseFlag("SYMMETRIC",symmetric); + parseFlag("HBONDS",hbonds); + if( symmetric && hbonds ) + error("matrix should be either symmetric or hbonds"); + if( symmetric && function->ablocks[0].size()!=function->ablocks[1].size() ) + error("matrix is supposed to be symmetric but nrows!=ncols"); + if( hbonds && function->ablocks[0].size()!=function->ablocks[1].size() ) + error("matrix is supposed to be hbonds but nrows!=ncols"); } bool AdjacencyMatrixVessel::isSymmetric() const { @@ -64,13 +68,16 @@ 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 && !hbonds ) + return (function->ablocks[1].size())*ielem + jelem; if( !symmetric ) { plumed_dbg_assert( ielem!=jelem ); - if( jelemablocks[1].size()-1)*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; + if( ielem>jelem ) + return 0.5*ielem*(ielem-1)+jelem; return 0.5*jelem*(jelem-1) + ielem; } @@ -79,22 +86,32 @@ 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() ) { + // Have to remove number of columns as returns number in ablocks[1] + j -= function->ablocks[0].size(); + } } void AdjacencyMatrixVessel::retrieveMatrix( DynamicList& myactive_elements, Matrix& mymatrix ) { - myactive_elements.deactivateAll(); std::vector vals( getNumberOfComponents() ); + myactive_elements.deactivateAll(); + std::vector vals( getNumberOfComponents() ); for(unsigned i=0; igetPositionInFullTaskList(i), k, j ); + 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(); } @@ -102,34 +119,43 @@ void AdjacencyMatrixVessel::retrieveMatrix( DynamicList& myactive_elem 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 ); + unsigned j, k; + getMatrixIndices( function->getPositionInFullTaskList(i), k, j ); - if( nneigh[j]>=adj_list.ncols() || nneigh[k]>=adj_list.ncols() ) error("adjacency lists are not large enough, increase maxconnections"); + 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]++; + 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 ) { - plumed_dbg_assert( undirectedGraph() ); nedge=0; + plumed_dbg_assert( undirectedGraph() ); + nedge=0; std::vector myvals( getNumberOfComponents() ); - if( getNumberOfStoredValues()>edge_list.size() ) error("adjacency lists are not large enough, increase maxconnections"); + 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++; @@ -137,7 +163,8 @@ void AdjacencyMatrixVessel::retrieveEdgeList( unsigned& nedge, std::vector myvals( getNumberOfComponents() ); diff --git a/src/adjmat/AlignedMatrixBase.cpp b/src/adjmat/AlignedMatrixBase.cpp index 7d865e964d..ba8596f441 100644 --- a/src/adjmat/AlignedMatrixBase.cpp +++ b/src/adjmat/AlignedMatrixBase.cpp @@ -51,9 +51,12 @@ AlignedMatrixBase::AlignedMatrixBase( const ActionOptions& ao ): { // Read in the atomic positions readMaxTwoSpeciesMatrix( "ATOMS", "ATOMSA", "ATOMSB", true ); - 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"); + 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); @@ -63,7 +66,8 @@ AlignedMatrixBase::AlignedMatrixBase( const ActionOptions& ao ): for(unsigned i=0; isfmax ) sfmax=tsf; + if( tsf>sfmax ) + sfmax=tsf; } } // And set the link cell cutoff @@ -73,9 +77,13 @@ AlignedMatrixBase::AlignedMatrixBase( const ActionOptions& ao ): 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); + 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 ); @@ -84,15 +92,18 @@ void AlignedMatrixBase::setupConnector( const unsigned& id, const unsigned& i, c double AlignedMatrixBase::calculateWeight( const unsigned& taskCode, const double& weight, multicolvar::AtomValuePack& myatoms ) const { Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - if( distance.modulo2() 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 ); + getInputData( 0, true, myatoms, orient0 ); + getInputData( 1, true, myatoms, orient1 ); double f_dot = computeVectorFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t, distance, orient0, orient1, ddistance, dorient0, dorient1 ); @@ -105,7 +116,10 @@ double AlignedMatrixBase::compute( const unsigned& tindex, multicolvar::AtomValu myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) - sw*extProduct( distance, ddistance ) ); // Add derivatives of orientation - for(unsigned k=2; k fake_atoms; + matsums=usespecies=true; + std::vector fake_atoms; // Find what action we are taking the clusters from - if( !parseMultiColvarAtomList("CLUSTERS",-1,fake_atoms ) ) error("unable to interpret input CLUSTERS" ); - if( mybasemulticolvars.size()!=1 ) error("should be exactly one multicolvar input"); - atom_lab.resize(0); myclusters = dynamic_cast( mybasemulticolvars[0] ); - if( !myclusters ) error("input label is not that of a DFS object"); + if( !parseMultiColvarAtomList("CLUSTERS",-1,fake_atoms ) ) + error("unable to interpret input CLUSTERS" ); + if( mybasemulticolvars.size()!=1 ) + error("should be exactly one multicolvar input"); + atom_lab.resize(0); + myclusters = dynamic_cast( mybasemulticolvars[0] ); + if( !myclusters ) + error("input label is not that of a DFS object"); // 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() { // 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"); + if( getPntrToVessel(i)->getName()=="MEAN" ) + error("MEAN of cluster is not differentiable"); + if( getPntrToVessel(i)->getName()=="VMEAN" ) + error("VMEAN of cluster is not differentiable"); } MultiColvarBase::turnOnDerivatives(); } diff --git a/src/adjmat/ClusterAnalysisBase.h b/src/adjmat/ClusterAnalysisBase.h index 97593afb5d..b43cb465cd 100644 --- a/src/adjmat/ClusterAnalysisBase.h +++ b/src/adjmat/ClusterAnalysisBase.h @@ -50,7 +50,9 @@ class ClusterAnalysisBase : public multicolvar::MultiColvarBase { void turnOnDerivatives() override; void setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ) {} Vector getPositionOfAtomForLinkCells( const unsigned& ) const override; - double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const override { plumed_error(); } + double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const override { + plumed_error(); + } }; } diff --git a/src/adjmat/ClusterDiameter.cpp b/src/adjmat/ClusterDiameter.cpp index aa67dce394..cedd2b4373 100644 --- a/src/adjmat/ClusterDiameter.cpp +++ b/src/adjmat/ClusterDiameter.cpp @@ -91,15 +91,20 @@ ClusterDiameter::ClusterDiameter(const ActionOptions&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"); + 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 ); + addVessel("HIGHEST", "", -1); + std::vector fake_atoms; + setupMultiColvarBase( fake_atoms ); } void ClusterDiameter::turnOnDerivatives() { @@ -108,11 +113,13 @@ void ClusterDiameter::turnOnDerivatives() { void ClusterDiameter::calculate() { // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); + std::vector myatoms; + retrieveAtomsInCluster( clustr, myatoms ); // Activate the relevant tasks deactivateAllTasks(); for(unsigned i=1; i fake_atoms; setupMultiColvarBase( fake_atoms ); + std::vector fake_atoms; + setupMultiColvarBase( fake_atoms ); } void ClusterDistribution::calculate() { // Activate the relevant tasks nderivatives = getNumberOfDerivatives(); deactivateAllTasks(); - for(unsigned i=0; i myatoms; retrieveAtomsInCluster( current+1, myatoms ); + std::vector myatoms; + retrieveAtomsInCluster( current+1, myatoms ); // This deals with filters - if( myatoms.size()==1 && !nodeIsActive(myatoms[0]) ) return ; + if( myatoms.size()==1 && !nodeIsActive(myatoms[0]) ) + return ; std::vector vals( getNumberOfQuantities() ); MultiValue tvals( getNumberOfQuantities(), nderivatives ); @@ -137,12 +151,16 @@ void ClusterDistribution::performTask( const unsigned& task_index, const unsigne getPropertiesOfNode( i, vals ); if( use_switch && !inverse ) { vv = 1.0 - sf.calculate( vals[1], df ); - tval += vals[0]*vv; df=-df*vals[1]; + tval += vals[0]*vv; + df=-df*vals[1]; } else if( use_switch ) { vv = sf.calculate( vals[1], df ); - tval += vals[0]*vv; df=df*vals[1]; + tval += vals[0]*vv; + df=df*vals[1]; } else { - tval += vals[0]*vals[1]; df=1.; vv=vals[1]; + tval += vals[0]*vals[1]; + df=1.; + vv=vals[1]; } if( !doNotCalculateDerivatives() ) { getNodePropertyDerivatives( i, tvals ); @@ -153,7 +171,8 @@ void ClusterDistribution::performTask( const unsigned& task_index, const unsigne tvals.clearAll(); } } - myvals.setValue( 0, 1.0 ); myvals.setValue( 1, tval ); + myvals.setValue( 0, 1.0 ); + myvals.setValue( 1, tval ); } } diff --git a/src/adjmat/ClusterProperties.cpp b/src/adjmat/ClusterProperties.cpp index 5739fd443b..860d20da21 100644 --- a/src/adjmat/ClusterProperties.cpp +++ b/src/adjmat/ClusterProperties.cpp @@ -76,11 +76,22 @@ PLUMED_REGISTER_ACTION(ClusterProperties,"CLUSTER_PROPERTIES") void ClusterProperties::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."); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); - if( keys.reserved("VMEAN") ) keys.use("VMEAN"); - if( keys.reserved("VSUM") ) keys.use("VSUM"); - keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.use("ALT_MIN"); - keys.use("MIN"); keys.use("MAX"); keys.use("SUM"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("MEAN"); + keys.use("MORE_THAN"); + keys.use("LESS_THAN"); + if( keys.reserved("VMEAN") ) + keys.use("VMEAN"); + if( keys.reserved("VSUM") ) + keys.use("VSUM"); + keys.use("BETWEEN"); + keys.use("HISTOGRAM"); + keys.use("MOMENTS"); + keys.use("ALT_MIN"); + keys.use("MIN"); + keys.use("MAX"); + keys.use("SUM"); + keys.use("LOWEST"); + keys.use("HIGHEST"); } ClusterProperties::ClusterProperties(const ActionOptions&ao): @@ -90,31 +101,40 @@ ClusterProperties::ClusterProperties(const ActionOptions&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"); + 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 ); + std::vector fake_atoms; + setupMultiColvarBase( fake_atoms ); } void ClusterProperties::calculate() { // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); + std::vector 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(); + std::vector fake_atoms; + setupMultiColvarBase( fake_atoms ); + addValue(); + setNotPeriodic(); } void ClusterSize::turnOnDerivatives() { @@ -106,7 +113,9 @@ void ClusterSize::turnOnDerivatives() { void ClusterSize::calculate() { // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); setValue( myatoms.size() ); + std::vector myatoms; + retrieveAtomsInCluster( clustr, myatoms ); + setValue( myatoms.size() ); } } diff --git a/src/adjmat/ClusterWithSurface.cpp b/src/adjmat/ClusterWithSurface.cpp index 780dd7ab95..5e1e6b663e 100644 --- a/src/adjmat/ClusterWithSurface.cpp +++ b/src/adjmat/ClusterWithSurface.cpp @@ -110,16 +110,22 @@ ClusterWithSurface::ClusterWithSurface(const ActionOptions&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"); + 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"); + 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); + 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 @@ -152,35 +158,46 @@ unsigned ClusterWithSurface::getNumberOfQuantities() const { double ClusterWithSurface::getCutoffForConnection() const { double tcut = myclusters->getCutoffForConnection(); - if( tcut>std::sqrt(rcut_surf2) ) return tcut; + if( tcut>std::sqrt(rcut_surf2) ) + return tcut; return std::sqrt(rcut_surf2); } void ClusterWithSurface::retrieveAtomsInCluster( const unsigned& clust, std::vector& myatoms ) const { - std::vector tmpat; myclusters->retrieveAtomsInCluster( clust, tmpat ); + std::vector tmpat; + myclusters->retrieveAtomsInCluster( clust, tmpat ); // Prevent double counting std::vector incluster( getNumberOfNodes(), false ); - for(unsigned i=0; i surface_atom( getNumberOfNodes(), false ); for(unsigned i=0; iundirectedGraph() ) error("input contact matrix is incompatible with clustering"); + 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 ); + 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"); + if( getBaseMultiColvar(0)->isDensity() ) + error("DFS clustering cannot be differentiated if base multicolvar is DENSITY"); } // Ensure that derivatives are turned on in base classes @@ -57,7 +62,10 @@ void ClusteringBase::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 ); + unsigned n=0; + myatoms.resize( cluster_sizes[cluster_sizes.size() - clust].first ); for(unsigned i=0; i& 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); + 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; ksfmax ) sfmax=tsf; + if( tsf>sfmax ) + sfmax=tsf; } } // And set the link cell cutoff @@ -120,15 +123,20 @@ ContactMatrix::ContactMatrix( const ActionOptions& ao ): } 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); + 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); log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); } double ContactMatrix::calculateWeight( const unsigned& taskCode, const double& weight, multicolvar::AtomValuePack& myatoms ) const { Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - if( distance.modulo2()0 ) edge_list.resize( getNumberOfNodes()*maxconnections ); - else edge_list.resize(0.5*getNumberOfNodes()*(getNumberOfNodes()-1)); + 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() { #ifdef __PLUMED_HAS_BOOST_GRAPH // Get the list of edges - unsigned nedges=0; getAdjacencyVessel()->retrieveEdgeList( nedges, edge_list ); + unsigned nedges=0; + getAdjacencyVessel()->retrieveEdgeList( nedges, edge_list ); // Build the graph using boost boost::adjacency_list sg(&edge_list[0],&edge_list[nedges],getNumberOfNodes()); @@ -128,15 +135,20 @@ void DFSClustering::performClustering() { 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); + 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"); + 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 ) + 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(); + 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"); + 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); + 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 ); + unsigned nedge; + std::vector > edge_list( mymatrix->getNumberOfRows()*maxconnections ); mymatrix->retrieveEdgeList( nedge, edge_list ); - for(unsigned i=0; isfmax ) sfmax=tsf; + if( tsf>sfmax ) + sfmax=tsf; } } // Set the link cell cutoff @@ -161,45 +165,60 @@ HBondMatrix::HBondMatrix( const ActionOptions& ao ): 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); + 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); + 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); + 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; igetMatrixAction())->mybasemulticolvars.size()>0 ) error("matrix row sums should only be calculated when inputs are atoms"); + if( (mymatrix->getMatrixAction())->mybasemulticolvars.size()>0 ) + error("matrix row sums should only be calculated when inputs are atoms"); // Setup the tasks unsigned ncols = mymatrix->getNumberOfColumns(); - ablocks.resize(1); ablocks[0].resize( ncols ); - for(unsigned i=0; iundirectedGraph() ) { - for(unsigned i=0; igetNumberOfRows() + i; + for(unsigned i=0; igetNumberOfRows() + i; } - std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); + 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() ); + double sum=0.0; + std::vector tvals( mymatrix->getNumberOfComponents() ); unsigned nrows = mymatrix->getNumberOfRows(); for(unsigned i=0; iundirectedGraph() && tinded==i ) continue; + if( mymatrix->undirectedGraph() && tinded==i ) + continue; sum+=retrieveConnectionValue( i, tinded, tvals ); } @@ -111,7 +127,8 @@ double MatrixColumnSums::compute( const unsigned& tinded, multicolvar::AtomValue MultiValue myvals( mymatrix->getNumberOfComponents(), myatoms.getNumberOfDerivatives() ); MultiValue& myvout=myatoms.getUnderlyingMultiValue(); for(unsigned i=0; iisSymmetric() && tinded==i ) continue ; + if( mymatrix->isSymmetric() && tinded==i ) + continue ; addConnectionDerivatives( i, tinded, myvals, myvout ); } } diff --git a/src/adjmat/MatrixRowSums.cpp b/src/adjmat/MatrixRowSums.cpp index 4905f9b0aa..e96943b3b4 100644 --- a/src/adjmat/MatrixRowSums.cpp +++ b/src/adjmat/MatrixRowSums.cpp @@ -76,29 +76,45 @@ PLUMED_REGISTER_ACTION(MatrixRowSums,"ROWSUMS") void MatrixRowSums::registerKeywords( Keywords& keys ) { ActionWithInputMatrix::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("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); + 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("MORE_THAN"); + keys.use("BETWEEN"); + keys.use("HISTOGRAM"); + keys.use("MOMENTS"); } MatrixRowSums::MatrixRowSums(const ActionOptions& ao): Action(ao), ActionWithInputMatrix(ao) { - if( (mymatrix->getMatrixAction())->mybasemulticolvars.size()>0 ) warning("matrix row may be problematic when inputs are not atoms"); + if( (mymatrix->getMatrixAction())->mybasemulticolvars.size()>0 ) + warning("matrix row may be problematic when inputs are not atoms"); // Setup the tasks unsigned nrows = mymatrix->getNumberOfRows(); - ablocks.resize(1); ablocks[0].resize( nrows ); - for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); + 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() ); - getInputData( tinded, false, myatoms, tvals ); double fval=tvals[1]; + getInputData( tinded, false, myatoms, tvals ); + double fval=tvals[1]; if( !doNotCalculateDerivatives() ) { - tvals.assign( tvals.size(), 0 ); tvals[1]=1.0; + 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 7fe7a3cd27..cb29341051 100644 --- a/src/adjmat/OutputCluster.cpp +++ b/src/adjmat/OutputCluster.cpp @@ -106,30 +106,44 @@ OutputCluster::OutputCluster(const ActionOptions& 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"); + 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.substr(dot+1)=="xyz" ) + output_xyz=true; } - 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"); + 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]); + 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; + addDependency( myclusters ); + double rcut=myclusters->getCutoffForConnection() + 0.3; + rcut2=rcut*rcut; // Read in the cluster we are calculating 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"); + 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() ); } @@ -141,35 +155,56 @@ void OutputCluster::update() { if( makewhole ) { // Retrieve the atom positions atomsin.resize( myatoms.size() ); - for(unsigned i=0; igetPositionOfAtomForLinkCells( myatoms[i] ); + 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() ); + 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]++; } + if( myclusters->areConnected( myatoms[i], myatoms[j] ) ) { + adj_list(i,nneigh[i])=j; + adj_list(j,nneigh[j])=i; + nneigh[i]++; + nneigh[j]++; + } } } @@ -177,18 +212,21 @@ void OutputCluster::update() { for(unsigned jj=0; jjrcut2 ) { visited[j]=true; - for(unsigned depth=0; depth<=maxdepth; ++depth) explore( j, depth ); + for(unsigned depth=0; depth<=maxdepth; ++depth) + explore( j, depth ); } } } } // And print final positions - for(unsigned i=0; igetPositionOfAtomForLinkCells( myatoms[i] ); @@ -198,16 +236,19 @@ void OutputCluster::update() { } 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()); + for(unsigned i=0; igetAbsoluteIndexOfCentralAtom(myatoms[i])).index()); ofile.printf("\n"); } } void OutputCluster::explore( const unsigned& index, const unsigned& depth ) { - if( depth==0 ) return ; + if( depth==0 ) + return ; for(unsigned i=0; ipbcDistance( atomsin[index], atomsin[j] ); atomsin[j] = atomsin[index] + svec; explore( j, depth-1 ); @@ -218,7 +259,8 @@ bool OutputCluster::explore_dfs( const unsigned& index ) { visited[index]=true; for(unsigned i=0; i& desc ) { for(int i=0; i& 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); + 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; i() ); pos[i]->setDomain( "-pi", "pi" ); } + for(unsigned i=0; i() ); + pos[i]->setDomain( "-pi", "pi" ); + } for(unsigned j=0; jset( angle ); } - double ans=0; std::vector deriv( nvectors ), df( nvectors, 0 ); + double ans=0; + std::vector deriv( nvectors ), df( nvectors, 0 ); auto pos_ptr=Tools::unique2raw(pos); 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 ); + if( !getAdjacencyVessel()->isSymmetric() ) + error("input contact matrix is not symmetric"); + std::vector fake_atoms; + setupMultiColvarBase( fake_atoms ); // Create all the values sqrtn = std::sqrt( static_cast( getNumberOfNodes() ) ); for(unsigned i=0; iresizeDerivatives( getNumberOfDerivatives() ); @@ -145,7 +148,8 @@ Sprint::Sprint(const ActionOptions&ao): // Setup the dynamic list to hold all the tasks unsigned ntriangle = 0.5*getNumberOfNodes()*(getNumberOfNodes()-1); - for(unsigned i=0; i mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); // std::vector catoms(2); - unsigned nval = getNumberOfNodes(); mymat_ders=0; + unsigned nval = getNumberOfNodes(); + mymat_ders=0; for(unsigned i=rank; igetMatrixIndices( active_elements[i], j, k ); + unsigned j, k; + getAdjacencyVessel()->getMatrixIndices( active_elements[i], j, k ); double tmp1 = 2 * eigenvecs(nval-1,j)*eigenvecs(nval-1,k); for(int icomp=0; icompaddDerivative( i, mymat_ders(j,i) ); + for(unsigned i=0; iaddDerivative( i, mymat_ders(j,i) ); } } diff --git a/src/adjmat/TopologyMatrix.cpp b/src/adjmat/TopologyMatrix.cpp index 07abbd501a..043989ae03 100644 --- a/src/adjmat/TopologyMatrix.cpp +++ b/src/adjmat/TopologyMatrix.cpp @@ -102,18 +102,26 @@ TopologyMatrix::TopologyMatrix( const ActionOptions& ao ): maxbins(0) { readMaxThreeSpeciesMatrix("NODES", "FAKE", "FAKE", "ATOMS", true ); - unsigned nrows, ncols, ndonor_types; retrieveTypeDimensions( nrows, ncols, ndonor_types ); - switchingFunction.resize( nrows, ncols ); parseConnectionDescriptions("SWITCH",false,ndonor_types); - cylinder_sw.resize( nrows, ncols ); parseConnectionDescriptions("RADIUS",false,ndonor_types); - low_sf.resize( nrows, ncols ); parseConnectionDescriptions("CYLINDER_SWITCH",false,ndonor_types); - binw_mat.resize( nrows, ncols ); cell_volume.resize( nrows, ncols ); + unsigned nrows, ncols, ndonor_types; + retrieveTypeDimensions( nrows, ncols, ndonor_types ); + switchingFunction.resize( nrows, ncols ); + parseConnectionDescriptions("SWITCH",false,ndonor_types); + cylinder_sw.resize( nrows, ncols ); + parseConnectionDescriptions("RADIUS",false,ndonor_types); + low_sf.resize( nrows, ncols ); + parseConnectionDescriptions("CYLINDER_SWITCH",false,ndonor_types); + binw_mat.resize( nrows, ncols ); + cell_volume.resize( nrows, ncols ); parseConnectionDescriptions("BIN_SIZE",false,ndonor_types); // Read in stuff for grid - parse("SIGMA",sigma); parse("KERNEL",kerneltype); + parse("SIGMA",sigma); + parse("KERNEL",kerneltype); // Read in threshold for density cutoff - std::string errors, thresh_sw_str; parse("DENSITY_THRESHOLD",thresh_sw_str); + std::string errors, thresh_sw_str; + parse("DENSITY_THRESHOLD",thresh_sw_str); threshold_switch.set(thresh_sw_str, errors ); - if( errors.length()>0 ) 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; + if( tsf>sfmax ) + sfmax=tsf; double rsf=cylinder_sw(i,j).get_dmax(); - if( rsf>rfmax ) rfmax=rsf; + if( rsf>rfmax ) + rfmax=rsf; double lsf=low_sf(i,j).get_dmax(); - if( lsf>lsfmax ) lsfmax=lsf; + if( lsf>lsfmax ) + lsfmax=lsf; } } // Get the width of the bead - HistogramBead bead; bead.isNotPeriodic(); - bead.setKernelType( kerneltype ); bead.set( 0.0, 1.0, sigma ); + HistogramBead bead; + bead.isNotPeriodic(); + bead.setKernelType( kerneltype ); + bead.set( 0.0, 1.0, sigma ); beadrad = bead.getCutoff(); // Set the link cell cutoff @@ -149,7 +162,8 @@ TopologyMatrix::TopologyMatrix( const ActionOptions& ao ): double maxsize=0; for(unsigned i=0; imaxsize ) maxsize=binw_mat(i,j); + if( binw_mat(i,j)>maxsize ) + maxsize=binw_mat(i,j); } } // Set the maximum number of bins that we will need to compute @@ -166,55 +180,75 @@ unsigned TopologyMatrix::getNumberOfQuantities() const { 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); + 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); + 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); + 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); + 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) ); } } double TopologyMatrix::calculateWeight( const unsigned& taskCode, const double& weight, multicolvar::AtomValuePack& myatoms ) const { Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - if( distance.modulo2() binvals( 1+maxbins ); for(unsigned i=1;imax ) { max=myatoms.getValue(i); vout=i; } + if( myatoms.getValue(i)>max ) { + 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) ), @@ -248,12 +282,14 @@ void TopologyMatrix::calculateForThreeAtoms( const unsigned& iat, const Vector& // This tells us if we are outside the end of the cylinder double excess = proj - d1_len; // Return if we are outside of the cylinder as calculated based on excess - if( excess>low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).get_dmax() ) return; + if( excess>low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).get_dmax() ) + return; // Find the length of the cylinder double binw = binw_mat( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ); double lcylinder = (std::floor( d1_len / binw ) + 1)*binw; // Return if the projection is outside the length of interest - if( proj<-bead.getCutoff() || proj>(lcylinder+bead.getCutoff()) ) return; + if( proj<-bead.getCutoff() || proj>(lcylinder+bead.getCutoff()) ) + return; // Calculate the excess swiching function double edf, eval = low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( excess, edf ); @@ -297,11 +333,14 @@ void TopologyMatrix::calculateForThreeAtoms( const unsigned& iat, const Vector& Vector pos1 = myatoms.getPosition(0) + d1_len*d1; Vector pos2 = myatoms.getPosition(0) + d2; - Vector g1derivf,g2derivf,lderivf; Tensor vir; + Vector g1derivf,g2derivf,lderivf; + Tensor vir; for(unsigned bin=0; binbinw*(bin+1)+bead.getCutoff() ) continue; - double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; der /= cellv; + if( proj<(bin*binw-bead.getCutoff()) || proj>binw*(bin+1)+bead.getCutoff() ) + continue; + double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; + der /= cellv; myatoms.addValue( 2+bin, contr*val*eval ); if( !doNotCalculateDerivatives() ) { diff --git a/src/astyle.sh b/src/astyle.sh index 7ff80b99b1..463066547e 100755 --- a/src/astyle.sh +++ b/src/astyle.sh @@ -8,7 +8,6 @@ echo "$DIRS" # shellcheck disable=SC2125 test -z "$DIRS" && DIRS=* use_legacy=( - adjmat analysis annfunc asmjit diff --git a/src/config/Config.inc.in b/src/config/Config.inc.in index 0a6f99e9cf..9c55128e68 100644 --- a/src/config/Config.inc.in +++ b/src/config/Config.inc.in @@ -29,20 +29,20 @@ namespace PLMD { namespace config { namespace { - /// local tool that, given a string, returns a new string which is: - /// - enclosed in single quotes (') - /// - with all single quotes escaped - std::string escapeForSingleQuote(const std::string& input) { - std::string escaped; - for (char c : input) { - if (c == '\'') { - escaped += "'\\''"; - } else { - escaped += c; - } +/// local tool that, given a string, returns a new string which is: +/// - enclosed in single quotes (') +/// - with all single quotes escaped +std::string escapeForSingleQuote(const std::string& input) { + std::string escaped; + for (char c : input) { + if (c == '\'') { + escaped += "'\\''"; + } else { + escaped += c; } - return "'" + escaped + "'"; } + return "'" + escaped + "'"; +} } // This is a fix to allow conda to correctly replace paths in binary files.