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 1654 : Colvar::Colvar(const ActionOptions&ao): 31 : Action(ao), 32 : ActionAtomistic(ao), 33 : ActionWithValue(ao), 34 : isEnergy(false), 35 1654 : isExtraCV(false) 36 : { 37 1654 : } 38 : 39 1627 : void Colvar::registerKeywords( Keywords& keys ) { 40 1627 : Action::registerKeywords( keys ); 41 1627 : ActionWithValue::registerKeywords( keys ); 42 1627 : ActionAtomistic::registerKeywords( keys ); 43 4881 : keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances"); 44 1627 : } 45 : 46 1981 : void Colvar::requestAtoms(const vector<AtomNumber> & a) { 47 1981 : plumed_massert(!isEnergy,"request atoms should not be called if this is energy"); 48 : // Tell actionAtomistic what atoms we are getting 49 1981 : ActionAtomistic::requestAtoms(a); 50 : // Resize the derivatives of all atoms 51 14133 : for(int i=0; i<getNumberOfComponents(); ++i) getPntrToComponent(i)->resizeDerivatives(3*a.size()+9); 52 1980 : } 53 : 54 105225 : void Colvar::apply() { 55 105225 : vector<Vector>& f(modifyForces()); 56 105225 : Tensor& v(modifyVirial()); 57 : const unsigned nat=getNumberOfAtoms(); 58 105225 : const unsigned ncp=getNumberOfComponents(); 59 105225 : const unsigned fsz=f.size(); 60 : 61 : unsigned stride=1; 62 : unsigned rank=0; 63 105225 : if(ncp>4*comm.Get_size()) { 64 1560 : stride=comm.Get_size(); 65 1560 : rank=comm.Get_rank(); 66 : } 67 : 68 105225 : unsigned nt=OpenMP::getNumThreads(); 69 105225 : if(nt>ncp/(4*stride)) nt=1; 70 : 71 105225 : if(!isEnergy && !isExtraCV) { 72 204010 : #pragma omp parallel num_threads(nt) 73 : { 74 102612 : vector<Vector> omp_f(fsz); 75 102612 : Tensor omp_v; 76 102614 : vector<double> forces(3*nat+9); 77 102616 : #pragma omp for 78 : for(unsigned i=rank; i<ncp; i+=stride) { 79 168569 : if(getPntrToComponent(i)->applyForce(forces)) { 80 1666529 : for(unsigned j=0; j<nat; ++j) { 81 2391417 : omp_f[j][0]+=forces[3*j+0]; 82 2391417 : omp_f[j][1]+=forces[3*j+1]; 83 2391417 : omp_f[j][2]+=forces[3*j+2]; 84 : } 85 144502 : omp_v(0,0)+=forces[3*nat+0]; 86 144502 : omp_v(0,1)+=forces[3*nat+1]; 87 144502 : omp_v(0,2)+=forces[3*nat+2]; 88 144502 : omp_v(1,0)+=forces[3*nat+3]; 89 144502 : omp_v(1,1)+=forces[3*nat+4]; 90 144502 : omp_v(1,2)+=forces[3*nat+5]; 91 144502 : omp_v(2,0)+=forces[3*nat+6]; 92 144502 : omp_v(2,1)+=forces[3*nat+7]; 93 144502 : omp_v(2,2)+=forces[3*nat+8]; 94 : } 95 : } 96 205232 : #pragma omp critical 97 : { 98 3415964 : for(unsigned j=0; j<nat; ++j) f[j]+=omp_f[j]; 99 102616 : v+=omp_v; 100 : } 101 : } 102 : 103 101398 : if(ncp>4*comm.Get_size()) { 104 2970 : if(fsz>0) comm.Sum(&f[0][0],3*fsz); 105 1560 : comm.Sum(&v[0][0],9); 106 : } 107 : 108 3827 : } else if( isEnergy ) { 109 3787 : vector<double> forces(1); 110 3837 : if(getPntrToComponent(0)->applyForce(forces)) modifyForceOnEnergy()+=forces[0]; 111 40 : } else if( isExtraCV ) { 112 40 : vector<double> forces(1); 113 80 : if(getPntrToComponent(0)->applyForce(forces)) modifyForceOnExtraCV()+=forces[0]; 114 : } 115 105225 : } 116 : 117 184510 : void Colvar::setBoxDerivativesNoPbc(Value* v) { 118 184510 : Tensor virial; 119 : unsigned nat=getNumberOfAtoms(); 120 78724310 : for(unsigned i=0; i<nat; i++) virial-=Tensor(getPosition(i), 121 : Vector(v->getDerivative(3*i+0), 122 : v->getDerivative(3*i+1), 123 31415920 : v->getDerivative(3*i+2))); 124 184510 : setBoxDerivatives(v,virial); 125 184510 : } 126 5874 : }