void f_calc_vir(int i0, int i1, rvec x[], rvec f[], tensor vir, t_graph *g, matrix box) { int start, end; if (g && (g->nnodes > 0)) { /* Calculate virial for bonded forces only when they belong to * this node. */ start = std::max(i0, g->at_start); end = std::min(i1, g->at_end); lo_fcv(start, end, x[0], f[0], vir, g->ishift[0], box[0], TRICLINIC(box)); /* If not all atoms are bonded, calculate their virial contribution * anyway, without shifting back their coordinates. * Note the nifty pointer arithmetic... */ if (start > i0) { calc_vir(start-i0, x + i0, f + i0, vir, FALSE, box); } if (end < i1) { calc_vir(i1-end, x + end, f + end, vir, FALSE, box); } } else { calc_vir(i1-i0, x + i0, f + i0, vir, FALSE, box); } }
void f_calc_vir(FILE *log,int i0,int i1,rvec x[],rvec f[],tensor vir, t_graph *g,matrix box) { int start,end; if (g && (g->nnodes > 0)) { /* Calculate virial for bonded forces only when they belong to * this node. */ start = max(i0,g->start); end = min(i1,g->end+1); #ifdef SAFE lo_fcv2(start,end,x,f,vir,g->ishift,box,TRICLINIC(box)); #else lo_fcv(start,end,0,x[0],f[0],vir,g->ishift[0],box[0],TRICLINIC(box)); #endif /* If not all atoms are bonded, calculate their virial contribution * anyway, without shifting back their coordinates. * Note the nifty pointer arithmetic... */ if (start > i0) calc_vir(log,start-i0,x + i0,f + i0,vir,FALSE,box); if (end < i1) calc_vir(log,i1-end,x + end,f + end,vir,FALSE,box); } else calc_vir(log,i1-i0,x + i0,f + i0,vir,FALSE,box); }
static void calc_virial(FILE *fplog,int start,int homenr,rvec x[],rvec f[], tensor vir_part,t_graph *graph,matrix box, t_nrnb *nrnb,const t_forcerec *fr,int ePBC) { int i,j; tensor virtest; /* The short-range virial from surrounding boxes */ clear_mat(vir_part); calc_vir(fplog,SHIFTS,fr->shift_vec,fr->fshift,vir_part,ePBC==epbcSCREW,box); inc_nrnb(nrnb,eNR_VIRIAL,SHIFTS); /* Calculate partial virial, for local atoms only, based on short range. * Total virial is computed in global_stat, called from do_md */ f_calc_vir(fplog,start,start+homenr,x,f,vir_part,graph,box); inc_nrnb(nrnb,eNR_VIRIAL,homenr); /* Add position restraint contribution */ for(i=0; i<DIM; i++) { vir_part[i][i] += fr->vir_diag_posres[i]; } /* Add wall contribution */ for(i=0; i<DIM; i++) { vir_part[i][ZZ] += fr->vir_wall_z[i]; } if (debug) pr_rvecs(debug,0,"vir_part",vir_part,DIM); }
void do_force(FILE *log,t_commrec *cr,t_commrec *mcr, t_parm *parm,t_nsborder *nsb,tensor vir_part,tensor pme_vir, int step,t_nrnb *nrnb,t_topology *top,t_groups *grps, rvec x[],rvec v[],rvec f[],rvec buf[], t_mdatoms *mdatoms,real ener[],t_fcdata *fcd,bool bVerbose, real lambda,t_graph *graph, bool bNS,bool bNBFonly,t_forcerec *fr, rvec mu_tot, bool bGatherOnly) { static rvec box_size; static real dvdl_lr = 0; int cg0,cg1,i,j; int start,homenr; static real mu_and_q[DIM+1]; real qsum; start = START(nsb); homenr = HOMENR(nsb); cg0 = CG0(nsb); cg1 = CG1(nsb); update_forcerec(log,fr,parm->box); /* Calculate total (local) dipole moment in a temporary common array. * This makes it possible to sum them over nodes faster. */ calc_mu_and_q(nsb,x,mdatoms->chargeT,mu_and_q,mu_and_q+DIM); if (fr->ePBC != epbcNONE) { /* Compute shift vectors every step, because of pressure coupling! */ if (parm->ir.epc != epcNO) calc_shifts(parm->box,box_size,fr->shift_vec); if (bNS) { put_charge_groups_in_box(log,cg0,cg1,parm->box,box_size, &(top->blocks[ebCGS]),x,fr->cg_cm); inc_nrnb(nrnb,eNR_RESETX,homenr); } else if (parm->ir.eI==eiSteep || parm->ir.eI==eiCG) unshift_self(graph,parm->box,x); } else if (bNS) calc_cgcm(log,cg0,cg1,&(top->blocks[ebCGS]),x,fr->cg_cm); if (bNS) { inc_nrnb(nrnb,eNR_CGCM,cg1-cg0); if (PAR(cr)) move_cgcm(log,cr,fr->cg_cm,nsb->workload); if (debug) pr_rvecs(debug,0,"cgcm",fr->cg_cm,nsb->cgtotal); } /* Communicate coordinates and sum dipole and net charge if necessary */ if (PAR(cr)) { move_x(log,cr->left,cr->right,x,nsb,nrnb); gmx_sum(DIM+1,mu_and_q,cr); } for(i=0;i<DIM;i++) mu_tot[i]=mu_and_q[i]; qsum=mu_and_q[DIM]; /* Reset energies */ reset_energies(&(parm->ir.opts),grps,fr,bNS,ener); if (bNS) { if (fr->ePBC != epbcNONE) /* Calculate intramolecular shift vectors to make molecules whole */ mk_mshift(log,graph,parm->box,x); /* Reset long range forces if necessary */ if (fr->bTwinRange) { clear_rvecs(nsb->natoms,fr->f_twin); clear_rvecs(SHIFTS,fr->fshift_twin); } /* Do the actual neighbour searching and if twin range electrostatics * also do the calculation of long range forces and energies. */ dvdl_lr = 0; ns(log,fr,x,f,parm->box,grps,&(parm->ir.opts),top,mdatoms, cr,nrnb,nsb,step,lambda,&dvdl_lr); } /* Reset PME/Ewald forces if necessary */ if (EEL_LR(fr->eeltype)) clear_rvecs(homenr,fr->f_pme+start); /* Copy long range forces into normal buffers */ if (fr->bTwinRange) { for(i=0; i<nsb->natoms; i++) copy_rvec(fr->f_twin[i],f[i]); for(i=0; i<SHIFTS; i++) copy_rvec(fr->fshift_twin[i],fr->fshift[i]); } else { clear_rvecs(nsb->natoms,f); clear_rvecs(SHIFTS,fr->fshift); } /* Compute the forces */ force(log,step,fr,&(parm->ir),&(top->idef),nsb,cr,mcr,nrnb,grps,mdatoms, top->atoms.grps[egcENER].nr,&(parm->ir.opts), x,f,ener,fcd,bVerbose,parm->box,lambda,graph,&(top->atoms.excl), bNBFonly,pme_vir,mu_tot,qsum,bGatherOnly); /* Take long range contribution to free energy into account */ ener[F_DVDL] += dvdl_lr; #ifdef DEBUG if (bNS) print_nrnb(log,nrnb); #endif /* The short-range virial from surrounding boxes */ clear_mat(vir_part); calc_vir(log,SHIFTS,fr->shift_vec,fr->fshift,vir_part); inc_nrnb(nrnb,eNR_VIRIAL,SHIFTS); if (debug) pr_rvecs(debug,0,"vir_shifts",vir_part,DIM); /* Compute forces due to electric field */ calc_f_el(start,homenr,mdatoms->chargeT,f,parm->ir.ex); /* When using PME/Ewald we compute the long range virial (pme_vir) there. * otherwise we do it based on long range forces from twin range * cut-off based calculation (or not at all). */ /* Communicate the forces */ if (PAR(cr)) move_f(log,cr->left,cr->right,f,buf,nsb,nrnb); }