static void do_lincsp(rvec *x,rvec *f,rvec *fp,t_pbc *pbc, struct gmx_lincsdata *lincsd,real *invmass, int econq,real *dvdlambda, gmx_bool bCalcVir,tensor rmdf) { int b,i,j,k,n; real tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,wfac,lam; rvec dx; int ncons,*bla,*blnr,*blbnb; rvec *r; real *blc,*blmf,*blcc,*rhs1,*rhs2,*sol; ncons = lincsd->nc; bla = lincsd->bla; r = lincsd->tmpv; blnr = lincsd->blnr; blbnb = lincsd->blbnb; if (econq != econqForce) { /* Use mass-weighted parameters */ blc = lincsd->blc; blmf = lincsd->blmf; } else { /* Use non mass-weighted parameters */ blc = lincsd->blc1; blmf = lincsd->blmf1; } blcc = lincsd->tmpncc; rhs1 = lincsd->tmp1; rhs2 = lincsd->tmp2; sol = lincsd->tmp3; if (econq != econqForce) { dvdlambda = NULL; } /* Compute normalized i-j vectors */ if (pbc) { for(b=0; b<ncons; b++) { pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx); unitv(dx,r[b]); } } else { for(b=0; b<ncons; b++) { rvec_sub(x[bla[2*b]],x[bla[2*b+1]],dx); unitv(dx,r[b]); } /* 16 ncons flops */ } for(b=0; b<ncons; b++) { tmp0 = r[b][0]; tmp1 = r[b][1]; tmp2 = r[b][2]; i = bla[2*b]; j = bla[2*b+1]; for(n=blnr[b]; n<blnr[b+1]; n++) { k = blbnb[n]; blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]); } /* 6 nr flops */ mvb = blc[b]*(tmp0*(f[i][0] - f[j][0]) + tmp1*(f[i][1] - f[j][1]) + tmp2*(f[i][2] - f[j][2])); rhs1[b] = mvb; sol[b] = mvb; /* 7 flops */ } /* Together: 23*ncons + 6*nrtot flops */ lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol); /* nrec*(ncons+2*nrtot) flops */ if (econq != econqForce) { for(b=0; b<ncons; b++) { /* With econqDeriv_FlexCon only use the flexible constraints */ if (econq != econqDeriv_FlexCon || (lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0)) { i = bla[2*b]; j = bla[2*b+1]; mvb = blc[b]*sol[b]; im1 = invmass[i]; im2 = invmass[j]; tmp0 = r[b][0]*mvb; tmp1 = r[b][1]*mvb; tmp2 = r[b][2]*mvb; fp[i][0] -= tmp0*im1; fp[i][1] -= tmp1*im1; fp[i][2] -= tmp2*im1; fp[j][0] += tmp0*im2; fp[j][1] += tmp1*im2; fp[j][2] += tmp2*im2; if (dvdlambda) { /* This is only correct with forces and invmass=1 */ *dvdlambda -= mvb*lincsd->ddist[b]; } } } /* 16 ncons flops */ } else { for(b=0; b<ncons; b++) { i = bla[2*b]; j = bla[2*b+1]; mvb = blc[b]*sol[b]; tmp0 = r[b][0]*mvb; tmp1 = r[b][1]*mvb; tmp2 = r[b][2]*mvb; fp[i][0] -= tmp0; fp[i][1] -= tmp1; fp[i][2] -= tmp2; fp[j][0] += tmp0; fp[j][1] += tmp1; fp[j][2] += tmp2; if (dvdlambda) { *dvdlambda -= mvb*lincsd->ddist[b]; } } /* 10 ncons flops */ } if (bCalcVir) { /* Constraint virial, * determines sum r_bond x delta f, * where delta f is the constraint correction * of the quantity that is being constrained. */ for(b=0; b<ncons; b++) { mvb = lincsd->bllen[b]*blc[b]*sol[b]; for(i=0; i<DIM; i++) { tmp1 = mvb*r[b][i]; for(j=0; j<DIM; j++) { rmdf[i][j] += tmp1*r[b][j]; } } } /* 23 ncons flops */ } }
static void do_lincs(rvec *x,rvec *xp,matrix box,t_pbc *pbc, struct gmx_lincsdata *lincsd,real *invmass, t_commrec *cr, real wangle,int *warn, real invdt,rvec *v, gmx_bool bCalcVir,tensor rmdr) { int b,i,j,k,n,iter; real tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,len2,dlen2,wfac,lam; rvec dx; int ncons,*bla,*blnr,*blbnb; rvec *r; real *blc,*blmf,*bllen,*blcc,*rhs1,*rhs2,*sol,*lambda; int *nlocat; ncons = lincsd->nc; bla = lincsd->bla; r = lincsd->tmpv; blnr = lincsd->blnr; blbnb = lincsd->blbnb; blc = lincsd->blc; blmf = lincsd->blmf; bllen = lincsd->bllen; blcc = lincsd->tmpncc; rhs1 = lincsd->tmp1; rhs2 = lincsd->tmp2; sol = lincsd->tmp3; lambda = lincsd->lambda; if (DOMAINDECOMP(cr) && cr->dd->constraints) { nlocat = dd_constraints_nlocalatoms(cr->dd); } else if (PARTDECOMP(cr)) { nlocat = pd_constraints_nlocalatoms(cr->pd); } else { nlocat = NULL; } *warn = 0; if (pbc) { /* Compute normalized i-j vectors */ for(b=0; b<ncons; b++) { pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx); unitv(dx,r[b]); } for(b=0; b<ncons; b++) { for(n=blnr[b]; n<blnr[b+1]; n++) { blcc[n] = blmf[n]*iprod(r[b],r[blbnb[n]]); } pbc_dx_aiuc(pbc,xp[bla[2*b]],xp[bla[2*b+1]],dx); mvb = blc[b]*(iprod(r[b],dx) - bllen[b]); rhs1[b] = mvb; sol[b] = mvb; } } else { /* Compute normalized i-j vectors */ for(b=0; b<ncons; b++) { i = bla[2*b]; j = bla[2*b+1]; tmp0 = x[i][0] - x[j][0]; tmp1 = x[i][1] - x[j][1]; tmp2 = x[i][2] - x[j][2]; rlen = gmx_invsqrt(tmp0*tmp0+tmp1*tmp1+tmp2*tmp2); r[b][0] = rlen*tmp0; r[b][1] = rlen*tmp1; r[b][2] = rlen*tmp2; } /* 16 ncons flops */ for(b=0; b<ncons; b++) { tmp0 = r[b][0]; tmp1 = r[b][1]; tmp2 = r[b][2]; len = bllen[b]; i = bla[2*b]; j = bla[2*b+1]; for(n=blnr[b]; n<blnr[b+1]; n++) { k = blbnb[n]; blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]); } /* 6 nr flops */ mvb = blc[b]*(tmp0*(xp[i][0] - xp[j][0]) + tmp1*(xp[i][1] - xp[j][1]) + tmp2*(xp[i][2] - xp[j][2]) - len); rhs1[b] = mvb; sol[b] = mvb; /* 10 flops */ } /* Together: 26*ncons + 6*nrtot flops */ } lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol); /* nrec*(ncons+2*nrtot) flops */ for(b=0; b<ncons; b++) { i = bla[2*b]; j = bla[2*b+1]; mvb = blc[b]*sol[b]; lambda[b] = -mvb; im1 = invmass[i]; im2 = invmass[j]; tmp0 = r[b][0]*mvb; tmp1 = r[b][1]*mvb; tmp2 = r[b][2]*mvb; xp[i][0] -= tmp0*im1; xp[i][1] -= tmp1*im1; xp[i][2] -= tmp2*im1; xp[j][0] += tmp0*im2; xp[j][1] += tmp1*im2; xp[j][2] += tmp2*im2; } /* 16 ncons flops */ /* ******** Correction for centripetal effects ******** */ wfac = cos(DEG2RAD*wangle); wfac = wfac*wfac; for(iter=0; iter<lincsd->nIter; iter++) { if (DOMAINDECOMP(cr) && cr->dd->constraints) { /* Communicate the corrected non-local coordinates */ dd_move_x_constraints(cr->dd,box,xp,NULL); } else if (PARTDECOMP(cr)) { pd_move_x_constraints(cr,xp,NULL); } for(b=0; b<ncons; b++) { len = bllen[b]; if (pbc) { pbc_dx_aiuc(pbc,xp[bla[2*b]],xp[bla[2*b+1]],dx); } else { rvec_sub(xp[bla[2*b]],xp[bla[2*b+1]],dx); } len2 = len*len; dlen2 = 2*len2 - norm2(dx); if (dlen2 < wfac*len2 && (nlocat==NULL || nlocat[b])) { *warn = b; } if (dlen2 > 0) { mvb = blc[b]*(len - dlen2*gmx_invsqrt(dlen2)); } else { mvb = blc[b]*len; } rhs1[b] = mvb; sol[b] = mvb; } /* 20*ncons flops */ lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol); /* nrec*(ncons+2*nrtot) flops */ for(b=0; b<ncons; b++) { i = bla[2*b]; j = bla[2*b+1]; lam = lambda[b]; mvb = blc[b]*sol[b]; lambda[b] = lam - mvb; im1 = invmass[i]; im2 = invmass[j]; tmp0 = r[b][0]*mvb; tmp1 = r[b][1]*mvb; tmp2 = r[b][2]*mvb; xp[i][0] -= tmp0*im1; xp[i][1] -= tmp1*im1; xp[i][2] -= tmp2*im1; xp[j][0] += tmp0*im2; xp[j][1] += tmp1*im2; xp[j][2] += tmp2*im2; } /* 17 ncons flops */ } /* nit*ncons*(37+9*nrec) flops */ if (v) { /* Correct the velocities */ for(b=0; b<ncons; b++) { i = bla[2*b]; j = bla[2*b+1]; im1 = invmass[i]*lambda[b]*invdt; im2 = invmass[j]*lambda[b]*invdt; v[i][0] += im1*r[b][0]; v[i][1] += im1*r[b][1]; v[i][2] += im1*r[b][2]; v[j][0] -= im2*r[b][0]; v[j][1] -= im2*r[b][1]; v[j][2] -= im2*r[b][2]; } /* 16 ncons flops */ } if (nlocat) { /* Only account for local atoms */ for(b=0; b<ncons; b++) { lambda[b] *= 0.5*nlocat[b]; } } if (bCalcVir) { /* Constraint virial */ for(b=0; b<ncons; b++) { tmp0 = bllen[b]*lambda[b]; for(i=0; i<DIM; i++) { tmp1 = tmp0*r[b][i]; for(j=0; j<DIM; j++) { rmdr[i][j] -= tmp1*r[b][j]; } } } /* 22 ncons flops */ } /* Total: * 26*ncons + 6*nrtot + nrec*(ncons+2*nrtot) * + nit * (20*ncons + nrec*(ncons+2*nrtot) + 17 ncons) * * (26+nrec)*ncons + (6+2*nrec)*nrtot * + nit * ((37+nrec)*ncons + 2*nrec*nrtot) * if nit=1 * (63+nrec)*ncons + (6+4*nrec)*nrtot */ }
/* LINCS projection, works on derivatives of the coordinates */ static void do_lincsp(rvec *x,rvec *f,rvec *fp,t_pbc *pbc, struct gmx_lincsdata *lincsd,int th, real *invmass, int econq,real *dvdlambda, gmx_bool bCalcVir,tensor rmdf) { int b0,b1,b,i,j,k,n; real tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,wfac,lam; rvec dx; int *bla,*blnr,*blbnb; rvec *r; real *blc,*blmf,*blcc,*rhs1,*rhs2,*sol; b0 = lincsd->th[th].b0; b1 = lincsd->th[th].b1; bla = lincsd->bla; r = lincsd->tmpv; blnr = lincsd->blnr; blbnb = lincsd->blbnb; if (econq != econqForce) { /* Use mass-weighted parameters */ blc = lincsd->blc; blmf = lincsd->blmf; } else { /* Use non mass-weighted parameters */ blc = lincsd->blc1; blmf = lincsd->blmf1; } blcc = lincsd->tmpncc; rhs1 = lincsd->tmp1; rhs2 = lincsd->tmp2; sol = lincsd->tmp3; /* Compute normalized i-j vectors */ if (pbc) { for(b=b0; b<b1; b++) { pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx); unitv(dx,r[b]); } } else { for(b=b0; b<b1; b++) { rvec_sub(x[bla[2*b]],x[bla[2*b+1]],dx); unitv(dx,r[b]); } /* 16 ncons flops */ } #pragma omp barrier for(b=b0; b<b1; b++) { tmp0 = r[b][0]; tmp1 = r[b][1]; tmp2 = r[b][2]; i = bla[2*b]; j = bla[2*b+1]; for(n=blnr[b]; n<blnr[b+1]; n++) { k = blbnb[n]; blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]); } /* 6 nr flops */ mvb = blc[b]*(tmp0*(f[i][0] - f[j][0]) + tmp1*(f[i][1] - f[j][1]) + tmp2*(f[i][2] - f[j][2])); rhs1[b] = mvb; sol[b] = mvb; /* 7 flops */ } /* Together: 23*ncons + 6*nrtot flops */ lincs_matrix_expand(lincsd,b0,b1,blcc,rhs1,rhs2,sol); /* nrec*(ncons+2*nrtot) flops */ if (econq == econqDeriv_FlexCon) { /* We only want to constraint the flexible constraints, * so we mask out the normal ones by setting sol to 0. */ for(b=b0; b<b1; b++) { if (!(lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0)) { sol[b] = 0; } } } if (econq != econqForce) { lincs_update_atoms(lincsd,th,1.0,sol,r,invmass,fp); } else { for(b=b0; b<b1; b++) { i = bla[2*b]; j = bla[2*b+1]; mvb = blc[b]*sol[b]; tmp0 = r[b][0]*mvb; tmp1 = r[b][1]*mvb; tmp2 = r[b][2]*mvb; fp[i][0] -= tmp0; fp[i][1] -= tmp1; fp[i][2] -= tmp2; fp[j][0] += tmp0; fp[j][1] += tmp1; fp[j][2] += tmp2; } if (dvdlambda != NULL) { #pragma omp barrier for(b=b0; b<b1; b++) { *dvdlambda -= blc[b]*sol[b]*lincsd->ddist[b]; } } /* 10 ncons flops */ } if (bCalcVir) { /* Constraint virial, * determines sum r_bond x delta f, * where delta f is the constraint correction * of the quantity that is being constrained. */ for(b=b0; b<b1; b++) { mvb = lincsd->bllen[b]*blc[b]*sol[b]; for(i=0; i<DIM; i++) { tmp1 = mvb*r[b][i]; for(j=0; j<DIM; j++) { rmdf[i][j] += tmp1*r[b][j]; } } } /* 23 ncons flops */ } }