int n_bonded_dx(const gmx_mtop_t *mtop, gmx_bool bExcl) { int mb, nmol, ftype, ndxb, ndx_excl; int ndx; const gmx_moltype_t *molt; /* Count the number of pbc_rvec_sub calls required for bonded interactions. * This number is also roughly proportional to the computational cost. */ ndx = 0; ndx_excl = 0; #if defined _ICC && __ICC == 1400 || defined __ICL && __ICL == 1400 #pragma novector /* Work-around for incorrect vectorization */ #endif for (mb = 0; mb < mtop->nmolblock; mb++) { molt = &mtop->moltype[mtop->molblock[mb].type]; nmol = mtop->molblock[mb].nmol; for (ftype = 0; ftype < F_NRE; ftype++) { if (interaction_function[ftype].flags & IF_BOND) { switch (ftype) { case F_POSRES: case F_FBPOSRES: ndxb = 1; break; case F_CONNBONDS: ndxb = 0; break; default: ndxb = NRAL(ftype) - 1; break; } ndx += nmol*ndxb*molt->ilist[ftype].nr/(1 + NRAL(ftype)); } } if (bExcl) { ndx_excl += nmol*(molt->excls.nra - molt->atoms.nr)/2; } else { ndx_excl = 0; } } if (debug) { fprintf(debug, "ndx bonded %d exclusions %d\n", ndx, ndx_excl); } ndx += ndx_excl; return ndx; }
static void enter_function(t_params *p, t_functype ftype, int comb, real reppow, gmx_ffparams_t *ffparams, t_ilist *il, int *maxtypes, gmx_bool bNB, gmx_bool bAppend) { int k, type, nr, nral, delta, start; start = ffparams->ntypes; nr = p->nr; for (k = 0; k < nr; k++) { if (*maxtypes <= ffparams->ntypes) { *maxtypes += 1000; srenew(ffparams->functype, *maxtypes); srenew(ffparams->iparams, *maxtypes); if (debug) { fprintf(debug, "%s, line %d: srenewed idef->functype and idef->iparams to %d\n", __FILE__, __LINE__, *maxtypes); } } type = enter_params(ffparams, ftype, p->param[k].c, comb, reppow, start, bAppend); /* Type==-1 is used as a signal that this interaction is all-zero and should not be added. */ if (!bNB && type >= 0) { nral = NRAL(ftype); delta = nr*(nral+1); srenew(il->iatoms, il->nr+delta); append_interaction(il, type, nral, p->param[k].a); } } }
static void cppar(t_param p[], int np, t_params plist[], int ftype) { int i, j, nral, nrfp; t_params *ps; ps = &plist[ftype]; nral = NRAL(ftype); nrfp = NRFP(ftype); /* Keep old stuff */ pr_alloc(np, ps); for (i = 0; (i < np); i++) { for (j = 0; (j < nral); j++) { ps->param[ps->nr].a[j] = p[i].a[j]; } for (j = 0; (j < nrfp); j++) { ps->param[ps->nr].c[j] = p[i].c[j]; } for (j = 0; (j < MAXSLEN); j++) { ps->param[ps->nr].s[j] = p[i].s[j]; } ps->nr++; } }
static int vsite_bond_nrcheck(int ftype) { int nrcheck; if ((interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT | IF_ATYPE)) || (ftype == F_IDIHS)) nrcheck = NRAL(ftype); else nrcheck = 0; return nrcheck; }
int gmx_mtop_ftype_count(const gmx_mtop_t *mtop,int ftype) { gmx_mtop_ilistloop_t iloop; t_ilist *il; int n,nmol; n = 0; iloop = gmx_mtop_ilistloop_init(mtop); while (gmx_mtop_ilistloop_next(iloop,&il,&nmol)) { n += nmol*il[ftype].nr/(1+NRAL(ftype)); } return n; }
gmx_bool inter_charge_group_constraints(const gmx_mtop_t *mtop) { const gmx_moltype_t *molt; const t_block *cgs; const t_ilist *il; int mb; int nat, *at2cg, cg, a, ftype, i; gmx_bool bInterCG; bInterCG = FALSE; for (mb = 0; mb < mtop->nmolblock && !bInterCG; mb++) { molt = &mtop->moltype[mtop->molblock[mb].type]; if (molt->ilist[F_CONSTR].nr > 0 || molt->ilist[F_CONSTRNC].nr > 0 || molt->ilist[F_SETTLE].nr > 0) { cgs = &molt->cgs; snew(at2cg, molt->atoms.nr); for (cg = 0; cg < cgs->nr; cg++) { for (a = cgs->index[cg]; a < cgs->index[cg+1]; a++) { at2cg[a] = cg; } } for (ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++) { il = &molt->ilist[ftype]; for (i = 0; i < il->nr && !bInterCG; i += 1+NRAL(ftype)) { if (at2cg[il->iatoms[i+1]] != at2cg[il->iatoms[i+2]]) { bInterCG = TRUE; } } } sfree(at2cg); } } return bInterCG; }
static at2vsitecon_t *make_at2vsitecon(int natoms,t_params plist[]) { gmx_bool *bVSI; int ftype,i,j,ai,aj,nr; at2vsitecon_t *at2vc; snew(at2vc,natoms); snew(bVSI,natoms); for(ftype=0; (ftype<F_NRE); ftype++) { if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN) { for(i=0; (i<plist[ftype].nr); i++) { for(j=0; j<NRAL(ftype); j++) bVSI[plist[ftype].param[i].a[j]] = TRUE; } } } for(ftype=0; (ftype<F_NRE); ftype++) { if (interaction_function[ftype].flags & IF_CONSTRAINT) { for(i=0; (i<plist[ftype].nr); i++) { ai = plist[ftype].param[i].AI; aj = plist[ftype].param[i].AJ; if (bVSI[ai] && bVSI[aj]) { /* Store forward direction */ nr = at2vc[ai].nr; if (nr % 10 == 0) srenew(at2vc[ai].aj,nr+10); at2vc[ai].aj[nr] = aj; at2vc[ai].nr++; /* Store backward direction */ nr = at2vc[aj].nr; if (nr % 10 == 0) srenew(at2vc[aj].aj,nr+10); at2vc[aj].aj[nr] = ai; at2vc[aj].nr++; } } } } sfree(bVSI); return at2vc; }
static at2vsitebond_t *make_at2vsitebond(int natoms,t_params plist[]) { gmx_bool *bVSI; int ftype,i,j,nrcheck,nr; t_iatom *aa; at2vsitebond_t *at2vb; snew(at2vb,natoms); snew(bVSI,natoms); for(ftype=0; (ftype<F_NRE); ftype++) { if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN) { for(i=0; (i<plist[ftype].nr); i++) { for(j=0; j<NRAL(ftype); j++) bVSI[plist[ftype].param[i].a[j]] = TRUE; } } } for(ftype=0; (ftype<F_NRE); ftype++) { nrcheck = vsite_bond_nrcheck(ftype); if (nrcheck > 0) { for(i=0; (i<plist[ftype].nr); i++) { aa = plist[ftype].param[i].a; for(j=0; j<nrcheck; j++) { if (bVSI[aa[j]]) { nr = at2vb[aa[j]].nr; if (nr % 10 == 0) srenew(at2vb[aa[j]].vsbp,nr+10); at2vb[aa[j]].vsbp[nr].ftype = ftype; at2vb[aa[j]].vsbp[nr].param = &plist[ftype].param[i]; at2vb[aa[j]].nr++; } } } } } sfree(bVSI); return at2vb; }
static void enter_function(t_params *p, t_functype ftype, int comb, real reppow, gmx_ffparams_t *ffparams, InteractionList *il, bool bNB, bool bAppend) { int k, type, nr, nral, start; start = ffparams->numTypes(); nr = p->nr; for (k = 0; k < nr; k++) { type = enter_params(ffparams, ftype, p->param[k].c, comb, reppow, start, bAppend); /* Type==-1 is used as a signal that this interaction is all-zero and should not be added. */ if (!bNB && type >= 0) { assert(il); nral = NRAL(ftype); append_interaction(il, type, nral, p->param[k].a); } } }
static int *make_at2settle(int natoms, const t_ilist *ilist) { int *at2s; int a, stride, s; snew(at2s, natoms); /* Set all to no settle */ for (a = 0; a < natoms; a++) { at2s[a] = -1; } stride = 1 + NRAL(F_SETTLE); for (s = 0; s < ilist->nr; s += stride) { at2s[ilist->iatoms[s+1]] = s/stride; at2s[ilist->iatoms[s+2]] = s/stride; at2s[ilist->iatoms[s+3]] = s/stride; } return at2s; }
static void ilistcat(int ftype,t_ilist *dest,t_ilist *src,int copies, int dnum,int snum) { int nral,c,i,a; nral = NRAL(ftype); dest->nalloc = dest->nr + copies*src->nr; srenew(dest->iatoms,dest->nalloc); for(c=0; c<copies; c++) { for(i=0; i<src->nr; ) { dest->iatoms[dest->nr++] = src->iatoms[i++]; for(a=0; a<nral; a++) { dest->iatoms[dest->nr++] = dnum + src->iatoms[i++]; } } dnum += snum; } }
//! Divides bonded interactions over threads static void divide_bondeds_over_threads(t_idef *idef, int nthread, int max_nthread_uniform, bool *haveBondeds) { ilist_data_t ild[F_NRE]; int ntype; int f; assert(nthread > 0); idef->nthreads = nthread; if (F_NRE*(nthread + 1) > idef->il_thread_division_nalloc) { idef->il_thread_division_nalloc = F_NRE*(nthread + 1); snew(idef->il_thread_division, idef->il_thread_division_nalloc); } *haveBondeds = false; ntype = 0; for (f = 0; f < F_NRE; f++) { if (!ftype_is_bonded_potential(f)) { continue; } if (idef->il[f].nr > 0) { *haveBondeds = true; } if (idef->il[f].nr == 0) { /* No interactions, avoid all the integer math below */ int t; for (t = 0; t <= nthread; t++) { idef->il_thread_division[f*(nthread + 1) + t] = 0; } } else if (nthread <= max_nthread_uniform || f == F_DISRES) { /* On up to 4 threads, load balancing the bonded work * is more important than minimizing the reduction cost. */ int nat1, t; /* nat1 = 1 + #atoms(ftype) which is the stride use for iatoms */ nat1 = 1 + NRAL(f); for (t = 0; t <= nthread; t++) { int nr_t; /* Divide equally over the threads */ nr_t = (((idef->il[f].nr/nat1)*t)/nthread)*nat1; if (f == F_DISRES) { /* Ensure that distance restraint pairs with the same label * end up on the same thread. */ while (nr_t > 0 && nr_t < idef->il[f].nr && idef->iparams[idef->il[f].iatoms[nr_t]].disres.label == idef->iparams[idef->il[f].iatoms[nr_t-nat1]].disres.label) { nr_t += nat1; } } idef->il_thread_division[f*(nthread + 1) + t] = nr_t; } } else { /* Add this ftype to the list to be distributed */ int nat; nat = NRAL(f); ild[ntype].ftype = f; ild[ntype].il = &idef->il[f]; ild[ntype].nat = nat; /* The first index for the thread division is always 0 */ idef->il_thread_division[f*(nthread + 1)] = 0; ntype++; } } if (ntype > 0) { divide_bondeds_by_locality(ntype, ild, nthread, idef); } if (debug) { int f; fprintf(debug, "Division of bondeds over threads:\n"); for (f = 0; f < F_NRE; f++) { if (ftype_is_bonded_potential(f) && idef->il[f].nr > 0) { int t; fprintf(debug, "%16s", interaction_function[f].name); for (t = 0; t < nthread; t++) { fprintf(debug, " %4d", (idef->il_thread_division[f*(nthread + 1) + t + 1] - idef->il_thread_division[f*(nthread + 1) + t])/ (1 + NRAL(f))); } fprintf(debug, "\n"); } } } }
static void get_verlet_buffer_atomtypes(const gmx_mtop_t *mtop, verletbuf_atomtype_t **att_p, int *natt_p, int *n_nonlin_vsite) { verletbuf_atomtype_t *att; int natt; int mb, nmol, ft, i, a1, a2, a3, a; const t_atoms *atoms; const t_ilist *il; const t_iparams *ip; atom_nonbonded_kinetic_prop_t *prop; real *vsite_m; int n_nonlin_vsite_mol; att = NULL; natt = 0; if (n_nonlin_vsite != NULL) { *n_nonlin_vsite = 0; } for (mb = 0; mb < mtop->nmolblock; mb++) { nmol = mtop->molblock[mb].nmol; atoms = &mtop->moltype[mtop->molblock[mb].type].atoms; /* Check for constraints, as they affect the kinetic energy. * For virtual sites we need the masses and geometry of * the constructing atoms to determine their velocity distribution. */ snew(prop, atoms->nr); snew(vsite_m, atoms->nr); for (ft = F_CONSTR; ft <= F_CONSTRNC; ft++) { il = &mtop->moltype[mtop->molblock[mb].type].ilist[ft]; for (i = 0; i < il->nr; i += 1+NRAL(ft)) { ip = &mtop->ffparams.iparams[il->iatoms[i]]; a1 = il->iatoms[i+1]; a2 = il->iatoms[i+2]; if (atoms->atom[a2].m > prop[a1].con_mass) { prop[a1].con_mass = atoms->atom[a2].m; prop[a1].con_len = ip->constr.dA; } if (atoms->atom[a1].m > prop[a2].con_mass) { prop[a2].con_mass = atoms->atom[a1].m; prop[a2].con_len = ip->constr.dA; } } } il = &mtop->moltype[mtop->molblock[mb].type].ilist[F_SETTLE]; for (i = 0; i < il->nr; i += 1+NRAL(F_SETTLE)) { ip = &mtop->ffparams.iparams[il->iatoms[i]]; a1 = il->iatoms[i+1]; a2 = il->iatoms[i+2]; a3 = il->iatoms[i+3]; /* Usually the mass of a1 (usually oxygen) is larger than a2/a3. * If this is not the case, we overestimate the displacement, * which leads to a larger buffer (ok since this is an exotic case). */ prop[a1].con_mass = atoms->atom[a2].m; prop[a1].con_len = ip->settle.doh; prop[a2].con_mass = atoms->atom[a1].m; prop[a2].con_len = ip->settle.doh; prop[a3].con_mass = atoms->atom[a1].m; prop[a3].con_len = ip->settle.doh; } get_vsite_masses(&mtop->moltype[mtop->molblock[mb].type], &mtop->ffparams, vsite_m, &n_nonlin_vsite_mol); if (n_nonlin_vsite != NULL) { *n_nonlin_vsite += nmol*n_nonlin_vsite_mol; } for (a = 0; a < atoms->nr; a++) { if (atoms->atom[a].ptype == eptVSite) { prop[a].mass = vsite_m[a]; } else { prop[a].mass = atoms->atom[a].m; } prop[a].type = atoms->atom[a].type; prop[a].q = atoms->atom[a].q; /* We consider an atom constrained, #DOF=2, when it is * connected with constraints to (at least one) atom with * a mass of more than 0.4x its own mass. This is not a critical * parameter, since with roughly equal masses the unconstrained * and constrained displacement will not differ much (and both * overestimate the displacement). */ prop[a].bConstr = (prop[a].con_mass > 0.4*prop[a].mass); add_at(&att, &natt, &prop[a], nmol); } sfree(vsite_m); sfree(prop); } if (gmx_debug_at) { for (a = 0; a < natt; a++) { fprintf(debug, "type %d: m %5.2f t %d q %6.3f con %d con_m %5.3f con_l %5.3f n %d\n", a, att[a].prop.mass, att[a].prop.type, att[a].prop.q, att[a].prop.bConstr, att[a].prop.con_mass, att[a].prop.con_len, att[a].n); } } *att_p = att; *natt_p = natt; }
static void get_vsite_masses(const gmx_moltype_t *moltype, const gmx_ffparams_t *ffparams, real *vsite_m, int *n_nonlin_vsite) { int ft, i; const t_ilist *il; *n_nonlin_vsite = 0; /* Check for virtual sites, determine mass from constructing atoms */ for (ft = 0; ft < F_NRE; ft++) { if (IS_VSITE(ft)) { il = &moltype->ilist[ft]; for (i = 0; i < il->nr; i += 1+NRAL(ft)) { const t_iparams *ip; real cam[5] = {0}, inv_mass, coeff, m_aj; int a1, j, aj; ip = &ffparams->iparams[il->iatoms[i]]; a1 = il->iatoms[i+1]; if (ft != F_VSITEN) { for (j = 1; j < NRAL(ft); j++) { cam[j] = moltype->atoms.atom[il->iatoms[i+1+j]].m; if (cam[j] == 0) { cam[j] = vsite_m[il->iatoms[i+1+j]]; } if (cam[j] == 0) { gmx_fatal(FARGS, "In molecule type '%s' %s construction involves atom %d, which is a virtual site of equal or high complexity. This is not supported.", *moltype->name, interaction_function[ft].longname, il->iatoms[i+1+j]+1); } } } switch (ft) { case F_VSITE2: /* Exact */ vsite_m[a1] = (cam[1]*cam[2])/(cam[2]*sqr(1-ip->vsite.a) + cam[1]*sqr(ip->vsite.a)); break; case F_VSITE3: /* Exact */ vsite_m[a1] = (cam[1]*cam[2]*cam[3])/(cam[2]*cam[3]*sqr(1-ip->vsite.a-ip->vsite.b) + cam[1]*cam[3]*sqr(ip->vsite.a) + cam[1]*cam[2]*sqr(ip->vsite.b)); break; case F_VSITEN: /* Exact */ inv_mass = 0; for (j = 0; j < 3*ffparams->iparams[il->iatoms[i]].vsiten.n; j += 3) { aj = il->iatoms[i+j+2]; coeff = ffparams->iparams[il->iatoms[i+j]].vsiten.a; if (moltype->atoms.atom[aj].ptype == eptVSite) { m_aj = vsite_m[aj]; } else { m_aj = moltype->atoms.atom[aj].m; } if (m_aj <= 0) { gmx_incons("The mass of a vsiten constructing atom is <= 0"); } inv_mass += coeff*coeff/m_aj; } vsite_m[a1] = 1/inv_mass; /* Correct for loop increment of i */ i += j - 1 - NRAL(ft); break; default: /* Use the mass of the lightest constructing atom. * This is an approximation. * If the distance of the virtual site to the * constructing atom is less than all distances * between constructing atoms, this is a safe * over-estimate of the displacement of the vsite. * This condition holds for all H mass replacement * vsite constructions, except for SP2/3 groups. * In SP3 groups one H will have a F_VSITE3 * construction, so even there the total drift * estimate shouldn't be far off. */ assert(j >= 1); vsite_m[a1] = cam[1]; for (j = 2; j < NRAL(ft); j++) { vsite_m[a1] = min(vsite_m[a1], cam[j]); } (*n_nonlin_vsite)++; break; } if (gmx_debug_at) { fprintf(debug, "atom %4d %-20s mass %6.3f\n", a1, interaction_function[ft].longname, vsite_m[a1]); } } } } }
void count_bonded_distances(gmx_mtop_t *mtop, const t_inputrec *ir, double *ndistance_c, double *ndistance_simd) { gmx_bool bExcl; int nst_ener_or_vir; double nonsimd_step_frac; int mb, nmol, ftype; gmx_moltype_t *molt; double ndtot_c, ndtot_simd; #ifdef GMX_SIMD_HAVE_REAL gmx_bool bSimdBondeds = TRUE; #else gmx_bool bSimdBondeds = FALSE; #endif bExcl = (ir->cutoff_scheme == ecutsGROUP && IR_EXCL_FORCES(*ir) && !EEL_FULL(ir->coulombtype)); if (bSimdBondeds) { /* We only have SIMD versions of these bondeds without energy and * without shift-forces, we take that into account here. */ if (ir->nstcalcenergy > 0) { nonsimd_step_frac = 1.0/ir->nstcalcenergy; } else { nonsimd_step_frac = 0; } if (ir->epc != epcNO && 1.0/ir->nstpcouple > nonsimd_step_frac) { nonsimd_step_frac = 1.0/ir->nstpcouple; } } else { nonsimd_step_frac = 1; } /* Count the number of pbc_rvec_sub calls required for bonded interactions. * This number is also roughly proportional to the computational cost. */ ndtot_c = 0; ndtot_simd = 0; #if defined _ICC && __ICC == 1400 || defined __ICL && __ICL == 1400 #pragma novector /* Work-around for incorrect vectorization */ #endif for (mb = 0; mb < mtop->nmolblock; mb++) { molt = &mtop->moltype[mtop->molblock[mb].type]; nmol = mtop->molblock[mb].nmol; for (ftype = 0; ftype < F_NRE; ftype++) { int nbonds; if (interaction_function[ftype].flags & IF_BOND) { double nd_c, nd_simd; nd_c = 0; nd_simd = 0; /* For all interactions, except for the three exceptions * in the switch below, #distances = #atoms - 1. */ switch (ftype) { case F_POSRES: case F_FBPOSRES: nd_c = 1; break; case F_CONNBONDS: break; /* These bonded potentially use SIMD */ case F_ANGLES: case F_PDIHS: case F_RBDIHS: nd_c = nonsimd_step_frac *(NRAL(ftype) - 1); nd_simd = (1 - nonsimd_step_frac)*(NRAL(ftype) - 1); break; default: nd_c = NRAL(ftype) - 1; break; } nbonds = nmol*molt->ilist[ftype].nr/(1 + NRAL(ftype)); ndtot_c += nbonds*nd_c; ndtot_simd += nbonds*nd_simd; } } if (bExcl) { ndtot_c += nmol*(molt->excls.nra - molt->atoms.nr)/2; } } if (debug) { fprintf(debug, "nr. of distance calculations in bondeds: C %.1f SIMD %.1f\n", ndtot_c, ndtot_simd); } if (ndistance_c != NULL) { *ndistance_c = ndtot_c; } if (ndistance_simd != NULL) { *ndistance_simd = ndtot_simd; } }
void print_bt(FILE *out, directive d, gpp_atomtype_t at, int ftype, int fsubtype, t_params plist[], gmx_bool bFullDih) { /* This dihp is a DIRTY patch because the dih-types do not use * all four atoms to determine the type. */ const int dihp[2][2] = { { 1, 2 }, { 0, 3 } }; t_params *bt; int i, j, f, nral, nrfp; gmx_bool bDih = FALSE, bSwapParity; bt = &(plist[ftype]); if (!bt->nr) { return; } f = 0; switch (ftype) { case F_G96ANGLES: f = 1; break; case F_G96BONDS: f = 1; break; case F_MORSE: f = 2; break; case F_CUBICBONDS: f = 3; break; case F_CONNBONDS: f = 4; break; case F_HARMONIC: f = 5; break; case F_CROSS_BOND_ANGLES: f = 2; break; case F_CROSS_BOND_BONDS: f = 3; break; case F_UREY_BRADLEY: f = 4; break; case F_PDIHS: case F_RBDIHS: case F_FOURDIHS: bDih = TRUE; break; case F_IDIHS: f = 1; bDih = TRUE; break; case F_CONSTRNC: f = 1; break; case F_VSITE3FD: f = 1; break; case F_VSITE3FAD: f = 2; break; case F_VSITE3OUT: f = 3; break; case F_VSITE4FDN: f = 1; break; case F_CMAP: f = 1; break; default: bDih = FALSE; } if (bFullDih) { bDih = FALSE; } if (fsubtype) { f = fsubtype-1; } nral = NRAL(ftype); nrfp = NRFP(ftype); /* header */ fprintf(out, "[ %s ]\n", dir2str(d)); fprintf(out, "; "); if (!bDih) { fprintf (out, "%3s %4s", "ai", "aj"); for (j = 2; (j < nral); j++) { fprintf (out, " %3c%c", 'a', 'i'+j); } } else { for (j = 0; (j < 2); j++) { fprintf (out, "%3c%c", 'a', 'i'+dihp[f][j]); } } fprintf (out, " funct"); for (j = 0; (j < nrfp); j++) { fprintf (out, " %12c%1d", 'c', j); } fprintf (out, "\n"); /* print bondtypes */ for (i = 0; (i < bt->nr); i++) { bSwapParity = (bt->param[i].C0 == NOTSET) && (bt->param[i].C1 == -1); if (!bDih) { for (j = 0; (j < nral); j++) { fprintf (out, "%5s ", get_atomtype_name(bt->param[i].a[j], at)); } } else { for (j = 0; (j < 2); j++) { fprintf (out, "%5s ", get_atomtype_name(bt->param[i].a[dihp[f][j]], at)); } } fprintf (out, "%5d ", bSwapParity ? -f-1 : f+1); if (bt->param[i].s[0]) { fprintf(out, " %s", bt->param[i].s); } else { for (j = 0; (j < nrfp && (bt->param[i].c[j] != NOTSET)); j++) { fprintf (out, "%13.6e ", bt->param[i].c[j]); } } fprintf (out, "\n"); } fprintf (out, "\n"); fflush (out); }
static void clean_vsite_angles(t_params *plist, t_pindex pindex[], int cftype, int vsite_type[], at2vsitecon_t *at2vc) { int i,j,parnr,k,l,m,n,nvsite,kept_i,vsnral,vsitetype; atom_id atom,constr,at1,at2; atom_id vsiteatoms[MAXATOMLIST]; gmx_bool bKeep,bUsed,bPresent,bAll3FAD,bFirstTwo; t_params *ps; ps = &(plist[cftype]); vsnral=0; kept_i=0; for(i=0; (i<ps->nr); i++) { /* for all angles in the plist */ bKeep=FALSE; bAll3FAD=TRUE; /* check if all virtual sites are constructed from the same atoms */ nvsite=0; for(k=0; (k<3) && !bKeep; k++) { /* for all atoms in the angle */ atom = ps->param[i].a[k]; if (vsite_type[atom]!=NOTSET) { nvsite++; bAll3FAD = bAll3FAD && (pindex[atom].ftype == F_VSITE3FAD); if (nvsite==1) { /* store construction atoms of first vsite */ vsnral=NRAL(pindex[atom].ftype)-1; for(m=0; (m<vsnral); m++) vsiteatoms[m]= plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1]; } else /* check if this vsite is constructed from the same atoms */ if (vsnral == NRAL(pindex[atom].ftype)-1 ) for(m=0; (m<vsnral) && !bKeep; m++) { bPresent=FALSE; constr= plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1]; for(n=0; (n<vsnral) && !bPresent; n++) if (constr == vsiteatoms[n]) bPresent=TRUE; if (!bPresent) bKeep=TRUE; } else bKeep=TRUE; } } /* keep all angles with no virtual sites in them or with virtual sites with more than 3 constr. atoms */ if ( nvsite == 0 && vsnral > 3 ) bKeep=TRUE; /* check if all non-vsite atoms are used in construction: */ bFirstTwo=TRUE; for(k=0; (k<3) && !bKeep; k++) { /* for all atoms in the angle */ atom = ps->param[i].a[k]; if (vsite_type[atom]==NOTSET) { bUsed=FALSE; for(m=0; (m<vsnral) && !bUsed; m++) if (atom == vsiteatoms[m]) { bUsed=TRUE; bFirstTwo = bFirstTwo && m<2; } if (!bUsed) bKeep=TRUE; } } if ( ! ( bAll3FAD && bFirstTwo ) ) /* check if all constructing atoms are constrained together */ for (m=0; m<vsnral && !bKeep; m++) { /* all constr. atoms */ at1 = vsiteatoms[m]; at2 = vsiteatoms[(m+1) % vsnral]; bPresent=FALSE; for(j=0; j<at2vc[at1].nr; j++) { if (at2vc[at1].aj[j] == at2) bPresent = TRUE; } if (!bPresent) bKeep=TRUE; } if ( bKeep ) { /* now copy the angle to the new array */ memcpy(&(ps->param[kept_i]), &(ps->param[i]),(size_t)sizeof(ps->param[0])); kept_i++; } } if (ps->nr != kept_i) fprintf(stderr,"Removed %4d %15ss with virtual sites, %5d left\n", ps->nr-kept_i, interaction_function[cftype].longname, kept_i); ps->nr=kept_i; }
int dd_make_local_constraints(gmx_domdec_t *dd,int at_start, const gmx_mtop_t *mtop, const int *cginfo, gmx_constr_t constr,int nrec, t_ilist *il_local) { gmx_domdec_constraints_t *dc; t_ilist *ilc_local,*ils_local; ind_req_t *ireq; const t_blocka *at2con_mt; const int **at2settle_mt; gmx_hash_t ga2la_specat; int at_end,i,j; t_iatom *iap; dc = dd->constraints; ilc_local = &il_local[F_CONSTR]; ils_local = &il_local[F_SETTLE]; dc->ncon = 0; ilc_local->nr = 0; if (dd->constraint_comm) { at2con_mt = atom2constraints_moltype(constr); ireq = &dd->constraint_comm->ireq[0]; ireq->n = 0; } else { at2con_mt = NULL; ireq = NULL; } if (dd->bInterCGsettles) { at2settle_mt = atom2settle_moltype(constr); ils_local->nr = 0; } else { /* Settle works inside charge groups, we assigned them already */ at2settle_mt = NULL; } if (at2settle_mt == NULL) { atoms_to_constraints(dd,mtop,cginfo,at2con_mt,nrec, ilc_local,ireq); } else { int t0_set; int thread; /* Do the constraints, if present, on the first thread. * Do the settles on all other threads. */ t0_set = ((at2con_mt != NULL && dc->nthread > 1) ? 1 : 0); #pragma omp parallel for num_threads(dc->nthread) schedule(static) for(thread=0; thread<dc->nthread; thread++) { if (at2con_mt && thread == 0) { atoms_to_constraints(dd,mtop,cginfo,at2con_mt,nrec, ilc_local,ireq); } if (thread >= t0_set) { int cg0,cg1; t_ilist *ilst; ind_req_t *ireqt; /* Distribute the settle check+assignments over * dc->nthread or dc->nthread-1 threads. */ cg0 = (dd->ncg_home*(thread-t0_set ))/(dc->nthread-t0_set); cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set); if (thread == t0_set) { ilst = ils_local; } else { ilst = &dc->ils[thread]; } ilst->nr = 0; ireqt = &dd->constraint_comm->ireq[thread]; if (thread > 0) { ireqt->n = 0; } atoms_to_settles(dd,mtop,cginfo,at2settle_mt, cg0,cg1, ilst,ireqt); } } /* Combine the generate settles and requested indices */ for(thread=1; thread<dc->nthread; thread++) { t_ilist *ilst; ind_req_t *ireqt; int ia; if (thread > t0_set) { ilst = &dc->ils[thread]; if (ils_local->nr + ilst->nr > ils_local->nalloc) { ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr); srenew(ils_local->iatoms,ils_local->nalloc); } for(ia=0; ia<ilst->nr; ia++) { ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia]; } ils_local->nr += ilst->nr; } ireqt = &dd->constraint_comm->ireq[thread]; if (ireq->n+ireqt->n > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+ireqt->n); srenew(ireq->ind,ireq->nalloc); } for(ia=0; ia<ireqt->n; ia++) { ireq->ind[ireq->n+ia] = ireqt->ind[ia]; } ireq->n += ireqt->n; } if (debug) { fprintf(debug,"Settles: total %3d\n",ils_local->nr/4); } } if (dd->constraint_comm) { int nral1; at_end = setup_specat_communication(dd,ireq,dd->constraint_comm, dd->constraints->ga2la, at_start,2, "constraint"," or lincs-order"); /* Fill in the missing indices */ ga2la_specat = dd->constraints->ga2la; nral1 = 1 + NRAL(F_CONSTR); for(i=0; i<ilc_local->nr; i+=nral1) { iap = ilc_local->iatoms + i; for(j=1; j<nral1; j++) { if (iap[j] < 0) { iap[j] = gmx_hash_get_minone(ga2la_specat,-iap[j]-1); } } } nral1 = 1 + NRAL(F_SETTLE); for(i=0; i<ils_local->nr; i+=nral1) { iap = ils_local->iatoms + i; for(j=1; j<nral1; j++) { if (iap[j] < 0) { iap[j] = gmx_hash_get_minone(ga2la_specat,-iap[j]-1); } } } } else { at_end = at_start; } return at_end; }
void gmx_sort_ilist_fe(t_idef *idef, const real *qA, const real *qB) { int ftype, nral, i, ic, ib, a; t_iparams *iparams; t_ilist *ilist; t_iatom *iatoms; gmx_bool bPert; t_iatom *iabuf; int iabuf_nalloc; if (qB == NULL) { qB = qA; } iabuf_nalloc = 0; iabuf = NULL; iparams = idef->iparams; for (ftype = 0; ftype < F_NRE; ftype++) { if (interaction_function[ftype].flags & IF_BOND) { ilist = &idef->il[ftype]; iatoms = ilist->iatoms; nral = NRAL(ftype); ic = 0; ib = 0; i = 0; while (i < ilist->nr) { /* Check if this interaction is perturbed */ if (ip_q_pert(ftype, iatoms+i, iparams, qA, qB)) { /* Copy to the perturbed buffer */ if (ib + 1 + nral > iabuf_nalloc) { iabuf_nalloc = over_alloc_large(ib+1+nral); srenew(iabuf, iabuf_nalloc); } for (a = 0; a < 1+nral; a++) { iabuf[ib++] = iatoms[i++]; } } else { /* Copy in place */ for (a = 0; a < 1+nral; a++) { iatoms[ic++] = iatoms[i++]; } } } /* Now we now the number of non-perturbed interactions */ ilist->nr_nonperturbed = ic; /* Copy the buffer with perturbed interactions to the ilist */ for (a = 0; a < ib; a++) { iatoms[ic++] = iabuf[a]; } if (debug) { fprintf(debug, "%s non-pert %d pert %d\n", interaction_function[ftype].longname, ilist->nr_nonperturbed, ilist->nr-ilist->nr_nonperturbed); } } } sfree(iabuf); idef->ilsort = ilsortFE_SORTED; }
void convert_params(int atnr, t_params nbtypes[], t_molinfo *mi, t_molinfo *intermolecular_interactions, int comb, double reppow, real fudgeQQ, gmx_mtop_t *mtop) { int i; unsigned long flags; gmx_ffparams_t *ffp; gmx_moltype_t *molt; t_params *plist; ffp = &mtop->ffparams; ffp->atnr = atnr; ffp->functype.clear(); ffp->iparams.clear(); ffp->reppow = reppow; enter_function(&(nbtypes[F_LJ]), static_cast<t_functype>(F_LJ), comb, reppow, ffp, nullptr, TRUE, TRUE); enter_function(&(nbtypes[F_BHAM]), static_cast<t_functype>(F_BHAM), comb, reppow, ffp, nullptr, TRUE, TRUE); for (size_t mt = 0; mt < mtop->moltype.size(); mt++) { molt = &mtop->moltype[mt]; for (i = 0; (i < F_NRE); i++) { molt->ilist[i].iatoms.clear(); plist = mi[mt].plist; flags = interaction_function[i].flags; if ((i != F_LJ) && (i != F_BHAM) && ((flags & IF_BOND) || (flags & IF_VSITE) || (flags & IF_CONSTRAINT))) { enter_function(&(plist[i]), static_cast<t_functype>(i), comb, reppow, ffp, &molt->ilist[i], FALSE, (i == F_POSRES || i == F_FBPOSRES)); } } } mtop->bIntermolecularInteractions = FALSE; if (intermolecular_interactions != nullptr) { /* Process the intermolecular interaction list */ mtop->intermolecular_ilist = gmx::compat::make_unique<InteractionLists>(); for (i = 0; (i < F_NRE); i++) { (*mtop->intermolecular_ilist)[i].iatoms.clear(); plist = intermolecular_interactions->plist; if (plist[i].nr > 0) { flags = interaction_function[i].flags; /* For intermolecular interactions we (currently) * only support potentials. * Constraints and virtual sites would be possible, * but require a lot of extra (bug-prone) code. */ if (!(flags & IF_BOND)) { gmx_fatal(FARGS, "The intermolecular_interaction section may only contain bonded potentials"); } else if (NRAL(i) == 1) /* e.g. position restraints */ { gmx_fatal(FARGS, "Single atom interactions don't make sense in the intermolecular_interaction section, you can put them in the moleculetype section"); } else if (flags & IF_CHEMBOND) { gmx_fatal(FARGS, "The intermolecular_interaction can not contain chemically bonding interactions"); } else { enter_function(&(plist[i]), static_cast<t_functype>(i), comb, reppow, ffp, &(*mtop->intermolecular_ilist)[i], FALSE, FALSE); mtop->bIntermolecularInteractions = TRUE; } } } if (!mtop->bIntermolecularInteractions) { mtop->intermolecular_ilist.reset(nullptr); } } ffp->fudgeQQ = fudgeQQ; }
static void clean_vsite_dihs(t_params *plist, t_pindex pindex[], int cftype, int vsite_type[]) { int ftype,i,parnr,k,l,m,n,nvsite,kept_i,vsnral; atom_id atom,constr; atom_id vsiteatoms[3]; gmx_bool bKeep,bUsed,bPresent; t_params *ps; ps = &(plist[cftype]); vsnral=0; kept_i=0; for(i=0; (i<ps->nr); i++) { /* for all dihedrals in the plist */ bKeep=FALSE; /* check if all virtual sites are constructed from the same atoms */ nvsite=0; for(k=0; (k<4) && !bKeep; k++) { /* for all atoms in the dihedral */ atom = ps->param[i].a[k]; if (vsite_type[atom]!=NOTSET) { nvsite++; if (nvsite==1) { /* store construction atoms of first vsite */ vsnral=NRAL(pindex[atom].ftype)-1; for(m=0; (m<vsnral); m++) vsiteatoms[m]= plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1]; if (debug) { fprintf(debug,"dih w. vsite: %u %u %u %u\n", ps->param[i].AI+1,ps->param[i].AJ+1, ps->param[i].AK+1,ps->param[i].AL+1); fprintf(debug,"vsite %u from: %u %u %u\n", atom+1,vsiteatoms[0]+1,vsiteatoms[1]+1,vsiteatoms[2]+1); } } else /* check if this vsite is constructed from the same atoms */ if (vsnral == NRAL(pindex[atom].ftype)-1 ) for(m=0; (m<vsnral) && !bKeep; m++) { bPresent=FALSE; constr= plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1]; for(n=0; (n<vsnral) && !bPresent; n++) if (constr == vsiteatoms[n]) bPresent=TRUE; if (!bPresent) bKeep=TRUE; } } } /* keep all dihedrals with no virtual sites in them */ if (nvsite==0) bKeep=TRUE; /* check if all atoms in dihedral are either virtual sites, or used in construction of virtual sites. If so, keep it, if not throw away: */ for(k=0; (k<4) && !bKeep; k++) { /* for all atoms in the dihedral */ atom = ps->param[i].a[k]; if (vsite_type[atom]==NOTSET) { bUsed=FALSE; for(m=0; (m<vsnral) && !bUsed; m++) if (atom == vsiteatoms[m]) bUsed=TRUE; if (!bUsed) { bKeep=TRUE; if (debug) fprintf(debug,"unused atom in dih: %u\n",atom+1); } } } if ( bKeep ) { memcpy(&(ps->param[kept_i]), &(ps->param[i]),(size_t)sizeof(ps->param[0])); kept_i++; } } if (ps->nr != kept_i) fprintf(stderr,"Removed %4d %15ss with virtual sites, %5d left\n", ps->nr-kept_i, interaction_function[cftype].longname, kept_i); ps->nr=kept_i; }
int set_vsites(gmx_bool bVerbose, t_atoms *atoms, gpp_atomtype_t atype, t_params plist[]) { int i,j,ftype; int nvsite,nrbond,nrang,nridih,nrset; gmx_bool bFirst,bSet,bERROR; at2vsitebond_t *at2vb; t_mybonded *bonds; t_mybonded *angles; t_mybonded *idihs; bFirst = TRUE; bERROR = TRUE; nvsite=0; if (debug) fprintf(debug, "\nCalculating parameters for virtual sites\n"); /* Make a reverse list to avoid ninteractions^2 operations */ at2vb = make_at2vsitebond(atoms->nr,plist); for(ftype=0; (ftype<F_NRE); ftype++) if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN) { nrset=0; nvsite+=plist[ftype].nr; for(i=0; (i<plist[ftype].nr); i++) { /* check if all parameters are set */ bSet=TRUE; for(j=0; j<NRFP(ftype) && bSet; j++) bSet = plist[ftype].param[i].c[j]!=NOTSET; if (debug) { fprintf(debug,"bSet=%s ",bool_names[bSet]); print_param(debug,ftype,i,&plist[ftype].param[i]); } if (!bSet) { if (bVerbose && bFirst) { fprintf(stderr,"Calculating parameters for virtual sites\n"); bFirst=FALSE; } nrbond=nrang=nridih=0; bonds = NULL; angles= NULL; idihs = NULL; nrset++; /* now set the vsite parameters: */ get_bondeds(NRAL(ftype), plist[ftype].param[i].a, at2vb, plist, &nrbond, &bonds, &nrang, &angles, &nridih, &idihs); if (debug) { fprintf(debug, "Found %d bonds, %d angles and %d idihs " "for virtual site %u (%s)\n",nrbond,nrang,nridih, plist[ftype].param[i].AI+1, interaction_function[ftype].longname); print_bad(debug, nrbond, bonds, nrang, angles, nridih, idihs); } /* debug */ switch(ftype) { case F_VSITE3: bERROR = calc_vsite3_param(atype, &(plist[ftype].param[i]), atoms, nrbond, bonds, nrang, angles); break; case F_VSITE3FD: bERROR = calc_vsite3fd_param(&(plist[ftype].param[i]), nrbond, bonds, nrang, angles); break; case F_VSITE3FAD: bERROR = calc_vsite3fad_param(&(plist[ftype].param[i]), nrbond, bonds, nrang, angles); break; case F_VSITE3OUT: bERROR = calc_vsite3out_param(atype, &(plist[ftype].param[i]), atoms, nrbond, bonds, nrang, angles); break; case F_VSITE4FD: bERROR = calc_vsite4fd_param(&(plist[ftype].param[i]), nrbond, bonds, nrang, angles); break; case F_VSITE4FDN: bERROR = calc_vsite4fdn_param(&(plist[ftype].param[i]), nrbond, bonds, nrang, angles); break; default: gmx_fatal(FARGS,"Automatic parameter generation not supported " "for %s atom %d", interaction_function[ftype].longname, plist[ftype].param[i].AI+1); } /* switch */ if (bERROR) gmx_fatal(FARGS,"Automatic parameter generation not supported " "for %s atom %d for this bonding configuration", interaction_function[ftype].longname, plist[ftype].param[i].AI+1); sfree(bonds); sfree(angles); sfree(idihs); } /* if bSet */ } /* for i */ if (debug && plist[ftype].nr) fprintf(stderr,"Calculated parameters for %d out of %d %s atoms\n", nrset,plist[ftype].nr,interaction_function[ftype].longname); } /* if IF_VSITE */ done_at2vsitebond(atoms->nr,at2vb); return nvsite; }
/*! \brief Looks up SETTLE constraints for a range of charge-groups */ static void atoms_to_settles(gmx_domdec_t *dd, const gmx_mtop_t *mtop, const int *cginfo, const int **at2settle_mt, int cg_start, int cg_end, t_ilist *ils_local, ind_req_t *ireq) { gmx_ga2la_t *ga2la; gmx_mtop_atomlookup_t alook; int settle; int nral, sa; int cg, a, a_gl, a_glsa, a_gls[3], a_locs[3]; int mb, molnr, a_mol, offset; const gmx_molblock_t *molb; const t_iatom *ia1; gmx_bool a_home[3]; int nlocal; gmx_bool bAssign; ga2la = dd->ga2la; alook = gmx_mtop_atomlookup_settle_init(mtop); nral = NRAL(F_SETTLE); for (cg = cg_start; cg < cg_end; cg++) { if (GET_CGINFO_SETTLE(cginfo[cg])) { for (a = dd->cgindex[cg]; a < dd->cgindex[cg+1]; a++) { a_gl = dd->gatindex[a]; gmx_mtop_atomnr_to_molblock_ind(alook, a_gl, &mb, &molnr, &a_mol); molb = &mtop->molblock[mb]; settle = at2settle_mt[molb->type][a_mol]; if (settle >= 0) { offset = a_gl - a_mol; ia1 = mtop->moltype[molb->type].ilist[F_SETTLE].iatoms; bAssign = FALSE; nlocal = 0; for (sa = 0; sa < nral; sa++) { a_glsa = offset + ia1[settle*(1+nral)+1+sa]; a_gls[sa] = a_glsa; a_home[sa] = ga2la_get_home(ga2la, a_glsa, &a_locs[sa]); if (a_home[sa]) { if (nlocal == 0 && a_gl == a_glsa) { bAssign = TRUE; } nlocal++; } } if (bAssign) { if (ils_local->nr+1+nral > ils_local->nalloc) { ils_local->nalloc = over_alloc_dd(ils_local->nr+1+nral); srenew(ils_local->iatoms, ils_local->nalloc); } ils_local->iatoms[ils_local->nr++] = ia1[settle*4]; for (sa = 0; sa < nral; sa++) { if (ga2la_get_home(ga2la, a_gls[sa], &a_locs[sa])) { ils_local->iatoms[ils_local->nr++] = a_locs[sa]; } else { ils_local->iatoms[ils_local->nr++] = -a_gls[sa] - 1; /* Add this non-home atom to the list */ if (ireq->n+1 > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+1); srenew(ireq->ind, ireq->nalloc); } ireq->ind[ireq->n++] = a_gls[sa]; /* A check on double atom requests is * not required for settle. */ } } } } } } } gmx_mtop_atomlookup_destroy(alook); }
static void clean_vsite_bonds(t_params *plist, t_pindex pindex[], int cftype, int vsite_type[]) { int ftype,i,j,parnr,k,l,m,n,nvsite,nOut,kept_i,vsnral,vsitetype; int nconverted,nremoved; atom_id atom,oatom,constr,at1,at2; atom_id vsiteatoms[MAXATOMLIST]; gmx_bool bKeep,bRemove,bUsed,bPresent,bThisFD,bThisOUT,bAllFD,bFirstTwo; t_params *ps; if (cftype == F_CONNBONDS) return; ps = &(plist[cftype]); vsnral=0; kept_i=0; nconverted=0; nremoved=0; nOut=0; for(i=0; (i<ps->nr); i++) { /* for all bonds in the plist */ bKeep=FALSE; bRemove=FALSE; bAllFD=TRUE; /* check if all virtual sites are constructed from the same atoms */ nvsite=0; if(debug) fprintf(debug,"constr %u %u:",ps->param[i].AI+1,ps->param[i].AJ+1); for(k=0; (k<2) && !bKeep && !bRemove; k++) { /* for all atoms in the bond */ atom = ps->param[i].a[k]; if (vsite_type[atom]!=NOTSET) { if(debug) { fprintf(debug," d%d[%d: %d %d %d]",k,atom+1, plist[pindex[atom].ftype].param[pindex[atom].parnr].AJ+1, plist[pindex[atom].ftype].param[pindex[atom].parnr].AK+1, plist[pindex[atom].ftype].param[pindex[atom].parnr].AL+1); } nvsite++; bThisFD = ( (pindex[atom].ftype == F_VSITE3FD ) || (pindex[atom].ftype == F_VSITE3FAD) || (pindex[atom].ftype == F_VSITE4FD ) || (pindex[atom].ftype == F_VSITE4FDN ) ); bThisOUT= ( (pindex[atom].ftype == F_VSITE3OUT) && (interaction_function[cftype].flags & IF_CONSTRAINT) ); bAllFD = bAllFD && bThisFD; if (bThisFD || bThisOUT) { if(debug)fprintf(debug," %s",bThisOUT?"out":"fd"); oatom = ps->param[i].a[1-k]; /* the other atom */ if ( vsite_type[oatom]==NOTSET && oatom==plist[pindex[atom].ftype].param[pindex[atom].parnr].AJ ){ /* if the other atom isn't a vsite, and it is AI */ bRemove=TRUE; if (bThisOUT) nOut++; if(debug)fprintf(debug," D-AI"); } } if (!bRemove) { if (nvsite==1) { /* if this is the first vsite we encounter then store construction atoms */ vsnral=NRAL(pindex[atom].ftype)-1; for(m=0; (m<vsnral); m++) vsiteatoms[m]= plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1]; } else { /* if it is not the first then check if this vsite is constructed from the same atoms */ if (vsnral == NRAL(pindex[atom].ftype)-1 ) for(m=0; (m<vsnral) && !bKeep; m++) { bPresent=FALSE; constr= plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1]; for(n=0; (n<vsnral) && !bPresent; n++) if (constr == vsiteatoms[n]) bPresent=TRUE; if (!bPresent) { bKeep=TRUE; if(debug)fprintf(debug," !present"); } } else { bKeep=TRUE; if(debug)fprintf(debug," !same#at"); } } } } } if (bRemove) bKeep=FALSE; else { /* if we have no virtual sites in this bond, keep it */ if (nvsite==0) { if (debug)fprintf(debug," no vsite"); bKeep=TRUE; } /* check if all non-vsite atoms are used in construction: */ bFirstTwo=TRUE; for(k=0; (k<2) && !bKeep; k++) { /* for all atoms in the bond */ atom = ps->param[i].a[k]; if (vsite_type[atom]==NOTSET) { bUsed=FALSE; for(m=0; (m<vsnral) && !bUsed; m++) if (atom == vsiteatoms[m]) { bUsed=TRUE; bFirstTwo = bFirstTwo && m<2; } if (!bUsed) { bKeep=TRUE; if(debug)fprintf(debug," !used"); } } } if ( ! ( bAllFD && bFirstTwo ) ) /* check if all constructing atoms are constrained together */ for (m=0; m<vsnral && !bKeep; m++) { /* all constr. atoms */ at1 = vsiteatoms[m]; at2 = vsiteatoms[(m+1) % vsnral]; bPresent=FALSE; for (ftype=0; ftype<F_NRE; ftype++) if ( interaction_function[ftype].flags & IF_CONSTRAINT ) for (j=0; (j<plist[ftype].nr) && !bPresent; j++) /* all constraints until one matches */ bPresent = ( ( (plist[ftype].param[j].AI == at1) && (plist[ftype].param[j].AJ == at2) ) || ( (plist[ftype].param[j].AI == at2) && (plist[ftype].param[j].AJ == at1) ) ); if (!bPresent) { bKeep=TRUE; if(debug)fprintf(debug," !bonded"); } } } if ( bKeep ) { if(debug)fprintf(debug," keeping"); /* now copy the bond to the new array */ memcpy(&(ps->param[kept_i]), &(ps->param[i]),(size_t)sizeof(ps->param[0])); kept_i++; } else if (IS_CHEMBOND(cftype)) { srenew(plist[F_CONNBONDS].param,plist[F_CONNBONDS].nr+1); memcpy(&(plist[F_CONNBONDS].param[plist[F_CONNBONDS].nr]), &(ps->param[i]),(size_t)sizeof(plist[F_CONNBONDS].param[0])); plist[F_CONNBONDS].nr++; nconverted++; } else nremoved++; if(debug)fprintf(debug,"\n"); } if (nremoved) fprintf(stderr,"Removed %4d %15ss with virtual sites, %5d left\n", nremoved, interaction_function[cftype].longname, kept_i); if (nconverted) fprintf(stderr,"Converted %4d %15ss with virtual sites to connections, %5d left\n", nconverted, interaction_function[cftype].longname, kept_i); if (nOut) fprintf(stderr,"Warning: removed %d %ss with vsite with %s construction\n" " This vsite construction does not guarantee constant " "bond-length\n" " If the constructions were generated by pdb2gmx ignore " "this warning\n", nOut, interaction_function[cftype].longname, interaction_function[F_VSITE3OUT].longname ); ps->nr=kept_i; }
gmx_bool constrain(FILE *fplog, gmx_bool bLog, gmx_bool bEner, struct gmx_constr *constr, t_idef *idef, t_inputrec *ir, gmx_ekindata_t *ekind, t_commrec *cr, gmx_int64_t step, int delta_step, t_mdatoms *md, rvec *x, rvec *xprime, rvec *min_proj, gmx_bool bMolPBC, matrix box, real lambda, real *dvdlambda, rvec *v, tensor *vir, t_nrnb *nrnb, int econq, gmx_bool bPscal, real veta, real vetanew) { gmx_bool bOK, bDump; int start, homenr, nrend; int i, j, d; int ncons, settle_error; tensor vir_r_m_dr; rvec *vstor; real invdt, vir_fac, t; t_ilist *settle; int nsettle; t_pbc pbc, *pbc_null; char buf[22]; t_vetavars vetavar; int nth, th; if (econq == econqForceDispl && !EI_ENERGY_MINIMIZATION(ir->eI)) { gmx_incons("constrain called for forces displacements while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted"); } bOK = TRUE; bDump = FALSE; start = 0; homenr = md->homenr; nrend = start+homenr; /* set constants for pressure control integration */ init_vetavars(&vetavar, econq != econqCoord, veta, vetanew, ir, ekind, bPscal); if (ir->delta_t == 0) { invdt = 0; } else { invdt = 1/ir->delta_t; } if (ir->efep != efepNO && EI_DYNAMICS(ir->eI)) { /* Set the constraint lengths for the step at which this configuration * is meant to be. The invmasses should not be changed. */ lambda += delta_step*ir->fepvals->delta_lambda; } if (vir != NULL) { clear_mat(vir_r_m_dr); } where(); settle = &idef->il[F_SETTLE]; nsettle = settle->nr/(1+NRAL(F_SETTLE)); if (nsettle > 0) { nth = gmx_omp_nthreads_get(emntSETTLE); } else { nth = 1; } if (nth > 1 && constr->vir_r_m_dr_th == NULL) { snew(constr->vir_r_m_dr_th, nth); snew(constr->settle_error, nth); } settle_error = -1; /* We do not need full pbc when constraints do not cross charge groups, * i.e. when dd->constraint_comm==NULL. * Note that PBC for constraints is different from PBC for bondeds. * For constraints there is both forward and backward communication. */ if (ir->ePBC != epbcNONE && (cr->dd || bMolPBC) && !(cr->dd && cr->dd->constraint_comm == NULL)) { /* With pbc=screw the screw has been changed to a shift * by the constraint coordinate communication routine, * so that here we can use normal pbc. */ pbc_null = set_pbc_dd(&pbc, ir->ePBC, cr->dd, FALSE, box); } else { pbc_null = NULL; } /* Communicate the coordinates required for the non-local constraints * for LINCS and/or SETTLE. */ if (cr->dd) { dd_move_x_constraints(cr->dd, box, x, xprime, econq == econqCoord); } if (constr->lincsd != NULL) { bOK = constrain_lincs(fplog, bLog, bEner, ir, step, constr->lincsd, md, cr, x, xprime, min_proj, box, pbc_null, lambda, dvdlambda, invdt, v, vir != NULL, vir_r_m_dr, econq, nrnb, constr->maxwarn, &constr->warncount_lincs); if (!bOK && constr->maxwarn >= 0) { if (fplog != NULL) { fprintf(fplog, "Constraint error in algorithm %s at step %s\n", econstr_names[econtLINCS], gmx_step_str(step, buf)); } bDump = TRUE; } } if (constr->nblocks > 0) { switch (econq) { case (econqCoord): bOK = bshakef(fplog, constr->shaked, md->invmass, constr->nblocks, constr->sblock, idef, ir, x, xprime, nrnb, constr->lagr, lambda, dvdlambda, invdt, v, vir != NULL, vir_r_m_dr, constr->maxwarn >= 0, econq, &vetavar); break; case (econqVeloc): bOK = bshakef(fplog, constr->shaked, md->invmass, constr->nblocks, constr->sblock, idef, ir, x, min_proj, nrnb, constr->lagr, lambda, dvdlambda, invdt, NULL, vir != NULL, vir_r_m_dr, constr->maxwarn >= 0, econq, &vetavar); break; default: gmx_fatal(FARGS, "Internal error, SHAKE called for constraining something else than coordinates"); break; } if (!bOK && constr->maxwarn >= 0) { if (fplog != NULL) { fprintf(fplog, "Constraint error in algorithm %s at step %s\n", econstr_names[econtSHAKE], gmx_step_str(step, buf)); } bDump = TRUE; } } if (nsettle > 0) { int calcvir_atom_end; if (vir == NULL) { calcvir_atom_end = 0; } else { calcvir_atom_end = md->homenr; } switch (econq) { case econqCoord: #pragma omp parallel for num_threads(nth) schedule(static) for (th = 0; th < nth; th++) { int start_th, end_th; if (th > 0) { clear_mat(constr->vir_r_m_dr_th[th]); } start_th = (nsettle* th )/nth; end_th = (nsettle*(th+1))/nth; if (start_th >= 0 && end_th - start_th > 0) { csettle(constr->settled, end_th-start_th, settle->iatoms+start_th*(1+NRAL(F_SETTLE)), pbc_null, x[0], xprime[0], invdt, v ? v[0] : NULL, calcvir_atom_end, th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th], th == 0 ? &settle_error : &constr->settle_error[th], &vetavar); } } inc_nrnb(nrnb, eNR_SETTLE, nsettle); if (v != NULL) { inc_nrnb(nrnb, eNR_CONSTR_V, nsettle*3); } if (vir != NULL) { inc_nrnb(nrnb, eNR_CONSTR_VIR, nsettle*3); } break; case econqVeloc: case econqDeriv: case econqForce: case econqForceDispl: #pragma omp parallel for num_threads(nth) schedule(static) for (th = 0; th < nth; th++) { int start_th, end_th; if (th > 0) { clear_mat(constr->vir_r_m_dr_th[th]); } start_th = (nsettle* th )/nth; end_th = (nsettle*(th+1))/nth; if (start_th >= 0 && end_th - start_th > 0) { settle_proj(constr->settled, econq, end_th-start_th, settle->iatoms+start_th*(1+NRAL(F_SETTLE)), pbc_null, x, xprime, min_proj, calcvir_atom_end, th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th], &vetavar); } } /* This is an overestimate */ inc_nrnb(nrnb, eNR_SETTLE, nsettle); break; case econqDeriv_FlexCon: /* Nothing to do, since the are no flexible constraints in settles */ break; default: gmx_incons("Unknown constraint quantity for settle"); } } if (settle->nr > 0) { /* Combine virial and error info of the other threads */ for (i = 1; i < nth; i++) { m_add(vir_r_m_dr, constr->vir_r_m_dr_th[i], vir_r_m_dr); settle_error = constr->settle_error[i]; } if (econq == econqCoord && settle_error >= 0) { bOK = FALSE; if (constr->maxwarn >= 0) { char buf[256]; sprintf(buf, "\nstep " "%"GMX_PRId64 ": Water molecule starting at atom %d can not be " "settled.\nCheck for bad contacts and/or reduce the timestep if appropriate.\n", step, ddglatnr(cr->dd, settle->iatoms[settle_error*(1+NRAL(F_SETTLE))+1])); if (fplog) { fprintf(fplog, "%s", buf); } fprintf(stderr, "%s", buf); constr->warncount_settle++; if (constr->warncount_settle > constr->maxwarn) { too_many_constraint_warnings(-1, constr->warncount_settle); } bDump = TRUE; } } } free_vetavars(&vetavar); if (vir != NULL) { switch (econq) { case econqCoord: vir_fac = 0.5/(ir->delta_t*ir->delta_t); break; case econqVeloc: vir_fac = 0.5/ir->delta_t; break; case econqForce: case econqForceDispl: vir_fac = 0.5; break; default: vir_fac = 0; gmx_incons("Unsupported constraint quantity for virial"); } if (EI_VV(ir->eI)) { vir_fac *= 2; /* only constraining over half the distance here */ } for (i = 0; i < DIM; i++) { for (j = 0; j < DIM; j++) { (*vir)[i][j] = vir_fac*vir_r_m_dr[i][j]; } } } if (bDump) { dump_confs(fplog, step, constr->warn_mtop, start, homenr, cr, x, xprime, box); } if (econq == econqCoord) { if (ir->ePull == epullCONSTRAINT) { if (EI_DYNAMICS(ir->eI)) { t = ir->init_t + (step + delta_step)*ir->delta_t; } else { t = ir->init_t; } set_pbc(&pbc, ir->ePBC, box); pull_constraint(ir->pull, md, &pbc, cr, ir->delta_t, t, x, xprime, v, *vir); } if (constr->ed && delta_step > 0) { /* apply the essential dynamcs constraints here */ do_edsam(ir, step, cr, xprime, v, box, constr->ed); } } return bOK; }
int dd_make_local_vsites(gmx_domdec_t *dd, int at_start, t_ilist *lil) { gmx_domdec_specat_comm_t *spac; ind_req_t *ireq; gmx_hash_t ga2la_specat; int ftype, nral, i, j, a; t_ilist *lilf; t_iatom *iatoms; int at_end; spac = dd->vsite_comm; ireq = &spac->ireq[0]; ga2la_specat = dd->ga2la_vsite; ireq->n = 0; /* Loop over all the home vsites */ for (ftype = 0; ftype < F_NRE; ftype++) { if (interaction_function[ftype].flags & IF_VSITE) { nral = NRAL(ftype); lilf = &lil[ftype]; for (i = 0; i < lilf->nr; i += 1+nral) { iatoms = lilf->iatoms + i; /* Check if we have the other atoms */ for (j = 1; j < 1+nral; j++) { if (iatoms[j] < 0) { /* This is not a home atom, * we need to ask our neighbors. */ a = -iatoms[j] - 1; /* Check to not ask for the same atom more than once */ if (gmx_hash_get_minone(dd->ga2la_vsite, a) == -1) { /* Add this non-home atom to the list */ if (ireq->n+1 > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+1); srenew(ireq->ind, ireq->nalloc); } ireq->ind[ireq->n++] = a; /* Temporarily mark with -2, * we get the index later. */ gmx_hash_set(ga2la_specat, a, -2); } } } } } } at_end = setup_specat_communication(dd, ireq, dd->vsite_comm, ga2la_specat, at_start, 1, "vsite", ""); /* Fill in the missing indices */ for (ftype = 0; ftype < F_NRE; ftype++) { if (interaction_function[ftype].flags & IF_VSITE) { nral = NRAL(ftype); lilf = &lil[ftype]; for (i = 0; i < lilf->nr; i += 1+nral) { iatoms = lilf->iatoms + i; for (j = 1; j < 1+nral; j++) { if (iatoms[j] < 0) { iatoms[j] = gmx_hash_get_minone(ga2la_specat, -iatoms[j]-1); } } } } } return at_end; }
/*! \brief Looks up constraint for the local atoms */ static void atoms_to_constraints(gmx_domdec_t *dd, const gmx_mtop_t *mtop, const int *cginfo, const t_blocka *at2con_mt, int nrec, t_ilist *ilc_local, ind_req_t *ireq) { const t_blocka *at2con; gmx_ga2la_t *ga2la; gmx_mtop_atomlookup_t alook; int ncon1; gmx_molblock_t *molb; t_iatom *ia1, *ia2, *iap; int nhome, cg, a, a_gl, a_mol, a_loc, b_lo, offset, mb, molnr, b_mol, i, con, con_offset; gmx_domdec_constraints_t *dc; gmx_domdec_specat_comm_t *dcc; dc = dd->constraints; dcc = dd->constraint_comm; ga2la = dd->ga2la; alook = gmx_mtop_atomlookup_init(mtop); nhome = 0; for (cg = 0; cg < dd->ncg_home; cg++) { if (GET_CGINFO_CONSTR(cginfo[cg])) { for (a = dd->cgindex[cg]; a < dd->cgindex[cg+1]; a++) { a_gl = dd->gatindex[a]; gmx_mtop_atomnr_to_molblock_ind(alook, a_gl, &mb, &molnr, &a_mol); molb = &mtop->molblock[mb]; ncon1 = mtop->moltype[molb->type].ilist[F_CONSTR].nr/NRAL(F_SETTLE); ia1 = mtop->moltype[molb->type].ilist[F_CONSTR].iatoms; ia2 = mtop->moltype[molb->type].ilist[F_CONSTRNC].iatoms; /* Calculate the global constraint number offset for the molecule. * This is only required for the global index to make sure * that we use each constraint only once. */ con_offset = dc->molb_con_offset[mb] + molnr*dc->molb_ncon_mol[mb]; /* The global atom number offset for this molecule */ offset = a_gl - a_mol; at2con = &at2con_mt[molb->type]; for (i = at2con->index[a_mol]; i < at2con->index[a_mol+1]; i++) { con = at2con->a[i]; iap = constr_iatomptr(ncon1, ia1, ia2, con); if (a_mol == iap[1]) { b_mol = iap[2]; } else { b_mol = iap[1]; } if (ga2la_get_home(ga2la, offset+b_mol, &a_loc)) { /* Add this fully home constraint at the first atom */ if (a_mol < b_mol) { if (dc->ncon+1 > dc->con_nalloc) { dc->con_nalloc = over_alloc_large(dc->ncon+1); srenew(dc->con_gl, dc->con_nalloc); srenew(dc->con_nlocat, dc->con_nalloc); } dc->con_gl[dc->ncon] = con_offset + con; dc->con_nlocat[dc->ncon] = 2; if (ilc_local->nr + 3 > ilc_local->nalloc) { ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3); srenew(ilc_local->iatoms, ilc_local->nalloc); } b_lo = a_loc; ilc_local->iatoms[ilc_local->nr++] = iap[0]; ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? a : b_lo); ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? b_lo : a ); dc->ncon++; nhome++; } } else { /* We need the nrec constraints coupled to this constraint, * so we need to walk out of the home cell by nrec+1 atoms, * since already atom bg is not locally present. * Therefore we call walk_out with nrec recursions to go * after this first call. */ walk_out(con, con_offset, b_mol, offset, nrec, ncon1, ia1, ia2, at2con, dd->ga2la, TRUE, dc, dcc, ilc_local, ireq); } } } } } gmx_mtop_atomlookup_destroy(alook); if (debug) { fprintf(debug, "Constraints: home %3d border %3d atoms: %3d\n", nhome, dc->ncon-nhome, dd->constraint_comm ? ireq->n : 0); } }
static void get_verlet_buffer_atomtypes(const gmx_mtop_t *mtop, verletbuf_atomtype_t **att_p, int *natt_p, int *n_nonlin_vsite) { verletbuf_atomtype_t *att; int natt; int mb, nmol, ft, i, j, a1, a2, a3, a; const t_atoms *atoms; const t_ilist *il; const t_atom *at; const t_iparams *ip; real *con_m, *vsite_m, cam[5]; att = NULL; natt = 0; if (n_nonlin_vsite != NULL) { *n_nonlin_vsite = 0; } for (mb = 0; mb < mtop->nmolblock; mb++) { nmol = mtop->molblock[mb].nmol; atoms = &mtop->moltype[mtop->molblock[mb].type].atoms; /* Check for constraints, as they affect the kinetic energy */ snew(con_m, atoms->nr); snew(vsite_m, atoms->nr); for (ft = F_CONSTR; ft <= F_CONSTRNC; ft++) { il = &mtop->moltype[mtop->molblock[mb].type].ilist[ft]; for (i = 0; i < il->nr; i += 1+NRAL(ft)) { a1 = il->iatoms[i+1]; a2 = il->iatoms[i+2]; con_m[a1] += atoms->atom[a2].m; con_m[a2] += atoms->atom[a1].m; } } il = &mtop->moltype[mtop->molblock[mb].type].ilist[F_SETTLE]; for (i = 0; i < il->nr; i += 1+NRAL(F_SETTLE)) { a1 = il->iatoms[i+1]; a2 = il->iatoms[i+2]; a3 = il->iatoms[i+3]; con_m[a1] += atoms->atom[a2].m + atoms->atom[a3].m; con_m[a2] += atoms->atom[a1].m + atoms->atom[a3].m; con_m[a3] += atoms->atom[a1].m + atoms->atom[a2].m; } /* Check for virtual sites, determine mass from constructing atoms */ for (ft = 0; ft < F_NRE; ft++) { if (IS_VSITE(ft)) { il = &mtop->moltype[mtop->molblock[mb].type].ilist[ft]; for (i = 0; i < il->nr; i += 1+NRAL(ft)) { ip = &mtop->ffparams.iparams[il->iatoms[i]]; a1 = il->iatoms[i+1]; for (j = 1; j < NRAL(ft); j++) { cam[j] = atoms->atom[il->iatoms[i+1+j]].m; if (cam[j] == 0) { cam[j] = vsite_m[il->iatoms[i+1+j]]; } if (cam[j] == 0) { gmx_fatal(FARGS, "In molecule type '%s' %s construction involves atom %d, which is a virtual site of equal or high complexity. This is not supported.", *mtop->moltype[mtop->molblock[mb].type].name, interaction_function[ft].longname, il->iatoms[i+1+j]+1); } } switch (ft) { case F_VSITE2: /* Exact except for ignoring constraints */ vsite_m[a1] = (cam[2]*sqr(1-ip->vsite.a) + cam[1]*sqr(ip->vsite.a))/(cam[1]*cam[2]); break; case F_VSITE3: /* Exact except for ignoring constraints */ vsite_m[a1] = (cam[2]*cam[3]*sqr(1-ip->vsite.a-ip->vsite.b) + cam[1]*cam[3]*sqr(ip->vsite.a) + cam[1]*cam[2]*sqr(ip->vsite.b))/(cam[1]*cam[2]*cam[3]); break; default: /* Use the mass of the lightest constructing atom. * This is an approximation. * If the distance of the virtual site to the * constructing atom is less than all distances * between constructing atoms, this is a safe * over-estimate of the displacement of the vsite. * This condition holds for all H mass replacement * replacement vsite constructions, except for SP2/3 * groups. In SP3 groups one H will have a F_VSITE3 * construction, so even there the total drift * estimation shouldn't be far off. */ assert(j >= 1); vsite_m[a1] = cam[1]; for (j = 2; j < NRAL(ft); j++) { vsite_m[a1] = min(vsite_m[a1], cam[j]); } if (n_nonlin_vsite != NULL) { *n_nonlin_vsite += nmol; } break; } } } } for (a = 0; a < atoms->nr; a++) { at = &atoms->atom[a]; /* We consider an atom constrained, #DOF=2, when it is * connected with constraints to one or more atoms with * total mass larger than 1.5 that of the atom itself. */ add_at(&att, &natt, at->m, at->type, at->q, con_m[a] > 1.5*at->m, nmol); } sfree(vsite_m); sfree(con_m); } if (gmx_debug_at) { for (a = 0; a < natt; a++) { fprintf(debug, "type %d: m %5.2f t %d q %6.3f con %d n %d\n", a, att[a].mass, att[a].type, att[a].q, att[a].con, att[a].n); } } *att_p = att; *natt_p = natt; }
void convert_params(int atnr, t_params nbtypes[], t_molinfo *mi, t_molinfo *intermolecular_interactions, int comb, double reppow, real fudgeQQ, gmx_mtop_t *mtop) { int i, maxtypes, mt; unsigned long flags; gmx_ffparams_t *ffp; gmx_moltype_t *molt; t_params *plist; maxtypes = 0; ffp = &mtop->ffparams; ffp->ntypes = 0; ffp->atnr = atnr; ffp->functype = NULL; ffp->iparams = NULL; ffp->reppow = reppow; enter_function(&(nbtypes[F_LJ]), (t_functype)F_LJ, comb, reppow, ffp, NULL, &maxtypes, TRUE, TRUE); enter_function(&(nbtypes[F_BHAM]), (t_functype)F_BHAM, comb, reppow, ffp, NULL, &maxtypes, TRUE, TRUE); for (mt = 0; mt < mtop->nmoltype; mt++) { molt = &mtop->moltype[mt]; for (i = 0; (i < F_NRE); i++) { molt->ilist[i].nr = 0; molt->ilist[i].iatoms = NULL; plist = mi[mt].plist; flags = interaction_function[i].flags; if ((i != F_LJ) && (i != F_BHAM) && ((flags & IF_BOND) || (flags & IF_VSITE) || (flags & IF_CONSTRAINT))) { enter_function(&(plist[i]), (t_functype)i, comb, reppow, ffp, &molt->ilist[i], &maxtypes, FALSE, (i == F_POSRES || i == F_FBPOSRES)); } } } mtop->bIntermolecularInteractions = FALSE; if (intermolecular_interactions != NULL) { /* Process the intermolecular interaction list */ snew(mtop->intermolecular_ilist, F_NRE); for (i = 0; (i < F_NRE); i++) { mtop->intermolecular_ilist[i].nr = 0; mtop->intermolecular_ilist[i].iatoms = NULL; plist = intermolecular_interactions->plist; if (plist[i].nr > 0) { flags = interaction_function[i].flags; /* For intermolecular interactions we (currently) * only support potentials. * Constraints and virtual sites would be possible, * but require a lot of extra (bug-prone) code. */ if (!(flags & IF_BOND)) { gmx_fatal(FARGS, "The intermolecular_interaction section may only contain bonded potentials"); } else if (NRAL(i) == 1) /* e.g. position restraints */ { gmx_fatal(FARGS, "Single atom interactions don't make sense in the intermolecular_interaction section, you can put them in the moleculetype section"); } else if (flags & IF_CHEMBOND) { gmx_fatal(FARGS, "The intermolecular_interaction can not contain chemically bonding interactions"); } else { enter_function(&(plist[i]), (t_functype)i, comb, reppow, ffp, &mtop->intermolecular_ilist[i], &maxtypes, FALSE, FALSE); mtop->bIntermolecularInteractions = TRUE; } } } if (!mtop->bIntermolecularInteractions) { sfree(mtop->intermolecular_ilist); } } if (debug) { fprintf(debug, "%s, line %d: There are %d functypes in idef\n", __FILE__, __LINE__, ffp->ntypes); } ffp->fudgeQQ = fudgeQQ; }
int dd_make_local_constraints(gmx_domdec_t *dd, int at_start, const struct gmx_mtop_t *mtop, const int *cginfo, gmx_constr_t constr, int nrec, t_ilist *il_local) { gmx_domdec_constraints_t *dc; t_ilist *ilc_local, *ils_local; ind_req_t *ireq; const t_blocka *at2con_mt; const int **at2settle_mt; gmx_hash_t *ga2la_specat; int at_end, i, j; t_iatom *iap; // This code should not be called unless this condition is true, // because that's the only time init_domdec_constraints is // called... GMX_RELEASE_ASSERT(dd->bInterCGcons || dd->bInterCGsettles, "dd_make_local_constraints called when there are no local constraints"); // ... and init_domdec_constraints always sets // dd->constraint_comm... GMX_RELEASE_ASSERT(dd->constraint_comm, "Invalid use of dd_make_local_constraints before construction of constraint_comm"); // ... which static analysis needs to be reassured about, because // otherwise, when dd->bInterCGsettles is // true. dd->constraint_comm is unilaterally dereferenced before // the call to atoms_to_settles. dc = dd->constraints; ilc_local = &il_local[F_CONSTR]; ils_local = &il_local[F_SETTLE]; dc->ncon = 0; ilc_local->nr = 0; if (dd->constraint_comm) { at2con_mt = atom2constraints_moltype(constr); ireq = &dd->constraint_comm->ireq[0]; ireq->n = 0; } else { // Currently unreachable at2con_mt = NULL; ireq = NULL; } if (dd->bInterCGsettles) { at2settle_mt = atom2settle_moltype(constr); ils_local->nr = 0; } else { /* Settle works inside charge groups, we assigned them already */ at2settle_mt = NULL; } if (at2settle_mt == NULL) { atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec, ilc_local, ireq); } else { int t0_set; int thread; /* Do the constraints, if present, on the first thread. * Do the settles on all other threads. */ t0_set = ((at2con_mt != NULL && dc->nthread > 1) ? 1 : 0); #pragma omp parallel for num_threads(dc->nthread) schedule(static) for (thread = 0; thread < dc->nthread; thread++) { try { if (at2con_mt && thread == 0) { atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec, ilc_local, ireq); } if (thread >= t0_set) { int cg0, cg1; t_ilist *ilst; ind_req_t *ireqt; /* Distribute the settle check+assignments over * dc->nthread or dc->nthread-1 threads. */ cg0 = (dd->ncg_home*(thread-t0_set ))/(dc->nthread-t0_set); cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set); if (thread == t0_set) { ilst = ils_local; } else { ilst = &dc->ils[thread]; } ilst->nr = 0; ireqt = &dd->constraint_comm->ireq[thread]; if (thread > 0) { ireqt->n = 0; } atoms_to_settles(dd, mtop, cginfo, at2settle_mt, cg0, cg1, ilst, ireqt); } } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; } /* Combine the generate settles and requested indices */ for (thread = 1; thread < dc->nthread; thread++) { t_ilist *ilst; ind_req_t *ireqt; int ia; if (thread > t0_set) { ilst = &dc->ils[thread]; if (ils_local->nr + ilst->nr > ils_local->nalloc) { ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr); srenew(ils_local->iatoms, ils_local->nalloc); } for (ia = 0; ia < ilst->nr; ia++) { ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia]; } ils_local->nr += ilst->nr; } ireqt = &dd->constraint_comm->ireq[thread]; if (ireq->n+ireqt->n > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+ireqt->n); srenew(ireq->ind, ireq->nalloc); } for (ia = 0; ia < ireqt->n; ia++) { ireq->ind[ireq->n+ia] = ireqt->ind[ia]; } ireq->n += ireqt->n; } if (debug) { fprintf(debug, "Settles: total %3d\n", ils_local->nr/4); } } if (dd->constraint_comm) { int nral1; at_end = setup_specat_communication(dd, ireq, dd->constraint_comm, dd->constraints->ga2la, at_start, 2, "constraint", " or lincs-order"); /* Fill in the missing indices */ ga2la_specat = dd->constraints->ga2la; nral1 = 1 + NRAL(F_CONSTR); for (i = 0; i < ilc_local->nr; i += nral1) { iap = ilc_local->iatoms + i; for (j = 1; j < nral1; j++) { if (iap[j] < 0) { iap[j] = gmx_hash_get_minone(ga2la_specat, -iap[j]-1); } } } nral1 = 1 + NRAL(F_SETTLE); for (i = 0; i < ils_local->nr; i += nral1) { iap = ils_local->iatoms + i; for (j = 1; j < nral1; j++) { if (iap[j] < 0) { iap[j] = gmx_hash_get_minone(ga2la_specat, -iap[j]-1); } } } } else { // Currently unreachable at_end = at_start; } return at_end; }