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