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 "Function.h"
23 : #include "tools/OpenMP.h"
24 :
25 : using namespace std;
26 : namespace PLMD {
27 : namespace function {
28 :
29 487 : void Function::registerKeywords(Keywords& keys) {
30 487 : Action::registerKeywords(keys);
31 487 : ActionWithValue::registerKeywords(keys);
32 487 : ActionWithArguments::registerKeywords(keys);
33 1948 : 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");
34 487 : }
35 :
36 475 : Function::Function(const ActionOptions&ao):
37 : Action(ao),
38 : ActionWithValue(ao),
39 475 : ActionWithArguments(ao)
40 : {
41 475 : }
42 :
43 389 : void Function::addValueWithDerivatives() {
44 389 : plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values");
45 389 : ActionWithValue::addValueWithDerivatives();
46 389 : getPntrToValue()->resizeDerivatives(getNumberOfArguments());
47 :
48 778 : if( keywords.exists("PERIODIC") ) {
49 386 : std::vector<std::string> period;
50 772 : parseVector("PERIODIC",period);
51 769 : if(period.size()==1 && period[0]=="NO") {
52 383 : setNotPeriodic();
53 3 : } else if(period.size()==2) {
54 3 : setPeriodic(period[0],period[1]);
55 0 : } else error("missing PERIODIC keyword");
56 : }
57 389 : }
58 :
59 3159 : void Function::addComponentWithDerivatives( const std::string& name ) {
60 3159 : plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values");
61 3159 : ActionWithValue::addComponentWithDerivatives(name);
62 3159 : getPntrToComponent(name)->resizeDerivatives(getNumberOfArguments());
63 3159 : }
64 :
65 26240 : void Function::apply()
66 : {
67 26240 : const unsigned noa=getNumberOfArguments();
68 26240 : const unsigned ncp=getNumberOfComponents();
69 26240 : const unsigned cgs=comm.Get_size();
70 :
71 26240 : vector<double> f(noa,0.0);
72 :
73 : unsigned stride=1;
74 : unsigned rank=0;
75 26240 : if(ncp>4*cgs) {
76 6 : stride=comm.Get_size();
77 6 : rank=comm.Get_rank();
78 : }
79 :
80 26240 : unsigned at_least_one_forced=0;
81 78720 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(f)
82 : {
83 52480 : vector<double> omp_f(noa,0.0);
84 52480 : vector<double> forces(noa);
85 52480 : #pragma omp for reduction( + : at_least_one_forced)
86 : for(unsigned i=rank; i<ncp; i+=stride) {
87 29441 : if(getPntrToComponent(i)->applyForce(forces)) {
88 26183 : at_least_one_forced+=1;
89 3248588 : for(unsigned j=0; j<noa; j++) omp_f[j]+=forces[j];
90 : }
91 : }
92 104960 : #pragma omp critical
93 383288 : for(unsigned j=0; j<noa; j++) f[j]+=omp_f[j];
94 : }
95 :
96 26246 : if(noa>0&&ncp>4*cgs) { comm.Sum(&f[0],noa); comm.Sum(at_least_one_forced); }
97 :
98 98490 : if(at_least_one_forced>0) for(unsigned i=0; i<noa; ++i) getPntrToArgument(i)->addForce(f[i]);
99 26240 : }
100 :
101 : }
102 4839 : }
|