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 10772 : PLUMED_REGISTER_ACTION(Restraint,"RESTRAINT") 71 : 72 179 : void Restraint::registerKeywords(Keywords& keys) { 73 179 : Bias::registerKeywords(keys); 74 179 : keys.use("ARG"); 75 358 : 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 358 : 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 358 : keys.add("compulsory","AT","the position of the restraint"); 78 358 : keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); 79 179 : } 80 : 81 178 : Restraint::Restraint(const ActionOptions&ao): 82 : PLUMED_BIAS_INIT(ao), 83 350 : at(getNumberOfArguments()), 84 175 : kappa(getNumberOfArguments(),0.0), 85 353 : slope(getNumberOfArguments(),0.0) 86 : { 87 175 : parseVector("SLOPE",slope); 88 175 : parseVector("KAPPA",kappa); 89 175 : parseVector("AT",at); 90 175 : checkRead(); 91 : 92 175 : log.printf(" at"); 93 385 : for(unsigned i=0; i<at.size(); i++) log.printf(" %f",at[i]); 94 175 : log.printf("\n"); 95 175 : log.printf(" with harmonic force constant"); 96 385 : for(unsigned i=0; i<kappa.size(); i++) log.printf(" %f",kappa[i]); 97 175 : log.printf("\n"); 98 175 : log.printf(" and linear force constant"); 99 385 : for(unsigned i=0; i<slope.size(); i++) log.printf(" %f",slope[i]); 100 175 : log.printf("\n"); 101 : 102 175 : addComponent("force2"); 103 175 : componentIsNotPeriodic("force2"); 104 175 : valueForce2=getPntrToComponent("force2"); 105 178 : } 106 : 107 : 108 4670 : void Restraint::calculate() { 109 : double ene=0.0; 110 : double totf2=0.0; 111 9607 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 112 4937 : const double cv=difference(i,at[i],getArgument(i)); 113 4937 : const double k=kappa[i]; 114 4937 : const double m=slope[i]; 115 4937 : const double f=-(k*cv+m); 116 4937 : ene+=0.5*k*cv*cv+m*cv; 117 : setOutputForce(i,f); 118 4937 : totf2+=f*f; 119 : } 120 : setBias(ene); 121 4670 : valueForce2->set(totf2); 122 4670 : } 123 : 124 : } 125 : 126 : 127 : }