Beispiel #1
0
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;
}
Beispiel #2
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);
}