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 3179 : void ActionWithValue::registerKeywords(Keywords& keys) {
30 6358 : 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 quanties can be referenced elsewhere in the input by using this Action's "
34 : "label followed by a dot and the name of the quantity required from the list below.");
35 9537 : keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically");
36 3179 : }
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 891 : void ActionWithValue::componentsAreNotOptional(Keywords& keys) {
44 1782 : keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quanties can "
45 : "be referenced elsewhere in the input by using this Action's label followed by a "
46 : "dot and the name of the quantity required from the list below.");
47 891 : }
48 :
49 415 : void ActionWithValue::useCustomisableComponents(Keywords& keys) {
50 830 : 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 these customizable components the "
52 : "following quantities will always be output");
53 415 : }
54 :
55 3024 : ActionWithValue::ActionWithValue(const ActionOptions&ao):
56 : Action(ao),
57 : noderiv(true),
58 6048 : numericalDerivatives(false)
59 : {
60 8824 : if( keywords.exists("NUMERICAL_DERIVATIVES") ) parseFlag("NUMERICAL_DERIVATIVES",numericalDerivatives);
61 3024 : if(numericalDerivatives) log.printf(" using numerical derivatives\n");
62 3024 : }
63 :
64 3024 : ActionWithValue::~ActionWithValue() {
65 108582 : for(unsigned i=0; i<values.size(); ++i)delete values[i];
66 3024 : }
67 :
68 147518 : void ActionWithValue::clearInputForces() {
69 1999772 : for(unsigned i=0; i<values.size(); i++) values[i]->clearInputForce();
70 147518 : }
71 :
72 150273 : void ActionWithValue::clearDerivatives() {
73 150273 : unsigned nt = OpenMP::getNumThreads();
74 450159 : #pragma omp parallel num_threads(nt)
75 : {
76 : #pragma omp for
77 730964 : for(unsigned i=0; i<values.size(); i++) values[i]->clearDerivatives();
78 : }
79 150273 : }
80 :
81 : // -- These are the routine for copying the value pointers to other classes -- //
82 :
83 2553115 : bool ActionWithValue::exists( const std::string& name ) const {
84 230444009 : for(unsigned i=0; i<values.size(); ++i) {
85 75136623 : if (values[i]->name==name) return true;
86 : }
87 : return false;
88 : }
89 :
90 24033 : Value* ActionWithValue::copyOutput( const std::string& name ) const {
91 32331063 : for(unsigned i=0; i<values.size(); ++i) {
92 10785032 : if (values[i]->name==name) return values[i];
93 : }
94 0 : plumed_merror("there is no pointer with name " + name);
95 : return NULL;
96 : }
97 :
98 10070 : Value* ActionWithValue::copyOutput( const unsigned& n ) const {
99 20140 : plumed_massert(n<values.size(),"you have requested a pointer that is out of bounds");
100 10070 : return values[n];
101 : }
102 :
103 : // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- //
104 :
105 37 : void ActionWithValue::addValue() {
106 37 : plumed_massert(values.empty(),"You have already added the default value for this action");
107 111 : values.push_back(new Value(this,getLabel(), false ) );
108 37 : }
109 :
110 1682 : void ActionWithValue::addValueWithDerivatives() {
111 1682 : plumed_massert(values.empty(),"You have already added the default value for this action");
112 5046 : values.push_back(new Value(this,getLabel(), true ) );
113 1682 : }
114 :
115 1262 : void ActionWithValue::setNotPeriodic() {
116 1262 : plumed_massert(values.size()==1,"The number of components is not equal to one");
117 2524 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
118 2524 : values[0]->min=0; values[0]->max=0;
119 1262 : values[0]->setupPeriodicity();
120 1262 : }
121 :
122 457 : void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) {
123 457 : plumed_massert(values.size()==1,"The number of components is not equal to one");
124 914 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
125 457 : values[0]->setDomain( min, max );
126 457 : }
127 :
128 15299144 : 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 15299144 : return values[0];
132 : }
133 :
134 : // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- //
135 :
136 22216 : void ActionWithValue::addComponent( const std::string& name ) {
137 22216 : if( !keywords.outputComponentExists(name,true) ) {
138 432 : warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
139 : "registerKeywords as described in the developer docs.");
140 : }
141 88864 : std::string thename; thename=getLabel() + "." + name;
142 55978778 : for(unsigned i=0; i<values.size(); ++i) {
143 55934346 : plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
144 37289564 : 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"
145 : "Remove the line addComponent(\"bias\") from your bias.");
146 37289564 : plumed_massert(values[i]->name!=thename,"there is already a value with this name");
147 : }
148 44432 : values.push_back(new Value(this,thename, false ) );
149 44432 : std::string msg=" added component to this action: "+thename+" \n";
150 44432 : log.printf(msg.c_str());
151 22216 : }
152 :
153 10243 : void ActionWithValue::addComponentWithDerivatives( const std::string& name ) {
154 10243 : if( !keywords.outputComponentExists(name,true) ) {
155 3 : warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
156 : "registerKeywords as described in the developer doc.");
157 : }
158 40972 : std::string thename; thename=getLabel() + "." + name;
159 7309805 : for(unsigned i=0; i<values.size(); ++i) {
160 7289319 : plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
161 4859546 : 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"
162 : "Remove the line addComponentWithDerivatives(\"bias\") from your bias.");
163 4859546 : plumed_massert(values[i]->name!=thename,"there is already a value with this name");
164 : }
165 20486 : values.push_back(new Value(this,thename, true ) );
166 20486 : std::string msg=" added component to this action: "+thename+" \n";
167 20486 : log.printf(msg.c_str());
168 10243 : }
169 :
170 2522295 : int ActionWithValue::getComponent( const std::string& name ) const {
171 5044590 : plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value");
172 10089180 : std::string thename; thename=getLabel() + "." + name;
173 166822377 : for(unsigned i=0; i<values.size(); ++i) {
174 56448224 : 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 789 : std::vector<std::string> ActionWithValue::getComponentsVector( ) const {
189 : std::vector<std::string> complist;
190 635463 : for(unsigned i=0; i<values.size(); ++i) {
191 211295 : complist.push_back(values[i]->name);
192 : }
193 789 : return complist;
194 : }
195 :
196 29333 : void ActionWithValue::componentIsNotPeriodic( const std::string& name ) {
197 29333 : int kk=getComponent(name);
198 87999 : values[kk]->min=0; values[kk]->max=0;
199 29333 : values[kk]->setupPeriodicity();
200 29333 : }
201 :
202 80 : void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) {
203 80 : int kk=getComponent(name);
204 160 : values[kk]->setDomain(min,max);
205 80 : }
206 :
207 147518 : void ActionWithValue::setGradientsIfNeeded() {
208 295036 : if(isOptionOn("GRADIENTS")) {
209 1164 : for(unsigned i=0; i<values.size(); i++) values[i]->setGradients();
210 : }
211 147518 : }
212 :
213 3491500 : void ActionWithValue::turnOnDerivatives() {
214 : // Turn on the derivatives
215 3491500 : noderiv=false;
216 : // Resize the derivatives
217 16417849908 : 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 17443649 : for(unsigned i=0; i<getDependencies().size(); ++i) {
220 3486883 : ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] );
221 3486883 : if(vv) vv->turnOnDerivatives();
222 : }
223 3491500 : }
224 :
225 2492882 : Value* ActionWithValue::getPntrToComponent( const std::string& name ) {
226 2492882 : int kk=getComponent(name);
227 4985764 : return values[kk];
228 : }
229 :
230 469777 : Value* ActionWithValue::getPntrToComponent( int n ) {
231 : plumed_dbg_massert(n<values.size(),"you have requested a pointer that is out of bounds");
232 939554 : return values[n];
233 : }
234 :
235 : }
|