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 577 : void Restraint::registerKeywords(Keywords& keys) { 82 577 : Bias::registerKeywords(keys); 83 1154 : keys.setDisplayName("RESTRAINT"); 84 577 : 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"); 85 577 : 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"); 86 577 : keys.add("compulsory","AT","the position of the restraint"); 87 1154 : keys.addOutputComponent("force2","default","scalar","the instantaneous value of the squared force due to this bias potential"); 88 577 : } 89 : 90 287 : Restraint::Restraint(const ActionOptions&ao): 91 : PLUMED_BIAS_INIT(ao), 92 574 : at(getNumberOfArguments()), 93 287 : kappa(getNumberOfArguments(),0.0), 94 574 : slope(getNumberOfArguments(),0.0) { 95 287 : parseVector("SLOPE",slope); 96 287 : parseVector("KAPPA",kappa); 97 287 : parseVector("AT",at); 98 287 : checkRead(); 99 : 100 287 : log.printf(" at"); 101 636 : for(unsigned i=0; i<at.size(); i++) { 102 349 : log.printf(" %f",at[i]); 103 : } 104 287 : log.printf("\n"); 105 287 : log.printf(" with harmonic force constant"); 106 636 : for(unsigned i=0; i<kappa.size(); i++) { 107 349 : log.printf(" %f",kappa[i]); 108 : } 109 287 : log.printf("\n"); 110 287 : log.printf(" and linear force constant"); 111 636 : for(unsigned i=0; i<slope.size(); i++) { 112 349 : log.printf(" %f",slope[i]); 113 : } 114 287 : log.printf("\n"); 115 : 116 574 : addComponent("force2"); 117 287 : componentIsNotPeriodic("force2"); 118 287 : valueForce2=getPntrToComponent("force2"); 119 287 : } 120 : 121 : 122 4856 : void Restraint::calculate() { 123 : double ene=0.0; 124 : double totf2=0.0; 125 10088 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 126 5232 : const double cv=difference(i,at[i],getArgument(i)); 127 5232 : const double k=kappa[i]; 128 5232 : const double m=slope[i]; 129 5232 : const double f=-(k*cv+m); 130 5232 : ene+=0.5*k*cv*cv+m*cv; 131 5232 : setOutputForce(i,f); 132 5232 : totf2+=f*f; 133 : } 134 4856 : setBias(ene); 135 4856 : valueForce2->set(totf2); 136 4856 : } 137 : 138 : } 139 : 140 : 141 : }