Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
/* 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;
}
Exemplo n.º 3
0
void set_pull_init(t_inputrec *ir, gmx_mtop_t *mtop, rvec *x, matrix box, real lambda,
                   const output_env_t oenv)
{
    pull_params_t *pull;
    struct pull_t *pull_work;
    t_mdatoms     *md;
    t_pbc          pbc;
    int            c;
    double         t_start;

    pull      = ir->pull;
    pull_work = init_pull(NULL, pull, ir, 0, NULL, mtop, NULL, oenv, lambda, FALSE, 0);
    md        = init_mdatoms(NULL, mtop, ir->efep);
    atoms2md(mtop, ir, 0, NULL, mtop->natoms, md);
    if (ir->efep)
    {
        update_mdatoms(md, lambda);
    }

    set_pbc(&pbc, ir->ePBC, box);

    t_start = ir->init_t + ir->init_step*ir->delta_t;

    pull_calc_coms(NULL, pull_work, md, &pbc, t_start, x, NULL);

    fprintf(stderr, "Pull group  natoms  pbc atom  distance at start  reference at t=0\n");
    for (c = 0; c < pull->ncoord; c++)
    {
        t_pull_coord *pcrd;
        t_pull_group *pgrp0, *pgrp1;
        double        value;
        real          init = 0;

        pcrd  = &pull->coord[c];

        pgrp0 = &pull->group[pcrd->group[0]];
        pgrp1 = &pull->group[pcrd->group[1]];
        fprintf(stderr, "%8d  %8d  %8d\n",
                pcrd->group[0], pgrp0->nat, pgrp0->pbcatom+1);
        fprintf(stderr, "%8d  %8d  %8d ",
                pcrd->group[1], pgrp1->nat, pgrp1->pbcatom+1);

        if (pcrd->bStart)
        {
            init       = pcrd->init;
            pcrd->init = 0;
        }

        get_pull_coord_value(pull_work, c, &pbc, &value);
        fprintf(stderr, " %10.3f nm", value);

        if (pcrd->bStart)
        {
            pcrd->init = value + init;
        }
        fprintf(stderr, "     %10.3f nm\n", pcrd->init);
    }

    finish_pull(pull_work);
}
Exemplo n.º 4
0
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;
            }
        }
    }
}
Exemplo n.º 5
0
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);
}
Exemplo n.º 6
0
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);
                    }
                }
            }
        }
    }
}
Exemplo n.º 7
0
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);

    }

}
Exemplo n.º 8
0
void setStateDependentAwhParams(AwhParams *awhParams,
                                const pull_params_t *pull_params, pull_t *pull_work,
                                const matrix box,  int ePBC,
                                const t_grpopts *inputrecGroupOptions, warninp_t wi)
{
    /* The temperature is not really state depenendent but is not known
     * when read_awhParams is called (in get ir).
     * It is known first after do_index has been called in grompp.cpp.
     */
    if (inputrecGroupOptions->ref_t == NULL ||
        inputrecGroupOptions->ref_t[0] <= 0)
    {
        gmx_fatal(FARGS, "AWH biasing is only supported for temperatures > 0");
    }
    for (int i = 1; i < inputrecGroupOptions->ngtc; i++)
    {
        if (inputrecGroupOptions->ref_t[i] != inputrecGroupOptions->ref_t[0])
        {
            gmx_fatal(FARGS, "AWH biasing is currently only supported for identical temperatures for all temperature coupling groups");
        }
    }

    t_pbc          pbc;
    set_pbc(&pbc, ePBC, box);

    for (int k = 0; k < awhParams->numBias; k++)
    {
        AwhBiasParams *awhBiasParams = &awhParams->awhBiasParams[k];
        for (int d = 0; d < awhBiasParams->ndim; d++)
        {
            AwhDimParams *dimParams = &awhBiasParams->dimParams[d];

            /* The periodiciy of the AWH grid in certain cases depends on the simulation box */
            dimParams->period = get_pull_coord_period(pull_params, dimParams->coordIndex, box);

            /* The initial coordinate value, converted to external user units. */
            dimParams->coordValueInit =
                get_pull_coord_value(pull_work, dimParams->coordIndex, &pbc);

            t_pull_coord *pullCoord = &pull_params->coord[dimParams->coordIndex];
            dimParams->coordValueInit *= pull_conversion_factor_internal2userinput(pullCoord);
        }
    }
    checkInputConsistencyInterval(awhParams, wi);

    /* Register AWH as external potential with pull to check consistency. */
    Awh::registerAwhWithPull(*awhParams, pull_work);
}
Exemplo n.º 9
0
void calc_angles_dihs(t_params *ang, t_params *dih, rvec x[], gmx_bool bPBC,
                      matrix box)
{
    int    i, ai, aj, ak, al, t1, t2, t3;
    rvec   r_ij, r_kj, r_kl, m, n;
    real   sign, th, costh, ph;
    t_pbc  pbc;

    if (bPBC)
    {
        set_pbc(&pbc, epbcXYZ, box);
    }
    if (debug)
    {
        pr_rvecs(debug, 0, "X2TOP", box, DIM);
    }
    for (i = 0; (i < ang->nr); i++)
    {
        ai = ang->param[i].AI;
        aj = ang->param[i].AJ;
        ak = ang->param[i].AK;
        th = RAD2DEG*bond_angle(x[ai], x[aj], x[ak], bPBC ? &pbc : NULL,
                                r_ij, r_kj, &costh, &t1, &t2);
        if (debug)
        {
            fprintf(debug, "X2TOP: ai=%3d aj=%3d ak=%3d r_ij=%8.3f r_kj=%8.3f th=%8.3f\n",
                    ai, aj, ak, norm(r_ij), norm(r_kj), th);
        }
        ang->param[i].C0 = th;
    }
    for (i = 0; (i < dih->nr); i++)
    {
        ai = dih->param[i].AI;
        aj = dih->param[i].AJ;
        ak = dih->param[i].AK;
        al = dih->param[i].AL;
        ph = RAD2DEG*dih_angle(x[ai], x[aj], x[ak], x[al], bPBC ? &pbc : NULL,
                               r_ij, r_kj, r_kl, m, n, &sign, &t1, &t2, &t3);
        if (debug)
        {
            fprintf(debug, "X2TOP: ai=%3d aj=%3d ak=%3d al=%3d r_ij=%8.3f r_kj=%8.3f r_kl=%8.3f ph=%8.3f\n",
                    ai, aj, ak, al, norm(r_ij), norm(r_kj), norm(r_kl), ph);
        }
        dih->param[i].C0 = ph;
    }
}
Exemplo n.º 10
0
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;
        }
    }
}
Exemplo n.º 11
0
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;
                              }
Exemplo n.º 12
0
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);
        }
    }
}
Exemplo n.º 13
0
void
partition_absorbing_box( grid_t * g,
                         double gx0, double gy0, double gz0,
                         double gx1, double gy1, double gz1,
                         int gnx, int gny, int gnz,
                         int gpx, int gpy, int gpz,
                         int pbc ) {
  int px, py, pz; 

  partition_periodic_box( g,
                          gx0, gy0, gz0,
                          gx1, gy1, gz1,
                          gnx, gny, gnz,
                          gpx, gpy, gpz );

  // Override periodic boundary conditions

  RANK_TO_INDEX( world_rank, px,py,pz );

  if( px==0 && gnx>1 ) { 
    set_fbc(g,BOUNDARY(-1,0,0),absorb_fields);
    set_pbc(g,BOUNDARY(-1,0,0),pbc);
  } 

  if( px==gpx-1 && gnx>1 ) {
    set_fbc(g,BOUNDARY( 1,0,0),absorb_fields);
    set_pbc(g,BOUNDARY( 1,0,0),pbc);
  }

  if( py==0 && gny>1 ) { 
    set_fbc(g,BOUNDARY(0,-1,0),absorb_fields);
    set_pbc(g,BOUNDARY(0,-1,0),pbc);
  } 

  if( py==gpy-1 && gny>1 ) {
    set_fbc(g,BOUNDARY(0, 1,0),absorb_fields);
    set_pbc(g,BOUNDARY(0, 1,0),pbc);
  }

  if( pz==0 && gnz>1 ) { 
    set_fbc(g,BOUNDARY(0,0,-1),absorb_fields);
    set_pbc(g,BOUNDARY(0,0,-1),pbc);
  } 

  if( pz==gpz-1 && gnz>1 ) {
    set_fbc(g,BOUNDARY(0,0, 1),absorb_fields);
    set_pbc(g,BOUNDARY(0,0, 1),pbc);
  }
}
Exemplo n.º 14
0
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]);
    }
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
void read_ang_dih(const char *trj_fn,
                  gmx_bool bAngles, gmx_bool bSaveAll, gmx_bool bRb, gmx_bool bPBC,
                  int maxangstat, int angstat[],
                  int *nframes, real **time,
                  int isize, atom_id index[],
                  real **trans_frac,
                  real **aver_angle,
                  real *dih[],
                  const output_env_t oenv)
{
    t_pbc       *pbc;
    t_trxstatus *status;
    int          i, angind, natoms, total, teller;
    int          nangles, n_alloc;
    real         t, fraction, pifac, aa, angle;
    real        *angles[2];
    matrix       box;
    rvec        *x;
    int          cur = 0;
#define prev (1-cur)

    snew(pbc, 1);
    natoms = read_first_x(oenv, &status, trj_fn, &t, &x, box);

    if (bAngles)
    {
        nangles = isize/3;
        pifac   = M_PI;
    }
    else
    {
        nangles = isize/4;
        pifac   = 2.0*M_PI;
    }
    snew(angles[cur], nangles);
    snew(angles[prev], nangles);

    /* Start the loop over frames */
    total       = 0;
    teller      = 0;
    n_alloc     = 0;
    *time       = NULL;
    *trans_frac = NULL;
    *aver_angle = NULL;

    do
    {
        if (teller >= n_alloc)
        {
            n_alloc += 100;
            if (bSaveAll)
            {
                for (i = 0; (i < nangles); i++)
                {
                    srenew(dih[i], n_alloc);
                }
            }
            srenew(*time, n_alloc);
            srenew(*trans_frac, n_alloc);
            srenew(*aver_angle, n_alloc);
        }

        (*time)[teller] = t;

        if (pbc)
        {
            set_pbc(pbc, -1, box);
        }

        if (bAngles)
        {
            calc_angles(pbc, isize, index, angles[cur], x);
        }
        else
        {
            calc_dihs(pbc, isize, index, angles[cur], x);

            /* Trans fraction */
            fraction              = calc_fraction(angles[cur], nangles);
            (*trans_frac)[teller] = fraction;

            /* Change Ryckaert-Bellemans dihedrals to polymer convention
             * Modified 990913 by Erik:
             * We actually shouldn't change the convention, since it's
             * calculated from polymer above, but we change the intervall
             * from [-180,180] to [0,360].
             */
            if (bRb)
            {
                for (i = 0; (i < nangles); i++)
                {
                    if (angles[cur][i] <= 0.0)
                    {
                        angles[cur][i] += 2*M_PI;
                    }
                }
            }

            /* Periodicity in dihedral space... */
            if (bPBC)
            {
                for (i = 0; (i < nangles); i++)
                {
                    real dd = angles[cur][i];
                    angles[cur][i] = atan2(sin(dd), cos(dd));
                }
            }
            else
            {
                if (teller > 1)
                {
                    for (i = 0; (i < nangles); i++)
                    {
                        while (angles[cur][i] <= angles[prev][i] - M_PI)
                        {
                            angles[cur][i] += 2*M_PI;
                        }
                        while (angles[cur][i] > angles[prev][i] + M_PI)
                        {
                            angles[cur][i] -= 2*M_PI;
                        }
                    }
                }
            }
        }

        /* Average angles */
        aa = 0;
        for (i = 0; (i < nangles); i++)
        {
            aa = aa+angles[cur][i];

            /* angle in rad / 2Pi * max determines bin. bins go from 0 to maxangstat,
               even though scale goes from -pi to pi (dihedral) or -pi/2 to pi/2
               (angle) Basically: translate the x-axis by Pi. Translate it back by
               -Pi when plotting.
             */

            angle = angles[cur][i];
            if (!bAngles)
            {
                while (angle < -M_PI)
                {
                    angle += 2*M_PI;
                }
                while (angle >= M_PI)
                {
                    angle -= 2*M_PI;
                }

                angle += M_PI;
            }

            /* Update the distribution histogram */
            angind = (int) ((angle*maxangstat)/pifac + 0.5);
            if (angind == maxangstat)
            {
                angind = 0;
            }
            if ( (angind < 0) || (angind >= maxangstat) )
            {
                /* this will never happen */
                gmx_fatal(FARGS, "angle (%f) index out of range (0..%d) : %d\n",
                          angle, maxangstat, angind);
            }

            angstat[angind]++;
            if (angind == maxangstat)
            {
                fprintf(stderr, "angle %d fr %d = %g\n", i, cur, angle);
            }

            total++;
        }

        /* average over all angles */
        (*aver_angle)[teller] = (aa/nangles);

        /* this copies all current dih. angles to dih[i], teller is frame */
        if (bSaveAll)
        {
            for (i = 0; i < nangles; i++)
            {
                dih[i][teller] = angles[cur][i];
            }
        }

        /* Swap buffers */
        cur = prev;

        /* Increment loop counter */
        teller++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);

    sfree(x);
    sfree(angles[cur]);
    sfree(angles[prev]);

    *nframes = teller;
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
gmx_bool constrain(FILE *fplog, gmx_bool bLog, gmx_bool bEner,
                   struct gmx_constr *constr,
                   t_idef *idef, t_inputrec *ir, gmx_ekindata_t *ekind,
                   t_commrec *cr,
                   gmx_int64_t step, int delta_step,
                   t_mdatoms *md,
                   rvec *x, rvec *xprime, rvec *min_proj,
                   gmx_bool bMolPBC, matrix box,
                   real lambda, real *dvdlambda,
                   rvec *v, tensor *vir,
                   t_nrnb *nrnb, int econq, gmx_bool bPscal,
                   real veta, real vetanew)
{
    gmx_bool    bOK, bDump;
    int         start, homenr, nrend;
    int         i, j, d;
    int         ncons, settle_error;
    tensor      vir_r_m_dr;
    rvec       *vstor;
    real        invdt, vir_fac, t;
    t_ilist    *settle;
    int         nsettle;
    t_pbc       pbc, *pbc_null;
    char        buf[22];
    t_vetavars  vetavar;
    int         nth, th;

    if (econq == econqForceDispl && !EI_ENERGY_MINIMIZATION(ir->eI))
    {
        gmx_incons("constrain called for forces displacements while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted");
    }

    bOK   = TRUE;
    bDump = FALSE;

    start  = 0;
    homenr = md->homenr;
    nrend  = start+homenr;

    /* set constants for pressure control integration */
    init_vetavars(&vetavar, econq != econqCoord,
                  veta, vetanew, ir, ekind, bPscal);

    if (ir->delta_t == 0)
    {
        invdt = 0;
    }
    else
    {
        invdt  = 1/ir->delta_t;
    }

    if (ir->efep != efepNO && EI_DYNAMICS(ir->eI))
    {
        /* Set the constraint lengths for the step at which this configuration
         * is meant to be. The invmasses should not be changed.
         */
        lambda += delta_step*ir->fepvals->delta_lambda;
    }

    if (vir != NULL)
    {
        clear_mat(vir_r_m_dr);
    }

    where();

    settle  = &idef->il[F_SETTLE];
    nsettle = settle->nr/(1+NRAL(F_SETTLE));

    if (nsettle > 0)
    {
        nth = gmx_omp_nthreads_get(emntSETTLE);
    }
    else
    {
        nth = 1;
    }

    if (nth > 1 && constr->vir_r_m_dr_th == NULL)
    {
        snew(constr->vir_r_m_dr_th, nth);
        snew(constr->settle_error, nth);
    }

    settle_error = -1;

    /* We do not need full pbc when constraints do not cross charge groups,
     * i.e. when dd->constraint_comm==NULL.
     * Note that PBC for constraints is different from PBC for bondeds.
     * For constraints there is both forward and backward communication.
     */
    if (ir->ePBC != epbcNONE &&
        (cr->dd || bMolPBC) && !(cr->dd && cr->dd->constraint_comm == NULL))
    {
        /* With pbc=screw the screw has been changed to a shift
         * by the constraint coordinate communication routine,
         * so that here we can use normal pbc.
         */
        pbc_null = set_pbc_dd(&pbc, ir->ePBC, cr->dd, FALSE, box);
    }
    else
    {
        pbc_null = NULL;
    }

    /* Communicate the coordinates required for the non-local constraints
     * for LINCS and/or SETTLE.
     */
    if (cr->dd)
    {
        dd_move_x_constraints(cr->dd, box, x, xprime, econq == econqCoord);
    }

    if (constr->lincsd != NULL)
    {
        bOK = constrain_lincs(fplog, bLog, bEner, ir, step, constr->lincsd, md, cr,
                              x, xprime, min_proj,
                              box, pbc_null, lambda, dvdlambda,
                              invdt, v, vir != NULL, vir_r_m_dr,
                              econq, nrnb,
                              constr->maxwarn, &constr->warncount_lincs);
        if (!bOK && constr->maxwarn >= 0)
        {
            if (fplog != NULL)
            {
                fprintf(fplog, "Constraint error in algorithm %s at step %s\n",
                        econstr_names[econtLINCS], gmx_step_str(step, buf));
            }
            bDump = TRUE;
        }
    }

    if (constr->nblocks > 0)
    {
        switch (econq)
        {
            case (econqCoord):
                bOK = bshakef(fplog, constr->shaked,
                              md->invmass, constr->nblocks, constr->sblock,
                              idef, ir, x, xprime, nrnb,
                              constr->lagr, lambda, dvdlambda,
                              invdt, v, vir != NULL, vir_r_m_dr,
                              constr->maxwarn >= 0, econq, &vetavar);
                break;
            case (econqVeloc):
                bOK = bshakef(fplog, constr->shaked,
                              md->invmass, constr->nblocks, constr->sblock,
                              idef, ir, x, min_proj, nrnb,
                              constr->lagr, lambda, dvdlambda,
                              invdt, NULL, vir != NULL, vir_r_m_dr,
                              constr->maxwarn >= 0, econq, &vetavar);
                break;
            default:
                gmx_fatal(FARGS, "Internal error, SHAKE called for constraining something else than coordinates");
                break;
        }

        if (!bOK && constr->maxwarn >= 0)
        {
            if (fplog != NULL)
            {
                fprintf(fplog, "Constraint error in algorithm %s at step %s\n",
                        econstr_names[econtSHAKE], gmx_step_str(step, buf));
            }
            bDump = TRUE;
        }
    }

    if (nsettle > 0)
    {
        int calcvir_atom_end;

        if (vir == NULL)
        {
            calcvir_atom_end = 0;
        }
        else
        {
            calcvir_atom_end = md->homenr;
        }

        switch (econq)
        {
            case econqCoord:
#pragma omp parallel for num_threads(nth) schedule(static)
                for (th = 0; th < nth; th++)
                {
                    int start_th, end_th;

                    if (th > 0)
                    {
                        clear_mat(constr->vir_r_m_dr_th[th]);
                    }

                    start_th = (nsettle* th   )/nth;
                    end_th   = (nsettle*(th+1))/nth;
                    if (start_th >= 0 && end_th - start_th > 0)
                    {
                        csettle(constr->settled,
                                end_th-start_th,
                                settle->iatoms+start_th*(1+NRAL(F_SETTLE)),
                                pbc_null,
                                x[0], xprime[0],
                                invdt, v ? v[0] : NULL, calcvir_atom_end,
                                th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th],
                                th == 0 ? &settle_error : &constr->settle_error[th],
                                &vetavar);
                    }
                }
                inc_nrnb(nrnb, eNR_SETTLE, nsettle);
                if (v != NULL)
                {
                    inc_nrnb(nrnb, eNR_CONSTR_V, nsettle*3);
                }
                if (vir != NULL)
                {
                    inc_nrnb(nrnb, eNR_CONSTR_VIR, nsettle*3);
                }
                break;
            case econqVeloc:
            case econqDeriv:
            case econqForce:
            case econqForceDispl:
#pragma omp parallel for num_threads(nth) schedule(static)
                for (th = 0; th < nth; th++)
                {
                    int start_th, end_th;

                    if (th > 0)
                    {
                        clear_mat(constr->vir_r_m_dr_th[th]);
                    }

                    start_th = (nsettle* th   )/nth;
                    end_th   = (nsettle*(th+1))/nth;

                    if (start_th >= 0 && end_th - start_th > 0)
                    {
                        settle_proj(constr->settled, econq,
                                    end_th-start_th,
                                    settle->iatoms+start_th*(1+NRAL(F_SETTLE)),
                                    pbc_null,
                                    x,
                                    xprime, min_proj, calcvir_atom_end,
                                    th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th],
                                    &vetavar);
                    }
                }
                /* This is an overestimate */
                inc_nrnb(nrnb, eNR_SETTLE, nsettle);
                break;
            case econqDeriv_FlexCon:
                /* Nothing to do, since the are no flexible constraints in settles */
                break;
            default:
                gmx_incons("Unknown constraint quantity for settle");
        }
    }

    if (settle->nr > 0)
    {
        /* Combine virial and error info of the other threads */
        for (i = 1; i < nth; i++)
        {
            m_add(vir_r_m_dr, constr->vir_r_m_dr_th[i], vir_r_m_dr);
            settle_error = constr->settle_error[i];
        }

        if (econq == econqCoord && settle_error >= 0)
        {
            bOK = FALSE;
            if (constr->maxwarn >= 0)
            {
                char buf[256];
                sprintf(buf,
                        "\nstep " "%"GMX_PRId64 ": Water molecule starting at atom %d can not be "
                        "settled.\nCheck for bad contacts and/or reduce the timestep if appropriate.\n",
                        step, ddglatnr(cr->dd, settle->iatoms[settle_error*(1+NRAL(F_SETTLE))+1]));
                if (fplog)
                {
                    fprintf(fplog, "%s", buf);
                }
                fprintf(stderr, "%s", buf);
                constr->warncount_settle++;
                if (constr->warncount_settle > constr->maxwarn)
                {
                    too_many_constraint_warnings(-1, constr->warncount_settle);
                }
                bDump = TRUE;
            }
        }
    }

    free_vetavars(&vetavar);

    if (vir != NULL)
    {
        switch (econq)
        {
            case econqCoord:
                vir_fac = 0.5/(ir->delta_t*ir->delta_t);
                break;
            case econqVeloc:
                vir_fac = 0.5/ir->delta_t;
                break;
            case econqForce:
            case econqForceDispl:
                vir_fac = 0.5;
                break;
            default:
                vir_fac = 0;
                gmx_incons("Unsupported constraint quantity for virial");
        }

        if (EI_VV(ir->eI))
        {
            vir_fac *= 2;  /* only constraining over half the distance here */
        }
        for (i = 0; i < DIM; i++)
        {
            for (j = 0; j < DIM; j++)
            {
                (*vir)[i][j] = vir_fac*vir_r_m_dr[i][j];
            }
        }
    }

    if (bDump)
    {
        dump_confs(fplog, step, constr->warn_mtop, start, homenr, cr, x, xprime, box);
    }

    if (econq == econqCoord)
    {
        if (ir->ePull == epullCONSTRAINT)
        {
            if (EI_DYNAMICS(ir->eI))
            {
                t = ir->init_t + (step + delta_step)*ir->delta_t;
            }
            else
            {
                t = ir->init_t;
            }
            set_pbc(&pbc, ir->ePBC, box);
            pull_constraint(ir->pull, md, &pbc, cr, ir->delta_t, t, x, xprime, v, *vir);
        }
        if (constr->ed && delta_step > 0)
        {
            /* apply the essential dynamcs constraints here */
            do_edsam(ir, step, cr, xprime, v, box, constr->ed);
        }
    }

    return bOK;
}
Exemplo n.º 20
0
void orient(int natom,rvec *x,rvec *v, rvec angle,matrix box)
{
  real longest,rij,rzi;
  int  i,j,m,max_i=0,max_j=0;
  rvec origin;
  int  temp;
  real alfa=0,beta=0,gamma=0;
  t_pbc pbc;

  set_pbc(&pbc,-1,box);

  /*first i am going to look for the longest atom-atom distance*/
  longest=dist2(&pbc,x[0],x[1]);
  i=0;
  j=1;
  for (i=0;(i<natom);i++) {
    for (j=0;(j<natom);j++) {
      rij=dist2(&pbc,x[i],x[j]);
      if (rij>longest) {
	max_i=i;
	max_j=j;
	longest=rij;
      }
    }
  }
  /* first check if x[max_i]<x[max_j] else swap*/
  if (x[max_i][2]>x[max_j][2]) {
    temp=max_i;
    max_i=max_j;
    max_j=temp;
  }
  
  /*set the origin to x[i]*/
  for(m=0;(m<DIM);m++) 
    origin[m]=x[max_i][m];
  for(i=0;(i<natom);i++)
    for(m=0;(m<DIM);m++)
      x[i][m]-=origin[m];
      
  /* calculate the rotation angles alfa(x_axis) and beta(y_axis)
   * the rotation angles must be calculated clockwise looking 
   * along the rotation axis to the origin*
   * alfa (x-axis)
   */
  alfa=atan(x[max_j][ZZ]/x[max_j][YY])-M_PI_2;
  beta=M_PI_2-atan(x[max_j][ZZ]/x[max_j][XX]);
  rotate_conf(natom,x,v,alfa,beta,gamma);
  
  /* now search the longest distance for rotation along the z_axis */
  longest=distance_to_z(x[0]);
  max_i=0;
  for (i=1;(i<natom);i++) {
    rzi=distance_to_z(x[i]);
    if (rzi>longest) {
      longest = rzi;
      max_i=i;
    }
  }
  gamma=atan(x[max_i][YY]/x[max_i][XX])-M_PI_2;
  rotate_conf(natom,x,v,0,0,gamma);
  angle[0]=alfa;
  angle[1]=beta;
  angle[2]=gamma;
} /*orient()*/
Exemplo n.º 21
0
void do_force_lowlevel(t_forcerec *fr,      t_inputrec *ir,
                       t_idef     *idef,    t_commrec  *cr,
                       t_nrnb     *nrnb,    gmx_wallcycle_t wcycle,
                       t_mdatoms  *md,
                       rvec       x[],      history_t  *hist,
                       rvec       f[],
                       rvec       f_longrange[],
                       gmx_enerdata_t *enerd,
                       t_fcdata   *fcd,
                       gmx_localtop_t *top,
                       gmx_genborn_t *born,
                       gmx_bool       bBornRadii,
                       matrix     box,
                       t_lambda   *fepvals,
                       real       *lambda,
                       t_graph    *graph,
                       t_blocka   *excl,
                       rvec       mu_tot[],
                       int        flags,
                       float      *cycles_pme)
{
    int         i, j;
    int         donb_flags;
    gmx_bool    bSB;
    int         pme_flags;
    matrix      boxs;
    rvec        box_size;
    t_pbc       pbc;
    real        dvdl_dum[efptNR], dvdl_nb[efptNR];

#ifdef GMX_MPI
    double  t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */
#endif

    set_pbc(&pbc, fr->ePBC, box);

    /* reset free energy components */
    for (i = 0; i < efptNR; i++)
    {
        dvdl_nb[i]  = 0;
        dvdl_dum[i] = 0;
    }

    /* Reset box */
    for (i = 0; (i < DIM); i++)
    {
        box_size[i] = box[i][i];
    }

    debug_gmx();

    /* do QMMM first if requested */
    if (fr->bQMMM)
    {
        enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr);
    }

    /* Call the short range functions all in one go. */

#ifdef GMX_MPI
    /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/
#define TAKETIME FALSE
    if (TAKETIME)
    {
        MPI_Barrier(cr->mpi_comm_mygroup);
        t0 = MPI_Wtime();
    }
#endif

    if (ir->nwall)
    {
        /* foreign lambda component for walls */
        real dvdl_walls = do_walls(ir, fr, box, md, x, f, lambda[efptVDW],
                                   enerd->grpp.ener[egLJSR], nrnb);
        enerd->dvdl_lin[efptVDW] += dvdl_walls;
    }

    /* If doing GB, reset dvda and calculate the Born radii */
    if (ir->implicit_solvent)
    {
        wallcycle_sub_start(wcycle, ewcsNONBONDED);

        for (i = 0; i < born->nr; i++)
        {
            fr->dvda[i] = 0;
        }

        if (bBornRadii)
        {
            calc_gb_rad(cr, fr, ir, top, x, &(fr->gblist), born, md, nrnb);
        }

        wallcycle_sub_stop(wcycle, ewcsNONBONDED);
    }

    where();
    /* We only do non-bonded calculation with group scheme here, the verlet
     * calls are done from do_force_cutsVERLET(). */
    if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED))
    {
        donb_flags = 0;
        /* Add short-range interactions */
        donb_flags |= GMX_NONBONDED_DO_SR;

        /* Currently all group scheme kernels always calculate (shift-)forces */
        if (flags & GMX_FORCE_FORCES)
        {
            donb_flags |= GMX_NONBONDED_DO_FORCE;
        }
        if (flags & GMX_FORCE_VIRIAL)
        {
            donb_flags |= GMX_NONBONDED_DO_SHIFTFORCE;
        }
        if (flags & GMX_FORCE_ENERGY)
        {
            donb_flags |= GMX_NONBONDED_DO_POTENTIAL;
        }
        if (flags & GMX_FORCE_DO_LR)
        {
            donb_flags |= GMX_NONBONDED_DO_LR;
        }

        wallcycle_sub_start(wcycle, ewcsNONBONDED);
        do_nonbonded(fr, x, f, f_longrange, md, excl,
                     &enerd->grpp, nrnb,
                     lambda, dvdl_nb, -1, -1, donb_flags);

        /* If we do foreign lambda and we have soft-core interactions
         * we have to recalculate the (non-linear) energies contributions.
         */
        if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0)
        {
            for (i = 0; i < enerd->n_lambda; i++)
            {
                real lam_i[efptNR];

                for (j = 0; j < efptNR; j++)
                {
                    lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                }
                reset_foreign_enerdata(enerd);
                do_nonbonded(fr, x, f, f_longrange, md, excl,
                             &(enerd->foreign_grpp), nrnb,
                             lam_i, dvdl_dum, -1, -1,
                             (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA);
                sum_epot(&(enerd->foreign_grpp), enerd->foreign_term);
                enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
            }
        }
        wallcycle_sub_stop(wcycle, ewcsNONBONDED);
        where();
    }

    /* If we are doing GB, calculate bonded forces and apply corrections
     * to the solvation forces */
    /* MRS: Eventually, many need to include free energy contribution here! */
    if (ir->implicit_solvent)
    {
        wallcycle_sub_start(wcycle, ewcsLISTED);
        calc_gb_forces(cr, md, born, top, x, f, fr, idef,
                       ir->gb_algorithm, ir->sa_algorithm, nrnb, &pbc, graph, enerd);
        wallcycle_sub_stop(wcycle, ewcsLISTED);
    }

#ifdef GMX_MPI
    if (TAKETIME)
    {
        t1          = MPI_Wtime();
        fr->t_fnbf += t1-t0;
    }
#endif

    if (fepvals->sc_alpha != 0)
    {
        enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW];
    }
    else
    {
        enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW];
    }

    if (fepvals->sc_alpha != 0)

    /* even though coulomb part is linear, we already added it, beacuse we
       need to go through the vdw calculation anyway */
    {
        enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL];
    }
    else
    {
        enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL];
    }

    debug_gmx();


    if (debug)
    {
        pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS);
    }

    /* Shift the coordinates. Must be done before listed forces and PPPM,
     * but is also necessary for SHAKE and update, therefore it can NOT
     * go when no listed forces have to be evaluated.
     *
     * The shifting and PBC code is deliberately not timed, since with
     * the Verlet scheme it only takes non-zero time with triclinic
     * boxes, and even then the time is around a factor of 100 less
     * than the next smallest counter.
     */


    /* Here sometimes we would not need to shift with NBFonly,
     * but we do so anyhow for consistency of the returned coordinates.
     */
    if (graph)
    {
        shift_self(graph, box, x);
        if (TRICLINIC(box))
        {
            inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes);
        }
        else
        {
            inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes);
        }
    }
    /* Check whether we need to do listed interactions or correct for exclusions */
    if (fr->bMolPBC &&
        ((flags & GMX_FORCE_LISTED)
         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype)))
    {
        /* TODO There are no electrostatics methods that require this
           transformation, when using the Verlet scheme, so update the
           above conditional. */
        /* Since all atoms are in the rectangular or triclinic unit-cell,
         * only single box vector shifts (2 in x) are required.
         */
        set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box);
    }
    debug_gmx();

    do_force_listed(wcycle, box, ir->fepvals, cr->ms,
                    idef, (const rvec *) x, hist, f, fr,
                    &pbc, graph, enerd, nrnb, lambda, md, fcd,
                    DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL,
                    flags);

    where();

    *cycles_pme = 0;
    clear_mat(fr->vir_el_recip);
    clear_mat(fr->vir_lj_recip);

    /* Do long-range electrostatics and/or LJ-PME, including related short-range
     * corrections.
     */
    if (EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype))
    {
        int  status            = 0;
        real Vlr_q             = 0, Vlr_lj = 0, Vcorr_q = 0, Vcorr_lj = 0;
        real dvdl_long_range_q = 0, dvdl_long_range_lj = 0;

        bSB = (ir->nwall == 2);
        if (bSB)
        {
            copy_mat(box, boxs);
            svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]);
            box_size[ZZ] *= ir->wall_ewald_zfac;
        }

        if (EEL_PME_EWALD(fr->eeltype) || EVDW_PME(fr->vdwtype))
        {
            real dvdl_long_range_correction_q   = 0;
            real dvdl_long_range_correction_lj  = 0;
            /* With the Verlet scheme exclusion forces are calculated
             * in the non-bonded kernel.
             */
            /* The TPI molecule does not have exclusions with the rest
             * of the system and no intra-molecular PME grid
             * contributions will be calculated in
             * gmx_pme_calc_energy.
             */
            if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) ||
                ir->ewald_geometry != eewg3D ||
                ir->epsilon_surface != 0)
            {
                int nthreads, t;

                wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION);

                if (fr->n_tpi > 0)
                {
                    gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions");
                }

                nthreads = fr->nthread_ewc;
#pragma omp parallel for num_threads(nthreads) schedule(static)
                for (t = 0; t < nthreads; t++)
                {
                    try
                    {
                        tensor *vir_q, *vir_lj;
                        real   *Vcorrt_q, *Vcorrt_lj, *dvdlt_q, *dvdlt_lj;
                        if (t == 0)
                        {
                            vir_q     = &fr->vir_el_recip;
                            vir_lj    = &fr->vir_lj_recip;
                            Vcorrt_q  = &Vcorr_q;
                            Vcorrt_lj = &Vcorr_lj;
                            dvdlt_q   = &dvdl_long_range_correction_q;
                            dvdlt_lj  = &dvdl_long_range_correction_lj;
                        }
                        else
                        {
                            vir_q     = &fr->ewc_t[t].vir_q;
                            vir_lj    = &fr->ewc_t[t].vir_lj;
                            Vcorrt_q  = &fr->ewc_t[t].Vcorr_q;
                            Vcorrt_lj = &fr->ewc_t[t].Vcorr_lj;
                            dvdlt_q   = &fr->ewc_t[t].dvdl[efptCOUL];
                            dvdlt_lj  = &fr->ewc_t[t].dvdl[efptVDW];
                            clear_mat(*vir_q);
                            clear_mat(*vir_lj);
                        }
                        *dvdlt_q  = 0;
                        *dvdlt_lj = 0;

                        /* Threading is only supported with the Verlet cut-off
                         * scheme and then only single particle forces (no
                         * exclusion forces) are calculated, so we can store
                         * the forces in the normal, single fr->f_novirsum array.
                         */
                        ewald_LRcorrection(fr->excl_load[t], fr->excl_load[t+1],
                                           cr, t, fr,
                                           md->chargeA, md->chargeB,
                                           md->sqrt_c6A, md->sqrt_c6B,
                                           md->sigmaA, md->sigmaB,
                                           md->sigma3A, md->sigma3B,
                                           md->nChargePerturbed || md->nTypePerturbed,
                                           ir->cutoff_scheme != ecutsVERLET,
                                           excl, x, bSB ? boxs : box, mu_tot,
                                           ir->ewald_geometry,
                                           ir->epsilon_surface,
                                           fr->f_novirsum, *vir_q, *vir_lj,
                                           Vcorrt_q, Vcorrt_lj,
                                           lambda[efptCOUL], lambda[efptVDW],
                                           dvdlt_q, dvdlt_lj);
                    }
                    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
                }
                if (nthreads > 1)
                {
                    reduce_thread_energies(fr->vir_el_recip, fr->vir_lj_recip,
                                           &Vcorr_q, &Vcorr_lj,
                                           &dvdl_long_range_correction_q,
                                           &dvdl_long_range_correction_lj,
                                           nthreads, fr->ewc_t);
                }
                wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION);
            }
Exemplo n.º 22
0
int gmx_spatial(int argc,char *argv[])
{
  const char *desc[] = {
    "g_spatial calculates the spatial distribution function and ",
    "outputs it in a form that can be read by VMD as Gaussian98 cube format. ",
    "This was developed from template.c (gromacs-3.3). ",
    "For a system of 32K atoms and a 50ns trajectory, the SDF can be generated ",
    "in about 30 minutes, with most of the time dedicated to the two runs through ",
    "trjconv that are required to center everything properly. ",
    "This also takes a whole bunch of space (3 copies of the xtc file). ",
    "Still, the pictures are pretty and very informative when the fitted selection is properly made. ",
    "3-4 atoms in a widely mobile group like a free amino acid in solution works ",
    "well, or select the protein backbone in a stable folded structure to get the SDF ",
    "of solvent and look at the time-averaged solvation shell. ",
    "It is also possible using this program to generate the SDF based on some arbitrarty ",
    "Cartesian coordinate. To do that, simply omit the preliminary trjconv steps. \n",
    "USAGE: \n",
    "1. Use make_ndx to create a group containing the atoms around which you want the SDF \n",
    "2. trjconv -s a.tpr -f a.xtc -o b.xtc -center tric -ur compact -pbc none \n",
    "3. trjconv -s a.tpr -f b.xtc -o c.xtc -fit rot+trans \n",
    "4. run g_spatial on the xtc output of step #3. \n",
    "5. Load grid.cube into VMD and view as an isosurface. \n",
    "*** Systems such as micelles will require trjconv -pbc cluster between steps 1 and 2\n",
    "WARNINGS: \n",
    "The SDF will be generated for a cube that contains all bins that have some non-zero occupancy. ",
    "However, the preparatory -fit rot+trans option to trjconv implies that your system will be rotating ",
    "and translating in space (in order that the selected group does not). Therefore the values that are ",
    "returned will only be valid for some region around your central group/coordinate that has full overlap ",
    "with system volume throughout the entire translated/rotated system over the course of the trajectory. ",
    "It is up to the user to ensure that this is the case. \n",
    "BUGS: \n",
    "When the allocated memory is not large enough, a segmentation fault may occur. This is usually detected ",
    "and the program is halted prior to the fault while displaying a warning message suggesting the use of the -nab ",
    "option. However, the program does not detect all such events. If you encounter a segmentation fault, run it again ",
    "with an increased -nab value. \n",
    "RISKY OPTIONS: \n",
    "To reduce the amount of space and time required, you can output only the coords ",
    "that are going to be used in the first and subsequent run through trjconv. ",
    "However, be sure to set the -nab option to a sufficiently high value since ",
    "memory is allocated for cube bins based on the initial coords and the -nab ",
    "(Number of Additional Bins) option value. \n"
  };
  
  static gmx_bool bPBC=FALSE;
  static gmx_bool bSHIFT=FALSE;
  static int iIGNOREOUTER=-1; /*Positive values may help if the surface is spikey */
  static gmx_bool bCUTDOWN=TRUE;
  static real rBINWIDTH=0.05; /* nm */
  static gmx_bool bCALCDIV=TRUE;
  static int iNAB=4;

  t_pargs pa[] = {
    { "-pbc",      FALSE, etBOOL, {&bPBC},
      "Use periodic boundary conditions for computing distances" },
    { "-div",      FALSE, etBOOL, {&bCALCDIV},
      "Calculate and apply the divisor for bin occupancies based on atoms/minimal cube size. Set as TRUE for visualization and as FALSE (-nodiv) to get accurate counts per frame" },
    { "-ign",      FALSE, etINT, {&iIGNOREOUTER},
      "Do not display this number of outer cubes (positive values may reduce boundary speckles; -1 ensures outer surface is visible)" },
    /*    { "-cut",      bCUTDOWN, etBOOL, {&bCUTDOWN},*/
    /*      "Display a total cube that is of minimal size" }, */
    { "-bin",      FALSE, etREAL, {&rBINWIDTH},
      "Width of the bins in nm" },
    { "-nab",      FALSE, etINT, {&iNAB},
      "Number of additional bins to ensure proper memory allocation" }
  };

  double MINBIN[3];
  double MAXBIN[3];
  t_topology top;
  int        ePBC;
  char       title[STRLEN];
  t_trxframe fr;
  rvec       *xtop,*shx[26];
  matrix     box,box_pbc;
  t_trxstatus *status;
  int        flags = TRX_READ_X;
  t_pbc      pbc;
  t_atoms    *atoms;
  int        natoms;
  char        *grpnm,*grpnmp;
  atom_id     *index,*indexp;
  int         i,nidx,nidxp;
  int v;
  int j,k;
  long ***bin=(long ***)NULL;
  long nbin[3];
  FILE *flp;
  long x,y,z,minx,miny,minz,maxx,maxy,maxz;
  long numfr, numcu;
  long tot,max,min;
  double norm;
  output_env_t oenv;
  gmx_rmpbc_t  gpbc=NULL;

  t_filenm fnm[] = {
    { efTPS,  NULL,  NULL, ffREAD },   /* this is for the topology */
    { efTRX, "-f", NULL, ffREAD },      /* and this for the trajectory */
    { efNDX, NULL, NULL, ffOPTRD }
  };
  
#define NFILE asize(fnm)

  CopyRight(stderr,argv[0]);

  /* This is the routine responsible for adding default options,
   * calling the X/motif interface, etc. */
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);

  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,TRUE);
  sfree(xtop);

  atoms=&(top.atoms);
  printf("Select group to generate SDF:\n");
  get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&nidx,&index,&grpnm);
  printf("Select group to output coords (e.g. solute):\n");
  get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&nidxp,&indexp,&grpnmp);

  /* The first time we read data is a little special */
  natoms=read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,flags);

  /* Memory Allocation */
  MINBIN[XX]=MAXBIN[XX]=fr.x[0][XX];
  MINBIN[YY]=MAXBIN[YY]=fr.x[0][YY];
  MINBIN[ZZ]=MAXBIN[ZZ]=fr.x[0][ZZ];
  for(i=1; i<top.atoms.nr; ++i) {
    if(fr.x[i][XX]<MINBIN[XX])MINBIN[XX]=fr.x[i][XX];
    if(fr.x[i][XX]>MAXBIN[XX])MAXBIN[XX]=fr.x[i][XX];
    if(fr.x[i][YY]<MINBIN[YY])MINBIN[YY]=fr.x[i][YY];
    if(fr.x[i][YY]>MAXBIN[YY])MAXBIN[YY]=fr.x[i][YY];
    if(fr.x[i][ZZ]<MINBIN[ZZ])MINBIN[ZZ]=fr.x[i][ZZ];
    if(fr.x[i][ZZ]>MAXBIN[ZZ])MAXBIN[ZZ]=fr.x[i][ZZ];
  }
  for (i=ZZ; i>=XX; --i){
    MAXBIN[i]=(ceil((MAXBIN[i]-MINBIN[i])/rBINWIDTH)+(double)iNAB)*rBINWIDTH+MINBIN[i];
    MINBIN[i]-=(double)iNAB*rBINWIDTH; 
    nbin[i]=(long)ceil((MAXBIN[i]-MINBIN[i])/rBINWIDTH);
  }
  bin=(long ***)malloc(nbin[XX]*sizeof(long **));
  if(!bin)mequit();
  for(i=0; i<nbin[XX]; ++i){
    bin[i]=(long **)malloc(nbin[YY]*sizeof(long *));
    if(!bin[i])mequit();
    for(j=0; j<nbin[YY]; ++j){
      bin[i][j]=(long *)calloc(nbin[ZZ],sizeof(long));
      if(!bin[i][j])mequit();
    }
  }
  copy_mat(box,box_pbc); 
  numfr=0;
  minx=miny=minz=999;
  maxx=maxy=maxz=0;

  if (bPBC)
    gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
  /* This is the main loop over frames */
  do {
    /* Must init pbc every step because of pressure coupling */

    copy_mat(box,box_pbc);
    if (bPBC) {
      gmx_rmpbc_trxfr(gpbc,&fr);
      set_pbc(&pbc,ePBC,box_pbc);
    }

    for(i=0; i<nidx; i++) {
      if(fr.x[index[i]][XX]<MINBIN[XX]||fr.x[index[i]][XX]>MAXBIN[XX]||
         fr.x[index[i]][YY]<MINBIN[YY]||fr.x[index[i]][YY]>MAXBIN[YY]||
         fr.x[index[i]][ZZ]<MINBIN[ZZ]||fr.x[index[i]][ZZ]>MAXBIN[ZZ])
	{
	  printf("There was an item outside of the allocated memory. Increase the value given with the -nab option.\n");
	  printf("Memory was allocated for [%f,%f,%f]\tto\t[%f,%f,%f]\n",MINBIN[XX],MINBIN[YY],MINBIN[ZZ],MAXBIN[XX],MAXBIN[YY],MAXBIN[ZZ]);
	  printf("Memory was required for [%f,%f,%f]\n",fr.x[index[i]][XX],fr.x[index[i]][YY],fr.x[index[i]][ZZ]);
	  exit(1);
	}
      x=(long)ceil((fr.x[index[i]][XX]-MINBIN[XX])/rBINWIDTH);
      y=(long)ceil((fr.x[index[i]][YY]-MINBIN[YY])/rBINWIDTH);
      z=(long)ceil((fr.x[index[i]][ZZ]-MINBIN[ZZ])/rBINWIDTH);
      ++bin[x][y][z];
      if(x<minx)minx=x;
      if(x>maxx)maxx=x;
      if(y<miny)miny=y;
      if(y>maxy)maxy=y;
      if(z<minz)minz=z;
      if(z>maxz)maxz=z;
    }
    numfr++;
    /* printf("%f\t%f\t%f\n",box[XX][XX],box[YY][YY],box[ZZ][ZZ]); */

  } while(read_next_frame(oenv,status,&fr));

  if (bPBC)
    gmx_rmpbc_done(gpbc);

  if(!bCUTDOWN){
    minx=miny=minz=0;
    maxx=nbin[XX];
    maxy=nbin[YY];
    maxz=nbin[ZZ];
  }

  /* OUTPUT */
  flp=ffopen("grid.cube","w");
  fprintf(flp,"Spatial Distribution Function\n");
  fprintf(flp,"test\n");
  fprintf(flp,"%5d%12.6f%12.6f%12.6f\n",nidxp,(MINBIN[XX]+(minx+iIGNOREOUTER)*rBINWIDTH)*10./bohr,(MINBIN[YY]+(miny+iIGNOREOUTER)*rBINWIDTH)*10./bohr,(MINBIN[ZZ]+(minz+iIGNOREOUTER)*rBINWIDTH)*10./bohr);
  fprintf(flp,"%5ld%12.6f%12.6f%12.6f\n",maxx-minx+1-(2*iIGNOREOUTER),rBINWIDTH*10./bohr,0.,0.);
  fprintf(flp,"%5ld%12.6f%12.6f%12.6f\n",maxy-miny+1-(2*iIGNOREOUTER),0.,rBINWIDTH*10./bohr,0.);
  fprintf(flp,"%5ld%12.6f%12.6f%12.6f\n",maxz-minz+1-(2*iIGNOREOUTER),0.,0.,rBINWIDTH*10./bohr);
  for(i=0; i<nidxp; i++){
    v=2;
    if(*(top.atoms.atomname[indexp[i]][0])=='C')v=6;
    if(*(top.atoms.atomname[indexp[i]][0])=='N')v=7;
    if(*(top.atoms.atomname[indexp[i]][0])=='O')v=8;
    if(*(top.atoms.atomname[indexp[i]][0])=='H')v=1;
    if(*(top.atoms.atomname[indexp[i]][0])=='S')v=16;
    fprintf(flp,"%5d%12.6f%12.6f%12.6f%12.6f\n",v,0.,(double)fr.x[indexp[i]][XX]*10./bohr,(double)fr.x[indexp[i]][YY]*10./bohr,(double)fr.x[indexp[i]][ZZ]*10./bohr);
  }

  tot=0;
  for(k=0;k<nbin[XX];k++) {
    if(!(k<minx||k>maxx))continue;
    for(j=0;j<nbin[YY];j++) {
      if(!(j<miny||j>maxy))continue;
      for(i=0;i<nbin[ZZ];i++) {
	if(!(i<minz||i>maxz))continue;
	if(bin[k][j][i]!=0){
	  printf("A bin was not empty when it should have been empty. Programming error.\n");
	  printf("bin[%d][%d][%d] was = %ld\n",k,j,i,bin[k][j][i]);
	  exit(1);
	}
      }
    }
  }

  min=999;
  max=0;
  for(k=0;k<nbin[XX];k++) {
    if(k<minx+iIGNOREOUTER||k>maxx-iIGNOREOUTER)continue;
    for(j=0;j<nbin[YY];j++) {
      if(j<miny+iIGNOREOUTER||j>maxy-iIGNOREOUTER)continue;
      for(i=0;i<nbin[ZZ];i++) {
	if(i<minz+iIGNOREOUTER||i>maxz-iIGNOREOUTER)continue;
	tot+=bin[k][j][i];
	if(bin[k][j][i]>max)max=bin[k][j][i];
	if(bin[k][j][i]<min)min=bin[k][j][i];
      }
    }
  }

  numcu=(maxx-minx+1-(2*iIGNOREOUTER))*(maxy-miny+1-(2*iIGNOREOUTER))*(maxz-minz+1-(2*iIGNOREOUTER));
  if(bCALCDIV){
    norm=((double)numcu*(double)numfr) / (double)tot;
  }else{
    norm=1.0;
  }

  for(k=0;k<nbin[XX];k++) {
    if(k<minx+iIGNOREOUTER||k>maxx-iIGNOREOUTER)continue;
    for(j=0;j<nbin[YY];j++) {
      if(j<miny+iIGNOREOUTER||j>maxy-iIGNOREOUTER)continue;
      for(i=0;i<nbin[ZZ];i++) {
	if(i<minz+iIGNOREOUTER||i>maxz-iIGNOREOUTER)continue;
	fprintf(flp,"%12.6f ",norm*(double)bin[k][j][i]/(double)numfr);
      }
      fprintf(flp,"\n");
    }
    fprintf(flp,"\n");
  }
  ffclose(flp);

  /* printf("x=%d to %d\n",minx,maxx); */
  /* printf("y=%d to %d\n",miny,maxy); */
  /* printf("z=%d to %d\n",minz,maxz); */

  if(bCALCDIV){
    printf("Counts per frame in all %ld cubes divided by %le\n",numcu,1.0/norm);
    printf("Normalized data: average %le, min %le, max %le\n",1.0,norm*(double)min/(double)numfr,norm*(double)max/(double)numfr);
  }else{
    printf("grid.cube contains counts per frame in all %ld cubes\n",numcu);
    printf("Raw data: average %le, min %le, max %le\n",1.0/norm,(double)min/(double)numfr,(double)max/(double)numfr);
  }

  thanx(stderr);
  
  return 0;
}
Exemplo n.º 23
0
static char *insert_mols(char *mol_insrt,int nmol_insrt,int ntry,int seed,
			 t_atoms *atoms,rvec **x,real **r,int ePBC,matrix box,
			 gmx_atomprop_t aps,real r_distance,real rshell)
{
  t_pbc   pbc;
  static  char    *title_insrt;
  t_atoms atoms_insrt;
  rvec    *x_insrt,*x_n;
  real    *r_insrt;
  int     ePBC_insrt;
  matrix  box_insrt;
  int     i,mol,onr;
  real    alfa,beta,gamma;
  rvec    offset_x;
  int     try;
   
  set_pbc(&pbc,ePBC,box);
  
  /* read number of atoms of insert molecules */
  get_stx_coordnum(mol_insrt,&atoms_insrt.nr);
  if (atoms_insrt.nr == 0)
    gmx_fatal(FARGS,"No molecule in %s, please check your input\n",mol_insrt);
  /* allocate memory for atom coordinates of insert molecules */
  snew(x_insrt,atoms_insrt.nr);
  snew(r_insrt,atoms_insrt.nr);
  snew(atoms_insrt.resname,atoms_insrt.nr);
  snew(atoms_insrt.atomname,atoms_insrt.nr);
  snew(atoms_insrt.atom,atoms_insrt.nr);
  atoms_insrt.pdbinfo = NULL;
  snew(x_n,atoms_insrt.nr);
  snew(title_insrt,STRLEN);
  
  /* read residue number, residue names, atomnames, coordinates etc. */
  fprintf(stderr,"Reading molecule configuration \n");
  read_stx_conf(mol_insrt,title_insrt,&atoms_insrt,x_insrt,NULL,
		&ePBC_insrt,box_insrt);
  fprintf(stderr,"%s\nContaining %d atoms in %d residue\n",
	  title_insrt,atoms_insrt.nr,atoms_insrt.nres);
  srenew(atoms_insrt.resname,atoms_insrt.nres);  
    
  /* initialise van der waals arrays of insert molecules */
  mk_vdw(&atoms_insrt,r_insrt,aps,r_distance);

  srenew(atoms->resname,(atoms->nres+nmol_insrt));
  srenew(atoms->atomname,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  srenew(atoms->atom,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  srenew(*x,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  srenew(*r,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  
  try=mol=0;
  while ((mol < nmol_insrt) && (try < ntry*nmol_insrt)) {
    fprintf(stderr,"\rTry %d",try++);
    for (i=0;(i<atoms_insrt.nr);i++) {
      if (atoms_insrt.atom[i].resnr!=0) 
	gmx_fatal(FARGS,"more then one residue in insert molecules\n"
		    "program terminated\n");
      copy_rvec(x_insrt[i],x_n[i]);
    }
    alfa=2*M_PI*rando(&seed);
    beta=2*M_PI*rando(&seed);
    gamma=2*M_PI*rando(&seed);
    rotate_conf(atoms_insrt.nr,x_n,NULL,alfa,beta,gamma);
    offset_x[XX]=box[XX][XX]*rando(&seed);
    offset_x[YY]=box[YY][YY]*rando(&seed);
    offset_x[ZZ]=box[ZZ][ZZ]*rando(&seed);
    gen_box(0,atoms_insrt.nr,x_n,box_insrt,offset_x,TRUE);
    if (!in_box(&pbc,x_n[0]) || !in_box(&pbc,x_n[atoms_insrt.nr-1]))
      continue;
    onr=atoms->nr;
    
    add_conf(atoms,x,NULL,r,FALSE,ePBC,box,TRUE,
	     &atoms_insrt,x_n,NULL,r_insrt,FALSE,rshell,0);
    
    if (atoms->nr==(atoms_insrt.nr+onr)) {
      mol++;
      fprintf(stderr," success (now %d atoms)!",atoms->nr);
    }
  }
  srenew(atoms->resname,  atoms->nres);
  srenew(atoms->atomname, atoms->nr);
  srenew(atoms->atom,     atoms->nr);
  srenew(*x,              atoms->nr);
  srenew(*r,              atoms->nr);
  
  fprintf(stderr,"\n");
  /* print number of molecules added */
  fprintf(stderr,"Added %d molecules (out of %d requested) of %s\n",
	  mol,nmol_insrt,*atoms_insrt.resname[0]); 
    
  return title_insrt;
}

static void add_solv(char *fn,t_atoms *atoms,rvec **x,rvec **v,real **r,
		     int ePBC,matrix box,
		     gmx_atomprop_t aps,real r_distance,int *atoms_added,
		     int *residues_added,real rshell,int max_sol)
{
  int     i,nmol;
  ivec    n_box;
  char    filename[STRLEN];
  char    title_solvt[STRLEN];
  t_atoms *atoms_solvt;
  rvec    *x_solvt,*v_solvt=NULL;
  real    *r_solvt;
  int     ePBC_solvt;
  matrix  box_solvt;
  int     onr,onres;

  strncpy(filename,libfn(fn),STRLEN);
  snew(atoms_solvt,1);
  get_stx_coordnum(filename,&(atoms_solvt->nr)); 
  if (atoms_solvt->nr == 0)
    gmx_fatal(FARGS,"No solvent in %s, please check your input\n",filename);
  snew(x_solvt,atoms_solvt->nr);
  if (v) snew(v_solvt,atoms_solvt->nr);
  snew(r_solvt,atoms_solvt->nr);
  snew(atoms_solvt->resname,atoms_solvt->nr);
  snew(atoms_solvt->atomname,atoms_solvt->nr);
  snew(atoms_solvt->atom,atoms_solvt->nr);
  atoms_solvt->pdbinfo = NULL;
  fprintf(stderr,"Reading solvent configuration%s\n",
	  v_solvt?" and velocities":"");
  read_stx_conf(filename,title_solvt,atoms_solvt,x_solvt,v_solvt,
		&ePBC_solvt,box_solvt);
  fprintf(stderr,"\"%s\"\n",title_solvt);
  fprintf(stderr,"solvent configuration contains %d atoms in %d residues\n",
	  atoms_solvt->nr,atoms_solvt->nres);
  fprintf(stderr,"\n");
  
  /* apply pbc for solvent configuration for whole molecules */
  rm_res_pbc(atoms_solvt,x_solvt,box_solvt);
  
  /* initialise van der waals arrays of solvent configuration */
  mk_vdw(atoms_solvt,r_solvt,aps,r_distance);
  
  /* calculate the box multiplication factors n_box[0...DIM] */
  nmol=1;
  for (i=0; (i < DIM);i++) {
    n_box[i] = 1;
    while (n_box[i]*box_solvt[i][i] < box[i][i])
      n_box[i]++;
    nmol*=n_box[i];
  }
  fprintf(stderr,"Will generate new solvent configuration of %dx%dx%d boxes\n",
	  n_box[XX],n_box[YY],n_box[ZZ]);
  
  /* realloc atoms_solvt for the new solvent configuration */
  srenew(atoms_solvt->resname,atoms_solvt->nres*nmol);
  srenew(atoms_solvt->atomname,atoms_solvt->nr*nmol);
  srenew(atoms_solvt->atom,atoms_solvt->nr*nmol);
  srenew(x_solvt,atoms_solvt->nr*nmol);
  if (v_solvt) srenew(v_solvt,atoms_solvt->nr*nmol);
  srenew(r_solvt,atoms_solvt->nr*nmol);
  
  /* generate a new solvent configuration */
  genconf(atoms_solvt,x_solvt,v_solvt,r_solvt,box_solvt,n_box);

#ifdef DEBUG
  print_stat(x_solvt,atoms_solvt->nr,box_solvt);
#endif
  
#ifdef DEBUG
  print_stat(x_solvt,atoms_solvt->nr,box_solvt);
#endif
  /* Sort the solvent mixture, not the protein... */
  sort_molecule(&atoms_solvt,x_solvt,v_solvt,r_solvt);
  
  /* add the two configurations */
  onr=atoms->nr;
  onres=atoms->nres;
  add_conf(atoms,x,v,r,TRUE,ePBC,box,FALSE,
	   atoms_solvt,x_solvt,v_solvt,r_solvt,TRUE,rshell,max_sol);
  *atoms_added=atoms->nr-onr;
  *residues_added=atoms->nres-onres;
  
  sfree(x_solvt);
  sfree(r_solvt);

  fprintf(stderr,"Generated solvent containing %d atoms in %d residues\n",
	  *atoms_added,*residues_added);
}
Exemplo n.º 24
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");
        }
    }
}
Exemplo n.º 25
0
int gmx_saltbr(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_saltbr[tt] plots the distance between all combination of charged groups",
        "as a function of time. The groups are combined in different ways.",
        "A minimum distance can be given (i.e. a cut-off), such that groups",
        "that are never closer than that distance will not be plotted.[PAR]",
        "Output will be in a number of fixed filenames, [TT]min-min.xvg[tt], [TT]plus-min.xvg[tt]",
        "and [TT]plus-plus.xvg[tt], or files for every individual ion pair if the [TT]-sep[tt]",
        "option is selected. In this case, files are named as [TT]sb-(Resname)(Resnr)-(Atomnr)[tt].",
        "There may be [BB]many[bb] such files."
    };
    static gmx_bool bSep     = FALSE;
    static real     truncate = 1000.0;
    t_pargs         pa[]     = {
        { "-t",   FALSE, etREAL, {&truncate},
          "Groups that are never closer than this distance are not plotted" },
        { "-sep", FALSE, etBOOL, {&bSep},
          "Use separate files for each interaction (may be MANY)" }
    };
    t_filenm        fnm[] = {
        { efTRX, "-f",  NULL, ffREAD },
        { efTPX, NULL,  NULL, ffREAD },
    };
#define NFILE asize(fnm)

    FILE              *out[3], *fp;
    static const char *title[3] = {
        "Distance between positively charged groups",
        "Distance between negatively charged groups",
        "Distance between oppositely charged groups"
    };
    static const char *fn[3] = {
        "plus-plus.xvg",
        "min-min.xvg",
        "plus-min.xvg"
    };
    int                nset[3] = {0, 0, 0};

    t_topology        *top;
    int                ePBC;
    char              *buf;
    t_trxstatus       *status;
    int                i, j, k, m, nnn, teller, ncg, n1, n2, n3, natoms;
    real               t, *time, qi, qj;
    t_charge          *cg;
    real            ***cgdist;
    int              **nWithin;

    double             t0, dt;
    char               label[234];
    t_pbc              pbc;
    rvec              *x;
    matrix             box;
    output_env_t       oenv;

    parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv);

    top = read_top(ftp2fn(efTPX, NFILE, fnm), &ePBC);
    cg  = mk_charge(&top->atoms, &(top->cgs), &ncg);
    snew(cgdist, ncg);
    snew(nWithin, ncg);
    for (i = 0; (i < ncg); i++)
    {
        snew(cgdist[i], ncg);
        snew(nWithin[i], ncg);
    }

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    teller = 0;
    time   = NULL;
    do
    {
        srenew(time, teller+1);
        time[teller] = t;

        set_pbc(&pbc, ePBC, box);

        for (i = 0; (i < ncg); i++)
        {
            for (j = i+1; (j < ncg); j++)
            {
                srenew(cgdist[i][j], teller+1);
                cgdist[i][j][teller] =
                    calc_dist(&pbc, x, &(top->cgs), cg[i].cg, cg[j].cg);
                if (cgdist[i][j][teller] < truncate)
                {
                    nWithin[i][j] = 1;
                }
            }
        }

        teller++;
    }
    while (read_next_x(oenv, status, &t, natoms, x, box));
    fprintf(stderr, "\n");
    close_trj(status);

    if (bSep)
    {
        snew(buf, 256);
        for (i = 0; (i < ncg); i++)
        {
            for (j = i+1; (j < ncg); j++)
            {
                if (nWithin[i][j])
                {
                    sprintf(buf, "sb-%s:%s.xvg", cg[i].label, cg[j].label);
                    fp = xvgropen(buf, buf, "Time (ps)", "Distance (nm)", oenv);
                    for (k = 0; (k < teller); k++)
                    {
                        fprintf(fp, "%10g  %10g\n", time[k], cgdist[i][j][k]);
                    }
                    ffclose(fp);
                }
            }
        }
        sfree(buf);
    }
    else
    {

        for (m = 0; (m < 3); m++)
        {
            out[m] = xvgropen(fn[m], title[m], "Time (ps)", "Distance (nm)", oenv);
        }

        snew(buf, 256);
        for (i = 0; (i < ncg); i++)
        {
            qi = cg[i].q;
            for (j = i+1; (j < ncg); j++)
            {
                qj = cg[j].q;
                if (nWithin[i][j])
                {
                    sprintf(buf, "%s:%s", cg[i].label, cg[j].label);
                    if (qi*qj < 0)
                    {
                        nnn = 2;
                    }
                    else if (qi+qj > 0)
                    {
                        nnn = 0;
                    }
                    else
                    {
                        nnn = 1;
                    }

                    if (nset[nnn] == 0)
                    {
                        xvgr_legend(out[nnn], 1, (const char**)&buf, oenv);
                    }
                    else
                    {
                        if (output_env_get_xvg_format(oenv) == exvgXMGR)
                        {
                            fprintf(out[nnn], "@ legend string %d \"%s\"\n", nset[nnn], buf);
                        }
                        else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
                        {
                            fprintf(out[nnn], "@ s%d legend \"%s\"\n", nset[nnn], buf);
                        }
                    }
                    nset[nnn]++;
                    nWithin[i][j] = nnn+1;
                }
            }
        }
        for (k = 0; (k < teller); k++)
        {
            for (m = 0; (m < 3); m++)
            {
                fprintf(out[m], "%10g", time[k]);
            }

            for (i = 0; (i < ncg); i++)
            {
                for (j = i+1; (j < ncg); j++)
                {
                    nnn = nWithin[i][j];
                    if (nnn > 0)
                    {
                        fprintf(out[nnn-1], "  %10g", cgdist[i][j][k]);
                    }
                }
            }
            for (m = 0; (m < 3); m++)
            {
                fprintf(out[m], "\n");
            }
        }
        for (m = 0; (m < 3); m++)
        {
            ffclose(out[m]);
            if (nset[m] == 0)
            {
                remove(fn[m]);
            }
        }
    }
    thanx(stderr);

    return 0;
}
Exemplo n.º 26
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;
  } 
}
Exemplo n.º 27
0
int gmx_genion(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] randomly replaces solvent molecules with monoatomic ions.",
        "The group of solvent molecules should be continuous and all molecules",
        "should have the same number of atoms.",
        "The user should add the ion molecules to the topology file or use",
        "the [TT]-p[tt] option to automatically modify the topology.[PAR]",
        "The ion molecule type, residue and atom names in all force fields",
        "are the capitalized element names without sign. This molecule name",
        "should be given with [TT]-pname[tt] or [TT]-nname[tt], and the",
        "[TT][molecules][tt] section of your topology updated accordingly,",
        "either by hand or with [TT]-p[tt]. Do not use an atom name instead!",
        "[PAR]Ions which can have multiple charge states get the multiplicity",
        "added, without sign, for the uncommon states only.[PAR]",
        "For larger ions, e.g. sulfate we recommended using [gmx-insert-molecules]."
    };
    const char        *bugs[] = {
        "If you specify a salt concentration existing ions are not taken into "
        "account. In effect you therefore specify the amount of salt to be added.",
    };
    static int         p_num    = 0, n_num = 0, p_q = 1, n_q = -1;
    static const char *p_name   = "NA", *n_name = "CL";
    static real        rmin     = 0.6, conc = 0;
    static int         seed     = 1993;
    static gmx_bool    bNeutral = FALSE;
    static t_pargs     pa[]     = {
        { "-np",    FALSE, etINT,  {&p_num}, "Number of positive ions"       },
        { "-pname", FALSE, etSTR,  {&p_name}, "Name of the positive ion"      },
        { "-pq",    FALSE, etINT,  {&p_q},   "Charge of the positive ion"    },
        { "-nn",    FALSE, etINT,  {&n_num}, "Number of negative ions"       },
        { "-nname", FALSE, etSTR,  {&n_name}, "Name of the negative ion"      },
        { "-nq",    FALSE, etINT,  {&n_q},   "Charge of the negative ion"    },
        { "-rmin",  FALSE, etREAL, {&rmin},  "Minimum distance between ions" },
        { "-seed",  FALSE, etINT,  {&seed},  "Seed for random number generator" },
        { "-conc",  FALSE, etREAL, {&conc},
          "Specify salt concentration (mol/liter). This will add sufficient ions to reach up to the specified concentration as computed from the volume of the cell in the input [REF].tpr[ref] file. Overrides the [TT]-np[tt] and [TT]-nn[tt] options." },
        { "-neutral", FALSE, etBOOL, {&bNeutral}, "This option will add enough ions to neutralize the system. These ions are added on top of those specified with [TT]-np[tt]/[TT]-nn[tt] or [TT]-conc[tt]. "}
    };
    t_topology         top;
    rvec              *x, *v;
    real               vol, qtot;
    matrix             box;
    t_atoms            atoms;
    t_pbc              pbc;
    int               *repl, ePBC;
    atom_id           *index;
    char              *grpname;
    gmx_bool          *bSet;
    int                i, nw, nwa, nsa, nsalt, iqtot;
    gmx_output_env_t  *oenv;
    gmx_rng_t          rng;
    t_filenm           fnm[] = {
        { efTPR, NULL,  NULL,      ffREAD  },
        { efNDX, NULL,  NULL,      ffOPTRD },
        { efSTO, "-o",  NULL,      ffWRITE },
        { efTOP, "-p",  "topol",   ffOPTRW }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa,
                           asize(desc), desc, asize(bugs), bugs, &oenv))
    {
        return 0;
    }

    /* Check input for something sensible */
    if ((p_num < 0) || (n_num < 0))
    {
        gmx_fatal(FARGS, "Negative number of ions to add?");
    }

    if (conc > 0 && (p_num > 0 || n_num > 0))
    {
        fprintf(stderr, "WARNING: -conc specified, overriding -nn and -np.\n");
    }

    /* Read atom positions and charges */
    read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &ePBC, &x, &v, box, FALSE);
    atoms = top.atoms;

    /* Compute total charge */
    qtot = 0;
    for (i = 0; (i < atoms.nr); i++)
    {
        qtot += atoms.atom[i].q;
    }
    iqtot = std::round(qtot);


    if (conc > 0)
    {
        /* Compute number of ions to be added */
        vol   = det(box);
        nsalt = std::round(conc*vol*AVOGADRO/1e24);
        p_num = abs(nsalt*n_q);
        n_num = abs(nsalt*p_q);
    }
    if (bNeutral)
    {
        int qdelta = p_num*p_q + n_num*n_q + iqtot;

        /* Check if the system is neutralizable
         * is (qdelta == p_q*p_num + n_q*n_num) solvable for p_num and n_num? */
        int gcd = gmx_greatest_common_divisor(n_q, p_q);
        if ((qdelta % gcd) != 0)
        {
            gmx_fatal(FARGS, "Can't neutralize this system using -nq %d and"
                      " -pq %d.\n", n_q, p_q);
        }

        while (qdelta != 0)
        {
            while (qdelta < 0)
            {
                p_num++;
                qdelta += p_q;
            }
            while (qdelta > 0)
            {
                n_num++;
                qdelta += n_q;
            }
        }
    }

    if ((p_num == 0) && (n_num == 0))
    {
        fprintf(stderr, "No ions to add, will just copy input configuration.\n");
    }
    else
    {
        printf("Will try to add %d %s ions and %d %s ions.\n",
               p_num, p_name, n_num, n_name);
        printf("Select a continuous group of solvent molecules\n");
        get_index(&atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &nwa, &index, &grpname);
        for (i = 1; i < nwa; i++)
        {
            if (index[i] != index[i-1]+1)
            {
                gmx_fatal(FARGS, "The solvent group %s is not continuous: "
                          "index[%d]=%d, index[%d]=%d",
                          grpname, i, index[i-1]+1, i+1, index[i]+1);
            }
        }
        nsa = 1;
        while ((nsa < nwa) &&
               (atoms.atom[index[nsa]].resind ==
                atoms.atom[index[nsa-1]].resind))
        {
            nsa++;
        }
        if (nwa % nsa)
        {
            gmx_fatal(FARGS, "Your solvent group size (%d) is not a multiple of %d",
                      nwa, nsa);
        }
        nw = nwa/nsa;
        fprintf(stderr, "Number of (%d-atomic) solvent molecules: %d\n", nsa, nw);
        if (p_num+n_num > nw)
        {
            gmx_fatal(FARGS, "Not enough solvent for adding ions");
        }

        if (opt2bSet("-p", NFILE, fnm))
        {
            update_topol(opt2fn("-p", NFILE, fnm), p_num, n_num, p_name, n_name, grpname);
        }

        snew(bSet, nw);
        snew(repl, nw);

        snew(v, atoms.nr);
        snew(atoms.pdbinfo, atoms.nr);

        set_pbc(&pbc, ePBC, box);

        if (seed == 0)
        {
            rng = gmx_rng_init(gmx_rng_make_seed());
        }
        else
        {
            rng = gmx_rng_init(seed);
        }
        /* Now loop over the ions that have to be placed */
        while (p_num-- > 0)
        {
            insert_ion(nsa, &nw, bSet, repl, index, x, &pbc,
                       1, p_q, p_name, &atoms, rmin, rng);
        }
        while (n_num-- > 0)
        {
            insert_ion(nsa, &nw, bSet, repl, index, x, &pbc,
                       -1, n_q, n_name, &atoms, rmin, rng);
        }
        gmx_rng_destroy(rng);
        fprintf(stderr, "\n");

        if (nw)
        {
            sort_ions(nsa, nw, repl, index, &atoms, x, p_name, n_name);
        }

        sfree(atoms.pdbinfo);
        atoms.pdbinfo = NULL;
    }
    write_sto_conf(ftp2fn(efSTO, NFILE, fnm), *top.name, &atoms, x, NULL, ePBC, box);

    return 0;
}
Exemplo n.º 28
0
void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                       t_forcerec *fr,      t_inputrec *ir,
                       t_idef     *idef,    t_commrec  *cr,
                       t_nrnb     *nrnb,    gmx_wallcycle_t wcycle,
                       t_mdatoms  *md,
                       t_grpopts  *opts,
                       rvec       x[],      history_t  *hist,
                       rvec       f[],
                       rvec       f_longrange[],
                       gmx_enerdata_t *enerd,
                       t_fcdata   *fcd,
                       gmx_mtop_t     *mtop,
                       gmx_localtop_t *top,
                       gmx_genborn_t *born,
                       t_atomtypes *atype,
                       gmx_bool       bBornRadii,
                       matrix     box,
                       t_lambda   *fepvals,
                       real       *lambda,
                       t_graph    *graph,
                       t_blocka   *excl,
                       rvec       mu_tot[],
                       int        flags,
                       float      *cycles_pme)
{
    int         i, j, status;
    int         donb_flags;
    gmx_bool    bDoEpot, bSepDVDL, bSB;
    int         pme_flags;
    matrix      boxs;
    rvec        box_size;
    real        Vsr, Vlr, Vcorr = 0;
    t_pbc       pbc;
    real        dvdgb;
    char        buf[22];
    double      clam_i, vlam_i;
    real        dvdl_dum[efptNR], dvdl, dvdl_nb[efptNR], lam_i[efptNR];
    real        dvdlsum;

#ifdef GMX_MPI
    double  t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */
#endif

#define PRINT_SEPDVDL(s, v, dvdlambda) if (bSepDVDL) {fprintf(fplog, sepdvdlformat, s, v, dvdlambda); }

    GMX_MPE_LOG(ev_force_start);
    set_pbc(&pbc, fr->ePBC, box);

    /* reset free energy components */
    for (i = 0; i < efptNR; i++)
    {
        dvdl_nb[i]  = 0;
        dvdl_dum[i] = 0;
    }

    /* Reset box */
    for (i = 0; (i < DIM); i++)
    {
        box_size[i] = box[i][i];
    }

    bSepDVDL = (fr->bSepDVDL && do_per_step(step, ir->nstlog));
    debug_gmx();

    /* do QMMM first if requested */
    if (fr->bQMMM)
    {
        enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr, md);
    }

    if (bSepDVDL)
    {
        fprintf(fplog, "Step %s: non-bonded V and dVdl for node %d:\n",
                gmx_step_str(step, buf), cr->nodeid);
    }

    /* Call the short range functions all in one go. */
    GMX_MPE_LOG(ev_do_fnbf_start);

#ifdef GMX_MPI
    /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/
#define TAKETIME FALSE
    if (TAKETIME)
    {
        MPI_Barrier(cr->mpi_comm_mygroup);
        t0 = MPI_Wtime();
    }
#endif

    if (ir->nwall)
    {
        /* foreign lambda component for walls */
        dvdl = do_walls(ir, fr, box, md, x, f, lambda[efptVDW],
                        enerd->grpp.ener[egLJSR], nrnb);
        PRINT_SEPDVDL("Walls", 0.0, dvdl);
        enerd->dvdl_lin[efptVDW] += dvdl;
    }

    /* If doing GB, reset dvda and calculate the Born radii */
    if (ir->implicit_solvent)
    {
        wallcycle_sub_start(wcycle, ewcsNONBONDED);

        for (i = 0; i < born->nr; i++)
        {
            fr->dvda[i] = 0;
        }

        if (bBornRadii)
        {
            calc_gb_rad(cr, fr, ir, top, atype, x, &(fr->gblist), born, md, nrnb);
        }

        wallcycle_sub_stop(wcycle, ewcsNONBONDED);
    }

    where();
    /* We only do non-bonded calculation with group scheme here, the verlet
     * calls are done from do_force_cutsVERLET(). */
    if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED))
    {
        donb_flags = 0;
        /* Add short-range interactions */
        donb_flags |= GMX_NONBONDED_DO_SR;

        if (flags & GMX_FORCE_FORCES)
        {
            donb_flags |= GMX_NONBONDED_DO_FORCE;
        }
        if (flags & GMX_FORCE_ENERGY)
        {
            donb_flags |= GMX_NONBONDED_DO_POTENTIAL;
        }
        if (flags & GMX_FORCE_DO_LR)
        {
            donb_flags |= GMX_NONBONDED_DO_LR;
        }

        wallcycle_sub_start(wcycle, ewcsNONBONDED);
        do_nonbonded(cr, fr, x, f, f_longrange, md, excl,
                     &enerd->grpp, box_size, nrnb,
                     lambda, dvdl_nb, -1, -1, donb_flags);

        /* If we do foreign lambda and we have soft-core interactions
         * we have to recalculate the (non-linear) energies contributions.
         */
        if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0)
        {
            for (i = 0; i < enerd->n_lambda; i++)
            {
                for (j = 0; j < efptNR; j++)
                {
                    lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                }
                reset_foreign_enerdata(enerd);
                do_nonbonded(cr, fr, x, f, f_longrange, md, excl,
                             &(enerd->foreign_grpp), box_size, nrnb,
                             lam_i, dvdl_dum, -1, -1,
                             (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA);
                sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term);
                enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
            }
        }
        wallcycle_sub_stop(wcycle, ewcsNONBONDED);
        where();
    }

    /* If we are doing GB, calculate bonded forces and apply corrections
     * to the solvation forces */
    /* MRS: Eventually, many need to include free energy contribution here! */
    if (ir->implicit_solvent)
    {
        wallcycle_sub_start(wcycle, ewcsBONDED);
        calc_gb_forces(cr, md, born, top, atype, x, f, fr, idef,
                       ir->gb_algorithm, ir->sa_algorithm, nrnb, bBornRadii, &pbc, graph, enerd);
        wallcycle_sub_stop(wcycle, ewcsBONDED);
    }

#ifdef GMX_MPI
    if (TAKETIME)
    {
        t1          = MPI_Wtime();
        fr->t_fnbf += t1-t0;
    }
#endif

    if (fepvals->sc_alpha != 0)
    {
        enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW];
    }
    else
    {
        enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW];
    }

    if (fepvals->sc_alpha != 0)

    /* even though coulomb part is linear, we already added it, beacuse we
       need to go through the vdw calculation anyway */
    {
        enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL];
    }
    else
    {
        enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL];
    }

    Vsr = 0;
    if (bSepDVDL)
    {
        for (i = 0; i < enerd->grpp.nener; i++)
        {
            Vsr +=
                (fr->bBHAM ?
                 enerd->grpp.ener[egBHAMSR][i] :
                 enerd->grpp.ener[egLJSR][i])
                + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i];
        }
        dvdlsum = dvdl_nb[efptVDW] + dvdl_nb[efptCOUL];
        PRINT_SEPDVDL("VdW and Coulomb SR particle-p.", Vsr, dvdlsum);
    }
    debug_gmx();

    GMX_MPE_LOG(ev_do_fnbf_finish);

    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.
     */

    /* Here sometimes we would not need to shift with NBFonly,
     * but we do so anyhow for consistency of the returned coordinates.
     */
    if (graph)
    {
        shift_self(graph, box, x);
        if (TRICLINIC(box))
        {
            inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes);
        }
        else
        {
            inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes);
        }
    }
    /* Check whether we need to do bondeds or correct for exclusions */
    if (fr->bMolPBC &&
        ((flags & GMX_FORCE_BONDED)
         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype)))
    {
        /* Since all atoms are in the rectangular or triclinic unit-cell,
         * only single box vector shifts (2 in x) are required.
         */
        set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box);
    }
    debug_gmx();

    if (flags & GMX_FORCE_BONDED)
    {
        GMX_MPE_LOG(ev_calc_bonds_start);

        wallcycle_sub_start(wcycle, ewcsBONDED);
        calc_bonds(fplog, cr->ms,
                   idef, x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd,
                   DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born,
                   flags,
                   fr->bSepDVDL && do_per_step(step, ir->nstlog), step);

        /* Check if we have to determine energy differences
         * at foreign lambda's.
         */
        if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) &&
            idef->ilsort != ilsortNO_FE)
        {
            if (idef->ilsort != ilsortFE_SORTED)
            {
                gmx_incons("The bonded interactions are not sorted for free energy");
            }
            for (i = 0; i < enerd->n_lambda; i++)
            {
                reset_foreign_enerdata(enerd);
                for (j = 0; j < efptNR; j++)
                {
                    lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                }
                calc_bonds_lambda(fplog, idef, x, fr, &pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md,
                                  fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
                sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term);
                enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
            }
        }
        debug_gmx();
        GMX_MPE_LOG(ev_calc_bonds_finish);
        wallcycle_sub_stop(wcycle, ewcsBONDED);
    }

    where();

    *cycles_pme = 0;
    if (EEL_FULL(fr->eeltype))
    {
        bSB = (ir->nwall == 2);
        if (bSB)
        {
            copy_mat(box, boxs);
            svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]);
            box_size[ZZ] *= ir->wall_ewald_zfac;
        }

        clear_mat(fr->vir_el_recip);

        if (fr->bEwald)
        {
            Vcorr = 0;
            dvdl  = 0;

            /* With the Verlet scheme exclusion forces are calculated
             * in the non-bonded kernel.
             */
            /* The TPI molecule does not have exclusions with the rest
             * of the system and no intra-molecular PME grid contributions
             * will be calculated in gmx_pme_calc_energy.
             */
            if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) ||
                ir->ewald_geometry != eewg3D ||
                ir->epsilon_surface != 0)
            {
                int nthreads, t;

                wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION);

                if (fr->n_tpi > 0)
                {
                    gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions");
                }

                nthreads = gmx_omp_nthreads_get(emntBonded);
#pragma omp parallel for num_threads(nthreads) schedule(static)
                for (t = 0; t < nthreads; t++)
                {
                    int     s, e, i;
                    rvec   *fnv;
                    tensor *vir;
                    real   *Vcorrt, *dvdlt;
                    if (t == 0)
                    {
                        fnv    = fr->f_novirsum;
                        vir    = &fr->vir_el_recip;
                        Vcorrt = &Vcorr;
                        dvdlt  = &dvdl;
                    }
                    else
                    {
                        fnv    = fr->f_t[t].f;
                        vir    = &fr->f_t[t].vir;
                        Vcorrt = &fr->f_t[t].Vcorr;
                        dvdlt  = &fr->f_t[t].dvdl[efptCOUL];
                        for (i = 0; i < fr->natoms_force; i++)
                        {
                            clear_rvec(fnv[i]);
                        }
                        clear_mat(*vir);
                    }
                    *dvdlt  = 0;
                    *Vcorrt =
                        ewald_LRcorrection(fplog,
                                           fr->excl_load[t], fr->excl_load[t+1],
                                           cr, t, fr,
                                           md->chargeA,
                                           md->nChargePerturbed ? md->chargeB : NULL,
                                           ir->cutoff_scheme != ecutsVERLET,
                                           excl, x, bSB ? boxs : box, mu_tot,
                                           ir->ewald_geometry,
                                           ir->epsilon_surface,
                                           fnv, *vir,
                                           lambda[efptCOUL], dvdlt);
                }
                if (nthreads > 1)
                {
                    reduce_thread_forces(fr->natoms_force, fr->f_novirsum,
                                         fr->vir_el_recip,
                                         &Vcorr, efptCOUL, &dvdl,
                                         nthreads, fr->f_t);
                }

                wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION);
            }

            if (fr->n_tpi == 0)
            {
                Vcorr += ewald_charge_correction(cr, fr, lambda[efptCOUL], box,
                                                 &dvdl, fr->vir_el_recip);
            }

            PRINT_SEPDVDL("Ewald excl./charge/dip. corr.", Vcorr, dvdl);
            enerd->dvdl_lin[efptCOUL] += dvdl;
        }

        status = 0;
        Vlr    = 0;
        dvdl   = 0;
        switch (fr->eeltype)
        {
            case eelPME:
            case eelPMESWITCH:
            case eelPMEUSER:
            case eelPMEUSERSWITCH:
            case eelP3M_AD:
                if (cr->duty & DUTY_PME)
                {
                    assert(fr->n_tpi >= 0);
                    if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
                    {
                        pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE;
                        if (flags & GMX_FORCE_FORCES)
                        {
                            pme_flags |= GMX_PME_CALC_F;
                        }
                        if (flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY))
                        {
                            pme_flags |= GMX_PME_CALC_ENER_VIR;
                        }
                        if (fr->n_tpi > 0)
                        {
                            /* We don't calculate f, but we do want the potential */
                            pme_flags |= GMX_PME_CALC_POT;
                        }
                        wallcycle_start(wcycle, ewcPMEMESH);
                        status = gmx_pme_do(fr->pmedata,
                                            md->start, md->homenr - fr->n_tpi,
                                            x, fr->f_novirsum,
                                            md->chargeA, md->chargeB,
                                            bSB ? boxs : box, cr,
                                            DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0,
                                            DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
                                            nrnb, wcycle,
                                            fr->vir_el_recip, fr->ewaldcoeff,
                                            &Vlr, lambda[efptCOUL], &dvdl,
                                            pme_flags);
                        *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH);

                        /* We should try to do as little computation after
                         * this as possible, because parallel PME synchronizes
                         * the nodes, so we want all load imbalance of the rest
                         * of the force calculation to be before the PME call.
                         * DD load balancing is done on the whole time of
                         * the force call (without PME).
                         */
                    }
                    if (fr->n_tpi > 0)
                    {
                        /* Determine the PME grid energy of the test molecule
                         * with the PME grid potential of the other charges.
                         */
                        gmx_pme_calc_energy(fr->pmedata, fr->n_tpi,
                                            x + md->homenr - fr->n_tpi,
                                            md->chargeA + md->homenr - fr->n_tpi,
                                            &Vlr);
                    }
                    PRINT_SEPDVDL("PME mesh", Vlr, dvdl);
                }
                break;
            case eelEWALD:
                Vlr = do_ewald(fplog, FALSE, ir, x, fr->f_novirsum,
                               md->chargeA, md->chargeB,
                               box_size, cr, md->homenr,
                               fr->vir_el_recip, fr->ewaldcoeff,
                               lambda[efptCOUL], &dvdl, fr->ewald_table);
                PRINT_SEPDVDL("Ewald long-range", Vlr, dvdl);
                break;
            default:
                gmx_fatal(FARGS, "No such electrostatics method implemented %s",
                          eel_names[fr->eeltype]);
        }
        if (status != 0)
        {
            gmx_fatal(FARGS, "Error %d in long range electrostatics routine %s",
                      status, EELTYPE(fr->eeltype));
        }
        /* Note that with separate PME nodes we get the real energies later */
        enerd->dvdl_lin[efptCOUL] += dvdl;
        enerd->term[F_COUL_RECIP]  = Vlr + Vcorr;
        if (debug)
        {
            fprintf(debug, "Vlr = %g, Vcorr = %g, Vlr_corr = %g\n",
                    Vlr, Vcorr, enerd->term[F_COUL_RECIP]);
            pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM);
            pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS);
        }
    }
    else
    {
        if (EEL_RF(fr->eeltype))
        {
            /* With the Verlet scheme exclusion forces are calculated
             * in the non-bonded kernel.
             */
            if (ir->cutoff_scheme != ecutsVERLET && fr->eeltype != eelRF_NEC)
            {
                dvdl                   = 0;
                enerd->term[F_RF_EXCL] =
                    RF_excl_correction(fplog, fr, graph, md, excl, x, f,
                                       fr->fshift, &pbc, lambda[efptCOUL], &dvdl);
            }

            enerd->dvdl_lin[efptCOUL] += dvdl;
            PRINT_SEPDVDL("RF exclusion correction",
                          enerd->term[F_RF_EXCL], dvdl);
        }
    }
    where();
    debug_gmx();

    if (debug)
    {
        print_nrnb(debug, nrnb);
    }
    debug_gmx();

#ifdef GMX_MPI
    if (TAKETIME)
    {
        t2 = MPI_Wtime();
        MPI_Barrier(cr->mpi_comm_mygroup);
        t3          = MPI_Wtime();
        fr->t_wait += t3-t2;
        if (fr->timesteps == 11)
        {
            fprintf(stderr, "* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n",
                    cr->nodeid, gmx_step_str(fr->timesteps, buf),
                    100*fr->t_wait/(fr->t_wait+fr->t_fnbf),
                    (fr->t_fnbf+fr->t_wait)/fr->t_fnbf);
        }
        fr->timesteps++;
    }
#endif

    if (debug)
    {
        pr_rvecs(debug, 0, "fshift after bondeds", fr->fshift, SHIFTS);
    }

    GMX_MPE_LOG(ev_force_finish);

}
Exemplo n.º 29
0
static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int seed,
                         t_atoms *atoms, rvec **x, real **r, int ePBC, matrix box,
                         gmx_atomprop_t aps, real r_distance, real rshell,
                         const output_env_t oenv)
{
    t_pbc            pbc;
    static  char    *title_insrt;
    t_atoms          atoms_insrt;
    rvec            *x_insrt, *x_n;
    real            *r_insrt;
    int              ePBC_insrt;
    matrix           box_insrt;
    int              i, mol, onr;
    real             alfa, beta, gamma;
    rvec             offset_x;
    int              trial;

    set_pbc(&pbc, ePBC, box);

    /* read number of atoms of insert molecules */
    get_stx_coordnum(mol_insrt, &atoms_insrt.nr);
    if (atoms_insrt.nr == 0)
    {
        gmx_fatal(FARGS, "No molecule in %s, please check your input\n", mol_insrt);
    }
    /* allocate memory for atom coordinates of insert molecules */
    snew(x_insrt, atoms_insrt.nr);
    snew(r_insrt, atoms_insrt.nr);
    snew(atoms_insrt.resinfo, atoms_insrt.nr);
    snew(atoms_insrt.atomname, atoms_insrt.nr);
    snew(atoms_insrt.atom, atoms_insrt.nr);
    atoms_insrt.pdbinfo = NULL;
    snew(x_n, atoms_insrt.nr);
    snew(title_insrt, STRLEN);

    /* read residue number, residue names, atomnames, coordinates etc. */
    fprintf(stderr, "Reading molecule configuration \n");
    read_stx_conf(mol_insrt, title_insrt, &atoms_insrt, x_insrt, NULL,
                  &ePBC_insrt, box_insrt);
    fprintf(stderr, "%s\nContaining %d atoms in %d residue\n",
            title_insrt, atoms_insrt.nr, atoms_insrt.nres);
    srenew(atoms_insrt.resinfo, atoms_insrt.nres);

    /* initialise van der waals arrays of insert molecules */
    mk_vdw(&atoms_insrt, r_insrt, aps, r_distance);

    srenew(atoms->resinfo, (atoms->nres+nmol_insrt*atoms_insrt.nres));
    srenew(atoms->atomname, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(atoms->atom, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(*x, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(*r, (atoms->nr+atoms_insrt.nr*nmol_insrt));

    trial = mol = 0;
    while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt))
    {
        fprintf(stderr, "\rTry %d", trial++);
        for (i = 0; (i < atoms_insrt.nr); i++)
        {
            copy_rvec(x_insrt[i], x_n[i]);
        }
        alfa  = 2*M_PI*rando( &seed);
        beta  = 2*M_PI*rando( &seed);
        gamma = 2*M_PI*rando( &seed);
        rotate_conf(atoms_insrt.nr, x_n, NULL, alfa, beta, gamma);
        offset_x[XX] = box[XX][XX]*rando(&seed);
        offset_x[YY] = box[YY][YY]*rando(&seed);
        offset_x[ZZ] = box[ZZ][ZZ]*rando(&seed);
        gen_box(0, atoms_insrt.nr, x_n, box_insrt, offset_x, TRUE);
        if (!in_box(&pbc, x_n[0]) || !in_box(&pbc, x_n[atoms_insrt.nr-1]))
        {
            continue;
        }
        onr = atoms->nr;

        add_conf(atoms, x, NULL, r, FALSE, ePBC, box, TRUE,
                 &atoms_insrt, x_n, NULL, r_insrt, FALSE, rshell, 0, oenv);

        if (atoms->nr == (atoms_insrt.nr+onr))
        {
            mol++;
            fprintf(stderr, " success (now %d atoms)!", atoms->nr);
        }
    }
    srenew(atoms->resinfo,  atoms->nres);
    srenew(atoms->atomname, atoms->nr);
    srenew(atoms->atom,     atoms->nr);
    srenew(*x,              atoms->nr);
    srenew(*r,              atoms->nr);

    fprintf(stderr, "\n");
    /* print number of molecules added */
    fprintf(stderr, "Added %d molecules (out of %d requested) of %s\n",
            mol, nmol_insrt, *atoms_insrt.resinfo[0].name);

    return title_insrt;
}
Exemplo n.º 30
0
bool constrain(FILE *fplog,bool bLog,bool bEner,
               struct gmx_constr *constr,
               t_idef *idef,t_inputrec *ir,
               t_commrec *cr,
               gmx_step_t step,int delta_step,
               t_mdatoms *md,
               rvec *x,rvec *xprime,rvec *min_proj,matrix box,
               real lambda,real *dvdlambda,
               rvec *v,tensor *vir,
               t_nrnb *nrnb,int econq)
{
    bool    bOK;
    int     start,homenr;
    int     i,j;
    int     ncons,error;
    tensor  rmdr;
    real    invdt,vir_fac,t;
    t_ilist *settle;
    int     nsettle;
    t_pbc   pbc;
    char    buf[22];
    
    if (econq == econqForceDispl && !EI_ENERGY_MINIMIZATION(ir->eI))
    {
        gmx_incons("constrain called for forces displacements while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted");
    }
    
    bOK = TRUE;
    
    start  = md->start;
    homenr = md->homenr;
    if (ir->delta_t == 0)
    {
        invdt = 0;
    }
    else
    {
        invdt  = 1/ir->delta_t;
    }

    if (ir->efep != efepNO && EI_DYNAMICS(ir->eI))
    {
        /* Set the constraint lengths for the step at which this configuration
         * is meant to be. The invmasses should not be changed.
         */
        lambda += delta_step*ir->delta_lambda;
    }
    
    if (vir != NULL)
    {
        clear_mat(rmdr);
    }
    
    where();
    if (constr->lincsd)
    {
        bOK = constrain_lincs(fplog,bLog,bEner,ir,step,constr->lincsd,md,cr,
                              x,xprime,min_proj,box,lambda,dvdlambda,
                              invdt,v,vir!=NULL,rmdr,
                              econq,nrnb,
                              constr->maxwarn,&constr->warncount_lincs);
        if (!bOK && constr->maxwarn >= 0 && fplog)
        {
            fprintf(fplog,"Constraint error in algorithm %s at step %s\n",
                    econstr_names[econtLINCS],gmx_step_str(step,buf));
        }
    }	
    
    if (constr->nblocks > 0)
    {
        if (econq != econqCoord)
        {
            gmx_fatal(FARGS,"Internal error, SHAKE called for constraining something else than coordinates");
        }
        
        bOK = bshakef(fplog,constr->shaked,
                      homenr,md->invmass,constr->nblocks,constr->sblock,
                      idef,ir,box,x,xprime,nrnb,
                      constr->lagr,lambda,dvdlambda,
                      invdt,v,vir!=NULL,rmdr,constr->maxwarn>=0);
        if (!bOK && constr->maxwarn >= 0 && fplog)
        {
            fprintf(fplog,"Constraint error in algorithm %s at step %s\n",
                    econstr_names[econtSHAKE],gmx_step_str(step,buf));
        }
    }
    
    settle  = &idef->il[F_SETTLE];
    if (settle->nr > 0)
    {
        nsettle = settle->nr/2;
        
        switch (econq)
        {
        case econqCoord:
            csettle(constr->settled,
                    nsettle,settle->iatoms,x[0],xprime[0],
                    invdt,v[0],vir!=NULL,rmdr,&error);
            inc_nrnb(nrnb,eNR_SETTLE,nsettle);
            if (v != NULL)
            {
                inc_nrnb(nrnb,eNR_CONSTR_V,nsettle*3);
            }
            if (vir != NULL)
            {
                inc_nrnb(nrnb,eNR_CONSTR_VIR,nsettle*3);
            }
            
            bOK = (error < 0);
            if (!bOK && constr->maxwarn >= 0)
            {
                char buf[256];
                sprintf(buf,
                        "\nt = %.3f ps: Water molecule starting at atom %d can not be "
                        "settled.\nCheck for bad contacts and/or reduce the timestep.\n",
                        ir->init_t+step*ir->delta_t,
                        ddglatnr(cr->dd,settle->iatoms[error*2+1]));
                if (fplog)
                {
                    fprintf(fplog,"%s",buf);
                }
                fprintf(stderr,"%s",buf);
                constr->warncount_settle++;
                if (constr->warncount_settle > constr->maxwarn)
                {
                    too_many_constraint_warnings(-1,constr->warncount_settle);
                }
                break;
            case econqVeloc:
            case econqDeriv:
            case econqForce:
            case econqForceDispl:
                settle_proj(fplog,constr->settled,econq,
                            nsettle,settle->iatoms,x,
                            xprime,min_proj,vir!=NULL,rmdr);
                
                /* This is an overestimate */
                inc_nrnb(nrnb,eNR_SETTLE,nsettle);
                break;
            case econqDeriv_FlexCon:
                /* Nothing to do, since the are no flexible constraints in settles */
                break;
            default:
                gmx_incons("Unknown constraint quantity for settle");
            }
        }
    }

    if (vir != NULL)
    {
        switch (econq)
        {
        case econqCoord:
            vir_fac = 0.5/(ir->delta_t*ir->delta_t);
            break;
        case econqVeloc:
            /* Assume that these are velocities */
            vir_fac = 0.5/ir->delta_t;
            break;
        case econqForce:
        case econqForceDispl:
            vir_fac = 0.5;
            break;
        default:
            vir_fac = 0;
            gmx_incons("Unsupported constraint quantity for virial");
        }
        for(i=0; i<DIM; i++)
        {
            for(j=0; j<DIM; j++)
            {
                (*vir)[i][j] = vir_fac*rmdr[i][j];
            }
        }
    }
    
    if (!bOK && constr->maxwarn >= 0)
    {
        dump_confs(fplog,step,constr->warn_mtop,start,homenr,cr,x,xprime,box);
    }
    
    if (econq == econqCoord)
    {
        if (ir->ePull == epullCONSTRAINT)
        {
            if (EI_DYNAMICS(ir->eI))
            {
                t = ir->init_t + (step + delta_step)*ir->delta_t;
            }
            else
            {
                t = ir->init_t;
            }
            set_pbc(&pbc,ir->ePBC,box);
            pull_constraint(ir->pull,md,&pbc,cr,ir->delta_t,t,x,xprime,v,*vir);
        }
        if (constr->ed && delta_step > 0)
        {
            /* apply the essential dynamcs constraints here */
            do_edsam(ir,step,md,cr,xprime,v,box,constr->ed);
        }
    }
    
    return bOK;
}