/* This is a (maybe) slow workaround to avoid the neighbor searching in addconf.c, which * leaks memory (May 2012). The function could be deleted as soon as the momory leaks * in addconf.c are fixed. * However, when inserting a small molecule in a system containing not too many atoms, * allPairsDistOk is probably even faster than addconf.c */ static gmx_bool allPairsDistOk(t_atoms *atoms, rvec *x, real *r, int ePBC, matrix box, t_atoms *atoms_insrt, rvec *x_n, real *r_insrt) { int i, j; rvec dx; real n2, r2; t_pbc pbc; set_pbc(&pbc, ePBC, box); for (i = 0; i < atoms->nr; i++) { for (j = 0; j < atoms_insrt->nr; j++) { pbc_dx(&pbc, x[i], x_n[j], dx); n2 = norm2(dx); r2 = sqr(r[i]+r_insrt[j]); if (n2 < r2) { return FALSE; } } } return TRUE; }
static void calc_dist_tot(int nind, atom_id index[], rvec x[], int ePBC, matrix box, real **d, real **dtot, real **dtot2, gmx_bool bNMR, real **dtot1_3, real **dtot1_6) { int i, j; real *xi; real temp, temp2, temp1_3; rvec dx; t_pbc pbc; set_pbc(&pbc, ePBC, box); for (i = 0; (i < nind-1); i++) { xi = x[index[i]]; for (j = i+1; (j < nind); j++) { pbc_dx(&pbc, xi, x[index[j]], dx); temp2 = norm2(dx); temp = std::sqrt(temp2); d[i][j] = temp; dtot[i][j] += temp; dtot2[i][j] += temp2; if (bNMR) { temp1_3 = 1.0/(temp*temp2); dtot1_3[i][j] += temp1_3; dtot1_6[i][j] += temp1_3*temp1_3; } } } }
void Distance::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata) { AnalysisDataHandle dh = pdata->dataHandle(data_); const Selection &sel1 = pdata->parallelSelection(sel_[0]); const Selection &sel2 = pdata->parallelSelection(sel_[1]); rvec dx; real r; const SelectionPosition &p1 = sel1.position(0); const SelectionPosition &p2 = sel2.position(0); if (pbc != NULL) { pbc_dx(pbc, p1.x(), p2.x(), dx); } else { rvec_sub(p1.x(), p2.x(), dx); } r = norm(dx); dh.startFrame(frnr, fr.time); dh.setPoint(0, r); dh.setPoints(1, 3, dx); dh.finishFrame(); }
void mk_bonds(int nnm, t_nm2type nmt[], t_atoms *atoms, rvec x[], t_params *bond, int nbond[], gmx_bool bPBC, matrix box) { t_param b; int i, j; t_pbc pbc; rvec dx; real dx2; for (i = 0; (i < MAXATOMLIST); i++) { b.a[i] = -1; } for (i = 0; (i < MAXFORCEPARAM); i++) { b.c[i] = 0.0; } if (bPBC) { set_pbc(&pbc, -1, box); } for (i = 0; (i < atoms->nr); i++) { if ((i % 10) == 0) { fprintf(stderr, "\ratom %d", i); } for (j = i+1; (j < atoms->nr); j++) { if (bPBC) { pbc_dx(&pbc, x[i], x[j], dx); } else { rvec_sub(x[i], x[j], dx); } dx2 = iprod(dx, dx); if (is_bond(nnm, nmt, *atoms->atomname[i], *atoms->atomname[j], sqrt(dx2))) { b.AI = i; b.AJ = j; b.C0 = sqrt(dx2); add_param_to_list (bond, &b); nbond[i]++; nbond[j]++; if (debug) { fprintf(debug, "Bonding atoms %s-%d and %s-%d\n", *atoms->atomname[i], i+1, *atoms->atomname[j], j+1); } } } } fprintf(stderr, "\ratom %d\n", i); }
static t_bbb *mk_bonds(int natoms,rvec x[],real odist, gmx_bool bPBC,matrix box) { real od2 = odist*odist+1e-5; t_pbc pbc; t_bbb *bbb; int i,j; rvec dx; if (bPBC) set_pbc(&pbc,box); snew(bbb,natoms); for(i=0; (i<natoms); i++) { for(j=i+1; (j<natoms); j++) { if (bPBC) pbc_dx(&pbc,x[i],x[j],dx); else rvec_sub(x[i],x[j],dx); if (iprod(dx,dx) <= od2) { bbb[i].aa[bbb[i].n++] = j; bbb[j].aa[bbb[j].n++] = i; } } } if (debug) #define PRB(nn) (bbb[(i)].n >= (nn)) ? bbb[i].aa[nn-1] : -1 for(i=0; (i<natoms); i++) fprintf(debug,"bonds from %3d: %d %d %d %d\n", i,PRB(1),PRB(2),PRB(3),PRB(4)); #undef PRB return bbb; }
static void insert_ion(int nsa, const int *nwater, gmx_bool bSet[], int repl[], int index[], rvec x[], t_pbc *pbc, int sign, int q, const char *ionname, t_atoms *atoms, real rmin, gmx::DefaultRandomEngine * rng) { int i, ei, nw; real rmin2; rvec dx; int64_t maxrand; gmx::UniformIntDistribution<int> dist(0, *nwater-1); nw = *nwater; maxrand = nw; maxrand *= 1000; do { ei = dist(*rng); maxrand--; } while (bSet[ei] && (maxrand > 0)); if (bSet[ei]) { gmx_fatal(FARGS, "No more replaceable solvent!"); } fprintf(stderr, "Replacing solvent molecule %d (atom %d) with %s\n", ei, index[nsa*ei], ionname); /* Replace solvent molecule charges with ion charge */ bSet[ei] = TRUE; repl[ei] = sign; atoms->atom[index[nsa*ei]].q = q; for (i = 1; i < nsa; i++) { atoms->atom[index[nsa*ei+i]].q = 0; } /* Mark all solvent molecules within rmin as unavailable for substitution */ if (rmin > 0) { rmin2 = rmin*rmin; for (i = 0; (i < nw); i++) { if (!bSet[i]) { pbc_dx(pbc, x[index[nsa*ei]], x[index[nsa*i]], dx); if (iprod(dx, dx) < rmin2) { bSet[i] = TRUE; } } } } }
static real dist2(t_pbc *pbc,rvec x,rvec y) { rvec dx; pbc_dx(pbc,x,y,dx); return norm2(dx); }
static void calc_com_pbc(int nrefat, t_topology *top, rvec x[], t_pbc *pbc, atom_id index[], rvec xref, int ePBC) { const real tol = 1e-4; gmx_bool bChanged; int m, j, ai, iter; real mass, mtot; rvec dx, xtest; /* First simple calculation */ clear_rvec(xref); mtot = 0; for (m = 0; (m < nrefat); m++) { ai = index[m]; mass = top->atoms.atom[ai].m; for (j = 0; (j < DIM); j++) { xref[j] += mass*x[ai][j]; } mtot += mass; } svmul(1/mtot, xref, xref); /* Now check if any atom is more than half the box from the COM */ if (ePBC != epbcNONE) { iter = 0; do { bChanged = FALSE; for (m = 0; (m < nrefat); m++) { ai = index[m]; mass = top->atoms.atom[ai].m/mtot; pbc_dx(pbc, x[ai], xref, dx); rvec_add(xref, dx, xtest); for (j = 0; (j < DIM); j++) { if (std::abs(xtest[j]-x[ai][j]) > tol) { /* Here we have used the wrong image for contributing to the COM */ xref[j] += mass*(xtest[j]-x[ai][j]); x[ai][j] = xtest[j]; bChanged = TRUE; } } } if (bChanged) { printf("COM: %8.3f %8.3f %8.3f iter = %d\n", xref[XX], xref[YY], xref[ZZ], iter); } iter++; } while (bChanged); } }
static void chk_bonds(t_idef *idef, int ePBC, rvec *x, matrix box, real tol) { int ftype, i, k, ai, aj, type; real b0, blen, deviation, devtot; t_pbc pbc; rvec dx; devtot = 0; set_pbc(&pbc, ePBC, box); for (ftype = 0; (ftype < F_NRE); ftype++) { if ((interaction_function[ftype].flags & IF_CHEMBOND) == IF_CHEMBOND) { for (k = 0; (k < idef->il[ftype].nr); ) { type = idef->il[ftype].iatoms[k++]; ai = idef->il[ftype].iatoms[k++]; aj = idef->il[ftype].iatoms[k++]; b0 = 0; switch (ftype) { case F_BONDS: b0 = idef->iparams[type].harmonic.rA; break; case F_G96BONDS: b0 = sqrt(idef->iparams[type].harmonic.rA); break; case F_MORSE: b0 = idef->iparams[type].morse.b0A; break; case F_CUBICBONDS: b0 = idef->iparams[type].cubic.b0; break; case F_CONSTR: b0 = idef->iparams[type].constr.dA; break; default: break; } if (b0 != 0) { pbc_dx(&pbc, x[ai], x[aj], dx); blen = norm(dx); deviation = sqr(blen-b0); if (sqrt(deviation/sqr(b0) > tol)) { fprintf(stderr, "Distance between atoms %d and %d is %.3f, should be %.3f\n", ai+1, aj+1, blen, b0); } } } } } }
//! Helper method to calculate a vector from two or three positions. static void calc_vec(int natoms, rvec x[], t_pbc *pbc, rvec xout, rvec cout) { switch (natoms) { case 2: if (pbc) { pbc_dx(pbc, x[1], x[0], xout); } else { rvec_sub(x[1], x[0], xout); } svmul(0.5, xout, cout); rvec_add(x[0], cout, cout); break; case 3: { rvec v1, v2; if (pbc) { pbc_dx(pbc, x[1], x[0], v1); pbc_dx(pbc, x[2], x[0], v2); } else { rvec_sub(x[1], x[0], v1); rvec_sub(x[2], x[0], v2); } cprod(v1, v2, xout); rvec_add(x[0], x[1], cout); rvec_add(cout, x[2], cout); svmul(1.0/3.0, cout, cout); break; } default: GMX_RELEASE_ASSERT(false, "Incorrectly initialized number of atoms"); } }
/*! * \param[in] top Topology structure with masses. * \param[in] x Position vectors of all atoms. * \param[in] pbc Periodic boundary conditions structure. * \param[in] nrefat Number of atoms in the index. * \param[in] index Indices of atoms. * \param[out] xout COM position for the indexed atoms. * * Works as gmx_calc_com(), but takes into account periodic boundary * conditions: If any atom is more than half the box from the COM, * it is wrapped around and a new COM is calculated. This is repeated * until no atoms violate the condition. * * Modified from src/tools/gmx_sorient.c in Gromacs distribution. */ void gmx_calc_com_pbc(const gmx_mtop_t *top, rvec x[], const t_pbc *pbc, int nrefat, const int index[], rvec xout) { GMX_RELEASE_ASSERT(gmx_mtop_has_masses(top), "No masses available while mass weighting was requested"); /* First simple calculation */ clear_rvec(xout); real mtot = 0; int molb = 0; for (int m = 0; m < nrefat; ++m) { const int ai = index[m]; const real mass = mtopGetAtomMass(top, ai, &molb); for (int j = 0; j < DIM; ++j) { xout[j] += mass * x[ai][j]; } mtot += mass; } svmul(1.0/mtot, xout, xout); /* Now check if any atom is more than half the box from the COM */ if (pbc) { const real tol = 1e-4; bool bChanged; do { bChanged = false; molb = 0; for (int m = 0; m < nrefat; ++m) { rvec dx, xtest; const int ai = index[m]; const real mass = mtopGetAtomMass(top, ai, &molb) / mtot; pbc_dx(pbc, x[ai], xout, dx); rvec_add(xout, dx, xtest); for (int j = 0; j < DIM; ++j) { if (fabs(xtest[j] - x[ai][j]) > tol) { /* Here we have used the wrong image for contributing to the COM */ xout[j] += mass * (xtest[j] - x[ai][j]); x[ai][j] = xtest[j]; bChanged = true; } } } } while (bChanged); } }
// **************** PERIODIC BOUNDARY CONDITIONS **************** // Get the PBC-aware distance vector between two positions cvm::rvector colvarproxy_gromacs::position_distance (cvm::atom_pos const &pos1, cvm::atom_pos const &pos2) { rvec r1, r2, dr; r1[0] = pos1.x; r1[1] = pos1.y; r1[2] = pos1.z; r2[0] = pos2.x; r2[1] = pos2.y; r2[2] = pos2.z; pbc_dx(&gmx_pbc, r1, r2, dr); return cvm::atom_pos( dr[0], dr[1], dr[2] ); }
static void calc_vec(int natoms, rvec x[], t_pbc *pbc, rvec xout, rvec cout) { switch (natoms) { case 2: if (pbc) { pbc_dx(pbc, x[1], x[0], xout); } else { rvec_sub(x[1], x[0], xout); } svmul(0.5, xout, cout); rvec_add(x[0], cout, cout); break; case 3: { rvec v1, v2; if (pbc) { pbc_dx(pbc, x[1], x[0], v1); pbc_dx(pbc, x[2], x[0], v2); } else { rvec_sub(x[1], x[0], v1); rvec_sub(x[2], x[0], v2); } cprod(v1, v2, xout); rvec_add(x[0], x[1], cout); rvec_add(cout, x[2], cout); svmul(1.0/3.0, cout, cout); break; } } }
static void calc_mj(t_topology top, int ePBC, matrix box, gmx_bool bNoJump, int isize, int index0[], \ rvec fr[], rvec mj, real mass2[], real qmol[]) { int i, j, k, l; rvec tmp; rvec center; rvec mt1, mt2; t_pbc pbc; calc_box_center(ecenterRECT, box, center); if (!bNoJump) { set_pbc(&pbc, ePBC, box); } clear_rvec(tmp); for (i = 0; i < isize; i++) { clear_rvec(mt1); clear_rvec(mt2); k = top.mols.index[index0[i]]; l = top.mols.index[index0[i+1]]; for (j = k; j < l; j++) { svmul(mass2[j], fr[j], tmp); rvec_inc(mt1, tmp); } if (bNoJump) { svmul(qmol[k], mt1, mt1); } else { pbc_dx(&pbc, mt1, center, mt2); svmul(qmol[k], mt2, mt1); } rvec_inc(mj, mt1); } }
static real calc_dist(t_pbc *pbc,rvec x[],t_block *cgs,int icg,int jcg) { int i,j; rvec dx; real d2,mindist2=1000; for(i=cgs->index[icg]; (i<cgs->index[icg+1]); i++) { for(j=cgs->index[jcg]; (j<cgs->index[jcg+1]); j++) { pbc_dx(pbc,x[i],x[j],dx); d2 = norm2(dx); if (d2 < mindist2) mindist2 = d2; } } return sqrt(mindist2); }
static void calc_mat(int nres, int natoms, int rndx[], rvec x[], atom_id *index, real trunc, real **mdmat, int **nmat, int ePBC, matrix box) { int i, j, resi, resj; real trunc2, r, r2; t_pbc pbc; rvec ddx; set_pbc(&pbc, ePBC, box); trunc2 = sqr(trunc); for (resi = 0; (resi < nres); resi++) { for (resj = 0; (resj < nres); resj++) { mdmat[resi][resj] = FARAWAY; } } for (i = 0; (i < natoms); i++) { resi = rndx[i]; for (j = i+1; (j < natoms); j++) { resj = rndx[j]; pbc_dx(&pbc, x[index[i]], x[index[j]], ddx); r2 = norm2(ddx); if (r2 < trunc2) { nmat[resi][j]++; nmat[resj][i]++; } mdmat[resi][resj] = min(r2, mdmat[resi][resj]); } } for (resi = 0; (resi < nres); resi++) { mdmat[resi][resi] = 0; for (resj = resi+1; (resj < nres); resj++) { r = sqrt(mdmat[resi][resj]); mdmat[resi][resj] = r; mdmat[resj][resi] = r; } } }
const char * put_atoms_in_compact_unitcell(int ePBC,int ecenter,matrix box, int natoms,rvec x[]) { t_pbc pbc; rvec box_center,dx; int i; set_pbc(&pbc,ePBC,box); calc_box_center(ecenter,box,box_center); for(i=0; i<natoms; i++) { pbc_dx(&pbc,x[i],box_center,dx); rvec_add(box_center,dx,x[i]); } return pbc.bLimitDistance ? "WARNING: Could not put all atoms in the compact unitcell\n" : NULL; }
static void calc_dist(int nind, int index[], const rvec x[], int ePBC, matrix box, real **d) { int i, j; rvec dx; real temp2; t_pbc pbc; set_pbc(&pbc, ePBC, box); for (i = 0; (i < nind-1); i++) { const real *xi = x[index[i]]; for (j = i+1; (j < nind); j++) { pbc_dx(&pbc, xi, x[index[j]], dx); temp2 = norm2(dx); d[i][j] = std::sqrt(temp2); } } }
void put_atoms_in_compact_unitcell(int ePBC, int ecenter, const matrix box, int natoms, rvec x[]) { t_pbc pbc; rvec box_center, dx; int i; set_pbc(&pbc, ePBC, box); if (pbc.ePBCDX == epbcdxUNSUPPORTED) { gmx_fatal(FARGS, "Can not put atoms in compact unitcell with unsupported PBC"); } calc_box_center(ecenter, box, box_center); for (i = 0; i < natoms; i++) { pbc_dx(&pbc, x[i], box_center, dx); rvec_add(box_center, dx, x[i]); } }
/*! * \param[in] top Topology structure (unused, can be NULL). * \param[in] x Position vectors of all atoms. * \param[in] pbc Periodic boundary conditions structure. * \param[in] nrefat Number of atoms in the index. * \param[in] index Indices of atoms. * \param[out] xout COG position for the indexed atoms. * * Works exactly as gmx_calc_com_pbc(), but calculates the center of geometry. */ void gmx_calc_cog_pbc(const gmx_mtop_t *top, rvec x[], const t_pbc *pbc, int nrefat, const int index[], rvec xout) { const real tol = 1e-4; bool bChanged; int m, j, ai, iter; rvec dx, xtest; /* First simple calculation */ gmx_calc_cog(top, x, nrefat, index, xout); /* Now check if any atom is more than half the box from the COM */ if (pbc) { iter = 0; do { bChanged = false; for (m = 0; m < nrefat; ++m) { ai = index[m]; pbc_dx(pbc, x[ai], xout, dx); rvec_add(xout, dx, xtest); for (j = 0; j < DIM; ++j) { if (fabs(xtest[j] - x[ai][j]) > tol) { /* Here we have used the wrong image for contributing to the COM */ xout[j] += (xtest[j] - x[ai][j]) / nrefat; x[ai][j] = xtest[j]; bChanged = true; } } } iter++; } while (bChanged); } }
real adress_weight(rvec x, int adresstype, real adressr, real adressw, rvec * ref, t_pbc * pbc, t_forcerec * fr ) { int i; real l2 = adressr+adressw; real sqr_dl, dl; real tmp; rvec dx; sqr_dl = 0.0; if (pbc) { pbc_dx(pbc, (*ref), x, dx); } else { rvec_sub((*ref), x, dx); } switch (adresstype) { case eAdressOff: /* default to explicit simulation */ return 1; case eAdressConst: /* constant value for weighting function = adressw */ return fr->adress_const_wf; case eAdressXSplit: /* plane through center of ref, varies in x direction */ sqr_dl = dx[0]*dx[0]; break; case eAdressSphere: /* point at center of ref, assuming cubic geometry */ for (i = 0; i < 3; i++) { sqr_dl += dx[i]*dx[i]; } break; default: /* default to explicit simulation */ return 1; } dl = sqrt(sqr_dl); /* molecule is coarse grained */ if (dl > l2) { return 0; } /* molecule is explicit */ else if (dl < adressr) { return 1; } /* hybrid region */ else { tmp = cos((dl-adressr)*M_PI/2/adressw); return tmp*tmp; } }
int gmx_dyecoupl(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] extracts dye dynamics from trajectory files.", "Currently, R and kappa^2 between dyes is extracted for (F)RET", "simulations with assumed dipolar coupling as in the Foerster equation.", "It further allows the calculation of R(t) and kappa^2(t), R and", "kappa^2 histograms and averages, as well as the instantaneous FRET", "efficiency E(t) for a specified Foerster radius R_0 (switch [TT]-R0[tt]).", "The input dyes have to be whole (see res and mol pbc options", "in [TT]trjconv[tt]).", "The dye transition dipole moment has to be defined by at least", "a single atom pair, however multiple atom pairs can be provided ", "in the index file. The distance R is calculated on the basis of", "the COMs of the given atom pairs.", "The [TT]-pbcdist[tt] option calculates distances to the nearest periodic", "image instead to the distance in the box. This works however only," "for periodic boundaries in all 3 dimensions.", "The [TT]-norm[tt] option (area-) normalizes the histograms." }; static gmx_bool bPBCdist = FALSE, bNormHist = FALSE; int histbins = 50; gmx_output_env_t *oenv; real R0 = -1; t_pargs pa[] = { { "-pbcdist", FALSE, etBOOL, { &bPBCdist }, "Distance R based on PBC" }, { "-norm", FALSE, etBOOL, { &bNormHist }, "Normalize histograms" }, { "-bins", FALSE, etINT, {&histbins}, "# of histogram bins" }, { "-R0", FALSE, etREAL, {&R0}, "Foerster radius including kappa^2=2/3 in nm" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efNDX, NULL, NULL, ffREAD }, { efXVG, "-ot", "rkappa", ffOPTWR }, { efXVG, "-oe", "insteff", ffOPTWR }, { efDAT, "-o", "rkappa", ffOPTWR }, { efXVG, "-rhist", "rhist", ffOPTWR }, { efXVG, "-khist", "khist", ffOPTWR } }; #define NFILE asize(fnm) const char *in_trajfile, *out_xvgrkfile = NULL, *out_xvginstefffile = NULL, *out_xvgrhistfile = NULL, *out_xvgkhistfile = NULL, *out_datfile = NULL; gmx_bool bHaveFirstFrame, bHaveNextFrame, indexOK = TRUE; int ndon, nacc; atom_id *donindex, *accindex; char *grpnm; t_trxstatus *status; t_trxframe fr; int flags; int allocblock = 1000; real histexpand = 1e-6; rvec donvec, accvec, donpos, accpos, dist, distnorm; int natoms; /*we rely on PBC autodetection (...currently)*/ int ePBC = -1; real *rvalues = NULL, *kappa2values = NULL, *rhist = NULL, *khist = NULL; t_pbc *pbc = NULL; int i, bin; FILE *rkfp = NULL, *rhfp = NULL, *khfp = NULL, *datfp = NULL, *iefp = NULL; gmx_bool bRKout, bRhistout, bKhistout, bDatout, bInstEffout, grident; const char *rkleg[2] = { "R", "\\f{Symbol}k\\f{}\\S2\\N" }; const char *rhleg[1] = { "p(R)" }; const char *khleg[1] = { "p(\\f{Symbol}k\\f{}\\S2\\N)" }; const char *ieleg[1] = { "E\\sRET\\N(t)" }; real R, kappa2, insteff, Rs = 0., kappa2s = 0., insteffs = 0., rmax, rmin, kmin = 0., kmax = 4., rrange, krange, rincr, kincr, Rfrac; int rkcount = 0, rblocksallocated = 0, kblocksallocated = 0; if (!parse_common_args(&argc, argv, PCA_CAN_BEGIN | PCA_CAN_END | PCA_CAN_VIEW | PCA_TIME_UNIT, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } /* Check command line options for filenames and set bool flags when switch used*/ in_trajfile = opt2fn("-f", NFILE, fnm); out_xvgrkfile = opt2fn("-ot", NFILE, fnm); out_xvgrhistfile = opt2fn("-rhist", NFILE, fnm); out_xvgkhistfile = opt2fn("-khist", NFILE, fnm); out_xvginstefffile = opt2fn("-oe", NFILE, fnm); out_datfile = opt2fn("-o", NFILE, fnm); bRKout = opt2bSet("-ot", NFILE, fnm); bRhistout = opt2bSet("-rhist", NFILE, fnm); bKhistout = opt2bSet("-khist", NFILE, fnm); bDatout = opt2bSet("-o", NFILE, fnm); bInstEffout = opt2bSet("-oe", NFILE, fnm); /* PBC warning. */ if (bPBCdist) { printf("Calculating distances to periodic image.\n"); printf("Be careful! This produces only valid results for PBC in all three dimensions\n"); } if (bInstEffout && R0 <= 0.) { gmx_fatal(FARGS, "You have to specify R0 and R0 has to be larger than 0 nm.\n\n"); } printf("Select group with donor atom pairs defining the transition moment\n"); get_index(NULL, ftp2fn_null(efNDX, NFILE, fnm), 1, &ndon, &donindex, &grpnm); printf("Select group with acceptor atom pairs defining the transition moment\n"); get_index(NULL, ftp2fn_null(efNDX, NFILE, fnm), 1, &nacc, &accindex, &grpnm); /*check if groups are identical*/ grident = TRUE; if (ndon == nacc) { for (i = 0; i < nacc; i++) { if (accindex[i] != donindex[i]) { grident = FALSE; break; } } } if (grident) { gmx_fatal(FARGS, "Donor and acceptor group are identical. This makes no sense."); } printf("Reading first frame\n"); /* open trx file for reading */ flags = 0; flags = flags | TRX_READ_X; bHaveFirstFrame = read_first_frame(oenv, &status, in_trajfile, &fr, flags); if (bHaveFirstFrame) { printf("First frame is OK\n"); natoms = fr.natoms; if ((ndon % 2 != 0) || (nacc % 2 != 0)) { indexOK = FALSE; } else { for (i = 0; i < ndon; i++) { if (donindex[i] >= natoms) { indexOK = FALSE; } } for (i = 0; i < nacc; i++) { if (accindex[i] >= natoms) { indexOK = FALSE; } } } if (indexOK) { if (bDatout) { datfp = gmx_ffopen(out_datfile, "w"); } if (bRKout) { rkfp = xvgropen(out_xvgrkfile, "Distance and \\f{Symbol}k\\f{}\\S2\\N trajectory", "Time (ps)", "Distance (nm) / \\f{Symbol}k\\f{}\\S2\\N", oenv); xvgr_legend(rkfp, 2, rkleg, oenv); } if (bInstEffout) { iefp = xvgropen(out_xvginstefffile, "Instantaneous RET Efficiency", "Time (ps)", "RET Efficiency", oenv); xvgr_legend(iefp, 1, ieleg, oenv); } if (bRhistout) { snew(rvalues, allocblock); rblocksallocated += 1; snew(rhist, histbins); } if (bKhistout) { snew(kappa2values, allocblock); kblocksallocated += 1; snew(khist, histbins); } do { clear_rvec(donvec); clear_rvec(accvec); clear_rvec(donpos); clear_rvec(accpos); for (i = 0; i < ndon / 2; i++) { rvec_sub(donvec, fr.x[donindex[2 * i]], donvec); rvec_add(donvec, fr.x[donindex[2 * i + 1]], donvec); rvec_add(donpos, fr.x[donindex[2 * i]], donpos); rvec_add(donpos, fr.x[donindex[2 * i + 1]], donpos); } for (i = 0; i < nacc / 2; i++) { rvec_sub(accvec, fr.x[accindex[2 * i]], accvec); rvec_add(accvec, fr.x[accindex[2 * i + 1]], accvec); rvec_add(accpos, fr.x[accindex[2 * i]], accpos); rvec_add(accpos, fr.x[accindex[2 * i + 1]], accpos); } unitv(donvec, donvec); unitv(accvec, accvec); svmul(1.0 / ndon, donpos, donpos); svmul(1.0 / nacc, accpos, accpos); if (bPBCdist) { set_pbc(pbc, ePBC, fr.box); pbc_dx(pbc, donpos, accpos, dist); } else { rvec_sub(donpos, accpos, dist); } unitv(dist, distnorm); R = norm(dist); kappa2 = iprod(donvec, accvec)- 3.* (iprod(donvec, distnorm) * iprod(distnorm, accvec)); kappa2 *= kappa2; if (R0 > 0) { Rfrac = R/R0; insteff = 1/(1+(Rfrac*Rfrac*Rfrac*Rfrac*Rfrac*Rfrac)*2/3/kappa2); insteffs += insteff; if (bInstEffout) { fprintf(iefp, "%12.7f %12.7f\n", fr.time, insteff); } } Rs += R; kappa2s += kappa2; rkcount++; if (bRKout) { fprintf(rkfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2); } if (bDatout) { fprintf(datfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2); } if (bRhistout) { rvalues[rkcount-1] = R; if (rkcount % allocblock == 0) { srenew(rvalues, allocblock*(rblocksallocated+1)); rblocksallocated += 1; } } if (bKhistout) { kappa2values[rkcount-1] = kappa2; if (rkcount % allocblock == 0) { srenew(kappa2values, allocblock*(kblocksallocated+1)); kblocksallocated += 1; } } bHaveNextFrame = read_next_frame(oenv, status, &fr); } while (bHaveNextFrame); if (bRKout) { xvgrclose(rkfp); } if (bDatout) { gmx_ffclose(datfp); } if (bInstEffout) { xvgrclose(iefp); } if (bRhistout) { printf("Writing R-Histogram\n"); rmin = rvalues[0]; rmax = rvalues[0]; for (i = 1; i < rkcount; i++) { if (rvalues[i] < rmin) { rmin = rvalues[i]; } else if (rvalues[i] > rmax) { rmax = rvalues[i]; } } rmin -= histexpand; rmax += histexpand; rrange = rmax - rmin; rincr = rrange / histbins; for (i = 1; i < rkcount; i++) { bin = static_cast<int>((rvalues[i] - rmin) / rincr); rhist[bin] += 1; } if (bNormHist) { for (i = 0; i < histbins; i++) { rhist[i] /= rkcount * rrange/histbins; } rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution", "R (nm)", "Normalized Probability", oenv); } else { rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution", "R (nm)", "Probability", oenv); } xvgr_legend(rhfp, 1, rhleg, oenv); for (i = 0; i < histbins; i++) { fprintf(rhfp, "%12.7f %12.7f\n", (i + 0.5) * rincr + rmin, rhist[i]); } xvgrclose(rhfp); } if (bKhistout) { printf("Writing kappa^2-Histogram\n"); krange = kmax - kmin; kincr = krange / histbins; for (i = 1; i < rkcount; i++) { bin = static_cast<int>((kappa2values[i] - kmin) / kincr); khist[bin] += 1; } if (bNormHist) { for (i = 0; i < histbins; i++) { khist[i] /= rkcount * krange/histbins; } khfp = xvgropen(out_xvgkhistfile, "\\f{Symbol}k\\f{}\\S2\\N Distribution", "\\f{Symbol}k\\f{}\\S2\\N", "Normalized Probability", oenv); } else { khfp = xvgropen(out_xvgkhistfile, "\\f{Symbol}k\\f{}\\S2\\N Distribution", "\\f{Symbol}k\\f{}\\S2\\N", "Probability", oenv); } xvgr_legend(khfp, 1, khleg, oenv); for (i = 0; i < histbins; i++) { fprintf(khfp, "%12.7f %12.7f\n", (i + 0.5) * kincr + kmin, khist[i]); } xvgrclose(khfp); } printf("\nAverages:\n"); printf("R_avg = %8.4f nm\nKappa^2 = %8.4f\n", Rs / rkcount, kappa2s / rkcount); if (R0 > 0) { printf("E_RETavg = %8.4f\n", insteffs / rkcount); } please_cite(stdout, "Hoefling2011"); } else { gmx_fatal(FARGS, "Index file invalid, check your index file for correct pairs.\n"); } } else { gmx_fatal(FARGS, "Could not read first frame of the trajectory.\n"); } return 0; }
/* calculates center of mass of selection index from all coordinates x */ void pull_calc_coms(t_commrec *cr, t_pull *pull, t_mdatoms *md, t_pbc *pbc, double t, rvec x[], rvec *xp) { int g, i, ii, m; real mass, w, wm, twopi_box = 0; double wmass, wwmass, invwmass; dvec com, comp; double cm, sm, cmp, smp, ccm, csm, ssm, csw, snw; rvec *xx[2], x_pbc = {0, 0, 0}, dx; t_pull_group *pgrp; if (pull->rbuf == NULL) { snew(pull->rbuf, pull->ngroup); } if (pull->dbuf == NULL) { snew(pull->dbuf, 3*pull->ngroup); } if (pull->bRefAt) { pull_set_pbcatoms(cr, pull, md, x, pull->rbuf); } if (pull->cosdim >= 0) { for (m = pull->cosdim+1; m < pull->npbcdim; m++) { if (pbc->box[m][pull->cosdim] != 0) { gmx_fatal(FARGS, "Can not do cosine weighting for trilinic dimensions"); } } twopi_box = 2.0*M_PI/pbc->box[pull->cosdim][pull->cosdim]; } for (g = 0; g < pull->ngroup; g++) { pgrp = &pull->group[g]; clear_dvec(com); clear_dvec(comp); wmass = 0; wwmass = 0; cm = 0; sm = 0; cmp = 0; smp = 0; ccm = 0; csm = 0; ssm = 0; if (!(g == 0 && PULL_CYL(pull))) { if (pgrp->epgrppbc == epgrppbcREFAT) { /* Set the pbc atom */ copy_rvec(pull->rbuf[g], x_pbc); } w = 1; for (i = 0; i < pgrp->nat_loc; i++) { ii = pgrp->ind_loc[i]; mass = md->massT[ii]; if (pgrp->epgrppbc != epgrppbcCOS) { if (pgrp->weight_loc) { w = pgrp->weight_loc[i]; } wm = w*mass; wmass += wm; wwmass += wm*w; if (pgrp->epgrppbc == epgrppbcNONE) { /* Plain COM: sum the coordinates */ for (m = 0; m < DIM; m++) { com[m] += wm*x[ii][m]; } if (xp) { for (m = 0; m < DIM; m++) { comp[m] += wm*xp[ii][m]; } } } else { /* Sum the difference with the reference atom */ pbc_dx(pbc, x[ii], x_pbc, dx); for (m = 0; m < DIM; m++) { com[m] += wm*dx[m]; } if (xp) { /* For xp add the difference between xp and x to dx, * such that we use the same periodic image, * also when xp has a large displacement. */ for (m = 0; m < DIM; m++) { comp[m] += wm*(dx[m] + xp[ii][m] - x[ii][m]); } } } } else { /* Determine cos and sin sums */ csw = cos(x[ii][pull->cosdim]*twopi_box); snw = sin(x[ii][pull->cosdim]*twopi_box); cm += csw*mass; sm += snw*mass; ccm += csw*csw*mass; csm += csw*snw*mass; ssm += snw*snw*mass; if (xp) { csw = cos(xp[ii][pull->cosdim]*twopi_box); snw = sin(xp[ii][pull->cosdim]*twopi_box); cmp += csw*mass; smp += snw*mass; } } } } /* Copy local sums to a buffer for global summing */ switch (pgrp->epgrppbc) { case epgrppbcNONE: case epgrppbcREFAT: copy_dvec(com, pull->dbuf[g*3]); copy_dvec(comp, pull->dbuf[g*3+1]); pull->dbuf[g*3+2][0] = wmass; pull->dbuf[g*3+2][1] = wwmass; pull->dbuf[g*3+2][2] = 0; break; case epgrppbcCOS: pull->dbuf[g*3 ][0] = cm; pull->dbuf[g*3 ][1] = sm; pull->dbuf[g*3 ][2] = 0; pull->dbuf[g*3+1][0] = ccm; pull->dbuf[g*3+1][1] = csm; pull->dbuf[g*3+1][2] = ssm; pull->dbuf[g*3+2][0] = cmp; pull->dbuf[g*3+2][1] = smp; pull->dbuf[g*3+2][2] = 0; break; } } if (cr && PAR(cr)) { /* Sum the contributions over the nodes */ gmx_sumd(pull->ngroup*3*DIM, pull->dbuf[0], cr); } for (g = 0; g < pull->ngroup; g++) { pgrp = &pull->group[g]; if (pgrp->nat > 0 && !(g == 0 && PULL_CYL(pull))) { if (pgrp->epgrppbc != epgrppbcCOS) { /* Determine the inverse mass */ wmass = pull->dbuf[g*3+2][0]; wwmass = pull->dbuf[g*3+2][1]; invwmass = 1/wmass; /* invtm==0 signals a frozen group, so then we should keep it zero */ if (pgrp->invtm > 0) { pgrp->wscale = wmass/wwmass; pgrp->invtm = 1.0/(pgrp->wscale*wmass); } /* Divide by the total mass */ for (m = 0; m < DIM; m++) { pgrp->x[m] = pull->dbuf[g*3 ][m]*invwmass; if (xp) { pgrp->xp[m] = pull->dbuf[g*3+1][m]*invwmass; } if (pgrp->epgrppbc == epgrppbcREFAT) { pgrp->x[m] += pull->rbuf[g][m]; if (xp) { pgrp->xp[m] += pull->rbuf[g][m]; } } } } else { /* Determine the optimal location of the cosine weight */ csw = pull->dbuf[g*3][0]; snw = pull->dbuf[g*3][1]; pgrp->x[pull->cosdim] = atan2_0_2pi(snw, csw)/twopi_box; /* Set the weights for the local atoms */ wmass = sqrt(csw*csw + snw*snw); wwmass = (pull->dbuf[g*3+1][0]*csw*csw + pull->dbuf[g*3+1][1]*csw*snw + pull->dbuf[g*3+1][2]*snw*snw)/(wmass*wmass); pgrp->wscale = wmass/wwmass; pgrp->invtm = 1.0/(pgrp->wscale*wmass); /* Set the weights for the local atoms */ csw *= pgrp->invtm; snw *= pgrp->invtm; for (i = 0; i < pgrp->nat_loc; i++) { ii = pgrp->ind_loc[i]; pgrp->weight_loc[i] = csw*cos(twopi_box*x[ii][pull->cosdim]) + snw*sin(twopi_box*x[ii][pull->cosdim]); } if (xp) { csw = pull->dbuf[g*3+2][0]; snw = pull->dbuf[g*3+2][1]; pgrp->xp[pull->cosdim] = atan2_0_2pi(snw, csw)/twopi_box; } } if (debug) { fprintf(debug, "Pull group %d wmass %f wwmass %f invtm %f\n", g, wmass, wwmass, pgrp->invtm); } } } if (PULL_CYL(pull)) { /* Calculate the COMs for the cyclinder reference groups */ make_cyl_refgrps(cr, pull, md, pbc, t, x, xp); } }
void adress_thermo_force(int start, int homenr, t_block * cgs, rvec x[], rvec f[], t_forcerec * fr, t_mdatoms * mdatoms, t_pbc * pbc) { int iatom, n0, nnn, nrcg, i; int adresstype; real adressw, adressr; atom_id * cgindex; unsigned short * ptype; rvec * ref; real * wf; real tabscale; real * ATFtab; rvec dr; real w, wsq, wmin1, wmin1sq, wp, wt, rinv, sqr_dl, dl; real eps, eps2, F, Geps, Heps2, Fp, dmu_dwp, dwp_dr, fscal; adresstype = fr->adress_type; adressw = fr->adress_hy_width; adressr = fr->adress_ex_width; cgindex = cgs->index; ptype = mdatoms->ptype; ref = &(fr->adress_refs); wf = mdatoms->wf; for (iatom = start; (iatom < start+homenr); iatom++) { if (egp_coarsegrained(fr, mdatoms->cENER[iatom])) { if (ptype[iatom] == eptVSite) { w = wf[iatom]; /* is it hybrid or apply the thermodynamics force everywhere?*/ if (mdatoms->tf_table_index[iatom] != NO_TF_TABLE) { if (fr->n_adress_tf_grps > 0) { /* multi component tf is on, select the right table */ ATFtab = fr->atf_tabs[mdatoms->tf_table_index[iatom]].data; tabscale = fr->atf_tabs[mdatoms->tf_table_index[iatom]].scale; } else { /* just on component*/ ATFtab = fr->atf_tabs[DEFAULT_TF_TABLE].data; tabscale = fr->atf_tabs[DEFAULT_TF_TABLE].scale; } fscal = 0; if (pbc) { pbc_dx(pbc, (*ref), x[iatom], dr); } else { rvec_sub((*ref), x[iatom], dr); } /* calculate distace to adress center again */ sqr_dl = 0.0; switch (adresstype) { case eAdressXSplit: /* plane through center of ref, varies in x direction */ sqr_dl = dr[0]*dr[0]; rinv = gmx_invsqrt(dr[0]*dr[0]); break; case eAdressSphere: /* point at center of ref, assuming cubic geometry */ for (i = 0; i < 3; i++) { sqr_dl += dr[i]*dr[i]; } rinv = gmx_invsqrt(sqr_dl); break; default: /* This case should not happen */ rinv = 0.0; } dl = sqrt(sqr_dl); /* table origin is adress center */ wt = dl*tabscale; n0 = wt; eps = wt-n0; eps2 = eps*eps; nnn = 4*n0; F = ATFtab[nnn+1]; Geps = eps*ATFtab[nnn+2]; Heps2 = eps2*ATFtab[nnn+3]; Fp = F+Geps+Heps2; F = (Fp+Geps+2.0*Heps2)*tabscale; fscal = F*rinv; f[iatom][0] += fscal*dr[0]; if (adresstype != eAdressXSplit) { f[iatom][1] += fscal*dr[1]; f[iatom][2] += fscal*dr[2]; } } } } } }
int force_calc_bon(t_frame pframe, t_files fpkg) { int i,j,k,l,N,ci,cj,nqi,id1,id2,id3,id4; vector *x,*v,dx,dy; t_vector distx,disty; double dr,r,r2,r6,r12,ir,ir2,ir6,ir12,E=0.0,rc2; double ar21,ar22,air21,air22,air11,air12,ang; double C6ij,C12ij,FORCE,f,df,kc,ddr,fij; double q2,dfq,fq,fe,phi,cosval,cosv2,dV; int ist,isl,ds,m; distx=&dx; disty=&dy; for(i=0;i<pframe->nr_umols;i++){ for(j=0;j<pframe->nr_mols[i];j++){ // BONDED for(k=0;k<pframe->mol[pframe->mol_seq[i]]->nr_b;k++){ id1 = j*pframe->mol[pframe->mol_seq[i]]->nr_t + pframe->mol[pframe->mol_seq[i]]->b_seq[2*k ]+pframe->n_start[i]; id2 = j*pframe->mol[pframe->mol_seq[i]]->nr_t + pframe->mol[pframe->mol_seq[i]]->b_seq[2*k+1]+pframe->n_start[i]; r2 = pbc_dx(pframe,id1,id2,dx); dr = r2*InvSqrt(r2); // BEGIN HARMONIC kc = pframe->mol[pframe->mol_seq[i]]->k_bond[2*k]; ddr = dr-pframe->mol[pframe->mol_seq[i]]->k_bond[2*k+1]; df = kc*ddr; dV = 0.5*df*ddr; // END HARMONIC E += dV; df *= InvSqrt(r2); for (m=XX; m<=ZZ; m++) { fij=-df*dx[m]; pframe->f[id1][m]+=fij; pframe->f[id2][m]-=fij; } } // ANGLES for(k=0;k<pframe->mol[pframe->mol_seq[i]]->nr_a;k++){ id1 = j*pframe->mol[pframe->mol_seq[i]]->nr_t + pframe->mol[pframe->mol_seq[i]]->a_seq[2*k ]+pframe->n_start[i]; id2 = j*pframe->mol[pframe->mol_seq[i]]->nr_t + pframe->mol[pframe->mol_seq[i]]->a_seq[2*k+1]+pframe->n_start[i]; id3 = j*pframe->mol[pframe->mol_seq[i]]->nr_t + pframe->mol[pframe->mol_seq[i]]->a_seq[2*k+2]+pframe->n_start[i]; ar21 = pbc_dx(pframe,id1,id2,dx); ar22 = pbc_dx(pframe,id3,id2,dy); phi = calc_angle(dx,dy,&cosval); cosv2 = cosval*cosval; // BEGIN HARMONIC kc = pframe->mol[pframe->mol_seq[i]]->k_angle[2*k]; ddr = phi-pframe->mol[pframe->mol_seq[i]]->k_angle[2*k+1]*DEG2RAD; df = kc*ddr; dV = 0.5*df*ddr; // END HARMONIC E += dV; if(cosv2<1){ double st,sth; double cik,cii,ckk; double nrkj2,nrij2; vector f_i,f_j,f_k; st = -df*InvSqrt(1.0 - cosv2); sth = st*cosval; nrkj2 = iprod(dy,dy); nrij2 = iprod(dx,dx); cik = st*InvSqrt(nrkj2*nrij2); cii = sth/nrij2; ckk = sth/nrkj2; for (m=XX; (m<=ZZ); m++) { f_i[m]=-(cik*dy[m]-cii*dx[m]); f_k[m]=-(cik*dx[m]-ckk*dy[m]); f_j[m]=-f_i[m]-f_k[m]; pframe->f[id1][m]+=f_i[m]; pframe->f[id2][m]+=f_j[m]; pframe->f[id3][m]+=f_k[m]; } } } // PROPER DIHEDRALS E += pdihs(pframe,i,j); // IMPROPER DIHEDRALS E += idihs(pframe,i,j); } } pframe->E[2] = E; pframe->E[0] += E; return 0; }
int gmx_dist(int argc,char *argv[]) { const char *desc[] = { "[TT]g_dist[tt] can calculate the distance between the centers of mass of two", "groups of atoms as a function of time. The total distance and its", "[IT]x[it]-, [IT]y[it]-, and [IT]z[it]-components are plotted.[PAR]", "Or when [TT]-dist[tt] is set, print all the atoms in group 2 that are", "closer than a certain distance to the center of mass of group 1.[PAR]", "With options [TT]-lt[tt] and [TT]-dist[tt] the number of contacts", "of all atoms in group 2 that are closer than a certain distance", "to the center of mass of group 1 are plotted as a function of the time", "that the contact was continuously present.[PAR]", "Other programs that calculate distances are [TT]g_mindist[tt]", "and [TT]g_bond[tt]." }; t_topology *top=NULL; int ePBC; real t,t0,cut2,dist2; rvec *x=NULL,*v=NULL,dx; matrix box; t_trxstatus *status; int natoms; int g,d,i,j,res,teller=0; atom_id aid; int ngrps; /* the number of index groups */ atom_id **index,max; /* the index for the atom numbers */ int *isize; /* the size of each group */ char **grpname; /* the name of each group */ rvec *com; real *mass; FILE *fp=NULL,*fplt=NULL; gmx_bool bCutoff,bPrintDist,bLifeTime; t_pbc *pbc; int *contact_time=NULL,*ccount=NULL,ccount_nalloc=0,sum; char buf[STRLEN]; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; const char *leg[4] = { "|d|","d\\sx\\N","d\\sy\\N","d\\sz\\N" }; static real cut=0; static t_pargs pa[] = { { "-dist", FALSE, etREAL, {&cut}, "Print all atoms in group 2 closer than dist to the center of mass of group 1" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPX, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "dist", ffOPTWR }, { efXVG, "-lt", "lifetime", ffOPTWR }, }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv); bCutoff = opt2parg_bSet("-dist",NPA,pa); cut2 = cut*cut; bLifeTime = opt2bSet("-lt",NFILE,fnm); bPrintDist = (bCutoff && !bLifeTime); top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC); /* read index files */ ngrps = 2; snew(com,ngrps); snew(grpname,ngrps); snew(index,ngrps); snew(isize,ngrps); get_index(&top->atoms,ftp2fn(efNDX,NFILE,fnm),ngrps,isize,index,grpname); /* calculate mass */ max=0; snew(mass,ngrps); for(g=0;(g<ngrps);g++) { mass[g]=0; for(i=0;(i<isize[g]);i++) { if (index[g][i]>max) max=index[g][i]; if (index[g][i] >= top->atoms.nr) gmx_fatal(FARGS,"Atom number %d, item %d of group %d, is larger than number of atoms in the topolgy (%d)\n",index[g][i]+1,i+1,g+1,top->atoms.nr+1); mass[g]+=top->atoms.atom[index[g][i]].m; } } natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); t0 = t; if (max>=natoms) gmx_fatal(FARGS,"Atom number %d in an index group is larger than number of atoms in the trajectory (%d)\n",(int)max+1,natoms); if (!bCutoff) { /* open output file */ fp = xvgropen(ftp2fn(efXVG,NFILE,fnm), "Distance","Time (ps)","Distance (nm)",oenv); xvgr_legend(fp,4,leg,oenv); } else { ngrps = 1; if (bLifeTime) snew(contact_time,isize[1]); } if (ePBC != epbcNONE) snew(pbc,1); else pbc = NULL; gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box); do { /* initialisation for correct distance calculations */ if (pbc) { set_pbc(pbc,ePBC,box); /* make molecules whole again */ gmx_rmpbc(gpbc,natoms,box,x); } /* calculate center of masses */ for(g=0;(g<ngrps);g++) { if (isize[g] == 1) { copy_rvec(x[index[g][0]],com[g]); } else { for(d=0;(d<DIM);d++) { com[g][d]=0; for(i=0;(i<isize[g]);i++) { com[g][d] += x[index[g][i]][d] * top->atoms.atom[index[g][i]].m; } com[g][d] /= mass[g]; } } } if (!bCutoff) { /* write to output */ fprintf(fp,"%12.7f ",t); for(g=0;(g<ngrps/2);g++) { if (pbc) pbc_dx(pbc,com[2*g],com[2*g+1],dx); else rvec_sub(com[2*g],com[2*g+1],dx); fprintf(fp,"%12.7f %12.7f %12.7f %12.7f", norm(dx),dx[XX],dx[YY],dx[ZZ]); } fprintf(fp,"\n"); } else { for(i=0;(i<isize[1]);i++) { j=index[1][i]; if (pbc) pbc_dx(pbc,x[j],com[0],dx); else rvec_sub(x[j],com[0],dx); dist2 = norm2(dx); if (dist2<cut2) { if (bPrintDist) { res=top->atoms.atom[j].resind; fprintf(stdout,"\rt: %g %d %s %d %s %g (nm)\n", t,top->atoms.resinfo[res].nr,*top->atoms.resinfo[res].name, j+1,*top->atoms.atomname[j],sqrt(dist2)); } if (bLifeTime) contact_time[i]++; } else { if (bLifeTime) { if (contact_time[i]) { add_contact_time(&ccount,&ccount_nalloc,contact_time[i]-1); contact_time[i] = 0; } } } } } teller++; } while (read_next_x(oenv,status,&t,natoms,x,box)); gmx_rmpbc_done(gpbc); if (!bCutoff) ffclose(fp); close_trj(status); if (bCutoff && bLifeTime) { /* Add the contacts still present in the last frame */ for(i=0; i<isize[1]; i++) if (contact_time[i]) add_contact_time(&ccount,&ccount_nalloc,contact_time[i]-1); sprintf(buf,"%s - %s within %g nm", grpname[0],grpname[1],cut); fp = xvgropen(opt2fn("-lt",NFILE,fnm), buf,"Time (ps)","Number of contacts",oenv); for(i=0; i<min(ccount_nalloc,teller-1); i++) { /* Account for all subintervals of longer intervals */ sum = 0; for(j=i; j<ccount_nalloc; j++) sum += (j-i+1)*ccount[j]; fprintf(fp,"%10.3f %10.3f\n",i*(t-t0)/(teller-1),sum/(double)(teller-i)); } ffclose(fp); } thanx(stderr); return 0; }
int gmx_densmap(int argc,char *argv[]) { const char *desc[] = { "[TT]g_densmap[tt] computes 2D number-density maps.", "It can make planar and axial-radial density maps.", "The output [TT].xpm[tt] file can be visualized with for instance xv", "and can be converted to postscript with [TT]xpm2ps[tt].", "Optionally, output can be in text form to a [TT].dat[tt] file with [TT]-od[tt], instead of the usual [TT].xpm[tt] file with [TT]-o[tt].", "[PAR]", "The default analysis is a 2-D number-density map for a selected", "group of atoms in the x-y plane.", "The averaging direction can be changed with the option [TT]-aver[tt].", "When [TT]-xmin[tt] and/or [TT]-xmax[tt] are set only atoms that are", "within the limit(s) in the averaging direction are taken into account.", "The grid spacing is set with the option [TT]-bin[tt].", "When [TT]-n1[tt] or [TT]-n2[tt] is non-zero, the grid", "size is set by this option.", "Box size fluctuations are properly taken into account.", "[PAR]", "When options [TT]-amax[tt] and [TT]-rmax[tt] are set, an axial-radial", "number-density map is made. Three groups should be supplied, the centers", "of mass of the first two groups define the axis, the third defines the", "analysis group. The axial direction goes from -amax to +amax, where", "the center is defined as the midpoint between the centers of mass and", "the positive direction goes from the first to the second center of mass.", "The radial direction goes from 0 to rmax or from -rmax to +rmax", "when the [TT]-mirror[tt] option has been set.", "[PAR]", "The normalization of the output is set with the [TT]-unit[tt] option.", "The default produces a true number density. Unit [TT]nm-2[tt] leaves out", "the normalization for the averaging or the angular direction.", "Option [TT]count[tt] produces the count for each grid cell.", "When you do not want the scale in the output to go", "from zero to the maximum density, you can set the maximum", "with the option [TT]-dmax[tt]." }; static int n1=0,n2=0; static real xmin=-1,xmax=-1,bin=0.02,dmin=0,dmax=0,amax=0,rmax=0; static gmx_bool bMirror=FALSE, bSums=FALSE; static const char *eaver[]= { NULL, "z", "y", "x", NULL }; static const char *eunit[]= { NULL, "nm-3", "nm-2", "count", NULL }; t_pargs pa[] = { { "-bin", FALSE, etREAL, {&bin}, "Grid size (nm)" }, { "-aver", FALSE, etENUM, {eaver}, "The direction to average over" }, { "-xmin", FALSE, etREAL, {&xmin}, "Minimum coordinate for averaging" }, { "-xmax", FALSE, etREAL, {&xmax}, "Maximum coordinate for averaging" }, { "-n1", FALSE, etINT, {&n1}, "Number of grid cells in the first direction" }, { "-n2", FALSE, etINT, {&n2}, "Number of grid cells in the second direction" }, { "-amax", FALSE, etREAL, {&amax}, "Maximum axial distance from the center" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum radial distance" }, { "-mirror", FALSE, etBOOL, {&bMirror}, "Add the mirror image below the axial axis" }, { "-sums", FALSE, etBOOL, {&bSums}, "Print density sums (1D map) to stdout" }, { "-unit", FALSE, etENUM, {eunit}, "Unit for the output" }, { "-dmin", FALSE, etREAL, {&dmin}, "Minimum density in output" }, { "-dmax", FALSE, etREAL, {&dmax}, "Maximum density in output (0 means calculate it)" }, }; gmx_bool bXmin,bXmax,bRadial; FILE *fp; t_trxstatus *status; t_topology top; int ePBC=-1; rvec *x,xcom[2],direction,center,dx; matrix box; real t,m,mtot; t_pbc pbc; int cav=0,c1=0,c2=0,natoms; char **grpname,title[256],buf[STRLEN]; const char *unit; int i,j,k,l,ngrps,anagrp,*gnx=NULL,nindex,nradial=0,nfr,nmpower; atom_id **ind=NULL,*index; real **grid,maxgrid,m1,m2,box1,box2,*tickx,*tickz,invcellvol; real invspa=0,invspz=0,axial,r,vol_old,vol,rowsum; int nlev=51; t_rgb rlo= {1,1,1}, rhi= {0,0,0}; output_env_t oenv; const char *label[]= { "x (nm)", "y (nm)", "z (nm)" }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-od", "densmap", ffOPTWR }, { efXPM, "-o", "densmap", ffWRITE } }; #define NFILE asize(fnm) int npargs; CopyRight(stderr,argv[0]); npargs = asize(pa); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE,fnm,npargs,pa,asize(desc),desc,0,NULL,&oenv); bXmin = opt2parg_bSet("-xmin",npargs,pa); bXmax = opt2parg_bSet("-xmax",npargs,pa); bRadial = (amax>0 || rmax>0); if (bRadial) { if (amax<=0 || rmax<=0) gmx_fatal(FARGS,"Both amax and rmax should be larger than zero"); } if (strcmp(eunit[0],"nm-3") == 0) { nmpower = -3; unit = "(nm^-3)"; } else if (strcmp(eunit[0],"nm-2") == 0) { nmpower = -2; unit = "(nm^-2)"; } else { nmpower = 0; unit = "count"; } if (ftp2bSet(efTPS,NFILE,fnm) || !ftp2bSet(efNDX,NFILE,fnm)) read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box, bRadial); if (!bRadial) { ngrps = 1; fprintf(stderr,"\nSelect an analysis group\n"); } else { ngrps = 3; fprintf(stderr, "\nSelect two groups to define the axis and an analysis group\n"); } snew(gnx,ngrps); snew(grpname,ngrps); snew(ind,ngrps); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),ngrps,gnx,ind,grpname); anagrp = ngrps - 1; nindex = gnx[anagrp]; index = ind[anagrp]; if (bRadial) { if ((gnx[0]>1 || gnx[1]>1) && !ftp2bSet(efTPS,NFILE,fnm)) gmx_fatal(FARGS,"No run input file was supplied (option -s), this is required for the center of mass calculation"); } switch (eaver[0][0]) { case 'x': cav = XX; c1 = YY; c2 = ZZ; break; case 'y': cav = YY; c1 = XX; c2 = ZZ; break; case 'z': cav = ZZ; c1 = XX; c2 = YY; break; } natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (!bRadial) { if (n1 == 0) n1 = (int)(box[c1][c1]/bin + 0.5); if (n2 == 0) n2 = (int)(box[c2][c2]/bin + 0.5); } else { n1 = (int)(2*amax/bin + 0.5); nradial = (int)(rmax/bin + 0.5); invspa = n1/(2*amax); invspz = nradial/rmax; if (bMirror) n2 = 2*nradial; else n2 = nradial; } snew(grid,n1); for(i=0; i<n1; i++) snew(grid[i],n2); box1 = 0; box2 = 0; nfr = 0; do { if (!bRadial) { box1 += box[c1][c1]; box2 += box[c2][c2]; invcellvol = n1*n2; if (nmpower == -3) invcellvol /= det(box); else if (nmpower == -2) invcellvol /= box[c1][c1]*box[c2][c2]; for(i=0; i<nindex; i++) { j = index[i]; if ((!bXmin || x[j][cav] >= xmin) && (!bXmax || x[j][cav] <= xmax)) { m1 = x[j][c1]/box[c1][c1]; if (m1 >= 1) m1 -= 1; if (m1 < 0) m1 += 1; m2 = x[j][c2]/box[c2][c2]; if (m2 >= 1) m2 -= 1; if (m2 < 0) m2 += 1; grid[(int)(m1*n1)][(int)(m2*n2)] += invcellvol; } } } else { set_pbc(&pbc,ePBC,box); for(i=0; i<2; i++) { if (gnx[i] == 1) { /* One atom, just copy the coordinates */ copy_rvec(x[ind[i][0]],xcom[i]); } else { /* Calculate the center of mass */ clear_rvec(xcom[i]); mtot = 0; for(j=0; j<gnx[i]; j++) { k = ind[i][j]; m = top.atoms.atom[k].m; for(l=0; l<DIM; l++) xcom[i][l] += m*x[k][l]; mtot += m; } svmul(1/mtot,xcom[i],xcom[i]); } } pbc_dx(&pbc,xcom[1],xcom[0],direction); for(i=0; i<DIM; i++) center[i] = xcom[0][i] + 0.5*direction[i]; unitv(direction,direction); for(i=0; i<nindex; i++) { j = index[i]; pbc_dx(&pbc,x[j],center,dx); axial = iprod(dx,direction); r = sqrt(norm2(dx) - axial*axial); if (axial>=-amax && axial<amax && r<rmax) { if (bMirror) r += rmax; grid[(int)((axial + amax)*invspa)][(int)(r*invspz)] += 1; } } } nfr++; } while(read_next_x(oenv,status,&t,natoms,x,box)); close_trj(status); /* normalize gridpoints */ maxgrid = 0; if (!bRadial) { for (i=0; i<n1; i++) { for (j=0; j<n2; j++) { grid[i][j] /= nfr; if (grid[i][j] > maxgrid) maxgrid = grid[i][j]; } } } else { for (i=0; i<n1; i++) { vol_old = 0; for (j=0; j<nradial; j++) { switch (nmpower) { case -3: vol = M_PI*(j+1)*(j+1)/(invspz*invspz*invspa); break; case -2: vol = (j+1)/(invspz*invspa); break; default: vol = j+1; break; } if (bMirror) k = j + nradial; else k = j; grid[i][k] /= nfr*(vol - vol_old); if (bMirror) grid[i][nradial-1-j] = grid[i][k]; vol_old = vol; if (grid[i][k] > maxgrid) maxgrid = grid[i][k]; } } } fprintf(stdout,"\n The maximum density is %f %s\n",maxgrid,unit); if (dmax > 0) maxgrid = dmax; snew(tickx,n1+1); snew(tickz,n2+1); if (!bRadial) { /* normalize box-axes */ box1 /= nfr; box2 /= nfr; for (i=0; i<=n1; i++) tickx[i] = i*box1/n1; for (i=0; i<=n2; i++) tickz[i] = i*box2/n2; } else { for (i=0; i<=n1; i++) tickx[i] = i/invspa - amax; if (bMirror) { for (i=0; i<=n2; i++) tickz[i] = i/invspz - rmax; } else { for (i=0; i<=n2; i++) tickz[i] = i/invspz; } } if (bSums) { for (i=0; i<n1; ++i) { fprintf(stdout,"Density sums:\n"); rowsum=0; for (j=0; j<n2; ++j) rowsum+=grid[i][j]; fprintf(stdout,"%g\t",rowsum); } fprintf(stdout,"\n"); } sprintf(buf,"%s number density",grpname[anagrp]); if (!bRadial && (bXmin || bXmax)) { if (!bXmax) sprintf(buf+strlen(buf),", %c > %g nm",eaver[0][0],xmin); else if (!bXmin) sprintf(buf+strlen(buf),", %c < %g nm",eaver[0][0],xmax); else sprintf(buf+strlen(buf),", %c: %g - %g nm",eaver[0][0],xmin,xmax); } if (ftp2bSet(efDAT,NFILE,fnm)) { fp = ffopen(ftp2fn(efDAT,NFILE,fnm),"w"); /*optional text form output: first row is tickz; first col is tickx */ fprintf(fp,"0\t"); for(j=0; j<n2; ++j) fprintf(fp,"%g\t",tickz[j]); fprintf(fp,"\n"); for (i=0; i<n1; ++i) { fprintf(fp,"%g\t",tickx[i]); for (j=0; j<n2; ++j) fprintf(fp,"%g\t",grid[i][j]); fprintf(fp,"\n"); } ffclose(fp); } else { fp = ffopen(ftp2fn(efXPM,NFILE,fnm),"w"); write_xpm(fp,MAT_SPATIAL_X | MAT_SPATIAL_Y,buf,unit, bRadial ? "axial (nm)" : label[c1],bRadial ? "r (nm)" : label[c2], n1,n2,tickx,tickz,grid,dmin,maxgrid,rlo,rhi,&nlev); ffclose(fp); } thanx(stderr); do_view(oenv,opt2fn("-o",NFILE,fnm),NULL); return 0; }
/* calculate the angle and distance between the two groups */ static void calc_angle(int ePBC,matrix box,rvec x[], atom_id index1[], atom_id index2[], int gnx1, int gnx2, real *angle, real *distance, real *distance1, real *distance2) /* distance is distance between centers, distance 1 between center of plane and atom one of vector, distance 2 same for atom two */ { rvec normal1,normal2, /* normals on planes of interest */ center1,center2, /* center of triangle of points given to define plane,*/ /* or center of vector if a vector is given */ h1,h2,h3,h4,h5; /* temp. vectors */ t_pbc pbc; set_pbc(&pbc,ePBC,box); switch(gnx1) { case 3: /* group 1 defines plane */ calculate_normal(index1,x,normal1,center1); break; case 2: /* group 1 defines vector */ rvec_sub(x[index1[0]],x[index1[1]],normal1); rvec_add(x[index1[0]],x[index1[1]],h1); svmul(0.5,h1,center1); /* center is geometric mean */ break; default: /* group 1 does none of the above */ gmx_fatal(FARGS,"Something wrong with contents of index file.\n"); } switch(gnx2) { case 3: /* group 2 defines plane */ calculate_normal(index2,x,normal2,center2); break; case 2: /* group 2 defines vector */ rvec_sub(x[index2[0]],x[index2[1]],normal2); rvec_add(x[index2[0]],x[index2[1]],h2); svmul(0.5,h2,center2); /* center is geometric mean */ break; case 0: normal2[XX] = 0; normal2[YY] = 0; normal2[ZZ] = 1; center2[XX] = 0; center2[YY] = 0; center2[ZZ] = 0; break; default: /* group 2 does none of the above */ gmx_fatal(FARGS,"Something wrong with contents of index file.\n"); } *angle = cos_angle(normal1,normal2); if (box) pbc_dx(&pbc,center1,center2,h3); else rvec_sub(center1,center2,h3); *distance = norm(h3); if (gnx1 == 3 && gnx2 == 2) { if (box) { pbc_dx(&pbc,center1,x[index2[0]],h4); pbc_dx(&pbc,center1,x[index2[1]],h5); } else { rvec_sub(center1,x[index2[0]],h4); rvec_sub(center1,x[index2[1]],h5); } *distance1 = norm(h4); *distance2 = norm(h5); } else if (gnx1 == 2 && gnx2 ==3) { rvec_sub(center1,x[index1[0]],h4); rvec_sub(center1,x[index1[1]],h5); *distance1 = norm(h4); *distance2 = norm(h5); } else { *distance1 = 0; *distance2 = 0; } }
void chk_tps(const char *fn, real vdw_fac, real bon_lo, real bon_hi) { int natom, i, j, k; char title[STRLEN]; t_topology top; int ePBC; t_atoms *atoms; rvec *x, *v; rvec dx; matrix box; t_pbc pbc; gmx_bool bV, bX, bB, bFirst, bOut; real r2, ekin, temp1, temp2, dist2, vdwfac2, bonlo2, bonhi2; real *atom_vdw; gmx_atomprop_t aps; fprintf(stderr, "Checking coordinate file %s\n", fn); read_tps_conf(fn, title, &top, &ePBC, &x, &v, box, TRUE); atoms = &top.atoms; natom = atoms->nr; fprintf(stderr, "%d atoms in file\n", atoms->nr); /* check coordinates and box */ bV = FALSE; bX = FALSE; for (i = 0; (i < natom) && !(bV && bX); i++) { for (j = 0; (j < DIM) && !(bV && bX); j++) { bV = bV || (v[i][j] != 0); bX = bX || (x[i][j] != 0); } } bB = FALSE; for (i = 0; (i < DIM) && !bB; i++) { for (j = 0; (j < DIM) && !bB; j++) { bB = bB || (box[i][j] != 0); } } fprintf(stderr, "coordinates %s\n", bX ? "found" : "absent"); fprintf(stderr, "box %s\n", bB ? "found" : "absent"); fprintf(stderr, "velocities %s\n", bV ? "found" : "absent"); fprintf(stderr, "\n"); /* check velocities */ if (bV) { ekin = 0.0; for (i = 0; (i < natom); i++) { for (j = 0; (j < DIM); j++) { ekin += 0.5*atoms->atom[i].m*v[i][j]*v[i][j]; } } temp1 = (2.0*ekin)/(natom*DIM*BOLTZ); temp2 = (2.0*ekin)/(natom*(DIM-1)*BOLTZ); fprintf(stderr, "Kinetic energy: %g (kJ/mol)\n", ekin); fprintf(stderr, "Assuming the number of degrees of freedom to be " "Natoms * %d or Natoms * %d,\n" "the velocities correspond to a temperature of the system\n" "of %g K or %g K respectively.\n\n", DIM, DIM-1, temp1, temp2); } /* check coordinates */ if (bX) { vdwfac2 = sqr(vdw_fac); bonlo2 = sqr(bon_lo); bonhi2 = sqr(bon_hi); fprintf(stderr, "Checking for atoms closer than %g and not between %g and %g,\n" "relative to sum of Van der Waals distance:\n", vdw_fac, bon_lo, bon_hi); snew(atom_vdw, natom); aps = gmx_atomprop_init(); for (i = 0; (i < natom); i++) { gmx_atomprop_query(aps, epropVDW, *(atoms->resinfo[atoms->atom[i].resind].name), *(atoms->atomname[i]), &(atom_vdw[i])); if (debug) { fprintf(debug, "%5d %4s %4s %7g\n", i+1, *(atoms->resinfo[atoms->atom[i].resind].name), *(atoms->atomname[i]), atom_vdw[i]); } } gmx_atomprop_destroy(aps); if (bB) { set_pbc(&pbc, ePBC, box); } bFirst = TRUE; for (i = 0; (i < natom); i++) { if (((i+1)%10) == 0) { fprintf(stderr, "\r%5d", i+1); } for (j = i+1; (j < natom); j++) { if (bB) { pbc_dx(&pbc, x[i], x[j], dx); } else { rvec_sub(x[i], x[j], dx); } r2 = iprod(dx, dx); dist2 = sqr(atom_vdw[i]+atom_vdw[j]); if ( (r2 <= dist2*bonlo2) || ( (r2 >= dist2*bonhi2) && (r2 <= dist2*vdwfac2) ) ) { if (bFirst) { fprintf(stderr, "\r%5s %4s %8s %5s %5s %4s %8s %5s %6s\n", "atom#", "name", "residue", "r_vdw", "atom#", "name", "residue", "r_vdw", "distance"); bFirst = FALSE; } fprintf(stderr, "\r%5d %4s %4s%4d %-5.3g %5d %4s %4s%4d %-5.3g %-6.4g\n", i+1, *(atoms->atomname[i]), *(atoms->resinfo[atoms->atom[i].resind].name), atoms->resinfo[atoms->atom[i].resind].nr, atom_vdw[i], j+1, *(atoms->atomname[j]), *(atoms->resinfo[atoms->atom[j].resind].name), atoms->resinfo[atoms->atom[j].resind].nr, atom_vdw[j], sqrt(r2) ); } } } if (bFirst) { fprintf(stderr, "\rno close atoms found\n"); } fprintf(stderr, "\r \n"); if (bB) { /* check box */ bFirst = TRUE; k = 0; for (i = 0; (i < natom) && (k < 10); i++) { bOut = FALSE; for (j = 0; (j < DIM) && !bOut; j++) { bOut = bOut || (x[i][j] < 0) || (x[i][j] > box[j][j]); } if (bOut) { k++; if (bFirst) { fprintf(stderr, "Atoms outside box ( "); for (j = 0; (j < DIM); j++) { fprintf(stderr, "%g ", box[j][j]); } fprintf(stderr, "):\n" "(These may occur often and are normally not a problem)\n" "%5s %4s %8s %5s %s\n", "atom#", "name", "residue", "r_vdw", "coordinate"); bFirst = FALSE; } fprintf(stderr, "%5d %4s %4s%4d %-5.3g", i, *(atoms->atomname[i]), *(atoms->resinfo[atoms->atom[i].resind].name), atoms->resinfo[atoms->atom[i].resind].nr, atom_vdw[i]); for (j = 0; (j < DIM); j++) { fprintf(stderr, " %6.3g", x[i][j]); } fprintf(stderr, "\n"); } } if (k == 10) { fprintf(stderr, "(maybe more)\n"); } if (bFirst) { fprintf(stderr, "no atoms found outside box\n"); } fprintf(stderr, "\n"); } } }
int force_calc_nb(t_frame pframe, t_files fpkg) { int i,j,k,N,ci,cj,nqi; vector *x,*v,distx; double dr,r,r2,r6,r12,ir,ir2,ir6,ir12,E=0.0,rc2; double C6ij,C12ij,FORCE,f,df; double q2,dfq,fq,fe; int ui,uj,mi,mj,ip,jp; N = pframe->nr_parts; pframe->virial = 0.0; rc2 = pframe->rc2; nqi = pframe->nr_unique; for(i=0;i<N;i++){ for(j=i+1;j<N;j++){ mi = pframe->resnr [i]; ui = pframe->restyp[i]; mj = pframe->resnr [j]; uj = pframe->restyp[j]; if( (mi==mj && ui==uj) ) continue; r2 = pbc_dx(pframe,i,j,distx); if( r2>rc2 ) //if outside cutoff or same residue continue; ir2 = 1.0/r2; ci = pframe->partyp_key[pframe->partyp[i]]; cj = pframe->partyp_key[pframe->partyp[j]]; if(pframe->C6 [ci*nqi+cj] > 0 && pframe->C12[ci*nqi+cj]>0){ ir6 = ir2*ir2*ir2; ir12 = ir6*ir6; C6ij = pframe->C6 [ci*nqi+cj]*ir6; C12ij= pframe->C12[ci*nqi+cj]*ir12; E += C12ij-C6ij; df = (12.0*C12ij - 6.0*C6ij); f = df*ir2; for(k=XX;k<=ZZ;k++){ FORCE = f * distx[k] ; pframe->f[i][k] += FORCE; pframe->f[j][k] -= FORCE; } } if( pframe->Q [ci*nqi+cj] != 0.0 ){ ir = InvSqrt(r2); fe = ELUNIT*pframe->Q[ci*nqi+cj]*ir; E += fe; f = fe*ir2; for(k=XX;k<=ZZ;k++){ FORCE = f * distx[k] ; pframe->f[i][k] += FORCE; pframe->f[j][k] -= FORCE; } } } } if(!isfinite(E)) fatal("NAN ENERGY"); pframe->E[1]=E; return 0; }