Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2015-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 "AlignedMatrixBase.h" 23 : #include "core/ActionRegister.h" 24 : #include "tools/Matrix.h" 25 : 26 : //+PLUMEDOC MATRIX ALIGNED_MATRIX 27 : /* 28 : Adjacency matrix in which two molecule are adjacent if they are within a certain cutoff and if they have the same orientation. 29 : 30 : As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the 31 : 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 32 : 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 33 : analyzed using a number of other algorithms as is detailed in \cite tribello-clustering. 34 : 35 : For this action the elements of the adjacency matrix are calculated using: 36 : 37 : \f[ 38 : a_{ij} = \sigma_1( |\mathbf{r}_{ij}| ) \sigma_2( \mathbf{v}_i . \mathbf{v}_j ) 39 : \f] 40 : 41 : 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$. 42 : These orientations might represent the 43 : orientation of a molecule, which could be calculated using \ref MOLECULES or \ref PLANES, or it might be the complex vectors calculated using the 44 : 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 45 : 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. 46 : \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 47 : objects \f$i\f$ and \f$j\f$. 48 : 49 : \par Examples 50 : 51 : The example input below is necessarily but gives you an idea of what can be achieved using this action. 52 : The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the 53 : centers of mass of the two atoms specified and the direction of the vector connecting the two atoms that were specified. 54 : 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 55 : 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 56 : 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 57 : 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 58 : 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. 59 : 60 : \plumedfile 61 : m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 62 : mat: ALIGNED_MATRIX ATOMS=m1 SWITCH={RATIONAL R_0=0.1} ORIENTATION_SWITCH={RATIONAL R_0=0.1 D_MAX=0.5} 63 : row: ROWSUMS MATRIX=mat MORE_THAN={RATIONAL D_0=1.0 R_0=0.1} 64 : PRINT ARG=row.* FILE=colvar 65 : \endplumedfile 66 : 67 : */ 68 : //+ENDPLUMEDOC 69 : 70 : namespace PLMD { 71 : namespace adjmat { 72 : 73 : class ContactAlignedMatrix : public AlignedMatrixBase { 74 : private: 75 : Matrix<SwitchingFunction> sf; 76 : public: 77 : /// 78 : static void registerKeywords( Keywords& keys ); 79 : /// 80 : explicit ContactAlignedMatrix(const ActionOptions&); 81 : void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector<std::string>& desc ) override; 82 : double computeVectorFunction( const unsigned& iv, const unsigned& jv, 83 : const Vector& conn, const std::vector<double>& vec1, const std::vector<double>& vec2, 84 : Vector& dconn, std::vector<double>& dvec1, std::vector<double>& dvec2 ) const override; 85 : }; 86 : 87 10419 : PLUMED_REGISTER_ACTION(ContactAlignedMatrix,"ALIGNED_MATRIX") 88 : 89 1 : void ContactAlignedMatrix::registerKeywords( Keywords& keys ) { 90 1 : AlignedMatrixBase::registerKeywords( keys ); 91 3 : keys.add("numbered","ORIENTATION_SWITCH","A switching function that transforms the dot product of the input vectors."); 92 1 : } 93 : 94 0 : ContactAlignedMatrix::ContactAlignedMatrix( const ActionOptions& ao ): 95 : Action(ao), 96 0 : AlignedMatrixBase(ao) 97 : { 98 0 : unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); 99 0 : sf.resize( nrows, ncols ); 100 0 : parseConnectionDescriptions("ORIENTATION_SWITCH",false,0); 101 0 : } 102 : 103 0 : void ContactAlignedMatrix::readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector<std::string>& desc ) { 104 0 : plumed_assert( desc.size()==1 ); std::string errors; sf(j,i).set(desc[0],errors); 105 0 : if( j!=i ) sf(i,j).set(desc[0],errors); 106 0 : 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() ); 107 0 : } 108 : 109 0 : double ContactAlignedMatrix::computeVectorFunction( const unsigned& iv, const unsigned& jv, 110 : const Vector& conn, const std::vector<double>& vec1, const std::vector<double>& vec2, 111 : Vector& dconn, std::vector<double>& dvec1, std::vector<double>& dvec2 ) const { 112 0 : double dot_df, dot=0; dconn.zero(); 113 0 : for(unsigned k=2; k<vec1.size(); ++k) dot+=vec1[k]*vec2[k]; 114 0 : double f_dot = sf(iv,jv).calculate( dot, dot_df ); 115 0 : for(unsigned k=2; k<vec1.size(); ++k) { dvec1[k]=dot_df*vec2[k]; dvec2[k]=dot_df*vec1[k]; } 116 0 : return f_dot; 117 : } 118 : 119 : } 120 : } 121 : 122 : 123 :