void check_ir_old_tpx_versions(t_commrec *cr, FILE *fplog, t_inputrec *ir, gmx_mtop_t *mtop) { /* Check required for old tpx files */ if (IR_TWINRANGE(*ir) && ir->nstlist > 1 && ir->nstcalcenergy % ir->nstlist != 0) { md_print_warn(cr, fplog, "Old tpr file with twin-range settings: modifying energy calculation and/or T/P-coupling frequencies\n"); if (gmx_mtop_ftype_count(mtop, F_CONSTR) + gmx_mtop_ftype_count(mtop, F_CONSTRNC) > 0 && ir->eConstrAlg == econtSHAKE) { md_print_warn(cr, fplog, "With twin-range cut-off's and SHAKE the virial and pressure are incorrect\n"); if (ir->epc != epcNO) { gmx_fatal(FARGS, "Can not do pressure coupling with twin-range cut-off's and SHAKE"); } } check_nst_param(fplog, cr, "nstlist", ir->nstlist, "nstcalcenergy", &ir->nstcalcenergy); if (ir->epc != epcNO) { check_nst_param(fplog, cr, "nstlist", ir->nstlist, "nstpcouple", &ir->nstpcouple); } check_nst_param(fplog, cr, "nstcalcenergy", ir->nstcalcenergy, "nstenergy", &ir->nstenergy); check_nst_param(fplog, cr, "nstcalcenergy", ir->nstcalcenergy, "nstlog", &ir->nstlog); if (ir->efep != efepNO) { check_nst_param(fplog, cr, "nstcalcenergy", ir->nstcalcenergy, "nstdhdl", &ir->fepvals->nstdhdl); } } if (EI_VV(ir->eI) && IR_TWINRANGE(*ir) && ir->nstlist > 1) { gmx_fatal(FARGS, "Twin-range multiple time stepping does not work with integrator %s.", ei_names[ir->eI]); } }
void global_stat(gmx_global_stat_t gs, t_commrec *cr, gmx_enerdata_t *enerd, tensor fvir, tensor svir, rvec mu_tot, t_inputrec *inputrec, gmx_ekindata_t *ekind, gmx_constr_t constr, t_vcm *vcm, int nsig, real *sig, int *totalNumberOfBondedInteractions, gmx_bool bSumEkinhOld, int flags) /* instead of current system, gmx_booleans for summing virial, kinetic energy, and other terms */ { t_bin *rb; int *itc0, *itc1; int ie = 0, ifv = 0, isv = 0, irmsd = 0, imu = 0; int idedl = 0, idvdll = 0, idvdlnl = 0, iepl = 0, icm = 0, imass = 0, ica = 0, inb = 0; int isig = -1; int icj = -1, ici = -1, icx = -1; int inn[egNR]; real copyenerd[F_NRE]; int nener, j; real *rmsd_data = NULL; double nb; gmx_bool bVV, bTemp, bEner, bPres, bConstrVir, bEkinAveVel, bReadEkin; bool checkNumberOfBondedInteractions = flags & CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS; bVV = EI_VV(inputrec->eI); bTemp = flags & CGLO_TEMPERATURE; bEner = flags & CGLO_ENERGY; bPres = (flags & CGLO_PRESSURE); bConstrVir = (flags & CGLO_CONSTRAINT); bEkinAveVel = (inputrec->eI == eiVV || (inputrec->eI == eiVVAK && bPres)); bReadEkin = (flags & CGLO_READEKIN); rb = gs->rb; itc0 = gs->itc0; itc1 = gs->itc1; reset_bin(rb); /* This routine copies all the data to be summed to one big buffer * using the t_bin struct. */ /* First, we neeed to identify which enerd->term should be communicated. Temperature and pressure terms should only be communicated and summed when they need to be, to avoid repeating the sums and overcounting. */ nener = filter_enerdterm(enerd->term, TRUE, copyenerd, bTemp, bPres, bEner); /* First, the data that needs to be communicated with velocity verlet every time This is just the constraint virial.*/ if (bConstrVir) { isv = add_binr(rb, DIM*DIM, svir[0]); where(); } /* We need the force virial and the kinetic energy for the first time through with velocity verlet */ if (bTemp || !bVV) { if (ekind) { for (j = 0; (j < inputrec->opts.ngtc); j++) { if (bSumEkinhOld) { itc0[j] = add_binr(rb, DIM*DIM, ekind->tcstat[j].ekinh_old[0]); } if (bEkinAveVel && !bReadEkin) { itc1[j] = add_binr(rb, DIM*DIM, ekind->tcstat[j].ekinf[0]); } else if (!bReadEkin) { itc1[j] = add_binr(rb, DIM*DIM, ekind->tcstat[j].ekinh[0]); } } /* these probably need to be put into one of these categories */ where(); idedl = add_binr(rb, 1, &(ekind->dekindl)); where(); ica = add_binr(rb, 1, &(ekind->cosacc.mvcos)); where(); } } where(); if (bPres) { ifv = add_binr(rb, DIM*DIM, fvir[0]); } if (bEner) { where(); ie = add_binr(rb, nener, copyenerd); where(); if (constr) { rmsd_data = constr_rmsd_data(constr); if (rmsd_data) { irmsd = add_binr(rb, 2, rmsd_data); } } if (!inputrecNeedMutot(inputrec)) { imu = add_binr(rb, DIM, mu_tot); where(); } for (j = 0; (j < egNR); j++) { inn[j] = add_binr(rb, enerd->grpp.nener, enerd->grpp.ener[j]); } where(); if (inputrec->efep != efepNO) { idvdll = add_bind(rb, efptNR, enerd->dvdl_lin); idvdlnl = add_bind(rb, efptNR, enerd->dvdl_nonlin); if (enerd->n_lambda > 0) { iepl = add_bind(rb, enerd->n_lambda, enerd->enerpart_lambda); } } } if (vcm) { icm = add_binr(rb, DIM*vcm->nr, vcm->group_p[0]); where(); imass = add_binr(rb, vcm->nr, vcm->group_mass); where(); if (vcm->mode == ecmANGULAR) { icj = add_binr(rb, DIM*vcm->nr, vcm->group_j[0]); where(); icx = add_binr(rb, DIM*vcm->nr, vcm->group_x[0]); where(); ici = add_binr(rb, DIM*DIM*vcm->nr, vcm->group_i[0][0]); where(); } } if (checkNumberOfBondedInteractions) { nb = cr->dd->nbonded_local; inb = add_bind(rb, 1, &nb); } where(); if (nsig > 0) { isig = add_binr(rb, nsig, sig); } /* Global sum it all */ if (debug) { fprintf(debug, "Summing %d energies\n", rb->maxreal); } sum_bin(rb, cr); where(); /* Extract all the data locally */ if (bConstrVir) { extract_binr(rb, isv, DIM*DIM, svir[0]); } /* We need the force virial and the kinetic energy for the first time through with velocity verlet */ if (bTemp || !bVV) { if (ekind) { for (j = 0; (j < inputrec->opts.ngtc); j++) { if (bSumEkinhOld) { extract_binr(rb, itc0[j], DIM*DIM, ekind->tcstat[j].ekinh_old[0]); } if (bEkinAveVel && !bReadEkin) { extract_binr(rb, itc1[j], DIM*DIM, ekind->tcstat[j].ekinf[0]); } else if (!bReadEkin) { extract_binr(rb, itc1[j], DIM*DIM, ekind->tcstat[j].ekinh[0]); } } extract_binr(rb, idedl, 1, &(ekind->dekindl)); extract_binr(rb, ica, 1, &(ekind->cosacc.mvcos)); where(); } } if (bPres) { extract_binr(rb, ifv, DIM*DIM, fvir[0]); } if (bEner) { extract_binr(rb, ie, nener, copyenerd); if (rmsd_data) { extract_binr(rb, irmsd, 2, rmsd_data); } if (!inputrecNeedMutot(inputrec)) { extract_binr(rb, imu, DIM, mu_tot); } for (j = 0; (j < egNR); j++) { extract_binr(rb, inn[j], enerd->grpp.nener, enerd->grpp.ener[j]); } if (inputrec->efep != efepNO) { extract_bind(rb, idvdll, efptNR, enerd->dvdl_lin); extract_bind(rb, idvdlnl, efptNR, enerd->dvdl_nonlin); if (enerd->n_lambda > 0) { extract_bind(rb, iepl, enerd->n_lambda, enerd->enerpart_lambda); } } where(); filter_enerdterm(copyenerd, FALSE, enerd->term, bTemp, bPres, bEner); } if (vcm) { extract_binr(rb, icm, DIM*vcm->nr, vcm->group_p[0]); where(); extract_binr(rb, imass, vcm->nr, vcm->group_mass); where(); if (vcm->mode == ecmANGULAR) { extract_binr(rb, icj, DIM*vcm->nr, vcm->group_j[0]); where(); extract_binr(rb, icx, DIM*vcm->nr, vcm->group_x[0]); where(); extract_binr(rb, ici, DIM*DIM*vcm->nr, vcm->group_i[0][0]); where(); } } if (checkNumberOfBondedInteractions) { extract_bind(rb, inb, 1, &nb); *totalNumberOfBondedInteractions = static_cast<int>(nb+0.5); } if (nsig > 0) { extract_binr(rb, isig, nsig, sig); } where(); }
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; }
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_large_int_t step,int delta_step, t_mdatoms *md, rvec *x,rvec *xprime,rvec *min_proj,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,error; tensor rmdr; rvec *vstor; real invdt,vir_fac,t; t_ilist *settle; int nsettle; t_pbc pbc; char buf[22]; t_vetavars *vetavar; 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 = md->start; homenr = md->homenr; nrend = start+homenr; /* set constants for pressure control integration */ vetavar = init_vetavars(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->delta_lambda; } if (vir != NULL) { clear_mat(rmdr); } where(); if (constr->lincsd) { bOK = constrain_lincs(fplog,bLog,bEner,ir,step,constr->lincsd,md,cr, x,xprime,min_proj,box,lambda,dvdlambda, invdt,v,vir!=NULL,rmdr, 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, homenr,md->invmass,constr->nblocks,constr->sblock, idef,ir,box,x,xprime,nrnb, constr->lagr,lambda,dvdlambda, invdt,v,vir!=NULL,rmdr,constr->maxwarn>=0,econq,vetavar); break; case (econqVeloc): bOK = bshakef(fplog,constr->shaked, homenr,md->invmass,constr->nblocks,constr->sblock, idef,ir,box,x,min_proj,nrnb, constr->lagr,lambda,dvdlambda, invdt,NULL,vir!=NULL,rmdr,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; } } settle = &idef->il[F_SETTLE]; if (settle->nr > 0) { nsettle = settle->nr/2; switch (econq) { case econqCoord: csettle(constr->settled, nsettle,settle->iatoms,x[0],xprime[0], invdt,v[0],vir!=NULL,rmdr,&error,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); } bOK = (error < 0); if (!bOK && constr->maxwarn >= 0) { char buf[256]; sprintf(buf, "\nstep " gmx_large_int_pfmt ": 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[error*2+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; break; case econqVeloc: case econqDeriv: case econqForce: case econqForceDispl: settle_proj(fplog,constr->settled,econq, nsettle,settle->iatoms,x, xprime,min_proj,vir!=NULL,rmdr,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"); } } } 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*rmdr[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,md,cr,xprime,v,box,constr->ed); } } return bOK; }