diff --git a/developer-doc/usingDoxygen.txt b/developer-doc/usingDoxygen.txt index 17faf15007ef398e63da31ca439f90ddcf6304eb..f115a9c3c95062f35c3542b5793f0cf6b6eafdc3 100644 --- a/developer-doc/usingDoxygen.txt +++ b/developer-doc/usingDoxygen.txt @@ -100,6 +100,20 @@ compulsory keyword and do not specify a default value then the code will automat In addition, if the vector you pass to PLMD::Action::parseVector and PLMD::Action::parseNumberedVector has a size greater than 0 plumed will assume that the input should contain a vector of this size and will complain if it finds a different sized vector. +\section reserved Reserved Keywords + +To maintain some consistency for end users of the code certain keywords (e.g. ARG, PERIODIC) are reserved. +The reserved keywords for PLMD::Colvar, PLMD::Function and PLMD::Bias are explained inside the documentation for +these actions. To use one of the registered keywords you shold insert the following command into the registerKeywords +method of your new function. + +\verbatim +keys.use( keyword ); +\endverbatim + +where <i> keyword </i> is a string that tells the method which reserved keyword you wish to use. To be clear +when you use a reserved keyword all the parsing and registering for it is looked after automatically. + \section errors Generating errors You may need to check for other mistakes in input. When you find these mistakes you can report them to users using PLMD::Action::error. This routine will diff --git a/src/ActionWithArguments.cpp b/src/ActionWithArguments.cpp index 020d179bd57fe7cb14f3772bb4d643a3a62351af..48da48e23eb3108d2388b6507c46af6ef8fb2f0d 100644 --- a/src/ActionWithArguments.cpp +++ b/src/ActionWithArguments.cpp @@ -7,7 +7,7 @@ using namespace std; using namespace PLMD; void ActionWithArguments::registerKeywords(Keywords& keys){ - keys.add("compulsory","ARG","the input for this action is the output from one or more other actions. The particular output that you used is referenced using that action of interests label. If the label appears on its own then the default output is taken. If * appears then the default output from all actions is taken. Some actions have multi-component outputs, each component of the output has a specific label so for instance an action labelled dist may have three componets x, y and z. To take just the x component you should use dist.x, if you wish to take all three components then use dist.*"); + keys.reserve("compulsory","ARG","the input for this action is the output from one or more other actions. The particular output that you used is referenced using that action of interests label. If the label appears on its own then the value of the relevant Action is taken. If * or *.* appears the information from all arguments is taken. Some actions have multi-component outputs, each component of the output has a specific label so for instance an action labelled dist may have three componets x, y and z. To take just the x component you should use dist.x, if you wish to take all three components then use dist.*"); } void ActionWithArguments::parseArgumentList(const std::string&key,std::vector<Value*>&arg){ @@ -79,7 +79,7 @@ void ActionWithArguments::requestArguments(const vector<Value*> &arg){ name=fullname; } ActionWithValue* action=plumed.getActionSet().selectWithLabel<ActionWithValue*>(name); - if(!action) error("cannot find action named (in requestArguments - this is weird)" + name); + plumed_massert(action,"cannot find action named (in requestArguments - this is weird)" + name); addDependency(action); } } @@ -88,17 +88,17 @@ ActionWithArguments::ActionWithArguments(const ActionOptions&ao): Action(ao), lockRequestArguments(false) { - vector<Value*> arg; - parseArgumentList("ARG",arg); - - if(arg.size()>0){ - log.printf(" with arguments"); - for(unsigned i=0;i<arg.size();i++) log.printf(" %s",arg[i]->getName().c_str()); - log.printf("\n"); + if( keywords.exists("ARG") ){ + vector<Value*> arg; + parseArgumentList("ARG",arg); + + if(arg.size()>0){ + log.printf(" with arguments"); + for(unsigned i=0;i<arg.size();i++) log.printf(" %s",arg[i]->getName().c_str()); + log.printf("\n"); + } + requestArguments(arg); } - - requestArguments(arg); - } void ActionWithArguments::calculateNumericalDerivatives(){ diff --git a/src/ActionWithArguments.h b/src/ActionWithArguments.h index dc87a4547dc6cfcb04ab404d3b1fc8ef6072f402..e55ff9a0a9ec404c8b2111acdc6903a8a8c0be66 100644 --- a/src/ActionWithArguments.h +++ b/src/ActionWithArguments.h @@ -14,9 +14,12 @@ This is used in PLMD::Function and PLMD::Bias */ //+ENDDEVELDOC -/// Action which takes other Action's as arguments. -/// Arguments are objects of type PLMD::Value, and -/// are addressed using the ARG= keyword on the directive line +/// PLMD::Action objects that inherit from PLMD::ActionWithArguments take +/// values and components calculated in other PLMD::Action objects and +/// use this information to calculate some new function. If you have +/// only one list of arguments you should use the reserved keyword <b> ARG </b> +/// when you use parseArgumentList. + class ActionWithArguments: public virtual Action { diff --git a/src/BiasExternal.cpp b/src/BiasExternal.cpp index b20aa37fdbc9d6e4b12ce4a0a9a0e699253f5af4..3fd4320da6a8a32b0b7dc304c0b5ec5c4f922263 100644 --- a/src/BiasExternal.cpp +++ b/src/BiasExternal.cpp @@ -42,6 +42,7 @@ PLUMED_REGISTER_ACTION(BiasExternal,"EXTERNAL") void BiasExternal::registerKeywords(Keywords& keys){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","FILE","the name of the file containing the external potential"); keys.addFlag("NOSPLINE",false,"specifies that no spline interpolation is to be used when calculating the energy and forces due to the external potential"); keys.addFlag("SPARSE",false,"specifies that the external potential uses a sparse grid"); diff --git a/src/BiasLWalls.cpp b/src/BiasLWalls.cpp index dae30cc601be210c894f9cdb2b983a4e475d6185..b4139bb78880954e6365668a4b23723430992a45 100644 --- a/src/BiasLWalls.cpp +++ b/src/BiasLWalls.cpp @@ -54,6 +54,7 @@ PLUMED_REGISTER_ACTION(BiasLWalls,"LOWER_WALLS") void BiasLWalls::registerKeywords(Keywords& keys){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall."); keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall."); keys.add("compulsory","OFFSET","0.0","the offset for the start of the wall. The o_i in the expression for a wall."); diff --git a/src/BiasMetaD.cpp b/src/BiasMetaD.cpp index cd442db20311e13fdc72cb4d10f804049b4007f9..ab152cb81d99e4fe0d6a1314b197c523a5772e71 100644 --- a/src/BiasMetaD.cpp +++ b/src/BiasMetaD.cpp @@ -115,6 +115,7 @@ PLUMED_REGISTER_ACTION(BiasMetaD,"METAD") void BiasMetaD::registerKeywords(Keywords& keys){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","SIGMA","the widths of the Gaussian hills"); keys.add("compulsory","HEIGHT","the heights of the Gaussian hills"); keys.add("compulsory","PACE","the frequency for hill addition"); diff --git a/src/BiasMovingRestraint.cpp b/src/BiasMovingRestraint.cpp index 8b5fcff9f9caf529faf3d1c967264efd2d801745..bcc76bb5395d9179d76f07d4fc274048b8eecadb 100644 --- a/src/BiasMovingRestraint.cpp +++ b/src/BiasMovingRestraint.cpp @@ -92,6 +92,7 @@ PLUMED_REGISTER_ACTION(BiasMovingRestraint,"MOVINGRESTRAINT") void BiasMovingRestraint::registerKeywords( Keywords& keys ){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","VERSE","B","Tells plumed whether the restraint is only acting for CV larger (U) or smaller (L) than the restraint or whether it is acting on both sides (B)"); keys.add("numbered","STEP","This keyword appears multiple times as STEPx with x=0,1,2,...,n. Each value given represents the MD step at which the restraint parameters take the values KAPPAx and ATx."); keys.add("numbered","AT","ATx is equal to the position of the restraint at time STEPx. For intermediate times this parameter is linearly interpolated. If no ATx is specified for STEPx then the values of AT are kept constant during the interval of time between STEPx-1 and STEPx."); diff --git a/src/BiasRatchet.cpp b/src/BiasRatchet.cpp index 8480557cb3a77fea1768244d7d49289206f07300..e65bb71c38f9be2bd135906f0fe957203886bdaf 100644 --- a/src/BiasRatchet.cpp +++ b/src/BiasRatchet.cpp @@ -58,6 +58,7 @@ PLUMED_REGISTER_ACTION(BiasRatchet,"ABMD") void BiasRatchet::registerKeywords(Keywords& keys){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","TO","The array of a values in the above equation"); keys.add("compulsory","KAPPA","The array of force constants."); keys.add("compulsory","MIN","Also the array of a values in the above equation - I don't understand."); diff --git a/src/BiasRestraint.cpp b/src/BiasRestraint.cpp index 48f025607dd8bef762a66cdbd562585500201047..5870073b02c5a3c60c9522edaf4583c16050fdb6 100644 --- a/src/BiasRestraint.cpp +++ b/src/BiasRestraint.cpp @@ -51,6 +51,7 @@ PLUMED_REGISTER_ACTION(BiasRestraint,"RESTRAINT") void BiasRestraint::registerKeywords(Keywords& keys){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","SLOPE","0.0","specifies that the restraint is linear and what the values of the force constants on each of the variables are"); keys.add("compulsory","KAPPA","0.0","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); keys.add("compulsory","AT","the position of the restraint"); diff --git a/src/BiasUWalls.cpp b/src/BiasUWalls.cpp index 41d6a45d5cbd86ef5527d9e7973cd8558ad0a7de..fc60c47813a06ca4c33870d938982f95aa591df2 100644 --- a/src/BiasUWalls.cpp +++ b/src/BiasUWalls.cpp @@ -54,6 +54,7 @@ PLUMED_REGISTER_ACTION(BiasUWalls,"UPPER_WALLS") void BiasUWalls::registerKeywords(Keywords& keys){ Bias::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall."); keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall."); keys.add("compulsory","OFFSET","0.0","the offset for the start of the wall. The o_i in the expression for a wall."); diff --git a/src/Function.cpp b/src/Function.cpp index b77092de7a323527175048fbdde92424fda9221a..682fb7eb13e83fd71c45cb6615bbb787e3b520c4 100644 --- a/src/Function.cpp +++ b/src/Function.cpp @@ -4,6 +4,13 @@ using namespace PLMD; using namespace std; +void Function::registerKeywords(Keywords& keys){ + Action::registerKeywords(keys); + ActionWithValue::registerKeywords(keys); + ActionWithArguments::registerKeywords(keys); + keys.reserve("compulsory","PERIODIC","if the output of your function is periodic then you should specify the periodicity of the function. If the output is not periodic you must state this using PERIODIC=NO"); +} + Function::Function(const ActionOptions&ao): Action(ao), ActionWithValue(ao), @@ -15,6 +22,18 @@ void Function::addValueWithDerivatives(){ plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values"); ActionWithValue::addValueWithDerivatives(); getPntrToValue()->resizeDerivatives(getNumberOfArguments()); + + if( keywords.exists("PERIODIC") ){ + double min(0),max(0); std::vector<std::string> period; + parseVector("PERIODIC",period); + if(period.size()==1 && period[0]=="NO"){ + setNotPeriodic(); + } else if(period.size()==2 && Tools::convert(period[0],min) && Tools::convert(period[1],max)){ + setPeriodic(min,max); + } else error("missing PERIODIC keyword"); + } else { + plumed_massert(0,"You should use the reserved keyword PERIODIC to read in the periodicity for single value functions"); + } } void Function::addComponentWithDerivatives( const std::string& name ){ @@ -40,12 +59,3 @@ void Function::apply(){ getPntrToArgument(i)->addForce(f[i]); } } - -void Function::registerKeywords(Keywords& keys){ - Action::registerKeywords(keys); - ActionWithValue::registerKeywords(keys); - ActionWithArguments::registerKeywords(keys); - keys.reserve("compulsory","PERIODIC","if the output of your function is periodic then you should specify the periodicity of the function. If the output is not periodic you must state this using PERIODIC=NO"); -} - - diff --git a/src/FunctionCombine.cpp b/src/FunctionCombine.cpp index e9ea9e02180fee7a7262d15860aa7028956e5dcb..ccda34cd73fd4d35f56586ea165b3661695c4e7c 100644 --- a/src/FunctionCombine.cpp +++ b/src/FunctionCombine.cpp @@ -73,18 +73,7 @@ powers(getNumberOfArguments(),1.0) for(unsigned i=0;i<coefficients.size();i++) coefficients[i]*=(1.0/n); } -<<<<<<< HEAD - addValueWithDerivatives(); getPntrToComponent(0)->resizeDerivatives(getNumberOfArguments()); -======= addValueWithDerivatives(); ->>>>>>> 6166262... Made it so that we don't have to resize the values in the individual - double min(0),max(0); std::vector<std::string> period; - parseVector("PERIODIC",period); - if(period.size()==1 && period[0]=="NO"){ - setNotPeriodic(); - } else if(period.size()==2 && Tools::convert(period[0],min) && Tools::convert(period[1],max)){ - setPeriodic(min,max); - } else error("missing PERIODIC keyword"); checkRead(); log.printf(" with coefficients:"); diff --git a/src/FunctionMatheval.cpp b/src/FunctionMatheval.cpp index 970c51abc04c6f36c1f96045aec935efca986479..b58f73a1a8de1a33818d150ebd1a0856923f09e3 100644 --- a/src/FunctionMatheval.cpp +++ b/src/FunctionMatheval.cpp @@ -65,7 +65,6 @@ void FunctionMatheval::registerKeywords(Keywords& keys){ keys.use("ARG"); keys.use("PERIODIC"); keys.add("compulsory","FUNC","the function you wish to evaluate"); keys.add("optional","VAR","the names to give each of the arguments in the function. If you have up to three arguments in your function you can use x, y and z to refer to them. Otherwise you must use this flag to give your variables names."); - } FunctionMatheval::FunctionMatheval(const ActionOptions&ao): @@ -85,18 +84,7 @@ names(getNumberOfArguments()) } assert(var.size()==getNumberOfArguments()); parse("FUNC",func); -<<<<<<< HEAD - addValueWithDerivatives(); getPntrToComponent(0)->resizeDerivatives(getNumberOfArguments()); -======= addValueWithDerivatives(); ->>>>>>> 6166262... Made it so that we don't have to resize the values in the individual - double min(0),max(0); std::vector<std::string> period; - parseVector("PERIODIC",period); - if(period.size()==1 && period[0]=="NO"){ - setNotPeriodic(); - } else if(period.size()==2 && Tools::convert(period[0],min) && Tools::convert(period[1],max)){ - setPeriodic(min,max); - } else error("missing PERIODIC keyword"); checkRead(); evaluator=evaluator_create(const_cast<char*>(func.c_str())); diff --git a/src/GenericDumpDerivatives.cpp b/src/GenericDumpDerivatives.cpp index 127a687b9bc39c82429a238df4ef3c5d4507334f..35609c0747f3937f332e85e8b510cb0afcb1da6c 100644 --- a/src/GenericDumpDerivatives.cpp +++ b/src/GenericDumpDerivatives.cpp @@ -53,6 +53,7 @@ void GenericDumpDerivatives::registerKeywords(Keywords& keys){ Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","STRIDE","1","the frequency with which the derivatives should be output"); keys.add("compulsory","FILE","the name of the file on which to output the derivatives"); keys.add("compulsory","FMT","%15.10f","the format with which the derivatives should be output"); diff --git a/src/GenericDumpForces.cpp b/src/GenericDumpForces.cpp index 2cde9f2458710c0fd24780527f48f74a27b350a6..cd5c090f671646c47c908de6ae9c313185202a13 100644 --- a/src/GenericDumpForces.cpp +++ b/src/GenericDumpForces.cpp @@ -53,6 +53,7 @@ void GenericDumpForces::registerKeywords(Keywords& keys){ Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","STRIDE","1","the frequency with which the forces should be output"); keys.add("compulsory","FILE","the name of the file on which to output the forces"); } diff --git a/src/GenericPrint.cpp b/src/GenericPrint.cpp index 5dbab1f0e9fc8825ac295bb901daa5d2ca7a6b42..221f5ba1223b2a34fdf39b1fad9f0299d0f33b92 100644 --- a/src/GenericPrint.cpp +++ b/src/GenericPrint.cpp @@ -60,6 +60,7 @@ void GenericPrint::registerKeywords(Keywords& keys){ Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); + keys.use("ARG"); keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output"); keys.add("compulsory","FILE","the name of the file on which to output these quantities"); keys.add("optional","FMT","the format that should be used to output real numbers"); diff --git a/src/Keywords.cpp b/src/Keywords.cpp index 1b7042ae42c6860a4fb3ad055ca09d0160b2621b..11f83509f4b6b1f67fb338a5fae3f48492f02d39 100644 --- a/src/Keywords.cpp +++ b/src/Keywords.cpp @@ -22,14 +22,31 @@ KeyType::KeyType( const std::string& type ){ } } +void Keywords::reserve( const std::string t, const std::string k, const std::string d ){ + plumed_assert( !exists(k) ); plumed_assert( t!="flag"); // Cannot reserve flags at the moment - if you need it let me know + plumed_assert( !reserved(k) ); + reserved_types.push_back( KeyType(t) ); reserved_keys.push_back(k); reserved_documentation.push_back(d); +} + +void Keywords::use( const std::string k ){ + plumed_assert( reserved(k) ); + for(unsigned i=0;i<reserved_keys.size();++i){ + if(reserved_keys[i]==k){ + types.push_back( reserved_types[i] ); keys.push_back( reserved_keys[i] ); documentation.push_back( reserved_documentation[i] ); + } + } +} + void Keywords::add( const std::string t, const std::string k, const std::string d ){ plumed_assert( !exists(k) ); plumed_assert( t!="flag"); // Use addFlag to add flags + plumed_assert( !reserved(k) ); types.push_back( KeyType(t) ); keys.push_back(k); documentation.push_back(d); //defaults.push_back(false); } void Keywords::add( const std::string t, const std::string k, const std::string def, const std::string d ){ plumed_assert( !exists(k) ); plumed_assert( t=="compulsory" ); // An optional keyword can't have a default + plumed_assert( !reserved(k) ); types.push_back( KeyType(t) ); keys.push_back(k); documentation.push_back( "( default=" + def + " ) " + d ); numdefs.insert( std::pair<std::string,std::string>(k,def) ); @@ -37,6 +54,7 @@ void Keywords::add( const std::string t, const std::string k, const std::string void Keywords::addFlag( const std::string k, const bool def, const std::string d ){ plumed_assert( !exists(k) ); std::string defstr, flag="flag"; + plumed_assert( !reserved(k) ); if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; } types.push_back( KeyType(flag) ); keys.push_back(k); documentation.push_back( defstr + d ); //defaults.push_back(def); booldefs.insert( std::pair<std::string,bool>(k,def) ); @@ -122,6 +140,16 @@ bool Keywords::exists( const std::string k ) const { return false; } +bool Keywords::reserved( const std::string k ) const { + plumed_massert( reserved_keys.size()==reserved_documentation.size(), "documentation doesn't match keys" ); + plumed_massert( reserved_keys.size()==reserved_types.size(), "types doesn't match keys" ); + + for(unsigned i=0;i<reserved_keys.size();++i){ + if( reserved_keys[i]==k ) return true; + } + return false; +} + void Keywords::print_html() const { unsigned nkeys=0; for(unsigned i=0;i<keys.size();++i){ diff --git a/src/Keywords.h b/src/Keywords.h index 9e697cff2259117af9a096d6afefece8cbe74098..3af6b06ffa60752b3978a7697e85b72735927e5f 100644 --- a/src/Keywords.h +++ b/src/Keywords.h @@ -30,6 +30,12 @@ public: class Keywords{ friend class Action; private: +/// Whether the keyword is compulsory, optional... + std::vector<KeyType> reserved_types; +/// The names of the keyword + std::vector<std::string> reserved_keys; +/// The documentation for the keywords + std::vector<std::string> reserved_documentation; /// Whether the keyword is compulsory, optional... std::vector<KeyType> types; /// The names of the keyword @@ -53,6 +59,10 @@ private: /// Return the number of defined keywords unsigned size() const; public: +/// Reserve a keyword + void reserve( const std::string t, const std::string k, const std::string d ); +/// Use one of the reserved keywords + void use( const std::string k ); /// Add a new keyword of type t with name k and description d void add( const std::string t, const std::string k, const std::string d ); /// Add a new compulsory keyword (t must equal compulsory) with name k, default value def and description d @@ -67,6 +77,8 @@ public: // unsigned size() const; /// Check if there is a keyword with name k bool exists( const std::string k ) const ; +/// Check the keyword k has been reserved + bool reserved( const std::string k ) const ; /// Check if the keyword with name k has style t bool style( const std::string k, const std::string t ) const ; // /// Print the documentation to the log file (used by PLMD::Action::error)