Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-2017 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 : #ifndef __PLUMED_function_LessThan_h 23 : #define __PLUMED_function_LessThan_h 24 : #include "FunctionSetup.h" 25 : #include "tools/SwitchingFunction.h" 26 : 27 : #include <cmath> 28 : 29 : namespace PLMD { 30 : namespace function { 31 : 32 244 : class LessThan { 33 : public: 34 : bool squared; 35 : #ifdef __PLUMED_HAS_OPENACC 36 : SwitchingFunctionAccelerable switchingFunction; 37 : #else 38 : SwitchingFunction switchingFunction; 39 : #endif //__PLUMED_HAS_OPENACC 40 : static void registerKeywords( Keywords& keys ); 41 : static void read( LessThan& func, 42 : ActionWithArguments* action, 43 : FunctionOptions& options ); 44 : static void calc( const LessThan& func, 45 : bool noderiv, 46 : const View<const double>& args, 47 : FunctionOutput& funcout ); 48 : #ifdef __PLUMED_HAS_OPENACC 49 : void toACCDevice() const { 50 : #pragma acc enter data copyin(this[0:1],squared) 51 : switchingFunction.toACCDevice(); 52 : } 53 : void removeFromACCDevice() const { 54 : switchingFunction.removeFromACCDevice(); 55 : #pragma acc exit data delete(squared,this[0:1]) 56 : } 57 : #endif //__PLUMED_HAS_OPENACC 58 : }; 59 : 60 496 : void LessThan::registerKeywords(Keywords& keys) { 61 496 : keys.add("compulsory","NN","6","The n parameter of the switching function "); 62 496 : keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); 63 496 : keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); 64 496 : keys.add("compulsory","R_0","The r_0 parameter of the switching function"); 65 496 : keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous switching function defined above. " 66 : "The following provides information on the switching functions that are available. " 67 : "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); 68 496 : keys.addFlag("SQUARED",false,"is the input quantity the square of the value that you would like to apply the switching function to"); 69 992 : keys.setValueDescription("scalar/vector/matrix","a function that is one if the input is less than a threshold"); 70 496 : } 71 : 72 122 : void LessThan::read( LessThan& func, ActionWithArguments* action, FunctionOptions& options ) { 73 122 : options.derivativeZeroIfValueIsZero = true; 74 122 : if( action->getNumberOfArguments()!=1 ) { 75 46 : ActionWithVector* av = dynamic_cast<ActionWithVector*>( action ); 76 46 : if( !av || (av && action->getNumberOfArguments()-av->getNumberOfMasks()!=1) ) { 77 0 : action->error("should only be one argument to less_than actions"); 78 : } 79 : } 80 122 : if( action->getPntrToArgument(0)->isPeriodic() ) { 81 0 : action->error("cannot use this function on periodic functions"); 82 : } 83 : 84 : 85 : std::string errors; 86 : std::string sfinput; 87 244 : action->parse("SWITCH",sfinput); 88 122 : if(sfinput.length()>0) { 89 122 : func.switchingFunction.set(sfinput,errors); 90 122 : if( errors.length()!=0 ) { 91 0 : action->error("problem reading SWITCH keyword : " + errors ); 92 : } 93 : } else { 94 0 : int nn=6; 95 0 : int mm=0; 96 0 : double d0=0.0; 97 0 : double r0=0.0; 98 0 : action->parse("R_0",r0); 99 0 : if(r0<=0.0) { 100 0 : action->error("R_0 should be explicitly specified and positive"); 101 : } 102 0 : action->parse("D_0",d0); 103 0 : action->parse("NN",nn); 104 0 : action->parse("MM",mm); 105 0 : func.switchingFunction.set(nn,mm,r0,d0); 106 : } 107 122 : action->log<<" using switching function with cutoff "<<func.switchingFunction.description()<<"\n"; 108 122 : action->parseFlag("SQUARED",func.squared); 109 122 : if( func.squared ) { 110 1 : action->log<<" input quantity is square of quantity that switching function acts upon\n"; 111 : } 112 122 : } 113 : 114 352964 : void LessThan::calc( const LessThan& func, 115 : bool noderiv, 116 : const View<const double>& args, 117 : FunctionOutput& funcout ) { 118 : double d; 119 352964 : if( func.squared ) { 120 13401 : funcout.values[0] = func.switchingFunction.calculateSqr( args[0], d ); 121 13401 : if( !noderiv ) { 122 6700 : funcout.derivs[0][0] = d/2; 123 : } 124 : } else { 125 339563 : funcout.values[0] = func.switchingFunction.calculate( args[0], d ); 126 339563 : if( !noderiv ) { 127 98868 : funcout.derivs[0][0] = args[0]*d; 128 : } 129 : } 130 352964 : } 131 : 132 : } 133 : } 134 : 135 : 136 : #endif //__PLUMED_function_LessThan_h