double SwitchingFunction::calculate(double distance,double&dfunc)const{ plumed_massert(init,"you are trying to use an unset SwitchingFunction"); if(distance>dmax){ dfunc=0.0; return 0.0; } const double rdist = (distance-d0)*invr0; double result; if(rdist<=0.){ result=1.; dfunc=0.0; }else{ if(type==smap){ double sx=c*pow( rdist, a ); result=pow( 1.0 + sx, d ); dfunc=-b*sx/rdist*result/(1.0+sx); } else if(type==rational){ result=do_rational(rdist,dfunc,nn,mm); }else if(type==exponential){ result=exp(-rdist); dfunc=-result; }else if(type==nativeq){ double rdist2 = beta*(distance - lambda * ref); double exprdist=exp(rdist2); result=1./(1.+exprdist); dfunc=-exprdist/(1.+exprdist)/(1.+exprdist); }else if(type==gaussian){ result=exp(-0.5*rdist*rdist); dfunc=-rdist*result; }else if(type==cubic){ double tmp1=rdist-1, tmp2=(1+2*rdist); result=tmp1*tmp1*tmp2; dfunc=2*tmp1*tmp2 + 2*tmp1*tmp1; }else if(type==tanh){ double tmp1=std::tanh(rdist); result = 1.0 - tmp1; dfunc=-(1-tmp1*tmp1); #ifdef __PLUMED_HAS_MATHEVAL }else if(type==matheval){ result=evaluator_evaluate_x(evaluator,rdist); dfunc=evaluator_evaluate_x(evaluator_deriv,rdist); #endif }else plumed_merror("Unknown switching function type"); // this is for the chain rule: dfunc*=invr0; // this is because calculate() sets dfunc to the derivative divided times the distance. // (I think this is misleading and I would like to modify it - GB) dfunc/=distance; } result=result*stretch+shift; dfunc*=stretch; return result; }
double SwitchingFunction::calculateSqr(double distance2,double&dfunc)const{ if(type==rational && nn%2==0 && mm%2==0 && d0==0.0){ if(distance2>dmax_2){ dfunc=0.0; return 0.0; } const double rdist_2 = distance2*invr0_2; double result=do_rational(rdist_2,dfunc,nn/2,mm/2); // chain rule: dfunc*=2*invr0_2; // stretch: result=result*stretch+shift; dfunc*=stretch; return result; } else { double distance=std::sqrt(distance2); return calculate(distance,dfunc); } }
double SwitchingFunction::calculate(double distance,double&dfunc)const{ plumed_massert(init,"you are trying to use an unset SwitchingFunction"); if(distance>dmax){ dfunc=0.0; return 0.0; } const double rdist = (distance-d0)*invr0; double result; if(rdist<=0.){ result=1.; dfunc=0.0; }else{ if(type==smap){ double sx=c*pow( rdist, a ); result=pow( 1.0 + sx, d ); dfunc=-b*sx/rdist*result/(1.0+sx); } else if(type==rational){ result=do_rational(rdist,dfunc,nn,mm); }else if(type==exponential){ result=exp(-rdist); dfunc=-result; }else if(type==gaussian){ result=exp(-0.5*rdist*rdist); dfunc=-rdist*result; }else plumed_merror("Unknown switching function type"); // this is for the chain rule: dfunc*=invr0; // this is because calculate() sets dfunc to the derivative divided times the distance. // (I think this is misleading and I would like to modify it - GB) dfunc/=distance; } result=result*stretch+shift; dfunc*=stretch; return result; }