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 : 24 : #include <algorithm> 25 : 26 : 27 : namespace PLMD { 28 : namespace bias { 29 : 30 2004 : Bias::Bias(const ActionOptions&ao): 31 : Action(ao), 32 : ActionPilot(ao), 33 : ActionWithValue(ao), 34 : ActionWithArguments(ao), 35 2004 : outputForces(getNumberOfArguments(),0.0) { 36 4006 : addComponentWithDerivatives("bias"); 37 2003 : componentIsNotPeriodic("bias"); 38 2003 : valueBias=getPntrToComponent("bias"); 39 : 40 2003 : if(getStride()>1) { 41 16 : log<<" multiple time step "<<getStride()<<" "; 42 32 : log<<cite("Ferrarotti, Bottaro, Perez-Villa, and Bussi, J. Chem. Theory Comput. 11, 139 (2015)")<<"\n"; 43 : } 44 7893 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 45 : // only the first element of a vector or matrix argument would be read and biased 46 5891 : if(getPntrToArgument(i)->getRank()!=0 && getPntrToArgument(i)->getNumberOfValues()!=1) { 47 3 : error("argument " + getPntrToArgument(i)->getName() + " is not a scalar: biases act on scalars (use e.g. SUM to make a scalar)"); 48 : } 49 5890 : (getPntrToArgument(i)->getPntrToAction())->turnOnDerivatives(); 50 : } 51 : 52 2002 : ActionWithValue::turnOnDerivatives(); 53 2005 : } 54 : 55 2571 : void Bias::registerKeywords( Keywords& keys ) { 56 2571 : Action::registerKeywords(keys); 57 2571 : ActionPilot::registerKeywords(keys); 58 2571 : ActionWithValue::registerKeywords(keys); 59 2571 : ActionWithArguments::registerKeywords(keys); 60 5142 : keys.addInputKeyword("compulsory","ARG","scalar","the labels of the scalars on which the bias will act"); 61 2571 : keys.add("hidden","STRIDE","the frequency with which the forces due to the bias should be calculated. This can be used to correctly set up multistep algorithms"); 62 5142 : keys.addOutputComponent("bias","default","scalar","the instantaneous value of the bias potential"); 63 2571 : } 64 : 65 225047 : void Bias::clearDerivatives(const bool& force) { 66 225047 : ActionWithValue::clearDerivatives(force); 67 : std::fill(outputForces.begin(),outputForces.end(),0.0); 68 225047 : } 69 : 70 224929 : void Bias::apply() { 71 224929 : const unsigned noa=getNumberOfArguments(); 72 224929 : const unsigned ncp=getNumberOfComponents(); 73 : 74 224929 : if(onStep()) { 75 224929 : double gstr = static_cast<double>(getStride()); 76 635303 : for(unsigned i=0; i<noa; ++i) { 77 410374 : getPntrToArgument(i)->addForce(gstr*outputForces[i]); 78 : } 79 : } 80 : 81 224929 : accumForces.assign(noa,0.0); 82 224929 : forces.resize(noa); 83 : 84 : bool at_least_one_forced=false; 85 1043302 : for(unsigned i=0; i<ncp; ++i) { 86 818373 : if(getPntrToComponent(i)->applyForce(forces)) { 87 : at_least_one_forced=true; 88 1313 : for(unsigned j=0; j<noa; j++) { 89 807 : accumForces[j]+=forces[j]; 90 : } 91 : //it may be faster like this(needs some measurements): 92 : //(it produces ~20 less asm instructions) 93 : /* 94 : auto aF = accumForces.begin(); 95 : auto f = forces.begin(); 96 : //accumForces and forces have the same size: 97 : while (aF!=accumForces.end()) { 98 : *aF+=*f; 99 : ++aF; 100 : ++f; 101 : } 102 : */ 103 : } 104 : } 105 : 106 224929 : if(at_least_one_forced && !onStep()) { 107 0 : error("you are biasing a bias with an inconsistent STRIDE"); 108 : } 109 : 110 224929 : if(at_least_one_forced) 111 1241 : for(unsigned i=0; i<noa; ++i) { 112 759 : getPntrToArgument(i)->addForce(accumForces[i]); 113 : } 114 : 115 224929 : } 116 : 117 : } 118 : } 119 : 120 :