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 "core/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 : //+PLUMEDOC BIAS RESTRAINT_SCALAR 60 : /* 61 : Adds harmonic and/or linear restraints on one or more scalar variables. 62 : 63 : \par Examples 64 : 65 : */ 66 : //+ENDPLUMEDOC 67 : 68 : class Restraint : public Bias { 69 : std::vector<double> at; 70 : std::vector<double> kappa; 71 : std::vector<double> slope; 72 : Value* valueForce2; 73 : public: 74 : explicit Restraint(const ActionOptions&); 75 : void calculate() override; 76 : static void registerKeywords(Keywords& keys); 77 : }; 78 : 79 : PLUMED_REGISTER_ACTION(Restraint,"RESTRAINT_SCALAR") 80 : 81 575 : void Restraint::registerKeywords(Keywords& keys) { 82 575 : Bias::registerKeywords(keys); keys.setDisplayName("RESTRAINT"); 83 1150 : 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"); 84 1150 : 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"); 85 1150 : keys.add("compulsory","AT","the position of the restraint"); 86 1150 : keys.addOutputComponent("force2","default","scalar","the instantaneous value of the squared force due to this bias potential"); 87 575 : } 88 : 89 286 : Restraint::Restraint(const ActionOptions&ao): 90 : PLUMED_BIAS_INIT(ao), 91 572 : at(getNumberOfArguments()), 92 286 : kappa(getNumberOfArguments(),0.0), 93 572 : slope(getNumberOfArguments(),0.0) 94 : { 95 286 : parseVector("SLOPE",slope); 96 286 : parseVector("KAPPA",kappa); 97 286 : parseVector("AT",at); 98 286 : checkRead(); 99 : 100 286 : log.printf(" at"); 101 628 : for(unsigned i=0; i<at.size(); i++) log.printf(" %f",at[i]); 102 286 : log.printf("\n"); 103 286 : log.printf(" with harmonic force constant"); 104 628 : for(unsigned i=0; i<kappa.size(); i++) log.printf(" %f",kappa[i]); 105 286 : log.printf("\n"); 106 286 : log.printf(" and linear force constant"); 107 628 : for(unsigned i=0; i<slope.size(); i++) log.printf(" %f",slope[i]); 108 286 : log.printf("\n"); 109 : 110 572 : addComponent("force2"); 111 286 : componentIsNotPeriodic("force2"); 112 286 : valueForce2=getPntrToComponent("force2"); 113 286 : } 114 : 115 : 116 4850 : void Restraint::calculate() { 117 : double ene=0.0; 118 : double totf2=0.0; 119 10040 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 120 5190 : const double cv=difference(i,at[i],getArgument(i)); 121 5190 : const double k=kappa[i]; 122 5190 : const double m=slope[i]; 123 5190 : const double f=-(k*cv+m); 124 5190 : ene+=0.5*k*cv*cv+m*cv; 125 5190 : setOutputForce(i,f); 126 5190 : totf2+=f*f; 127 : } 128 4850 : setBias(ene); 129 4850 : valueForce2->set(totf2); 130 4850 : } 131 : 132 : } 133 : 134 : 135 : }