void Function::apply() { const unsigned noa=getNumberOfArguments(); const unsigned ncp=getNumberOfComponents(); const unsigned cgs=comm.Get_size(); vector<double> f(noa,0.0); unsigned stride=1; unsigned rank=0; if(ncp>4*cgs) { stride=comm.Get_size(); rank=comm.Get_rank(); } unsigned at_least_one_forced=0; #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(f) { vector<double> omp_f(noa,0.0); vector<double> forces(noa); #pragma omp for reduction( + : at_least_one_forced) for(unsigned i=rank; i<ncp; i+=stride) { if(getPntrToComponent(i)->applyForce(forces)) { at_least_one_forced+=1; for(unsigned j=0; j<noa; j++) omp_f[j]+=forces[j]; } } #pragma omp critical for(unsigned j=0; j<noa; j++) f[j]+=omp_f[j]; } if(noa>0&&ncp>4*cgs) { comm.Sum(&f[0],noa); comm.Sum(at_least_one_forced); } if(at_least_one_forced>0) for(unsigned i=0; i<noa; ++i) getPntrToArgument(i)->addForce(f[i]); }
void Colvar::apply(){ vector<Vector>& f(modifyForces()); Tensor& v(modifyVirial()); const unsigned nat=getNumberOfAtoms(); const unsigned ncp=getNumberOfComponents(); const unsigned fsz=f.size(); for(unsigned i=0;i<fsz;i++) f[i].zero(); v.zero(); unsigned stride=1; unsigned rank=0; if(ncp>comm.Get_size()) { stride=comm.Get_size(); rank=comm.Get_rank(); } unsigned nt=OpenMP::getNumThreads(); if(nt>ncp/(2.*stride)) nt=1; if(!isEnergy){ #pragma omp parallel num_threads(nt) { vector<Vector> omp_f(fsz); Tensor omp_v; vector<double> forces(3*nat+9); #pragma omp for for(unsigned i=rank;i<ncp;i+=stride){ if(getPntrToComponent(i)->applyForce(forces)){ for(unsigned j=0;j<nat;++j){ omp_f[j][0]+=forces[3*j+0]; omp_f[j][1]+=forces[3*j+1]; omp_f[j][2]+=forces[3*j+2]; } omp_v(0,0)+=forces[3*nat+0]; omp_v(0,1)+=forces[3*nat+1]; omp_v(0,2)+=forces[3*nat+2]; omp_v(1,0)+=forces[3*nat+3]; omp_v(1,1)+=forces[3*nat+4]; omp_v(1,2)+=forces[3*nat+5]; omp_v(2,0)+=forces[3*nat+6]; omp_v(2,1)+=forces[3*nat+7]; omp_v(2,2)+=forces[3*nat+8]; } } #pragma omp critical { for(unsigned j=0;j<nat;++j) f[j]+=omp_f[j]; v+=omp_v; } } if(ncp>comm.Get_size()) { if(fsz>0) comm.Sum(&f[0][0],3*fsz); comm.Sum(&v[0][0],9); } } else if( isEnergy ){ vector<double> forces(1); if(getPntrToComponent(0)->applyForce(forces)) modifyForceOnEnergy()+=forces[0]; } }