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); }
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 write_espresso_conf_indexed(FILE *out, const char *title, t_atoms *atoms, int nx, int *index, rvec *x, rvec *v, matrix box) { int i, j; fprintf(out, "# %s\n", title); if (TRICLINIC(box)) { gmx_warning("The Espresso format does not support triclinic unit-cells"); } fprintf(out, "{variable {box_l %f %f %f}}\n", box[0][0], box[1][1], box[2][2]); fprintf(out, "{particles {id pos type q%s}\n", v ? " v" : ""); for (i = 0; i < nx; i++) { if (index) { j = index[i]; } else { j = i; } fprintf(out, "\t{%d %f %f %f %u %g", j, x[j][XX], x[j][YY], x[j][ZZ], atoms->atom[j].type, atoms->atom[j].q); if (v) { fprintf(out, " %f %f %f", v[j][XX], v[j][YY], v[j][ZZ]); } fprintf(out, "}\n"); } fprintf(out, "}\n"); }
void put_atoms_in_box(int ePBC, matrix box, int natoms, rvec x[]) { int npbcdim, i, m, d; if (ePBC == epbcSCREW) { gmx_fatal(FARGS, "Sorry, %s pbc is not yet supported", epbc_names[ePBC]); } if (ePBC == epbcXY) { npbcdim = 2; } else { npbcdim = 3; } if (TRICLINIC(box)) { for (i = 0; (i < natoms); i++) { for (m = npbcdim-1; m >= 0; m--) { while (x[i][m] < 0) { for (d = 0; d <= m; d++) { x[i][d] += box[m][d]; } } while (x[i][m] >= box[m][m]) { for (d = 0; d <= m; d++) { x[i][d] -= box[m][d]; } } } } } else { for (i = 0; i < natoms; i++) { for (d = 0; d < npbcdim; d++) { while (x[i][d] < 0) { x[i][d] += box[d][d]; } while (x[i][d] >= box[d][d]) { x[i][d] -= box[d][d]; } } } } }
void visualize_box(FILE *out,int a0,int r0,matrix box,rvec gridsize) { int *edge; rvec *vert,shift; int nx,ny,nz,nbox,nat; int i,j,x,y,z; int rectedge[24] = { 0,1, 1,3, 3,2, 0,2, 0,4, 1,5, 3,7, 2,6, 4,5, 5,7, 7,6, 6,4 }; a0++; r0++; nx = (int)(gridsize[XX]+0.5); ny = (int)(gridsize[YY]+0.5); nz = (int)(gridsize[ZZ]+0.5); nbox = nx*ny*nz; if (TRICLINIC(box)) { nat = nbox*NCUCVERT; snew(vert,nat); calc_compact_unitcell_vertices(ecenterDEF,box,vert); j = 0; for(z=0; z<nz; z++) for(y=0; y<ny; y++) for(x=0; x<nx; x++) { for(i=0; i<DIM; i++) shift[i] = x*box[0][i]+y*box[1][i]+z*box[2][i]; for(i=0; i<NCUCVERT; i++) { rvec_add(vert[i],shift,vert[j]); j++; } } for(i=0; i<nat; i++) { fprintf(out,pdbformat,"ATOM",a0+i,"C","BOX",'K'+i/NCUCVERT,r0+i, 10*vert[i][XX],10*vert[i][YY],10*vert[i][ZZ]); fprintf(out,"\n"); } edge = compact_unitcell_edges(); for(j=0; j<nbox; j++) for(i=0; i<NCUCEDGE; i++) fprintf(out,"CONECT%5d%5d\n", a0 + j*NCUCVERT + edge[2*i], a0 + j*NCUCVERT + edge[2*i+1]); sfree(vert); } else { i=0; for(z=0; z<=1; z++) for(y=0; y<=1; y++) for(x=0; x<=1; x++) { fprintf(out,pdbformat,"ATOM",a0+i,"C","BOX",'K'+i/8,r0+i, x*10*box[XX][XX],y*10*box[YY][YY],z*10*box[ZZ][ZZ]); fprintf(out,"\n"); i++; } for(i=0; i<24; i+=2) fprintf(out,"CONECT%5d%5d\n",a0+rectedge[i],a0+rectedge[i+1]); } }
void set_def (t_molwin *mw,int ePBC,matrix box) { mw->bShowHydrogen=TRUE; mw->bond_type=eBFat; mw->ePBC=ePBC; mw->boxtype=esbRect; mw->realbox=TRICLINIC(box) ? esbTri : esbRect; }
void get_enx_state(char *fn, real t, gmx_groups_t *groups, t_inputrec *ir, t_state *state) { /* Should match the names in mdebin.c */ static const char *boxvel_nm[] = { "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ", "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY" }; static const char *pcouplmu_nm[] = { "Pcoupl-Mu-XX", "Pcoupl-Mu-YY", "Pcoupl-Mu-ZZ", "Pcoupl-Mu-YX", "Pcoupl-Mu-ZX", "Pcoupl-Mu-ZY" }; int ind0[] = { XX,YY,ZZ,YY,ZZ,ZZ }; int ind1[] = { XX,YY,ZZ,XX,XX,YY }; int in,nre,nfr,i,ni,npcoupl; char buf[STRLEN]; gmx_enxnm_t *enm; t_enxframe *fr; in = open_enx(fn,"r"); do_enxnms(in,&nre,&enm); snew(fr,1); nfr = 0; while ((nfr==0 || fr->t != t) && do_enx(in,fr)) { nfr++; } close_enx(in); fprintf(stderr,"\n"); if (nfr == 0 || fr->t != t) gmx_fatal(FARGS,"Could not find frame with time %f in '%s'",t,fn); npcoupl = TRICLINIC(ir->compress) ? 6 : 3; if (ir->epc == epcPARRINELLORAHMAN) { clear_mat(state->boxv); for(i=0; i<npcoupl; i++) { state->boxv[ind0[i]][ind1[i]] = find_energy(boxvel_nm[i],nre,enm,fr); } fprintf(stderr,"\nREAD %d BOX VELOCITIES FROM %s\n\n",npcoupl,fn); } if (ir->etc == etcNOSEHOOVER) { for(i=0; i<state->ngtc; i++) { ni = groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Xi-%s",*(groups->grpname[ni])); state->nosehoover_xi[i] = find_energy(buf,nre,enm,fr); } fprintf(stderr,"\nREAD %d NOSE-HOOVER Xi's FROM %s\n\n",state->ngtc,fn); } free_enxnms(nre,enm); free_enxframe(fr); sfree(fr); }
void unshift_x(const t_graph *g, matrix box, rvec x[], const rvec x_s[]) { ivec *is; int g0, g1; int j, tx, ty, tz; if (g->bScrewPBC) { gmx_incons("screw pbc not implemented (yet) for unshift_x"); } g0 = g->at_start; g1 = g->at_end; is = g->ishift; for (j = g->at0; j < g0; j++) { copy_rvec(x_s[j], x[j]); } if (TRICLINIC(box)) { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x[j][XX] = x_s[j][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX]; x[j][YY] = x_s[j][YY]-ty*box[YY][YY]-tz*box[ZZ][YY]; x[j][ZZ] = x_s[j][ZZ]-tz*box[ZZ][ZZ]; } } else { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x[j][XX] = x_s[j][XX]-tx*box[XX][XX]; x[j][YY] = x_s[j][YY]-ty*box[YY][YY]; x[j][ZZ] = x_s[j][ZZ]-tz*box[ZZ][ZZ]; } } for (j = g1; j < g->at1; j++) { copy_rvec(x_s[j], x[j]); } }
void shift_self(const t_graph *g, matrix box, rvec x[]) { ivec *is; int g0, g1; int j, tx, ty, tz; if (g->bScrewPBC) { gmx_incons("screw pbc not implemented for shift_self"); } g0 = g->at_start; g1 = g->at_end; is = g->ishift; #ifdef DEBUG fprintf(stderr, "Shifting atoms %d to %d\n", g0, g0+gn); #endif if (TRICLINIC(box)) { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX]; x[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY]; x[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ]; } } else { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x[j][XX] = x[j][XX]+tx*box[XX][XX]; x[j][YY] = x[j][YY]+ty*box[YY][YY]; x[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ]; } } }
void unshift_self(const t_graph *g, matrix box, rvec x[]) { ivec *is; int g0, g1; int j, tx, ty, tz; if (g->bScrewPBC) { gmx_incons("screw pbc not implemented for unshift_self"); } g0 = g->at_start; g1 = g->at_end; is = g->ishift; if (TRICLINIC(box)) { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x[j][XX] = x[j][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX]; x[j][YY] = x[j][YY]-ty*box[YY][YY]-tz*box[ZZ][YY]; x[j][ZZ] = x[j][ZZ]-tz*box[ZZ][ZZ]; } } else { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x[j][XX] = x[j][XX]-tx*box[XX][XX]; x[j][YY] = x[j][YY]-ty*box[YY][YY]; x[j][ZZ] = x[j][ZZ]-tz*box[ZZ][ZZ]; } } }
static void shift_positions_group( const matrix box, rvec x[], /* The positions [0..nr] */ ivec *is, /* The shifts [0..nr] */ int nr) /* The number of positions and shifts */ { int i, tx, ty, tz; /* Loop over the group's atoms */ if (TRICLINIC(box)) { for (i = 0; i < nr; i++) { tx = is[i][XX]; ty = is[i][YY]; tz = is[i][ZZ]; x[i][XX] = x[i][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX]; x[i][YY] = x[i][YY]+ty*box[YY][YY]+tz*box[ZZ][YY]; x[i][ZZ] = x[i][ZZ]+tz*box[ZZ][ZZ]; } } else { for (i = 0; i < nr; i++) { tx = is[i][XX]; ty = is[i][YY]; tz = is[i][ZZ]; x[i][XX] = x[i][XX]+tx*box[XX][XX]; x[i][YY] = x[i][YY]+ty*box[YY][YY]; x[i][ZZ] = x[i][ZZ]+tz*box[ZZ][ZZ]; } } }
/*! \brief * Sets ua a search grid for a given box. * * \param[in,out] d Grid information. * \param[in] pbc Information about the box. * \returns FALSE if grid search is not suitable. */ static gmx_bool grid_set_box(gmx_ana_nbsearch_t *d, t_pbc *pbc) { int dd; /* TODO: This check could be improved. */ if (0.5*pbc->max_cutoff2 < d->cutoff2) { return FALSE; } if (!grid_setup_cells(d, pbc)) { return FALSE; } d->bTric = TRICLINIC(pbc->box); if (d->bTric) { for (dd = 0; dd < DIM; ++dd) { svmul(1.0 / d->ncelldim[dd], pbc->box[dd], d->cellbox[dd]); } m_inv_ur0(d->cellbox, d->recipcell); } else { for (dd = 0; dd < DIM; ++dd) { d->cellbox[dd][dd] = pbc->box[dd][dd] / d->ncelldim[dd]; d->recipcell[dd][dd] = 1 / d->cellbox[dd][dd]; } } grid_init_cell_nblist(d, pbc); return TRUE; }
void shift_x(const t_graph *g, matrix box, const rvec x[], rvec x_s[]) { ivec *is; int g0, g1; int j, tx, ty, tz; GCHECK(g); g0 = g->at_start; g1 = g->at_end; is = g->ishift; for (j = g->at0; j < g0; j++) { copy_rvec(x[j], x_s[j]); } if (g->bScrewPBC) { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; if ((tx > 0 && tx % 2 == 1) || (tx < 0 && -tx %2 == 1)) { x_s[j][XX] = x[j][XX] + tx*box[XX][XX]; x_s[j][YY] = box[YY][YY] + box[ZZ][YY] - x[j][YY]; x_s[j][ZZ] = box[ZZ][ZZ] - x[j][ZZ]; } else { x_s[j][XX] = x[j][XX]; } x_s[j][YY] = x[j][YY] + ty*box[YY][YY] + tz*box[ZZ][YY]; x_s[j][ZZ] = x[j][ZZ] + tz*box[ZZ][ZZ]; } } else if (TRICLINIC(box)) { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x_s[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX]; x_s[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY]; x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ]; } } else { for (j = g0; (j < g1); j++) { tx = is[j][XX]; ty = is[j][YY]; tz = is[j][ZZ]; x_s[j][XX] = x[j][XX]+tx*box[XX][XX]; x_s[j][YY] = x[j][YY]+ty*box[YY][YY]; x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ]; } } for (j = g1; j < g->at1; j++) { copy_rvec(x[j], x_s[j]); } }
static int mk_grey(egCol egc[], t_graph *g, int *AtomI, int npbcdim, matrix box, const rvec x[], int *nerror) { int m, j, ng, ai, aj, g0; rvec dx, hbox; gmx_bool bTriclinic; ivec is_aj; t_pbc pbc; for (m = 0; (m < DIM); m++) { hbox[m] = box[m][m]*0.5; } bTriclinic = TRICLINIC(box); g0 = g->at_start; ng = 0; ai = g0 + *AtomI; /* Loop over all the bonds */ for (j = 0; (j < g->nedge[ai-g0]); j++) { aj = g->edge[ai-g0][j]; /* If there is a white one, make it grey and set pbc */ if (g->bScrewPBC) { mk_1shift_screw(box, hbox, x[ai], x[aj], g->ishift[ai], is_aj); } else if (bTriclinic) { mk_1shift_tric(npbcdim, box, hbox, x[ai], x[aj], g->ishift[ai], is_aj); } else { mk_1shift(npbcdim, hbox, x[ai], x[aj], g->ishift[ai], is_aj); } if (egc[aj-g0] == egcolWhite) { if (aj - g0 < *AtomI) { *AtomI = aj - g0; } egc[aj-g0] = egcolGrey; copy_ivec(is_aj, g->ishift[aj]); ng++; } else if ((is_aj[XX] != g->ishift[aj][XX]) || (is_aj[YY] != g->ishift[aj][YY]) || (is_aj[ZZ] != g->ishift[aj][ZZ])) { if (gmx_debug_at) { set_pbc(&pbc, -1, box); pbc_dx(&pbc, x[ai], x[aj], dx); fprintf(debug, "mk_grey: shifts for atom %d due to atom %d\n" "are (%d,%d,%d), should be (%d,%d,%d)\n" "dx = (%g,%g,%g)\n", aj+1, ai+1, is_aj[XX], is_aj[YY], is_aj[ZZ], g->ishift[aj][XX], g->ishift[aj][YY], g->ishift[aj][ZZ], dx[XX], dx[YY], dx[ZZ]); } (*nerror)++; } } return ng; }
void get_enx_state(const char *fn, real t, gmx_groups_t *groups, t_inputrec *ir, t_state *state) { /* Should match the names in mdebin.c */ static const char *boxvel_nm[] = { "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ", "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY" }; static const char *pcouplmu_nm[] = { "Pcoupl-Mu-XX", "Pcoupl-Mu-YY", "Pcoupl-Mu-ZZ", "Pcoupl-Mu-YX", "Pcoupl-Mu-ZX", "Pcoupl-Mu-ZY" }; static const char *baro_nm[] = { "Barostat" }; int ind0[] = { XX,YY,ZZ,YY,ZZ,ZZ }; int ind1[] = { XX,YY,ZZ,XX,XX,YY }; int nre,nfr,i,j,ni,npcoupl; char buf[STRLEN]; const char *bufi; gmx_enxnm_t *enm=NULL; t_enxframe *fr; ener_file_t in; in = open_enx(fn,"r"); do_enxnms(in,&nre,&enm); snew(fr,1); nfr = 0; while ((nfr==0 || fr->t != t) && do_enx(in,fr)) { nfr++; } close_enx(in); fprintf(stderr,"\n"); if (nfr == 0 || fr->t != t) gmx_fatal(FARGS,"Could not find frame with time %f in '%s'",t,fn); npcoupl = TRICLINIC(ir->compress) ? 6 : 3; if (ir->epc == epcPARRINELLORAHMAN) { clear_mat(state->boxv); for(i=0; i<npcoupl; i++) { state->boxv[ind0[i]][ind1[i]] = find_energy(boxvel_nm[i],nre,enm,fr); } fprintf(stderr,"\nREAD %d BOX VELOCITIES FROM %s\n\n",npcoupl,fn); } if (ir->etc == etcNOSEHOOVER) { for(i=0; i<state->ngtc; i++) { ni = groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); for(j=0; (j<state->nhchainlength); j++) { sprintf(buf,"Xi-%d-%s",j,bufi); state->nosehoover_xi[i] = find_energy(buf,nre,enm,fr); sprintf(buf,"vXi-%d-%s",j,bufi); state->nosehoover_vxi[i] = find_energy(buf,nre,enm,fr); } } fprintf(stderr,"\nREAD %d NOSE-HOOVER Xi chains FROM %s\n\n",state->ngtc,fn); if (IR_NPT_TROTTER(ir)) { for(i=0; i<state->nnhpres; i++) { bufi = baro_nm[0]; /* All barostat DOF's together for now */ for(j=0; (j<state->nhchainlength); j++) { sprintf(buf,"Xi-%d-%s",j,bufi); state->nhpres_xi[i] = find_energy(buf,nre,enm,fr); sprintf(buf,"vXi-%d-%s",j,bufi); state->nhpres_vxi[i] = find_energy(buf,nre,enm,fr); } } fprintf(stderr,"\nREAD %d NOSE-HOOVER BAROSTAT Xi chains FROM %s\n\n",state->nnhpres,fn); } } free_enxnms(nre,enm); free_enxframe(fr); sfree(fr); }
//! Do the real arithmetic for filling the pbc struct static void low_set_pbc(t_pbc *pbc, int ePBC, const ivec dd_pbc, const matrix box) { int order[3] = { 0, -1, 1 }; ivec bPBC; const char *ptr; pbc->ePBC = ePBC; pbc->ndim_ePBC = ePBC2npbcdim(ePBC); copy_mat(box, pbc->box); pbc->max_cutoff2 = 0; pbc->dim = -1; pbc->ntric_vec = 0; for (int i = 0; (i < DIM); i++) { pbc->fbox_diag[i] = box[i][i]; pbc->hbox_diag[i] = pbc->fbox_diag[i]*0.5; pbc->mhbox_diag[i] = -pbc->hbox_diag[i]; } ptr = check_box(ePBC, box); if (ePBC == epbcNONE) { pbc->ePBCDX = epbcdxNOPBC; } else if (ptr) { fprintf(stderr, "Warning: %s\n", ptr); pr_rvecs(stderr, 0, " Box", box, DIM); fprintf(stderr, " Can not fix pbc.\n\n"); pbc->ePBCDX = epbcdxUNSUPPORTED; } else { if (ePBC == epbcSCREW && NULL != dd_pbc) { /* This combinated should never appear here */ gmx_incons("low_set_pbc called with screw pbc and dd_nc != NULL"); } int npbcdim = 0; for (int i = 0; i < DIM; i++) { if ((dd_pbc && dd_pbc[i] == 0) || (ePBC == epbcXY && i == ZZ)) { bPBC[i] = 0; } else { bPBC[i] = 1; npbcdim++; } } switch (npbcdim) { case 1: /* 1D pbc is not an mdp option and it is therefore only used * with single shifts. */ pbc->ePBCDX = epbcdx1D_RECT; for (int i = 0; i < DIM; i++) { if (bPBC[i]) { pbc->dim = i; } } GMX_ASSERT(pbc->dim < DIM, "Dimension for PBC incorrect"); for (int i = 0; i < pbc->dim; i++) { if (pbc->box[pbc->dim][i] != 0) { pbc->ePBCDX = epbcdx1D_TRIC; } } break; case 2: pbc->ePBCDX = epbcdx2D_RECT; for (int i = 0; i < DIM; i++) { if (!bPBC[i]) { pbc->dim = i; } } for (int i = 0; i < DIM; i++) { if (bPBC[i]) { for (int j = 0; j < i; j++) { if (pbc->box[i][j] != 0) { pbc->ePBCDX = epbcdx2D_TRIC; } } } } break; case 3: if (ePBC != epbcSCREW) { if (TRICLINIC(box)) { pbc->ePBCDX = epbcdxTRICLINIC; } else { pbc->ePBCDX = epbcdxRECTANGULAR; } } else { pbc->ePBCDX = (box[ZZ][YY] == 0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC); if (pbc->ePBCDX == epbcdxSCREW_TRIC) { fprintf(stderr, "Screw pbc is not yet implemented for triclinic boxes.\n" "Can not fix pbc.\n"); pbc->ePBCDX = epbcdxUNSUPPORTED; } } break; default: gmx_fatal(FARGS, "Incorrect number of pbc dimensions with DD: %d", npbcdim); } pbc->max_cutoff2 = max_cutoff2(ePBC, box); if (pbc->ePBCDX == epbcdxTRICLINIC || pbc->ePBCDX == epbcdx2D_TRIC || pbc->ePBCDX == epbcdxSCREW_TRIC) { if (debug) { pr_rvecs(debug, 0, "Box", box, DIM); fprintf(debug, "max cutoff %.3f\n", sqrt(pbc->max_cutoff2)); } /* We will only need single shifts here */ for (int kk = 0; kk < 3; kk++) { int k = order[kk]; if (!bPBC[ZZ] && k != 0) { continue; } for (int jj = 0; jj < 3; jj++) { int j = order[jj]; if (!bPBC[YY] && j != 0) { continue; } for (int ii = 0; ii < 3; ii++) { int i = order[ii]; if (!bPBC[XX] && i != 0) { continue; } /* A shift is only useful when it is trilinic */ if (j != 0 || k != 0) { rvec trial; rvec pos; real d2old = 0; real d2new = 0; for (int d = 0; d < DIM; d++) { trial[d] = i*box[XX][d] + j*box[YY][d] + k*box[ZZ][d]; /* Choose the vector within the brick around 0,0,0 that * will become the shortest due to shift try. */ if (d == pbc->dim) { trial[d] = 0; pos[d] = 0; } else { if (trial[d] < 0) { pos[d] = std::min( pbc->hbox_diag[d], -trial[d]); } else { pos[d] = std::max(-pbc->hbox_diag[d], -trial[d]); } } d2old += gmx::square(pos[d]); d2new += gmx::square(pos[d] + trial[d]); } if (BOX_MARGIN*d2new < d2old) { /* Check if shifts with one box vector less do better */ gmx_bool bUse = TRUE; for (int dd = 0; dd < DIM; dd++) { int shift = (dd == 0 ? i : (dd == 1 ? j : k)); if (shift) { real d2new_c = 0; for (int d = 0; d < DIM; d++) { d2new_c += gmx::square(pos[d] + trial[d] - shift*box[dd][d]); } if (d2new_c <= BOX_MARGIN*d2new) { bUse = FALSE; } } } if (bUse) { /* Accept this shift vector. */ if (pbc->ntric_vec >= MAX_NTRICVEC) { fprintf(stderr, "\nWARNING: Found more than %d triclinic correction vectors, ignoring some.\n" " There is probably something wrong with your box.\n", MAX_NTRICVEC); pr_rvecs(stderr, 0, " Box", box, DIM); } else { copy_rvec(trial, pbc->tric_vec[pbc->ntric_vec]); pbc->tric_shift[pbc->ntric_vec][XX] = i; pbc->tric_shift[pbc->ntric_vec][YY] = j; pbc->tric_shift[pbc->ntric_vec][ZZ] = k; pbc->ntric_vec++; if (debug) { fprintf(debug, " tricvec %2d = %2d %2d %2d %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f\n", pbc->ntric_vec, i, j, k, sqrt(d2old), sqrt(d2new), trial[XX], trial[YY], trial[ZZ], pos[XX], pos[YY], pos[ZZ]); } } } } } } } } } } }
void force(FILE *fp, int step, t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_nsborder *nsb, t_commrec *cr, t_commrec *mcr, t_nrnb *nrnb, t_groups *grps, t_mdatoms *md, int ngener, t_grpopts *opts, rvec x[], rvec f[], real epot[], t_fcdata *fcd, bool bVerbose, matrix box, real lambda, t_graph *graph, t_block *excl, bool bNBFonly, matrix lr_vir, rvec mu_tot, real qsum, bool bGatherOnly) { int i,nit; bool bDoEpot; rvec box_size; real Vlr,Vcorr=0; /* Reset box */ for(i=0; (i<DIM); i++) box_size[i]=box[i][i]; bDoEpot=((fr->nmol > 0) && (fr->nstcalc > 0) && (mod(step,fr->nstcalc)==0)); /* Reset epot... */ if (bDoEpot) for(i=0; (i<fr->nmol); i++) fr->mol_epot[i]=0.0; debug_gmx(); /* Call the short range functions all in one go. */ do_fnbf(fp,cr,fr,x,f,md, fr->bBHAM ? grps->estat.ee[egBHAM] : grps->estat.ee[egLJ], grps->estat.ee[egCOUL],box_size,nrnb, lambda,&epot[F_DVDL],FALSE,-1); debug_gmx(); if (debug) pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS); /* Shift the coordinates. Must be done before bonded forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no bonded forces have to be evaluated. */ if (debug && 0) p_graph(debug,"DeBUGGGG",graph); /* Check whether we need to do bondeds */ if (!bNBFonly) { shift_self(graph,box,x); if (debug && 0) { fprintf(debug,"BBBBBBBBBBBBBBBB\n"); fprintf(debug,"%5d\n",graph->nnodes); for(i=graph->start; (i<=graph->end); i++) fprintf(debug,"%5d%5s%5s%5d%8.3f%8.3f%8.3f\n", i,"A","B",i,x[i][XX],x[i][YY],x[i][ZZ]); fprintf(debug,"%10.5f%10.5f%10.5f\n", box[XX][XX],box[YY][YY],box[ZZ][ZZ]); } if (TRICLINIC(box)) inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes); else inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes); debug_gmx(); } if (EEL_LR(fr->eeltype)) { switch (fr->eeltype) { case eelPPPM: Vlr = do_pppm(fp,FALSE,x,fr->f_pme,md->chargeT, box_size,fr->phi,cr,nsb,nrnb); break; case eelPOISSON: Vlr = do_poisson(fp,FALSE,ir,md->nr,x,fr->f_pme,md->chargeT, box_size,fr->phi,cr,nrnb,&nit,TRUE); break; case eelPME: Vlr = do_pme(fp,FALSE,ir,x,fr->f_pme,md->chargeT, box,cr,nsb,nrnb,lr_vir,fr->ewaldcoeff,bGatherOnly); break; case eelEWALD: Vlr = do_ewald(fp,FALSE,ir,x,fr->f_pme,md->chargeT, box_size,cr,nsb,lr_vir,fr->ewaldcoeff); break; default: Vlr = 0; fatal_error(0,"No such electrostatics method implemented %s", eel_names[fr->eeltype]); } if(fr->bEwald) Vcorr = ewald_LRcorrection(fp,nsb,cr,fr,md->chargeT,excl,x,box,mu_tot,qsum, ir->ewald_geometry,ir->epsilon_surface,lr_vir); else Vcorr = shift_LRcorrection(fp,nsb,cr,fr,md->chargeT,excl,x,TRUE,box,lr_vir); epot[F_LR] = Vlr + Vcorr; if (debug) fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n", Vlr,Vcorr,epot[F_LR]); if (debug) { pr_rvecs(debug,0,"lr_vir after corr",lr_vir,DIM); pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS); } } debug_gmx(); if (debug) print_nrnb(debug,nrnb); debug_gmx(); if (!bNBFonly) { calc_bonds(fp,cr,mcr, idef,x,f,fr,graph,epot,nrnb,box,lambda,md, opts->ngener,grps->estat.ee[egLJ14],grps->estat.ee[egCOUL14], fcd,step,fr->bSepDVDL && do_per_step(step,ir->nstlog)); debug_gmx(); } if (debug) pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS); for(i=0; (i<F_EPOT); i++) if (i != F_DISRES) epot[F_EPOT]+=epot[i]; }
void put_charge_groups_in_box(FILE *fplog,int cg0,int cg1, int ePBC,matrix box,t_block *cgs, rvec pos[],rvec cg_cm[]) { int npbcdim,icg,k,k0,k1,d,e; rvec cg; real nrcg,inv_ncg; atom_id *cgindex; gmx_bool bTric; if (ePBC == epbcNONE) gmx_incons("Calling put_charge_groups_in_box for a system without PBC"); #ifdef DEBUG fprintf(fplog,"Putting cgs %d to %d in box\n",cg0,cg1); #endif cgindex = cgs->index; if (ePBC == epbcXY) npbcdim = 2; else npbcdim = 3; bTric = TRICLINIC(box); for(icg=cg0; (icg<cg1); icg++) { /* First compute the center of geometry for this charge group */ k0 = cgindex[icg]; k1 = cgindex[icg+1]; nrcg = k1-k0; if (nrcg == 1) { copy_rvec(pos[k0],cg_cm[icg]); } else { inv_ncg = 1.0/nrcg; clear_rvec(cg); for(k=k0; (k<k1); k++) { for(d=0; d<DIM; d++) cg[d] += pos[k][d]; } for(d=0; d<DIM; d++) cg_cm[icg][d] = inv_ncg*cg[d]; } /* Now check pbc for this cg */ if (bTric) { for(d=npbcdim-1; d>=0; d--) { while(cg_cm[icg][d] < 0) { for(e=d; e>=0; e--) { cg_cm[icg][e] += box[d][e]; for(k=k0; (k<k1); k++) pos[k][e] += box[d][e]; } } while(cg_cm[icg][d] >= box[d][d]) { for(e=d; e>=0; e--) { cg_cm[icg][e] -= box[d][e]; for(k=k0; (k<k1); k++) pos[k][e] -= box[d][e]; } } } } else { for(d=0; d<npbcdim; d++) { while(cg_cm[icg][d] < 0) { cg_cm[icg][d] += box[d][d]; for(k=k0; (k<k1); k++) pos[k][d] += box[d][d]; } while(cg_cm[icg][d] >= box[d][d]) { cg_cm[icg][d] -= box[d][d]; for(k=k0; (k<k1); k++) pos[k][d] -= box[d][d]; } } } #ifdef DEBUG_PBC for(d=0; (d<npbcdim); d++) { if ((cg_cm[icg][d] < 0) || (cg_cm[icg][d] >= box[d][d])) gmx_fatal(FARGS,"cg_cm[%d] = %15f %15f %15f\n" "box = %15f %15f %15f\n", icg,cg_cm[icg][XX],cg_cm[icg][YY],cg_cm[icg][ZZ], box[XX][XX],box[YY][YY],box[ZZ][ZZ]); } #endif } }
static void low_set_pbc(t_pbc *pbc, int ePBC, ivec *dd_nc, matrix box) { int order[5] = {0, -1, 1, -2, 2}; int ii, jj, kk, i, j, k, d, dd, jc, kc, npbcdim, shift; ivec bPBC; real d2old, d2new, d2new_c; rvec trial, pos; gmx_bool bXY, bUse; const char *ptr; pbc->ndim_ePBC = ePBC2npbcdim(ePBC); copy_mat(box, pbc->box); pbc->bLimitDistance = FALSE; pbc->max_cutoff2 = 0; pbc->dim = -1; for (i = 0; (i < DIM); i++) { pbc->fbox_diag[i] = box[i][i]; pbc->hbox_diag[i] = pbc->fbox_diag[i]*0.5; pbc->mhbox_diag[i] = -pbc->hbox_diag[i]; } ptr = check_box(ePBC, box); if (ePBC == epbcNONE) { pbc->ePBCDX = epbcdxNOPBC; } else if (ptr) { fprintf(stderr, "Warning: %s\n", ptr); pr_rvecs(stderr, 0, " Box", box, DIM); fprintf(stderr, " Can not fix pbc.\n"); pbc->ePBCDX = epbcdxUNSUPPORTED; pbc->bLimitDistance = TRUE; pbc->limit_distance2 = 0; } else { if (ePBC == epbcSCREW && dd_nc) { /* This combinated should never appear here */ gmx_incons("low_set_pbc called with screw pbc and dd_nc != NULL"); } npbcdim = 0; for (i = 0; i < DIM; i++) { if ((dd_nc && (*dd_nc)[i] > 1) || (ePBC == epbcXY && i == ZZ)) { bPBC[i] = 0; } else { bPBC[i] = 1; npbcdim++; } } switch (npbcdim) { case 1: /* 1D pbc is not an mdp option and it is therefore only used * with single shifts. */ pbc->ePBCDX = epbcdx1D_RECT; for (i = 0; i < DIM; i++) { if (bPBC[i]) { pbc->dim = i; } } for (i = 0; i < pbc->dim; i++) { if (pbc->box[pbc->dim][i] != 0) { pbc->ePBCDX = epbcdx1D_TRIC; } } break; case 2: pbc->ePBCDX = epbcdx2D_RECT; for (i = 0; i < DIM; i++) { if (!bPBC[i]) { pbc->dim = i; } } for (i = 0; i < DIM; i++) { if (bPBC[i]) { for (j = 0; j < i; j++) { if (pbc->box[i][j] != 0) { pbc->ePBCDX = epbcdx2D_TRIC; } } } } break; case 3: if (ePBC != epbcSCREW) { if (TRICLINIC(box)) { pbc->ePBCDX = epbcdxTRICLINIC; } else { pbc->ePBCDX = epbcdxRECTANGULAR; } } else { pbc->ePBCDX = (box[ZZ][YY] == 0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC); if (pbc->ePBCDX == epbcdxSCREW_TRIC) { fprintf(stderr, "Screw pbc is not yet implemented for triclinic boxes.\n" "Can not fix pbc.\n"); pbc->ePBCDX = epbcdxUNSUPPORTED; } } break; default: gmx_fatal(FARGS, "Incorrect number of pbc dimensions with DD: %d", npbcdim); } pbc->max_cutoff2 = max_cutoff2(ePBC, box); if (pbc->ePBCDX == epbcdxTRICLINIC || pbc->ePBCDX == epbcdx2D_TRIC || pbc->ePBCDX == epbcdxSCREW_TRIC) { if (debug) { pr_rvecs(debug, 0, "Box", box, DIM); fprintf(debug, "max cutoff %.3f\n", sqrt(pbc->max_cutoff2)); } pbc->ntric_vec = 0; /* We will only use single shifts, but we will check a few * more shifts to see if there is a limiting distance * above which we can not be sure of the correct distance. */ for (kk = 0; kk < 5; kk++) { k = order[kk]; if (!bPBC[ZZ] && k != 0) { continue; } for (jj = 0; jj < 5; jj++) { j = order[jj]; if (!bPBC[YY] && j != 0) { continue; } for (ii = 0; ii < 3; ii++) { i = order[ii]; if (!bPBC[XX] && i != 0) { continue; } /* A shift is only useful when it is trilinic */ if (j != 0 || k != 0) { d2old = 0; d2new = 0; for (d = 0; d < DIM; d++) { trial[d] = i*box[XX][d] + j*box[YY][d] + k*box[ZZ][d]; /* Choose the vector within the brick around 0,0,0 that * will become the shortest due to shift try. */ if (d == pbc->dim) { trial[d] = 0; pos[d] = 0; } else { if (trial[d] < 0) { pos[d] = min( pbc->hbox_diag[d], -trial[d]); } else { pos[d] = max(-pbc->hbox_diag[d], -trial[d]); } } d2old += sqr(pos[d]); d2new += sqr(pos[d] + trial[d]); } if (BOX_MARGIN*d2new < d2old) { if (j < -1 || j > 1 || k < -1 || k > 1) { /* Check if there is a single shift vector * that decreases this distance even more. */ jc = 0; kc = 0; if (j < -1 || j > 1) { jc = j/2; } if (k < -1 || k > 1) { kc = k/2; } d2new_c = 0; for (d = 0; d < DIM; d++) { d2new_c += sqr(pos[d] + trial[d] - jc*box[YY][d] - kc*box[ZZ][d]); } if (d2new_c > BOX_MARGIN*d2new) { /* Reject this shift vector, as there is no a priori limit * to the number of shifts that decrease distances. */ if (!pbc->bLimitDistance || d2new < pbc->limit_distance2) { pbc->limit_distance2 = d2new; } pbc->bLimitDistance = TRUE; } } else { /* Check if shifts with one box vector less do better */ bUse = TRUE; for (dd = 0; dd < DIM; dd++) { shift = (dd == 0 ? i : (dd == 1 ? j : k)); if (shift) { d2new_c = 0; for (d = 0; d < DIM; d++) { d2new_c += sqr(pos[d] + trial[d] - shift*box[dd][d]); } if (d2new_c <= BOX_MARGIN*d2new) { bUse = FALSE; } } } if (bUse) { /* Accept this shift vector. */ if (pbc->ntric_vec >= MAX_NTRICVEC) { fprintf(stderr, "\nWARNING: Found more than %d triclinic correction vectors, ignoring some.\n" " There is probably something wrong with your box.\n", MAX_NTRICVEC); pr_rvecs(stderr, 0, " Box", box, DIM); } else { copy_rvec(trial, pbc->tric_vec[pbc->ntric_vec]); pbc->tric_shift[pbc->ntric_vec][XX] = i; pbc->tric_shift[pbc->ntric_vec][YY] = j; pbc->tric_shift[pbc->ntric_vec][ZZ] = k; pbc->ntric_vec++; } } } if (debug) { fprintf(debug, " tricvec %2d = %2d %2d %2d %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f\n", pbc->ntric_vec, i, j, k, sqrt(d2old), sqrt(d2new), trial[XX], trial[YY], trial[ZZ], pos[XX], pos[YY], pos[ZZ]); } } } } } } } } }
void do_force_lowlevel(FILE *fplog, gmx_large_int_t step, t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, t_grpopts *opts, rvec x[], history_t *hist, rvec f[], rvec f_longrange[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_mtop_t *mtop, gmx_localtop_t *top, gmx_genborn_t *born, t_atomtypes *atype, gmx_bool bBornRadii, matrix box, t_lambda *fepvals, real *lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i, j, status; int donb_flags; gmx_bool bDoEpot, bSepDVDL, bSB; int pme_flags; matrix boxs; rvec box_size; real Vsr, Vlr, Vcorr = 0; t_pbc pbc; real dvdgb; char buf[22]; double clam_i, vlam_i; real dvdl_dum[efptNR], dvdl, dvdl_nb[efptNR], lam_i[efptNR]; real dvdlsum; #ifdef GMX_MPI double t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */ #endif #define PRINT_SEPDVDL(s, v, dvdlambda) if (bSepDVDL) {fprintf(fplog, sepdvdlformat, s, v, dvdlambda); } GMX_MPE_LOG(ev_force_start); set_pbc(&pbc, fr->ePBC, box); /* reset free energy components */ for (i = 0; i < efptNR; i++) { dvdl_nb[i] = 0; dvdl_dum[i] = 0; } /* Reset box */ for (i = 0; (i < DIM); i++) { box_size[i] = box[i][i]; } bSepDVDL = (fr->bSepDVDL && do_per_step(step, ir->nstlog)); debug_gmx(); /* do QMMM first if requested */ if (fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr, md); } if (bSepDVDL) { fprintf(fplog, "Step %s: non-bonded V and dVdl for node %d:\n", gmx_step_str(step, buf), cr->nodeid); } /* Call the short range functions all in one go. */ GMX_MPE_LOG(ev_do_fnbf_start); #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0 = MPI_Wtime(); } #endif if (ir->nwall) { /* foreign lambda component for walls */ dvdl = do_walls(ir, fr, box, md, x, f, lambda[efptVDW], enerd->grpp.ener[egLJSR], nrnb); PRINT_SEPDVDL("Walls", 0.0, dvdl); enerd->dvdl_lin[efptVDW] += dvdl; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsNONBONDED); for (i = 0; i < born->nr; i++) { fr->dvda[i] = 0; } if (bBornRadii) { calc_gb_rad(cr, fr, ir, top, atype, x, &(fr->gblist), born, md, nrnb); } wallcycle_sub_stop(wcycle, ewcsNONBONDED); } where(); /* We only do non-bonded calculation with group scheme here, the verlet * calls are done from do_force_cutsVERLET(). */ if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED)) { donb_flags = 0; /* Add short-range interactions */ donb_flags |= GMX_NONBONDED_DO_SR; if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_NONBONDED_DO_FORCE; } if (flags & GMX_FORCE_ENERGY) { donb_flags |= GMX_NONBONDED_DO_POTENTIAL; } if (flags & GMX_FORCE_DO_LR) { donb_flags |= GMX_NONBONDED_DO_LR; } wallcycle_sub_start(wcycle, ewcsNONBONDED); do_nonbonded(cr, fr, x, f, f_longrange, md, excl, &enerd->grpp, box_size, nrnb, lambda, dvdl_nb, -1, -1, donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0) { for (i = 0; i < enerd->n_lambda; i++) { for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } reset_foreign_enerdata(enerd); do_nonbonded(cr, fr, x, f, f_longrange, md, excl, &(enerd->foreign_grpp), box_size, nrnb, lam_i, dvdl_dum, -1, -1, (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA); sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } wallcycle_sub_stop(wcycle, ewcsNONBONDED); where(); } /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ /* MRS: Eventually, many need to include free energy contribution here! */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsBONDED); calc_gb_forces(cr, md, born, top, atype, x, f, fr, idef, ir->gb_algorithm, ir->sa_algorithm, nrnb, bBornRadii, &pbc, graph, enerd); wallcycle_sub_stop(wcycle, ewcsBONDED); } #ifdef GMX_MPI if (TAKETIME) { t1 = MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (fepvals->sc_alpha != 0) { enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW]; } else { enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW]; } if (fepvals->sc_alpha != 0) /* even though coulomb part is linear, we already added it, beacuse we need to go through the vdw calculation anyway */ { enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL]; } else { enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL]; } Vsr = 0; if (bSepDVDL) { for (i = 0; i < enerd->grpp.nener; i++) { Vsr += (fr->bBHAM ? enerd->grpp.ener[egBHAMSR][i] : enerd->grpp.ener[egLJSR][i]) + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i]; } dvdlsum = dvdl_nb[efptVDW] + dvdl_nb[efptCOUL]; PRINT_SEPDVDL("VdW and Coulomb SR particle-p.", Vsr, dvdlsum); } debug_gmx(); GMX_MPE_LOG(ev_do_fnbf_finish); if (debug) { pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS); } /* Shift the coordinates. Must be done before bonded forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no bonded forces have to be evaluated. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph, box, x); if (TRICLINIC(box)) { inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes); } else { inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes); } } /* Check whether we need to do bondeds or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_BONDED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype))) { /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box); } debug_gmx(); if (flags & GMX_FORCE_BONDED) { GMX_MPE_LOG(ev_calc_bonds_start); wallcycle_sub_start(wcycle, ewcsBONDED); calc_bonds(fplog, cr->ms, idef, x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born, flags, fr->bSepDVDL && do_per_step(step, ir->nstlog), step); /* Check if we have to determine energy differences * at foreign lambda's. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && idef->ilsort != ilsortNO_FE) { if (idef->ilsort != ilsortFE_SORTED) { gmx_incons("The bonded interactions are not sorted for free energy"); } for (i = 0; i < enerd->n_lambda; i++) { reset_foreign_enerdata(enerd); for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } calc_bonds_lambda(fplog, idef, x, fr, &pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL); sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } debug_gmx(); GMX_MPE_LOG(ev_calc_bonds_finish); wallcycle_sub_stop(wcycle, ewcsBONDED); } where(); *cycles_pme = 0; if (EEL_FULL(fr->eeltype)) { bSB = (ir->nwall == 2); if (bSB) { copy_mat(box, boxs); svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } clear_mat(fr->vir_el_recip); if (fr->bEwald) { Vcorr = 0; dvdl = 0; /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid contributions * will be calculated in gmx_pme_calc_energy. */ if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) || ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { int nthreads, t; wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION); if (fr->n_tpi > 0) { gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } nthreads = gmx_omp_nthreads_get(emntBonded); #pragma omp parallel for num_threads(nthreads) schedule(static) for (t = 0; t < nthreads; t++) { int s, e, i; rvec *fnv; tensor *vir; real *Vcorrt, *dvdlt; if (t == 0) { fnv = fr->f_novirsum; vir = &fr->vir_el_recip; Vcorrt = &Vcorr; dvdlt = &dvdl; } else { fnv = fr->f_t[t].f; vir = &fr->f_t[t].vir; Vcorrt = &fr->f_t[t].Vcorr; dvdlt = &fr->f_t[t].dvdl[efptCOUL]; for (i = 0; i < fr->natoms_force; i++) { clear_rvec(fnv[i]); } clear_mat(*vir); } *dvdlt = 0; *Vcorrt = ewald_LRcorrection(fplog, fr->excl_load[t], fr->excl_load[t+1], cr, t, fr, md->chargeA, md->nChargePerturbed ? md->chargeB : NULL, ir->cutoff_scheme != ecutsVERLET, excl, x, bSB ? boxs : box, mu_tot, ir->ewald_geometry, ir->epsilon_surface, fnv, *vir, lambda[efptCOUL], dvdlt); } if (nthreads > 1) { reduce_thread_forces(fr->natoms_force, fr->f_novirsum, fr->vir_el_recip, &Vcorr, efptCOUL, &dvdl, nthreads, fr->f_t); } wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION); } if (fr->n_tpi == 0) { Vcorr += ewald_charge_correction(cr, fr, lambda[efptCOUL], box, &dvdl, fr->vir_el_recip); } PRINT_SEPDVDL("Ewald excl./charge/dip. corr.", Vcorr, dvdl); enerd->dvdl_lin[efptCOUL] += dvdl; } status = 0; Vlr = 0; dvdl = 0; switch (fr->eeltype) { case eelPME: case eelPMESWITCH: case eelPMEUSER: case eelPMEUSERSWITCH: case eelP3M_AD: if (cr->duty & DUTY_PME) { assert(fr->n_tpi >= 0); if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED)) { pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE; if (flags & GMX_FORCE_FORCES) { pme_flags |= GMX_PME_CALC_F; } if (flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY)) { pme_flags |= GMX_PME_CALC_ENER_VIR; } if (fr->n_tpi > 0) { /* We don't calculate f, but we do want the potential */ pme_flags |= GMX_PME_CALC_POT; } wallcycle_start(wcycle, ewcPMEMESH); status = gmx_pme_do(fr->pmedata, md->start, md->homenr - fr->n_tpi, x, fr->f_novirsum, md->chargeA, md->chargeB, bSB ? boxs : box, cr, DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0, DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb, wcycle, fr->vir_el_recip, fr->ewaldcoeff, &Vlr, lambda[efptCOUL], &dvdl, pme_flags); *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH); /* We should try to do as little computation after * this as possible, because parallel PME synchronizes * the nodes, so we want all load imbalance of the rest * of the force calculation to be before the PME call. * DD load balancing is done on the whole time of * the force call (without PME). */ } if (fr->n_tpi > 0) { /* Determine the PME grid energy of the test molecule * with the PME grid potential of the other charges. */ gmx_pme_calc_energy(fr->pmedata, fr->n_tpi, x + md->homenr - fr->n_tpi, md->chargeA + md->homenr - fr->n_tpi, &Vlr); } PRINT_SEPDVDL("PME mesh", Vlr, dvdl); } break; case eelEWALD: Vlr = do_ewald(fplog, FALSE, ir, x, fr->f_novirsum, md->chargeA, md->chargeB, box_size, cr, md->homenr, fr->vir_el_recip, fr->ewaldcoeff, lambda[efptCOUL], &dvdl, fr->ewald_table); PRINT_SEPDVDL("Ewald long-range", Vlr, dvdl); break; default: gmx_fatal(FARGS, "No such electrostatics method implemented %s", eel_names[fr->eeltype]); } if (status != 0) { gmx_fatal(FARGS, "Error %d in long range electrostatics routine %s", status, EELTYPE(fr->eeltype)); } /* Note that with separate PME nodes we get the real energies later */ enerd->dvdl_lin[efptCOUL] += dvdl; enerd->term[F_COUL_RECIP] = Vlr + Vcorr; if (debug) { fprintf(debug, "Vlr = %g, Vcorr = %g, Vlr_corr = %g\n", Vlr, Vcorr, enerd->term[F_COUL_RECIP]); pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM); pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS); } } else { if (EEL_RF(fr->eeltype)) { /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ if (ir->cutoff_scheme != ecutsVERLET && fr->eeltype != eelRF_NEC) { dvdl = 0; enerd->term[F_RF_EXCL] = RF_excl_correction(fplog, fr, graph, md, excl, x, f, fr->fshift, &pbc, lambda[efptCOUL], &dvdl); } enerd->dvdl_lin[efptCOUL] += dvdl; PRINT_SEPDVDL("RF exclusion correction", enerd->term[F_RF_EXCL], dvdl); } } where(); debug_gmx(); if (debug) { print_nrnb(debug, nrnb); } debug_gmx(); #ifdef GMX_MPI if (TAKETIME) { t2 = MPI_Wtime(); MPI_Barrier(cr->mpi_comm_mygroup); t3 = MPI_Wtime(); fr->t_wait += t3-t2; if (fr->timesteps == 11) { fprintf(stderr, "* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", cr->nodeid, gmx_step_str(fr->timesteps, buf), 100*fr->t_wait/(fr->t_wait+fr->t_fnbf), (fr->t_fnbf+fr->t_wait)/fr->t_fnbf); } fr->timesteps++; } #endif if (debug) { pr_rvecs(debug, 0, "fshift after bondeds", fr->fshift, SHIFTS); } GMX_MPE_LOG(ev_force_finish); }
void init_md(t_commrec *cr,t_inputrec *ir,tensor box,real *t,real *t0, real *lambda,real *lam0,real *SAfactor, t_nrnb *mynrnb,bool *bTYZ,t_topology *top, int nfile,t_filenm fnm[],char **traj, char **xtc_traj,int *fp_ene, FILE **fp_dgdl,t_mdebin **mdebin,t_groups *grps, tensor force_vir,tensor pme_vir, tensor shake_vir,t_mdatoms *mdatoms,rvec mu_tot, bool *bNEMD,t_vcm **vcm,t_nsborder *nsb) { bool bBHAM,b14,bLR,bLJLR; int i; /* Initial values */ *t = *t0 = ir->init_t; if (ir->efep != efepNO) { *lambda = *lam0 = ir->init_lambda; } else { *lambda = *lam0 = 0.0; } if (ir->bSimAnn) { *SAfactor = 1.0 - *t0/ir->zero_temp_time; if (*SAfactor < 0) *SAfactor = 0; } else *SAfactor = 1.0; init_nrnb(mynrnb); /* Check Environment variables & other booleans */ #ifdef SPEC_CPU *bTYZ = FALSE; #else *bTYZ=getenv("TYZ") != NULL; #endif set_pot_bools(ir,top,&bLR,&bLJLR,&bBHAM,&b14); if (nfile != -1) { /* Filenames */ *traj = ftp2fn(efTRN,nfile,fnm); *xtc_traj = ftp2fn(efXTC,nfile,fnm); #ifndef SPEC_CPU if (MASTER(cr)) { *fp_ene = open_enx(ftp2fn(efENX,nfile,fnm),"w"); if ((fp_dgdl != NULL) && ir->efep!=efepNO) *fp_dgdl = xvgropen(opt2fn("-dgdl",nfile,fnm), "dG/d\\8l\\4","Time (ps)", "dG/d\\8l\\4 (kJ mol\\S-1\\N nm\\S-2\\N \\8l\\4\\S-1\\N)"); } else #endif *fp_ene = -1; *mdebin = init_mdebin(*fp_ene,grps,&(top->atoms),&(top->idef), bLR,bLJLR,bBHAM,b14,ir->efep!=efepNO,ir->epc, ir->eDispCorr,(TRICLINIC(ir->compress) || TRICLINIC(box)), (ir->etc==etcNOSEHOOVER),cr); } /* Initiate variables */ clear_mat(force_vir); clear_mat(pme_vir); clear_mat(shake_vir); clear_rvec(mu_tot); /* Set initial values for invmass etc. */ init_mdatoms(mdatoms,*lambda,TRUE); *vcm = init_vcm(stdlog,top,cr,mdatoms,START(nsb),HOMENR(nsb),ir->nstcomm); debug_gmx(); *bNEMD = (ir->opts.ngacc > 1) || (norm(ir->opts.acc[0]) > 0); if (ir->eI == eiSD) init_sd_consts(ir->opts.ngtc,ir->opts.tau_t,ir->delta_t); }
void do_force_lowlevel(t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, rvec x[], history_t *hist, rvec f[], rvec f_longrange[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_localtop_t *top, gmx_genborn_t *born, gmx_bool bBornRadii, matrix box, t_lambda *fepvals, real *lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i, j; int donb_flags; gmx_bool bSB; int pme_flags; matrix boxs; rvec box_size; t_pbc pbc; real dvdl_dum[efptNR], dvdl_nb[efptNR]; #ifdef GMX_MPI double t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */ #endif set_pbc(&pbc, fr->ePBC, box); /* reset free energy components */ for (i = 0; i < efptNR; i++) { dvdl_nb[i] = 0; dvdl_dum[i] = 0; } /* Reset box */ for (i = 0; (i < DIM); i++) { box_size[i] = box[i][i]; } debug_gmx(); /* do QMMM first if requested */ if (fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr); } /* Call the short range functions all in one go. */ #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0 = MPI_Wtime(); } #endif if (ir->nwall) { /* foreign lambda component for walls */ real dvdl_walls = do_walls(ir, fr, box, md, x, f, lambda[efptVDW], enerd->grpp.ener[egLJSR], nrnb); enerd->dvdl_lin[efptVDW] += dvdl_walls; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsNONBONDED); for (i = 0; i < born->nr; i++) { fr->dvda[i] = 0; } if (bBornRadii) { calc_gb_rad(cr, fr, ir, top, x, &(fr->gblist), born, md, nrnb); } wallcycle_sub_stop(wcycle, ewcsNONBONDED); } where(); /* We only do non-bonded calculation with group scheme here, the verlet * calls are done from do_force_cutsVERLET(). */ if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED)) { donb_flags = 0; /* Add short-range interactions */ donb_flags |= GMX_NONBONDED_DO_SR; /* Currently all group scheme kernels always calculate (shift-)forces */ if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_NONBONDED_DO_FORCE; } if (flags & GMX_FORCE_VIRIAL) { donb_flags |= GMX_NONBONDED_DO_SHIFTFORCE; } if (flags & GMX_FORCE_ENERGY) { donb_flags |= GMX_NONBONDED_DO_POTENTIAL; } if (flags & GMX_FORCE_DO_LR) { donb_flags |= GMX_NONBONDED_DO_LR; } wallcycle_sub_start(wcycle, ewcsNONBONDED); do_nonbonded(fr, x, f, f_longrange, md, excl, &enerd->grpp, nrnb, lambda, dvdl_nb, -1, -1, donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0) { for (i = 0; i < enerd->n_lambda; i++) { real lam_i[efptNR]; for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } reset_foreign_enerdata(enerd); do_nonbonded(fr, x, f, f_longrange, md, excl, &(enerd->foreign_grpp), nrnb, lam_i, dvdl_dum, -1, -1, (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA); sum_epot(&(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } wallcycle_sub_stop(wcycle, ewcsNONBONDED); where(); } /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ /* MRS: Eventually, many need to include free energy contribution here! */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsLISTED); calc_gb_forces(cr, md, born, top, x, f, fr, idef, ir->gb_algorithm, ir->sa_algorithm, nrnb, &pbc, graph, enerd); wallcycle_sub_stop(wcycle, ewcsLISTED); } #ifdef GMX_MPI if (TAKETIME) { t1 = MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (fepvals->sc_alpha != 0) { enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW]; } else { enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW]; } if (fepvals->sc_alpha != 0) /* even though coulomb part is linear, we already added it, beacuse we need to go through the vdw calculation anyway */ { enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL]; } else { enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL]; } debug_gmx(); if (debug) { pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS); } /* Shift the coordinates. Must be done before listed forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no listed forces have to be evaluated. * * The shifting and PBC code is deliberately not timed, since with * the Verlet scheme it only takes non-zero time with triclinic * boxes, and even then the time is around a factor of 100 less * than the next smallest counter. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph, box, x); if (TRICLINIC(box)) { inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes); } else { inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes); } } /* Check whether we need to do listed interactions or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_LISTED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype))) { /* TODO There are no electrostatics methods that require this transformation, when using the Verlet scheme, so update the above conditional. */ /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box); } debug_gmx(); do_force_listed(wcycle, box, ir->fepvals, cr->ms, idef, (const rvec *) x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, flags); where(); *cycles_pme = 0; clear_mat(fr->vir_el_recip); clear_mat(fr->vir_lj_recip); /* Do long-range electrostatics and/or LJ-PME, including related short-range * corrections. */ if (EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype)) { int status = 0; real Vlr_q = 0, Vlr_lj = 0, Vcorr_q = 0, Vcorr_lj = 0; real dvdl_long_range_q = 0, dvdl_long_range_lj = 0; bSB = (ir->nwall == 2); if (bSB) { copy_mat(box, boxs); svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } if (EEL_PME_EWALD(fr->eeltype) || EVDW_PME(fr->vdwtype)) { real dvdl_long_range_correction_q = 0; real dvdl_long_range_correction_lj = 0; /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid * contributions will be calculated in * gmx_pme_calc_energy. */ if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) || ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { int nthreads, t; wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION); if (fr->n_tpi > 0) { gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } nthreads = gmx_omp_nthreads_get(emntBonded); #pragma omp parallel for num_threads(nthreads) schedule(static) for (t = 0; t < nthreads; t++) { int i; rvec *fnv; tensor *vir_q, *vir_lj; real *Vcorrt_q, *Vcorrt_lj, *dvdlt_q, *dvdlt_lj; if (t == 0) { fnv = fr->f_novirsum; vir_q = &fr->vir_el_recip; vir_lj = &fr->vir_lj_recip; Vcorrt_q = &Vcorr_q; Vcorrt_lj = &Vcorr_lj; dvdlt_q = &dvdl_long_range_correction_q; dvdlt_lj = &dvdl_long_range_correction_lj; } else { fnv = fr->f_t[t].f; vir_q = &fr->f_t[t].vir_q; vir_lj = &fr->f_t[t].vir_lj; Vcorrt_q = &fr->f_t[t].Vcorr_q; Vcorrt_lj = &fr->f_t[t].Vcorr_lj; dvdlt_q = &fr->f_t[t].dvdl[efptCOUL]; dvdlt_lj = &fr->f_t[t].dvdl[efptVDW]; for (i = 0; i < fr->natoms_force; i++) { clear_rvec(fnv[i]); } clear_mat(*vir_q); clear_mat(*vir_lj); } *dvdlt_q = 0; *dvdlt_lj = 0; ewald_LRcorrection(fr->excl_load[t], fr->excl_load[t+1], cr, t, fr, md->chargeA, md->chargeB, md->sqrt_c6A, md->sqrt_c6B, md->sigmaA, md->sigmaB, md->sigma3A, md->sigma3B, md->nChargePerturbed || md->nTypePerturbed, ir->cutoff_scheme != ecutsVERLET, excl, x, bSB ? boxs : box, mu_tot, ir->ewald_geometry, ir->epsilon_surface, fnv, *vir_q, *vir_lj, Vcorrt_q, Vcorrt_lj, lambda[efptCOUL], lambda[efptVDW], dvdlt_q, dvdlt_lj); } if (nthreads > 1) { reduce_thread_forces(fr->natoms_force, fr->f_novirsum, fr->vir_el_recip, fr->vir_lj_recip, &Vcorr_q, &Vcorr_lj, &dvdl_long_range_correction_q, &dvdl_long_range_correction_lj, nthreads, fr->f_t); } wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION); } if (EEL_PME_EWALD(fr->eeltype) && fr->n_tpi == 0) { /* This is not in a subcounter because it takes a negligible and constant-sized amount of time */ Vcorr_q += ewald_charge_correction(cr, fr, lambda[efptCOUL], box, &dvdl_long_range_correction_q, fr->vir_el_recip); } enerd->dvdl_lin[efptCOUL] += dvdl_long_range_correction_q; enerd->dvdl_lin[efptVDW] += dvdl_long_range_correction_lj; if ((EEL_PME(fr->eeltype) || EVDW_PME(fr->vdwtype)) && (cr->duty & DUTY_PME)) { /* Do reciprocal PME for Coulomb and/or LJ. */ assert(fr->n_tpi >= 0); if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED)) { pme_flags = GMX_PME_SPREAD | GMX_PME_SOLVE; if (EEL_PME(fr->eeltype)) { pme_flags |= GMX_PME_DO_COULOMB; } if (EVDW_PME(fr->vdwtype)) { pme_flags |= GMX_PME_DO_LJ; } if (flags & GMX_FORCE_FORCES) { pme_flags |= GMX_PME_CALC_F; } if (flags & GMX_FORCE_VIRIAL) { pme_flags |= GMX_PME_CALC_ENER_VIR; } if (fr->n_tpi > 0) { /* We don't calculate f, but we do want the potential */ pme_flags |= GMX_PME_CALC_POT; } wallcycle_start(wcycle, ewcPMEMESH); status = gmx_pme_do(fr->pmedata, 0, md->homenr - fr->n_tpi, x, fr->f_novirsum, md->chargeA, md->chargeB, md->sqrt_c6A, md->sqrt_c6B, md->sigmaA, md->sigmaB, bSB ? boxs : box, cr, DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0, DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb, wcycle, fr->vir_el_recip, fr->ewaldcoeff_q, fr->vir_lj_recip, fr->ewaldcoeff_lj, &Vlr_q, &Vlr_lj, lambda[efptCOUL], lambda[efptVDW], &dvdl_long_range_q, &dvdl_long_range_lj, pme_flags); *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH); if (status != 0) { gmx_fatal(FARGS, "Error %d in reciprocal PME routine", status); } /* We should try to do as little computation after * this as possible, because parallel PME synchronizes * the nodes, so we want all load imbalance of the * rest of the force calculation to be before the PME * call. DD load balancing is done on the whole time * of the force call (without PME). */ } if (fr->n_tpi > 0) { if (EVDW_PME(ir->vdwtype)) { gmx_fatal(FARGS, "Test particle insertion not implemented with LJ-PME"); } /* Determine the PME grid energy of the test molecule * with the PME grid potential of the other charges. */ gmx_pme_calc_energy(fr->pmedata, fr->n_tpi, x + md->homenr - fr->n_tpi, md->chargeA + md->homenr - fr->n_tpi, &Vlr_q); } } } if (!EEL_PME(fr->eeltype) && EEL_PME_EWALD(fr->eeltype)) { Vlr_q = do_ewald(ir, x, fr->f_novirsum, md->chargeA, md->chargeB, box_size, cr, md->homenr, fr->vir_el_recip, fr->ewaldcoeff_q, lambda[efptCOUL], &dvdl_long_range_q, fr->ewald_table); } /* Note that with separate PME nodes we get the real energies later */ enerd->dvdl_lin[efptCOUL] += dvdl_long_range_q; enerd->dvdl_lin[efptVDW] += dvdl_long_range_lj; enerd->term[F_COUL_RECIP] = Vlr_q + Vcorr_q; enerd->term[F_LJ_RECIP] = Vlr_lj + Vcorr_lj; if (debug) { fprintf(debug, "Vlr_q = %g, Vcorr_q = %g, Vlr_corr_q = %g\n", Vlr_q, Vcorr_q, enerd->term[F_COUL_RECIP]); pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM); pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS); fprintf(debug, "Vlr_lj: %g, Vcorr_lj = %g, Vlr_corr_lj = %g\n", Vlr_lj, Vcorr_lj, enerd->term[F_LJ_RECIP]); pr_rvecs(debug, 0, "vir_lj_recip after corr", fr->vir_lj_recip, DIM); } } else { /* Is there a reaction-field exclusion correction needed? */ if (EEL_RF(fr->eeltype) && eelRF_NEC != fr->eeltype) { /* With the Verlet scheme, exclusion forces are calculated * in the non-bonded kernel. */ if (ir->cutoff_scheme != ecutsVERLET) { real dvdl_rf_excl = 0; enerd->term[F_RF_EXCL] = RF_excl_correction(fr, graph, md, excl, x, f, fr->fshift, &pbc, lambda[efptCOUL], &dvdl_rf_excl); enerd->dvdl_lin[efptCOUL] += dvdl_rf_excl; } } } where(); debug_gmx(); if (debug) { print_nrnb(debug, nrnb); } debug_gmx(); #ifdef GMX_MPI if (TAKETIME) { t2 = MPI_Wtime(); MPI_Barrier(cr->mpi_comm_mygroup); t3 = MPI_Wtime(); fr->t_wait += t3-t2; if (fr->timesteps == 11) { char buf[22]; fprintf(stderr, "* PP load balancing info: rank %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", cr->nodeid, gmx_step_str(fr->timesteps, buf), 100*fr->t_wait/(fr->t_wait+fr->t_fnbf), (fr->t_fnbf+fr->t_wait)/fr->t_fnbf); } fr->timesteps++; } #endif if (debug) { pr_rvecs(debug, 0, "fshift after bondeds", fr->fshift, SHIFTS); } }
t_mdebin *init_mdebin(ener_file_t fp_ene, const gmx_mtop_t *mtop, const t_inputrec *ir, FILE *fp_dhdl) { const char *ener_nm[F_NRE]; static const char *vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY", "Vir-YZ", "Vir-ZX", "Vir-ZY", "Vir-ZZ" }; static const char *sv_nm[] = { "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ", "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ", "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ" }; static const char *fv_nm[] = { "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ", "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ", "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ" }; static const char *pres_nm[] = { "Pres-XX","Pres-XY","Pres-XZ", "Pres-YX","Pres-YY","Pres-YZ", "Pres-ZX","Pres-ZY","Pres-ZZ" }; static const char *surft_nm[] = { "#Surf*SurfTen" }; static const char *mu_nm[] = { "Mu-X", "Mu-Y", "Mu-Z" }; static const char *vcos_nm[] = { "2CosZ*Vel-X" }; static const char *visc_nm[] = { "1/Viscosity" }; static const char *baro_nm[] = { "Barostat" }; char **grpnms; const gmx_groups_t *groups; char **gnm; char buf[256]; const char *bufi; t_mdebin *md; int i,j,ni,nj,n,nh,k,kk,ncon,nset; gmx_bool bBHAM,bNoseHoover,b14; snew(md,1); if (EI_DYNAMICS(ir->eI)) { md->delta_t = ir->delta_t; } else { md->delta_t = 0; } groups = &mtop->groups; bBHAM = (mtop->ffparams.functype[0] == F_BHAM); b14 = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 || gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0); ncon = gmx_mtop_ftype_count(mtop,F_CONSTR); nset = gmx_mtop_ftype_count(mtop,F_SETTLE); md->bConstr = (ncon > 0 || nset > 0); md->bConstrVir = FALSE; if (md->bConstr) { if (ncon > 0 && ir->eConstrAlg == econtLINCS) { if (ir->eI == eiSD2) md->nCrmsd = 2; else md->nCrmsd = 1; } md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL); } else { md->nCrmsd = 0; } /* Energy monitoring */ for(i=0;i<egNR;i++) { md->bEInd[i]=FALSE; } #ifndef GMX_OPENMM for(i=0; i<F_NRE; i++) { md->bEner[i] = FALSE; if (i == F_LJ) md->bEner[i] = !bBHAM; else if (i == F_BHAM) md->bEner[i] = bBHAM; else if (i == F_EQM) md->bEner[i] = ir->bQMMM; else if (i == F_COUL_LR) md->bEner[i] = (ir->rcoulomb > ir->rlist); else if (i == F_LJ_LR) md->bEner[i] = (!bBHAM && ir->rvdw > ir->rlist); else if (i == F_BHAM_LR) md->bEner[i] = (bBHAM && ir->rvdw > ir->rlist); else if (i == F_RF_EXCL) md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC); else if (i == F_COUL_RECIP) md->bEner[i] = EEL_FULL(ir->coulombtype); else if (i == F_LJ14) md->bEner[i] = b14; else if (i == F_COUL14) md->bEner[i] = b14; else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB) md->bEner[i] = FALSE; else if ((i == F_DVDL) || (i == F_DKDL)) md->bEner[i] = (ir->efep != efepNO); else if (i == F_DHDL_CON) md->bEner[i] = (ir->efep != efepNO && md->bConstr); else if ((interaction_function[i].flags & IF_VSITE) || (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE)) md->bEner[i] = FALSE; else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES) || (i==F_EQM)) md->bEner[i] = TRUE; else if ((i == F_GBPOL) && ir->implicit_solvent==eisGBSA) md->bEner[i] = TRUE; else if ((i == F_NPSOLVATION) && ir->implicit_solvent==eisGBSA && (ir->sa_algorithm != esaNO)) md->bEner[i] = TRUE; else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14)) md->bEner[i] = FALSE; else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP)) md->bEner[i] = EI_DYNAMICS(ir->eI); else if (i==F_VTEMP) md->bEner[i] = (EI_DYNAMICS(ir->eI) && getenv("GMX_VIRIAL_TEMPERATURE")); else if (i == F_DISPCORR || i == F_PDISPCORR) md->bEner[i] = (ir->eDispCorr != edispcNO); else if (i == F_DISRESVIOL) md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0); else if (i == F_ORIRESDEV) md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0); else if (i == F_CONNBONDS) md->bEner[i] = FALSE; else if (i == F_COM_PULL) md->bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F); else if (i == F_ECONSERVED) md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) && (ir->epc == epcNO || ir->epc==epcMTTK)); else md->bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0); } #else /* OpenMM always produces only the following 4 energy terms */ md->bEner[F_EPOT] = TRUE; md->bEner[F_EKIN] = TRUE; md->bEner[F_ETOT] = TRUE; md->bEner[F_TEMP] = TRUE; #endif md->f_nre=0; for(i=0; i<F_NRE; i++) { if (md->bEner[i]) { /* FIXME: The constness should not be cast away */ /*ener_nm[f_nre]=(char *)interaction_function[i].longname;*/ ener_nm[md->f_nre]=interaction_function[i].longname; md->f_nre++; } } md->epc = ir->epc; for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { md->ref_p[i][j] = ir->ref_p[i][j]; } } md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); md->bDynBox = DYNAMIC_BOX(*ir); md->etc = ir->etc; md->bNHC_trotter = IR_NVT_TROTTER(ir); md->bMTTK = IR_NPT_TROTTER(ir); md->ebin = mk_ebin(); /* Pass NULL for unit to let get_ebin_space determine the units * for interaction_function[i].longname */ md->ie = get_ebin_space(md->ebin,md->f_nre,ener_nm,NULL); if (md->nCrmsd) { /* This should be called directly after the call for md->ie, * such that md->iconrmsd follows directly in the list. */ md->iconrmsd = get_ebin_space(md->ebin,md->nCrmsd,conrmsd_nm,""); } if (md->bDynBox) { md->ib = get_ebin_space(md->ebin, md->bTricl ? NTRICLBOXS : NBOXS, md->bTricl ? tricl_boxs_nm : boxs_nm, unit_length); md->ivol = get_ebin_space(md->ebin, 1, vol_nm, unit_volume); md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI); md->ipv = get_ebin_space(md->ebin, 1, pv_nm, unit_energy); md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm, unit_energy); } if (md->bConstrVir) { md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm,unit_energy); md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm,unit_energy); } md->ivir = get_ebin_space(md->ebin,asize(vir_nm),vir_nm,unit_energy); md->ipres = get_ebin_space(md->ebin,asize(pres_nm),pres_nm,unit_pres_bar); md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm, unit_surft_bar); if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK) { md->ipc = get_ebin_space(md->ebin,md->bTricl ? 6 : 3, boxvel_nm,unit_vel); } md->imu = get_ebin_space(md->ebin,asize(mu_nm),mu_nm,unit_dipole_D); if (ir->cos_accel != 0) { md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm,unit_vel); md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm, unit_invvisc_SI); } /* Energy monitoring */ for(i=0;i<egNR;i++) { md->bEInd[i] = FALSE; } md->bEInd[egCOULSR] = TRUE; md->bEInd[egLJSR ] = TRUE; if (ir->rcoulomb > ir->rlist) { md->bEInd[egCOULLR] = TRUE; } if (!bBHAM) { if (ir->rvdw > ir->rlist) { md->bEInd[egLJLR] = TRUE; } } else { md->bEInd[egLJSR] = FALSE; md->bEInd[egBHAMSR] = TRUE; if (ir->rvdw > ir->rlist) { md->bEInd[egBHAMLR] = TRUE; } } if (b14) { md->bEInd[egLJ14] = TRUE; md->bEInd[egCOUL14] = TRUE; } md->nEc=0; for(i=0; (i<egNR); i++) { if (md->bEInd[i]) { md->nEc++; } } n=groups->grps[egcENER].nr; md->nEg=n; md->nE=(n*(n+1))/2; snew(md->igrp,md->nE); if (md->nE > 1) { n=0; snew(gnm,md->nEc); for(k=0; (k<md->nEc); k++) { snew(gnm[k],STRLEN); } for(i=0; (i<groups->grps[egcENER].nr); i++) { ni=groups->grps[egcENER].nm_ind[i]; for(j=i; (j<groups->grps[egcENER].nr); j++) { nj=groups->grps[egcENER].nm_ind[j]; for(k=kk=0; (k<egNR); k++) { if (md->bEInd[k]) { sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k], *(groups->grpname[ni]),*(groups->grpname[nj])); kk++; } } md->igrp[n]=get_ebin_space(md->ebin,md->nEc, (const char **)gnm,unit_energy); n++; } } for(k=0; (k<md->nEc); k++) { sfree(gnm[k]); } sfree(gnm); if (n != md->nE) { gmx_incons("Number of energy terms wrong"); } } md->nTC=groups->grps[egcTC].nr; md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ if (md->bMTTK) { md->nTCP = 1; /* assume only one possible coupling system for barostat for now */ } else { md->nTCP = 0; } if (md->etc == etcNOSEHOOVER) { if (md->bNHC_trotter) { md->mde_n = 2*md->nNHC*md->nTC; } else { md->mde_n = 2*md->nTC; } if (md->epc == epcMTTK) { md->mdeb_n = 2*md->nNHC*md->nTCP; } } else { md->mde_n = md->nTC; md->mdeb_n = 0; } snew(md->tmp_r,md->mde_n); snew(md->tmp_v,md->mde_n); snew(md->grpnms,md->mde_n); grpnms = md->grpnms; for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"T-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itemp=get_ebin_space(md->ebin,md->nTC,(const char **)grpnms, unit_temp_K); bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); /* whether to print Nose-Hoover chains */ if (md->etc == etcNOSEHOOVER) { if (bNoseHoover) { if (md->bNHC_trotter) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); for(j=0; (j<md->nNHC); j++) { sprintf(buf,"Xi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)]=strdup(buf); sprintf(buf,"vXi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)+1]=strdup(buf); } } md->itc=get_ebin_space(md->ebin,md->mde_n, (const char **)grpnms,unit_invtime); if (md->bMTTK) { for(i=0; (i<md->nTCP); i++) { bufi = baro_nm[0]; /* All barostat DOF's together for now. */ for(j=0; (j<md->nNHC); j++) { sprintf(buf,"Xi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)]=strdup(buf); sprintf(buf,"vXi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)+1]=strdup(buf); } } md->itcb=get_ebin_space(md->ebin,md->mdeb_n, (const char **)grpnms,unit_invtime); } } else { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); sprintf(buf,"Xi-%s",bufi); grpnms[2*i]=strdup(buf); sprintf(buf,"vXi-%s",bufi); grpnms[2*i+1]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->mde_n, (const char **)grpnms,unit_invtime); } } } else if (md->etc == etcBERENDSEN || md->etc == etcYES || md->etc == etcVRESCALE) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Lamb-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->mde_n,(const char **)grpnms,""); } sfree(grpnms); md->nU=groups->grps[egcACC].nr; if (md->nU > 1) { snew(grpnms,3*md->nU); for(i=0; (i<md->nU); i++) { ni=groups->grps[egcACC].nm_ind[i]; sprintf(buf,"Ux-%s",*(groups->grpname[ni])); grpnms[3*i+XX]=strdup(buf); sprintf(buf,"Uy-%s",*(groups->grpname[ni])); grpnms[3*i+YY]=strdup(buf); sprintf(buf,"Uz-%s",*(groups->grpname[ni])); grpnms[3*i+ZZ]=strdup(buf); } md->iu=get_ebin_space(md->ebin,3*md->nU,(const char **)grpnms,unit_vel); sfree(grpnms); } if ( fp_ene ) { do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm); } md->print_grpnms=NULL; /* check whether we're going to write dh histograms */ md->dhc=NULL; if (ir->separate_dhdl_file == sepdhdlfileNO ) { int i; snew(md->dhc, 1); mde_delta_h_coll_init(md->dhc, ir); md->fp_dhdl = NULL; } else { md->fp_dhdl = fp_dhdl; } md->dhdl_derivatives = (ir->dhdl_derivatives==dhdlderivativesYES); return md; }
void do_force_lowlevel(t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, rvec x[], history_t *hist, rvec f[], rvec f_longrange[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_localtop_t *top, gmx_genborn_t *born, gmx_bool bBornRadii, matrix box, t_lambda *fepvals, real *lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i, j; int donb_flags; gmx_bool bSB; int pme_flags; matrix boxs; rvec box_size; t_pbc pbc; real dvdl_dum[efptNR], dvdl_nb[efptNR]; #ifdef GMX_MPI double t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */ #endif set_pbc(&pbc, fr->ePBC, box); /* reset free energy components */ for (i = 0; i < efptNR; i++) { dvdl_nb[i] = 0; dvdl_dum[i] = 0; } /* Reset box */ for (i = 0; (i < DIM); i++) { box_size[i] = box[i][i]; } debug_gmx(); /* do QMMM first if requested */ if (fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr); } /* Call the short range functions all in one go. */ #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0 = MPI_Wtime(); } #endif if (ir->nwall) { /* foreign lambda component for walls */ real dvdl_walls = do_walls(ir, fr, box, md, x, f, lambda[efptVDW], enerd->grpp.ener[egLJSR], nrnb); enerd->dvdl_lin[efptVDW] += dvdl_walls; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsNONBONDED); for (i = 0; i < born->nr; i++) { fr->dvda[i] = 0; } if (bBornRadii) { calc_gb_rad(cr, fr, ir, top, x, &(fr->gblist), born, md, nrnb); } wallcycle_sub_stop(wcycle, ewcsNONBONDED); } where(); /* We only do non-bonded calculation with group scheme here, the verlet * calls are done from do_force_cutsVERLET(). */ if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED)) { donb_flags = 0; /* Add short-range interactions */ donb_flags |= GMX_NONBONDED_DO_SR; /* Currently all group scheme kernels always calculate (shift-)forces */ if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_NONBONDED_DO_FORCE; } if (flags & GMX_FORCE_VIRIAL) { donb_flags |= GMX_NONBONDED_DO_SHIFTFORCE; } if (flags & GMX_FORCE_ENERGY) { donb_flags |= GMX_NONBONDED_DO_POTENTIAL; } if (flags & GMX_FORCE_DO_LR) { donb_flags |= GMX_NONBONDED_DO_LR; } wallcycle_sub_start(wcycle, ewcsNONBONDED); do_nonbonded(fr, x, f, f_longrange, md, excl, &enerd->grpp, nrnb, lambda, dvdl_nb, -1, -1, donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0) { for (i = 0; i < enerd->n_lambda; i++) { real lam_i[efptNR]; for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } reset_foreign_enerdata(enerd); do_nonbonded(fr, x, f, f_longrange, md, excl, &(enerd->foreign_grpp), nrnb, lam_i, dvdl_dum, -1, -1, (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA); sum_epot(&(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } wallcycle_sub_stop(wcycle, ewcsNONBONDED); where(); } /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ /* MRS: Eventually, many need to include free energy contribution here! */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsLISTED); calc_gb_forces(cr, md, born, top, x, f, fr, idef, ir->gb_algorithm, ir->sa_algorithm, nrnb, &pbc, graph, enerd); wallcycle_sub_stop(wcycle, ewcsLISTED); } #ifdef GMX_MPI if (TAKETIME) { t1 = MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (fepvals->sc_alpha != 0) { enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW]; } else { enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW]; } if (fepvals->sc_alpha != 0) /* even though coulomb part is linear, we already added it, beacuse we need to go through the vdw calculation anyway */ { enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL]; } else { enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL]; } debug_gmx(); if (debug) { pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS); } /* Shift the coordinates. Must be done before listed forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no listed forces have to be evaluated. * * The shifting and PBC code is deliberately not timed, since with * the Verlet scheme it only takes non-zero time with triclinic * boxes, and even then the time is around a factor of 100 less * than the next smallest counter. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph, box, x); if (TRICLINIC(box)) { inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes); } else { inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes); } } /* Check whether we need to do listed interactions or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_LISTED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype))) { /* TODO There are no electrostatics methods that require this transformation, when using the Verlet scheme, so update the above conditional. */ /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box); } debug_gmx(); do_force_listed(wcycle, box, ir->fepvals, cr->ms, idef, (const rvec *) x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, flags); where(); *cycles_pme = 0; clear_mat(fr->vir_el_recip); clear_mat(fr->vir_lj_recip); /* Do long-range electrostatics and/or LJ-PME, including related short-range * corrections. */ if (EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype)) { int status = 0; real Vlr_q = 0, Vlr_lj = 0, Vcorr_q = 0, Vcorr_lj = 0; real dvdl_long_range_q = 0, dvdl_long_range_lj = 0; bSB = (ir->nwall == 2); if (bSB) { copy_mat(box, boxs); svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } if (EEL_PME_EWALD(fr->eeltype) || EVDW_PME(fr->vdwtype)) { real dvdl_long_range_correction_q = 0; real dvdl_long_range_correction_lj = 0; /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid * contributions will be calculated in * gmx_pme_calc_energy. */ if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) || ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { int nthreads, t; wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION); if (fr->n_tpi > 0) { gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } nthreads = fr->nthread_ewc; #pragma omp parallel for num_threads(nthreads) schedule(static) for (t = 0; t < nthreads; t++) { try { tensor *vir_q, *vir_lj; real *Vcorrt_q, *Vcorrt_lj, *dvdlt_q, *dvdlt_lj; if (t == 0) { vir_q = &fr->vir_el_recip; vir_lj = &fr->vir_lj_recip; Vcorrt_q = &Vcorr_q; Vcorrt_lj = &Vcorr_lj; dvdlt_q = &dvdl_long_range_correction_q; dvdlt_lj = &dvdl_long_range_correction_lj; } else { vir_q = &fr->ewc_t[t].vir_q; vir_lj = &fr->ewc_t[t].vir_lj; Vcorrt_q = &fr->ewc_t[t].Vcorr_q; Vcorrt_lj = &fr->ewc_t[t].Vcorr_lj; dvdlt_q = &fr->ewc_t[t].dvdl[efptCOUL]; dvdlt_lj = &fr->ewc_t[t].dvdl[efptVDW]; clear_mat(*vir_q); clear_mat(*vir_lj); } *dvdlt_q = 0; *dvdlt_lj = 0; /* Threading is only supported with the Verlet cut-off * scheme and then only single particle forces (no * exclusion forces) are calculated, so we can store * the forces in the normal, single fr->f_novirsum array. */ ewald_LRcorrection(fr->excl_load[t], fr->excl_load[t+1], cr, t, fr, md->chargeA, md->chargeB, md->sqrt_c6A, md->sqrt_c6B, md->sigmaA, md->sigmaB, md->sigma3A, md->sigma3B, md->nChargePerturbed || md->nTypePerturbed, ir->cutoff_scheme != ecutsVERLET, excl, x, bSB ? boxs : box, mu_tot, ir->ewald_geometry, ir->epsilon_surface, fr->f_novirsum, *vir_q, *vir_lj, Vcorrt_q, Vcorrt_lj, lambda[efptCOUL], lambda[efptVDW], dvdlt_q, dvdlt_lj); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; } if (nthreads > 1) { reduce_thread_energies(fr->vir_el_recip, fr->vir_lj_recip, &Vcorr_q, &Vcorr_lj, &dvdl_long_range_correction_q, &dvdl_long_range_correction_lj, nthreads, fr->ewc_t); } wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION); }
void sas_plot(int nfile,t_filenm fnm[],real solsize,int ndots, real qcut,gmx_bool bSave,real minarea,gmx_bool bPBC, real dgs_default,gmx_bool bFindex, const output_env_t oenv) { FILE *fp,*fp2,*fp3=NULL,*vp; const char *flegend[] = { "Hydrophobic", "Hydrophilic", "Total", "D Gsolv" }; const char *vlegend[] = { "Volume (nm\\S3\\N)", "Density (g/l)" }; const char *or_and_oa_legend[] = { "Average (nm\\S2\\N)", "Standard deviation (nm\\S2\\N)" }; const char *vfile; real t; gmx_atomprop_t aps=NULL; gmx_rmpbc_t gpbc=NULL; t_trxstatus *status; int ndefault; int i,j,ii,nfr,natoms,flag,nsurfacedots,res; rvec *xtop,*x; matrix topbox,box; t_topology top; char title[STRLEN]; int ePBC; gmx_bool bTop; t_atoms *atoms; gmx_bool *bOut,*bPhobic; gmx_bool bConnelly; gmx_bool bResAt,bITP,bDGsol; real *radius,*dgs_factor=NULL,*area=NULL,*surfacedots=NULL; real at_area,*atom_area=NULL,*atom_area2=NULL; real *res_a=NULL,*res_area=NULL,*res_area2=NULL; real totarea,totvolume,totmass=0,density,harea,tarea,fluc2; atom_id **index,*findex; int *nx,nphobic,npcheck,retval; char **grpname,*fgrpname; real dgsolv; bITP = opt2bSet("-i",nfile,fnm); bResAt = opt2bSet("-or",nfile,fnm) || opt2bSet("-oa",nfile,fnm) || bITP; bTop = read_tps_conf(ftp2fn(efTPS,nfile,fnm),title,&top,&ePBC, &xtop,NULL,topbox,FALSE); atoms = &(top.atoms); if (!bTop) { fprintf(stderr,"No tpr file, will not compute Delta G of solvation\n"); bDGsol = FALSE; } else { bDGsol = strcmp(*(atoms->atomtype[0]),"?") != 0; if (!bDGsol) { fprintf(stderr,"Warning: your tpr file is too old, will not compute " "Delta G of solvation\n"); } else { printf("In case you use free energy of solvation predictions:\n"); please_cite(stdout,"Eisenberg86a"); } } aps = gmx_atomprop_init(); if ((natoms=read_first_x(oenv,&status,ftp2fn(efTRX,nfile,fnm), &t,&x,box))==0) gmx_fatal(FARGS,"Could not read coordinates from statusfile\n"); if ((ePBC != epbcXYZ) || (TRICLINIC(box))) { fprintf(stderr,"\n\nWARNING: non-rectangular boxes may give erroneous results or crashes.\n" "Analysis based on vacuum simulations (with the possibility of evaporation)\n" "will certainly crash the analysis.\n\n"); } snew(nx,2); snew(index,2); snew(grpname,2); fprintf(stderr,"Select a group for calculation of surface and a group for output:\n"); get_index(atoms,ftp2fn_null(efNDX,nfile,fnm),2,nx,index,grpname); if (bFindex) { fprintf(stderr,"Select a group of hydrophobic atoms:\n"); get_index(atoms,ftp2fn_null(efNDX,nfile,fnm),1,&nphobic,&findex,&fgrpname); } snew(bOut,natoms); for(i=0; i<nx[1]; i++) bOut[index[1][i]] = TRUE; /* Now compute atomic readii including solvent probe size */ snew(radius,natoms); snew(bPhobic,nx[0]); if (bResAt) { snew(atom_area,nx[0]); snew(atom_area2,nx[0]); snew(res_a,atoms->nres); snew(res_area,atoms->nres); snew(res_area2,atoms->nres); } if (bDGsol) snew(dgs_factor,nx[0]); /* Get a Van der Waals radius for each atom */ ndefault = 0; for(i=0; (i<natoms); i++) { if (!gmx_atomprop_query(aps,epropVDW, *(atoms->resinfo[atoms->atom[i].resind].name), *(atoms->atomname[i]),&radius[i])) ndefault++; /* radius[i] = calc_radius(*(top->atoms.atomname[i])); */ radius[i] += solsize; } if (ndefault > 0) fprintf(stderr,"WARNING: could not find a Van der Waals radius for %d atoms\n",ndefault); /* Determine which atom is counted as hydrophobic */ if (bFindex) { npcheck = 0; for(i=0; (i<nx[0]); i++) { ii = index[0][i]; for(j=0; (j<nphobic); j++) { if (findex[j] == ii) { bPhobic[i] = TRUE; if (bOut[ii]) npcheck++; } } } if (npcheck != nphobic) gmx_fatal(FARGS,"Consistency check failed: not all %d atoms in the hydrophobic index\n" "found in the normal index selection (%d atoms)",nphobic,npcheck); } else nphobic = 0; for(i=0; (i<nx[0]); i++) { ii = index[0][i]; if (!bFindex) { bPhobic[i] = fabs(atoms->atom[ii].q) <= qcut; if (bPhobic[i] && bOut[ii]) nphobic++; } if (bDGsol) if (!gmx_atomprop_query(aps,epropDGsol, *(atoms->resinfo[atoms->atom[ii].resind].name), *(atoms->atomtype[ii]),&(dgs_factor[i]))) dgs_factor[i] = dgs_default; if (debug) fprintf(debug,"Atom %5d %5s-%5s: q= %6.3f, r= %6.3f, dgsol= %6.3f, hydrophobic= %s\n", ii+1,*(atoms->resinfo[atoms->atom[ii].resind].name), *(atoms->atomname[ii]), atoms->atom[ii].q,radius[ii]-solsize,dgs_factor[i], BOOL(bPhobic[i])); } fprintf(stderr,"%d out of %d atoms were classified as hydrophobic\n", nphobic,nx[1]); fp=xvgropen(opt2fn("-o",nfile,fnm),"Solvent Accessible Surface","Time (ps)", "Area (nm\\S2\\N)",oenv); xvgr_legend(fp,asize(flegend) - (bDGsol ? 0 : 1),flegend,oenv); vfile = opt2fn_null("-tv",nfile,fnm); if (vfile) { if (!bTop) { gmx_fatal(FARGS,"Need a tpr file for option -tv"); } vp=xvgropen(vfile,"Volume and Density","Time (ps)","",oenv); xvgr_legend(vp,asize(vlegend),vlegend,oenv); totmass = 0; ndefault = 0; for(i=0; (i<nx[0]); i++) { real mm; ii = index[0][i]; /* if (!query_atomprop(atomprop,epropMass, *(top->atoms.resname[top->atoms.atom[ii].resnr]), *(top->atoms.atomname[ii]),&mm)) ndefault++; totmass += mm; */ totmass += atoms->atom[ii].m; } if (ndefault) fprintf(stderr,"WARNING: Using %d default masses for density calculation, which most likely are inaccurate\n",ndefault); } else vp = NULL; gmx_atomprop_destroy(aps); if (bPBC) gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box); nfr=0; do { if (bPBC) gmx_rmpbc(gpbc,natoms,box,x); bConnelly = (nfr==0 && opt2bSet("-q",nfile,fnm)); if (bConnelly) { if (!bTop) gmx_fatal(FARGS,"Need a tpr file for Connelly plot"); flag = FLAG_ATOM_AREA | FLAG_DOTS; } else { flag = FLAG_ATOM_AREA; } if (vp) { flag = flag | FLAG_VOLUME; } if (debug) write_sto_conf("check.pdb","pbc check",atoms,x,NULL,ePBC,box); retval = nsc_dclm_pbc(x,radius,nx[0],ndots,flag,&totarea, &area,&totvolume,&surfacedots,&nsurfacedots, index[0],ePBC,bPBC ? box : NULL); if (retval) gmx_fatal(FARGS,"Something wrong in nsc_dclm_pbc"); if (bConnelly) connelly_plot(ftp2fn(efPDB,nfile,fnm), nsurfacedots,surfacedots,x,atoms, &(top.symtab),ePBC,box,bSave); harea = 0; tarea = 0; dgsolv = 0; if (bResAt) for(i=0; i<atoms->nres; i++) res_a[i] = 0; for(i=0; (i<nx[0]); i++) { ii = index[0][i]; if (bOut[ii]) { at_area = area[i]; if (bResAt) { atom_area[i] += at_area; atom_area2[i] += sqr(at_area); res_a[atoms->atom[ii].resind] += at_area; } tarea += at_area; if (bDGsol) dgsolv += at_area*dgs_factor[i]; if (bPhobic[i]) harea += at_area; } } if (bResAt) for(i=0; i<atoms->nres; i++) { res_area[i] += res_a[i]; res_area2[i] += sqr(res_a[i]); } fprintf(fp,"%10g %10g %10g %10g",t,harea,tarea-harea,tarea); if (bDGsol) fprintf(fp," %10g\n",dgsolv); else fprintf(fp,"\n"); /* Print volume */ if (vp) { density = totmass*AMU/(totvolume*NANO*NANO*NANO); fprintf(vp,"%12.5e %12.5e %12.5e\n",t,totvolume,density); } if (area) { sfree(area); area = NULL; } if (surfacedots) { sfree(surfacedots); surfacedots = NULL; } nfr++; } while (read_next_x(oenv,status,&t,natoms,x,box)); if (bPBC) gmx_rmpbc_done(gpbc); fprintf(stderr,"\n"); close_trj(status); ffclose(fp); if (vp) ffclose(vp); /* if necessary, print areas per atom to file too: */ if (bResAt) { for(i=0; i<atoms->nres; i++) { res_area[i] /= nfr; res_area2[i] /= nfr; } for(i=0; i<nx[0]; i++) { atom_area[i] /= nfr; atom_area2[i] /= nfr; } fprintf(stderr,"Printing out areas per atom\n"); fp = xvgropen(opt2fn("-or",nfile,fnm),"Area per residue over the trajectory","Residue", "Area (nm\\S2\\N)",oenv); xvgr_legend(fp, asize(or_and_oa_legend),or_and_oa_legend,oenv); fp2 = xvgropen(opt2fn("-oa",nfile,fnm),"Area per atom over the trajectory","Atom #", "Area (nm\\S2\\N)",oenv); xvgr_legend(fp2, asize(or_and_oa_legend),or_and_oa_legend,oenv); if (bITP) { fp3 = ftp2FILE(efITP,nfile,fnm,"w"); fprintf(fp3,"[ position_restraints ]\n" "#define FCX 1000\n" "#define FCY 1000\n" "#define FCZ 1000\n" "; Atom Type fx fy fz\n"); } for(i=0; i<nx[0]; i++) { ii = index[0][i]; res = atoms->atom[ii].resind; if (i==nx[0]-1 || res!=atoms->atom[index[0][i+1]].resind) { fluc2 = res_area2[res]-sqr(res_area[res]); if (fluc2 < 0) fluc2 = 0; fprintf(fp,"%10d %10g %10g\n", atoms->resinfo[res].nr,res_area[res],sqrt(fluc2)); } fluc2 = atom_area2[i]-sqr(atom_area[i]); if (fluc2 < 0) fluc2 = 0; fprintf(fp2,"%d %g %g\n",index[0][i]+1,atom_area[i],sqrt(fluc2)); if (bITP && (atom_area[i] > minarea)) fprintf(fp3,"%5d 1 FCX FCX FCZ\n",ii+1); } if (bITP) ffclose(fp3); ffclose(fp); } /* Be a good citizen, keep our memory free! */ sfree(x); sfree(nx); for(i=0;i<2;i++) { sfree(index[i]); sfree(grpname[i]); } sfree(bOut); sfree(radius); sfree(bPhobic); if(bResAt) { sfree(atom_area); sfree(atom_area2); sfree(res_a); sfree(res_area); sfree(res_area2); } if(bDGsol) { sfree(dgs_factor); } }
int gmx_editconf(int argc, char *argv[]) { const char *desc[] = { "editconf converts generic structure format to [TT].gro[tt], [TT].g96[tt]", "or [TT].pdb[tt].", "[PAR]", "The box can be modified with options [TT]-box[tt], [TT]-d[tt] and", "[TT]-angles[tt]. Both [TT]-box[tt] and [TT]-d[tt]", "will center the system in the box, unless [TT]-noc[tt] is used.", "[PAR]", "Option [TT]-bt[tt] determines the box type: [TT]triclinic[tt] is a", "triclinic box, [TT]cubic[tt] is a rectangular box with all sides equal", "[TT]dodecahedron[tt] represents a rhombic dodecahedron and", "[TT]octahedron[tt] is a truncated octahedron.", "The last two are special cases of a triclinic box.", "The length of the three box vectors of the truncated octahedron is the", "shortest distance between two opposite hexagons.", "The volume of a dodecahedron is 0.71 and that of a truncated octahedron", "is 0.77 of that of a cubic box with the same periodic image distance.", "[PAR]", "Option [TT]-box[tt] requires only", "one value for a cubic box, dodecahedron and a truncated octahedron.", "[PAR]", "With [TT]-d[tt] and a [TT]triclinic[tt] box the size of the system in the x, y", "and z directions is used. With [TT]-d[tt] and [TT]cubic[tt],", "[TT]dodecahedron[tt] or [TT]octahedron[tt] boxes, the dimensions are set", "to the diameter of the system (largest distance between atoms) plus twice", "the specified distance.", "[PAR]", "Option [TT]-angles[tt] is only meaningful with option [TT]-box[tt] and", "a triclinic box and can not be used with option [TT]-d[tt].", "[PAR]", "When [TT]-n[tt] or [TT]-ndef[tt] is set, a group", "can be selected for calculating the size and the geometric center,", "otherwise the whole system is used.", "[PAR]", "[TT]-rotate[tt] rotates the coordinates and velocities.", "[PAR]", "[TT]-princ[tt] aligns the principal axes of the system along the", "coordinate axes, this may allow you to decrease the box volume,", "but beware that molecules can rotate significantly in a nanosecond.", "[PAR]", "Scaling is applied before any of the other operations are", "performed. Boxes and coordinates can be scaled to give a certain density (option", "[TT]-density[tt]). Note that this may be inaccurate in case a gro", "file is given as input. A special feature of the scaling option, when the", "factor -1 is given in one dimension, one obtains a mirror image,", "mirrored in one of the plains, when one uses -1 in three dimensions", "a point-mirror image is obtained.[PAR]", "Groups are selected after all operations have been applied.[PAR]", "Periodicity can be removed in a crude manner.", "It is important that the box sizes at the bottom of your input file", "are correct when the periodicity is to be removed.", "[PAR]", "When writing [TT].pdb[tt] files, B-factors can be", "added with the [TT]-bf[tt] option. B-factors are read", "from a file with with following format: first line states number of", "entries in the file, next lines state an index", "followed by a B-factor. The B-factors will be attached per residue", "unless an index is larger than the number of residues or unless the", "[TT]-atom[tt] option is set. Obviously, any type of numeric data can", "be added instead of B-factors. [TT]-legend[tt] will produce", "a row of CA atoms with B-factors ranging from the minimum to the", "maximum value found, effectively making a legend for viewing.", "[PAR]", "With the option -mead a special pdb (pqr) file for the MEAD electrostatics", "program (Poisson-Boltzmann solver) can be made. A further prerequisite", "is that the input file is a run input file.", "The B-factor field is then filled with the Van der Waals radius", "of the atoms while the occupancy field will hold the charge.", "[PAR]", "The option -grasp is similar, but it puts the charges in the B-factor", "and the radius in the occupancy.", "[PAR]", "Option [TT]-align[tt] allows alignment", "of the principal axis of a specified group against the given vector, ", "with an optional center of rotation specified by [TT]-aligncenter[tt].", "[PAR]", "Finally with option [TT]-label[tt] editconf can add a chain identifier", "to a pdb file, which can be useful for analysis with e.g. rasmol.", "[PAR]", "To convert a truncated octrahedron file produced by a package which uses", "a cubic box with the corners cut off (such as Gromos) use:[BR]", "[TT]editconf -f <in> -rotate 0 45 35.264 -bt o -box <veclen> -o <out>[tt][BR]", "where [TT]veclen[tt] is the size of the cubic box times sqrt(3)/2." }; const char *bugs[] = { "For complex molecules, the periodicity removal routine may break down, ", "in that case you can use trjconv." }; static real dist = 0.0, rbox = 0.0, to_diam = 0.0; static gmx_bool bNDEF = FALSE, bRMPBC = FALSE, bCenter = FALSE, bReadVDW = FALSE, bCONECT = FALSE; static gmx_bool peratom = FALSE, bLegend = FALSE, bOrient = FALSE, bMead = FALSE, bGrasp = FALSE, bSig56 = FALSE; static rvec scale = { 1, 1, 1 }, newbox = { 0, 0, 0 }, newang = { 90, 90, 90 }; static real rho = 1000.0, rvdw = 0.12; static rvec center = { 0, 0, 0 }, translation = { 0, 0, 0 }, rotangles = { 0, 0, 0 }, aligncenter = { 0, 0, 0 }, targetvec = { 0, 0, 0 }; static const char *btype[] = { NULL, "triclinic", "cubic", "dodecahedron", "octahedron", NULL }, *label = "A"; static rvec visbox = { 0, 0, 0 }; t_pargs pa[] = { { "-ndef", FALSE, etBOOL, { &bNDEF }, "Choose output from default index groups" }, { "-visbox", FALSE, etRVEC, { visbox }, "HIDDENVisualize a grid of boxes, -1 visualizes the 14 box images" }, { "-bt", FALSE, etENUM, { btype }, "Box type for -box and -d" }, { "-box", FALSE, etRVEC, { newbox }, "Box vector lengths (a,b,c)" }, { "-angles", FALSE, etRVEC, { newang }, "Angles between the box vectors (bc,ac,ab)" }, { "-d", FALSE, etREAL, { &dist }, "Distance between the solute and the box" }, { "-c", FALSE, etBOOL, { &bCenter }, "Center molecule in box (implied by -box and -d)" }, { "-center", FALSE, etRVEC, { center }, "Coordinates of geometrical center" }, { "-aligncenter", FALSE, etRVEC, { aligncenter }, "Center of rotation for alignment" }, { "-align", FALSE, etRVEC, { targetvec }, "Align to target vector" }, { "-translate", FALSE, etRVEC, { translation }, "Translation" }, { "-rotate", FALSE, etRVEC, { rotangles }, "Rotation around the X, Y and Z axes in degrees" }, { "-princ", FALSE, etBOOL, { &bOrient }, "Orient molecule(s) along their principal axes" }, { "-scale", FALSE, etRVEC, { scale }, "Scaling factor" }, { "-density", FALSE, etREAL, { &rho }, "Density (g/l) of the output box achieved by scaling" }, { "-pbc", FALSE, etBOOL, { &bRMPBC }, "Remove the periodicity (make molecule whole again)" }, { "-grasp", FALSE, etBOOL, { &bGrasp }, "Store the charge of the atom in the B-factor field and the radius of the atom in the occupancy field" }, { "-rvdw", FALSE, etREAL, { &rvdw }, "Default Van der Waals radius (in nm) if one can not be found in the database or if no parameters are present in the topology file" }, { "-sig56", FALSE, etREAL, { &bSig56 }, "Use rmin/2 (minimum in the Van der Waals potential) rather than sigma/2 " }, { "-vdwread", FALSE, etBOOL, { &bReadVDW }, "Read the Van der Waals radii from the file vdwradii.dat rather than computing the radii based on the force field" }, { "-atom", FALSE, etBOOL, { &peratom }, "Force B-factor attachment per atom" }, { "-legend", FALSE, etBOOL, { &bLegend }, "Make B-factor legend" }, { "-label", FALSE, etSTR, { &label }, "Add chain label for all residues" }, { "-conect", FALSE, etBOOL, { &bCONECT }, "Add CONECT records to a pdb file when written. Can only be done when a topology is present" } }; #define NPA asize(pa) FILE *out; const char *infile, *outfile; char title[STRLEN]; int outftp, inftp, natom, i, j, n_bfac, itype, ntype; double *bfac = NULL, c6, c12; int *bfac_nr = NULL; t_topology *top = NULL; t_atoms atoms; char *grpname, *sgrpname, *agrpname; int isize, ssize, tsize, asize; atom_id *index, *sindex, *tindex, *aindex; rvec *x, *v, gc, min, max, size; int ePBC; matrix box,rotmatrix,trans; rvec princd,tmpvec; gmx_bool bIndex, bSetSize, bSetAng, bCubic, bDist, bSetCenter, bAlign; gmx_bool bHaveV, bScale, bRho, bTranslate, bRotate, bCalcGeom, bCalcDiam; real xs, ys, zs, xcent, ycent, zcent, diam = 0, mass = 0, d, vdw; gmx_atomprop_t aps; gmx_conect conect; output_env_t oenv; t_filenm fnm[] = { { efSTX, "-f", NULL, ffREAD }, { efNDX, "-n", NULL, ffOPTRD }, { efSTO, NULL, NULL, ffOPTWR }, { efPQR, "-mead", "mead", ffOPTWR }, { efDAT, "-bf", "bfact", ffOPTRD } }; #define NFILE asize(fnm) CopyRight(stderr, argv[0]); parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, NPA, pa, asize(desc), desc, asize(bugs), bugs, &oenv); bIndex = opt2bSet("-n", NFILE, fnm) || bNDEF; bMead = opt2bSet("-mead", NFILE, fnm); bSetSize = opt2parg_bSet("-box", NPA, pa); bSetAng = opt2parg_bSet("-angles", NPA, pa); bSetCenter = opt2parg_bSet("-center", NPA, pa); bDist = opt2parg_bSet("-d", NPA, pa); bAlign = opt2parg_bSet("-align", NPA, pa); /* Only automatically turn on centering without -noc */ if ((bDist || bSetSize || bSetCenter) && !opt2parg_bSet("-c", NPA, pa)) { bCenter = TRUE; } bScale = opt2parg_bSet("-scale", NPA, pa); bRho = opt2parg_bSet("-density", NPA, pa); bTranslate = opt2parg_bSet("-translate", NPA, pa); bRotate = opt2parg_bSet("-rotate", NPA, pa); if (bScale && bRho) fprintf(stderr, "WARNING: setting -density overrides -scale\n"); bScale = bScale || bRho; bCalcGeom = bCenter || bRotate || bOrient || bScale; bCalcDiam = btype[0][0] == 'c' || btype[0][0] == 'd' || btype[0][0] == 'o'; infile = ftp2fn(efSTX, NFILE, fnm); if (bMead) outfile = ftp2fn(efPQR, NFILE, fnm); else outfile = ftp2fn(efSTO, NFILE, fnm); outftp = fn2ftp(outfile); inftp = fn2ftp(infile); aps = gmx_atomprop_init(); if (bMead && bGrasp) { printf("Incompatible options -mead and -grasp. Turning off -grasp\n"); bGrasp = FALSE; } if (bGrasp && (outftp != efPDB)) gmx_fatal(FARGS, "Output file should be a .pdb file" " when using the -grasp option\n"); if ((bMead || bGrasp) && !((fn2ftp(infile) == efTPR) || (fn2ftp(infile) == efTPA) || (fn2ftp(infile) == efTPB))) gmx_fatal(FARGS,"Input file should be a .tp[abr] file" " when using the -mead option\n"); get_stx_coordnum(infile,&natom); init_t_atoms(&atoms,natom,TRUE); snew(x,natom); snew(v,natom); read_stx_conf(infile,title,&atoms,x,v,&ePBC,box); if (fn2ftp(infile) == efPDB) { get_pdb_atomnumber(&atoms,aps); } printf("Read %d atoms\n",atoms.nr); /* Get the element numbers if available in a pdb file */ if (fn2ftp(infile) == efPDB) get_pdb_atomnumber(&atoms,aps); if (ePBC != epbcNONE) { real vol = det(box); printf("Volume: %g nm^3, corresponds to roughly %d electrons\n", vol,100*((int)(vol*4.5))); } if (bMead || bGrasp || bCONECT) top = read_top(infile,NULL); if (bMead || bGrasp) { if (atoms.nr != top->atoms.nr) gmx_fatal(FARGS,"Atom numbers don't match (%d vs. %d)",atoms.nr,top->atoms.nr); snew(atoms.pdbinfo,top->atoms.nr); ntype = top->idef.atnr; for(i=0; (i<atoms.nr); i++) { /* Determine the Van der Waals radius from the force field */ if (bReadVDW) { if (!gmx_atomprop_query(aps,epropVDW, *top->atoms.resinfo[top->atoms.atom[i].resind].name, *top->atoms.atomname[i],&vdw)) vdw = rvdw; } else { itype = top->atoms.atom[i].type; c12 = top->idef.iparams[itype*ntype+itype].lj.c12; c6 = top->idef.iparams[itype*ntype+itype].lj.c6; if ((c6 != 0) && (c12 != 0)) { real sig6; if (bSig56) sig6 = 2*c12/c6; else sig6 = c12/c6; vdw = 0.5*pow(sig6,1.0/6.0); } else vdw = rvdw; } /* Factor of 10 for nm -> Angstroms */ vdw *= 10; if (bMead) { atoms.pdbinfo[i].occup = top->atoms.atom[i].q; atoms.pdbinfo[i].bfac = vdw; } else { atoms.pdbinfo[i].occup = vdw; atoms.pdbinfo[i].bfac = top->atoms.atom[i].q; } } } bHaveV=FALSE; for (i=0; (i<natom) && !bHaveV; i++) for (j=0; (j<DIM) && !bHaveV; j++) bHaveV=bHaveV || (v[i][j]!=0); printf("%selocities found\n",bHaveV?"V":"No v"); if (visbox[0] > 0) { if (bIndex) gmx_fatal(FARGS,"Sorry, can not visualize box with index groups"); if (outftp != efPDB) gmx_fatal(FARGS,"Sorry, can only visualize box with a pdb file"); } else if (visbox[0] == -1) visualize_images("images.pdb",ePBC,box); /* remove pbc */ if (bRMPBC) rm_gropbc(&atoms,x,box); if (bCalcGeom) { if (bIndex) { fprintf(stderr,"\nSelect a group for determining the system size:\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm), 1,&ssize,&sindex,&sgrpname); } else { ssize = atoms.nr; sindex = NULL; } diam=calc_geom(ssize,sindex,x,gc,min,max,bCalcDiam); rvec_sub(max, min, size); printf(" system size :%7.3f%7.3f%7.3f (nm)\n", size[XX], size[YY], size[ZZ]); if (bCalcDiam) printf(" diameter :%7.3f (nm)\n",diam); printf(" center :%7.3f%7.3f%7.3f (nm)\n", gc[XX], gc[YY], gc[ZZ]); printf(" box vectors :%7.3f%7.3f%7.3f (nm)\n", norm(box[XX]), norm(box[YY]), norm(box[ZZ])); printf(" box angles :%7.2f%7.2f%7.2f (degrees)\n", norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[YY],box[ZZ])), norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[ZZ])), norm2(box[YY])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[YY]))); printf(" box volume :%7.2f (nm^3)\n",det(box)); } if (bRho || bOrient || bAlign) mass = calc_mass(&atoms,!fn2bTPX(infile),aps); if (bOrient) { atom_id *index; char *grpnames; /* Get a group for principal component analysis */ fprintf(stderr,"\nSelect group for the determining the orientation\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpnames); /* Orient the principal axes along the coordinate axes */ orient_princ(&atoms,isize,index,natom,x,bHaveV ? v : NULL, NULL); sfree(index); sfree(grpnames); } if ( bScale ) { /* scale coordinates and box */ if (bRho) { /* Compute scaling constant */ real vol,dens; vol = det(box); dens = (mass*AMU)/(vol*NANO*NANO*NANO); fprintf(stderr,"Volume of input %g (nm^3)\n",vol); fprintf(stderr,"Mass of input %g (a.m.u.)\n",mass); fprintf(stderr,"Density of input %g (g/l)\n",dens); if (vol==0 || mass==0) gmx_fatal(FARGS,"Cannot scale density with " "zero mass (%g) or volume (%g)\n",mass,vol); scale[XX] = scale[YY] = scale[ZZ] = pow(dens/rho,1.0/3.0); fprintf(stderr,"Scaling all box vectors by %g\n",scale[XX]); } scale_conf(atoms.nr,x,box,scale); } if (bAlign) { if (bIndex) { fprintf(stderr,"\nSelect a group that you want to align:\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm), 1,&asize,&aindex,&agrpname); } else { asize = atoms.nr; snew(aindex,asize); for (i=0;i<asize;i++) aindex[i]=i; } printf("Aligning %d atoms (out of %d) to %g %g %g, center of rotation %g %g %g\n",asize,natom, targetvec[XX],targetvec[YY],targetvec[ZZ], aligncenter[XX],aligncenter[YY],aligncenter[ZZ]); /*subtract out pivot point*/ for(i=0; i<asize; i++) rvec_dec(x[aindex[i]],aligncenter); /*now determine transform and rotate*/ /*will this work?*/ principal_comp(asize,aindex,atoms.atom,x, trans,princd); unitv(targetvec,targetvec); printf("Using %g %g %g as principal axis\n", trans[0][2],trans[1][2],trans[2][2]); tmpvec[XX]=trans[0][2]; tmpvec[YY]=trans[1][2]; tmpvec[ZZ]=trans[2][2]; calc_rotmatrix(tmpvec, targetvec, rotmatrix); /* rotmatrix finished */ for (i=0;i<asize;++i) { mvmul(rotmatrix,x[aindex[i]],tmpvec); copy_rvec(tmpvec,x[aindex[i]]); } /*add pivot point back*/ for(i=0; i<asize; i++) rvec_inc(x[aindex[i]],aligncenter); if (!bIndex) sfree(aindex); } if (bTranslate) { if (bIndex) { fprintf(stderr,"\nSelect a group that you want to translate:\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm), 1,&ssize,&sindex,&sgrpname); } else { ssize = atoms.nr; sindex = NULL; } printf("Translating %d atoms (out of %d) by %g %g %g nm\n",ssize,natom, translation[XX],translation[YY],translation[ZZ]); if (sindex) { for(i=0; i<ssize; i++) rvec_inc(x[sindex[i]],translation); } else { for(i=0; i<natom; i++) rvec_inc(x[i],translation); } } if (bRotate) { /* Rotate */ printf("Rotating %g, %g, %g degrees around the X, Y and Z axis respectively\n",rotangles[XX],rotangles[YY],rotangles[ZZ]); for(i=0; i<DIM; i++) rotangles[i] *= DEG2RAD; rotate_conf(natom,x,v,rotangles[XX],rotangles[YY],rotangles[ZZ]); } if (bCalcGeom) { /* recalc geometrical center and max and min coordinates and size */ calc_geom(ssize,sindex,x,gc,min,max,FALSE); rvec_sub(max, min, size); if (bScale || bOrient || bRotate) printf("new system size : %6.3f %6.3f %6.3f\n", size[XX],size[YY],size[ZZ]); } if (bSetSize || bDist || (btype[0][0]=='t' && bSetAng)) { ePBC = epbcXYZ; if (!(bSetSize || bDist)) for (i=0; i<DIM; i++) newbox[i] = norm(box[i]); clear_mat(box); /* calculate new boxsize */ switch(btype[0][0]){ case 't': if (bDist) for(i=0; i<DIM; i++) newbox[i] = size[i]+2*dist; if (!bSetAng) { box[XX][XX] = newbox[XX]; box[YY][YY] = newbox[YY]; box[ZZ][ZZ] = newbox[ZZ]; } else { matrix_convert(box,newbox,newang); } break; case 'c': case 'd': case 'o': if (bSetSize) d = newbox[0]; else d = diam+2*dist; if (btype[0][0] == 'c') for(i=0; i<DIM; i++) box[i][i] = d; else if (btype[0][0] == 'd') { box[XX][XX] = d; box[YY][YY] = d; box[ZZ][XX] = d/2; box[ZZ][YY] = d/2; box[ZZ][ZZ] = d*sqrt(2)/2; } else { box[XX][XX] = d; box[YY][XX] = d/3; box[YY][YY] = d*sqrt(2)*2/3; box[ZZ][XX] = -d/3; box[ZZ][YY] = d*sqrt(2)/3; box[ZZ][ZZ] = d*sqrt(6)/3; } break; } } /* calculate new coords for geometrical center */ if (!bSetCenter) calc_box_center(ecenterDEF,box,center); /* center molecule on 'center' */ if (bCenter) center_conf(natom,x,center,gc); /* print some */ if (bCalcGeom) { calc_geom(ssize,sindex,x, gc, min, max, FALSE); printf("new center :%7.3f%7.3f%7.3f (nm)\n",gc[XX],gc[YY],gc[ZZ]); } if (bOrient || bScale || bDist || bSetSize) { printf("new box vectors :%7.3f%7.3f%7.3f (nm)\n", norm(box[XX]), norm(box[YY]), norm(box[ZZ])); printf("new box angles :%7.2f%7.2f%7.2f (degrees)\n", norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[YY],box[ZZ])), norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[ZZ])), norm2(box[YY])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[YY]))); printf("new box volume :%7.2f (nm^3)\n",det(box)); } if (check_box(epbcXYZ,box)) printf("\nWARNING: %s\n",check_box(epbcXYZ,box)); if (bDist && btype[0][0]=='t') { if(TRICLINIC(box)) { printf("\nWARNING: Your box is triclinic with non-orthogonal axes. In this case, the\n" "distance from the solute to a box surface along the corresponding normal\n" "vector might be somewhat smaller than your specified value %f.\n" "You can check the actual value with g_mindist -pi\n",dist); } else { printf("\nWARNING: No boxtype specified - distance condition applied in each dimension.\n" "If the molecule rotates the actual distance will be smaller. You might want\n" "to use a cubic box instead, or why not try a dodecahedron today?\n"); } } if (bCONECT && (outftp == efPDB) && (inftp == efTPR)) conect = gmx_conect_generate(top); else conect = NULL; if (bIndex) { fprintf(stderr,"\nSelect a group for output:\n"); get_index(&atoms,opt2fn_null("-n",NFILE,fnm), 1,&isize,&index,&grpname); if (opt2parg_bSet("-label",NPA,pa)) { for(i=0; (i<atoms.nr); i++) atoms.resinfo[atoms.atom[i].resind].chainid=label[0]; } if (opt2bSet("-bf",NFILE,fnm) || bLegend) { gmx_fatal(FARGS,"Sorry, cannot do bfactors with an index group."); } if (outftp == efPDB) { out=ffopen(outfile,"w"); write_pdbfile_indexed(out,title,&atoms,x,ePBC,box,' ',1,isize,index,conect,TRUE); ffclose(out); } else { write_sto_conf_indexed(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box,isize,index); } } else { if ((outftp == efPDB) || (outftp == efPQR)) { out=ffopen(outfile,"w"); if (bMead) { set_pdb_wide_format(TRUE); fprintf(out,"REMARK " "The B-factors in this file hold atomic radii\n"); fprintf(out,"REMARK " "The occupancy in this file hold atomic charges\n"); } else if (bGrasp) { fprintf(out,"GRASP PDB FILE\nFORMAT NUMBER=1\n"); fprintf(out,"REMARK " "The B-factors in this file hold atomic charges\n"); fprintf(out,"REMARK " "The occupancy in this file hold atomic radii\n"); } else if (opt2bSet("-bf",NFILE,fnm)) { read_bfac(opt2fn("-bf",NFILE,fnm),&n_bfac,&bfac,&bfac_nr); set_pdb_conf_bfac(atoms.nr,atoms.nres,&atoms, n_bfac,bfac,bfac_nr,peratom); } if (opt2parg_bSet("-label",NPA,pa)) { for(i=0; (i<atoms.nr); i++) atoms.resinfo[atoms.atom[i].resind].chainid=label[0]; } write_pdbfile(out,title,&atoms,x,ePBC,box,' ',-1,conect,TRUE); if (bLegend) pdb_legend(out,atoms.nr,atoms.nres,&atoms,x); if (visbox[0] > 0) visualize_box(out,bLegend ? atoms.nr+12 : atoms.nr, bLegend? atoms.nres=12 : atoms.nres,box,visbox); ffclose(out); } else write_sto_conf(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box); } gmx_atomprop_destroy(aps); do_view(oenv,outfile,NULL); thanx(stderr); return 0; }
void do_force_lowlevel(FILE *fplog, gmx_large_int_t step, t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, t_grpopts *opts, rvec x[], history_t *hist, rvec f[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_mtop_t *mtop, gmx_localtop_t *top, gmx_genborn_t *born, t_atomtypes *atype, gmx_bool bBornRadii, matrix box, real lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i,status; int donb_flags; gmx_bool bDoEpot,bSepDVDL,bSB; int pme_flags; matrix boxs; rvec box_size; real dvdlambda,Vsr,Vlr,Vcorr=0,vdip,vcharge; t_pbc pbc; real dvdgb; char buf[22]; gmx_enerdata_t ed_lam; double lam_i; real dvdl_dum; #ifdef GMX_MPI double t0=0.0,t1,t2,t3; /* time measurement for coarse load balancing */ #endif #define PRINT_SEPDVDL(s,v,dvdl) if (bSepDVDL) fprintf(fplog,sepdvdlformat,s,v,dvdl); GMX_MPE_LOG(ev_force_start); set_pbc(&pbc,fr->ePBC,box); /* Reset box */ for(i=0; (i<DIM); i++) { box_size[i]=box[i][i]; } bSepDVDL=(fr->bSepDVDL && do_per_step(step,ir->nstlog)); debug_gmx(); /* do QMMM first if requested */ if(fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr,x,f,fr,md); } if (bSepDVDL) { fprintf(fplog,"Step %s: non-bonded V and dVdl for node %d:\n", gmx_step_str(step,buf),cr->nodeid); } /* Call the short range functions all in one go. */ GMX_MPE_LOG(ev_do_fnbf_start); dvdlambda = 0; #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0=MPI_Wtime(); } #endif if (ir->nwall) { dvdlambda = do_walls(ir,fr,box,md,x,f,lambda, enerd->grpp.ener[egLJSR],nrnb); PRINT_SEPDVDL("Walls",0.0,dvdlambda); enerd->dvdl_lin += dvdlambda; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { /* wallcycle_start(wcycle,ewcGB); */ for(i=0; i<born->nr; i++) { fr->dvda[i]=0; } if(bBornRadii) { calc_gb_rad(cr,fr,ir,top,atype,x,&(fr->gblist),born,md,nrnb); } /* wallcycle_stop(wcycle, ewcGB); */ } where(); donb_flags = 0; if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_DONB_FORCES; } do_nonbonded(cr,fr,x,f,md,excl, fr->bBHAM ? enerd->grpp.ener[egBHAMSR] : enerd->grpp.ener[egLJSR], enerd->grpp.ener[egCOULSR], enerd->grpp.ener[egGB],box_size,nrnb, lambda,&dvdlambda,-1,-1,donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && ir->sc_alpha != 0) { init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam); for(i=0; i<enerd->n_lambda; i++) { lam_i = (i==0 ? lambda : ir->flambda[i-1]); dvdl_dum = 0; reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE); do_nonbonded(cr,fr,x,f,md,excl, fr->bBHAM ? ed_lam.grpp.ener[egBHAMSR] : ed_lam.grpp.ener[egLJSR], ed_lam.grpp.ener[egCOULSR], enerd->grpp.ener[egGB], box_size,nrnb, lam_i,&dvdl_dum,-1,-1, GMX_DONB_FOREIGNLAMBDA); sum_epot(&ir->opts,&ed_lam); enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT]; } destroy_enerdata(&ed_lam); } where(); /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ if (ir->implicit_solvent) { calc_gb_forces(cr,md,born,top,atype,x,f,fr,idef, ir->gb_algorithm,ir->sa_algorithm,nrnb,bBornRadii,&pbc,graph,enerd); } #ifdef GMX_MPI if (TAKETIME) { t1=MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (ir->sc_alpha != 0) { enerd->dvdl_nonlin += dvdlambda; } else { enerd->dvdl_lin += dvdlambda; } Vsr = 0; if (bSepDVDL) { for(i=0; i<enerd->grpp.nener; i++) { Vsr += (fr->bBHAM ? enerd->grpp.ener[egBHAMSR][i] : enerd->grpp.ener[egLJSR][i]) + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i]; } } PRINT_SEPDVDL("VdW and Coulomb SR particle-p.",Vsr,dvdlambda); debug_gmx(); GMX_MPE_LOG(ev_do_fnbf_finish); if (debug) { pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS); } /* Shift the coordinates. Must be done before bonded forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no bonded forces have to be evaluated. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph,box,x); if (TRICLINIC(box)) { inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes); } else { inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes); } } /* Check whether we need to do bondeds or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_BONDED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype))) { /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc,fr->ePBC,cr->dd,TRUE,box); } debug_gmx(); if (flags & GMX_FORCE_BONDED) { GMX_MPE_LOG(ev_calc_bonds_start); calc_bonds(fplog,cr->ms, idef,x,hist,f,fr,&pbc,graph,enerd,nrnb,lambda,md,fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born, fr->bSepDVDL && do_per_step(step,ir->nstlog),step); /* Check if we have to determine energy differences * at foreign lambda's. */ if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && idef->ilsort != ilsortNO_FE) { if (idef->ilsort != ilsortFE_SORTED) { gmx_incons("The bonded interactions are not sorted for free energy"); } init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam); for(i=0; i<enerd->n_lambda; i++) { lam_i = (i==0 ? lambda : ir->flambda[i-1]); dvdl_dum = 0; reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE); calc_bonds_lambda(fplog, idef,x,fr,&pbc,graph,&ed_lam,nrnb,lam_i,md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL); sum_epot(&ir->opts,&ed_lam); enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT]; } destroy_enerdata(&ed_lam); } debug_gmx(); GMX_MPE_LOG(ev_calc_bonds_finish); } where(); *cycles_pme = 0; if (EEL_FULL(fr->eeltype)) { bSB = (ir->nwall == 2); if (bSB) { copy_mat(box,boxs); svmul(ir->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } clear_mat(fr->vir_el_recip); if (fr->bEwald) { if (fr->n_tpi == 0) { dvdlambda = 0; Vcorr = ewald_LRcorrection(fplog,md->start,md->start+md->homenr, cr,fr, md->chargeA, md->nChargePerturbed ? md->chargeB : NULL, excl,x,bSB ? boxs : box,mu_tot, ir->ewald_geometry, ir->epsilon_surface, lambda,&dvdlambda,&vdip,&vcharge); PRINT_SEPDVDL("Ewald excl./charge/dip. corr.",Vcorr,dvdlambda); enerd->dvdl_lin += dvdlambda; } else { if (ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { gmx_fatal(FARGS,"TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid contributions * will be calculated in gmx_pme_calc_energy. */ Vcorr = 0; } } else { Vcorr = shift_LRcorrection(fplog,md->start,md->homenr,cr,fr, md->chargeA,excl,x,TRUE,box, fr->vir_el_recip); } dvdlambda = 0; status = 0; switch (fr->eeltype) { case eelPPPM: status = gmx_pppm_do(fplog,fr->pmedata,FALSE,x,fr->f_novirsum, md->chargeA, box_size,fr->phi,cr,md->start,md->homenr, nrnb,ir->pme_order,&Vlr); break; case eelPME: case eelPMESWITCH: case eelPMEUSER: case eelPMEUSERSWITCH: if (cr->duty & DUTY_PME) { if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED)) { pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE; if (flags & GMX_FORCE_FORCES) { pme_flags |= GMX_PME_CALC_F; } if (flags & GMX_FORCE_VIRIAL) { pme_flags |= GMX_PME_CALC_ENER_VIR; } if (fr->n_tpi > 0) { /* We don't calculate f, but we do want the potential */ pme_flags |= GMX_PME_CALC_POT; } wallcycle_start(wcycle,ewcPMEMESH); status = gmx_pme_do(fr->pmedata, md->start,md->homenr - fr->n_tpi, x,fr->f_novirsum, md->chargeA,md->chargeB, bSB ? boxs : box,cr, DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0, DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb,wcycle, fr->vir_el_recip,fr->ewaldcoeff, &Vlr,lambda,&dvdlambda, pme_flags); *cycles_pme = wallcycle_stop(wcycle,ewcPMEMESH); /* We should try to do as little computation after * this as possible, because parallel PME synchronizes * the nodes, so we want all load imbalance of the rest * of the force calculation to be before the PME call. * DD load balancing is done on the whole time of * the force call (without PME). */ } if (fr->n_tpi > 0) { /* Determine the PME grid energy of the test molecule * with the PME grid potential of the other charges. */ gmx_pme_calc_energy(fr->pmedata,fr->n_tpi, x + md->homenr - fr->n_tpi, md->chargeA + md->homenr - fr->n_tpi, &Vlr); } PRINT_SEPDVDL("PME mesh",Vlr,dvdlambda); } else { /* Energies and virial are obtained later from the PME nodes */ /* but values have to be zeroed out here */ Vlr=0.0; } break; case eelEWALD: Vlr = do_ewald(fplog,FALSE,ir,x,fr->f_novirsum, md->chargeA,md->chargeB, box_size,cr,md->homenr, fr->vir_el_recip,fr->ewaldcoeff, lambda,&dvdlambda,fr->ewald_table); PRINT_SEPDVDL("Ewald long-range",Vlr,dvdlambda); break; default: Vlr = 0; gmx_fatal(FARGS,"No such electrostatics method implemented %s", eel_names[fr->eeltype]); } if (status != 0) { gmx_fatal(FARGS,"Error %d in long range electrostatics routine %s", status,EELTYPE(fr->eeltype)); } enerd->dvdl_lin += dvdlambda; enerd->term[F_COUL_RECIP] = Vlr + Vcorr; if (debug) { fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n", Vlr,Vcorr,enerd->term[F_COUL_RECIP]); pr_rvecs(debug,0,"vir_el_recip after corr",fr->vir_el_recip,DIM); pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS); } } else { if (EEL_RF(fr->eeltype)) { dvdlambda = 0; if (fr->eeltype != eelRF_NEC) { enerd->term[F_RF_EXCL] = RF_excl_correction(fplog,fr,graph,md,excl,x,f, fr->fshift,&pbc,lambda,&dvdlambda); } enerd->dvdl_lin += dvdlambda; PRINT_SEPDVDL("RF exclusion correction", enerd->term[F_RF_EXCL],dvdlambda); } } where(); debug_gmx(); if (debug) { print_nrnb(debug,nrnb); } debug_gmx(); #ifdef GMX_MPI if (TAKETIME) { t2=MPI_Wtime(); MPI_Barrier(cr->mpi_comm_mygroup); t3=MPI_Wtime(); fr->t_wait += t3-t2; if (fr->timesteps == 11) { fprintf(stderr,"* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", cr->nodeid, gmx_step_str(fr->timesteps,buf), 100*fr->t_wait/(fr->t_wait+fr->t_fnbf), (fr->t_fnbf+fr->t_wait)/fr->t_fnbf); } fr->timesteps++; } #endif if (debug) { pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS); } GMX_MPE_LOG(ev_force_finish); }
t_mdebin *init_mdebin(ener_file_t fp_ene, const gmx_mtop_t *mtop, const t_inputrec *ir, FILE *fp_dhdl) { const char *ener_nm[F_NRE]; static const char *vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY", "Vir-YZ", "Vir-ZX", "Vir-ZY", "Vir-ZZ" }; static const char *sv_nm[] = { "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ", "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ", "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ" }; static const char *fv_nm[] = { "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ", "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ", "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ" }; static const char *pres_nm[] = { "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY", "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ" }; static const char *surft_nm[] = { "#Surf*SurfTen" }; static const char *mu_nm[] = { "Mu-X", "Mu-Y", "Mu-Z" }; static const char *vcos_nm[] = { "2CosZ*Vel-X" }; static const char *visc_nm[] = { "1/Viscosity" }; static const char *baro_nm[] = { "Barostat" }; char **grpnms; const gmx_groups_t *groups; char **gnm; char buf[256]; const char *bufi; t_mdebin *md; int i, j, ni, nj, n, k, kk, ncon, nset; gmx_bool bBHAM, b14; snew(md, 1); if (EI_DYNAMICS(ir->eI)) { md->delta_t = ir->delta_t; } else { md->delta_t = 0; } groups = &mtop->groups; bBHAM = (mtop->ffparams.functype[0] == F_BHAM); b14 = (gmx_mtop_ftype_count(mtop, F_LJ14) > 0 || gmx_mtop_ftype_count(mtop, F_LJC14_Q) > 0); ncon = gmx_mtop_ftype_count(mtop, F_CONSTR); nset = gmx_mtop_ftype_count(mtop, F_SETTLE); md->bConstr = (ncon > 0 || nset > 0); md->bConstrVir = FALSE; if (md->bConstr) { if (ncon > 0 && ir->eConstrAlg == econtLINCS) { md->nCrmsd = 1; } md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL); } else { md->nCrmsd = 0; } /* Energy monitoring */ for (i = 0; i < egNR; i++) { md->bEInd[i] = FALSE; } for (i = 0; i < F_NRE; i++) { md->bEner[i] = FALSE; if (i == F_LJ) { md->bEner[i] = !bBHAM; } else if (i == F_BHAM) { md->bEner[i] = bBHAM; } else if (i == F_EQM) { md->bEner[i] = ir->bQMMM; } else if (i == F_RF_EXCL) { md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->cutoff_scheme == ecutsGROUP); } else if (i == F_COUL_RECIP) { md->bEner[i] = EEL_FULL(ir->coulombtype); } else if (i == F_LJ_RECIP) { md->bEner[i] = EVDW_PME(ir->vdwtype); } else if (i == F_LJ14) { md->bEner[i] = b14; } else if (i == F_COUL14) { md->bEner[i] = b14; } else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB) { md->bEner[i] = FALSE; } else if ((i == F_DVDL_COUL && ir->fepvals->separate_dvdl[efptCOUL]) || (i == F_DVDL_VDW && ir->fepvals->separate_dvdl[efptVDW]) || (i == F_DVDL_BONDED && ir->fepvals->separate_dvdl[efptBONDED]) || (i == F_DVDL_RESTRAINT && ir->fepvals->separate_dvdl[efptRESTRAINT]) || (i == F_DKDL && ir->fepvals->separate_dvdl[efptMASS]) || (i == F_DVDL && ir->fepvals->separate_dvdl[efptFEP])) { md->bEner[i] = (ir->efep != efepNO); } else if ((interaction_function[i].flags & IF_VSITE) || (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE)) { md->bEner[i] = FALSE; } else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES) || (i == F_EQM)) { md->bEner[i] = TRUE; } else if ((i == F_GBPOL) && ir->implicit_solvent == eisGBSA) { md->bEner[i] = TRUE; } else if ((i == F_NPSOLVATION) && ir->implicit_solvent == eisGBSA && (ir->sa_algorithm != esaNO)) { md->bEner[i] = TRUE; } else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14)) { md->bEner[i] = FALSE; } else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP)) { md->bEner[i] = EI_DYNAMICS(ir->eI); } else if (i == F_DISPCORR || i == F_PDISPCORR) { md->bEner[i] = (ir->eDispCorr != edispcNO); } else if (i == F_DISRESVIOL) { md->bEner[i] = (gmx_mtop_ftype_count(mtop, F_DISRES) > 0); } else if (i == F_ORIRESDEV) { md->bEner[i] = (gmx_mtop_ftype_count(mtop, F_ORIRES) > 0); } else if (i == F_CONNBONDS) { md->bEner[i] = FALSE; } else if (i == F_COM_PULL) { md->bEner[i] = (ir->bPull && pull_have_potential(ir->pull_work)); } else if (i == F_ECONSERVED) { md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) && (ir->epc == epcNO || ir->epc == epcMTTK)); } else { md->bEner[i] = (gmx_mtop_ftype_count(mtop, i) > 0); } } md->f_nre = 0; for (i = 0; i < F_NRE; i++) { if (md->bEner[i]) { ener_nm[md->f_nre] = interaction_function[i].longname; md->f_nre++; } } md->epc = ir->epc; md->bDiagPres = !TRICLINIC(ir->ref_p); md->ref_p = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM; md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); md->bDynBox = inputrecDynamicBox(ir); md->etc = ir->etc; md->bNHC_trotter = inputrecNvtTrotter(ir); md->bPrintNHChains = ir->bPrintNHChains; md->bMTTK = (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)); md->bMu = inputrecNeedMutot(ir); md->ebin = mk_ebin(); /* Pass NULL for unit to let get_ebin_space determine the units * for interaction_function[i].longname */ md->ie = get_ebin_space(md->ebin, md->f_nre, ener_nm, NULL); if (md->nCrmsd) { /* This should be called directly after the call for md->ie, * such that md->iconrmsd follows directly in the list. */ md->iconrmsd = get_ebin_space(md->ebin, md->nCrmsd, conrmsd_nm, ""); } if (md->bDynBox) { md->ib = get_ebin_space(md->ebin, md->bTricl ? NTRICLBOXS : NBOXS, md->bTricl ? tricl_boxs_nm : boxs_nm, unit_length); md->ivol = get_ebin_space(md->ebin, 1, vol_nm, unit_volume); md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI); if (md->bDiagPres) { md->ipv = get_ebin_space(md->ebin, 1, pv_nm, unit_energy); md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm, unit_energy); } } if (md->bConstrVir) { md->isvir = get_ebin_space(md->ebin, asize(sv_nm), sv_nm, unit_energy); md->ifvir = get_ebin_space(md->ebin, asize(fv_nm), fv_nm, unit_energy); } md->ivir = get_ebin_space(md->ebin, asize(vir_nm), vir_nm, unit_energy); md->ipres = get_ebin_space(md->ebin, asize(pres_nm), pres_nm, unit_pres_bar); md->isurft = get_ebin_space(md->ebin, asize(surft_nm), surft_nm, unit_surft_bar); if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK) { md->ipc = get_ebin_space(md->ebin, md->bTricl ? 6 : 3, boxvel_nm, unit_vel); } if (md->bMu) { md->imu = get_ebin_space(md->ebin, asize(mu_nm), mu_nm, unit_dipole_D); } if (ir->cos_accel != 0) { md->ivcos = get_ebin_space(md->ebin, asize(vcos_nm), vcos_nm, unit_vel); md->ivisc = get_ebin_space(md->ebin, asize(visc_nm), visc_nm, unit_invvisc_SI); } /* Energy monitoring */ for (i = 0; i < egNR; i++) { md->bEInd[i] = FALSE; } md->bEInd[egCOULSR] = TRUE; md->bEInd[egLJSR ] = TRUE; if (bBHAM) { md->bEInd[egLJSR] = FALSE; md->bEInd[egBHAMSR] = TRUE; } if (b14) { md->bEInd[egLJ14] = TRUE; md->bEInd[egCOUL14] = TRUE; } md->nEc = 0; for (i = 0; (i < egNR); i++) { if (md->bEInd[i]) { md->nEc++; } } n = groups->grps[egcENER].nr; md->nEg = n; md->nE = (n*(n+1))/2; snew(md->igrp, md->nE); if (md->nE > 1) { n = 0; snew(gnm, md->nEc); for (k = 0; (k < md->nEc); k++) { snew(gnm[k], STRLEN); } for (i = 0; (i < groups->grps[egcENER].nr); i++) { ni = groups->grps[egcENER].nm_ind[i]; for (j = i; (j < groups->grps[egcENER].nr); j++) { nj = groups->grps[egcENER].nm_ind[j]; for (k = kk = 0; (k < egNR); k++) { if (md->bEInd[k]) { sprintf(gnm[kk], "%s:%s-%s", egrp_nm[k], *(groups->grpname[ni]), *(groups->grpname[nj])); kk++; } } md->igrp[n] = get_ebin_space(md->ebin, md->nEc, (const char **)gnm, unit_energy); n++; } } for (k = 0; (k < md->nEc); k++) { sfree(gnm[k]); } sfree(gnm); if (n != md->nE) { gmx_incons("Number of energy terms wrong"); } } md->nTC = groups->grps[egcTC].nr; md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ if (md->bMTTK) { md->nTCP = 1; /* assume only one possible coupling system for barostat for now */ } else { md->nTCP = 0; } if (md->etc == etcNOSEHOOVER) { if (md->bNHC_trotter) { md->mde_n = 2*md->nNHC*md->nTC; } else { md->mde_n = 2*md->nTC; } if (md->epc == epcMTTK) { md->mdeb_n = 2*md->nNHC*md->nTCP; } } else { md->mde_n = md->nTC; md->mdeb_n = 0; } snew(md->tmp_r, md->mde_n); snew(md->tmp_v, md->mde_n); snew(md->grpnms, md->mde_n); grpnms = md->grpnms; for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; sprintf(buf, "T-%s", *(groups->grpname[ni])); grpnms[i] = gmx_strdup(buf); } md->itemp = get_ebin_space(md->ebin, md->nTC, (const char **)grpnms, unit_temp_K); if (md->etc == etcNOSEHOOVER) { if (md->bPrintNHChains) { if (md->bNHC_trotter) { for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); for (j = 0; (j < md->nNHC); j++) { sprintf(buf, "Xi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)] = gmx_strdup(buf); sprintf(buf, "vXi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)+1] = gmx_strdup(buf); } } md->itc = get_ebin_space(md->ebin, md->mde_n, (const char **)grpnms, unit_invtime); if (md->bMTTK) { for (i = 0; (i < md->nTCP); i++) { bufi = baro_nm[0]; /* All barostat DOF's together for now. */ for (j = 0; (j < md->nNHC); j++) { sprintf(buf, "Xi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)] = gmx_strdup(buf); sprintf(buf, "vXi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)+1] = gmx_strdup(buf); } } md->itcb = get_ebin_space(md->ebin, md->mdeb_n, (const char **)grpnms, unit_invtime); } } else { for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); sprintf(buf, "Xi-%s", bufi); grpnms[2*i] = gmx_strdup(buf); sprintf(buf, "vXi-%s", bufi); grpnms[2*i+1] = gmx_strdup(buf); } md->itc = get_ebin_space(md->ebin, md->mde_n, (const char **)grpnms, unit_invtime); } } } else if (md->etc == etcBERENDSEN || md->etc == etcYES || md->etc == etcVRESCALE) { for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; sprintf(buf, "Lamb-%s", *(groups->grpname[ni])); grpnms[i] = gmx_strdup(buf); } md->itc = get_ebin_space(md->ebin, md->mde_n, (const char **)grpnms, ""); } sfree(grpnms); md->nU = groups->grps[egcACC].nr; if (md->nU > 1) { snew(grpnms, 3*md->nU); for (i = 0; (i < md->nU); i++) { ni = groups->grps[egcACC].nm_ind[i]; sprintf(buf, "Ux-%s", *(groups->grpname[ni])); grpnms[3*i+XX] = gmx_strdup(buf); sprintf(buf, "Uy-%s", *(groups->grpname[ni])); grpnms[3*i+YY] = gmx_strdup(buf); sprintf(buf, "Uz-%s", *(groups->grpname[ni])); grpnms[3*i+ZZ] = gmx_strdup(buf); } md->iu = get_ebin_space(md->ebin, 3*md->nU, (const char **)grpnms, unit_vel); sfree(grpnms); } if (fp_ene) { do_enxnms(fp_ene, &md->ebin->nener, &md->ebin->enm); } md->print_grpnms = NULL; /* check whether we're going to write dh histograms */ md->dhc = NULL; if (ir->fepvals->separate_dhdl_file == esepdhdlfileNO) { /* Currently dh histograms are only written with dynamics */ if (EI_DYNAMICS(ir->eI)) { snew(md->dhc, 1); mde_delta_h_coll_init(md->dhc, ir); } md->fp_dhdl = NULL; snew(md->dE, ir->fepvals->n_lambda); } else { md->fp_dhdl = fp_dhdl; snew(md->dE, ir->fepvals->n_lambda); } if (ir->bSimTemp) { int i; snew(md->temperatures, ir->fepvals->n_lambda); for (i = 0; i < ir->fepvals->n_lambda; i++) { md->temperatures[i] = ir->simtempvals->temperatures[i]; } } return md; }
t_mdebin *init_mdebin(int fp_ene, const gmx_mtop_t *mtop, const t_inputrec *ir) { char *ener_nm[F_NRE]; static char *vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY", "Vir-YZ", "Vir-ZX", "Vir-ZY", "Vir-ZZ" }; static char *sv_nm[] = { "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ", "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ", "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ" }; static char *fv_nm[] = { "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ", "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ", "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ" }; static char *pres_nm[] = { "Pres-XX (bar)","Pres-XY (bar)","Pres-XZ (bar)", "Pres-YX (bar)","Pres-YY (bar)","Pres-YZ (bar)", "Pres-ZX (bar)","Pres-ZY (bar)","Pres-ZZ (bar)" }; static char *surft_nm[] = { "#Surf*SurfTen" }; static char *mu_nm[] = { "Mu-X", "Mu-Y", "Mu-Z" }; static char *vcos_nm[] = { "2CosZ*Vel-X" }; static char *visc_nm[] = { "1/Viscosity (SI)" }; static char **grpnms; const gmx_groups_t *groups; char **gnm; char buf[256]; t_mdebin *md; int i,j,ni,nj,n,k,kk,ncon,nset; bool bBHAM,b14; f_nre = 0; // otherwise, multiple calls to mdrunner_integrate are not possible!NnCrmsd; groups = &mtop->groups; bBHAM = (mtop->ffparams.functype[0] == F_BHAM); b14 = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 || gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0); ncon = gmx_mtop_ftype_count(mtop,F_CONSTR); nset = gmx_mtop_ftype_count(mtop,F_SETTLE); bConstr = (ncon > 0 || nset > 0); bConstrVir = FALSE; if (bConstr) { if (ncon > 0 && ir->eConstrAlg == econtLINCS) { if (ir->eI == eiSD2) nCrmsd = 2; else nCrmsd = 1; } bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL); } else { nCrmsd = 0; } for(i=0; i<F_NRE; i++) { bEner[i] = FALSE; if (i == F_LJ) bEner[i] = !bBHAM; else if (i == F_BHAM) bEner[i] = bBHAM; else if (i == F_EQM) bEner[i] = ir->bQMMM; else if (i == F_COUL_LR) bEner[i] = (ir->rcoulomb > ir->rlist); else if (i == F_LJ_LR) bEner[i] = (!bBHAM && ir->rvdw > ir->rlist); else if (i == F_BHAM_LR) bEner[i] = (bBHAM && ir->rvdw > ir->rlist); else if (i == F_RF_EXCL) bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC); else if (i == F_COUL_RECIP) bEner[i] = EEL_FULL(ir->coulombtype); else if (i == F_LJ14) bEner[i] = b14; else if (i == F_COUL14) bEner[i] = b14; else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB) bEner[i] = FALSE; else if ((i == F_DVDL) || (i == F_DKDL)) bEner[i] = (ir->efep != efepNO); else if (i == F_DGDL_CON) bEner[i] = (ir->efep != efepNO && bConstr); else if ((interaction_function[i].flags & IF_VSITE) || (i == F_CONSTR) || (i == F_SETTLE)) bEner[i] = FALSE; else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES) || (i==F_EQM)) bEner[i] = TRUE; else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP)) bEner[i] = EI_DYNAMICS(ir->eI); else if (i == F_DISPCORR) bEner[i] = (ir->eDispCorr != edispcNO); else if (i == F_DISRESVIOL) bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0); else if (i == F_ORIRESDEV) bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0); else if (i == F_CONNBONDS) bEner[i] = FALSE; else if (i == F_COM_PULL) bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F); else if (i == F_ECONSERVED) bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) && ir->epc == epcNO); else bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0); } for(i=0; i<F_NRE; i++) if (bEner[i]) { ener_nm[f_nre]=interaction_function[i].longname; f_nre++; } epc = ir->epc; bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); bDynBox = DYNAMIC_BOX(*ir); etc = ir->etc; /* Energy monitoring */ snew(md,1); md->ebin = mk_ebin(); md->ie = get_ebin_space(md->ebin,f_nre,ener_nm); if (nCrmsd) { /* This should be called directly after the call for md->ie, * such that md->iconrmsd follows directly in the list. */ md->iconrmsd = get_ebin_space(md->ebin,nCrmsd,conrmsd_nm); } if (bDynBox) md->ib = get_ebin_space(md->ebin, bTricl ? NTRICLBOXS : NBOXS, bTricl ? tricl_boxs_nm : boxs_nm); if (bConstrVir) { md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm); md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm); } md->ivir = get_ebin_space(md->ebin,asize(vir_nm),vir_nm); md->ipres = get_ebin_space(md->ebin,asize(pres_nm),pres_nm); md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm); if (epc == epcPARRINELLORAHMAN) { md->ipc = get_ebin_space(md->ebin,bTricl ? 6 : 3,boxvel_nm); } md->imu = get_ebin_space(md->ebin,asize(mu_nm),mu_nm); if (ir->cos_accel != 0) { md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm); md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm); } if (ir->rcoulomb > ir->rlist) bEInd[egCOULLR] = TRUE; if (!bBHAM) { if (ir->rvdw > ir->rlist) bEInd[egLJLR] = TRUE; } else { bEInd[egLJSR] = FALSE; bEInd[egBHAMSR] = TRUE; if (ir->rvdw > ir->rlist) bEInd[egBHAMLR] = TRUE; } if (b14) { bEInd[egLJ14] = TRUE; bEInd[egCOUL14] = TRUE; } md->nEc=0; for(i=0; (i<egNR); i++) if (bEInd[i]) md->nEc++; n=groups->grps[egcENER].nr; md->nEg=n; md->nE=(n*(n+1))/2; snew(md->igrp,md->nE); if (md->nE > 1) { n=0; snew(gnm,md->nEc); for(k=0; (k<md->nEc); k++) snew(gnm[k],STRLEN); for(i=0; (i<groups->grps[egcENER].nr); i++) { ni=groups->grps[egcENER].nm_ind[i]; for(j=i; (j<groups->grps[egcENER].nr); j++) { nj=groups->grps[egcENER].nm_ind[j]; for(k=kk=0; (k<egNR); k++) { if (bEInd[k]) { sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k], *(groups->grpname[ni]),*(groups->grpname[nj])); kk++; } } md->igrp[n]=get_ebin_space(md->ebin,md->nEc,gnm); n++; } } for(k=0; (k<md->nEc); k++) sfree(gnm[k]); sfree(gnm); if (n != md->nE) gmx_incons("Number of energy terms wrong"); } md->nTC=groups->grps[egcTC].nr; snew(grpnms,md->nTC); for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"T-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itemp=get_ebin_space(md->ebin,md->nTC,grpnms); sfree(*grpnms); if (etc == etcNOSEHOOVER) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Xi-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->nTC,grpnms); sfree(*grpnms); } else if (etc == etcBERENDSEN || etc == etcYES || etc == etcVRESCALE) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Lamb-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->nTC,grpnms); sfree(*grpnms); } sfree(grpnms); md->nU=groups->grps[egcACC].nr; if (md->nU > 1) { snew(grpnms,3*md->nU); for(i=0; (i<md->nU); i++) { ni=groups->grps[egcACC].nm_ind[i]; sprintf(buf,"Ux-%s",*(groups->grpname[ni])); grpnms[3*i+XX]=strdup(buf); sprintf(buf,"Uy-%s",*(groups->grpname[ni])); grpnms[3*i+YY]=strdup(buf); sprintf(buf,"Uz-%s",*(groups->grpname[ni])); grpnms[3*i+ZZ]=strdup(buf); } md->iu=get_ebin_space(md->ebin,3*md->nU,grpnms); sfree(*grpnms); sfree(grpnms); } if (fp_ene != -1) do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm); return md; }