static void init_grpstat(FILE *log, gmx_mtop_t *mtop, int ngacc, t_grp_acc gstat[]) { gmx_groups_t *groups; gmx_mtop_atomloop_all_t aloop; int i, grp; t_atom *atom; if (ngacc > 0) { groups = &mtop->groups; aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop, &i, &atom)) { grp = ggrpnr(groups, egcACC, i); if ((grp < 0) && (grp >= ngacc)) { gmx_incons("Input for acceleration groups wrong"); } gstat[grp].nat++; /* This will not work for integrator BD */ gstat[grp].mA += atom->m; gstat[grp].mB += atom->mB; } } }
static void write_hconf_mtop(FILE *out,char *title,gmx_mtop_t *mtop, int pr, rvec *x,rvec *v,matrix box) { char format[100]; int i,resnr; gmx_mtop_atomloop_all_t aloop; t_atom *atom; char *atomname,*resname; bromacs(format,99); fprintf (out,"%s\n",(title && title[0])?title:format); fprintf (out,"%5d\n",mtop->natoms); make_hconf_format(pr,v!=NULL,format); aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) { gmx_mtop_atomloop_all_names(aloop,&atomname,&resnr,&resname); fprintf(out,"%5d%-5.5s%5.5s%5d", (resnr+1)%100000,resname,atomname,(i+1)%100000); /* next fprintf uses built format string */ if (v) fprintf(out,format, x[i][XX], x[i][YY], x[i][ZZ], v[i][XX],v[i][YY],v[i][ZZ]); else fprintf(out,format, x[i][XX], x[i][YY], x[i][ZZ]); } write_hconf_box(out,pr,box); fflush(out); }
t_mdatoms *init_mdatoms(FILE *fp, gmx_mtop_t *mtop, gmx_bool bFreeEnergy) { int mb, a, g, nmol; double tmA, tmB; t_atom *atom; t_mdatoms *md; gmx_mtop_atomloop_all_t aloop; t_ilist *ilist; snew(md, 1); md->nenergrp = mtop->groups.grps[egcENER].nr; md->bVCMgrps = FALSE; tmA = 0.0; tmB = 0.0; aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop, &a, &atom)) { if (ggrpnr(&mtop->groups, egcVCM, a) > 0) { md->bVCMgrps = TRUE; } if (bFreeEnergy && PERTURBED(*atom)) { md->nPerturbed++; if (atom->mB != atom->m) { md->nMassPerturbed++; } if (atom->qB != atom->q) { md->nChargePerturbed++; } if (atom->typeB != atom->type) { md->nTypePerturbed++; } } tmA += atom->m; tmB += atom->mB; } md->tmassA = tmA; md->tmassB = tmB; if (bFreeEnergy && fp) { fprintf(fp, "There are %d atoms and %d charges for free energy perturbation\n", md->nPerturbed, md->nChargePerturbed); } md->bOrires = gmx_mtop_ftype_count(mtop, F_ORIRES); return md; }
static void low_mspeed(real tempi, gmx_mtop_t *mtop, rvec v[], gmx_rng_t rng) { int i, m, nrdf; real boltz, sd; real ekin, temp, mass, scal; gmx_mtop_atomloop_all_t aloop; t_atom *atom; boltz = BOLTZ*tempi; ekin = 0.0; nrdf = 0; aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop, &i, &atom)) { mass = atom->m; if (mass > 0) { sd = sqrt(boltz/mass); for (m = 0; (m < DIM); m++) { v[i][m] = sd*gmx_rng_gaussian_real(rng); ekin += 0.5*mass*v[i][m]*v[i][m]; } nrdf += DIM; } } temp = (2.0*ekin)/(nrdf*BOLTZ); if (temp > 0) { scal = sqrt(tempi/temp); for (i = 0; (i < mtop->natoms); i++) { for (m = 0; (m < DIM); m++) { v[i][m] *= scal; } } } fprintf(stderr, "Velocities were taken from a Maxwell distribution at %g K\n", tempi); if (debug) { fprintf(debug, "Velocities were taken from a Maxwell distribution\n" "Initial generated temperature: %12.5e (scaled to: %12.5e)\n", temp, tempi); } }
static void check_vel(gmx_mtop_t *mtop,rvec v[]) { gmx_mtop_atomloop_all_t aloop; t_atom *atom; int a; aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop,&a,&atom)) { if (atom->ptype == eptShell || atom->ptype == eptBond || atom->ptype == eptVSite) { clear_rvec(v[a]); } } }
/* Allocate and fill an array with coordinates and charges, * returns the number of charges found */ static int prepare_x_q(real *q[], rvec *x[], gmx_mtop_t *mtop, rvec x_orig[], t_commrec *cr) { int i; int nq; /* number of charged particles */ gmx_mtop_atomloop_all_t aloop; t_atom *atom; if (MASTER(cr)) { snew(*q, mtop->natoms); snew(*x, mtop->natoms); nq = 0; aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop, &i, &atom)) { if (is_charge(atom->q)) { (*q)[nq] = atom->q; (*x)[nq][XX] = x_orig[i][XX]; (*x)[nq][YY] = x_orig[i][YY]; (*x)[nq][ZZ] = x_orig[i][ZZ]; nq++; } } /* Give back some unneeded memory */ srenew(*q, nq); srenew(*x, nq); } /* Broadcast x and q in the parallel case */ if (PAR(cr)) { /* Transfer the number of charges */ block_bc(cr, nq); snew_bc(cr, *x, nq); snew_bc(cr, *q, nq); nblock_bc(cr, nq, *x); nblock_bc(cr, nq, *q); } return nq; }
gmx_shellfc_t init_shell_flexcon(FILE *fplog, gmx_bool bCutoffSchemeIsVerlet, gmx_mtop_t *mtop, int nflexcon, rvec *x) { struct gmx_shellfc *shfc; t_shell *shell; int *shell_index = NULL, *at2cg; t_atom *atom; int n[eptNR], ns, nshell, nsi; int i, j, nmol, type, mb, mt, a_offset, cg, mol, ftype, nra; real qS, alpha; int aS, aN = 0; /* Shell and nucleus */ int bondtypes[] = { F_BONDS, F_HARMONIC, F_CUBICBONDS, F_POLARIZATION, F_ANHARM_POL, F_WATER_POL }; #define NBT asize(bondtypes) t_iatom *ia; gmx_mtop_atomloop_block_t aloopb; gmx_mtop_atomloop_all_t aloop; gmx_ffparams_t *ffparams; gmx_molblock_t *molb; gmx_moltype_t *molt; t_block *cgs; /* Count number of shells, and find their indices */ for (i = 0; (i < eptNR); i++) { n[i] = 0; } aloopb = gmx_mtop_atomloop_block_init(mtop); while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol)) { n[atom->ptype] += nmol; } if (fplog) { /* Print the number of each particle type */ for (i = 0; (i < eptNR); i++) { if (n[i] != 0) { fprintf(fplog, "There are: %d %ss\n", n[i], ptype_str[i]); } } } nshell = n[eptShell]; if (nshell == 0 && nflexcon == 0) { /* We're not doing shells or flexible constraints */ return NULL; } if (bCutoffSchemeIsVerlet) { gmx_fatal(FARGS, "The shell code does not work with the Verlet cut-off scheme.\n"); } snew(shfc, 1); shfc->nflexcon = nflexcon; if (nshell == 0) { return shfc; } /* We have shells: fill the shell data structure */ /* Global system sized array, this should be avoided */ snew(shell_index, mtop->natoms); aloop = gmx_mtop_atomloop_all_init(mtop); nshell = 0; while (gmx_mtop_atomloop_all_next(aloop, &i, &atom)) { if (atom->ptype == eptShell) { shell_index[i] = nshell++; } } snew(shell, nshell); /* Initiate the shell structures */ for (i = 0; (i < nshell); i++) { shell[i].shell = NO_ATID; shell[i].nnucl = 0; shell[i].nucl1 = NO_ATID; shell[i].nucl2 = NO_ATID; shell[i].nucl3 = NO_ATID; /* shell[i].bInterCG=FALSE; */ shell[i].k_1 = 0; shell[i].k = 0; } ffparams = &mtop->ffparams; /* Now fill the structures */ shfc->bInterCG = FALSE; ns = 0; a_offset = 0; for (mb = 0; mb < mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; molt = &mtop->moltype[molb->type]; cgs = &molt->cgs; snew(at2cg, molt->atoms.nr); for (cg = 0; cg < cgs->nr; cg++) { for (i = cgs->index[cg]; i < cgs->index[cg+1]; i++) { at2cg[i] = cg; } } atom = molt->atoms.atom; for (mol = 0; mol < molb->nmol; mol++) { for (j = 0; (j < NBT); j++) { ia = molt->ilist[bondtypes[j]].iatoms; for (i = 0; (i < molt->ilist[bondtypes[j]].nr); ) { type = ia[0]; ftype = ffparams->functype[type]; nra = interaction_function[ftype].nratoms; /* Check whether we have a bond with a shell */ aS = NO_ATID; switch (bondtypes[j]) { case F_BONDS: case F_HARMONIC: case F_CUBICBONDS: case F_POLARIZATION: case F_ANHARM_POL: if (atom[ia[1]].ptype == eptShell) { aS = ia[1]; aN = ia[2]; } else if (atom[ia[2]].ptype == eptShell) { aS = ia[2]; aN = ia[1]; } break; case F_WATER_POL: aN = ia[4]; /* Dummy */ aS = ia[5]; /* Shell */ break; default: gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__); } if (aS != NO_ATID) { qS = atom[aS].q; /* Check whether one of the particles is a shell... */ nsi = shell_index[a_offset+aS]; if ((nsi < 0) || (nsi >= nshell)) { gmx_fatal(FARGS, "nsi is %d should be within 0 - %d. aS = %d", nsi, nshell, aS); } if (shell[nsi].shell == NO_ATID) { shell[nsi].shell = a_offset + aS; ns++; } else if (shell[nsi].shell != a_offset+aS) { gmx_fatal(FARGS, "Weird stuff in %s, %d", __FILE__, __LINE__); } if (shell[nsi].nucl1 == NO_ATID) { shell[nsi].nucl1 = a_offset + aN; } else if (shell[nsi].nucl2 == NO_ATID) { shell[nsi].nucl2 = a_offset + aN; } else if (shell[nsi].nucl3 == NO_ATID) { shell[nsi].nucl3 = a_offset + aN; } else { if (fplog) { pr_shell(fplog, ns, shell); } gmx_fatal(FARGS, "Can not handle more than three bonds per shell\n"); } if (at2cg[aS] != at2cg[aN]) { /* shell[nsi].bInterCG = TRUE; */ shfc->bInterCG = TRUE; } switch (bondtypes[j]) { case F_BONDS: case F_HARMONIC: shell[nsi].k += ffparams->iparams[type].harmonic.krA; break; case F_CUBICBONDS: shell[nsi].k += ffparams->iparams[type].cubic.kb; break; case F_POLARIZATION: case F_ANHARM_POL: if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10)) { gmx_fatal(FARGS, "polarize can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1); } shell[nsi].k += sqr(qS)*ONE_4PI_EPS0/ ffparams->iparams[type].polarize.alpha; break; case F_WATER_POL: if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10)) { gmx_fatal(FARGS, "water_pol can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1); } alpha = (ffparams->iparams[type].wpol.al_x+ ffparams->iparams[type].wpol.al_y+ ffparams->iparams[type].wpol.al_z)/3.0; shell[nsi].k += sqr(qS)*ONE_4PI_EPS0/alpha; break; default: gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__); } shell[nsi].nnucl++; } ia += nra+1; i += nra+1; } } a_offset += molt->atoms.nr; } /* Done with this molecule type */ sfree(at2cg); } /* Verify whether it's all correct */ if (ns != nshell) { gmx_fatal(FARGS, "Something weird with shells. They may not be bonded to something"); } for (i = 0; (i < ns); i++) { shell[i].k_1 = 1.0/shell[i].k; } if (debug) { pr_shell(debug, ns, shell); } shfc->nshell_gl = ns; shfc->shell_gl = shell; shfc->shell_index_gl = shell_index; shfc->bPredict = (getenv("GMX_NOPREDICT") == NULL); shfc->bRequireInit = FALSE; if (!shfc->bPredict) { if (fplog) { fprintf(fplog, "\nWill never predict shell positions\n"); } } else { shfc->bRequireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != NULL); if (shfc->bRequireInit && fplog) { fprintf(fplog, "\nWill always initiate shell positions\n"); } } if (shfc->bPredict) { if (x) { predict_shells(fplog, x, NULL, 0, shfc->nshell_gl, shfc->shell_gl, NULL, mtop, TRUE); } if (shfc->bInterCG) { if (fplog) { fprintf(fplog, "\nNOTE: there all shells that are connected to particles outside thier own charge group, will not predict shells positions during the run\n\n"); } shfc->bPredict = FALSE; } } return shfc; }
void init_QMMMrec(t_commrec *cr, matrix box, gmx_mtop_t *mtop, t_inputrec *ir, t_forcerec *fr) { /* we put the atomsnumbers of atoms that belong to the QMMM group in * an array that will be copied later to QMMMrec->indexQM[..]. Also * it will be used to create an QMMMrec->bQMMM index array that * simply contains true/false for QM and MM (the other) atoms. */ gmx_groups_t *groups; atom_id *qm_arr=NULL,vsite,ai,aj; int qm_max=0,qm_nr=0,i,j,jmax,k,l,nrvsite2=0; t_QMMMrec *qr; t_MMrec *mm; t_iatom *iatoms; real c12au,c6au; gmx_mtop_atomloop_all_t aloop; t_atom *atom; gmx_mtop_ilistloop_all_t iloop; int a_offset; t_ilist *ilist_mol; c6au = (HARTREE2KJ*AVOGADRO*pow(BOHR2NM,6)); c12au = (HARTREE2KJ*AVOGADRO*pow(BOHR2NM,12)); fprintf(stderr,"there we go!\n"); /* Make a local copy of the QMMMrec */ qr = fr->qr; /* bQMMM[..] is an array containing TRUE/FALSE for atoms that are * QM/not QM. We first set all elemenst at false. Afterwards we use * the qm_arr (=MMrec->indexQM) to changes the elements * corresponding to the QM atoms at TRUE. */ qr->QMMMscheme = ir->QMMMscheme; /* we take the possibility into account that a user has * defined more than one QM group: */ /* an ugly work-around in case there is only one group In this case * the whole system is treated as QM. Otherwise the second group is * always the rest of the total system and is treated as MM. */ /* small problem if there is only QM.... so no MM */ jmax = ir->opts.ngQM; if(qr->QMMMscheme==eQMMMschemeoniom) qr->nrQMlayers = jmax; else qr->nrQMlayers = 1; groups = &mtop->groups; /* there are jmax groups of QM atoms. In case of multiple QM groups * I assume that the users wants to do ONIOM. However, maybe it * should also be possible to define more than one QM subsystem with * independent neighbourlists. I have to think about * that.. 11-11-2003 */ snew(qr->qm,jmax); for(j=0;j<jmax;j++){ /* new layer */ aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) { if(qm_nr >= qm_max){ qm_max += 1000; srenew(qm_arr,qm_max); } if (ggrpnr(groups,egcQMMM ,i) == j) { /* hack for tip4p */ qm_arr[qm_nr++] = i; } } if(qr->QMMMscheme==eQMMMschemeoniom){ /* add the atoms to the bQMMM array */ /* I assume that users specify the QM groups from small to * big(ger) in the mdp file */ qr->qm[j] = mk_QMrec(); /* we need to throw out link atoms that in the previous layer * existed to separate this QMlayer from the previous * QMlayer. We use the iatoms array in the idef for that * purpose. If all atoms defining the current Link Atom (Dummy2) * are part of the current QM layer it needs to be removed from * qm_arr[]. */ iloop = gmx_mtop_ilistloop_all_init(mtop); while (gmx_mtop_ilistloop_all_next(iloop,&ilist_mol,&a_offset)) { nrvsite2 = ilist_mol[F_VSITE2].nr; iatoms = ilist_mol[F_VSITE2].iatoms; for(k=0; k<nrvsite2; k+=4) { vsite = a_offset + iatoms[k+1]; /* the vsite */ ai = a_offset + iatoms[k+2]; /* constructing atom */ aj = a_offset + iatoms[k+3]; /* constructing atom */ if (ggrpnr(groups, egcQMMM, vsite) == ggrpnr(groups, egcQMMM, ai) && ggrpnr(groups, egcQMMM, vsite) == ggrpnr(groups, egcQMMM, aj)) { /* this dummy link atom needs to be removed from the qm_arr * before making the QMrec of this layer! */ for(i=0;i<qm_nr;i++){ if(qm_arr[i]==vsite){ /* drop the element */ for(l=i;l<qm_nr;l++){ qm_arr[l]=qm_arr[l+1]; } qm_nr--; } } } } } /* store QM atoms in this layer in the QMrec and initialise layer */ init_QMrec(j,qr->qm[j],qm_nr,qm_arr,mtop,ir); /* we now store the LJ C6 and C12 parameters in QM rec in case * we need to do an optimization */ if(qr->qm[j]->bOPT || qr->qm[j]->bTS){ for(i=0;i<qm_nr;i++){ qr->qm[j]->c6[i] = C6(fr->nbfp,mtop->ffparams.atnr, atom->type,atom->type)/c6au; qr->qm[j]->c12[i] = C12(fr->nbfp,mtop->ffparams.atnr, atom->type,atom->type)/c12au; } } /* now we check for frontier QM atoms. These occur in pairs that * construct the vsite */ iloop = gmx_mtop_ilistloop_all_init(mtop); while (gmx_mtop_ilistloop_all_next(iloop,&ilist_mol,&a_offset)) { nrvsite2 = ilist_mol[F_VSITE2].nr; iatoms = ilist_mol[F_VSITE2].iatoms; for(k=0; k<nrvsite2; k+=4){ vsite = a_offset + iatoms[k+1]; /* the vsite */ ai = a_offset + iatoms[k+2]; /* constructing atom */ aj = a_offset + iatoms[k+3]; /* constructing atom */ if(ggrpnr(groups,egcQMMM,ai) < (groups->grps[egcQMMM].nr-1) && (ggrpnr(groups,egcQMMM,aj) >= (groups->grps[egcQMMM].nr-1))){ /* mark ai as frontier atom */ for(i=0;i<qm_nr;i++){ if( (qm_arr[i]==ai) || (qm_arr[i]==vsite) ){ qr->qm[j]->frontatoms[i]=TRUE; } } } else if(ggrpnr(groups,egcQMMM,aj) < (groups->grps[egcQMMM].nr-1) && (ggrpnr(groups,egcQMMM,ai) >= (groups->grps[egcQMMM].nr-1))){ /* mark aj as frontier atom */ for(i=0;i<qm_nr;i++){ if( (qm_arr[i]==aj) || (qm_arr[i]==vsite)){ qr->qm[j]->frontatoms[i]=TRUE; } } } } } } } if(qr->QMMMscheme!=eQMMMschemeoniom){ /* standard QMMM, all layers are merged together so there is one QM * subsystem and one MM subsystem. * Also we set the charges to zero in the md->charge arrays to prevent * the innerloops from doubly counting the electostatic QM MM interaction */ for (k=0;k<qm_nr;k++){ gmx_mtop_atomnr_to_atom(mtop,qm_arr[k],&atom); atom->q = 0.0; atom->qB = 0.0; } qr->qm[0] = mk_QMrec(); /* store QM atoms in the QMrec and initialise */ init_QMrec(0,qr->qm[0],qm_nr,qm_arr,mtop,ir); if(qr->qm[0]->bOPT || qr->qm[0]->bTS){ for(i=0;i<qm_nr;i++){ gmx_mtop_atomnr_to_atom(mtop,qm_arr[i],&atom); qr->qm[0]->c6[i] = C6(fr->nbfp,mtop->ffparams.atnr, atom->type,atom->type)/c6au; qr->qm[0]->c12[i] = C12(fr->nbfp,mtop->ffparams.atnr, atom->type,atom->type)/c12au; } } /* find frontier atoms and mark them true in the frontieratoms array. */ for(i=0;i<qm_nr;i++) { gmx_mtop_atomnr_to_ilist(mtop,qm_arr[i],&ilist_mol,&a_offset); nrvsite2 = ilist_mol[F_VSITE2].nr; iatoms = ilist_mol[F_VSITE2].iatoms; for(k=0;k<nrvsite2;k+=4){ vsite = a_offset + iatoms[k+1]; /* the vsite */ ai = a_offset + iatoms[k+2]; /* constructing atom */ aj = a_offset + iatoms[k+3]; /* constructing atom */ if(ggrpnr(groups,egcQMMM,ai) < (groups->grps[egcQMMM].nr-1) && (ggrpnr(groups,egcQMMM,aj) >= (groups->grps[egcQMMM].nr-1))){ /* mark ai as frontier atom */ if ( (qm_arr[i]==ai) || (qm_arr[i]==vsite) ){ qr->qm[0]->frontatoms[i]=TRUE; } } else if (ggrpnr(groups,egcQMMM,aj) < (groups->grps[egcQMMM].nr-1) && (ggrpnr(groups,egcQMMM,ai) >=(groups->grps[egcQMMM].nr-1))) { /* mark aj as frontier atom */ if ( (qm_arr[i]==aj) || (qm_arr[i]==vsite) ){ qr->qm[0]->frontatoms[i]=TRUE; } } } } /* MM rec creation */ mm = mk_MMrec(); mm->scalefactor = ir->scalefactor; mm->nrMMatoms = (mtop->natoms)-(qr->qm[0]->nrQMatoms); /* rest of the atoms */ qr->mm = mm; } else {/* ONIOM */ /* MM rec creation */ mm = mk_MMrec(); mm->scalefactor = ir->scalefactor; mm->nrMMatoms = 0; qr->mm = mm; } /* these variables get updated in the update QMMMrec */ if(qr->nrQMlayers==1){ /* with only one layer there is only one initialisation * needed. Multilayer is a bit more complicated as it requires * re-initialisation at every step of the simulation. This is due * to the use of COMMON blocks in the fortran QM subroutines. */ if (qr->qm[0]->QMmethod<eQMmethodRHF) { #ifdef GMX_QMMM_MOPAC /* semi-empiprical 1-layer ONIOM calculation requested (mopac93) */ init_mopac(cr,qr->qm[0],qr->mm); #else gmx_fatal(FARGS,"Semi-empirical QM only supported with Mopac."); #endif } else { /* ab initio calculation requested (gamess/gaussian/ORCA) */ #ifdef GMX_QMMM_GAMESS init_gamess(cr,qr->qm[0],qr->mm); #elif defined GMX_QMMM_GAUSSIAN init_gaussian(cr,qr->qm[0],qr->mm); #elif defined GMX_QMMM_ORCA init_orca(cr,qr->qm[0],qr->mm); #else gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA."); #endif } } } /* init_QMMMrec */
void init_orires(FILE *fplog,const gmx_mtop_t *mtop, rvec xref[], const t_inputrec *ir, const gmx_multisim_t *ms,t_oriresdata *od, t_state *state) { int i,j,d,ex,nmol,nr,*nr_ex; double mtot; rvec com; gmx_mtop_ilistloop_t iloop; t_ilist *il; gmx_mtop_atomloop_all_t aloop; t_atom *atom; od->fc = ir->orires_fc; od->nex = 0; od->S = NULL; od->nr = gmx_mtop_ftype_count(mtop,F_ORIRES); if (od->nr == 0) { return; } nr_ex = NULL; iloop = gmx_mtop_ilistloop_init(mtop); while (gmx_mtop_ilistloop_next(iloop,&il,&nmol)) { for(i=0; i<il[F_ORIRES].nr; i+=3) { ex = mtop->ffparams.iparams[il[F_ORIRES].iatoms[i]].orires.ex; if (ex >= od->nex) { srenew(nr_ex,ex+1); for(j=od->nex; j<ex+1; j++) { nr_ex[j] = 0; } od->nex = ex+1; } nr_ex[ex]++; } } snew(od->S,od->nex); /* When not doing time averaging, the instaneous and time averaged data * are indentical and the pointers can point to the same memory. */ snew(od->Dinsl,od->nr); if (ms) { snew(od->Dins,od->nr); } else { od->Dins = od->Dinsl; } if (ir->orires_tau == 0) { od->Dtav = od->Dins; od->edt = 0.0; od->edt1 = 1.0; } else { snew(od->Dtav,od->nr); od->edt = exp(-ir->delta_t/ir->orires_tau); od->edt1 = 1.0 - od->edt; /* Extend the state with the orires history */ state->flags |= (1<<estORIRE_INITF); state->hist.orire_initf = 1; state->flags |= (1<<estORIRE_DTAV); state->hist.norire_Dtav = od->nr*5; snew(state->hist.orire_Dtav,state->hist.norire_Dtav); } snew(od->oinsl,od->nr); if (ms) { snew(od->oins,od->nr); } else { od->oins = od->oinsl; } if (ir->orires_tau == 0) { od->otav = od->oins; } else { snew(od->otav,od->nr); } snew(od->tmp,od->nex); snew(od->TMP,od->nex); for(ex=0; ex<od->nex; ex++) { snew(od->TMP[ex],5); for(i=0; i<5; i++) { snew(od->TMP[ex][i],5); } } od->nref = 0; for(i=0; i<mtop->natoms; i++) { if (ggrpnr(&mtop->groups,egcORFIT,i) == 0) { od->nref++; } } snew(od->mref,od->nref); snew(od->xref,od->nref); snew(od->xtmp,od->nref); snew(od->eig,od->nex*12); /* Determine the reference structure on the master node. * Copy it to the other nodes after checking multi compatibility, * so we are sure the subsystems match before copying. */ clear_rvec(com); mtot = 0.0; j = 0; aloop = gmx_mtop_atomloop_all_init(mtop); while(gmx_mtop_atomloop_all_next(aloop,&i,&atom)) { if (mtop->groups.grpnr[egcORFIT] == NULL || mtop->groups.grpnr[egcORFIT][i] == 0) { /* Not correct for free-energy with changing masses */ od->mref[j] = atom->m; if (ms==NULL || MASTERSIM(ms)) { copy_rvec(xref[i],od->xref[j]); for(d=0; d<DIM; d++) { com[d] += od->mref[j]*xref[i][d]; } } mtot += od->mref[j]; j++; } } svmul(1.0/mtot,com,com); if (ms==NULL || MASTERSIM(ms)) { for(j=0; j<od->nref; j++) { rvec_dec(od->xref[j],com); } } fprintf(fplog,"Found %d orientation experiments\n",od->nex); for(i=0; i<od->nex; i++) { fprintf(fplog," experiment %d has %d restraints\n",i+1,nr_ex[i]); } sfree(nr_ex); fprintf(fplog," the fit group consists of %d atoms and has total mass %g\n", od->nref,mtot); if (ms) { fprintf(fplog," the orientation restraints are ensemble averaged over %d systems\n",ms->nsim); check_multi_int(fplog,ms,od->nr, "the number of orientation restraints"); check_multi_int(fplog,ms,od->nref, "the number of fit atoms for orientation restraining"); check_multi_int(fplog,ms,ir->nsteps,"nsteps"); /* Copy the reference coordinates from the master to the other nodes */ gmx_sum_sim(DIM*od->nref,od->xref[0],ms); } please_cite(fplog,"Hess2003"); }
static void gen_local_top(const gmx_mtop_t *mtop,const t_inputrec *ir, gmx_bool bMergeConstr, gmx_localtop_t *top) { int mb,srcnr,destnr,ftype,ftype_dest,mt,natoms,mol,nposre_old; gmx_molblock_t *molb; gmx_moltype_t *molt; const gmx_ffparams_t *ffp; t_idef *idef; real *qA,*qB; gmx_mtop_atomloop_all_t aloop; int ag; t_atom *atom; top->atomtypes = mtop->atomtypes; ffp = &mtop->ffparams; idef = &top->idef; idef->ntypes = ffp->ntypes; idef->atnr = ffp->atnr; idef->functype = ffp->functype; idef->iparams = ffp->iparams; idef->iparams_posres = NULL; idef->iparams_posres_nalloc = 0; idef->fudgeQQ = ffp->fudgeQQ; idef->cmap_grid = ffp->cmap_grid; idef->ilsort = ilsortUNKNOWN; init_block(&top->cgs); init_blocka(&top->excls); for(ftype=0; ftype<F_NRE; ftype++) { idef->il[ftype].nr = 0; idef->il[ftype].nalloc = 0; idef->il[ftype].iatoms = NULL; } natoms = 0; for(mb=0; mb<mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; molt = &mtop->moltype[molb->type]; srcnr = molt->atoms.nr; destnr = natoms; blockcat(&top->cgs,&molt->cgs,molb->nmol,destnr,srcnr); blockacat(&top->excls,&molt->excls,molb->nmol,destnr,srcnr); nposre_old = idef->il[F_POSRES].nr; for(ftype=0; ftype<F_NRE; ftype++) { if (bMergeConstr && ftype == F_CONSTR && molt->ilist[F_CONSTRNC].nr > 0) { /* Merge all constrains into one ilist. * This simplifies the constraint code. */ for(mol=0; mol<molb->nmol; mol++) { ilistcat(ftype,&idef->il[F_CONSTR],&molt->ilist[F_CONSTR], 1,destnr+mol*srcnr,srcnr); ilistcat(ftype,&idef->il[F_CONSTR],&molt->ilist[F_CONSTRNC], 1,destnr+mol*srcnr,srcnr); } } else if (!(bMergeConstr && ftype == F_CONSTRNC)) { ilistcat(ftype,&idef->il[ftype],&molt->ilist[ftype], molb->nmol,destnr,srcnr); } } if (idef->il[F_POSRES].nr > nposre_old) { set_posres_params(idef,molb,nposre_old/2,natoms); } natoms += molb->nmol*srcnr; } if (ir == NULL) { top->idef.ilsort = ilsortUNKNOWN; } else { if (ir->efep != efepNO && gmx_mtop_bondeds_free_energy(mtop)) { snew(qA,mtop->natoms); snew(qB,mtop->natoms); aloop = gmx_mtop_atomloop_all_init(mtop); while (gmx_mtop_atomloop_all_next(aloop,&ag,&atom)) { qA[ag] = atom->q; qB[ag] = atom->qB; } gmx_sort_ilist_fe(&top->idef,qA,qB); sfree(qA); sfree(qB); } else { top->idef.ilsort = ilsortNO_FE; } } }
static void new_status(char *topfile,char *topppfile,char *confin, t_gromppopts *opts,t_inputrec *ir,bool bZero, bool bGenVel,bool bVerbose,t_state *state, gpp_atomtype_t atype,gmx_mtop_t *sys, int *nmi,t_molinfo **mi,t_params plist[], int *comb,double *reppow,real *fudgeQQ, bool bMorse, int *nerror) { t_molinfo *molinfo=NULL; int nmolblock; gmx_molblock_t *molblock,*molbs; t_atoms *confat; int mb,mbs,i,nrmols,nmismatch; char buf[STRLEN]; bool bGB=FALSE; init_mtop(sys); /* Set boolean for GB */ if(ir->implicit_solvent) bGB=TRUE; /* TOPOLOGY processing */ sys->name = do_top(bVerbose,topfile,topppfile,opts,bZero,&(sys->symtab), plist,comb,reppow,fudgeQQ, atype,&nrmols,&molinfo,ir, &nmolblock,&molblock,bGB); sys->nmolblock = 0; snew(sys->molblock,nmolblock); mbs; sys->natoms = 0; for(mb=0; mb<nmolblock; mb++) { if (sys->nmolblock > 0 && molblock[mb].type == sys->molblock[sys->nmolblock-1].type) { /* Merge consecutive blocks with the same molecule type */ sys->molblock[sys->nmolblock-1].nmol += molblock[mb].nmol; sys->natoms += molblock[mb].nmol*sys->molblock[sys->nmolblock-1].natoms_mol; } else if (molblock[mb].nmol > 0) { /* Add a new molblock to the topology */ molbs = &sys->molblock[sys->nmolblock]; *molbs = molblock[mb]; molbs->natoms_mol = molinfo[molbs->type].atoms.nr; molbs->nposres_xA = 0; molbs->nposres_xB = 0; sys->natoms += molbs->nmol*molbs->natoms_mol; sys->nmolblock++; } } if (sys->nmolblock == 0) { gmx_fatal(FARGS,"No molecules were defined in the system"); } renumber_moltypes(sys,&nrmols,&molinfo); if (bMorse) convert_harmonics(nrmols,molinfo,atype); if (ir->eDisre == edrNone) { i = rm_interactions(F_DISRES,nrmols,molinfo); if (i > 0) { set_warning_line("unknown",-1); sprintf(warn_buf,"disre = no, removed %d distance restraints",i); warning_note(NULL); } } if (opts->bOrire == FALSE) { i = rm_interactions(F_ORIRES,nrmols,molinfo); if (i > 0) { set_warning_line("unknown",-1); sprintf(warn_buf,"orire = no, removed %d orientation restraints",i); warning_note(NULL); } } if (opts->bDihre == FALSE) { i = rm_interactions(F_DIHRES,nrmols,molinfo); if (i > 0) { set_warning_line("unknown",-1); sprintf(warn_buf,"dihre = no, removed %d dihedral restraints",i); warning_note(NULL); } } /* Copy structures from msys to sys */ molinfo2mtop(nrmols,molinfo,sys); /* COORDINATE file processing */ if (bVerbose) fprintf(stderr,"processing coordinates...\n"); get_stx_coordnum(confin,&state->natoms); if (state->natoms != sys->natoms) gmx_fatal(FARGS,"number of coordinates in coordinate file (%s, %d)\n" " does not match topology (%s, %d)", confin,state->natoms,topfile,sys->natoms); else { /* make space for coordinates and velocities */ char title[STRLEN]; snew(confat,1); init_t_atoms(confat,state->natoms,FALSE); init_state(state,state->natoms,0); read_stx_conf(confin,title,confat,state->x,state->v,NULL,state->box); /* This call fixes the box shape for runs with pressure scaling */ set_box_rel(ir,state); nmismatch = check_atom_names(topfile, confin, sys, confat); free_t_atoms(confat,TRUE); sfree(confat); if (nmismatch) { sprintf(buf,"%d non-matching atom name%s\n" "atom names from %s will be used\n" "atom names from %s will be ignored\n", nmismatch,(nmismatch == 1) ? "" : "s",topfile,confin); warning(buf); } if (bVerbose) fprintf(stderr,"double-checking input for internal consistency...\n"); double_check(ir,state->box,nint_ftype(sys,molinfo,F_CONSTR),nerror); } if (bGenVel) { real *mass; gmx_mtop_atomloop_all_t aloop; t_atom *atom; snew(mass,state->natoms); aloop = gmx_mtop_atomloop_all_init(sys); while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) { mass[i] = atom->m; } if (opts->seed == -1) { opts->seed = make_seed(); fprintf(stderr,"Setting gen_seed to %d\n",opts->seed); } maxwell_speed(opts->tempi,opts->seed,sys,state->v); stop_cm(stdout,state->natoms,mass,state->x,state->v); sfree(mass); } *nmi = nrmols; *mi = molinfo; }
gmx_shellfc_t *init_shell_flexcon(FILE *fplog, gmx_mtop_t *mtop, int nflexcon, int nstcalcenergy, bool usingDomainDecomposition) { gmx_shellfc_t *shfc; t_shell *shell; int *shell_index = NULL, *at2cg; t_atom *atom; int ns, nshell, nsi; int i, j, type, mb, a_offset, cg, mol, ftype, nra; real qS, alpha; int aS, aN = 0; /* Shell and nucleus */ int bondtypes[] = { F_BONDS, F_HARMONIC, F_CUBICBONDS, F_POLARIZATION, F_ANHARM_POL, F_WATER_POL }; #define NBT asize(bondtypes) t_iatom *ia; gmx_mtop_atomloop_all_t aloop; gmx_ffparams_t *ffparams; gmx_molblock_t *molb; gmx_moltype_t *molt; t_block *cgs; std::array<int, eptNR> n = countPtypes(fplog, mtop); nshell = n[eptShell]; if (nshell == 0 && nflexcon == 0) { /* We're not doing shells or flexible constraints */ return NULL; } snew(shfc, 1); shfc->nflexcon = nflexcon; if (nshell == 0) { /* Only flexible constraints, no shells. * Note that make_local_shells() does not need to be called. */ shfc->nshell = 0; shfc->bPredict = FALSE; return shfc; } if (nstcalcenergy != 1) { gmx_fatal(FARGS, "You have nstcalcenergy set to a value (%d) that is different from 1.\nThis is not supported in combination with shell particles.\nPlease make a new tpr file.", nstcalcenergy); } if (usingDomainDecomposition) { gmx_fatal(FARGS, "Shell particles are not implemented with domain decomposition, use a single rank"); } /* We have shells: fill the shell data structure */ /* Global system sized array, this should be avoided */ snew(shell_index, mtop->natoms); aloop = gmx_mtop_atomloop_all_init(mtop); nshell = 0; while (gmx_mtop_atomloop_all_next(aloop, &i, &atom)) { if (atom->ptype == eptShell) { shell_index[i] = nshell++; } } snew(shell, nshell); /* Initiate the shell structures */ for (i = 0; (i < nshell); i++) { shell[i].shell = -1; shell[i].nnucl = 0; shell[i].nucl1 = -1; shell[i].nucl2 = -1; shell[i].nucl3 = -1; /* shell[i].bInterCG=FALSE; */ shell[i].k_1 = 0; shell[i].k = 0; } ffparams = &mtop->ffparams; /* Now fill the structures */ shfc->bInterCG = FALSE; ns = 0; a_offset = 0; for (mb = 0; mb < mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; molt = &mtop->moltype[molb->type]; cgs = &molt->cgs; snew(at2cg, molt->atoms.nr); for (cg = 0; cg < cgs->nr; cg++) { for (i = cgs->index[cg]; i < cgs->index[cg+1]; i++) { at2cg[i] = cg; } } atom = molt->atoms.atom; for (mol = 0; mol < molb->nmol; mol++) { for (j = 0; (j < NBT); j++) { ia = molt->ilist[bondtypes[j]].iatoms; for (i = 0; (i < molt->ilist[bondtypes[j]].nr); ) { type = ia[0]; ftype = ffparams->functype[type]; nra = interaction_function[ftype].nratoms; /* Check whether we have a bond with a shell */ aS = -1; switch (bondtypes[j]) { case F_BONDS: case F_HARMONIC: case F_CUBICBONDS: case F_POLARIZATION: case F_ANHARM_POL: if (atom[ia[1]].ptype == eptShell) { aS = ia[1]; aN = ia[2]; } else if (atom[ia[2]].ptype == eptShell) { aS = ia[2]; aN = ia[1]; } break; case F_WATER_POL: aN = ia[4]; /* Dummy */ aS = ia[5]; /* Shell */ break; default: gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__); } if (aS != -1) { qS = atom[aS].q; /* Check whether one of the particles is a shell... */ nsi = shell_index[a_offset+aS]; if ((nsi < 0) || (nsi >= nshell)) { gmx_fatal(FARGS, "nsi is %d should be within 0 - %d. aS = %d", nsi, nshell, aS); } if (shell[nsi].shell == -1) { shell[nsi].shell = a_offset + aS; ns++; } else if (shell[nsi].shell != a_offset+aS) { gmx_fatal(FARGS, "Weird stuff in %s, %d", __FILE__, __LINE__); } if (shell[nsi].nucl1 == -1) { shell[nsi].nucl1 = a_offset + aN; } else if (shell[nsi].nucl2 == -1) { shell[nsi].nucl2 = a_offset + aN; } else if (shell[nsi].nucl3 == -1) { shell[nsi].nucl3 = a_offset + aN; } else { if (fplog) { pr_shell(fplog, ns, shell); } gmx_fatal(FARGS, "Can not handle more than three bonds per shell\n"); } if (at2cg[aS] != at2cg[aN]) { /* shell[nsi].bInterCG = TRUE; */ shfc->bInterCG = TRUE; } switch (bondtypes[j]) { case F_BONDS: case F_HARMONIC: shell[nsi].k += ffparams->iparams[type].harmonic.krA; break; case F_CUBICBONDS: shell[nsi].k += ffparams->iparams[type].cubic.kb; break; case F_POLARIZATION: case F_ANHARM_POL: if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10)) { gmx_fatal(FARGS, "polarize can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1); } shell[nsi].k += gmx::square(qS)*ONE_4PI_EPS0/ ffparams->iparams[type].polarize.alpha; break; case F_WATER_POL: if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10)) { gmx_fatal(FARGS, "water_pol can not be used with qA(%e) != qB(%e) for atom %d of molecule block %d", qS, atom[aS].qB, aS+1, mb+1); } alpha = (ffparams->iparams[type].wpol.al_x+ ffparams->iparams[type].wpol.al_y+ ffparams->iparams[type].wpol.al_z)/3.0; shell[nsi].k += gmx::square(qS)*ONE_4PI_EPS0/alpha; break; default: gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__); } shell[nsi].nnucl++; } ia += nra+1; i += nra+1; } } a_offset += molt->atoms.nr; } /* Done with this molecule type */ sfree(at2cg); } /* Verify whether it's all correct */ if (ns != nshell) { gmx_fatal(FARGS, "Something weird with shells. They may not be bonded to something"); } for (i = 0; (i < ns); i++) { shell[i].k_1 = 1.0/shell[i].k; } if (debug) { pr_shell(debug, ns, shell); } shfc->nshell_gl = ns; shfc->shell_gl = shell; shfc->shell_index_gl = shell_index; shfc->bPredict = (getenv("GMX_NOPREDICT") == NULL); shfc->bRequireInit = FALSE; if (!shfc->bPredict) { if (fplog) { fprintf(fplog, "\nWill never predict shell positions\n"); } } else { shfc->bRequireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != NULL); if (shfc->bRequireInit && fplog) { fprintf(fplog, "\nWill always initiate shell positions\n"); } } if (shfc->bPredict) { if (shfc->bInterCG) { if (fplog) { fprintf(fplog, "\nNOTE: there all shells that are connected to particles outside thier own charge group, will not predict shells positions during the run\n\n"); } /* Prediction improves performance, so we should implement either: * 1. communication for the atoms needed for prediction * 2. prediction using the velocities of shells; currently the * shell velocities are zeroed, it's a bit tricky to keep * track of the shell displacements and thus the velocity. */ shfc->bPredict = FALSE; } } return shfc; }