int inputrec2nboundeddim(t_inputrec *ir) { if (ir->nwall == 2 && ir->ePBC == epbcXY) { return 3; } else { return ePBC2npbcdim(ir->ePBC); } }
t_grid *init_grid(FILE *fplog, t_forcerec *fr) { int d, m; char *ptr; t_grid *grid; snew(grid, 1); grid->npbcdim = ePBC2npbcdim(fr->ePBC); if (fr->ePBC == epbcXY && fr->nwall == 2) { grid->nboundeddim = 3; } else { grid->nboundeddim = grid->npbcdim; } if (debug) { fprintf(debug, "The coordinates are bounded in %d dimensions\n", grid->nboundeddim); } /* The ideal number of cg's per ns grid cell seems to be 10 */ grid->ncg_ideal = 10; ptr = getenv("GMX_NSCELL_NCG"); if (ptr) { sscanf(ptr, "%d", &grid->ncg_ideal); if (fplog) { fprintf(fplog, "Set ncg_ideal to %d\n", grid->ncg_ideal); } if (grid->ncg_ideal <= 0) { gmx_fatal(FARGS, "The number of cg's per cell should be > 0"); } } if (debug) { fprintf(debug, "Set ncg_ideal to %d\n", grid->ncg_ideal); } return grid; }
static void low_set_ddbox(t_inputrec *ir, ivec *dd_nc, matrix box, gmx_bool bCalcUnboundedSize, int ncg, t_block *cgs, rvec *x, t_commrec *cr_sum, gmx_ddbox_t *ddbox) { rvec av, stddev; real b0, b1; int d; ddbox->npbcdim = ePBC2npbcdim(ir->ePBC); ddbox->nboundeddim = inputrec2nboundeddim(ir); for (d = 0; d < ddbox->nboundeddim; d++) { ddbox->box0[d] = 0; ddbox->box_size[d] = box[d][d]; } if (ddbox->nboundeddim < DIM && bCalcUnboundedSize) { calc_cgcm_av_stddev(cgs, ncg, x, av, stddev, cr_sum); /* GRID_STDDEV_FAC * stddev * gives a uniform load for a rectangular block of cg's. * For a sphere it is not a bad approximation for 4x1x1 up to 4x2x2. */ for (d = ddbox->nboundeddim; d < DIM; d++) { b0 = av[d] - GRID_STDDEV_FAC*stddev[d]; b1 = av[d] + GRID_STDDEV_FAC*stddev[d]; if (debug) { fprintf(debug, "Setting global DD grid boundaries to %f - %f\n", b0, b1); } ddbox->box0[d] = b0; ddbox->box_size[d] = b1 - b0; } } set_tric_dir(dd_nc, ddbox, box); }
static void read_posres(gmx_mtop_t *mtop,t_molinfo *molinfo,bool bTopB, char *fn, int rc_scaling, int ePBC, rvec com) { bool bFirst = TRUE; rvec *x,*v,*xp; dvec sum; double totmass; t_atoms dumat; matrix box,invbox; int natoms,npbcdim=0; char title[STRLEN]; int a,i,ai,j,k,mb,nat_molb; gmx_molblock_t *molb; t_params *pr; t_atom *atom; get_stx_coordnum(fn,&natoms); if (natoms != mtop->natoms) { sprintf(warn_buf,"The number of atoms in %s (%d) does not match the number of atoms in the topology (%d). Will assume that the first %d atoms in the topology and %s match.",fn,natoms,mtop->natoms,min(mtop->natoms,natoms),fn); warning(NULL); } snew(x,natoms); snew(v,natoms); init_t_atoms(&dumat,natoms,FALSE); read_stx_conf(fn,title,&dumat,x,v,NULL,box); npbcdim = ePBC2npbcdim(ePBC); clear_rvec(com); if (rc_scaling != erscNO) { copy_mat(box,invbox); for(j=npbcdim; j<DIM; j++) { clear_rvec(invbox[j]); invbox[j][j] = 1; } m_inv_ur0(invbox,invbox); } /* Copy the reference coordinates to mtop */ clear_dvec(sum); totmass = 0; a = 0; for(mb=0; mb<mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr; pr = &(molinfo[molb->type].plist[F_POSRES]); if (pr->nr > 0) { atom = mtop->moltype[molb->type].atoms.atom; for(i=0; (i<pr->nr); i++) { ai=pr->param[i].AI; if (ai >= natoms) { gmx_fatal(FARGS,"Position restraint atom index (%d) in moltype '%s' is larger than number of atoms in %s (%d).\n", ai+1,*molinfo[molb->type].name,fn,natoms); } if (rc_scaling == erscCOM) { /* Determine the center of mass of the posres reference coordinates */ for(j=0; j<npbcdim; j++) { sum[j] += atom[ai].m*x[a+ai][j]; } totmass += atom[ai].m; } } if (!bTopB) { molb->nposres_xA = nat_molb; snew(molb->posres_xA,molb->nposres_xA); for(i=0; i<nat_molb; i++) { copy_rvec(x[a+i],molb->posres_xA[i]); } } else { molb->nposres_xB = nat_molb; snew(molb->posres_xB,molb->nposres_xB); for(i=0; i<nat_molb; i++) { copy_rvec(x[a+i],molb->posres_xB[i]); } } } a += nat_molb; } if (rc_scaling == erscCOM) { if (totmass == 0) gmx_fatal(FARGS,"The total mass of the position restraint atoms is 0"); for(j=0; j<npbcdim; j++) com[j] = sum[j]/totmass; fprintf(stderr,"The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f\n",com[XX],com[YY],com[ZZ]); } if (rc_scaling != erscNO) { for(mb=0; mb<mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr; if (molb->nposres_xA > 0 || molb->nposres_xB > 0) { xp = (!bTopB ? molb->posres_xA : molb->posres_xB); for(i=0; i<nat_molb; i++) { for(j=0; j<npbcdim; j++) { if (rc_scaling == erscALL) { /* Convert from Cartesian to crystal coordinates */ xp[i][j] *= invbox[j][j]; for(k=j+1; k<npbcdim; k++) { xp[i][j] += invbox[k][j]*xp[i][k]; } } else if (rc_scaling == erscCOM) { /* Subtract the center of mass */ xp[i][j] -= com[j]; } } } } } if (rc_scaling == erscCOM) { /* Convert the COM from Cartesian to crystal coordinates */ for(j=0; j<npbcdim; j++) { com[j] *= invbox[j][j]; for(k=j+1; k<npbcdim; k++) { com[j] += invbox[k][j]*com[k]; } } } } free_t_atoms(&dumat,TRUE); sfree(x); sfree(v); }
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]); } } } } } } } } }
//! 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]); } } } } } } } } } } }