Ejemplo n.º 1
0
void
TransferOperatorRegistry::addRefineOperator(
   const char* var_type_name,
   const boost::shared_ptr<RefineOperator>& refine_op)
{
   if (d_max_op_stencil_width_req) {
      for (short unsigned int d(1); d <= SAMRAI::MAX_DIM_VAL; ++d) {
         if (refine_op->getStencilWidth(tbox::Dimension(d)) >
             getMaxTransferOpStencilWidth(tbox::Dimension(d))) {
            TBOX_WARNING(
               "Adding refine operator " << refine_op->getOperatorName()
                                         << "\nwith stencil width greater than current maximum\n"
                                         << "after call to getMaxTransferOpStencilWidth.\n");
         }
      }
   }
   boost::unordered_map<std::string, boost::unordered_map<std::string,
                                                          boost::shared_ptr<RefineOperator> > >::
   iterator refine_ops =
      d_refine_operators.find(refine_op->getOperatorName());
   if (refine_ops == d_refine_operators.end()) {
      refine_ops = d_refine_operators.insert(
            std::make_pair(refine_op->getOperatorName(),
               boost::unordered_map<std::string,
                                    boost::shared_ptr<RefineOperator> >(0))).first;
   }
   refine_ops->second.insert(std::make_pair(var_type_name, refine_op));
}
Ejemplo n.º 2
0
void
LinearOperator::modifyRhsForInhomogeneousBc(
    SAMRAIVectorReal<NDIM,double>& /*y*/)
{
    TBOX_WARNING("LinearOperator::modifyRhsForInhomogeneousBc() not implemented for this operator" << std::endl);
    return;
}// modifyRhsForInhomogeneousBc
void CartCellDoubleCubicCoarsen::coarsen(Patch<NDIM>& coarse,
                                         const Patch<NDIM>& fine,
                                         const int dst_component,
                                         const int src_component,
                                         const Box<NDIM>& coarse_box,
                                         const IntVector<NDIM>& ratio) const
{
    if (ratio.min() < 4)
    {
        IBTK_DO_ONCE(TBOX_WARNING("CartCellDoubleCubicCoarsen::coarsen():\n"
                                  << "  cubic coarsening requires a refinement ratio of 4 or larger.\n"
                                  << "  reverting to weighted averaging." << std::endl););
Ejemplo n.º 4
0
/*
 *************************************************************************
 *
 * Get data from input database.
 *
 *************************************************************************
 */
void
CVODEModel::getFromInput(
   std::shared_ptr<Database> input_db,
   bool is_from_restart)
{
   NULL_USE(is_from_restart);

   d_initial_value = input_db->getDoubleWithDefault("initial_value", 0.0);

   IntVector periodic(d_grid_geometry->getPeriodicShift(IntVector(d_dim,
                            1)));
   int num_per_dirs = 0;
   for (int id = 0; id < d_dim.getValue(); ++id) {
      if (periodic(id)) ++num_per_dirs;
   }

   if (input_db->keyExists("Boundary_data")) {
      std::shared_ptr<Database> boundary_db(
         input_db->getDatabase("Boundary_data"));

      if (d_dim == Dimension(2)) {
         CartesianBoundaryUtilities2::getFromInput(this,
            boundary_db,
            d_scalar_bdry_edge_conds,
            d_scalar_bdry_node_conds,
            periodic);
      } else if (d_dim == Dimension(3)) {
         CartesianBoundaryUtilities3::getFromInput(this,
            boundary_db,
            d_scalar_bdry_face_conds,
            d_scalar_bdry_edge_conds,
            d_scalar_bdry_node_conds,
            periodic);
      }

   } else {
      TBOX_WARNING(
         d_object_name << ": "
                       << "Key data `Boundary_data' not found in input. " << endl);
   }

#ifdef USE_FAC_PRECONDITIONER
   d_use_neumann_bcs =
      input_db->getBoolWithDefault("use_neumann_bcs", d_use_neumann_bcs);
   d_print_solver_info =
      input_db->getBoolWithDefault("print_solver_info", d_print_solver_info);
#endif

}
Ejemplo n.º 5
0
void
PenaltyIBMethod::getFromInput(Pointer<Database> db, bool is_from_restart)
{
    if (!is_from_restart)
    {
        if (db->keyExists("gravitational_acceleration"))
        {
            db->getDoubleArray("gravitational_acceleration", &d_gravitational_acceleration[0], NDIM);
        }
        else
        {
            TBOX_WARNING(d_object_name << ":  "
                                       << "Using penalty-IB method but key data "
                                          "`gravitational_acceleration' not found in input.");
        }
    }
    return;
} // getFromInput
Ejemplo n.º 6
0
RigidBodyKinematics::RigidBodyKinematics(const std::string& object_name,
                                         Pointer<Database> input_db,
                                         LDataManager* l_data_manager,
                                         Pointer<PatchHierarchy<NDIM> > /*patch_hierarchy*/,
                                         bool register_for_restart)
    : ConstraintIBKinematics(object_name, input_db, l_data_manager, register_for_restart),
      d_parser_time(0.0),
      d_center_of_mass(3, 0.0),
      d_incremented_angle_from_reference_axis(3, 0.0),
      d_tagged_pt_position(3, 0.0)
{
    // NOTE: Parent class constructor registers class with the restart manager, sets object name.

    // Read-in kinematics velocity functions
    for (int d = 0; d < NDIM; ++d)
    {
        const std::string postfix = "_function_" + std::to_string(d);
        std::string key_name = "kinematics_velocity" + postfix;

        if (input_db->isString(key_name))
        {
            d_kinematicsvel_function_strings.push_back(input_db->getString(key_name));
        }
        else
        {
            d_kinematicsvel_function_strings.push_back("0.0");
            TBOX_WARNING("RigidBodyKinematics::RigidBodyKinematics() :\n"
                         << "  no function corresponding to key " << key_name << "found for dimension = " << d
                         << "; using kinematics_vel = 0.0. " << std::endl);
        }

        d_kinematicsvel_parsers.push_back(new mu::Parser());
        d_kinematicsvel_parsers.back()->SetExpr(d_kinematicsvel_function_strings.back());
        d_all_parsers.push_back(d_kinematicsvel_parsers.back());
    }

    // Define constants and variables for the parsers.
    for (std::vector<mu::Parser*>::const_iterator cit = d_all_parsers.begin(); cit != d_all_parsers.end(); ++cit)
    {
        // Various names for pi.
        (*cit)->DefineConst("pi", PII);
        (*cit)->DefineConst("Pi", PII);
        (*cit)->DefineConst("PI", PII);

        // Variables
        (*cit)->DefineVar("T", &d_parser_time);
        (*cit)->DefineVar("t", &d_parser_time);
        for (int d = 0; d < NDIM; ++d)
        {
            const std::string postfix = std::to_string(d);
            (*cit)->DefineVar("X" + postfix, d_parser_posn.data() + d);
            (*cit)->DefineVar("x" + postfix, d_parser_posn.data() + d);
            (*cit)->DefineVar("X_" + postfix, d_parser_posn.data() + d);
            (*cit)->DefineVar("x_" + postfix, d_parser_posn.data() + d);
        }
    }

    // Set the size of vectors.
    const StructureParameters& struct_param = getStructureParameters();
    const int coarsest_ln = struct_param.getCoarsestLevelNumber();
    const int finest_ln = struct_param.getFinestLevelNumber();
    const int total_levels = finest_ln - coarsest_ln + 1;
    d_kinematics_vel.resize(total_levels);

    const std::vector<std::pair<int, int> >& idx_range = struct_param.getLagIdxRange();
    for (int ln = 0; ln < total_levels; ++ln)
    {
        const int nodes_this_ln = idx_range[ln].second - idx_range[ln].first;
        d_kinematics_vel[ln].resize(NDIM);
        for (int d = 0; d < NDIM; ++d)
        {
            d_kinematics_vel[ln][d].resize(nodes_this_ln);
        }
    }

    bool from_restart = RestartManager::getManager()->isFromRestart();
    if (from_restart)
    {
        getFromRestart();
        setRigidBodySpecificVelocity(
            d_current_time, d_incremented_angle_from_reference_axis, d_center_of_mass, d_tagged_pt_position);
        setShape(d_current_time, d_incremented_angle_from_reference_axis);
    }

    return;

} // RigidBodyKinematics
Ejemplo n.º 7
0
muParserRobinBcCoefs::muParserRobinBcCoefs(const std::string& object_name,
                                           Pointer<Database> input_db,
                                           Pointer<CartesianGridGeometry<NDIM> > grid_geom)
    : d_grid_geom(grid_geom), d_constants(), d_acoef_function_strings(), d_bcoef_function_strings(),
      d_gcoef_function_strings(), d_acoef_parsers(2 * NDIM), d_bcoef_parsers(2 * NDIM), d_gcoef_parsers(2 * NDIM),
      d_parser_time(new double), d_parser_posn(new Point)
{
#if !defined(NDEBUG)
    TBOX_ASSERT(!object_name.empty());
    TBOX_ASSERT(input_db);
#else
    NULL_USE(object_name);
#endif
    // Read in user-provided constants.
    Array<std::string> db_key_names = input_db->getAllKeys();
    for (int k = 0; k < db_key_names.size(); ++k)
    {
        const std::string& name = db_key_names[k];
        if (input_db->isDouble(name))
        {
            d_constants[name] = input_db->getDouble(name);
        }
        else if (input_db->isFloat(name))
        {
            d_constants[name] = input_db->getFloat(name);
        }
        else if (input_db->isInteger(name))
        {
            d_constants[name] = input_db->getInteger(name);
        }
    }

    // Initialize the parsers with data read in from the input database.
    for (int d = 0; d < 2 * NDIM; ++d)
    {
        std::string key_name;
        std::ostringstream stream;
        stream << "_function_" << d;
        const std::string postfix = stream.str();

        key_name = "acoef" + postfix;
        if (input_db->isString(key_name))
        {
            d_acoef_function_strings.push_back(input_db->getString(key_name));
        }
        else
        {
            d_acoef_function_strings.push_back("0.0");
            TBOX_WARNING("muParserRobinBcCoefs::muParserRobinBcCoefs():\n"
                         << "  no function corresponding to key ``" << key_name << "'' found for side = " << d
                         << "; using acoef = 0.0." << std::endl);
        }
        try
        {
            d_acoef_parsers[d].SetExpr(d_acoef_function_strings.back());
        }
        catch (mu::ParserError& e)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  error: " << e.GetMsg() << "\n"
                       << "  in:    " << e.GetExpr() << "\n");
        }
        catch (...)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  unrecognized exception generated by muParser library.\n");
        }

        key_name = "bcoef" + postfix;
        if (input_db->isString(key_name))
        {
            d_bcoef_function_strings.push_back(input_db->getString(key_name));
        }
        else
        {
            d_bcoef_function_strings.push_back("0.0");
            TBOX_WARNING("muParserRobinBcCoefs::muParserRobinBcCoefs():\n"
                         << "  no function corresponding to key ``" << key_name << "'' found for side = " << d
                         << "; using bcoef = 0.0." << std::endl);
        }
        try
        {
            d_bcoef_parsers[d].SetExpr(d_bcoef_function_strings.back());
        }
        catch (mu::ParserError& e)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  error: " << e.GetMsg() << "\n"
                       << "  in:    " << e.GetExpr() << "\n");
        }
        catch (...)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  unrecognized exception generated by muParser library.\n");
        }

        key_name = "gcoef" + postfix;
        if (input_db->isString(key_name))
        {
            d_gcoef_function_strings.push_back(input_db->getString(key_name));
        }
        else
        {
            d_gcoef_function_strings.push_back("0.0");
            TBOX_WARNING("muParserRobinBcCoefs::muParserRobinBcCoefs():\n"
                         << "  no function corresponding to key ``" << key_name << "'' found for side = " << d
                         << "; using gcoef = 0.0." << std::endl);
        }
        try
        {
            d_gcoef_parsers[d].SetExpr(d_gcoef_function_strings.back());
        }
        catch (mu::ParserError& e)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  error: " << e.GetMsg() << "\n"
                       << "  in:    " << e.GetExpr() << "\n");
        }
        catch (...)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  unrecognized exception generated by muParser library.\n");
        }
    }

    // Define the default and user-provided constants.
    std::vector<mu::Parser*> all_parsers(3 * 2 * NDIM);
    for (int d = 0; d < 2 * NDIM; ++d)
    {
        all_parsers[3 * d] = &d_acoef_parsers[d];
        all_parsers[3 * d + 1] = &d_bcoef_parsers[d];
        all_parsers[3 * d + 2] = &d_gcoef_parsers[d];
    }
    const double pi = 3.1415926535897932384626433832795;
    const double* const xLower = grid_geom->getXLower();
    const double* const xUpper = grid_geom->getXUpper();
    for (std::vector<mu::Parser*>::const_iterator cit = all_parsers.begin(); cit != all_parsers.end(); ++cit)
    {
        // Various names for pi.
        (*cit)->DefineConst("pi", pi);
        (*cit)->DefineConst("Pi", pi);
        (*cit)->DefineConst("PI", pi);

        // The extents of the domain.
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            std::ostringstream stream;
            stream << d;
            const std::string postfix = stream.str();

            (*cit)->DefineConst("X_LOWER" + postfix, xLower[d]);
            (*cit)->DefineConst("X_lower" + postfix, xLower[d]);
            (*cit)->DefineConst("x_lower" + postfix, xLower[d]);
            (*cit)->DefineConst("x_LOWER" + postfix, xLower[d]);
            (*cit)->DefineConst("X_Lower" + postfix, xLower[d]);
            (*cit)->DefineConst("X_lower" + postfix, xLower[d]);
            (*cit)->DefineConst("XLower" + postfix, xLower[d]);
            (*cit)->DefineConst("Xlower" + postfix, xLower[d]);
            (*cit)->DefineConst("x_Lower" + postfix, xLower[d]);
            (*cit)->DefineConst("x_lower" + postfix, xLower[d]);
            (*cit)->DefineConst("xLower" + postfix, xLower[d]);
            (*cit)->DefineConst("xlower" + postfix, xLower[d]);

            (*cit)->DefineConst("X_LOWER_" + postfix, xLower[d]);
            (*cit)->DefineConst("X_lower_" + postfix, xLower[d]);
            (*cit)->DefineConst("x_lower_" + postfix, xLower[d]);
            (*cit)->DefineConst("x_LOWER_" + postfix, xLower[d]);
            (*cit)->DefineConst("X_Lower_" + postfix, xLower[d]);
            (*cit)->DefineConst("X_lower_" + postfix, xLower[d]);
            (*cit)->DefineConst("XLower_" + postfix, xLower[d]);
            (*cit)->DefineConst("Xlower_" + postfix, xLower[d]);
            (*cit)->DefineConst("x_Lower_" + postfix, xLower[d]);
            (*cit)->DefineConst("x_lower_" + postfix, xLower[d]);
            (*cit)->DefineConst("xLower_" + postfix, xLower[d]);
            (*cit)->DefineConst("xlower_" + postfix, xLower[d]);

            (*cit)->DefineConst("X_UPPER" + postfix, xUpper[d]);
            (*cit)->DefineConst("X_upper" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_upper" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_UPPER" + postfix, xUpper[d]);
            (*cit)->DefineConst("X_Upper" + postfix, xUpper[d]);
            (*cit)->DefineConst("X_upper" + postfix, xUpper[d]);
            (*cit)->DefineConst("XUpper" + postfix, xUpper[d]);
            (*cit)->DefineConst("Xupper" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_Upper" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_upper" + postfix, xUpper[d]);
            (*cit)->DefineConst("xUpper" + postfix, xUpper[d]);
            (*cit)->DefineConst("xupper" + postfix, xUpper[d]);

            (*cit)->DefineConst("X_UPPER_" + postfix, xUpper[d]);
            (*cit)->DefineConst("X_upper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_upper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_UPPER_" + postfix, xUpper[d]);
            (*cit)->DefineConst("X_Upper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("X_upper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("XUpper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("Xupper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_Upper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("x_upper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("xUpper_" + postfix, xUpper[d]);
            (*cit)->DefineConst("xupper_" + postfix, xUpper[d]);
        }

        // User-provided constants.
        for (std::map<std::string, double>::const_iterator map_cit = d_constants.begin(); map_cit != d_constants.end();
             ++map_cit)
        {
            (*cit)->DefineConst(map_cit->first, map_cit->second);
        }

        // Variables.
        (*cit)->DefineVar("T", d_parser_time);
        (*cit)->DefineVar("t", d_parser_time);
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            std::ostringstream stream;
            stream << d;
            const std::string postfix = stream.str();
            (*cit)->DefineVar("X" + postfix, &d_parser_posn->data()[d]);
            (*cit)->DefineVar("x" + postfix, &d_parser_posn->data()[d]);
            (*cit)->DefineVar("X_" + postfix, &d_parser_posn->data()[d]);
            (*cit)->DefineVar("x_" + postfix, &d_parser_posn->data()[d]);
        }
    }
    return;
} // muParserRobinBcCoefs
Ejemplo n.º 8
0
/*
 ****************************************************************
 * Advance one communication Member by using MPI_Waitany
 * to complete one requests.
 *
 * Get one completed request and check its communication Member to see
 * if the Member finished its communication operation.  If it finished
 * its operation, return the member.  If not, repeat until one Member
 * has completed its communication operation.
 ****************************************************************
 */
bool
AsyncCommStage::advanceAny()
{
   if (!SAMRAI_MPI::usingMPI()) {
      return false;
   }

#ifdef DEBUG_CHECK_ASSERTIONS
   for (unsigned int i = static_cast<unsigned int>(d_member_to_req[d_members.size()]);
        i < d_req.size();
        ++i) {
      if (d_req[i] != MPI_REQUEST_NULL)
         TBOX_WARNING("non-null request above d_n_reg." << std::endl);
   }
#endif

   int ireq = MPI_UNDEFINED;
   int member_index_on_stage = -1;
   bool member_done;

   do {

      SAMRAI_MPI::Status mpi_stat;
      int errf;
      if (d_communication_timer) d_communication_timer->start();
      errf = SAMRAI_MPI::Waitany(
            static_cast<int>(d_member_to_req[d_members.size()]),
            &d_req[0],
            &ireq,
            &mpi_stat);
      if (d_communication_timer) d_communication_timer->stop();
      if (errf != MPI_SUCCESS) {
         TBOX_ERROR("Error in MPI_Waitany call.\n"
            << "Error-in-status is "
            << (errf == MPI_ERR_IN_STATUS) << '\n'
            << "MPI_ERROR value is " << mpi_stat.MPI_ERROR
            << '\n');
      }

      if (ireq == MPI_UNDEFINED) {
         // All input requests are completed even before waiting.
         break;
      }

      TBOX_ASSERT(ireq >= 0 &&
         ireq < static_cast<int>(d_member_to_req[d_members.size()]));

      d_stat[ireq] = mpi_stat;
      member_index_on_stage = static_cast<int>(d_req_to_member[ireq]);

      TBOX_ASSERT(member_index_on_stage >= 0 &&
         member_index_on_stage < static_cast<int>(d_members.size()));
      TBOX_ASSERT(d_members[member_index_on_stage] != 0);

      Member* member = d_members[member_index_on_stage];
      /*
       * Member member_index_on_stage had a request completed.
       * See if all of its requests are now completed.
       * If so, run proceedToNextWait() to see if the member is done.
       * (The member may not be done because it may initiate
       * follow-up communication tasks.)
       * Exit the do loop when a Member is actually done
       * with all of its communication tasks.
       */
      const size_t init_req = d_member_to_req[member->d_index_on_stage];
      const size_t term_req = d_member_to_req[member->d_index_on_stage + 1];
      size_t i;
      for (i = init_req; i < term_req; ++i) {
         if (d_req[i] != MPI_REQUEST_NULL) {
            break;
         }
      }
      if (i == term_req) {
         /*
          * Member is done with at least its current communication
          * requests.  Follow-up communication may be launched,
          * so check the return value of proceedToNextWait().
          */
         member_done = d_members[member_index_on_stage]->proceedToNextWait();
      } else {
         member_done = false;
         TBOX_ASSERT(d_members[member_index_on_stage]->hasPendingRequests());
      }

   } while (member_done == false);

   if (member_index_on_stage >= 0) {
      privatePushToCompletionQueue(*d_members[member_index_on_stage]);
   }

   return !d_completed_members.empty();
}
Ejemplo n.º 9
0
/*
 ******************************************************************
 * Advance one or more communication Members by using
 * MPI_Waitsome to complete one or more communication requests.
 *
 * Get one or more completed requests and check their communication
 * Members to see if any Member finished its communication operation.
 * If at least one Member finished its communication, return those that
 * finished.  If no Member has finished, repeat until at least one has.
 ******************************************************************
 */
bool
AsyncCommStage::advanceSome()
{
   if (!SAMRAI_MPI::usingMPI()) {
      return false;
   }

   if (d_members.empty()) {
      // Short cut for an empty stage.
      return false;
   }

#ifdef DEBUG_CHECK_ASSERTIONS
   for (unsigned int i = static_cast<unsigned int>(d_member_to_req[d_members.size()]);
        i < d_req.size();
        ++i) {
      if (d_req[i] != MPI_REQUEST_NULL)
         TBOX_WARNING("non-null request above d_n_req." << std::endl);
   }
#endif

   std::vector<int> index(static_cast<int>(d_member_to_req[d_members.size()]));
   std::vector<SAMRAI_MPI::Status> stat(
      static_cast<int>(d_member_to_req[d_members.size()]));

   size_t n_member_completed = 0;
   int n_req_completed = 0;

   do {

      int errf;
      if (d_communication_timer) d_communication_timer->start();
      errf = SAMRAI_MPI::Waitsome(
            static_cast<int>(d_member_to_req[d_members.size()]),
            &d_req[0],
            &n_req_completed,
            &index[0],
            &stat[0]);
      if (d_communication_timer) d_communication_timer->stop();
#ifdef DEBUG_CHECK_ASSERTIONS
      if (n_req_completed <= 0) {
         /*
          * Undocumented feature of some MPI_Waitsome implementations:
          * MPI_Waitsome sets n_req_completed to a negative number
          * if all the input requests are MPI_REQUEST_NULL.
          */
         for (size_t i = 0; i < d_member_to_req[d_members.size()]; ++i) {
            if (d_req[i] != MPI_REQUEST_NULL) {
               TBOX_ERROR("Library error in AsyncCommStage::advanceSome:\n"
                  << "errf = " << errf << '\n'
                  << "MPI_SUCCESS = " << MPI_SUCCESS << '\n'
                  << "MPI_ERR_IN_STATUS = " << MPI_ERR_IN_STATUS << '\n'
                  << "MPI_REQUEST_NULL = " << MPI_REQUEST_NULL << '\n'
                  << "number of requests = "
                  << d_member_to_req[d_members.size()] << '\n'
                  << "d_req.size() = " << d_req.size() << '\n'
                  << "n_req_completed = " << n_req_completed << '\n'
                  << "i = " << i << '\n'
                  );
            }
         }
         for (unsigned int i = static_cast<unsigned int>(d_member_to_req[d_members.size()]);
              i < d_req.size();
              ++i) {
            if (d_req[i] != MPI_REQUEST_NULL)
               TBOX_WARNING("non-null request above d_n_reg." << std::endl);
         }
      }
      if (n_req_completed == 0) {
         TBOX_ASSERT(!hasPendingRequests());
      }
#endif
      if (errf != MPI_SUCCESS) {
         TBOX_ERROR("Error in MPI_Waitsome call.\n"
            << "Error-in-status is "
            << (errf == MPI_ERR_IN_STATUS)
            << '\n');
      }

      /*
       * Construct array of Members with at least one completed
       * request.
       */
      // Number of Members to check with at least one completed request.
      unsigned int n_check_member = 0;

      for (int iout = 0; iout < n_req_completed; ++iout) {

         // Save status of completed request.
         d_stat[index[iout]] = stat[iout];
         /*
          * Change index from request index to Member index.
          * If the Member index is not a duplicate, add it to
          * the list of Members to check (which is actually
          * the same list) and increase n_check_member.
          */
         index[iout] = static_cast<int>(d_req_to_member[index[iout]]);
#ifdef AsyncCommStage_ExtraDebug
         plog << "AsyncCommStage::advanceSome completed:"
              << " tag-" << stat[iout].MPI_TAG
              << " source-" << stat[iout].MPI_SOURCE
              << " for member index " << index[iout]
              << std::endl;
#endif
         unsigned int i;
         for (i = 0; i < n_check_member; ++i) {
            if (index[i] == index[iout]) break;
         }
         if (i == n_check_member) {
            index[n_check_member++] = index[iout];
         }
      }

      /*
       * Check the Members whose requests completed and count up the
       * Members that completed all their communication tasks.
       */
      for (unsigned int imember = 0; imember < n_check_member; ++imember) {
         Member& memberi = *d_members[index[imember]];
         TBOX_ASSERT(!memberi.isDone());
         bool memberi_done = memberi.proceedToNextWait();
#ifdef AsyncCommStage_ExtraDebug
         plog
         << "AsyncCommStage::advanceSome proceedToNextWait for member:"
         << memberi.d_index_on_stage
         << " completion=" << memberi_done
         << std::endl;
#endif
         if (memberi_done) {
            ++n_member_completed;
            TBOX_ASSERT(!memberi.hasPendingRequests());
            privatePushToCompletionQueue(memberi);
         }
      }

   } while (n_req_completed > 0 && n_member_completed == 0);

   return !d_completed_members.empty();
}