LCOV - code coverage report
Current view: top level - adjmat - AdjacencyMatrixVessel.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 83 97 85.6 %
Date: 2026-03-30 13:16:06 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2013-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "AdjacencyMatrixVessel.h"
      23             : #include "AdjacencyMatrixBase.h"
      24             : #include "vesselbase/ActionWithVessel.h"
      25             : 
      26             : namespace PLMD {
      27             : namespace adjmat {
      28             : 
      29          23 : void AdjacencyMatrixVessel::registerKeywords( Keywords& keys ) {
      30          23 :   StoreDataVessel::registerKeywords(keys);
      31          46 :   keys.addFlag("SYMMETRIC",false,"is the matrix symmetric");
      32          46 :   keys.addFlag("HBONDS",false,"can we think of the matrix as a undirected graph");
      33          23 : }
      34             : 
      35          23 : AdjacencyMatrixVessel::AdjacencyMatrixVessel( const vesselbase::VesselOptions& da ):
      36          23 :   StoreDataVessel(da) {
      37          23 :   function=dynamic_cast<AdjacencyMatrixBase*>( getAction() );
      38          23 :   plumed_assert( function );
      39          23 :   parseFlag("SYMMETRIC",symmetric);
      40          23 :   parseFlag("HBONDS",hbonds);
      41          23 :   if( symmetric && hbonds ) {
      42           0 :     error("matrix should be either symmetric or hbonds");
      43             :   }
      44          23 :   if( symmetric && function->ablocks[0].size()!=function->ablocks[1].size() ) {
      45           0 :     error("matrix is supposed to be symmetric but nrows!=ncols");
      46             :   }
      47          23 :   if( hbonds &&  function->ablocks[0].size()!=function->ablocks[1].size() ) {
      48           0 :     error("matrix is supposed to be hbonds but nrows!=ncols");
      49             :   }
      50          23 : }
      51             : 
      52         775 : bool AdjacencyMatrixVessel::isSymmetric() const {
      53         775 :   return symmetric;
      54             : }
      55             : 
      56       72251 : bool AdjacencyMatrixVessel::undirectedGraph() const {
      57       72251 :   return ( symmetric || hbonds );
      58             : }
      59             : 
      60        1596 : unsigned AdjacencyMatrixVessel::getNumberOfRows() const {
      61        1596 :   return function->ablocks[0].size();
      62             : }
      63             : 
      64       39153 : unsigned AdjacencyMatrixVessel::getNumberOfColumns() const {
      65       39153 :   return function->ablocks[1].size();
      66             : }
      67             : 
      68       47892 : bool AdjacencyMatrixVessel::matrixElementIsActive( const unsigned& ielem, const unsigned& jelem ) const {
      69       47892 :   return StoreDataVessel::storedValueIsActive( getStoreIndexFromMatrixIndices( ielem, jelem ) );
      70             : }
      71             : 
      72       74692 : unsigned AdjacencyMatrixVessel::getStoreIndexFromMatrixIndices( const unsigned& ielem, const unsigned& jelem ) const {
      73       74692 :   if( !symmetric && !hbonds ) {
      74        2000 :     return (function->ablocks[1].size())*ielem + jelem;
      75             :   }
      76       72692 :   if( !symmetric ) {
      77             :     plumed_dbg_assert( ielem!=jelem );
      78       32256 :     if( jelem<ielem ) {
      79       16128 :       return (function->ablocks[1].size()-1)*ielem + jelem;
      80             :     }
      81       16128 :     return (function->ablocks[1].size()-1)*ielem + jelem - 1;
      82             :   }
      83       40436 :   if( ielem>jelem ) {
      84       23073 :     return 0.5*ielem*(ielem-1)+jelem;
      85             :   }
      86       17363 :   return 0.5*jelem*(jelem-1) + ielem;
      87             : }
      88             : 
      89          17 : AdjacencyMatrixBase* AdjacencyMatrixVessel::getMatrixAction() {
      90          17 :   return function;
      91             : }
      92             : 
      93       24491 : void AdjacencyMatrixVessel::getMatrixIndices( const unsigned& code, unsigned& i, unsigned& j ) const {
      94             :   std::vector<unsigned> myatoms;
      95       24491 :   function->decodeIndexToAtoms( function->getTaskCode(code), myatoms );
      96       24491 :   i=myatoms[0];
      97       24491 :   j=myatoms[1];
      98       24491 :   if( !undirectedGraph() ) {
      99           0 :     j -= function->ablocks[0].size();  // Have to remove number of columns as returns number in ablocks[1]
     100             :   }
     101       24491 : }
     102             : 
     103          17 : void AdjacencyMatrixVessel::retrieveMatrix( DynamicList<unsigned>& myactive_elements, Matrix<double>& mymatrix ) {
     104          17 :   myactive_elements.deactivateAll();
     105          17 :   std::vector<double> vals( getNumberOfComponents() );
     106        1564 :   for(unsigned i=0; i<getNumberOfStoredValues(); ++i) {
     107        1547 :     retrieveSequentialValue( i, false, vals );
     108        1547 :     if( vals[0]<epsilon ) {
     109           0 :       continue ;
     110             :     }
     111             : 
     112        1547 :     myactive_elements.activate(i);
     113             :     unsigned j, k;
     114        1547 :     getMatrixIndices( function->getPositionInFullTaskList(i), k, j );
     115             : 
     116        1547 :     if( symmetric ) {
     117        1547 :       mymatrix(k,j)=mymatrix(j,k)=vals[0]*vals[1];
     118             :     } else {
     119           0 :       mymatrix(k,j)=vals[0]*vals[1];
     120             :     }
     121             :   }
     122          17 :   myactive_elements.updateActiveMembers();
     123          17 : }
     124             : 
     125          24 : void AdjacencyMatrixVessel::retrieveAdjacencyLists( std::vector<unsigned>& nneigh, Matrix<unsigned>& adj_list ) {
     126             :   plumed_dbg_assert( undirectedGraph() );
     127             :   // Currently everything has zero neighbors
     128        8217 :   for(unsigned i=0; i<nneigh.size(); ++i) {
     129        8193 :     nneigh[i]=0;
     130             :   }
     131             : 
     132             :   // And set up the adjacency list
     133          24 :   std::vector<double> myvals( getNumberOfComponents() );
     134      214258 :   for(unsigned i=0; i<getNumberOfStoredValues(); ++i) {
     135             :     // Check if atoms are connected
     136      214234 :     retrieveSequentialValue( i, false, myvals );
     137      214234 :     if( myvals[0]<epsilon || myvals[1]<epsilon ) {
     138      199221 :       continue ;
     139             :     }
     140             : 
     141             :     unsigned j, k;
     142       15013 :     getMatrixIndices( function->getPositionInFullTaskList(i), k, j );
     143             : 
     144       15013 :     if( nneigh[j]>=adj_list.ncols() || nneigh[k]>=adj_list.ncols() ) {
     145           0 :       error("adjacency lists are not large enough, increase maxconnections");
     146             :     }
     147             :     // Store if atoms are connected
     148             :     // unsigned j, k; getMatrixIndices( i, k, j );
     149       15013 :     adj_list(k,nneigh[k])=j;
     150       15013 :     nneigh[k]++;
     151       15013 :     adj_list(j,nneigh[j])=k;
     152       15013 :     nneigh[j]++;
     153             :   }
     154          24 : }
     155             : 
     156           4 : void AdjacencyMatrixVessel::retrieveEdgeList( unsigned& nedge, std::vector<std::pair<unsigned,unsigned> >& edge_list ) {
     157             :   plumed_dbg_assert( undirectedGraph() );
     158           4 :   nedge=0;
     159           4 :   std::vector<double> myvals( getNumberOfComponents() );
     160           4 :   if( getNumberOfStoredValues()>edge_list.size() ) {
     161           0 :     error("adjacency lists are not large enough, increase maxconnections");
     162             :   }
     163             : 
     164      124576 :   for(unsigned i=0; i<getNumberOfStoredValues(); ++i) {
     165             :     // Check if atoms are connected
     166      124572 :     retrieveSequentialValue( i, false, myvals );
     167      124572 :     if( myvals[0]<epsilon || myvals[1]<epsilon ) {
     168      118188 :       continue ;
     169             :     }
     170             : 
     171        6384 :     getMatrixIndices( function->getPositionInFullTaskList(i), edge_list[nedge].first, edge_list[nedge].second );
     172        6384 :     nedge++;
     173             :   }
     174           4 : }
     175             : 
     176           0 : bool AdjacencyMatrixVessel::nodesAreConnected( const unsigned& iatom, const unsigned& jatom ) const {
     177           0 :   if( !matrixElementIsActive( iatom, jatom ) ) {
     178             :     return false;
     179             :   }
     180           0 :   unsigned ind=getStoreIndexFromMatrixIndices( iatom, jatom );
     181             : 
     182           0 :   std::vector<double> myvals( getNumberOfComponents() );
     183           0 :   retrieveValueWithIndex( ind, false, myvals );
     184           0 :   return ( myvals[0]>epsilon && myvals[1]>epsilon );
     185             : }
     186             : 
     187           8 : double AdjacencyMatrixVessel::getCutoffForConnection() const {
     188           8 :   return function->getLinkCellCutoff();
     189             : }
     190             : 
     191             : }
     192             : }
     193             : 

Generated by: LCOV version 1.16