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; }
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; }