Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-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 "Bias.h" 23 : #include "ActionRegister.h" 24 : 25 : namespace PLMD { 26 : namespace bias { 27 : 28 : //+PLUMEDOC BIAS RESTRAINT 29 : /* 30 : Adds harmonic and/or linear restraints on one or more variables. 31 : 32 : Either or both 33 : of SLOPE and KAPPA must be present to specify the linear and harmonic force constants 34 : respectively. The resulting potential is given by: 35 : \f[ 36 : \sum_i \frac{k_i}{2} (x_i-a_i)^2 + m_i*(x_i-a_i) 37 : \f]. 38 : 39 : The number of components for any vector of force constants must be equal to the number 40 : of arguments to the action. 41 : 42 : Additional material and examples can be also found in the tutorial \ref lugano-2 43 : 44 : \par Examples 45 : 46 : The following input tells plumed to restrain the distance between atoms 3 and 5 47 : and the distance between atoms 2 and 4, at different equilibrium 48 : values, and to print the energy of the restraint 49 : \plumedfile 50 : DISTANCE ATOMS=3,5 LABEL=d1 51 : DISTANCE ATOMS=2,4 LABEL=d2 52 : RESTRAINT ARG=d1,d2 AT=1.0,1.5 KAPPA=150.0,150.0 LABEL=restraint 53 : PRINT ARG=restraint.bias 54 : \endplumedfile 55 : 56 : */ 57 : //+ENDPLUMEDOC 58 : 59 : class Restraint : public Bias { 60 : std::vector<double> at; 61 : std::vector<double> kappa; 62 : std::vector<double> slope; 63 : Value* valueForce2; 64 : public: 65 : explicit Restraint(const ActionOptions&); 66 : void calculate() override; 67 : static void registerKeywords(Keywords& keys); 68 : }; 69 : 70 14144 : PLUMED_REGISTER_ACTION(Restraint,"RESTRAINT") 71 : 72 185 : void Restraint::registerKeywords(Keywords& keys) { 73 185 : Bias::registerKeywords(keys); 74 185 : keys.use("ARG"); 75 370 : keys.add("compulsory","SLOPE","0.0","specifies that the restraint is linear and what the values of the force constants on each of the variables are"); 76 370 : keys.add("compulsory","KAPPA","0.0","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); 77 370 : keys.add("compulsory","AT","the position of the restraint"); 78 370 : keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); 79 185 : } 80 : 81 181 : Restraint::Restraint(const ActionOptions&ao): 82 : PLUMED_BIAS_INIT(ao), 83 356 : at(getNumberOfArguments()), 84 178 : kappa(getNumberOfArguments(),0.0), 85 359 : slope(getNumberOfArguments(),0.0) { 86 178 : parseVector("SLOPE",slope); 87 178 : parseVector("KAPPA",kappa); 88 178 : parseVector("AT",at); 89 178 : checkRead(); 90 : 91 178 : log.printf(" at"); 92 409 : for(unsigned i=0; i<at.size(); i++) { 93 231 : log.printf(" %f",at[i]); 94 : } 95 178 : log.printf("\n"); 96 178 : log.printf(" with harmonic force constant"); 97 409 : for(unsigned i=0; i<kappa.size(); i++) { 98 231 : log.printf(" %f",kappa[i]); 99 : } 100 178 : log.printf("\n"); 101 178 : log.printf(" and linear force constant"); 102 409 : for(unsigned i=0; i<slope.size(); i++) { 103 231 : log.printf(" %f",slope[i]); 104 : } 105 178 : log.printf("\n"); 106 : 107 178 : addComponent("force2"); 108 178 : componentIsNotPeriodic("force2"); 109 178 : valueForce2=getPntrToComponent("force2"); 110 181 : } 111 : 112 : 113 4688 : void Restraint::calculate() { 114 : double ene=0.0; 115 : double totf2=0.0; 116 9751 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 117 5063 : const double cv=difference(i,at[i],getArgument(i)); 118 5063 : const double k=kappa[i]; 119 5063 : const double m=slope[i]; 120 5063 : const double f=-(k*cv+m); 121 5063 : ene+=0.5*k*cv*cv+m*cv; 122 : setOutputForce(i,f); 123 5063 : totf2+=f*f; 124 : } 125 : setBias(ene); 126 4688 : valueForce2->set(totf2); 127 4688 : } 128 : 129 : } 130 : 131 : 132 : }