Exemple #1
0
gmx_constr_t init_constraints(FILE *fplog,
                              gmx_mtop_t *mtop, t_inputrec *ir,
                              gmx_edsam_t ed, t_state *state,
                              t_commrec *cr)
{
    int                  ncon, nset, nmol, settle_type, i, natoms, mt, nflexcon;
    struct gmx_constr   *constr;
    char                *env;
    t_ilist             *ilist;
    gmx_mtop_ilistloop_t iloop;

    ncon =
        gmx_mtop_ftype_count(mtop, F_CONSTR) +
        gmx_mtop_ftype_count(mtop, F_CONSTRNC);
    nset = gmx_mtop_ftype_count(mtop, F_SETTLE);

    if (ncon+nset == 0 && ir->ePull != epullCONSTRAINT && ed == NULL)
    {
        return NULL;
    }

    snew(constr, 1);

    constr->ncon_tot = ncon;
    constr->nflexcon = 0;
    if (ncon > 0)
    {
        constr->n_at2con_mt = mtop->nmoltype;
        snew(constr->at2con_mt, constr->n_at2con_mt);
        for (mt = 0; mt < mtop->nmoltype; mt++)
        {
            constr->at2con_mt[mt] = make_at2con(0, mtop->moltype[mt].atoms.nr,
                                                mtop->moltype[mt].ilist,
                                                mtop->ffparams.iparams,
                                                EI_DYNAMICS(ir->eI), &nflexcon);
            for (i = 0; i < mtop->nmolblock; i++)
            {
                if (mtop->molblock[i].type == mt)
                {
                    constr->nflexcon += mtop->molblock[i].nmol*nflexcon;
                }
            }
        }

        if (constr->nflexcon > 0)
        {
            if (fplog)
            {
                fprintf(fplog, "There are %d flexible constraints\n",
                        constr->nflexcon);
                if (ir->fc_stepsize == 0)
                {
                    fprintf(fplog, "\n"
                            "WARNING: step size for flexible constraining = 0\n"
                            "         All flexible constraints will be rigid.\n"
                            "         Will try to keep all flexible constraints at their original length,\n"
                            "         but the lengths may exhibit some drift.\n\n");
                    constr->nflexcon = 0;
                }
            }
            if (constr->nflexcon > 0)
            {
                please_cite(fplog, "Hess2002");
            }
        }

        if (ir->eConstrAlg == econtLINCS)
        {
            constr->lincsd = init_lincs(fplog, mtop,
                                        constr->nflexcon, constr->at2con_mt,
                                        DOMAINDECOMP(cr) && cr->dd->bInterCGcons,
                                        ir->nLincsIter, ir->nProjOrder);
        }

        if (ir->eConstrAlg == econtSHAKE)
        {
            if (DOMAINDECOMP(cr) && cr->dd->bInterCGcons)
            {
                gmx_fatal(FARGS, "SHAKE is not supported with domain decomposition and constraint that cross charge group boundaries, use LINCS");
            }
            if (constr->nflexcon)
            {
                gmx_fatal(FARGS, "For this system also velocities and/or forces need to be constrained, this can not be done with SHAKE, you should select LINCS");
            }
            please_cite(fplog, "Ryckaert77a");
            if (ir->bShakeSOR)
            {
                please_cite(fplog, "Barth95a");
            }

            constr->shaked = shake_init();
        }
    }

    if (nset > 0)
    {
        please_cite(fplog, "Miyamoto92a");

        constr->bInterCGsettles = inter_charge_group_settles(mtop);

        /* Check that we have only one settle type */
        settle_type = -1;
        iloop       = gmx_mtop_ilistloop_init(mtop);
        while (gmx_mtop_ilistloop_next(iloop, &ilist, &nmol))
        {
            for (i = 0; i < ilist[F_SETTLE].nr; i += 4)
            {
                if (settle_type == -1)
                {
                    settle_type = ilist[F_SETTLE].iatoms[i];
                }
                else if (ilist[F_SETTLE].iatoms[i] != settle_type)
                {
                    gmx_fatal(FARGS,
                              "The [molecules] section of your topology specifies more than one block of\n"
                              "a [moleculetype] with a [settles] block. Only one such is allowed. If you\n"
                              "are trying to partition your solvent into different *groups* (e.g. for\n"
                              "freezing, T-coupling, etc.) then you are using the wrong approach. Index\n"
                              "files specify groups. Otherwise, you may wish to change the least-used\n"
                              "block of molecules with SETTLE constraints into 3 normal constraints.");
                }
            }
        }

        constr->n_at2settle_mt = mtop->nmoltype;
        snew(constr->at2settle_mt, constr->n_at2settle_mt);
        for (mt = 0; mt < mtop->nmoltype; mt++)
        {
            constr->at2settle_mt[mt] =
                make_at2settle(mtop->moltype[mt].atoms.nr,
                               &mtop->moltype[mt].ilist[F_SETTLE]);
        }
    }

    constr->maxwarn = 999;
    env             = getenv("GMX_MAXCONSTRWARN");
    if (env)
    {
        constr->maxwarn = 0;
        sscanf(env, "%d", &constr->maxwarn);
        if (fplog)
        {
            fprintf(fplog,
                    "Setting the maximum number of constraint warnings to %d\n",
                    constr->maxwarn);
        }
        if (MASTER(cr))
        {
            fprintf(stderr,
                    "Setting the maximum number of constraint warnings to %d\n",
                    constr->maxwarn);
        }
    }
    if (constr->maxwarn < 0 && fplog)
    {
        fprintf(fplog, "maxwarn < 0, will not stop on constraint errors\n");
    }
    constr->warncount_lincs  = 0;
    constr->warncount_settle = 0;

    /* Initialize the essential dynamics sampling.
     * Put the pointer to the ED struct in constr */
    constr->ed = ed;
    if (ed != NULL || state->edsamstate.nED > 0)
    {
        init_edsam(mtop, ir, cr, ed, state->x, state->box, &state->edsamstate);
    }

    constr->warn_mtop = mtop;

    return constr;
}
Exemple #2
0
static bool constrain_lincs(FILE *log,t_topology *top,t_inputrec *ir,
			    int step,t_mdatoms *md,int start,int homenr,
			    int *nbl,int **sbl,
			    rvec *x,rvec *xprime,rvec *min_proj,matrix box,
			    real lambda,real *dvdlambda,bool bCoordinates,
			    bool bInit,t_nrnb *nrnb,bool bDumpOnError)
{
  static int       *bla1,*bla2,*blnr,*blbnb,nrtot=0;
  static rvec      *r;
  static real      *bllen,*blc,*blcc,*blm,*tmp1,*tmp2,*tmp3,*lincslam,
                   *bllen0,*ddist;
  static int       nc;
  static bool      bItEqOrder;

  char             buf[STRLEN];
  int              b,i,j,nit,warn,p_imax,error;
  real             wang,p_max,p_rms;
  real             dt,dt_2;
  bool             bOK;
  
  bOK = TRUE;
  if (bInit) {
    nc = top->idef.il[F_SHAKE].nr/3;
    init_lincs(stdlog,top,ir,md,start,homenr,
               &nrtot,
               &r,&bla1,&bla2,&blnr,&blbnb,
               &bllen,&blc,&blcc,&blm,&tmp1,&tmp2,&tmp3,&lincslam,
               &bllen0,&ddist);
#ifdef SPEC_CPU
    bItEqOrder = FALSE;
#else
    bItEqOrder = (getenv("GMX_ACCURATE_LINCS") != NULL);
#endif
  } 
  else if (nc != 0) {
      /* If there are any constraints */
      if (bCoordinates) {
          dt   = ir->delta_t;
          dt_2 = 1.0/(dt*dt);
          
          if (ir->efep != efepNO)
              for(i=0;i<nc;i++)
                  bllen[i]=bllen0[i]+lambda*ddist[i];
          
          /* Set the zero lengths to the old lengths */
          for(b=0; b<nc; b++)
              if (bllen0[b]<GMX_REAL_MIN) {
                  i = bla1[b];
                  j = bla2[b];
                  bllen[b] = sqrt(sqr(x[i][XX]-x[j][XX])+
                                  sqr(x[i][YY]-x[j][YY])+
                                  sqr(x[i][ZZ]-x[j][ZZ]));
              }
                  
                  wang=ir->LincsWarnAngle;
          
          if (do_per_step(step,ir->nstlog) || step<0)
              cconerr(&p_max,&p_rms,&p_imax,xprime,nc,bla1,bla2,bllen);
          
          if ((ir->eI == eiSteep) || (ir->eI == eiCG) || bItEqOrder)
              /* Use more iterations when doing energy minimization, *
              * because we need very accurate positions and forces. */
              nit = ir->nProjOrder;
          else
              nit = 1;
          
#ifdef USE_FORTRAN
#ifdef DOUBLE
          F77_FUNC(flincsd,FLINCSD)(x[0],xprime[0],&nc,bla1,bla2,blnr,blbnb,
                                    bllen,blc,blcc,blm,&nit,&ir->nProjOrder,
                                    md->invmass,r[0],tmp1,tmp2,tmp3,&wang,&warn,
                                    lincslam);
#else
          F77_FUNC(flincs,FLINCS)(x[0],xprime[0],&nc,bla1,bla2,blnr,blbnb,
                                  bllen,blc,blcc,blm,&nit,&ir->nProjOrder,
                                  md->invmass,r[0],tmp1,tmp2,tmp3,&wang,&warn,
                                  lincslam);
#endif
#else
          clincs(x,xprime,nc,bla1,bla2,blnr,blbnb,
                 bllen,blc,blcc,blm,nit,ir->nProjOrder,
                 md->invmass,r,tmp1,tmp2,tmp3,wang,&warn,lincslam);
#endif
          if (ir->efep != efepNO) {
              real dvdl=0;
              
              for(i=0; (i<nc); i++)
                  dvdl+=lincslam[i]*dt_2*ddist[i];
              *dvdlambda+=dvdl;
          }
          
          if(stdlog)
          {
              if (do_per_step(step,ir->nstlog) || (step<0)) 
              {
                  fprintf(stdlog,"   Rel. Constraint Deviation:  Max    between atoms     RMS\n");
                  fprintf(stdlog,"       Before LINCS         %.6f %6d %6d   %.6f\n",
                          p_max,bla1[p_imax]+1,bla2[p_imax]+1,p_rms);
                  cconerr(&p_max,&p_rms,&p_imax,xprime,nc,bla1,bla2,bllen);
                  fprintf(stdlog,"        After LINCS         %.6f %6d %6d   %.6f\n\n",
                          p_max,bla1[p_imax]+1,bla2[p_imax]+1,p_rms);
              }
          }
                  
          if (warn > 0) 
          {
              if (bDumpOnError && stdlog) 
              {
                  cconerr(&p_max,&p_rms,&p_imax,xprime,nc,bla1,bla2,bllen);
                  sprintf(buf,"\nStep %d, time %g (ps)  LINCS WARNING\n"
                          "relative constraint deviation after LINCS:\n"
                          "max %.6f (between atoms %d and %d) rms %.6f\n",
                          step,ir->init_t+step*ir->delta_t,
                          p_max,bla1[p_imax]+1,bla2[p_imax]+1,p_rms);
                  fprintf(stdlog,"%s",buf);
                  fprintf(stderr,"%s",buf);
                  lincs_warning(x,xprime,nc,bla1,bla2,bllen,wang);
              }
              bOK = (p_max < 0.5);
          }
          for(b=0; (b<nc); b++)
              if (bllen0[b] < GMX_REAL_MIN)
                  bllen[b] = 0;
      } 
      else
      {
#ifdef USE_FORTRAN
#ifdef DOUBLE
          F77_FUNC(flincspd,FLINCSPD)(x[0],xprime[0],min_proj[0],&nc,bla1,bla2,blnr,blbnb,
                                      blc,blcc,blm,&ir->nProjOrder,
                                      md->invmass,r[0],tmp1,tmp2,tmp3);
#else
          F77_FUNC(flincsp,FLINCSP)(x[0],xprime[0],min_proj[0],&nc,bla1,bla2,blnr,blbnb,
                                    blc,blcc,blm,&ir->nProjOrder,
                                    md->invmass,r[0],tmp1,tmp2,tmp3);
#endif
#else
          clincsp(x,xprime,min_proj,nc,bla1,bla2,blnr,blbnb,
                  blc,blcc,blm,ir->nProjOrder,
                  md->invmass,r,tmp1,tmp2,tmp3);
#endif
      }
      
      /* count assuming nit=1 */
      inc_nrnb(nrnb,eNR_LINCS,nc);
      inc_nrnb(nrnb,eNR_LINCSMAT,(2+ir->nProjOrder)*nrtot);
  }
  return bOK;
}