double Action_LIE::Calculate_LJ(Frame const& frameIn, Topology const& parmIn) const { double result = 0; // Loop over ligand atoms AtomMask::const_iterator mask1_end = Mask1_.end(); AtomMask::const_iterator mask2_end = Mask2_.end(); for (AtomMask::const_iterator maskatom1 = Mask1_.begin(); maskatom1 != mask1_end; maskatom1++) { int crdidx1 = (*maskatom1) * 3; // index into coordinate array Vec3 atm1 = Vec3(frameIn.CRD(crdidx1)); for (AtomMask::const_iterator maskatom2 = Mask2_.begin(); maskatom2 != mask2_end; maskatom2++) { int crdidx2 = (*maskatom2) * 3; // index into coordinate array Vec3 atm2 = Vec3(frameIn.CRD(crdidx2)); double dist2; // Get imaged distance Matrix_3x3 ucell, recip; switch( ImageType() ) { case NONORTHO: frameIn.BoxCrd().ToRecip(ucell, recip); dist2 = DIST2_ImageNonOrtho(atm1, atm2, ucell, recip); break; case ORTHO: dist2 = DIST2_ImageOrtho(atm1, atm2, frameIn.BoxCrd()); break; default: dist2 = DIST2_NoImage(atm1, atm2); } if (dist2 > cut2vdw_) continue; // Here we add to our nonbonded (VDW) energy NonbondType const& LJ = parmIn.GetLJparam(*maskatom1, *maskatom2); double r2 = 1 / dist2; double r6 = r2 * r2 * r2; result += LJ.A() * r6 * r6 - LJ.B() * r6; } } return result; }
double Action_LIE::Calculate_Elec(Frame const& frameIn) const { double result = 0; // Loop over ligand atoms AtomMask::const_iterator mask1_end = Mask1_.end(); AtomMask::const_iterator mask2_end = Mask2_.end(); for (AtomMask::const_iterator maskatom1 = Mask1_.begin(); maskatom1 != mask1_end; maskatom1++) { int crdidx1 = (*maskatom1) * 3; // index into coordinate array Vec3 atm1 = Vec3(frameIn.CRD(crdidx1)); for (AtomMask::const_iterator maskatom2 = Mask2_.begin(); maskatom2 != mask2_end; maskatom2++) { int crdidx2 = (*maskatom2) * 3; // index into coordinate array Vec3 atm2 = Vec3(frameIn.CRD(crdidx2)); double dist2; // Get imaged distance Matrix_3x3 ucell, recip; switch( ImageType() ) { case NONORTHO: frameIn.BoxCrd().ToRecip(ucell, recip); dist2 = DIST2_ImageNonOrtho(atm1, atm2, ucell, recip); break; case ORTHO: dist2 = DIST2_ImageOrtho(atm1, atm2, frameIn.BoxCrd()); break; default: dist2 = DIST2_NoImage(atm1, atm2); } if (dist2 > cut2elec_) continue; // Here we add to our electrostatic energy double qiqj = atom_charge_[*maskatom1] * atom_charge_[*maskatom2]; double shift = (1 - dist2 * onecut2_); result += qiqj / sqrt(dist2) * shift * shift; } } return result; }
/** Calc Covariance Matrix */ void Action_Matrix::CalcCovarianceMatrix(Frame const& currentFrame) { # ifdef _OPENMP #ifdef NEW_MATRIX_PARA /* New matrix parallelization */ //int idx2, atomCrd2, offset2, midx, idx1, atomCrd1, offset1; int idx2, midx, idx1; double Mj; if (useMask2_) { // FULL MATRIX TODO return; } else { // HALF MATRIX DataSet_MatrixDbl& matrix = *Mat_; Darray& vect1 = Mat_->V1(); //int Ncoords = mask1_.Nselected() * 3; int Ncoords = (int)crd_indices_.size(); //# pragma omp parallel private(idx2, atomCrd2, offset2, midx, idx1, atomCrd1, offset1, Mj) # pragma omp parallel private(idx2, midx, idx1, Mj) { # pragma omp for schedule(dynamic) for (idx2 = 0; idx2 < Ncoords; idx2++) { //atomCrd2 = mask1_[idx2 / 3] * 3; //offset2 = idx2 % 3; //Mj = currentFrame[atomCrd2 + offset2]; Mj = currentFrame[ crd_indices_[idx2] ]; vect1[idx2] += Mj; vect2_[idx2] += (Mj * Mj); midx = (idx2 * (int)matrix.Ncols() - (idx2 * (idx2-1) / 2)); for (idx1 = idx2; idx1 < Ncoords; idx1++, midx++) { //atomCrd1 = mask1_[idx1 / 3] * 3; //offset1 = idx1 % 3; //matrix[midx] += (currentFrame[atomCrd1 + offset1] * Mj); matrix[midx] += (currentFrame[ crd_indices_[idx1] ] * Mj); } } // END for loop } // END openmp pragma } #else /* Original matrix parallelization */ int m1_idx, m2_idx; double Vj; const double* XYZi; const double* XYZj; unsigned int ny; DataSet_MatrixDbl::iterator mat; v_iterator v1, v2; if (useMask2_) { // FULL MATRIX int NX = (int)Mat_->Ncols(); int crd_max = (int)crd_indices_.size(); # pragma omp parallel private(m1_idx, m2_idx, XYZi, XYZj, Vj, mat, v1, v2, ny) { #pragma omp for for (m2_idx = 0; m2_idx < mask2_.Nselected(); m2_idx++) { mat = Mat_->begin() + ((m2_idx*3)*NX); XYZj = currentFrame.XYZ( mask2_[m2_idx] ); for (ny = 0; ny < 3; ny++) { Vj = XYZj[ny]; for (m1_idx = 0; m1_idx < mask1_.Nselected(); m1_idx++) { XYZi = currentFrame.XYZ( mask1_[m1_idx] ); *(mat++) += Vj * XYZi[0]; *(mat++) += Vj * XYZi[1]; *(mat++) += Vj * XYZi[2]; } } } // Mask1/Mask2 diagonal # pragma omp for for (m1_idx = 0; m1_idx < crd_max; m1_idx++) { v1 = Mat_->v1begin() + (m1_idx * 3); // Index into vect/vect2 v2 = vect2_.begin() + (m1_idx * 3); StoreVec(v1, v2, currentFrame.CRD( crd_indices_[m1_idx] )); } } // END PARALLEL BLOCK FULL return; } else { // HALF MATRIX int v_idx; unsigned int nx; double d_m2_idx; double TwoN = (double)( Mat_->Ncols() * 2 ); # pragma omp parallel private(m1_idx, m2_idx, d_m2_idx, v_idx, XYZi, XYZj, Vj, mat, v1, v2, ny, nx) { #pragma omp for schedule(dynamic) for (m2_idx = 0; m2_idx < mask1_.Nselected(); m2_idx++) { v_idx = m2_idx * 3; d_m2_idx = (double)v_idx; mat = Mat_->begin() + (int)(0.5*d_m2_idx*(TwoN-d_m2_idx-1.0)+d_m2_idx); v1 = Mat_->v1begin() + v_idx; v2 = vect2_.begin() + v_idx; XYZj = currentFrame.XYZ( mask1_[m2_idx] ); StoreVec(v1, v2, XYZj); for (ny = 0; ny < 3; ny++) { Vj = XYZj[ny]; // m1_idx = m2_idx, diagonal for (nx = ny; nx < 3; nx++) *(mat++) += Vj * XYZj[nx]; // Vj * i{0,1,2}, Vj * i{1,2}, Vj * i{2} for (m1_idx = m2_idx+1; m1_idx < mask1_.Nselected(); m1_idx++) { XYZi = currentFrame.XYZ( mask1_[m1_idx] ); *(mat++) += Vj * XYZi[0]; *(mat++) += Vj * XYZi[1]; *(mat++) += Vj * XYZi[2]; } } } } // END PARALLEL BLOCK HALF } #endif # else DataSet_MatrixDbl::iterator mat = Mat_->begin(); v_iterator v1idx1 = Mat_->v1begin(); v_iterator v2idx1 = vect2_.begin(); if (useMask2_) { // Full Matrix // Position for mask2 halfway through vect/vect2 v_iterator v1idx2 = Mat_->v1begin() + (mask1_.Nselected() * 3); v_iterator v2idx2 = vect2_.begin() + (mask1_.Nselected() * 3); bool storeVecj = true; // Only store vecj|vecj^2 first time through inner loop // OUTER LOOP for (AtomMask::const_iterator atom2 = mask2_.begin(); atom2 != mask2_.end(); ++atom2) { const double* XYZi = currentFrame.XYZ( *atom2 ); // Store veci and veci^2 StoreVec(v1idx2, v2idx2, XYZi); // Loop over X, Y, and Z of veci for (int iidx = 0; iidx < 3; ++iidx) { double Vi = XYZi[iidx]; // INNER LOOP for (AtomMask::const_iterator atom1 = mask1_.begin(); atom1 != mask1_.end(); ++atom1) { const double* XYZj = currentFrame.XYZ( *atom1 ); // Store vecj and vecj^2, first time through only if (storeVecj) StoreVec(v1idx1, v2idx1, XYZj); *(mat++) += Vi * XYZj[0]; *(mat++) += Vi * XYZj[1]; *(mat++) += Vi * XYZj[2]; } storeVecj = false; } } } else { // Half Matrix // OUTER LOOP for (AtomMask::const_iterator atom2 = mask1_.begin(); atom2 != mask1_.end(); ++atom2) { const double* XYZi = currentFrame.XYZ( *atom2 ); // Store veci and veci^2 StoreVec(v1idx1, v2idx1, XYZi); // Loop over X, Y, and Z of veci for (int iidx = 0; iidx < 3; ++iidx) { double Vi = XYZi[iidx]; // Diagonal for (int jidx = iidx; jidx < 3; jidx++) *(mat++) += Vi * XYZi[jidx]; // Vi * j{0,1,2}, Vi * j{1,2}, Vi * j{2} // INNER LOOP for (AtomMask::const_iterator atom1 = atom2 + 1; atom1 != mask1_.end(); ++atom1) { const double* XYZj = currentFrame.XYZ( *atom1 ); *(mat++) += Vi * XYZj[0]; *(mat++) += Vi * XYZj[1]; *(mat++) += Vi * XYZj[2]; } } } } # endif }