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 "FermiSwitchingFunction.h" 24 : 25 : #include "tools/Tools.h" 26 : #include "tools/Keywords.h" 27 : 28 : #include <vector> 29 : #include <limits> 30 : 31 : 32 : namespace PLMD { 33 : namespace ves { 34 : 35 : 36 0 : void FermiSwitchingFunction::registerKeywords( Keywords& keys ) { 37 0 : keys.add("compulsory","R_0","the value of R_0 in the switching function"); 38 0 : keys.add("compulsory","FERMI_LAMBDA","the value of lambda in the Fermi-type switching function (only needed for TYPE=FERMI)."); 39 0 : keys.add("optional","FERMI_EXP_MAX","only needed for TYPE=FERMI"); 40 0 : } 41 : 42 3 : void FermiSwitchingFunction::set(const std::string& definition,std::string& errormsg) { 43 3 : std::vector<std::string> data=Tools::getWords(definition); 44 3 : if( data.size()<1 ) { 45 : errormsg="missing all input for switching function"; 46 : return; 47 : } 48 3 : std::string name=data[0]; 49 : data.erase(data.begin()); 50 3 : if(name!="FERMI") {errormsg="only FERMI is supported";} 51 3 : type=fermi; 52 : // 53 3 : bool found_r0=Tools::parse(data,"R_0",r0_); 54 3 : if(!found_r0) {errormsg="R_0 is required";} 55 : 56 : // 57 3 : fermi_exp_max_=std::numeric_limits<double>::max(); 58 3 : Tools::parse(data,"FERMI_EXP_MAX",fermi_exp_max_); 59 : // 60 3 : bool found_lambda=Tools::parse(data,"FERMI_LAMBDA",fermi_lambda_); 61 3 : if(!found_lambda) {errormsg="FERMI_LAMBDA is required for FERMI";} 62 3 : if( !data.empty() ) { 63 : errormsg="found the following rogue keywords in switching function input : "; 64 0 : for(unsigned i=0; i<data.size(); ++i) errormsg = errormsg + data[i] + " "; 65 : } 66 3 : init=true; 67 3 : if(errormsg.size()>0) {init=false;} 68 3 : } 69 : 70 0 : std::string FermiSwitchingFunction::description() const { 71 0 : std::ostringstream ostr; 72 0 : ostr<<1./invr0_<<". Using "; 73 0 : if(type==fermi) { 74 0 : ostr<< "fermi switching function with parameter"; 75 0 : ostr<< " lambda="<<fermi_lambda_; 76 : } 77 : else { 78 0 : plumed_merror("Unknown switching function type"); 79 : } 80 0 : return ostr.str(); 81 0 : } 82 : 83 : 84 3263 : double FermiSwitchingFunction::calculate(double distance, double& dfunc) const { 85 3263 : plumed_massert(init,"you are trying to use an unset FermiSwitchingFunction"); 86 3263 : double rdist=fermi_lambda_*(distance-r0_); 87 3263 : if(rdist >= fermi_exp_max_) {rdist = fermi_exp_max_;} 88 3263 : double result = 1.0/(1.0+exp(rdist)); 89 3263 : dfunc=-fermi_lambda_*exp(rdist)*result*result; 90 : // this is because calculate() sets dfunc to the derivative divided times the distance. 91 : // (I think this is misleading and I would like to modify it - GB) 92 : // dfunc/=distance; 93 : // 94 3263 : return result; 95 : } 96 : 97 : 98 3 : FermiSwitchingFunction::FermiSwitchingFunction(): 99 3 : init(false), 100 3 : type(fermi), 101 3 : r0_(0.0), 102 3 : invr0_(0.0), 103 3 : fermi_lambda_(1.0), 104 3 : fermi_exp_max_(100.0) 105 : { 106 3 : } 107 : 108 0 : FermiSwitchingFunction::FermiSwitchingFunction(const FermiSwitchingFunction&sf): 109 0 : init(sf.init), 110 0 : type(sf.type), 111 0 : r0_(sf.r0_), 112 0 : invr0_(sf.invr0_), 113 0 : fermi_lambda_(sf.fermi_lambda_), 114 0 : fermi_exp_max_(sf.fermi_exp_max_) 115 : { 116 0 : } 117 : 118 0 : void FermiSwitchingFunction::set(const double r0, const double fermi_lambda, const double fermi_exp_max) { 119 0 : init=true; 120 0 : type=fermi; 121 0 : r0_=r0; 122 0 : fermi_lambda_=fermi_lambda; 123 0 : if(fermi_exp_max>0.0) { 124 0 : fermi_exp_max_=fermi_exp_max; 125 : } 126 : else { 127 0 : fermi_exp_max_=100.0; 128 : } 129 : 130 0 : } 131 : 132 0 : double FermiSwitchingFunction::get_r0() const { 133 0 : return r0_; 134 : } 135 : 136 : 137 3 : FermiSwitchingFunction::~FermiSwitchingFunction() { 138 3 : } 139 : 140 : 141 : } 142 : }