Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-2019 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 : #include "ActionWithValue.h" 23 : #include "tools/Exception.h" 24 : #include "tools/OpenMP.h" 25 : 26 : using namespace std; 27 : namespace PLMD { 28 : 29 3757 : void ActionWithValue::registerKeywords(Keywords& keys) { 30 : keys.setComponentsIntroduction("By default the value of the calculated quantity can be referenced elsewhere in the " 31 : "input file by using the label of the action. Alternatively this Action can be used " 32 : "to calculate the following quantities by employing the keywords listed " 33 : "below. These quantities can be referenced elsewhere in the input by using this Action's " 34 7514 : "label followed by a dot and the name of the quantity required from the list below."); 35 11271 : keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically"); 36 3757 : } 37 : 38 0 : void ActionWithValue::noAnalyticalDerivatives(Keywords& keys) { 39 0 : keys.remove("NUMERICAL_DERIVATIVES"); 40 0 : keys.addFlag("NUMERICAL_DERIVATIVES",true,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used"); 41 0 : } 42 : 43 1052 : void ActionWithValue::componentsAreNotOptional(Keywords& keys) { 44 : keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quantities can " 45 : "be referenced elsewhere in the input by using this Action's label followed by a " 46 2104 : "dot and the name of the quantity required from the list below."); 47 1052 : } 48 : 49 183 : void ActionWithValue::useCustomisableComponents(Keywords& keys) { 50 : keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the " 51 : "actions input file. However, in addition to the components that can be customized the " 52 366 : "following quantities will always be output"); 53 183 : } 54 : 55 3579 : ActionWithValue::ActionWithValue(const ActionOptions&ao): 56 : Action(ao), 57 : noderiv(true), 58 7158 : numericalDerivatives(false) 59 : { 60 10297 : if( keywords.exists("NUMERICAL_DERIVATIVES") ) parseFlag("NUMERICAL_DERIVATIVES",numericalDerivatives); 61 3579 : if(numericalDerivatives) log.printf(" using numerical derivatives\n"); 62 3579 : } 63 : 64 3579 : ActionWithValue::~ActionWithValue() { 65 : // empty destructor to delete unique_ptr 66 3579 : } 67 : 68 389626 : void ActionWithValue::clearInputForces() { 69 2226958 : for(unsigned i=0; i<values.size(); i++) values[i]->clearInputForce(); 70 389626 : } 71 : 72 392386 : void ActionWithValue::clearDerivatives() { 73 392386 : unsigned nt = OpenMP::getNumThreads(); 74 1175191 : #pragma omp parallel num_threads(nt) 75 : { 76 : #pragma omp for 77 782805 : for(unsigned i=0; i<values.size(); i++) values[i]->clearDerivatives(); 78 : } 79 392386 : } 80 : 81 : // -- These are the routine for copying the value pointers to other classes -- // 82 : 83 10284026 : bool ActionWithValue::exists( const std::string& name ) const { 84 197545472 : for(unsigned i=0; i<values.size(); ++i) { 85 88514048 : if (values[i]->name==name) return true; 86 : } 87 : return false; 88 : } 89 : 90 25340 : Value* ActionWithValue::copyOutput( const std::string& name ) const { 91 22617536 : for(unsigned i=0; i<values.size(); ++i) { 92 11308768 : if (values[i]->name==name) return values[i].get(); 93 : } 94 0 : plumed_merror("there is no pointer with name " + name); 95 : return NULL; 96 : } 97 : 98 10303 : Value* ActionWithValue::copyOutput( const unsigned& n ) const { 99 20606 : plumed_massert(n<values.size(),"you have requested a pointer that is out of bounds"); 100 10303 : return values[n].get(); 101 : } 102 : 103 : // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- // 104 : 105 55 : void ActionWithValue::addValue() { 106 55 : plumed_massert(values.empty(),"You have already added the default value for this action"); 107 55 : values.emplace_back(new Value(this,getLabel(), false ) ); 108 55 : } 109 : 110 1942 : void ActionWithValue::addValueWithDerivatives() { 111 1942 : plumed_massert(values.empty(),"You have already added the default value for this action"); 112 1942 : values.emplace_back(new Value(this,getLabel(), true ) ); 113 1942 : } 114 : 115 1464 : void ActionWithValue::setNotPeriodic() { 116 1464 : plumed_massert(values.size()==1,"The number of components is not equal to one"); 117 2928 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); 118 2928 : values[0]->min=0; values[0]->max=0; 119 1464 : values[0]->setupPeriodicity(); 120 1464 : } 121 : 122 533 : void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) { 123 533 : plumed_massert(values.size()==1,"The number of components is not equal to one"); 124 1066 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); 125 533 : values[0]->setDomain( min, max ); 126 533 : } 127 : 128 15766034 : Value* ActionWithValue::getPntrToValue() { 129 : plumed_dbg_massert(values.size()==1,"The number of components is not equal to one"); 130 : plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default"); 131 15766034 : return values[0].get(); 132 : } 133 : 134 : // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- // 135 : 136 22597 : void ActionWithValue::addComponent( const std::string& name ) { 137 22597 : if( !keywords.outputComponentExists(name,true) ) { 138 0 : plumed_merror("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " 139 0 : "registerKeywords as described in the developer docs."); 140 : } 141 67791 : std::string thename; thename=getLabel() + "." + name; 142 37339284 : for(unsigned i=0; i<values.size(); ++i) { 143 55941135 : plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components"); 144 18647045 : plumed_massert(values[i]->name!=thename,"there is already a value with this name: "+thename); 145 37294090 : plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" 146 0 : "Remove the line addComponent(\"bias\") from your bias."); 147 : } 148 22597 : values.emplace_back(new Value(this,thename, false ) ); 149 45194 : std::string msg=" added component to this action: "+thename+" \n"; 150 22597 : log.printf(msg.c_str()); 151 22597 : } 152 : 153 10529 : void ActionWithValue::addComponentWithDerivatives( const std::string& name ) { 154 10529 : if( !keywords.outputComponentExists(name,true) ) { 155 0 : plumed_merror("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " 156 0 : "registerKeywords as described in the developer doc."); 157 : } 158 31587 : std::string thename; thename=getLabel() + "." + name; 159 4883098 : for(unsigned i=0; i<values.size(); ++i) { 160 7293060 : plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components"); 161 2431020 : plumed_massert(values[i]->name!=thename,"there is already a value with this name: "+thename); 162 4862040 : plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" 163 0 : "Remove the line addComponentWithDerivatives(\"bias\") from your bias."); 164 : } 165 10529 : values.emplace_back(new Value(this,thename, true ) ); 166 21058 : std::string msg=" added component to this action: "+thename+" \n"; 167 10529 : log.printf(msg.c_str()); 168 10529 : } 169 : 170 10251982 : int ActionWithValue::getComponent( const std::string& name ) const { 171 10251982 : plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value"); 172 30755988 : std::string thename; thename=getLabel() + "." + name; 173 126924434 : for(unsigned i=0; i<values.size(); ++i) { 174 63462217 : if (values[i]->name==thename) return i; 175 : } 176 0 : plumed_merror("there is no component with name " + name); 177 : return -1; 178 : } 179 : 180 0 : std::string ActionWithValue::getComponentsList( ) const { 181 : std::string complist; 182 0 : for(unsigned i=0; i<values.size(); ++i) { 183 0 : complist+=values[i]->name+" "; 184 : } 185 0 : return complist; 186 : } 187 : 188 990 : std::vector<std::string> ActionWithValue::getComponentsVector( ) const { 189 : std::vector<std::string> complist; 190 441256 : for(unsigned i=0; i<values.size(); ++i) { 191 219638 : complist.push_back(values[i]->name); 192 : } 193 990 : return complist; 194 : } 195 : 196 29990 : void ActionWithValue::componentIsNotPeriodic( const std::string& name ) { 197 29990 : int kk=getComponent(name); 198 89970 : values[kk]->min=0; values[kk]->max=0; 199 29990 : values[kk]->setupPeriodicity(); 200 29990 : } 201 : 202 90 : void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) { 203 90 : int kk=getComponent(name); 204 180 : values[kk]->setDomain(min,max); 205 90 : } 206 : 207 389626 : void ActionWithValue::setGradientsIfNeeded() { 208 779252 : if(isOptionOn("GRADIENTS")) { 209 1590 : for(unsigned i=0; i<values.size(); i++) values[i]->setGradients(); 210 : } 211 389626 : } 212 : 213 3492091 : void ActionWithValue::turnOnDerivatives() { 214 : // Turn on the derivatives 215 3492091 : noderiv=false; 216 : // Resize the derivatives 217 8212422892 : for(unsigned i=0; i<values.size(); ++i) values[i]->resizeDerivatives( getNumberOfDerivatives() ); 218 : // And turn on the derivatives in all actions on which we are dependent 219 10466541 : for(unsigned i=0; i<getDependencies().size(); ++i) { 220 3487225 : ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] ); 221 3487225 : if(vv) vv->turnOnDerivatives(); 222 : } 223 3492091 : } 224 : 225 10221908 : Value* ActionWithValue::getPntrToComponent( const std::string& name ) { 226 10221908 : int kk=getComponent(name); 227 20443884 : return values[kk].get(); 228 : } 229 : 230 774974 : Value* ActionWithValue::getPntrToComponent( int n ) { 231 : plumed_dbg_massert(n<values.size(),"you have requested a pointer that is out of bounds"); 232 1549948 : return values[n].get(); 233 : } 234 : 235 : }