Beispiel #1
0
static void init_grpstat(FILE *log,
                         gmx_mtop_t *mtop, int ngacc, t_grp_acc gstat[])
{
    gmx_groups_t           *groups;
    gmx_mtop_atomloop_all_t aloop;
    int                     i, grp;
    t_atom                 *atom;

    if (ngacc > 0)
    {
        groups = &mtop->groups;
        aloop  = gmx_mtop_atomloop_all_init(mtop);
        while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
        {
            grp = ggrpnr(groups, egcACC, i);
            if ((grp < 0) && (grp >= ngacc))
            {
                gmx_incons("Input for acceleration groups wrong");
            }
            gstat[grp].nat++;
            /* This will not work for integrator BD */
            gstat[grp].mA += atom->m;
            gstat[grp].mB += atom->mB;
        }
    }
}
Beispiel #2
0
static void write_hconf_mtop(FILE *out,char *title,gmx_mtop_t *mtop,
			     int pr,
			     rvec *x,rvec *v,matrix box)
{
  char format[100];
  int  i,resnr;
  gmx_mtop_atomloop_all_t aloop;
  t_atom *atom;
  char *atomname,*resname;

  bromacs(format,99);
  fprintf (out,"%s\n",(title && title[0])?title:format);
  fprintf (out,"%5d\n",mtop->natoms);

  make_hconf_format(pr,v!=NULL,format);
  
  aloop = gmx_mtop_atomloop_all_init(mtop);
  while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
    gmx_mtop_atomloop_all_names(aloop,&atomname,&resnr,&resname);

    fprintf(out,"%5d%-5.5s%5.5s%5d",
	    (resnr+1)%100000,resname,atomname,(i+1)%100000);
    /* next fprintf uses built format string */
    if (v)
      fprintf(out,format,
	      x[i][XX], x[i][YY], x[i][ZZ], v[i][XX],v[i][YY],v[i][ZZ]);
    else
      fprintf(out,format,
	      x[i][XX], x[i][YY], x[i][ZZ]);
  }

  write_hconf_box(out,pr,box);

  fflush(out);
}
Beispiel #3
0
t_mdatoms *init_mdatoms(FILE *fp, gmx_mtop_t *mtop, gmx_bool bFreeEnergy)
{
    int                     mb, a, g, nmol;
    double                  tmA, tmB;
    t_atom                 *atom;
    t_mdatoms              *md;
    gmx_mtop_atomloop_all_t aloop;
    t_ilist                *ilist;

    snew(md, 1);

    md->nenergrp = mtop->groups.grps[egcENER].nr;
    md->bVCMgrps = FALSE;
    tmA          = 0.0;
    tmB          = 0.0;

    aloop = gmx_mtop_atomloop_all_init(mtop);
    while (gmx_mtop_atomloop_all_next(aloop, &a, &atom))
    {
        if (ggrpnr(&mtop->groups, egcVCM, a) > 0)
        {
            md->bVCMgrps = TRUE;
        }

        if (bFreeEnergy && PERTURBED(*atom))
        {
            md->nPerturbed++;
            if (atom->mB != atom->m)
            {
                md->nMassPerturbed++;
            }
            if (atom->qB != atom->q)
            {
                md->nChargePerturbed++;
            }
            if (atom->typeB != atom->type)
            {
                md->nTypePerturbed++;
            }
        }

        tmA += atom->m;
        tmB += atom->mB;
    }

    md->tmassA = tmA;
    md->tmassB = tmB;

    if (bFreeEnergy && fp)
    {
        fprintf(fp,
                "There are %d atoms and %d charges for free energy perturbation\n",
                md->nPerturbed, md->nChargePerturbed);
    }

    md->bOrires = gmx_mtop_ftype_count(mtop, F_ORIRES);

    return md;
}
static void low_mspeed(real tempi,
                       gmx_mtop_t *mtop, rvec v[], gmx_rng_t rng)
{
    int                     i, m, nrdf;
    real                    boltz, sd;
    real                    ekin, temp, mass, scal;
    gmx_mtop_atomloop_all_t aloop;
    t_atom                 *atom;

    boltz = BOLTZ*tempi;
    ekin  = 0.0;
    nrdf  = 0;
    aloop = gmx_mtop_atomloop_all_init(mtop);
    while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
    {
        mass = atom->m;
        if (mass > 0)
        {
            sd = sqrt(boltz/mass);
            for (m = 0; (m < DIM); m++)
            {
                v[i][m] = sd*gmx_rng_gaussian_real(rng);
                ekin   += 0.5*mass*v[i][m]*v[i][m];
            }
            nrdf += DIM;
        }
    }
    temp = (2.0*ekin)/(nrdf*BOLTZ);
    if (temp > 0)
    {
        scal = sqrt(tempi/temp);
        for (i = 0; (i < mtop->natoms); i++)
        {
            for (m = 0; (m < DIM); m++)
            {
                v[i][m] *= scal;
            }
        }
    }
    fprintf(stderr, "Velocities were taken from a Maxwell distribution at %g K\n",
            tempi);
    if (debug)
    {
        fprintf(debug,
                "Velocities were taken from a Maxwell distribution\n"
                "Initial generated temperature: %12.5e (scaled to: %12.5e)\n",
                temp, tempi);
    }
}
Beispiel #5
0
static void check_vel(gmx_mtop_t *mtop,rvec v[])
{
  gmx_mtop_atomloop_all_t aloop;
  t_atom *atom;
  int a;

  aloop = gmx_mtop_atomloop_all_init(mtop);
  while (gmx_mtop_atomloop_all_next(aloop,&a,&atom)) {
    if (atom->ptype == eptShell ||
	atom->ptype == eptBond  ||
	atom->ptype == eptVSite) {
      clear_rvec(v[a]);
    }
  }
}
Beispiel #6
0
/* Allocate and fill an array with coordinates and charges,
 * returns the number of charges found
 */
static int prepare_x_q(real *q[], rvec *x[], gmx_mtop_t *mtop, rvec x_orig[], t_commrec *cr)
{
    int                     i;
    int                     nq; /* number of charged particles */
    gmx_mtop_atomloop_all_t aloop;
    t_atom                 *atom;


    if (MASTER(cr))
    {
        snew(*q, mtop->natoms);
        snew(*x, mtop->natoms);
        nq = 0;

        aloop = gmx_mtop_atomloop_all_init(mtop);

        while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
        {
            if (is_charge(atom->q))
            {
                (*q)[nq]     = atom->q;
                (*x)[nq][XX] = x_orig[i][XX];
                (*x)[nq][YY] = x_orig[i][YY];
                (*x)[nq][ZZ] = x_orig[i][ZZ];
                nq++;
            }
        }
        /* Give back some unneeded memory */
        srenew(*q, nq);
        srenew(*x, nq);
    }
    /* Broadcast x and q in the parallel case */
    if (PAR(cr))
    {
        /* Transfer the number of charges */
        block_bc(cr, nq);
        snew_bc(cr, *x, nq);
        snew_bc(cr, *q, nq);
        nblock_bc(cr, nq, *x);
        nblock_bc(cr, nq, *q);
    }

    return nq;
}
Beispiel #7
0
gmx_shellfc_t init_shell_flexcon(FILE *fplog,
                                 gmx_bool bCutoffSchemeIsVerlet,
                                 gmx_mtop_t *mtop, int nflexcon,
                                 rvec *x)
{
    struct gmx_shellfc       *shfc;
    t_shell                  *shell;
    int                      *shell_index = NULL, *at2cg;
    t_atom                   *atom;
    int                       n[eptNR], ns, nshell, nsi;
    int                       i, j, nmol, type, mb, mt, a_offset, cg, mol, ftype, nra;
    real                      qS, alpha;
    int                       aS, aN = 0; /* Shell and nucleus */
    int                       bondtypes[] = { F_BONDS, F_HARMONIC, F_CUBICBONDS, F_POLARIZATION, F_ANHARM_POL, F_WATER_POL };
#define NBT asize(bondtypes)
    t_iatom                  *ia;
    gmx_mtop_atomloop_block_t aloopb;
    gmx_mtop_atomloop_all_t   aloop;
    gmx_ffparams_t           *ffparams;
    gmx_molblock_t           *molb;
    gmx_moltype_t            *molt;
    t_block                  *cgs;

    /* Count number of shells, and find their indices */
    for (i = 0; (i < eptNR); i++)
    {
        n[i] = 0;
    }

    aloopb = gmx_mtop_atomloop_block_init(mtop);
    while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
    {
        n[atom->ptype] += nmol;
    }

    if (fplog)
    {
        /* Print the number of each particle type */
        for (i = 0; (i < eptNR); i++)
        {
            if (n[i] != 0)
            {
                fprintf(fplog, "There are: %d %ss\n", n[i], ptype_str[i]);
            }
        }
    }

    nshell = n[eptShell];

    if (nshell == 0 && nflexcon == 0)
    {
        /* We're not doing shells or flexible constraints */
        return NULL;
    }

    if (bCutoffSchemeIsVerlet)
    {
        gmx_fatal(FARGS, "The shell code does not work with the Verlet cut-off scheme.\n");
    }

    snew(shfc, 1);
    shfc->nflexcon = nflexcon;

    if (nshell == 0)
    {
        return shfc;
    }

    /* We have shells: fill the shell data structure */

    /* Global system sized array, this should be avoided */
    snew(shell_index, mtop->natoms);

    aloop  = gmx_mtop_atomloop_all_init(mtop);
    nshell = 0;
    while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
    {
        if (atom->ptype == eptShell)
        {
            shell_index[i] = nshell++;
        }
    }

    snew(shell, nshell);

    /* Initiate the shell structures */
    for (i = 0; (i < nshell); i++)
    {
        shell[i].shell = NO_ATID;
        shell[i].nnucl = 0;
        shell[i].nucl1 = NO_ATID;
        shell[i].nucl2 = NO_ATID;
        shell[i].nucl3 = NO_ATID;
        /* shell[i].bInterCG=FALSE; */
        shell[i].k_1   = 0;
        shell[i].k     = 0;
    }

    ffparams = &mtop->ffparams;

    /* Now fill the structures */
    shfc->bInterCG = FALSE;
    ns             = 0;
    a_offset       = 0;
    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        molb = &mtop->molblock[mb];
        molt = &mtop->moltype[molb->type];

        cgs = &molt->cgs;
        snew(at2cg, molt->atoms.nr);
        for (cg = 0; cg < cgs->nr; cg++)
        {
            for (i = cgs->index[cg]; i < cgs->index[cg+1]; i++)
            {
                at2cg[i] = cg;
            }
        }

        atom = molt->atoms.atom;
        for (mol = 0; mol < molb->nmol; mol++)
        {
            for (j = 0; (j < NBT); j++)
            {
                ia = molt->ilist[bondtypes[j]].iatoms;
                for (i = 0; (i < molt->ilist[bondtypes[j]].nr); )
                {
                    type  = ia[0];
                    ftype = ffparams->functype[type];
                    nra   = interaction_function[ftype].nratoms;

                    /* Check whether we have a bond with a shell */
                    aS = NO_ATID;

                    switch (bondtypes[j])
                    {
                        case F_BONDS:
                        case F_HARMONIC:
                        case F_CUBICBONDS:
                        case F_POLARIZATION:
                        case F_ANHARM_POL:
                            if (atom[ia[1]].ptype == eptShell)
                            {
                                aS = ia[1];
                                aN = ia[2];
                            }
                            else if (atom[ia[2]].ptype == eptShell)
                            {
                                aS = ia[2];
                                aN = ia[1];
                            }
                            break;
                        case F_WATER_POL:
                            aN    = ia[4]; /* Dummy */
                            aS    = ia[5]; /* Shell */
                            break;
                        default:
                            gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
                    }

                    if (aS != NO_ATID)
                    {
                        qS = atom[aS].q;

                        /* Check whether one of the particles is a shell... */
                        nsi = shell_index[a_offset+aS];
                        if ((nsi < 0) || (nsi >= nshell))
                        {
                            gmx_fatal(FARGS, "nsi is %d should be within 0 - %d. aS = %d",
                                      nsi, nshell, aS);
                        }
                        if (shell[nsi].shell == NO_ATID)
                        {
                            shell[nsi].shell = a_offset + aS;
                            ns++;
                        }
                        else if (shell[nsi].shell != a_offset+aS)
                        {
                            gmx_fatal(FARGS, "Weird stuff in %s, %d", __FILE__, __LINE__);
                        }

                        if      (shell[nsi].nucl1 == NO_ATID)
                        {
                            shell[nsi].nucl1 = a_offset + aN;
                        }
                        else if (shell[nsi].nucl2 == NO_ATID)
                        {
                            shell[nsi].nucl2 = a_offset + aN;
                        }
                        else if (shell[nsi].nucl3 == NO_ATID)
                        {
                            shell[nsi].nucl3 = a_offset + aN;
                        }
                        else
                        {
                            if (fplog)
                            {
                                pr_shell(fplog, ns, shell);
                            }
                            gmx_fatal(FARGS, "Can not handle more than three bonds per shell\n");
                        }
                        if (at2cg[aS] != at2cg[aN])
                        {
                            /* shell[nsi].bInterCG = TRUE; */
                            shfc->bInterCG = TRUE;
                        }

                        switch (bondtypes[j])
                        {
                            case F_BONDS:
                            case F_HARMONIC:
                                shell[nsi].k    += ffparams->iparams[type].harmonic.krA;
                                break;
                            case F_CUBICBONDS:
                                shell[nsi].k    += ffparams->iparams[type].cubic.kb;
                                break;
                            case F_POLARIZATION:
                            case F_ANHARM_POL:
                                if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10))
                                {
                                    gmx_fatal(FARGS, "polarize can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1);
                                }
                                shell[nsi].k    += sqr(qS)*ONE_4PI_EPS0/
                                    ffparams->iparams[type].polarize.alpha;
                                break;
                            case F_WATER_POL:
                                if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10))
                                {
                                    gmx_fatal(FARGS, "water_pol can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1);
                                }
                                alpha          = (ffparams->iparams[type].wpol.al_x+
                                                  ffparams->iparams[type].wpol.al_y+
                                                  ffparams->iparams[type].wpol.al_z)/3.0;
                                shell[nsi].k  += sqr(qS)*ONE_4PI_EPS0/alpha;
                                break;
                            default:
                                gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
                        }
                        shell[nsi].nnucl++;
                    }
                    ia += nra+1;
                    i  += nra+1;
                }
            }
            a_offset += molt->atoms.nr;
        }
        /* Done with this molecule type */
        sfree(at2cg);
    }

    /* Verify whether it's all correct */
    if (ns != nshell)
    {
        gmx_fatal(FARGS, "Something weird with shells. They may not be bonded to something");
    }

    for (i = 0; (i < ns); i++)
    {
        shell[i].k_1 = 1.0/shell[i].k;
    }

    if (debug)
    {
        pr_shell(debug, ns, shell);
    }


    shfc->nshell_gl      = ns;
    shfc->shell_gl       = shell;
    shfc->shell_index_gl = shell_index;

    shfc->bPredict     = (getenv("GMX_NOPREDICT") == NULL);
    shfc->bRequireInit = FALSE;
    if (!shfc->bPredict)
    {
        if (fplog)
        {
            fprintf(fplog, "\nWill never predict shell positions\n");
        }
    }
    else
    {
        shfc->bRequireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != NULL);
        if (shfc->bRequireInit && fplog)
        {
            fprintf(fplog, "\nWill always initiate shell positions\n");
        }
    }

    if (shfc->bPredict)
    {
        if (x)
        {
            predict_shells(fplog, x, NULL, 0, shfc->nshell_gl, shfc->shell_gl,
                           NULL, mtop, TRUE);
        }

        if (shfc->bInterCG)
        {
            if (fplog)
            {
                fprintf(fplog, "\nNOTE: there all shells that are connected to particles outside thier own charge group, will not predict shells positions during the run\n\n");
            }
            shfc->bPredict = FALSE;
        }
    }

    return shfc;
}
Beispiel #8
0
void init_QMMMrec(t_commrec *cr,
		  matrix box,
		  gmx_mtop_t *mtop,
		  t_inputrec *ir,
		  t_forcerec *fr)
{
  /* we put the atomsnumbers of atoms that belong to the QMMM group in
   * an array that will be copied later to QMMMrec->indexQM[..]. Also
   * it will be used to create an QMMMrec->bQMMM index array that
   * simply contains true/false for QM and MM (the other) atoms.
   */

  gmx_groups_t *groups;
  atom_id   *qm_arr=NULL,vsite,ai,aj;
  int       qm_max=0,qm_nr=0,i,j,jmax,k,l,nrvsite2=0;
  t_QMMMrec *qr;
  t_MMrec   *mm;
  t_iatom   *iatoms;
  real      c12au,c6au;
  gmx_mtop_atomloop_all_t aloop;
  t_atom    *atom;
  gmx_mtop_ilistloop_all_t iloop;
  int       a_offset;
  t_ilist   *ilist_mol;

  c6au  = (HARTREE2KJ*AVOGADRO*pow(BOHR2NM,6));
  c12au = (HARTREE2KJ*AVOGADRO*pow(BOHR2NM,12));
  fprintf(stderr,"there we go!\n");

  /* Make a local copy of the QMMMrec */
  qr = fr->qr;

  /* bQMMM[..] is an array containing TRUE/FALSE for atoms that are
   * QM/not QM. We first set all elemenst at false. Afterwards we use
   * the qm_arr (=MMrec->indexQM) to changes the elements
   * corresponding to the QM atoms at TRUE.  */

  qr->QMMMscheme     = ir->QMMMscheme;

  /* we take the possibility into account that a user has
   * defined more than one QM group:
   */
  /* an ugly work-around in case there is only one group In this case
   * the whole system is treated as QM. Otherwise the second group is
   * always the rest of the total system and is treated as MM.
   */

  /* small problem if there is only QM.... so no MM */

  jmax = ir->opts.ngQM;

  if(qr->QMMMscheme==eQMMMschemeoniom)
    qr->nrQMlayers = jmax;
  else
    qr->nrQMlayers = 1;

  groups = &mtop->groups;

  /* there are jmax groups of QM atoms. In case of multiple QM groups
   * I assume that the users wants to do ONIOM. However, maybe it
   * should also be possible to define more than one QM subsystem with
   * independent neighbourlists. I have to think about
   * that.. 11-11-2003
   */
  snew(qr->qm,jmax);
  for(j=0;j<jmax;j++){
    /* new layer */
    aloop = gmx_mtop_atomloop_all_init(mtop);
    while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
      if(qm_nr >= qm_max){
	qm_max += 1000;
	srenew(qm_arr,qm_max);
      }
      if (ggrpnr(groups,egcQMMM ,i) == j) {
	/* hack for tip4p */
	qm_arr[qm_nr++] = i;
      }
    }
    if(qr->QMMMscheme==eQMMMschemeoniom){
      /* add the atoms to the bQMMM array
       */

      /* I assume that users specify the QM groups from small to
       * big(ger) in the mdp file
       */
      qr->qm[j] = mk_QMrec();
      /* we need to throw out link atoms that in the previous layer
       * existed to separate this QMlayer from the previous
       * QMlayer. We use the iatoms array in the idef for that
       * purpose. If all atoms defining the current Link Atom (Dummy2)
       * are part of the current QM layer it needs to be removed from
       * qm_arr[].  */

      iloop = gmx_mtop_ilistloop_all_init(mtop);
      while (gmx_mtop_ilistloop_all_next(iloop,&ilist_mol,&a_offset)) {
	nrvsite2 = ilist_mol[F_VSITE2].nr;
	iatoms   = ilist_mol[F_VSITE2].iatoms;

	for(k=0; k<nrvsite2; k+=4) {
	  vsite = a_offset + iatoms[k+1]; /* the vsite         */
	  ai    = a_offset + iatoms[k+2]; /* constructing atom */
	  aj    = a_offset + iatoms[k+3]; /* constructing atom */
	  if (ggrpnr(groups, egcQMMM, vsite) == ggrpnr(groups, egcQMMM, ai)
	      &&
	      ggrpnr(groups, egcQMMM, vsite) == ggrpnr(groups, egcQMMM, aj)) {
	    /* this dummy link atom needs to be removed from the qm_arr
	     * before making the QMrec of this layer!
	     */
	    for(i=0;i<qm_nr;i++){
	      if(qm_arr[i]==vsite){
		/* drop the element */
		for(l=i;l<qm_nr;l++){
		  qm_arr[l]=qm_arr[l+1];
		}
		qm_nr--;
	      }
	    }
	  }
	}
      }

      /* store QM atoms in this layer in the QMrec and initialise layer
       */
      init_QMrec(j,qr->qm[j],qm_nr,qm_arr,mtop,ir);

      /* we now store the LJ C6 and C12 parameters in QM rec in case
       * we need to do an optimization
       */
      if(qr->qm[j]->bOPT || qr->qm[j]->bTS){
	for(i=0;i<qm_nr;i++){
	  qr->qm[j]->c6[i]  =  C6(fr->nbfp,mtop->ffparams.atnr,
				  atom->type,atom->type)/c6au;
	  qr->qm[j]->c12[i] = C12(fr->nbfp,mtop->ffparams.atnr,
				  atom->type,atom->type)/c12au;
	}
      }
      /* now we check for frontier QM atoms. These occur in pairs that
       * construct the vsite
       */
      iloop = gmx_mtop_ilistloop_all_init(mtop);
      while (gmx_mtop_ilistloop_all_next(iloop,&ilist_mol,&a_offset)) {
	nrvsite2 = ilist_mol[F_VSITE2].nr;
	iatoms   = ilist_mol[F_VSITE2].iatoms;

	for(k=0; k<nrvsite2; k+=4){
	  vsite = a_offset + iatoms[k+1]; /* the vsite         */
	  ai    = a_offset + iatoms[k+2]; /* constructing atom */
	  aj    = a_offset + iatoms[k+3]; /* constructing atom */
	  if(ggrpnr(groups,egcQMMM,ai) < (groups->grps[egcQMMM].nr-1) &&
	     (ggrpnr(groups,egcQMMM,aj) >= (groups->grps[egcQMMM].nr-1))){
	      /* mark ai as frontier atom */
	    for(i=0;i<qm_nr;i++){
	      if( (qm_arr[i]==ai) || (qm_arr[i]==vsite) ){
		qr->qm[j]->frontatoms[i]=TRUE;
	      }
	    }
	  }
	  else if(ggrpnr(groups,egcQMMM,aj) < (groups->grps[egcQMMM].nr-1) &&
		  (ggrpnr(groups,egcQMMM,ai) >= (groups->grps[egcQMMM].nr-1))){
	    /* mark aj as frontier atom */
	    for(i=0;i<qm_nr;i++){
	      if( (qm_arr[i]==aj) || (qm_arr[i]==vsite)){
		qr->qm[j]->frontatoms[i]=TRUE;
	      }
	    }
	  }
	}
      }
    }
  }
  if(qr->QMMMscheme!=eQMMMschemeoniom){

    /* standard QMMM, all layers are merged together so there is one QM
     * subsystem and one MM subsystem.
     * Also we set the charges to zero in the md->charge arrays to prevent
     * the innerloops from doubly counting the electostatic QM MM interaction
     */
    for (k=0;k<qm_nr;k++){
      gmx_mtop_atomnr_to_atom(mtop,qm_arr[k],&atom);
      atom->q  = 0.0;
      atom->qB = 0.0;
    }
    qr->qm[0] = mk_QMrec();
    /* store QM atoms in the QMrec and initialise
     */
    init_QMrec(0,qr->qm[0],qm_nr,qm_arr,mtop,ir);
    if(qr->qm[0]->bOPT || qr->qm[0]->bTS){
      for(i=0;i<qm_nr;i++){
	gmx_mtop_atomnr_to_atom(mtop,qm_arr[i],&atom);
	qr->qm[0]->c6[i]  =  C6(fr->nbfp,mtop->ffparams.atnr,
				atom->type,atom->type)/c6au;
	qr->qm[0]->c12[i] = C12(fr->nbfp,mtop->ffparams.atnr,
				atom->type,atom->type)/c12au;
      }

    }



    /* find frontier atoms and mark them true in the frontieratoms array.
     */
    for(i=0;i<qm_nr;i++) {
      gmx_mtop_atomnr_to_ilist(mtop,qm_arr[i],&ilist_mol,&a_offset);
      nrvsite2 = ilist_mol[F_VSITE2].nr;
      iatoms   = ilist_mol[F_VSITE2].iatoms;

      for(k=0;k<nrvsite2;k+=4){
	vsite = a_offset + iatoms[k+1]; /* the vsite         */
	ai    = a_offset + iatoms[k+2]; /* constructing atom */
	aj    = a_offset + iatoms[k+3]; /* constructing atom */
	if(ggrpnr(groups,egcQMMM,ai) < (groups->grps[egcQMMM].nr-1) &&
	   (ggrpnr(groups,egcQMMM,aj) >= (groups->grps[egcQMMM].nr-1))){
	/* mark ai as frontier atom */
	  if ( (qm_arr[i]==ai) || (qm_arr[i]==vsite) ){
	    qr->qm[0]->frontatoms[i]=TRUE;
	  }
	}
	else if (ggrpnr(groups,egcQMMM,aj) < (groups->grps[egcQMMM].nr-1) &&
		 (ggrpnr(groups,egcQMMM,ai) >=(groups->grps[egcQMMM].nr-1))) {
	  /* mark aj as frontier atom */
	  if ( (qm_arr[i]==aj) || (qm_arr[i]==vsite) ){
	    qr->qm[0]->frontatoms[i]=TRUE;
	  }
	}
      }
    }

    /* MM rec creation */
    mm               = mk_MMrec();
    mm->scalefactor  = ir->scalefactor;
    mm->nrMMatoms    = (mtop->natoms)-(qr->qm[0]->nrQMatoms); /* rest of the atoms */
    qr->mm           = mm;
  } else {/* ONIOM */
    /* MM rec creation */
    mm               = mk_MMrec();
    mm->scalefactor  = ir->scalefactor;
    mm->nrMMatoms    = 0;
    qr->mm           = mm;
  }

  /* these variables get updated in the update QMMMrec */

  if(qr->nrQMlayers==1){
    /* with only one layer there is only one initialisation
     * needed. Multilayer is a bit more complicated as it requires
     * re-initialisation at every step of the simulation. This is due
     * to the use of COMMON blocks in the fortran QM subroutines.
     */
    if (qr->qm[0]->QMmethod<eQMmethodRHF)
    {
#ifdef GMX_QMMM_MOPAC
        /* semi-empiprical 1-layer ONIOM calculation requested (mopac93) */
        init_mopac(cr,qr->qm[0],qr->mm);
#else
        gmx_fatal(FARGS,"Semi-empirical QM only supported with Mopac.");
#endif
    }
    else
    {
        /* ab initio calculation requested (gamess/gaussian/ORCA) */
#ifdef GMX_QMMM_GAMESS
        init_gamess(cr,qr->qm[0],qr->mm);
#elif defined GMX_QMMM_GAUSSIAN
        init_gaussian(cr,qr->qm[0],qr->mm);
#elif defined GMX_QMMM_ORCA
        init_orca(cr,qr->qm[0],qr->mm);
#else
        gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
#endif
    }
  }
} /* init_QMMMrec */
Beispiel #9
0
void init_orires(FILE *fplog,const gmx_mtop_t *mtop,
                 rvec xref[],
                 const t_inputrec *ir,
                 const gmx_multisim_t *ms,t_oriresdata *od,
                 t_state *state)
{
    int    i,j,d,ex,nmol,nr,*nr_ex;
    double mtot;
    rvec   com;
    gmx_mtop_ilistloop_t iloop;
    t_ilist *il;
    gmx_mtop_atomloop_all_t aloop;
    t_atom *atom;

    od->fc  = ir->orires_fc;
    od->nex = 0;
    od->S   = NULL;

    od->nr = gmx_mtop_ftype_count(mtop,F_ORIRES);
    if (od->nr == 0)
    {
        return;
    }
    
    nr_ex = NULL;
    
    iloop = gmx_mtop_ilistloop_init(mtop);
    while (gmx_mtop_ilistloop_next(iloop,&il,&nmol))
    {
        for(i=0; i<il[F_ORIRES].nr; i+=3)
        {
            ex = mtop->ffparams.iparams[il[F_ORIRES].iatoms[i]].orires.ex;
            if (ex >= od->nex)
            {
                srenew(nr_ex,ex+1);
                for(j=od->nex; j<ex+1; j++)
                {
                    nr_ex[j] = 0;
            }
                od->nex = ex+1;
            }
            nr_ex[ex]++;
        }
    }
    snew(od->S,od->nex);
    /* When not doing time averaging, the instaneous and time averaged data
     * are indentical and the pointers can point to the same memory.
     */
    snew(od->Dinsl,od->nr);
    if (ms)
    {
        snew(od->Dins,od->nr);
    }
    else
    {
        od->Dins = od->Dinsl;
    }

    if (ir->orires_tau == 0)
    {
        od->Dtav = od->Dins;
        od->edt  = 0.0;
        od->edt1 = 1.0;
    }
    else
    {
        snew(od->Dtav,od->nr);
        od->edt  = exp(-ir->delta_t/ir->orires_tau);
        od->edt1 = 1.0 - od->edt;

        /* Extend the state with the orires history */
        state->flags |= (1<<estORIRE_INITF);
        state->hist.orire_initf = 1;
        state->flags |= (1<<estORIRE_DTAV);
        state->hist.norire_Dtav = od->nr*5;
        snew(state->hist.orire_Dtav,state->hist.norire_Dtav);
    }

    snew(od->oinsl,od->nr);
    if (ms)
    {
        snew(od->oins,od->nr);
    }
    else
    {
        od->oins = od->oinsl;
    }
    if (ir->orires_tau == 0) {
        od->otav = od->oins;
    }
    else
    {
        snew(od->otav,od->nr);
    }
    snew(od->tmp,od->nex);
    snew(od->TMP,od->nex);
    for(ex=0; ex<od->nex; ex++)
    {
        snew(od->TMP[ex],5);
        for(i=0; i<5; i++)
        {
            snew(od->TMP[ex][i],5);
        }
    }
    
    od->nref = 0;
    for(i=0; i<mtop->natoms; i++)
    {
        if (ggrpnr(&mtop->groups,egcORFIT,i) == 0)
        {
            od->nref++;
        }
    }
    snew(od->mref,od->nref);
    snew(od->xref,od->nref);
    snew(od->xtmp,od->nref);
    
    snew(od->eig,od->nex*12);
    
    /* Determine the reference structure on the master node.
     * Copy it to the other nodes after checking multi compatibility,
     * so we are sure the subsystems match before copying.
     */
    clear_rvec(com);
    mtot = 0.0;
    j = 0;
    aloop = gmx_mtop_atomloop_all_init(mtop);
    while(gmx_mtop_atomloop_all_next(aloop,&i,&atom))
    {
        if (mtop->groups.grpnr[egcORFIT] == NULL ||
            mtop->groups.grpnr[egcORFIT][i] == 0)
        {
            /* Not correct for free-energy with changing masses */
            od->mref[j] = atom->m;
            if (ms==NULL || MASTERSIM(ms))
            {
                copy_rvec(xref[i],od->xref[j]);
                for(d=0; d<DIM; d++)
                {
                    com[d] += od->mref[j]*xref[i][d];
                }
            }
            mtot += od->mref[j];
            j++;
        }
    }
    svmul(1.0/mtot,com,com);
    if (ms==NULL || MASTERSIM(ms))
    {
        for(j=0; j<od->nref; j++)
        {
            rvec_dec(od->xref[j],com);
        }
    }
    
    fprintf(fplog,"Found %d orientation experiments\n",od->nex);
    for(i=0; i<od->nex; i++)
    {
        fprintf(fplog,"  experiment %d has %d restraints\n",i+1,nr_ex[i]);
    }
    
    sfree(nr_ex);
    
    fprintf(fplog,"  the fit group consists of %d atoms and has total mass %g\n",
            od->nref,mtot);
    
    if (ms)
    {
        fprintf(fplog,"  the orientation restraints are ensemble averaged over %d systems\n",ms->nsim);
        
        check_multi_int(fplog,ms,od->nr,
                        "the number of orientation restraints");
        check_multi_int(fplog,ms,od->nref,
                        "the number of fit atoms for orientation restraining");
        check_multi_int(fplog,ms,ir->nsteps,"nsteps");
        /* Copy the reference coordinates from the master to the other nodes */
        gmx_sum_sim(DIM*od->nref,od->xref[0],ms);
    }
    
    please_cite(fplog,"Hess2003");
}
Beispiel #10
0
static void gen_local_top(const gmx_mtop_t *mtop,const t_inputrec *ir,
                          gmx_bool bMergeConstr,
                          gmx_localtop_t *top)
{
    int mb,srcnr,destnr,ftype,ftype_dest,mt,natoms,mol,nposre_old;
    gmx_molblock_t *molb;
    gmx_moltype_t *molt;
    const gmx_ffparams_t *ffp;
    t_idef *idef;
    real   *qA,*qB;
    gmx_mtop_atomloop_all_t aloop;
    int    ag;
    t_atom *atom;

    top->atomtypes = mtop->atomtypes;
    
    ffp = &mtop->ffparams;
    
    idef = &top->idef;
    idef->ntypes   = ffp->ntypes;
    idef->atnr     = ffp->atnr;
    idef->functype = ffp->functype;
    idef->iparams  = ffp->iparams;
    idef->iparams_posres = NULL;
    idef->iparams_posres_nalloc = 0;
    idef->fudgeQQ  = ffp->fudgeQQ;
    idef->cmap_grid = ffp->cmap_grid;
    idef->ilsort   = ilsortUNKNOWN;

    init_block(&top->cgs);
    init_blocka(&top->excls);
    for(ftype=0; ftype<F_NRE; ftype++)
    {
        idef->il[ftype].nr     = 0;
        idef->il[ftype].nalloc = 0;
        idef->il[ftype].iatoms = NULL;
    }

    natoms = 0;
    for(mb=0; mb<mtop->nmolblock; mb++)
    {
        molb = &mtop->molblock[mb];
        molt = &mtop->moltype[molb->type];
        
        srcnr  = molt->atoms.nr;
        destnr = natoms;
        
        blockcat(&top->cgs,&molt->cgs,molb->nmol,destnr,srcnr);

        blockacat(&top->excls,&molt->excls,molb->nmol,destnr,srcnr);

        nposre_old = idef->il[F_POSRES].nr;
        for(ftype=0; ftype<F_NRE; ftype++)
        {
            if (bMergeConstr &&
                ftype == F_CONSTR && molt->ilist[F_CONSTRNC].nr > 0)
            {
                /* Merge all constrains into one ilist.
                 * This simplifies the constraint code.
                 */
                for(mol=0; mol<molb->nmol; mol++) {
                    ilistcat(ftype,&idef->il[F_CONSTR],&molt->ilist[F_CONSTR],
                             1,destnr+mol*srcnr,srcnr);
                    ilistcat(ftype,&idef->il[F_CONSTR],&molt->ilist[F_CONSTRNC],
                             1,destnr+mol*srcnr,srcnr);
                }
            }
            else if (!(bMergeConstr && ftype == F_CONSTRNC))
            {
                ilistcat(ftype,&idef->il[ftype],&molt->ilist[ftype],
                         molb->nmol,destnr,srcnr);
            }
        }
        if (idef->il[F_POSRES].nr > nposre_old)
        {
            set_posres_params(idef,molb,nposre_old/2,natoms);
        }

        natoms += molb->nmol*srcnr;
    }

    if (ir == NULL)
    {
        top->idef.ilsort = ilsortUNKNOWN;
    }
    else
    {
        if (ir->efep != efepNO && gmx_mtop_bondeds_free_energy(mtop))
        {
            snew(qA,mtop->natoms);
            snew(qB,mtop->natoms);
            aloop = gmx_mtop_atomloop_all_init(mtop);
            while (gmx_mtop_atomloop_all_next(aloop,&ag,&atom))
            {
                qA[ag] = atom->q;
                qB[ag] = atom->qB;
            }
            gmx_sort_ilist_fe(&top->idef,qA,qB);
            sfree(qA);
            sfree(qB);
        }
        else
        {
            top->idef.ilsort = ilsortNO_FE;
        }
    }
}
Beispiel #11
0
static void
new_status(char *topfile,char *topppfile,char *confin,
	   t_gromppopts *opts,t_inputrec *ir,bool bZero,
	   bool bGenVel,bool bVerbose,t_state *state,
	   gpp_atomtype_t atype,gmx_mtop_t *sys,
	   int *nmi,t_molinfo **mi,t_params plist[],
	   int *comb,double *reppow,real *fudgeQQ,
	   bool bMorse,
	   int *nerror)
{
  t_molinfo   *molinfo=NULL;
  int         nmolblock;
  gmx_molblock_t *molblock,*molbs;
  t_atoms     *confat;
  int         mb,mbs,i,nrmols,nmismatch;
  char        buf[STRLEN];
  bool        bGB=FALSE;

  init_mtop(sys);

  /* Set boolean for GB */
  if(ir->implicit_solvent)
    bGB=TRUE;
  
  /* TOPOLOGY processing */
  sys->name = do_top(bVerbose,topfile,topppfile,opts,bZero,&(sys->symtab),
		     plist,comb,reppow,fudgeQQ,
		     atype,&nrmols,&molinfo,ir,
		     &nmolblock,&molblock,bGB);
  
  sys->nmolblock = 0;
  snew(sys->molblock,nmolblock);
  mbs;
  sys->natoms = 0;
  for(mb=0; mb<nmolblock; mb++) {
    if (sys->nmolblock > 0 &&
	molblock[mb].type == sys->molblock[sys->nmolblock-1].type) {
      /* Merge consecutive blocks with the same molecule type */
      sys->molblock[sys->nmolblock-1].nmol += molblock[mb].nmol;
      sys->natoms += molblock[mb].nmol*sys->molblock[sys->nmolblock-1].natoms_mol;
    } else if (molblock[mb].nmol > 0) {
      /* Add a new molblock to the topology */
      molbs = &sys->molblock[sys->nmolblock];
      *molbs = molblock[mb];
      molbs->natoms_mol = molinfo[molbs->type].atoms.nr;
      molbs->nposres_xA = 0;
      molbs->nposres_xB = 0;
      sys->natoms += molbs->nmol*molbs->natoms_mol;
      sys->nmolblock++;
    }
  }
  if (sys->nmolblock == 0) {
    gmx_fatal(FARGS,"No molecules were defined in the system");
  }

  renumber_moltypes(sys,&nrmols,&molinfo);

  if (bMorse)
    convert_harmonics(nrmols,molinfo,atype);

  if (ir->eDisre == edrNone) {
    i = rm_interactions(F_DISRES,nrmols,molinfo);
    if (i > 0) {
      set_warning_line("unknown",-1);
      sprintf(warn_buf,"disre = no, removed %d distance restraints",i);
      warning_note(NULL);
    }
  }
  if (opts->bOrire == FALSE) {
    i = rm_interactions(F_ORIRES,nrmols,molinfo);
    if (i > 0) {
      set_warning_line("unknown",-1);
      sprintf(warn_buf,"orire = no, removed %d orientation restraints",i);
      warning_note(NULL);
    }
  }
  if (opts->bDihre == FALSE) {
    i = rm_interactions(F_DIHRES,nrmols,molinfo);
    if (i > 0) {
      set_warning_line("unknown",-1);
      sprintf(warn_buf,"dihre = no, removed %d dihedral restraints",i);
      warning_note(NULL);
    }
  }
  
  /* Copy structures from msys to sys */
  molinfo2mtop(nrmols,molinfo,sys);
  
  /* COORDINATE file processing */
  if (bVerbose) 
    fprintf(stderr,"processing coordinates...\n");

  get_stx_coordnum(confin,&state->natoms);
  if (state->natoms != sys->natoms)
    gmx_fatal(FARGS,"number of coordinates in coordinate file (%s, %d)\n"
		"             does not match topology (%s, %d)",
	      confin,state->natoms,topfile,sys->natoms);
  else {
    /* make space for coordinates and velocities */
    char title[STRLEN];
    snew(confat,1);
    init_t_atoms(confat,state->natoms,FALSE);
    init_state(state,state->natoms,0);
    read_stx_conf(confin,title,confat,state->x,state->v,NULL,state->box);
    /* This call fixes the box shape for runs with pressure scaling */
    set_box_rel(ir,state);

    nmismatch = check_atom_names(topfile, confin, sys, confat);
    free_t_atoms(confat,TRUE);
    sfree(confat);
    
    if (nmismatch) {
      sprintf(buf,"%d non-matching atom name%s\n"
	      "atom names from %s will be used\n"
	      "atom names from %s will be ignored\n",
	      nmismatch,(nmismatch == 1) ? "" : "s",topfile,confin);
      warning(buf);
    }    
    if (bVerbose) 
      fprintf(stderr,"double-checking input for internal consistency...\n");
    double_check(ir,state->box,nint_ftype(sys,molinfo,F_CONSTR),nerror);
  }

  if (bGenVel) {
    real *mass;
    gmx_mtop_atomloop_all_t aloop;
    t_atom *atom;

    snew(mass,state->natoms);
    aloop = gmx_mtop_atomloop_all_init(sys);
    while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
      mass[i] = atom->m;
    }

    if (opts->seed == -1) {
      opts->seed = make_seed();
      fprintf(stderr,"Setting gen_seed to %d\n",opts->seed);
    }
    maxwell_speed(opts->tempi,opts->seed,sys,state->v);

    stop_cm(stdout,state->natoms,mass,state->x,state->v);
    sfree(mass);
  }

  *nmi = nrmols;
  *mi  = molinfo;
}
Beispiel #12
0
gmx_shellfc_t *init_shell_flexcon(FILE *fplog,
                                  gmx_mtop_t *mtop, int nflexcon,
                                  int nstcalcenergy,
                                  bool usingDomainDecomposition)
{
    gmx_shellfc_t            *shfc;
    t_shell                  *shell;
    int                      *shell_index = NULL, *at2cg;
    t_atom                   *atom;

    int                       ns, nshell, nsi;
    int                       i, j, type, mb, a_offset, cg, mol, ftype, nra;
    real                      qS, alpha;
    int                       aS, aN = 0; /* Shell and nucleus */
    int                       bondtypes[] = { F_BONDS, F_HARMONIC, F_CUBICBONDS, F_POLARIZATION, F_ANHARM_POL, F_WATER_POL };
#define NBT asize(bondtypes)
    t_iatom                  *ia;
    gmx_mtop_atomloop_all_t   aloop;
    gmx_ffparams_t           *ffparams;
    gmx_molblock_t           *molb;
    gmx_moltype_t            *molt;
    t_block                  *cgs;

    std::array<int, eptNR>    n = countPtypes(fplog, mtop);
    nshell = n[eptShell];

    if (nshell == 0 && nflexcon == 0)
    {
        /* We're not doing shells or flexible constraints */
        return NULL;
    }

    snew(shfc, 1);
    shfc->nflexcon = nflexcon;

    if (nshell == 0)
    {
        /* Only flexible constraints, no shells.
         * Note that make_local_shells() does not need to be called.
         */
        shfc->nshell   = 0;
        shfc->bPredict = FALSE;

        return shfc;
    }

    if (nstcalcenergy != 1)
    {
        gmx_fatal(FARGS, "You have nstcalcenergy set to a value (%d) that is different from 1.\nThis is not supported in combination with shell particles.\nPlease make a new tpr file.", nstcalcenergy);
    }
    if (usingDomainDecomposition)
    {
        gmx_fatal(FARGS, "Shell particles are not implemented with domain decomposition, use a single rank");
    }

    /* We have shells: fill the shell data structure */

    /* Global system sized array, this should be avoided */
    snew(shell_index, mtop->natoms);

    aloop  = gmx_mtop_atomloop_all_init(mtop);
    nshell = 0;
    while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
    {
        if (atom->ptype == eptShell)
        {
            shell_index[i] = nshell++;
        }
    }

    snew(shell, nshell);

    /* Initiate the shell structures */
    for (i = 0; (i < nshell); i++)
    {
        shell[i].shell = -1;
        shell[i].nnucl = 0;
        shell[i].nucl1 = -1;
        shell[i].nucl2 = -1;
        shell[i].nucl3 = -1;
        /* shell[i].bInterCG=FALSE; */
        shell[i].k_1   = 0;
        shell[i].k     = 0;
    }

    ffparams = &mtop->ffparams;

    /* Now fill the structures */
    shfc->bInterCG = FALSE;
    ns             = 0;
    a_offset       = 0;
    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        molb = &mtop->molblock[mb];
        molt = &mtop->moltype[molb->type];

        cgs = &molt->cgs;
        snew(at2cg, molt->atoms.nr);
        for (cg = 0; cg < cgs->nr; cg++)
        {
            for (i = cgs->index[cg]; i < cgs->index[cg+1]; i++)
            {
                at2cg[i] = cg;
            }
        }

        atom = molt->atoms.atom;
        for (mol = 0; mol < molb->nmol; mol++)
        {
            for (j = 0; (j < NBT); j++)
            {
                ia = molt->ilist[bondtypes[j]].iatoms;
                for (i = 0; (i < molt->ilist[bondtypes[j]].nr); )
                {
                    type  = ia[0];
                    ftype = ffparams->functype[type];
                    nra   = interaction_function[ftype].nratoms;

                    /* Check whether we have a bond with a shell */
                    aS = -1;

                    switch (bondtypes[j])
                    {
                        case F_BONDS:
                        case F_HARMONIC:
                        case F_CUBICBONDS:
                        case F_POLARIZATION:
                        case F_ANHARM_POL:
                            if (atom[ia[1]].ptype == eptShell)
                            {
                                aS = ia[1];
                                aN = ia[2];
                            }
                            else if (atom[ia[2]].ptype == eptShell)
                            {
                                aS = ia[2];
                                aN = ia[1];
                            }
                            break;
                        case F_WATER_POL:
                            aN    = ia[4]; /* Dummy */
                            aS    = ia[5]; /* Shell */
                            break;
                        default:
                            gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
                    }

                    if (aS != -1)
                    {
                        qS = atom[aS].q;

                        /* Check whether one of the particles is a shell... */
                        nsi = shell_index[a_offset+aS];
                        if ((nsi < 0) || (nsi >= nshell))
                        {
                            gmx_fatal(FARGS, "nsi is %d should be within 0 - %d. aS = %d",
                                      nsi, nshell, aS);
                        }
                        if (shell[nsi].shell == -1)
                        {
                            shell[nsi].shell = a_offset + aS;
                            ns++;
                        }
                        else if (shell[nsi].shell != a_offset+aS)
                        {
                            gmx_fatal(FARGS, "Weird stuff in %s, %d", __FILE__, __LINE__);
                        }

                        if      (shell[nsi].nucl1 == -1)
                        {
                            shell[nsi].nucl1 = a_offset + aN;
                        }
                        else if (shell[nsi].nucl2 == -1)
                        {
                            shell[nsi].nucl2 = a_offset + aN;
                        }
                        else if (shell[nsi].nucl3 == -1)
                        {
                            shell[nsi].nucl3 = a_offset + aN;
                        }
                        else
                        {
                            if (fplog)
                            {
                                pr_shell(fplog, ns, shell);
                            }
                            gmx_fatal(FARGS, "Can not handle more than three bonds per shell\n");
                        }
                        if (at2cg[aS] != at2cg[aN])
                        {
                            /* shell[nsi].bInterCG = TRUE; */
                            shfc->bInterCG = TRUE;
                        }

                        switch (bondtypes[j])
                        {
                            case F_BONDS:
                            case F_HARMONIC:
                                shell[nsi].k    += ffparams->iparams[type].harmonic.krA;
                                break;
                            case F_CUBICBONDS:
                                shell[nsi].k    += ffparams->iparams[type].cubic.kb;
                                break;
                            case F_POLARIZATION:
                            case F_ANHARM_POL:
                                if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10))
                                {
                                    gmx_fatal(FARGS, "polarize can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1);
                                }
                                shell[nsi].k    += gmx::square(qS)*ONE_4PI_EPS0/
                                    ffparams->iparams[type].polarize.alpha;
                                break;
                            case F_WATER_POL:
                                if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10))
                                {
                                    gmx_fatal(FARGS, "water_pol can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1);
                                }
                                alpha          = (ffparams->iparams[type].wpol.al_x+
                                                  ffparams->iparams[type].wpol.al_y+
                                                  ffparams->iparams[type].wpol.al_z)/3.0;
                                shell[nsi].k  += gmx::square(qS)*ONE_4PI_EPS0/alpha;
                                break;
                            default:
                                gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
                        }
                        shell[nsi].nnucl++;
                    }
                    ia += nra+1;
                    i  += nra+1;
                }
            }
            a_offset += molt->atoms.nr;
        }
        /* Done with this molecule type */
        sfree(at2cg);
    }

    /* Verify whether it's all correct */
    if (ns != nshell)
    {
        gmx_fatal(FARGS, "Something weird with shells. They may not be bonded to something");
    }

    for (i = 0; (i < ns); i++)
    {
        shell[i].k_1 = 1.0/shell[i].k;
    }

    if (debug)
    {
        pr_shell(debug, ns, shell);
    }


    shfc->nshell_gl      = ns;
    shfc->shell_gl       = shell;
    shfc->shell_index_gl = shell_index;

    shfc->bPredict     = (getenv("GMX_NOPREDICT") == NULL);
    shfc->bRequireInit = FALSE;
    if (!shfc->bPredict)
    {
        if (fplog)
        {
            fprintf(fplog, "\nWill never predict shell positions\n");
        }
    }
    else
    {
        shfc->bRequireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != NULL);
        if (shfc->bRequireInit && fplog)
        {
            fprintf(fplog, "\nWill always initiate shell positions\n");
        }
    }

    if (shfc->bPredict)
    {
        if (shfc->bInterCG)
        {
            if (fplog)
            {
                fprintf(fplog, "\nNOTE: there all shells that are connected to particles outside thier own charge group, will not predict shells positions during the run\n\n");
            }
            /* Prediction improves performance, so we should implement either:
             * 1. communication for the atoms needed for prediction
             * 2. prediction using the velocities of shells; currently the
             *    shell velocities are zeroed, it's a bit tricky to keep
             *    track of the shell displacements and thus the velocity.
             */
            shfc->bPredict = FALSE;
        }
    }

    return shfc;
}