int main(int argc,char *argv[]) { t_forcerec *fr; rvec box; fr=mk_forcerec(); fr->r1 = 0.6; fr->rc = 0.9; fr->eeltype = eelTWIN; box[XX]=box[YY]=box[ZZ]=1.0; set_shift_consts(stdout,fr->r1,fr->rc,box,fr); make_tables(fr); return 0; }
void init_forcerec(FILE *fp, t_forcerec *fr, t_inputrec *ir, t_topology *top, t_commrec *cr, t_mdatoms *mdatoms, t_nsborder *nsb, matrix box, bool bMolEpot, char *tabfn, bool bNoSolvOpt) { int i,j,m,natoms,ngrp,tabelemsize; real q,zsq,nrdf,T; rvec box_size; double rtab; t_block *mols,*cgs; t_idef *idef; if (check_box(box)) fatal_error(0,check_box(box)); cgs = &(top->blocks[ebCGS]); mols = &(top->blocks[ebMOLS]); idef = &(top->idef); natoms = mdatoms->nr; /* Shell stuff */ fr->fc_stepsize = ir->fc_stepsize; /* Free energy */ fr->efep = ir->efep; fr->sc_alpha = ir->sc_alpha; fr->sc_sigma6 = pow(ir->sc_sigma,6); /* Neighbour searching stuff */ fr->bGrid = (ir->ns_type == ensGRID); fr->ndelta = ir->ndelta; fr->ePBC = ir->ePBC; fr->rlist = ir->rlist; fr->rlistlong = max(ir->rlist,max(ir->rcoulomb,ir->rvdw)); fr->eeltype = ir->coulombtype; fr->vdwtype = ir->vdwtype; fr->bTwinRange = fr->rlistlong > fr->rlist; fr->bEwald = fr->eeltype==eelPME || fr->eeltype==eelEWALD; fr->bvdwtab = fr->vdwtype != evdwCUT; fr->bRF = (fr->eeltype==eelRF || fr->eeltype==eelGRF) && fr->vdwtype==evdwCUT; fr->bcoultab = (fr->eeltype!=eelCUT && !fr->bRF) || fr->bEwald; #ifndef SPEC_CPU if (getenv("GMX_FORCE_TABLES")) { fr->bvdwtab = TRUE; fr->bcoultab = TRUE; } #endif if (fp) { fprintf(fp,"Table routines are used for coulomb: %s\n",bool_names[fr->bcoultab]); fprintf(fp,"Table routines are used for vdw: %s\n",bool_names[fr->bvdwtab ]); } /* Tables are used for direct ewald sum */ if(fr->bEwald) { fr->ewaldcoeff=calc_ewaldcoeff(ir->rcoulomb, ir->ewald_rtol); if (fp) fprintf(fp,"Using a Gaussian width (1/beta) of %g nm for Ewald\n", 1/fr->ewaldcoeff); } /* Domain decomposition parallellism... */ fr->bDomDecomp = ir->bDomDecomp; fr->Dimension = ir->decomp_dir; /* Electrostatics */ fr->epsilon_r = ir->epsilon_r; fr->fudgeQQ = ir->fudgeQQ; fr->rcoulomb_switch = ir->rcoulomb_switch; fr->rcoulomb = ir->rcoulomb; #ifndef SPEC_CPU if (bNoSolvOpt || getenv("GMX_NO_SOLV_OPT")) fr->bSolvOpt = FALSE; else #endif fr->bSolvOpt = TRUE; /* Parameters for generalized RF */ fr->zsquare = 0.0; fr->temp = 0.0; if (fr->eeltype == eelGRF) { zsq = 0.0; for (i=0; (i<cgs->nr); i++) { q = 0; for(j=cgs->index[i]; (j<cgs->index[i+1]); j++) q+=mdatoms->chargeT[cgs->a[j]]; if (fabs(q) > GMX_REAL_MIN) /* Changed from square to fabs 990314 DvdS * Does not make a difference for monovalent ions, but doe for * divalent ions (Ca2+!!) */ zsq += fabs(q); } fr->zsquare = zsq; T = 0.0; nrdf = 0.0; for(i=0; (i<ir->opts.ngtc); i++) { nrdf += ir->opts.nrdf[i]; T += (ir->opts.nrdf[i] * ir->opts.ref_t[i]); } if (nrdf < GMX_REAL_MIN) fatal_error(0,"No degrees of freedom!"); fr->temp = T/nrdf; } else if (EEL_LR(fr->eeltype) || (fr->eeltype == eelSHIFT) || (fr->eeltype == eelUSER) || (fr->eeltype == eelSWITCH)) { /* We must use the long range cut-off for neighboursearching... * An extra range of e.g. 0.1 nm (half the size of a charge group) * is necessary for neighboursearching. This allows diffusion * into the cut-off range (between neighborlist updates), * and gives more accurate forces because all atoms within the short-range * cut-off rc must be taken into account, while the ns criterium takes * only those with the center of geometry within the cut-off. * (therefore we have to add half the size of a charge group, plus * something to account for diffusion if we have nstlist > 1) */ for(m=0; (m<DIM); m++) box_size[m]=box[m][m]; if (fr->phi == NULL) snew(fr->phi,mdatoms->nr); if ((fr->eeltype==eelPPPM) || (fr->eeltype==eelPOISSON) || (fr->eeltype == eelSHIFT && fr->rcoulomb > fr->rcoulomb_switch)) set_shift_consts(fp,fr->rcoulomb_switch,fr->rcoulomb,box_size,fr); } /* Initiate arrays */ if (fr->bTwinRange) { snew(fr->f_twin,natoms); snew(fr->fshift_twin,SHIFTS); } if (EEL_LR(fr->eeltype)) { snew(fr->f_pme,natoms); } /* Mask that says whether or not this NBF list should be computed */ /* if (fr->bMask == NULL) { ngrp = ir->opts.ngener*ir->opts.ngener; snew(fr->bMask,ngrp);*/ /* Defaults to always */ /* for(i=0; (i<ngrp); i++) fr->bMask[i] = TRUE; }*/ if (fr->cg_cm == NULL) snew(fr->cg_cm,cgs->nr); if (fr->shift_vec == NULL) snew(fr->shift_vec,SHIFTS); if (fr->fshift == NULL) snew(fr->fshift,SHIFTS); if (bMolEpot && (fr->nmol==0)) { fr->nmol=mols->nr; fr->mol_nr=make_invblock(mols,natoms); snew(fr->mol_epot,fr->nmol); fr->nstcalc=ir->nstenergy; } if (fr->nbfp == NULL) { fr->ntype = idef->atnr; fr->bBHAM = (idef->functype[0] == F_BHAM); fr->nbfp = mk_nbfp(idef,fr->bBHAM); } /* Copy the energy group exclusions */ fr->eg_excl = ir->opts.eg_excl; /* Van der Waals stuff */ fr->rvdw = ir->rvdw; fr->rvdw_switch = ir->rvdw_switch; if ((fr->vdwtype != evdwCUT) && (fr->vdwtype != evdwUSER) && !fr->bBHAM) { if (fr->rvdw_switch >= fr->rvdw) fatal_error(0,"rvdw_switch (%g) must be < rvdw (%g)", fr->rvdw_switch,fr->rvdw); if (fp) fprintf(fp,"Using %s Lennard-Jones, switch between %g and %g nm\n", (fr->eeltype==eelSWITCH) ? "switched":"shifted", fr->rvdw_switch,fr->rvdw); } if (fp) fprintf(fp,"Cut-off's: NS: %g Coulomb: %g %s: %g\n", fr->rlist,fr->rcoulomb,fr->bBHAM ? "BHAM":"LJ",fr->rvdw); if (ir->eDispCorr != edispcNO) set_avcsix(fp,fr,mdatoms); if (fr->bBHAM) set_bham_b_max(fp,fr,mdatoms); /* Now update the rest of the vars */ update_forcerec(fp,fr,box); /* if we are using LR electrostatics, and they are tabulated, * the tables will contain shifted coulomb interactions. * Since we want to use the non-shifted ones for 1-4 * coulombic interactions, we must have an extra set of * tables. This should be done in tables.c, instead of this * ugly hack, but it works for now... */ #define MAX_14_DIST 1.0 /* Shell to account for the maximum chargegroup radius (2*0.2 nm) * * and diffusion during nstlist steps (0.2 nm) */ #define TAB_EXT 0.6 /* Construct tables. * A little unnecessary to make both vdw and coul tables sometimes, * but what the heck... */ if (fr->bcoultab || fr->bvdwtab) { if (EEL_LR(fr->eeltype)) { bool bcoulsave,bvdwsave; /* generate extra tables for 1-4 interactions only * fake the forcerec so make_tables thinks it should * just create the non shifted version */ bcoulsave=fr->bcoultab; bvdwsave=fr->bvdwtab; fr->bcoultab=FALSE; fr->bvdwtab=FALSE; fr->rtab=MAX_14_DIST; make_tables(fp,fr,MASTER(cr),tabfn); fr->bcoultab=bcoulsave; fr->bvdwtab=bvdwsave; fr->coulvdw14tab=fr->coulvdwtab; fr->coulvdwtab=NULL; } fr->rtab = max(fr->rlistlong+TAB_EXT,MAX_14_DIST); } else if (fr->efep != efepNO) { if (fr->rlistlong < GMX_REAL_MIN) { char *ptr,*envvar="FEP_TABLE_LENGTH"; fr->rtab = 5; #ifdef SPEC_CPU ptr = NULL; #else ptr = getenv(envvar); #endif if (ptr) { sscanf(ptr,"%lf",&rtab); fr->rtab = rtab; } if (fp) fprintf(fp,"\nNote: Setting the free energy table length to %g nm\n" " You can set this value with the environment variable %s" "\n\n",fr->rtab,envvar); } else fr->rtab = max(fr->rlistlong+TAB_EXT,MAX_14_DIST); } else fr->rtab = MAX_14_DIST; /* make tables for ordinary interactions */ make_tables(fp,fr,MASTER(cr),tabfn); if(!(EEL_LR(fr->eeltype) && (fr->bcoultab || fr->bvdwtab))) fr->coulvdw14tab=fr->coulvdwtab; /* Copy the contents of the table to separate coulomb and LJ * tables too, to improve cache performance. */ tabelemsize=fr->bBHAM ? 16 : 12; snew(fr->coultab,4*(fr->ntab+1)*sizeof(real)); snew(fr->vdwtab,(tabelemsize-4)*(fr->ntab+1)*sizeof(real)); for(i=0; i<=fr->ntab; i++) { for(j=0; j<4; j++) fr->coultab[4*i+j]=fr->coulvdwtab[tabelemsize*i+j]; for(j=0; j<tabelemsize-4; j++) fr->vdwtab[(tabelemsize-4)*i+j]=fr->coulvdwtab[tabelemsize*i+4+j]; } if (!fr->mno_index) check_solvent(fp,top,fr,mdatoms,nsb); }