Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2016-2021 The VES code team 3 : (see the PEOPLE-VES file at the root of this folder for a list of names) 4 : 5 : See http://www.ves-code.org for more information. 6 : 7 : This file is part of VES code module. 8 : 9 : The VES code module 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 : The VES code module 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 the VES code module. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : 23 : #include "TargetDistribution.h" 24 : 25 : #include "core/ActionRegister.h" 26 : 27 : 28 : namespace PLMD { 29 : namespace ves { 30 : 31 : //+PLUMEDOC VES_TARGETDIST TD_EXPONENTIAL 32 : /* 33 : Exponential distribution (static). 34 : 35 : Employ a target distribution given by an 36 : [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution) 37 : that is defined as 38 : \f[ 39 : p(s) = 40 : \lambda e^{-\lambda(s-a)} 41 : \f] 42 : where \f$a\f$ is the minimum of the distribution that is defined on the interval \f$[a,\infty)\f$, 43 : and \f$\lambda>0\f$ is the so-called rate parameter. 44 : 45 : The minimum \f$a\f$ is given using the MINIMUM keyword, and the rate parameter \f$\lambda\f$ is given 46 : using the LAMBDA keyword. 47 : 48 : This target distribution action is only defined for one dimension, for multiple dimensions 49 : it should be used in combination with \ref TD_PRODUCT_DISTRIBUTION action. 50 : 51 : \par Examples 52 : 53 : Exponential distribution with \f$a=10.0\f$ and \f$\lambda=0.5\f$ 54 : \plumedfile 55 : td: TD_EXPONENTIAL MINIMUM=-10.0 LAMBDA=0.5 56 : \endplumedfile 57 : 58 : The exponential distribution is only defined for one dimension so for multiple 59 : dimensions we have to use it in combination with the \ref TD_PRODUCT_DISTRIBUTION action as shown in 60 : the following example where we have a uniform distribution for argument 1 and 61 : and an exponential distribution for argument 2 62 : \plumedfile 63 : td_uni: TD_UNIFORM 64 : 65 : td_exp: TD_EXPONENTIAL MINIMUM=-10.0 LAMBDA=0.5 66 : 67 : td_pd: TD_PRODUCT_DISTRIBUTION DISTRIBUTIONS=td_uni,td_exp 68 : \endplumedfile 69 : 70 : 71 : */ 72 : //+ENDPLUMEDOC 73 : 74 : class TD_Exponential: public TargetDistribution { 75 : std::vector<double> minima_; 76 : std::vector<double> lambda_; 77 : public: 78 : static void registerKeywords(Keywords&); 79 : explicit TD_Exponential(const ActionOptions& ao); 80 : double getValue(const std::vector<double>&) const override; 81 : }; 82 : 83 : 84 10427 : PLUMED_REGISTER_ACTION(TD_Exponential,"TD_EXPONENTIAL") 85 : 86 : 87 9 : void TD_Exponential::registerKeywords(Keywords& keys) { 88 9 : TargetDistribution::registerKeywords(keys); 89 18 : keys.add("compulsory","MINIMUM","The minimum of the exponential distribution."); 90 18 : keys.add("compulsory","LAMBDA","The \\f$\\lambda\\f$ parameter of the exponential distribution given as positive number."); 91 9 : keys.use("WELLTEMPERED_FACTOR"); 92 9 : keys.use("SHIFT_TO_ZERO"); 93 9 : keys.use("NORMALIZE"); 94 9 : } 95 : 96 : 97 8 : TD_Exponential::TD_Exponential(const ActionOptions& ao): 98 : PLUMED_VES_TARGETDISTRIBUTION_INIT(ao), 99 16 : minima_(0), 100 8 : lambda_(0) 101 : { 102 8 : parseVector("MINIMUM",minima_); 103 8 : parseVector("LAMBDA",lambda_); 104 16 : for(unsigned int k=0; k<lambda_.size(); k++) { 105 8 : if(lambda_[k] < 0.0) {plumed_merror(getName()+": the value given in LAMBDA should be positive.");} 106 : } 107 : 108 : 109 8 : setDimension(minima_.size()); 110 8 : if(getDimension()>1) {plumed_merror(getName()+": only defined for one dimension, for multiple dimensions it should be used in combination with the TD_PRODUCT_DISTRIBUTION action.");} 111 8 : if(lambda_.size()!=getDimension()) {plumed_merror(getName()+": the LAMBDA keyword does not match the given dimension in MINIMUM");} 112 8 : checkRead(); 113 8 : } 114 : 115 : 116 1308 : double TD_Exponential::getValue(const std::vector<double>& argument) const { 117 : double value = 1.0; 118 2616 : for(unsigned int k=0; k<argument.size(); k++) { 119 1308 : double arg = (argument[k]-minima_[k])*lambda_[k]; 120 1308 : if(arg<0.0) {plumed_merror(getName()+": the exponential distribution is not defined for values less that ones given in MINIMUM");} 121 1308 : value *= lambda_[k]*exp(-arg); 122 : } 123 1308 : return value; 124 : } 125 : 126 : 127 : 128 : } 129 : }