+
+ /* We should participate if we have pull or pbc atoms */
+ if (!bMustParticipate &&
+ (pull->group[g].nat_loc > 0 ||
+ (pull->group[g].params.pbcatom >= 0 &&
+ ga2la_get_home(dd->ga2la, pull->group[g].params.pbcatom, &a))))
+ {
+ bMustParticipate = TRUE;
+ }
+ }
+
+ if (!comm->bParticipateAll)
+ {
+ /* Keep currently not required ranks in the communicator
+ * if they needed to participate up to 20 decompositions ago.
+ * This avoids frequent rebuilds due to atoms jumping back and forth.
+ */
+ const gmx_int64_t history_count = 20;
+ gmx_bool bWillParticipate;
+ int count[2];
+
+ /* Increase the decomposition counter for the current call */
+ comm->setup_count++;
+
+ if (bMustParticipate)
+ {
+ comm->must_count = comm->setup_count;
+ }
+
+ bWillParticipate =
+ bMustParticipate ||
+ (comm->bParticipate &&
+ comm->must_count >= comm->setup_count - history_count);
+
+ if (debug && dd != NULL)
+ {
+ fprintf(debug, "Our DD rank (%3d) pull #atoms>0 or master: %d, will be part %d\n",
+ dd->rank, bMustParticipate, bWillParticipate);
+ }
+
+ if (bWillParticipate)
+ {
+ /* Count the number of ranks that we want to have participating */
+ count[0] = 1;
+ /* Count the number of ranks that need to be added */
+ count[1] = comm->bParticipate ? 0 : 1;
+ }
+ else
+ {
+ count[0] = 0;
+ count[1] = 0;
+ }
+
+ /* The cost of this global operation will be less that the cost
+ * of the extra MPI_Comm_split calls that we can avoid.
+ */
+ gmx_sumi(2, count, cr);
+
+ /* If we are missing ranks or if we have 20% more ranks than needed
+ * we make a new sub-communicator.
+ */
+ if (count[1] > 0 || 6*count[0] < 5*comm->nparticipate)
+ {
+ if (debug)
+ {
+ fprintf(debug, "Creating new pull subcommunicator of size %d\n",
+ count[0]);
+ }
+
+#ifdef GMX_MPI
+ if (comm->mpi_comm_com != MPI_COMM_NULL)
+ {
+ MPI_Comm_free(&comm->mpi_comm_com);
+ }
+
+ /* This might be an extremely expensive operation, so we try
+ * to avoid this splitting as much as possible.
+ */
+ assert(dd != NULL);
+ MPI_Comm_split(dd->mpi_comm_all, bWillParticipate ? 0 : 1, dd->rank,
+ &comm->mpi_comm_com);
+#endif
+
+ comm->bParticipate = bWillParticipate;
+ comm->nparticipate = count[0];
+ }