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 "Colvar.h"
23 : #include "tools/OpenMP.h"
24 : #include <vector>
25 : #include <string>
26 :
27 : using namespace std;
28 : namespace PLMD {
29 :
30 1424 : Colvar::Colvar(const ActionOptions&ao):
31 : Action(ao),
32 : ActionAtomistic(ao),
33 : ActionWithValue(ao),
34 1424 : isEnergy(false)
35 : {
36 1424 : }
37 :
38 1393 : void Colvar::registerKeywords( Keywords& keys ) {
39 1393 : Action::registerKeywords( keys );
40 1393 : ActionWithValue::registerKeywords( keys );
41 1393 : ActionAtomistic::registerKeywords( keys );
42 4179 : keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances");
43 1393 : }
44 :
45 1551 : void Colvar::requestAtoms(const vector<AtomNumber> & a) {
46 1551 : plumed_massert(!isEnergy,"request atoms should not be called if this is energy");
47 : // Tell actionAtomistic what atoms we are getting
48 1551 : ActionAtomistic::requestAtoms(a);
49 : // Resize the derivatives of all atoms
50 7628 : for(int i=0; i<getNumberOfComponents(); ++i) getPntrToComponent(i)->resizeDerivatives(3*a.size()+9);
51 1550 : }
52 :
53 77295 : void Colvar::apply() {
54 : vector<Vector>& f(modifyForces());
55 : Tensor& v(modifyVirial());
56 : const unsigned nat=getNumberOfAtoms();
57 77295 : const unsigned ncp=getNumberOfComponents();
58 77295 : const unsigned fsz=f.size();
59 :
60 : unsigned stride=1;
61 : unsigned rank=0;
62 77295 : if(ncp>4*comm.Get_size()) {
63 804 : stride=comm.Get_size();
64 804 : rank=comm.Get_rank();
65 : }
66 :
67 77295 : unsigned nt=OpenMP::getNumThreads();
68 77295 : if(nt>ncp/(4*stride)) nt=1;
69 :
70 77295 : if(!isEnergy) {
71 147688 : #pragma omp parallel num_threads(nt)
72 : {
73 74180 : vector<Vector> omp_f(fsz);
74 74180 : Tensor omp_v;
75 74180 : vector<double> forces(3*nat+9);
76 : #pragma omp for
77 : for(unsigned i=rank; i<ncp; i+=stride) {
78 121486 : if(getPntrToComponent(i)->applyForce(forces)) {
79 541415 : for(unsigned j=0; j<nat; ++j) {
80 739659 : omp_f[j][0]+=forces[3*j+0];
81 739659 : omp_f[j][1]+=forces[3*j+1];
82 739659 : omp_f[j][2]+=forces[3*j+2];
83 : }
84 96618 : omp_v(0,0)+=forces[3*nat+0];
85 96618 : omp_v(0,1)+=forces[3*nat+1];
86 96618 : omp_v(0,2)+=forces[3*nat+2];
87 96618 : omp_v(1,0)+=forces[3*nat+3];
88 96618 : omp_v(1,1)+=forces[3*nat+4];
89 96618 : omp_v(1,2)+=forces[3*nat+5];
90 96618 : omp_v(2,0)+=forces[3*nat+6];
91 96618 : omp_v(2,1)+=forces[3*nat+7];
92 96618 : omp_v(2,2)+=forces[3*nat+8];
93 : }
94 : }
95 148360 : #pragma omp critical
96 : {
97 2659448 : for(unsigned j=0; j<nat; ++j) f[j]+=omp_f[j];
98 74180 : v+=omp_v;
99 : }
100 : }
101 :
102 73508 : if(ncp>4*comm.Get_size()) {
103 1458 : if(fsz>0) comm.Sum(&f[0][0],3*fsz);
104 804 : comm.Sum(&v[0][0],9);
105 : }
106 :
107 : } else if( isEnergy ) {
108 3787 : vector<double> forces(1);
109 3837 : if(getPntrToComponent(0)->applyForce(forces)) modifyForceOnEnergy()+=forces[0];
110 : }
111 77295 : }
112 :
113 141326 : void Colvar::setBoxDerivativesNoPbc(Value* v) {
114 141326 : Tensor virial;
115 : unsigned nat=getNumberOfAtoms();
116 61825894 : for(unsigned i=0; i<nat; i++) virial-=Tensor(getPosition(i),
117 46263426 : Vector(v->getDerivative(3*i+0),
118 : v->getDerivative(3*i+1),
119 15421142 : v->getDerivative(3*i+2)));
120 141326 : setBoxDerivatives(v,virial);
121 141326 : }
122 4839 : }
|