Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2015-2020 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 "core/ActionShortcut.h" 23 : #include "core/ActionRegister.h" 24 : 25 : //+PLUMEDOC CONCOMP CLUSTER_WITHSURFACE 26 : /* 27 : Determine the atoms that are within a certain cutoff of the atoms in a cluster. 28 : 29 : This shortcut action can be used to identify the atoms within the largest connected cluster in a system as well 30 : as the atoms around the cluster as shown in the example input below: 31 : 32 : ```plumed 33 : # Calculate a matrix with elements that are non zero if the corresponding atoms are within 0.38 of each other 34 : cmat: CONTACT_MATRIX GROUP=1-1996 SWITCH={CUBIC D_0=0.34 D_MAX=0.38} 35 : # Calculate the coordination numbers of all the atoms 36 : ones: ONES SIZE=1996 37 : c1: MATRIX_VECTOR_PRODUCT ARG=cmat,ones 38 : # Now identify those atoms that have a coordination number that is less than 13.5 39 : cf: LESS_THAN ARG=c1 SWITCH={CUBIC D_0=13 D_MAX=13.5} 40 : 41 : # Now construct an adjacency matrix with elements that are equal to one if atoms are within 0.38 of each other 42 : # and if they both have a coordination number that is less than 13.5 43 : cmat2: CONTACT_MATRIX GROUP=1-1996 SWITCH={CUBIC D_0=0.34 D_MAX=0.38} 44 : dmat: OUTER_PRODUCT ARG=cf,cf 45 : mat: CUSTOM ARG=cmat2,dmat FUNC=x*y PERIODIC=NO 46 : # Find the connected componets of this matrix 47 : dfs: DFSCLUSTERING ARG=mat 48 : 49 : # Now identify the atoms that are within the largest cluster and the atoms that are within 0.38 nm of the 50 : # atoms that are within this cluster. Determine how many atoms in total satisfy this condition and the 51 : # distance betwen the two atoms in this set that are farthest appart. 52 : clust2a: CLUSTER_WITHSURFACE ATOMS=1-1996 CLUSTERS=dfs CLUSTER=1 RCUT_SURF={CUBIC D_0=0.34 D_MAX=0.38} 53 : size2a: SUM ARG=clust2a PERIODIC=NO 54 : dia2a: CLUSTER_DIAMETER ATOMS=1-1996 ARG=clust2a 55 : PRINT ARG=size2a,dia2a 56 : ``` 57 : 58 : */ 59 : //+ENDPLUMEDOC 60 : 61 : namespace PLMD { 62 : namespace clusters { 63 : 64 : class ClusterWithSurface : public ActionShortcut { 65 : public: 66 : static void registerKeywords(Keywords& keys); 67 : explicit ClusterWithSurface(const ActionOptions&); 68 : }; 69 : 70 : PLUMED_REGISTER_ACTION(ClusterWithSurface,"CLUSTER_WITHSURFACE") 71 : 72 4 : void ClusterWithSurface::registerKeywords(Keywords& keys) { 73 4 : ActionShortcut::registerKeywords(keys); 74 4 : keys.add("optional","RCUT_SURF","the cutoff to use for determining which atoms are connected to the surface of the cluster"); 75 4 : keys.add("compulsory","ATOMS","the atoms that were used to calculate the matrix that was clustered"); 76 4 : keys.add("compulsory","CLUSTERS","the label of the action that does the clustering"); 77 4 : 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."); 78 8 : keys.setValueDescription("vector","a vector that is one for those atoms that are within the cluster or that are within a cetain cutoff of one of the atoms in the cluster and zero otherwise"); 79 4 : keys.needsAction("CLUSTER_WEIGHTS"); 80 4 : keys.needsAction("CONTACT_MATRIX"); 81 4 : keys.needsAction("OUTER_PRODUCT"); 82 4 : keys.needsAction("CUSTOM"); 83 4 : keys.needsAction("DFSCLUSTERING"); 84 4 : keys.addDOI("https://doi.org/10.1021/acs.jctc.6b01073"); 85 4 : } 86 : 87 2 : ClusterWithSurface::ClusterWithSurface(const ActionOptions& ao): 88 : Action(ao), 89 2 : ActionShortcut(ao) { 90 : // Read atoms for contact matrix 91 : std::string atdata; 92 4 : parse("ATOMS",atdata); 93 : // Read rcut input 94 : std::string rcut_surf_str; 95 2 : parse("RCUT_SURF",rcut_surf_str); 96 : // Create a cluster weights object 97 4 : readInputLine( getShortcutLabel() + "_wnosurf: CLUSTER_WEIGHTS " + convertInputLineToString() ); 98 : // Now create a contact matrix 99 4 : readInputLine( getShortcutLabel() + "_cmat: CONTACT_MATRIX GROUP=" + atdata + " SWITCH={" + rcut_surf_str +"}" ); 100 : // Now create a custom matrix 101 4 : readInputLine( getShortcutLabel() + "_cwmat: OUTER_PRODUCT ARG=" + getShortcutLabel() + "_wnosurf," + getShortcutLabel() + "_wnosurf FUNC=max"); 102 : // Product of matrices 103 4 : readInputLine( getShortcutLabel() + "_pmat: CUSTOM ARG=" + getShortcutLabel() + "_cmat," + getShortcutLabel() + "_cwmat FUNC=x*y PERIODIC=NO"); 104 : // DFS clustering 105 4 : readInputLine( getShortcutLabel() + "_clust: DFSCLUSTERING ARG=" + getShortcutLabel() + "_pmat"); 106 : // And final cluster weights 107 4 : readInputLine( getShortcutLabel() + ": CLUSTER_WEIGHTS CLUSTERS=" + getShortcutLabel() + "_clust CLUSTER=1"); 108 2 : } 109 : 110 : } 111 : }