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