Merge release-2019 branch into master
authorSzilárd Páll <pall.szilard@gmail.com>
Tue, 18 Dec 2018 16:30:28 +0000 (17:30 +0100)
committerSzilárd Páll <pall.szilard@gmail.com>
Tue, 18 Dec 2018 22:48:53 +0000 (23:48 +0100)
Change-Id: Ie08781a0f40b2c92321e605db91d047a4451d2b2

1  2 
docs/CMakeLists.txt
src/api/cpp/context.cpp
src/gromacs/mdlib/forcerec.cpp
src/gromacs/mdrun/md.cpp
src/gromacs/pulling/pull.cpp

diff --combined docs/CMakeLists.txt
index 9f5b3b20edba18caf1333e710801fd85bb481ec5,36e184bc76c48b870a2de2cd7cc49b61bece5a7d..5c4fc632c7c67abc8838564c64c7f4b6b86324b2
@@@ -119,12 -119,13 +119,13 @@@ else(
      elseif(NOT SPHINX_FOUND)
          set(MANUAL_BUILD_IS_POSSIBLE OFF)
          set(MANUAL_BUILD_NOT_POSSIBLE_REASON "Sphinx has not been found and is needed to create the LaTex input files")
-     elseif(NOT PDFLATEX_COMPILER OR NOT IMAGE_CONVERT_POSSIBLE)
+     elseif(NOT PDFLATEX_COMPILER)
          set(MANUAL_BUILD_IS_POSSIBLE OFF)
-         set(MANUAL_BUILD_NOT_POSSIBLE_REASON "pdflatex or some other dependency (ImageMagick convert) is not available")
-         if (NOT IMAGE_CONVERT_POSSIBLE)
-             set(NO_IMAGE_CONVERT_REASON "Can not convert files for online or pdf manual")
-         endif()
+         set(MANUAL_BUILD_NOT_POSSIBLE_REASON "pdflatex is not available")
+     elseif(NOT IMAGE_CONVERT_POSSIBLE)
+         set(MANUAL_BUILD_IS_POSSIBLE OFF)
+         set(MANUAL_BUILD_NOT_POSSIBLE_REASON "a working form of ImageMagick convert is not available")
+         set(NO_IMAGE_CONVERT_REASON "Can not convert files for online or pdf manual")
          # TODO Later, identify other dependencies like bibtex,
          # make_index, date, some graphics conversion program,
          # etc. Perhaps patch UseLATEX.cmake and contribute upstream.
@@@ -229,6 -230,7 +230,7 @@@ if (SPHINX_FOUND
          reference-manual/special/qmmm.rst
          reference-manual/special/vmd-imd.rst
          reference-manual/special/membrane-embedding.rst
+         reference-manual/special/mimic-qmmm.rst
          # Analysis chapter
          reference-manual/analysis.rst
          reference-manual/analysis/using-groups.rst
          dev-manual/includestyle.rst
          dev-manual/index.rst
          dev-manual/jenkins.rst
+         dev-manual/known-issues.rst
          dev-manual/language-features.rst
          dev-manual/naming.rst
          dev-manual/overview.rst
          how-to/visualize.rst
          install-guide/index.rst
          release-notes/index.rst
 +        release-notes/highlights.rst
 +        release-notes/features.rst
 +        release-notes/performance.rst
 +        release-notes/tools.rst
 +        release-notes/bugs-fixed.rst
 +        release-notes/removed-functionality.rst
 +        release-notes/deprecated-functionality.rst
 +        release-notes/portability.rst
 +        release-notes/miscellaneous.rst
          release-notes/2019/major/highlights.rst
          release-notes/2019/major/features.rst
          release-notes/2019/major/performance.rst
diff --combined src/api/cpp/context.cpp
index c9875d8bb69b964c736375503d7a788c56494e7f,8b455db34d21074c2435b7d384df0958fe33a274..bea12dbf0f65ea0b57fcee99840275f772d3b693
@@@ -120,22 -120,23 +120,22 @@@ std::shared_ptr<Session> ContextImpl::l
           * a microstate for gmxapi interfaces.
           */
  
 -        // Note: these output options normalize the file names, but not their
 -        // paths. gmxapi 0.0.7 changes working directory for each session, so the
 -        // relative paths are appropriate, but a near-future version will avoid
 -        // changing directories once the process starts and manage file paths explicitly.
 -        using gmxapi::c_majorVersion;
 -        using gmxapi::c_minorVersion;
 -        using gmxapi::c_patchVersion;
 -        static_assert(!(c_majorVersion != 0 || c_minorVersion != 0 || c_patchVersion > 7),
 -                      "Developer notice: check assumptions about working directory and relative file paths for this "
 -                      "software version.");
 -
          // Set input TPR name
          mdArgs_.emplace_back("-s");
          mdArgs_.emplace_back(filename);
 +
          // Set checkpoint file name
          mdArgs_.emplace_back("-cpi");
          mdArgs_.emplace_back("state.cpt");
 +        /* Note: we normalize the checkpoint file name, but not its full path.
 +         * Through version 0.0.8, gmxapi clients change working directory
 +         * for each session, so relative path(s) below are appropriate.
 +         * A future gmxapi version should avoid changing directories once the
 +         * process starts and instead manage files (paths) in an absolute and
 +         * immutable way, with abstraction provided through the Context chain-of-responsibility.
 +         * TODO: API abstractions for initializing simulations that may be new or partially complete.
 +         * Reference gmxapi milestone 13 at https://redmine.gromacs.org/issues/2585
 +         */
  
          // Create a mock argv. Note that argv[0] is expected to hold the program name.
          const int  offset = 1;
              options_.logFileGuard = openLogFile(ftp2fn(efLOG,
                                                         options_.filenames.size(),
                                                         options_.filenames.data()),
-                                                 options_.mdrunOptions.continuationOptions.appendFiles,
-                                                 options_.cr->nodeid,
-                                                 options_.cr->nnodes);
+                                                 options_.mdrunOptions.continuationOptions.appendFiles);
          }
  
          auto simulationContext = createSimulationContext(options_.cr);
index fa66366e7e9f26f07344f8bb0898aa1cc2cbb200,6475581325ad4de78ec3e9c3d06f211b16b4e038..0c9cefce72cbefea53e08f11668621bacf178185
@@@ -58,7 -58,7 +58,7 @@@
  #include "gromacs/gmxlib/nonbonded/nonbonded.h"
  #include "gromacs/gpu_utils/gpu_utils.h"
  #include "gromacs/hardware/hw_info.h"
- #include "gromacs/listed-forces/listed-forces.h"
+ #include "gromacs/listed-forces/gpubonded.h"
  #include "gromacs/listed-forces/manage-threading.h"
  #include "gromacs/listed-forces/pairs.h"
  #include "gromacs/math/functions.h"
@@@ -675,8 -675,8 +675,8 @@@ static cginfo_mb_t *init_cginfo_mb(FIL
              {
                  a0 = cgs->index[cg];
                  a1 = cgs->index[cg+1];
 -                if (getGroupType(&mtop->groups, egcENER, a_offset+am+a0) !=
 -                    getGroupType(&mtop->groups, egcENER, a_offset   +a0))
 +                if (getGroupType(mtop->groups, egcENER, a_offset+am+a0) !=
 +                    getGroupType(mtop->groups, egcENER, a_offset   +a0))
                  {
                      bId = FALSE;
                  }
                  a1 = cgs->index[cg+1];
  
                  /* Store the energy group in cginfo */
 -                gid = getGroupType(&mtop->groups, egcENER, a_offset+am+a0);
 +                gid = getGroupType(mtop->groups, egcENER, a_offset+am+a0);
                  SET_CGINFO_GID(cginfo[cgm+cg], gid);
  
                  /* Check the intra/inter charge group exclusions */
@@@ -3065,11 -3065,6 +3065,6 @@@ void init_forcerec(FIL
      init_bonded_threading(fp, mtop->groups.grps[egcENER].nr,
                            &fr->bondedThreading);
  
-     if (useGpuForBonded)
-     {
-         fr->gpuBondedLists = new GpuBondedLists;
-     }
      fr->nthread_ewc = gmx_omp_nthreads_get(emntBonded);
      snew(fr->ewc_t, fr->nthread_ewc);
  
  
          if (useGpuForBonded)
          {
-             init_gpu_bonded(fr->gpuBondedLists,
-                             mtop->ffparams,
-                             DOMAINDECOMP(cr) ?
-                             nbnxn_gpu_get_command_stream(fr->nbv->gpu_nbv, eintNonlocal) :
-                             nbnxn_gpu_get_command_stream(fr->nbv->gpu_nbv, eintLocal));
+             auto stream = DOMAINDECOMP(cr) ?
+                 nbnxn_gpu_get_command_stream(fr->nbv->gpu_nbv, eintNonlocal) :
+                 nbnxn_gpu_get_command_stream(fr->nbv->gpu_nbv, eintLocal);
+             // TODO the heap allocation is only needed while
+             // t_forcerec lacks a constructor.
+             fr->gpuBonded = new gmx::GpuBonded(mtop->ffparams,
+                                                stream);
          }
      }
  
@@@ -3135,12 -3132,8 +3132,8 @@@ void free_gpu_resources(t_forcere
      {
          /* free nbnxn data in GPU memory */
          nbnxn_gpu_free(fr->nbv->gpu_nbv);
-         if (fr->gpuBondedLists)
-         {
-             delete fr->gpuBondedLists;
-             fr->gpuBondedLists = nullptr;
-         }
+         delete fr->gpuBonded;
+         fr->gpuBonded = nullptr;
      }
  
      /* With tMPI we need to wait for all ranks to finish deallocation before
@@@ -3175,7 -3168,7 +3168,7 @@@ void done_forcerec(t_forcerec *fr, int 
      done_ns(fr->ns, numEnergyGroups);
      sfree(fr->ewc_t);
      tear_down_bonded_threading(fr->bondedThreading);
-     GMX_RELEASE_ASSERT(fr->gpuBondedLists == nullptr, "Should have been deleted earlier, when used");
+     GMX_RELEASE_ASSERT(fr->gpuBonded == nullptr, "Should have been deleted earlier, when used");
      fr->bondedThreading = nullptr;
      sfree(fr);
  }
diff --combined src/gromacs/mdrun/md.cpp
index 68d166d24b1990d456cac22da98420692cbb05c1,ee93053af17439e8af65a94aa54a298cdcff8e79..765ffd18a627c57c52c7687a4235ee1284a6a9f2
@@@ -356,18 -356,21 +356,21 @@@ void gmx::Integrator::do_md(
              /* Update mdebin with energy history if appending to output files */
              if (continuationOptions.appendFiles)
              {
-                 restore_energyhistory_from_state(mdebin, observablesHistory->energyHistory.get());
-             }
-             else
-             {
-                 if (observablesHistory->energyHistory != nullptr)
+                 /* If no history is available (because a checkpoint is from before
+                  * it was written) make a new one later, otherwise restore it.
+                  */
+                 if (observablesHistory->energyHistory)
                  {
-                     /* We might have read an energy history from checkpoint.
-                      * As we are not appending, we want to restart the statistics.
-                      * Free the allocated memory and reset the counts.
-                      */
-                     observablesHistory->energyHistory = {};
+                     restore_energyhistory_from_state(mdebin, observablesHistory->energyHistory.get());
                  }
+             }
+             else if (observablesHistory->energyHistory)
+             {
+                 /* We might have read an energy history from checkpoint.
+                  * As we are not appending, we want to restart the statistics.
+                  * Free the allocated memory and reset the counts.
+                  */
+                 observablesHistory->energyHistory = {};
                  /* We might have read a pull history from checkpoint.
                   * We will still want to keep the statistics, so that the files
                   * can be joined and still be meaningful.
                   * should not be reset.
                   */
              }
-             if (ir->pull && ir->pull->bSetPbcRefToPrevStepCOM)
-             {
-                 /* Copy the pull group COM of the previous step from the checkpoint state to the pull state */
-                 setPrevStepPullComFromState(ir->pull_work, state);
-             }
          }
-         else if (ir->pull && ir->pull->bSetPbcRefToPrevStepCOM)
-         {
-             allocStatePrevStepPullCom(state, ir->pull_work);
-             t_pbc pbc;
-             set_pbc(&pbc, ir->ePBC, state->box);
-             initPullComFromPrevStep(cr, ir->pull_work, mdatoms, &pbc, as_rvec_array(state->x.data()));
-             updatePrevStepCom(ir->pull_work);
-             setStatePrevStepPullCom(ir->pull_work, state);
-         }
-         if (observablesHistory->energyHistory == nullptr)
+         if (!observablesHistory->energyHistory)
          {
              observablesHistory->energyHistory = compat::make_unique<energyhistory_t>();
          }
-         if (observablesHistory->pullHistory == nullptr)
+         if (!observablesHistory->pullHistory)
          {
              observablesHistory->pullHistory = compat::make_unique<PullHistory>();
          }
          update_energyhistory(observablesHistory->energyHistory.get(), mdebin);
      }
  
+     preparePrevStepPullCom(ir, mdatoms, state, state_global, cr, startingFromCheckpoint);
      // TODO: Remove this by converting AWH into a ForceProvider
      auto awh = prepareAwhModule(fplog, *ir, state_global, cr, ms, startingFromCheckpoint,
                                  shellfc != nullptr,
                                  constr, enerd, fcd,
                                  state, f.arrayRefWithPadding(), force_vir, mdatoms,
                                  nrnb, wcycle, graph, groups,
-                                 shellfc, fr, t, mu_tot,
+                                 shellfc, fr, ppForceWorkload, t, mu_tot,
                                  vsite,
                                  ddOpenBalanceRegion, ddCloseBalanceRegion);
          }
                       state->box, state->x.arrayRefWithPadding(), &state->hist,
                       f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd,
                       state->lambda, graph,
-                      fr, vsite, mu_tot, t, ed ? ed->getLegacyED() : nullptr,
+                      fr, ppForceWorkload, vsite, mu_tot, t, ed ? ed->getLegacyED() : nullptr,
                       (bNS ? GMX_FORCE_NS : 0) | force_flags,
                       ddOpenBalanceRegion, ddCloseBalanceRegion);
          }
                        state, graph,
                        nrnb, wcycle, upd, constr);
  
-         if (MASTER(cr) && ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
+         if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
          {
-             updatePrevStepCom(ir->pull_work);
-             setStatePrevStepPullCom(ir->pull_work, state);
+             updatePrevStepPullCom(ir->pull_work, state);
          }
  
          if (ir->eI == eiVVAK)
      walltime_accounting_set_nsteps_done(walltime_accounting, step_rel);
  
      destroy_enerdata(enerd);
 +
      sfree(enerd);
 +
 +    /* Clean up topology. top->atomtypes has an allocated pointer if no domain decomposition*/
 +    if (!DOMAINDECOMP(cr))
 +    {
 +        done_atomtypes(&top->atomtypes);
 +    }
      sfree(top);
  }
index 1f9722efc9dc5953a8c00d9665e634316e51bdf8,f9ae38483a80b526a95aa065f69a861044e25bc2..2b6017d56efc99399746ccf8d5847970a76738a5
@@@ -65,6 -65,7 +65,7 @@@
  #include "gromacs/mdtypes/inputrec.h"
  #include "gromacs/mdtypes/md_enums.h"
  #include "gromacs/mdtypes/mdatom.h"
+ #include "gromacs/mdtypes/state.h"
  #include "gromacs/pbcutil/pbc.h"
  #include "gromacs/topology/mtop_lookup.h"
  #include "gromacs/topology/topology.h"
@@@ -1691,6 -1692,21 +1692,21 @@@ void dd_make_local_pull_groups(const t_
  
              comm->bParticipate = bWillParticipate;
              comm->nparticipate = count[0];
+             /* When we use the previous COM for PBC, we need to broadcast
+              * the previous COM to ranks that have joined the communicator.
+              */
+             for (pull_group_work_t &group : pull->group)
+             {
+                 if (group.epgrppbc == epgrppbcPREVSTEPCOM)
+                 {
+                     GMX_ASSERT(comm->bParticipate || !MASTER(cr),
+                                "The master rank has to participate, as it should pass an up to date prev. COM "
+                                "to bcast here as well as to e.g. checkpointing");
+                     gmx_bcast(sizeof(dvec), group.x_prev_step, cr);
+                 }
+             }
          }
      }
  
@@@ -1715,7 -1731,7 +1731,7 @@@ static void init_pull_group_index(FILE 
      /* In parallel, store we need to extract localWeights from weights at DD time */
      std::vector<real>  &weights = ((cr && PAR(cr)) ? pg->globalWeights : pg->localWeights);
  
 -    const gmx_groups_t *groups  = &mtop->groups;
 +    const gmx_groups_t &groups  = mtop->groups;
  
      /* Count frozen dimensions and (weighted) mass */
      int    nfrozen = 0;
              }
              else
              {
 -                if (groups->grpnr[egcTC] == nullptr)
 +                if (groups.grpnr[egcTC] == nullptr)
                  {
                      mbd = ir->delta_t/ir->opts.tau_t[0];
                  }
                  else
                  {
 -                    mbd = ir->delta_t/ir->opts.tau_t[groups->grpnr[egcTC][ii]];
 +                    mbd = ir->delta_t/ir->opts.tau_t[groups.grpnr[egcTC][ii]];
                  }
              }
              w                   *= m/mbd;
@@@ -1877,7 -1893,7 +1893,7 @@@ init_pull(FILE *fplog, const pull_param
          /* Set up the global to local atom mapping for PBC atoms */
          for (pull_group_work_t &group : pull->group)
          {
-             if (group.epgrppbc == epgrppbcREFAT)
+             if (group.epgrppbc == epgrppbcREFAT || group.epgrppbc == epgrppbcPREVSTEPCOM)
              {
                  /* pbcAtomSet consists of a single atom */
                  group.pbcAtomSet = gmx::compat::make_unique<gmx::LocalAtomSet>(atomSets->add({&group.params.pbcatom, &group.params.pbcatom + 1}));
      pull->bFOutAverage = pull_params->bFOutAverage;
  
      GMX_RELEASE_ASSERT(pull->group[0].params.nat == 0, "pull group 0 is an absolute reference group and should not contain atoms");
-     pull->group[0].x_prev_step[XX] = NAN;
  
      pull->numCoordinatesWithExternalPotential = 0;
  
              init_pull_group_index(fplog, cr, g, pgrp,
                                    bConstraint, pulldim_con,
                                    mtop, ir, lambda);
-             pgrp->x_prev_step[XX] = NAN;
          }
          else
          {
      }
  
      comm->pbcAtomBuffer.resize(pull->group.size());
-     comm->comBuffer.resize(pull->group.size()*DIM);
+     comm->comBuffer.resize(pull->group.size()*c_comBufferStride);
      if (pull->bCylinder)
      {
          comm->cylinderBuffer.resize(pull->coord.size()*c_cylinderBufferStride);
@@@ -2253,6 -2266,35 +2266,35 @@@ static void destroy_pull(struct pull_t 
      delete pull;
  }
  
+ void preparePrevStepPullCom(const t_inputrec *ir, const t_mdatoms *md, t_state *state, const t_state *state_global, const t_commrec *cr, bool startingFromCheckpoint)
+ {
+     if (!ir->pull || !ir->pull->bSetPbcRefToPrevStepCOM)
+     {
+         return;
+     }
+     allocStatePrevStepPullCom(state, ir->pull_work);
+     if (startingFromCheckpoint)
+     {
+         if (MASTER(cr))
+         {
+             state->pull_com_prev_step = state_global->pull_com_prev_step;
+         }
+         if (PAR(cr))
+         {
+             /* Only the master rank has the checkpointed COM from the previous step */
+             gmx_bcast(sizeof(double) * state->pull_com_prev_step.size(), &state->pull_com_prev_step[0], cr);
+         }
+         setPrevStepPullComFromState(ir->pull_work, state);
+     }
+     else
+     {
+         t_pbc pbc;
+         set_pbc(&pbc, ir->ePBC, state->box);
+         initPullComFromPrevStep(cr, ir->pull_work, md, &pbc, state->x.rvec_array());
+         updatePrevStepPullCom(ir->pull_work, state);
+     }
+ }
  void finish_pull(struct pull_t *pull)
  {
      check_external_potential_registration(pull);