void setStateDependentAwhParams(AwhParams *awhParams, const pull_params_t *pull_params, pull_t *pull_work, const matrix box, int ePBC, const t_grpopts *inputrecGroupOptions, warninp_t wi) { /* The temperature is not really state depenendent but is not known * when read_awhParams is called (in get ir). * It is known first after do_index has been called in grompp.cpp. */ if (inputrecGroupOptions->ref_t == NULL || inputrecGroupOptions->ref_t[0] <= 0) { gmx_fatal(FARGS, "AWH biasing is only supported for temperatures > 0"); } for (int i = 1; i < inputrecGroupOptions->ngtc; i++) { if (inputrecGroupOptions->ref_t[i] != inputrecGroupOptions->ref_t[0]) { gmx_fatal(FARGS, "AWH biasing is currently only supported for identical temperatures for all temperature coupling groups"); } } t_pbc pbc; set_pbc(&pbc, ePBC, box); for (int k = 0; k < awhParams->numBias; k++) { AwhBiasParams *awhBiasParams = &awhParams->awhBiasParams[k]; for (int d = 0; d < awhBiasParams->ndim; d++) { AwhDimParams *dimParams = &awhBiasParams->dimParams[d]; /* The periodiciy of the AWH grid in certain cases depends on the simulation box */ dimParams->period = get_pull_coord_period(pull_params, dimParams->coordIndex, box); /* The initial coordinate value, converted to external user units. */ dimParams->coordValueInit = get_pull_coord_value(pull_work, dimParams->coordIndex, &pbc); t_pull_coord *pullCoord = &pull_params->coord[dimParams->coordIndex]; dimParams->coordValueInit *= pull_conversion_factor_internal2userinput(pullCoord); } } checkInputConsistencyInterval(awhParams, wi); /* Register AWH as external potential with pull to check consistency. */ Awh::registerAwhWithPull(*awhParams, pull_work); }
pull_t *set_pull_init(t_inputrec *ir, const gmx_mtop_t *mtop, rvec *x, matrix box, real lambda, warninp_t wi) { pull_params_t *pull; pull_t *pull_work; t_pbc pbc; int c; double t_start; pull = ir->pull; gmx::LocalAtomSetManager atomSets; pull_work = init_pull(nullptr, pull, ir, mtop, nullptr, &atomSets, lambda); auto mdAtoms = gmx::makeMDAtoms(nullptr, *mtop, *ir, false); auto md = mdAtoms->mdatoms(); atoms2md(mtop, ir, -1, nullptr, mtop->natoms, mdAtoms.get()); if (ir->efep) { update_mdatoms(md, lambda); } set_pbc(&pbc, ir->ePBC, box); t_start = ir->init_t + ir->init_step*ir->delta_t; if (pull->bSetPbcRefToPrevStepCOM) { initPullComFromPrevStep(nullptr, pull_work, md, &pbc, x); } pull_calc_coms(nullptr, pull_work, md, &pbc, t_start, x, nullptr); for (int g = 0; g < pull->ngroup; g++) { bool groupObeysPbc = pullCheckPbcWithinGroup(*pull_work, gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec *>(x), mtop->natoms), pbc, g, c_pullGroupSmallGroupThreshold); if (!groupObeysPbc) { char buf[STRLEN]; if (pull->group[g].pbcatom_input == 0) { sprintf(buf, "When the maximum distance from a pull group reference atom to other atoms in the " "group is larger than %g times half the box size a centrally placed " "atom should be chosen as pbcatom. Pull group %d is larger than that and does not have " "a specific atom selected as reference atom.", c_pullGroupSmallGroupThreshold, g); warning_error(wi, buf); } else if (!pull->bSetPbcRefToPrevStepCOM) { sprintf(buf, "The maximum distance from the chosen PBC atom (%d) of pull group %d to other " "atoms in the group is larger than %g times half the box size. " "Set the pull-pbc-ref-prev-step-com option to yes.", pull->group[g].pbcatom + 1, g, c_pullGroupSmallGroupThreshold); warning_error(wi, buf); } } if (groupObeysPbc) { groupObeysPbc = pullCheckPbcWithinGroup(*pull_work, gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec *>(x), mtop->natoms), pbc, g, c_pullGroupPbcMargin); if (!groupObeysPbc) { char buf[STRLEN]; sprintf(buf, "Pull group %d has atoms at a distance larger than %g times half the box size from the PBC atom (%d). " "If atoms are or will more beyond half the box size from the PBC atom, the COM will be ill defined.", g, c_pullGroupPbcMargin, pull->group[g].pbcatom + 1); set_warning_line(wi, nullptr, -1); warning(wi, buf); } } } fprintf(stderr, "Pull group natoms pbc atom distance at start reference at t=0\n"); for (c = 0; c < pull->ncoord; c++) { t_pull_coord *pcrd; t_pull_group *pgrp0, *pgrp1; double value; real init = 0; pcrd = &pull->coord[c]; pgrp0 = &pull->group[pcrd->group[0]]; pgrp1 = &pull->group[pcrd->group[1]]; fprintf(stderr, "%8d %8d %8d\n", pcrd->group[0], pgrp0->nat, pgrp0->pbcatom+1); fprintf(stderr, "%8d %8d %8d ", pcrd->group[1], pgrp1->nat, pgrp1->pbcatom+1); if (pcrd->bStart) { init = pcrd->init; pcrd->init = 0; } value = get_pull_coord_value(pull_work, c, &pbc); value *= pull_conversion_factor_internal2userinput(pcrd); fprintf(stderr, " %10.3f %s", value, pull_coordinate_units(pcrd)); if (pcrd->bStart) { pcrd->init = value + init; } if (pcrd->eGeom == epullgDIST) { if (pcrd->init < 0) { gmx_fatal(FARGS, "The initial pull distance (%g) needs to be non-negative with geometry %s. If you want a signed distance, use geometry %s instead.", pcrd->init, EPULLGEOM(pcrd->eGeom), EPULLGEOM(epullgDIR)); } /* TODO: With a positive init but a negative rate things could still * go wrong, but it might be fine if you don't pull too far. * We should give a warning or note when there is only one pull dim * active, since that is usually the problematic case when you should * be using direction. We will do this later, since an already planned * generalization of the pull code makes pull dim available here. */ } else if (pcrd->eGeom == epullgANGLE || pcrd->eGeom == epullgANGLEAXIS) { if (pcrd->init < 0 || pcrd->init > 180) { gmx_fatal(FARGS, "The initial pull reference angle (%g) is outside of the allowed range [0, 180] degrees.", pcrd->init); } } else if (pcrd->eGeom == epullgDIHEDRAL) { if (pcrd->init < -180 || pcrd->init > 180) { gmx_fatal(FARGS, "The initial pull reference angle (%g) is outside of the allowed range [-180, 180] degrees.", pcrd->init); } } fprintf(stderr, " %10.3f %s\n", pcrd->init, pull_coordinate_units(pcrd)); } return pull_work; }
pull_t *set_pull_init(t_inputrec *ir, const gmx_mtop_t *mtop, rvec *x, matrix box, real lambda, const gmx_output_env_t *oenv) { pull_params_t *pull; pull_t *pull_work; t_mdatoms *md; t_pbc pbc; int c; double t_start; pull = ir->pull; pull_work = init_pull(NULL, pull, ir, 0, NULL, mtop, NULL, oenv, lambda, FALSE, 0); md = init_mdatoms(NULL, mtop, ir->efep); atoms2md(mtop, ir, -1, NULL, mtop->natoms, md); if (ir->efep) { update_mdatoms(md, lambda); } set_pbc(&pbc, ir->ePBC, box); t_start = ir->init_t + ir->init_step*ir->delta_t; pull_calc_coms(NULL, pull_work, md, &pbc, t_start, x, NULL); fprintf(stderr, "Pull group natoms pbc atom distance at start reference at t=0\n"); for (c = 0; c < pull->ncoord; c++) { t_pull_coord *pcrd; t_pull_group *pgrp0, *pgrp1; double value; real init = 0; pcrd = &pull->coord[c]; pgrp0 = &pull->group[pcrd->group[0]]; pgrp1 = &pull->group[pcrd->group[1]]; fprintf(stderr, "%8d %8d %8d\n", pcrd->group[0], pgrp0->nat, pgrp0->pbcatom+1); fprintf(stderr, "%8d %8d %8d ", pcrd->group[1], pgrp1->nat, pgrp1->pbcatom+1); if (pcrd->bStart) { init = pcrd->init; pcrd->init = 0; } get_pull_coord_value(pull_work, c, &pbc, &value); value *= pull_conversion_factor_internal2userinput(pcrd); fprintf(stderr, " %10.3f %s", value, pull_coordinate_units(pcrd)); if (pcrd->bStart) { pcrd->init = value + init; } if (pcrd->eGeom == epullgDIST) { if (pcrd->init < 0) { gmx_fatal(FARGS, "The initial pull distance (%g) needs to be non-negative with geometry %s. If you want a signed distance, use geometry %s instead.", pcrd->init, EPULLGEOM(pcrd->eGeom), EPULLGEOM(epullgDIR)); } /* TODO: With a positive init but a negative rate things could still * go wrong, but it might be fine if you don't pull too far. * We should give a warning or note when there is only one pull dim * active, since that is usually the problematic case when you should * be using direction. We will do this later, since an already planned * generalization of the pull code makes pull dim available here. */ } else if (pcrd->eGeom == epullgANGLE || pcrd->eGeom == epullgANGLEAXIS) { if (pcrd->init < 0 || pcrd->init > 180) { gmx_fatal(FARGS, "The initial pull reference angle (%g) is outside of the allowed range [0, 180] degrees.", pcrd->init); } } else if (pcrd->eGeom == epullgDIHEDRAL) { if (pcrd->init < -180 || pcrd->init > 180) { gmx_fatal(FARGS, "The initial pull reference angle (%g) is outside of the allowed range [-180, 180] degrees.", pcrd->init); } } fprintf(stderr, " %10.3f %s\n", pcrd->init, pull_coordinate_units(pcrd)); } return pull_work; }