Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-2017 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 : #include "core/PlumedMain.h" 25 : #include "core/ActionSet.h" 26 : #include "core/ActionWithValue.h" 27 : #include "CoordinationNumbers.h" 28 : #include "multicolvar/MultiColvarShortcuts.h" 29 : 30 : #include <complex> 31 : 32 : namespace PLMD { 33 : namespace symfunc { 34 : 35 : //+PLUMEDOC MCOLVAR LOCAL_CRYSTALINITY 36 : /* 37 : Calculate the local crystalinity symmetry function 38 : 39 : This shortcut provides an implementation of the local crystalinity order parameter that is described in the paper in the bibliography. 40 : To use this CV you define a series of unit vectors, $g_k$, using multiple instances of the GVECTOR keyword. This allows you to define a 41 : [symmetry function](https://www.plumed-tutorials.org/lessons/23/001/data/SymmetryFunction.html) for the $i$th atom as: 42 : 43 : $$ 44 : s_i = \sum_k \left| \frac{\sum_j \sigma(|r_{ij}|) e^{ig_k r_{ij}}}{\sum_j \sigma(|r_{ij}|) \right|^2 45 : $$ 46 : 47 : In this expression $r_{ij}$ is the vector connecting atom $i$ to atom $j$ and $\sigma$ is a switching function that acts upon the magnidue of this vector, $|r_{ij}|$. 48 : The following input is an example that shows how this symmetry function can be used in practice. 49 : 50 : ```plumed 51 : lc: LOCAL_CRYSTALINITY SPECIES=1-64 SWITCH={RATIONAL D_0=3.0 R_0=1.5} GVECTOR1=1,1,1 GVECTOR2=1,0.5,0.5 GVECTOR3=0.5,1.0,1.0 SUM 52 : PRINT ARG=lc_sum FILE=colvar 53 : ``` 54 : 55 : As you can see if you expand the shortcut in this input, the sum over $k$ in the above expression has three terms in this input as 3 GVECTORS are specified. 56 : Sixty four values for the expression above are computed. These sixty four numbers are then added together in order to give a global mesuare of the crystallinity 57 : for the simulated system. 58 : 59 : */ 60 : //+ENDPLUMEDOC 61 : 62 : 63 : class LocalCrystallinity : public ActionShortcut { 64 : public: 65 : static void registerKeywords( Keywords& keys ); 66 : explicit LocalCrystallinity(const ActionOptions&); 67 : }; 68 : 69 : PLUMED_REGISTER_ACTION(LocalCrystallinity,"LOCAL_CRYSTALINITY") 70 : 71 3 : void LocalCrystallinity::registerKeywords( Keywords& keys ) { 72 3 : CoordinationNumbers::shortcutKeywords( keys ); 73 3 : keys.add("numbered","GVECTOR","the coefficients of the linear combinations to compute for the CV"); 74 6 : keys.setValueDescription("vector","the value of the local crystalinity for each of the input atoms"); 75 3 : keys.needsAction("ONES"); 76 3 : keys.needsAction("MATRIX_VECTOR_PRODUCT"); 77 3 : keys.needsAction("COMBINE"); 78 3 : keys.needsAction("CUSTOM"); 79 3 : keys.addDOI("10.1063/1.4822877"); 80 3 : } 81 : 82 1 : LocalCrystallinity::LocalCrystallinity( const ActionOptions& ao): 83 : Action(ao), 84 1 : ActionShortcut(ao) { 85 : // This builds an adjacency matrix 86 : std::string sp_str, specA, specB; 87 1 : parse("SPECIES",sp_str); 88 1 : parse("SPECIESA",specA); 89 1 : parse("SPECIESB",specB); 90 1 : CoordinationNumbers::expandMatrix( true, getShortcutLabel(), sp_str, specA, specB, this ); 91 : // Input for denominator (coord) 92 1 : ActionWithValue* av = plumed.getActionSet().selectWithLabel<ActionWithValue*>( getShortcutLabel() + "_mat"); 93 1 : plumed_assert( av && av->getNumberOfComponents()>0 && (av->copyOutput(0))->getRank()==2 ); 94 : std::string size; 95 1 : Tools::convert( (av->copyOutput(0))->getShape()[1], size ); 96 2 : readInputLine( getShortcutLabel() + "_ones: ONES SIZE=" + size ); 97 2 : readInputLine( getShortcutLabel() + "_denom: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_mat.w," + getShortcutLabel() + "_ones"); 98 : // Input for numerator 99 1 : std::string finput = ""; 100 1 : for(unsigned i=1;; ++i) { 101 : std::vector<std::string> gvec; 102 : std::string istr; 103 4 : Tools::convert( i, istr ); 104 8 : if( !parseNumberedVector("GVECTOR",i,gvec) ) { 105 : break; 106 : } 107 3 : if( gvec.size()!=3 ) { 108 0 : error("gvectors should have size 3"); 109 : } 110 : // This is the dot product between the input gvector and the bond vector 111 9 : readInputLine( getShortcutLabel() + "_dot" + istr + ": COMBINE ARG=" + getShortcutLabel() + "_mat.x," + getShortcutLabel() + "_mat.y," + getShortcutLabel() + "_mat.z " 112 6 : "PERIODIC=NO COEFFICIENTS=" + gvec[0] + "," + gvec[1] + "," + gvec[2] ); 113 : // Now calculate the sine and cosine of the dot product 114 6 : readInputLine( getShortcutLabel() + "_cos" + istr + ": CUSTOM ARG=" + getShortcutLabel() +"_mat.w," + getShortcutLabel() + "_dot" + istr + " FUNC=x*cos(y) PERIODIC=NO"); 115 6 : readInputLine( getShortcutLabel() + "_sin" + istr + ": CUSTOM ARG=" + getShortcutLabel() +"_mat.w," + getShortcutLabel() + "_dot" + istr + " FUNC=x*sin(y) PERIODIC=NO"); 116 : // And sum up the sine and cosine over the coordination spheres 117 6 : readInputLine( getShortcutLabel() + "_cossum" + istr + ": MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_cos" + istr + "," + getShortcutLabel() + "_ones"); 118 6 : readInputLine( getShortcutLabel() + "_sinsum" + istr + ": MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_sin" + istr + "," + getShortcutLabel() + "_ones"); 119 : // And average the sine and cosine over the number of bonds 120 6 : readInputLine( getShortcutLabel() + "_cosmean" + istr + ": CUSTOM FUNC=x/y PERIODIC=NO ARG=" + getShortcutLabel() + "_cossum" + istr + "," + getShortcutLabel() + "_denom"); 121 6 : readInputLine( getShortcutLabel() + "_sinmean" + istr + ": CUSTOM FUNC=x/y PERIODIC=NO ARG=" + getShortcutLabel() + "_sinsum" + istr + "," + getShortcutLabel() + "_denom"); 122 : // And work out the square modulus of this complex number 123 6 : readInputLine( getShortcutLabel() + "_" + istr + ": CUSTOM FUNC=x*x+y*y PERIODIC=NO ARG=" + getShortcutLabel() + "_cosmean" + istr + "," + getShortcutLabel() + "_sinmean" + istr); 124 : // These are all the kvectors that we are adding together in the final combine for the final CV 125 3 : if( i>1 ) { 126 : finput += ","; 127 : } 128 6 : finput += getShortcutLabel() + "_" + istr; 129 4 : } 130 : // This computes the final CV 131 2 : readInputLine( getShortcutLabel() + ": COMBINE NORMALIZE PERIODIC=NO ARG=" + finput ); 132 : // Now calculate the total length of the vector 133 2 : multicolvar::MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel(), "", this ); 134 1 : } 135 : 136 : } 137 : } 138 :