/* Pulling with a harmonic umbrella potential or constant force */ static void do_pull_pot(int ePull, t_pull *pull, t_pbc *pbc, double t, real lambda, real *V, tensor vir, real *dVdl) { int g,j,m; dvec dev; double ndr,invdr; real k,dkdl; t_pullgrp *pgrp; /* loop over the groups that are being pulled */ *V = 0; *dVdl = 0; for(g=1; g<1+pull->ngrp; g++) { pgrp = &pull->grp[g]; get_pullgrp_distance(pull,pbc,g,t,pgrp->dr,dev); k = (1.0 - lambda)*pgrp->k + lambda*pgrp->kB; dkdl = pgrp->kB - pgrp->k; switch (pull->eGeom) { case epullgDIST: ndr = dnorm(pgrp->dr); invdr = 1/ndr; if (ePull == epullUMBRELLA) { pgrp->f_scal = -k*dev[0]; *V += 0.5* k*dsqr(dev[0]); *dVdl += 0.5*dkdl*dsqr(dev[0]); } else { pgrp->f_scal = -k; *V += k*ndr; *dVdl += dkdl*ndr; } for(m=0; m<DIM; m++) { pgrp->f[m] = pgrp->f_scal*pgrp->dr[m]*invdr; } break; case epullgDIR: case epullgDIRPBC: case epullgCYL: if (ePull == epullUMBRELLA) { pgrp->f_scal = -k*dev[0]; *V += 0.5* k*dsqr(dev[0]); *dVdl += 0.5*dkdl*dsqr(dev[0]); } else { ndr = 0; for(m=0; m<DIM; m++) { ndr += pgrp->vec[m]*pgrp->dr[m]; } pgrp->f_scal = -k; *V += k*ndr; *dVdl += dkdl*ndr; } for(m=0; m<DIM; m++) { pgrp->f[m] = pgrp->f_scal*pgrp->vec[m]; } break; case epullgPOS: for(m=0; m<DIM; m++) { if (ePull == epullUMBRELLA) { pgrp->f[m] = -k*dev[m]; *V += 0.5* k*dsqr(dev[m]); *dVdl += 0.5*dkdl*dsqr(dev[m]); } else { pgrp->f[m] = -k*pull->dim[m]; *V += k*pgrp->dr[m]*pull->dim[m]; *dVdl += dkdl*pgrp->dr[m]*pull->dim[m]; } } break; } if (vir) { /* Add the pull contribution to the virial */ for(j=0; j<DIM; j++) { for(m=0;m<DIM;m++) { vir[j][m] -= 0.5*pgrp->f[j]*pgrp->dr[m]; } } } } }
void set_pull_init(t_inputrec *ir, gmx_mtop_t *mtop, rvec *x, matrix box, real lambda, const output_env_t oenv, gmx_bool bStart) { t_mdatoms *md; t_pull *pull; t_pullgrp *pgrp; t_pbc pbc; int ndim, g, m; double t_start, tinvrate; rvec init; dvec dr, dev; init_pull(NULL, ir, 0, NULL, mtop, NULL, oenv, lambda, FALSE, 0); md = init_mdatoms(NULL, mtop, ir->efep); atoms2md(mtop, ir, 0, NULL, 0, mtop->natoms, md); if (ir->efep) { update_mdatoms(md, lambda); } pull = ir->pull; if (pull->eGeom == epullgPOS) { ndim = 3; } else { ndim = 1; } set_pbc(&pbc, ir->ePBC, box); t_start = ir->init_t + ir->init_step*ir->delta_t; pull_calc_coms(NULL, pull, md, &pbc, t_start, x, NULL); fprintf(stderr, "Pull group natoms pbc atom distance at start reference at t=0\n"); for (g = 0; g < pull->ngrp+1; g++) { pgrp = &pull->grp[g]; fprintf(stderr, "%8d %8d %8d ", g, pgrp->nat, pgrp->pbcatom+1); copy_rvec(pgrp->init, init); clear_rvec(pgrp->init); if (g > 0) { if (pgrp->rate == 0) { tinvrate = 0; } else { tinvrate = t_start/pgrp->rate; } get_pullgrp_distance(pull, &pbc, g, 0, dr, dev); for (m = 0; m < DIM; m++) { if (m < ndim) { fprintf(stderr, " %6.3f", dev[m]); } else { fprintf(stderr, " "); } } fprintf(stderr, " "); for (m = 0; m < DIM; m++) { if (bStart) { pgrp->init[m] = init[m] + dev[m] - tinvrate*(pull->eGeom == epullgPOS ? pgrp->vec[m] : 1); } else { pgrp->init[m] = init[m]; } if (m < ndim) { fprintf(stderr, " %6.3f", pgrp->init[m]); } else { fprintf(stderr, " "); } } } fprintf(stderr, "\n"); } }