Exemplo n.º 1
0
void do_pbc_first(FILE *fplog,matrix box,t_forcerec *fr,
		  t_graph *graph,rvec x[])
{
  if (fplog)
    fprintf(fplog,"Removing pbc first time\n");
  calc_shifts(box,fr->shift_vec);
  if (graph) {
    mk_mshift(fplog,graph,fr->ePBC,box,x);
    if (gmx_debug_at)
      p_graph(debug,"do_pbc_first 1",graph);
    shift_self(graph,box,x);
    /* By doing an extra mk_mshift the molecules that are broken
     * because they were e.g. imported from another software
     * will be made whole again. Such are the healing powers
     * of GROMACS.
     */
    mk_mshift(fplog,graph,fr->ePBC,box,x);
    if (gmx_debug_at)
      p_graph(debug,"do_pbc_first 2",graph);
  }
  if (fplog)
    fprintf(fplog,"Done rmpbc\n");
}
Exemplo n.º 2
0
void mk_graph_ilist(FILE *fplog,
                    const t_ilist *ilist, int at_start, int at_end,
                    gmx_bool bShakeOnly, gmx_bool bSettle,
                    t_graph *g)
{
    int        *nbond;
    int         i, nbtot;
    gmx_bool    bMultiPart;

    /* The naming is somewhat confusing, but we need g->at0 and g->at1
     * for shifthing coordinates to a new array (not in place) when
     * some atoms are not connected by the graph, which runs from
     * g->at_start (>= g->at0) to g->at_end (<= g->at1).
     */
    g->at0 = at_start;
    g->at1 = at_end;

    snew(nbond, at_end);
    nbtot = calc_start_end(fplog, g, ilist, at_start, at_end, nbond);

    if (g->at_start >= g->at_end)
    {
        g->at_start = at_start;
        g->at_end   = at_end;
        g->nnodes   = 0;
        g->nbound   = 0;
    }
    else
    {
        g->nnodes = g->at_end - g->at_start;
        snew(g->nedge, g->nnodes);
        snew(g->edge, g->nnodes);
        /* Allocate a single array and set pointers into it */
        snew(g->edge[0], nbtot);
        for (i = 1; (i < g->nnodes); i++)
        {
            g->edge[i] = g->edge[i-1] + nbond[g->at_start+i-1];
        }

        if (!bShakeOnly)
        {
            /* First add all the real bonds: they should determine the molecular
             * graph.
             */
            for (i = 0; (i < F_NRE); i++)
            {
                if (interaction_function[i].flags & IF_CHEMBOND)
                {
                    mk_igraph(g, i, &(ilist[i]), at_start, at_end, NULL);
                }
            }

            /* Determine of which separated parts the IF_CHEMBOND graph consists.
             * Store the parts in the nbond array.
             */
            bMultiPart = determine_graph_parts(g, nbond);

            if (bMultiPart)
            {
                /* Then add all the other interactions in fixed lists,
                 * but only when they connect parts of the graph
                 * that are not connected through IF_CHEMBOND interactions.
                 */
                for (i = 0; (i < F_NRE); i++)
                {
                    if (!(interaction_function[i].flags & IF_CHEMBOND))
                    {
                        mk_igraph(g, i, &(ilist[i]), at_start, at_end, nbond);
                    }
                }
            }

            /* Removed all the unused space from the edge array */
            compact_graph(fplog, g);
        }
        else
        {
            /* This is a special thing used in splitter.c to generate shake-blocks */
            mk_igraph(g, F_CONSTR, &(ilist[F_CONSTR]), at_start, at_end, NULL);
            if (bSettle)
            {
                mk_igraph(g, F_SETTLE, &(ilist[F_SETTLE]), at_start, at_end, NULL);
            }
        }
        g->nbound = 0;
        for (i = 0; (i < g->nnodes); i++)
        {
            if (g->nedge[i] > 0)
            {
                g->nbound++;
            }
        }
    }

    g->negc = 0;
    g->egc  = NULL;

    sfree(nbond);

    snew(g->ishift, g->at1);

    if (gmx_debug_at)
    {
        p_graph(debug, "graph", g);
    }
}
Exemplo n.º 3
0
void calc_listed(const gmx_multisim_t *ms,
                 gmx_wallcycle        *wcycle,
                 const t_idef *idef,
                 const rvec x[], history_t *hist,
                 rvec f[], t_forcerec *fr,
                 const struct t_pbc *pbc,
                 const struct t_pbc *pbc_full,
                 const struct t_graph *g,
                 gmx_enerdata_t *enerd, t_nrnb *nrnb,
                 real *lambda,
                 const t_mdatoms *md,
                 t_fcdata *fcd, int *global_atom_index,
                 int force_flags)
{
    gmx_bool      bCalcEnerVir;
    int           i;
    real          dvdl[efptNR]; /* The dummy array is to have a place to store the dhdl at other values
                                                        of lambda, which will be thrown away in the end*/
    const  t_pbc *pbc_null;
    int           thread;

    assert(fr->nthreads == idef->nthreads);

    bCalcEnerVir = (force_flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY));

    for (i = 0; i < efptNR; i++)
    {
        dvdl[i] = 0.0;
    }
    if (fr->bMolPBC)
    {
        pbc_null = pbc;
    }
    else
    {
        pbc_null = NULL;
    }

#ifdef DEBUG
    if (g && debug)
    {
        p_graph(debug, "Bondage is fun", g);
    }
#endif

    if ((idef->il[F_POSRES].nr > 0) ||
        (idef->il[F_FBPOSRES].nr > 0) ||
        (idef->il[F_ORIRES].nr > 0) ||
        (idef->il[F_DISRES].nr > 0))
    {
        /* TODO Use of restraints triggers further function calls
           inside the loop over calc_one_bond(), but those are too
           awkward to account to this subtimer properly in the present
           code. We don't test / care much about performance with
           restraints, anyway. */
        wallcycle_sub_start(wcycle, ewcsRESTRAINTS);

        if (idef->il[F_POSRES].nr > 0)
        {
            posres_wrapper(nrnb, idef, pbc_full, x, enerd, lambda, fr);
        }

        if (idef->il[F_FBPOSRES].nr > 0)
        {
            fbposres_wrapper(nrnb, idef, pbc_full, x, enerd, fr);
        }

        /* Do pre force calculation stuff which might require communication */
        if (idef->il[F_ORIRES].nr > 0)
        {
            enerd->term[F_ORIRESDEV] =
                calc_orires_dev(ms, idef->il[F_ORIRES].nr,
                                idef->il[F_ORIRES].iatoms,
                                idef->iparams, md, x,
                                pbc_null, fcd, hist);
        }
        if (idef->il[F_DISRES].nr)
        {
            calc_disres_R_6(idef->il[F_DISRES].nr,
                            idef->il[F_DISRES].iatoms,
                            idef->iparams, x, pbc_null,
                            fcd, hist);
#ifdef GMX_MPI
            if (fcd->disres.nsystems > 1)
            {
                gmx_sum_sim(2*fcd->disres.nres, fcd->disres.Rt_6, ms);
            }
#endif
        }

        wallcycle_sub_stop(wcycle, ewcsRESTRAINTS);
    }

    wallcycle_sub_start(wcycle, ewcsLISTED);
#pragma omp parallel for num_threads(fr->nthreads) schedule(static)
    for (thread = 0; thread < fr->nthreads; thread++)
    {
        int                ftype;
        real              *epot, v;
        /* thread stuff */
        rvec              *ft, *fshift;
        real              *dvdlt;
        gmx_grppairener_t *grpp;

        if (thread == 0)
        {
            ft     = f;
            fshift = fr->fshift;
            epot   = enerd->term;
            grpp   = &enerd->grpp;
            dvdlt  = dvdl;
        }
        else
        {
            zero_thread_forces(&fr->f_t[thread], fr->natoms_force,
                               fr->red_nblock, 1<<fr->red_ashift);

            ft     = fr->f_t[thread].f;
            fshift = fr->f_t[thread].fshift;
            epot   = fr->f_t[thread].ener;
            grpp   = &fr->f_t[thread].grpp;
            dvdlt  = fr->f_t[thread].dvdl;
        }
        /* Loop over all bonded force types to calculate the bonded forces */
        for (ftype = 0; (ftype < F_NRE); ftype++)
        {
            if (idef->il[ftype].nr > 0 && ftype_is_bonded_potential(ftype))
            {
                v = calc_one_bond(thread, ftype, idef, x,
                                  ft, fshift, fr, pbc_null, g, grpp,
                                  nrnb, lambda, dvdlt,
                                  md, fcd, bCalcEnerVir,
                                  global_atom_index);
                epot[ftype] += v;
            }
        }
    }
    wallcycle_sub_stop(wcycle, ewcsLISTED);

    if (fr->nthreads > 1)
    {
        wallcycle_sub_start(wcycle, ewcsLISTED_BUF_OPS);
        reduce_thread_forces(fr->natoms_force, f, fr->fshift,
                             enerd->term, &enerd->grpp, dvdl,
                             fr->nthreads, fr->f_t,
                             fr->red_nblock, 1<<fr->red_ashift,
                             bCalcEnerVir,
                             force_flags & GMX_FORCE_DHDL);
        wallcycle_sub_stop(wcycle, ewcsLISTED_BUF_OPS);
    }

    /* Remaining code does not have enough flops to bother counting */
    if (force_flags & GMX_FORCE_DHDL)
    {
        for (i = 0; i < efptNR; i++)
        {
            enerd->dvdl_nonlin[i] += dvdl[i];
        }
    }

    /* Copy the sum of violations for the distance restraints from fcd */
    if (fcd)
    {
        enerd->term[F_DISRESVIOL] = fcd->disres.sumviol;

    }
}
Exemplo n.º 4
0
void gen_sblocks(FILE *fp, int at_start, int at_end,
                 t_idef *idef, t_blocka *sblock,
                 gmx_bool bSettle)
{
    t_graph *g;
    int      i, i0, j, k, istart, n;
    t_sid   *sid;
    int      isid, nsid;

    g = mk_graph(NULL, idef, at_start, at_end, TRUE, bSettle);
    if (debug)
    {
        p_graph(debug, "Graaf Dracula", g);
    }
    snew(sid, at_end);
    for (i = at_start; (i < at_end); i++)
    {
        sid[i].atom =  i;
        sid[i].sid  = -1;
    }
    nsid = mk_sblocks(fp, g, at_end, sid);

    if (!nsid)
    {
        return;
    }

    /* Now sort the shake blocks... */
    qsort(sid+at_start, at_end-at_start, (size_t)sizeof(sid[0]), sid_comp);

    if (debug)
    {
        fprintf(debug, "Sorted shake block\n");
        for (i = at_start; (i < at_end); i++)
        {
            fprintf(debug, "sid[%5d] = atom:%5d sid:%5d\n", i, sid[i].atom, sid[i].sid);
        }
    }
    /* Now check how many are NOT -1, i.e. how many have to be shaken */
    for (i0 = at_start; (i0 < at_end); i0++)
    {
        if (sid[i0].sid > -1)
        {
            break;
        }
    }

    /* Now we have the sids that have to be shaken. We'll check the min and
     * max atom numbers and this determines the shake block. DvdS 2007-07-19.
     * For the purpose of making boundaries all atoms in between need to be
     * part of the shake block too. There may be cases where blocks overlap
     * and they will have to be merged.
     */
    nsid = merge_sid(at_start, at_end, nsid, sid, sblock);
    /* Now sort the shake blocks again... */
    /*qsort(sid,natoms,(size_t)sizeof(sid[0]),sid_comp);*/

    /* Fill the sblock struct */
    /*  sblock->nr  = nsid;
       sblock->nra = natoms;
       srenew(sblock->a,sblock->nra);
       srenew(sblock->index,sblock->nr+1);

       i    = i0;
       isid = sid[i].sid;
       n    = k = 0;
       sblock->index[n++]=k;
       while (i < natoms) {
       istart = sid[i].atom;
       while ((i<natoms-1) && (sid[i+1].sid == isid))
       i++;*/
    /* After while: we found a new block, or are thru with the atoms */
    /*    for(j=istart; (j<=sid[i].atom); j++,k++)
        sblock->a[k]=j;
       sblock->index[n] = k;
       if (i < natoms-1)
        n++;
       if (n > nsid)
        gmx_fatal(FARGS,"Death Horror: nsid = %d, n= %d",nsid,n);
       i++;
       isid = sid[i].sid;
       }
     */
    sfree(sid);
    /* Due to unknown reason this free generates a problem sometimes */
    done_graph(g);
    sfree(g);
    if (debug)
    {
        fprintf(debug, "Done gen_sblocks\n");
    }
}
Exemplo n.º 5
0
void force(FILE       *fp,     int        step,
	   t_forcerec *fr,      t_inputrec *ir,
	   t_idef     *idef,    t_nsborder *nsb,
	   t_commrec  *cr,      t_commrec *mcr,
	   t_nrnb     *nrnb,
	   t_groups   *grps,    t_mdatoms  *md,
	   int        ngener,   t_grpopts  *opts,
	   rvec       x[],      rvec       f[],
	   real       epot[],   t_fcdata   *fcd,
	   bool       bVerbose, matrix     box,
	   real       lambda,   t_graph    *graph,
	   t_block    *excl,    bool       bNBFonly,
	   matrix lr_vir,       rvec       mu_tot,
	   real       qsum,     bool       bGatherOnly)
{
  int     i,nit;
  bool    bDoEpot;
  rvec    box_size;
  real    Vlr,Vcorr=0;
  
  /* Reset box */
  for(i=0; (i<DIM); i++)
    box_size[i]=box[i][i];
    
  bDoEpot=((fr->nmol > 0) && (fr->nstcalc > 0) && (mod(step,fr->nstcalc)==0));
  /* Reset epot... */
  if (bDoEpot) 
    for(i=0; (i<fr->nmol); i++)
      fr->mol_epot[i]=0.0;
  debug_gmx();
  
  /* Call the short range functions all in one go. */
  do_fnbf(fp,cr,fr,x,f,md,
	  fr->bBHAM ? grps->estat.ee[egBHAM] : grps->estat.ee[egLJ],
	  grps->estat.ee[egCOUL],box_size,nrnb,
	  lambda,&epot[F_DVDL],FALSE,-1);
  debug_gmx();

  if (debug) 
    pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS);
  
  /* Shift the coordinates. Must be done before bonded forces and PPPM, 
   * but is also necessary for SHAKE and update, therefore it can NOT 
   * go when no bonded forces have to be evaluated.
   */
  if (debug && 0)
    p_graph(debug,"DeBUGGGG",graph);
  
  /* Check whether we need to do bondeds */
  if (!bNBFonly) {
    shift_self(graph,box,x);
    if (debug && 0) {
      fprintf(debug,"BBBBBBBBBBBBBBBB\n");
      fprintf(debug,"%5d\n",graph->nnodes);
      for(i=graph->start; (i<=graph->end); i++)
	fprintf(debug,"%5d%5s%5s%5d%8.3f%8.3f%8.3f\n",
		i,"A","B",i,x[i][XX],x[i][YY],x[i][ZZ]);
      fprintf(debug,"%10.5f%10.5f%10.5f\n",
	      box[XX][XX],box[YY][YY],box[ZZ][ZZ]);
    }
    if (TRICLINIC(box))
	inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes);
    else
	inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes);
    debug_gmx();
  }
  
  if (EEL_LR(fr->eeltype)) {
    switch (fr->eeltype) {
    case eelPPPM:
      Vlr = do_pppm(fp,FALSE,x,fr->f_pme,md->chargeT,
		    box_size,fr->phi,cr,nsb,nrnb);
      break;
    case eelPOISSON:
      Vlr = do_poisson(fp,FALSE,ir,md->nr,x,fr->f_pme,md->chargeT,
		       box_size,fr->phi,cr,nrnb,&nit,TRUE);
      break;
    case eelPME:
      Vlr = do_pme(fp,FALSE,ir,x,fr->f_pme,md->chargeT,
		   box,cr,nsb,nrnb,lr_vir,fr->ewaldcoeff,bGatherOnly);
      break;
    case eelEWALD:
      Vlr = do_ewald(fp,FALSE,ir,x,fr->f_pme,md->chargeT,
		     box_size,cr,nsb,lr_vir,fr->ewaldcoeff);
      break;
    default:
      Vlr = 0;
      fatal_error(0,"No such electrostatics method implemented %s",
		  eel_names[fr->eeltype]);
    }
    if(fr->bEwald)
      Vcorr =
	ewald_LRcorrection(fp,nsb,cr,fr,md->chargeT,excl,x,box,mu_tot,qsum,
			   ir->ewald_geometry,ir->epsilon_surface,lr_vir);
    else
      Vcorr = shift_LRcorrection(fp,nsb,cr,fr,md->chargeT,excl,x,TRUE,box,lr_vir);
    epot[F_LR] = Vlr + Vcorr;
    if (debug)
      fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n",
	      Vlr,Vcorr,epot[F_LR]);
    if (debug) {
      pr_rvecs(debug,0,"lr_vir after corr",lr_vir,DIM);
      pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS);
    }
  }
  debug_gmx();
  
  if (debug)    
    print_nrnb(debug,nrnb); 
  debug_gmx();
  
  if (!bNBFonly) {
    calc_bonds(fp,cr,mcr,
	       idef,x,f,fr,graph,epot,nrnb,box,lambda,md,
	       opts->ngener,grps->estat.ee[egLJ14],grps->estat.ee[egCOUL14],
	       fcd,step,fr->bSepDVDL && do_per_step(step,ir->nstlog));    
    debug_gmx();
  }
  if (debug) 
    pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS);
  
  for(i=0; (i<F_EPOT); i++)
    if (i != F_DISRES)
      epot[F_EPOT]+=epot[i];
}