static real constr_r_max_moltype(FILE *fplog, gmx_moltype_t *molt,t_iparams *iparams, t_inputrec *ir) { int natoms,nflexcon,*path,at,count; t_blocka at2con; real r0,r1,r2maxA,r2maxB,rmax,lam0,lam1; if (molt->ilist[F_CONSTR].nr == 0 && molt->ilist[F_CONSTRNC].nr == 0) { return 0; } natoms = molt->atoms.nr; at2con = make_at2con(0,natoms,molt->ilist,iparams, EI_DYNAMICS(ir->eI),&nflexcon); snew(path,1+ir->nProjOrder); for(at=0; at<1+ir->nProjOrder; at++) path[at] = -1; r2maxA = 0; for(at=0; at<natoms; at++) { r0 = 0; r1 = 0; count = 0; constr_recur(&at2con,molt->ilist,iparams, FALSE,at,0,1+ir->nProjOrder,path,r0,r1,&r2maxA,&count); } if (ir->efep == efepNO) { rmax = sqrt(r2maxA); } else { r2maxB = 0; for(at=0; at<natoms; at++) { r0 = 0; r1 = 0; count = 0; constr_recur(&at2con,molt->ilist,iparams, TRUE,at,0,1+ir->nProjOrder,path,r0,r1,&r2maxB,&count); } lam0 = ir->init_lambda; if (EI_DYNAMICS(ir->eI)) lam0 += ir->init_step*ir->delta_lambda; rmax = (1 - lam0)*sqrt(r2maxA) + lam0*sqrt(r2maxB); if (EI_DYNAMICS(ir->eI)) { lam1 = ir->init_lambda + (ir->init_step + ir->nsteps)*ir->delta_lambda; rmax = max(rmax,(1 - lam1)*sqrt(r2maxA) + lam1*sqrt(r2maxB)); } } done_blocka(&at2con); sfree(path); return rmax; }
static void constr_recur(t_blocka *at2con, t_ilist *ilist, t_iparams *iparams, gmx_bool bTopB, int at, int depth, int nc, int *path, real r0, real r1, real *r2max, int *count) { int ncon1; t_iatom *ia1, *ia2; int c, con, a1; gmx_bool bUse; t_iatom *ia; real len, rn0, rn1; (*count)++; ncon1 = ilist[F_CONSTR].nr/3; ia1 = ilist[F_CONSTR].iatoms; ia2 = ilist[F_CONSTRNC].iatoms; /* Loop over all constraints connected to this atom */ for (c = at2con->index[at]; c < at2con->index[at+1]; c++) { con = at2con->a[c]; /* Do not walk over already used constraints */ bUse = TRUE; for (a1 = 0; a1 < depth; a1++) { if (con == path[a1]) { bUse = FALSE; } } if (bUse) { ia = constr_iatomptr(ncon1, ia1, ia2, con); /* Flexible constraints currently have length 0, which is incorrect */ if (!bTopB) { len = iparams[ia[0]].constr.dA; } else { len = iparams[ia[0]].constr.dB; } /* In the worst case the bond directions alternate */ if (nc % 2 == 0) { rn0 = r0 + len; rn1 = r1; } else { rn0 = r0; rn1 = r1 + len; } /* Assume angles of 120 degrees between all bonds */ if (rn0*rn0 + rn1*rn1 + rn0*rn1 > *r2max) { *r2max = rn0*rn0 + rn1*rn1 + r0*rn1; if (debug) { fprintf(debug, "Found longer constraint distance: r0 %5.3f r1 %5.3f rmax %5.3f\n", rn0, rn1, sqrt(*r2max)); for (a1 = 0; a1 < depth; a1++) { fprintf(debug, " %d %5.3f", path[a1], iparams[constr_iatomptr(ncon1, ia1, ia2, con)[0]].constr.dA); } fprintf(debug, " %d %5.3f\n", con, len); } } /* Limit the number of recursions to 1000*nc, * so a call does not take more than a second, * even for highly connected systems. */ if (depth + 1 < nc && *count < 1000*nc) { if (ia[1] == at) { a1 = ia[2]; } else { a1 = ia[1]; } /* Recursion */ path[depth] = con; constr_recur(at2con, ilist, iparams, bTopB, a1, depth+1, nc, path, rn0, rn1, r2max, count); path[depth] = -1; } } } }