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; }
void set_constraints(struct gmx_constr *constr, gmx_localtop_t *top,t_inputrec *ir, t_mdatoms *md,t_commrec *cr) { t_idef *idef; int ncons; t_ilist *settle; int iO,iH; idef = &top->idef; if (constr->ncon_tot > 0) { /* We are using the local topology, * so there are only F_CONSTR constraints. */ ncons = idef->il[F_CONSTR].nr/3; /* With DD we might also need to call LINCS with ncons=0 for * communicating coordinates to other nodes that do have constraints. */ if (ir->eConstrAlg == econtLINCS) { set_lincs(idef,md,EI_DYNAMICS(ir->eI),cr,constr->lincsd); } if (ir->eConstrAlg == econtSHAKE) { if (cr->dd) { make_shake_sblock_dd(constr,&idef->il[F_CONSTR],&top->cgs,cr->dd); } else { make_shake_sblock_pd(constr,idef,md); } if (ncons > constr->lagr_nalloc) { constr->lagr_nalloc = over_alloc_dd(ncons); srenew(constr->lagr,constr->lagr_nalloc); } constr->shaked = shake_init(); } } if (idef->il[F_SETTLE].nr > 0 && constr->settled == NULL) { settle = &idef->il[F_SETTLE]; iO = settle->iatoms[1]; iH = settle->iatoms[1]+1; constr->settled = settle_init(md->massT[iO],md->massT[iH], md->invmass[iO],md->invmass[iH], idef->iparams[settle->iatoms[0]].settle.doh, idef->iparams[settle->iatoms[0]].settle.dhh); } /* Make a selection of the local atoms for essential dynamics */ if (constr->ed && cr->dd) { dd_make_local_ed_indices(cr->dd,constr->ed,md); } }