コード例 #1
0
  void createBasicVector(
    std::vector<const scalar_t *> &entries,  std::vector<int> &entryStride,
    std::vector<const scalar_t *> &weights, std::vector<int> &weightStrides)
  {
    typedef StridedData<lno_t,scalar_t> input_t;

    if (numIds_){
      int stride = 1;
      entries_ = arcp(new input_t[numEntriesPerID_], 0, numEntriesPerID_, true);
      for (int v=0; v < numEntriesPerID_; v++) {
        if (entryStride.size()) stride = entryStride[v];
        ArrayRCP<const scalar_t> eltV(entries[v], 0, stride*numIds_, false);
        entries_[v] = input_t(eltV, stride);
      }
    }

    if (numWeights_) {
      int stride = 1;
      weights_ = arcp(new input_t [numWeights_], 0, numWeights_, true);
      for (int w=0; w < numWeights_; w++){
        if (weightStrides.size()) stride = weightStrides[w];
        ArrayRCP<const scalar_t> wgtV(weights[w], 0, stride*numIds_, false);
        weights_[w] = input_t(wgtV, stride);
      }
    }
  }
コード例 #2
0
  void PartitioningProblem<Adapter>::initializeProblem()
{
  HELLO;

  this->env_->debug(DETAILED_STATUS, "PartitioningProblem::initializeProblem");

  if (getenv("DEBUGME")){
#ifndef _WIN32
    std::cout << getpid() << std::endl;
    sleep(15);
#else
    std::cout << _getpid() << std::endl;
    Sleep(15000);
#endif
  }

#ifdef HAVE_ZOLTAN2_OVIS
  ovis_enabled(this->comm_->getRank());
#endif

  // Create a copy of the user's communicator.  

  problemComm_ = this->comm_->duplicate();
  problemCommConst_ = rcp_const_cast<const Comm<int> > (problemComm_);

  machine_ = RCP <Zoltan2::MachineRepresentation<typename Adapter::scalar_t> >(new Zoltan2::MachineRepresentation<typename Adapter::scalar_t>(problemComm_));

  // Number of criteria is number of user supplied weights if non-zero.
  // Otherwise it is 1 and uniform weight is implied.

  numberOfWeights_ = this->inputAdapter_->getNumWeightsPerID();

  numberOfCriteria_ = (numberOfWeights_ > 1) ? numberOfWeights_ : 1;

  inputType_ = this->inputAdapter_->adapterType();

  // The Caller can specify part sizes in setPartSizes().  If he/she
  // does not, the part size arrays are empty.

  ArrayRCP<part_t> *noIds = new ArrayRCP<part_t> [numberOfCriteria_];
  ArrayRCP<scalar_t> *noSizes = new ArrayRCP<scalar_t> [numberOfCriteria_];

  partIds_ = arcp(noIds, 0, numberOfCriteria_, true);
  partSizes_ = arcp(noSizes, 0, numberOfCriteria_, true);

  if (this->env_->getDebugLevel() >= DETAILED_STATUS){
    std::ostringstream msg;
    msg << problemComm_->getSize() << " procs,"
      << numberOfWeights_ << " user-defined weights\n";
    this->env_->debug(DETAILED_STATUS, msg.str());
  }

  this->env_->memory("After initializeProblem");
}
コード例 #3
0
  void GidLookupHelper<T, lno_t>::getIndices(
    ArrayRCP<lno_t> &indices) const
{
  lno_t numIds = size();
  lno_t *idx = new lno_t [numIds];
  ArrayRCP<lno_t> indexList = arcp(idx, 0, numIds, true);

  if (numIds == gidList_.size()){
    for (lno_t i=0; i < gidList_.size(); i++){
       *idx++ = i;
    }
  }
  else{
    const T *ids = gidList_.getRawPtr();
    set<T> allGids;

    for (lno_t i=0; i < gidList_.size(); i++){
      typename set<T>::iterator rec = allGids.find(ids[i]);
      if (rec == allGids.end()){
        allGids.insert(ids[i]);
        *idx++ = i;
      }
    }
  }

  indices = indexList;
}
コード例 #4
0
  IdentifierModel<Adapter>::IdentifierModel( 
    const RCP<const Adapter> &ia,
    const RCP<const Environment> &env,
    const RCP<const Comm<int> > &comm,
    modelFlag_t &modelFlags):
      numGlobalIdentifiers_(), env_(env), comm_(comm),
      gids_(), nUserWeights_(0), weights_()
{
  // Get the local and global problem size
  size_t nLocalIds = ia->getLocalNumIDs();
  gno_t lsum = nLocalIds;
  reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_SUM, 1, &lsum,
    &numGlobalIdentifiers_);

  // Get the number of weights
  // Use max number of weights over all processes as nUserWeights_
  int tmp = ia->getNumWeightsPerID();
  Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, 1,
      &tmp, &nUserWeights_);

  // Prepare to store views from input adapter
  // TODO:  Do we have to store these views, or can we get them on an 
  // TODO:  as-needed basis?
  Array<const scalar_t *> wgts(nUserWeights_, (const scalar_t *)NULL);
  Array<int> wgtStrides(nUserWeights_, 0);

  if (nUserWeights_ > 0){
    input_t *w = new input_t [nUserWeights_];
    weights_ = arcp<input_t>(w, 0, nUserWeights_);
  }

  const gno_t *gids=NULL;
  
  // Get the input adapter's views
  try{
    ia->getIDsView(gids);
    for (int idx=0; idx < nUserWeights_; idx++)
      ia->getWeightsView(wgts[idx], wgtStrides[idx], idx);
  }
  Z2_FORWARD_EXCEPTIONS;

  if (nLocalIds){
    gids_ = arcp(gids, 0, nLocalIds, false);

    if (nUserWeights_ > 0){
      for (int idx=0; idx < nUserWeights_; idx++){
        ArrayRCP<const scalar_t> wgtArray(wgts[idx], 0,
                                          nLocalIds*wgtStrides[idx], false);
        weights_[idx] = input_t(wgtArray, wgtStrides[idx]);
      }
    }
  }

  env_->memory("After construction of identifier model");
}
コード例 #5
0
  void PartitioningProblem<Adapter>::setPartSizesForCriteria(
    int criteria, int len, part_t *partIds, scalar_t *partSizes, bool makeCopy) 
{
  this->env_->localInputAssertion(__FILE__, __LINE__, "invalid length", 
    len>= 0, BASIC_ASSERTION);

  this->env_->localInputAssertion(__FILE__, __LINE__, "invalid criteria", 
    criteria >= 0 && criteria < numberOfCriteria_, BASIC_ASSERTION);

  if (len == 0){
    partIds_[criteria] = ArrayRCP<part_t>();
    partSizes_[criteria] = ArrayRCP<scalar_t>();
    return;
  }

  this->env_->localInputAssertion(__FILE__, __LINE__, "invalid arrays", 
    partIds && partSizes, BASIC_ASSERTION);

  // The global validity of the partIds and partSizes arrays is performed
  // by the PartitioningSolution, which computes global part distribution and
  // part sizes.

  part_t *z2_partIds = NULL;
  scalar_t *z2_partSizes = NULL;
  bool own_memory = false;

  if (makeCopy){
    z2_partIds = new part_t [len];
    z2_partSizes = new scalar_t [len];
    this->env_->localMemoryAssertion(__FILE__, __LINE__, len, z2_partSizes);
    memcpy(z2_partIds, partIds, len * sizeof(part_t));
    memcpy(z2_partSizes, partSizes, len * sizeof(scalar_t));
    own_memory=true;
  }
  else{
    z2_partIds = partIds;
    z2_partSizes = partSizes;
  }

  partIds_[criteria] = arcp(z2_partIds, 0, len, own_memory);
  partSizes_[criteria] = arcp(z2_partSizes, 0, len, own_memory);
}
コード例 #6
0
  /*! \brief Get the parts belonging to this rank
   *  \param numParts on return, set to the number of parts assigned to rank.
   *  \param parts on return, pointer (view) to the parts assigned to rank
   */
  void getMyPartsView(part_t &numParts, part_t *&parts)
  {
    bool useAlg = true;

    // Check first whether this algorithm answers getMyPartsView.
    if (mapping_algorithm != Teuchos::null) {
      try {
        mapping_algorithm->getMyPartsView(numParts, parts);
      }
      catch (NotImplemented &e) {
        // It is OK if the algorithm did not implement this method;
        // we'll get the information from the solution below.
        useAlg = false;
      }
      Z2_FORWARD_EXCEPTIONS;
    }

    if (!useAlg) {  

      // Algorithm did not implement this method.

      // Did the algorithm register a result with the solution?
      if ((partsForRank==Teuchos::null) && (rankForPart==Teuchos::null)) {
        numParts = 0;
        parts = NULL;
        throw std::runtime_error("No mapping solution available.");
      }
  
      if (partsForRank == Teuchos::null) {
        // Need to create the array since we haven't created it before.
        Teuchos::Array<part_t> tmp;

        part_t cnt = 0;
        for (typename rankmap_t::iterator it = rankForPart->begin();
             it != rankForPart->end(); it++) {
          if (it->second == myRank) {
            tmp.push_back(it->first); 
            cnt++;
          }
        }
        if (cnt)
          partsForRank = arcp(&tmp[0], 0, cnt, true);
      }

      numParts = partsForRank.size();
      if (numParts)
        parts = partsForRank.getRawPtr();
      else 
        parts = NULL;
    }
  }
コード例 #7
0
  BasicIdentifierAdapter<User>::BasicIdentifierAdapter(
    lno_t numIds, const gno_t *idPtr,
    std::vector<const scalar_t *> &weights, std::vector<int> &weightStrides):
      numIds_(numIds), idList_(idPtr), weights_()
{
  typedef StridedData<lno_t,scalar_t> input_t;
  size_t numWeights = weights.size();

  if (numWeights > 0){
    weights_ = arcp(new input_t [numWeights], 0, numWeights, true);

    if (numIds > 0){
      for (size_t i=0; i < numWeights; i++){
        int stride = weightStrides.size() ? weightStrides[i] : 1;
        ArrayRCP<const scalar_t> wgtV(weights[i], 0, stride*numIds, false);
        weights_[i] = input_t(wgtV, stride);
      }
    }
  }
}
コード例 #8
0
  ArrayRCP<std::string> GetFileList(const std::string & dirPath, const std::string & filter) {

    RCP<std::vector<std::string> > files = rcp(new std::vector<std::string>());

    DIR *dir;
    struct dirent *dirEntry;

    dir = opendir(dirPath.c_str());
    TEUCHOS_TEST_FOR_EXCEPTION(dir == NULL, MueLu::Exceptions::RuntimeError, "GetFileList(\"" + dirPath + "\") : " + strerror(errno));

    while ((dirEntry = readdir(dir)) != NULL) {
      std::string dirEntryS(dirEntry->d_name);

      if (dirEntryS.rfind(filter) != string::npos)
        files->push_back(std::string(dirEntryS));
    }

    closedir(dir);

    return arcp(files);
  }
コード例 #9
0
  IdentifierModel<IdentifierInput<User> >::IdentifierModel( 
    const IdentifierInput<User> *ia,
    const RCP<const Environment> &env, const RCP<const Comm<int> > &comm,
    modelFlag_t &modelFlags):
      gnosAreGids_(false), numGlobalIdentifiers_(), env_(env), comm_(comm),
      gids_(), userWeightDim_(0), weights_(), gnos_(), gnosConst_()
{
  userWeightDim_ = ia->getNumberOfWeights();
  size_t nLocalIds = ia->getLocalNumberOfIdentifiers();

  Model<IdentifierInput<User> >::maxCount(*comm, userWeightDim_);

  Array<const scalar_t *> wgts(userWeightDim_, (const scalar_t *)NULL);
  Array<int> wgtStrides(userWeightDim_, 0);
  Array<lno_t> weightArrayLengths(userWeightDim_, 0);

  if (userWeightDim_ > 0){
    input_t *w = new input_t [userWeightDim_];
    weights_ = arcp<input_t>(w, 0, userWeightDim_);
  }

  const gid_t *gids=NULL;

  try{
    ia->getIdentifierList(gids);
    for (int dim=0; dim < userWeightDim_; dim++)
      ia->getIdentifierWeights(dim, wgts[dim], wgtStrides[dim]);
  }
  Z2_FORWARD_EXCEPTIONS;

  if (nLocalIds){
    gids_ = arcp(gids, 0, nLocalIds, false);

    if (userWeightDim_ > 0){
      for (int i=0; i < userWeightDim_; i++){
        if (wgts[i] != NULL){
          ArrayRCP<const scalar_t> wgtArray(
            wgts[i], 0, nLocalIds*wgtStrides[i], false);
          weights_[i] = input_t(wgtArray, wgtStrides[i]);
          weightArrayLengths[i] = nLocalIds;
        }
      }
    }
  }

  this->setWeightArrayLengths(weightArrayLengths, *comm_);

  RCP<const idmap_t> idMap;

  try{
    if (modelFlags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE))
      idMap = rcp(new idmap_t(env_, comm_, gids_, true));
    else
      idMap = rcp(new idmap_t(env_, comm_, gids_, false));
  }
  Z2_FORWARD_EXCEPTIONS;

  gnosAreGids_ = idMap->gnosAreGids();

  this->setIdentifierMap(idMap);

  gno_t lsum = nLocalIds;
  reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_SUM, 1, &lsum,
    &numGlobalIdentifiers_);

  if (!gnosAreGids_ && nLocalIds>0){
    gno_t *tmpGno = new gno_t [nLocalIds];
    env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno);
    gnos_ = arcp(tmpGno, 0, nLocalIds);

    try{
      ArrayRCP<gid_t> gidsNonConst = arcp_const_cast<gid_t>(gids_);
      idMap->gidTranslate( gidsNonConst(0,nLocalIds),  gnos_(0,nLocalIds),
        TRANSLATE_APP_TO_LIB);
    }
    Z2_FORWARD_EXCEPTIONS;
  }
コード例 #10
0
size_t computeLocalEdgeList(
  const RCP<const Environment> &env, const RCP<const Comm<int> > &comm,
  size_t numLocalEdges,           // local edges
  size_t numLocalGraphEdges,      // edges in "local" graph
  RCP<const IdentifierMap<User> > &idMap,
  ArrayRCP<const typename InputTraits<User>::zgid_t> &allEdgeIds, // in
  ArrayRCP<const typename InputTraits<User>::gno_t> &allEdgeGnos, // in
  ArrayRCP<int> &allProcs,                                 // in
  ArrayRCP<const typename InputTraits<User>::lno_t> &allOffs,    // in
  ArrayRCP<StridedData<typename InputTraits<User>::lno_t,
                       typename InputTraits<User>::scalar_t> > &allWeights,// in
  ArrayRCP<const typename InputTraits<User>::lno_t> &edgeLocalIds, //
  ArrayRCP<const typename InputTraits<User>::lno_t> &offsets,      // out
  ArrayRCP<StridedData<typename InputTraits<User>::lno_t,
    typename InputTraits<User>::scalar_t> > &eWeights)             // out
{
  typedef typename InputTraits<User>::zgid_t zgid_t;
  typedef typename InputTraits<User>::gno_t gno_t;
  typedef typename InputTraits<User>::scalar_t scalar_t;
  typedef typename InputTraits<User>::lno_t lno_t;
  typedef StridedData<lno_t, scalar_t> input_t;
  int rank = comm->getRank();

  bool gnosAreGids = idMap->gnosAreGids();

  edgeLocalIds = ArrayRCP<const lno_t>(Teuchos::null);
  eWeights = ArrayRCP<input_t>(Teuchos::null);
  offsets = ArrayRCP<const lno_t>(Teuchos::null);

  if (numLocalGraphEdges == 0) {
    // Set the offsets array and return
    size_t allOffsSize = allOffs.size();
    lno_t *offs = new lno_t [allOffsSize];
    env->localMemoryAssertion(__FILE__, __LINE__, allOffsSize, offs);
    for (size_t i = 0; i < allOffsSize; i++) offs[i] = 0;
    offsets = arcp(offs, 0, allOffsSize, true);
    return 0;
  }

  if (numLocalGraphEdges == numLocalEdges){

    // Entire graph is local.

    lno_t *lnos = new lno_t [numLocalGraphEdges];
    env->localMemoryAssertion(__FILE__, __LINE__, numLocalGraphEdges, lnos);
    if (comm->getSize() == 1) {
      // With one rank, Can use gnos as local index.
      if (gnosAreGids)
        for (size_t i=0; i < numLocalEdges; i++) lnos[i] = allEdgeIds[i];
      else
        for (size_t i=0; i < numLocalEdges; i++) lnos[i] = allEdgeGnos[i];
    }
    else {
      ArrayRCP<gno_t> gnoArray;

      if (gnosAreGids){
        ArrayRCP<const gno_t> gnosConst =
                 arcp_reinterpret_cast<const gno_t>(allEdgeIds);
        gnoArray = arcp_const_cast<gno_t>(gnosConst);
      }
      else {
        gnoArray = arcp_const_cast<gno_t>(allEdgeGnos);
      }

      // Need to translate to gnos to local indexing
      ArrayView<lno_t> lnoView(lnos, numLocalGraphEdges);
      try {
        idMap->lnoTranslate(lnoView,
                            gnoArray.view(0,numLocalGraphEdges),
                            TRANSLATE_LIB_TO_APP);
      }
      Z2_FORWARD_EXCEPTIONS;
    }
    edgeLocalIds = arcp(lnos, 0, numLocalGraphEdges, true);
    offsets = allOffs;
    eWeights = allWeights;

  }
コード例 #11
0
size_t removeUndesiredEdges(
  const RCP<const Environment> &env,
  int myRank,
  bool removeSelfEdges,
  bool removeOffProcessEdges,
  bool removeOffGroupEdges,
  ArrayView<const typename InputTraits<User>::zgid_t> &gids,
  ArrayView<const typename InputTraits<User>::zgid_t> &gidNbors,
  ArrayView<const int> &procIds,
  ArrayView<StridedData<typename InputTraits<User>::lno_t,
                        typename InputTraits<User>::scalar_t> > &edgeWeights,
  ArrayView<const typename InputTraits<User>::lno_t> &offsets,
  ArrayRCP<const typename InputTraits<User>::zgid_t> &newGidNbors, // out
  typename InputTraits<User>::scalar_t **&newWeights,             // out
  ArrayRCP<const typename InputTraits<User>::lno_t> &newOffsets)  // out
{
  typedef typename InputTraits<User>::zgid_t zgid_t;
  typedef typename InputTraits<User>::scalar_t scalar_t;
  typedef typename InputTraits<User>::lno_t lno_t;
  size_t numKeep = 0;

  size_t numVtx = offsets.size() - 1;
  size_t numNbors = gidNbors.size();

  env->localInputAssertion(__FILE__, __LINE__, "need more input",
    (!removeSelfEdges ||
      gids.size() >=
       static_cast<typename ArrayView<const zgid_t>::size_type>(numVtx))
      &&
    (!removeOffProcessEdges ||
      procIds.size() >=
       static_cast<typename ArrayView<const int>::size_type>(numNbors)) &&
    (!removeOffGroupEdges ||
      procIds.size() >=
       static_cast<typename ArrayView<const int>::size_type>(numNbors)),
    BASIC_ASSERTION);

  // initialize edge weight array

  newWeights = NULL;
  int eDim = edgeWeights.size();

  // count desired edges

  lno_t *offs = new lno_t [numVtx + 1];
  env->localMemoryAssertion(__FILE__, __LINE__, numVtx+1, offs);
  for (size_t i = 0; i < numVtx+1; i++) offs[i] = 0;
  ArrayRCP<const lno_t> offArray = arcp(offs, 0, numVtx+1, true);

  const lno_t *allOffs = offsets.getRawPtr();
  const zgid_t *allIds = gidNbors.getRawPtr();

  const zgid_t *vtx = NULL;
  const int *proc = NULL;

  if (gids.size() > 0)
    vtx = gids.getRawPtr();

  if (procIds.size() > 0)
    proc = procIds.getRawPtr();

  offs[0] = 0;
  for (size_t i=0; i < numVtx; i++){
    offs[i+1] = 0;
    zgid_t vid = vtx ? vtx[i] : zgid_t(0);
    for (lno_t j=allOffs[i]; j < allOffs[i+1]; j++){
      int owner = proc ? proc[j] : 0;
      bool keep = (!removeSelfEdges || vid != allIds[j]) &&
               (!removeOffProcessEdges || owner == myRank) &&
               (!removeOffGroupEdges || owner >= 0);

      if (keep)
        offs[i+1]++;
    }
  }

  // from counters to offsets

  for (size_t i=1; i < numVtx; i++)
    offs[i+1] += offs[i];

  numKeep = offs[numVtx];

  // do we need a new neighbor list?

  if (numNbors == numKeep){
    newGidNbors = Teuchos::arcpFromArrayView(gidNbors);
    newOffsets = Teuchos::arcpFromArrayView(offsets);
    return numNbors;
  }
  else if (numKeep == 0){
    newGidNbors = ArrayRCP<const zgid_t>(Teuchos::null);
    newOffsets = offArray;
    return 0;
  }

  // Build the subset neighbor lists (id, weight, and offset).

  zgid_t *newGids = new zgid_t [numKeep];
  env->localMemoryAssertion(__FILE__, __LINE__, numKeep, newGids);

  newGidNbors = arcp(newGids, 0, numKeep, true);
  newOffsets = offArray;

  if (eDim > 0){
    newWeights = new scalar_t * [eDim];
    env->localMemoryAssertion(__FILE__, __LINE__, eDim, newWeights);

    if (numKeep) {
      for (int w=0; w < eDim; w++){
        newWeights[w] = new scalar_t [numKeep];
        env->localMemoryAssertion(__FILE__, __LINE__, numKeep, newWeights[w]);
      }
    }
    else {
      for (int w=0; w < eDim; w++)
        newWeights[w] = NULL;
    }
  }

  size_t next = 0;
  for (size_t i=0; i < numVtx && next < numKeep; i++){
    zgid_t vid = vtx ? vtx[i] : zgid_t(0);
    for (lno_t j=allOffs[i]; j < allOffs[i+1]; j++){
      int owner = proc ? proc[j] : 0;
      bool keep = (!removeSelfEdges || vid != allIds[j]) &&
               (!removeOffProcessEdges || owner == myRank) &&
               (!removeOffGroupEdges || owner >= 0);

      if (keep){
        newGids[next] = allIds[j];
        for (int w=0; w < eDim; w++){
          newWeights[w][next] = edgeWeights[w][j];
        }
        next++;
        if (next == numKeep)
          break;

      }  // if (keep)
    }
  }

  return numKeep;
}
コード例 #12
0
 void resetValues(){
   scalar_t *tmp = new scalar_t [evalNumMetrics];
   memset(tmp, 0, sizeof(scalar_t) * evalNumMetrics);
   values_ = arcp(tmp, 0, evalNumMetrics, true);
 }
コード例 #13
0
  void globalSumsByPart( 
    const RCP<const Environment> &env,
    const RCP<const Comm<int> > &comm, 
    const ArrayView<const pnum_t> &part, 
    const ArrayView<StridedData<lno_t, scalar_t> > &vwgts,
    multiCriteriaNorm mcNorm,
    partId_t &numParts, 
    partId_t &numNonemptyParts,
    ArrayRCP<MetricValues<scalar_t> > &metrics,
    ArrayRCP<scalar_t> &globalSums)
{
  env->debug(DETAILED_STATUS, "Entering globalSumsByPart");
  //////////////////////////////////////////////////////////
  // Initialize return values

  numParts = numNonemptyParts = 0;

  int vwgtDim = vwgts.size();

  int numMetrics = 1;        // "object count"
  if (vwgts[0].size() > 0)
    numMetrics++;            // "normed weight" or "weight 1"
  if (vwgtDim > 1)
    numMetrics += vwgtDim;   // "weight n"

  typedef MetricValues<scalar_t> mv_t;
  mv_t *newMetrics = new mv_t [numMetrics];
  env->localMemoryAssertion(__FILE__, __LINE__, numMetrics, newMetrics); 
  ArrayRCP<mv_t> metricArray(newMetrics, 0, numMetrics, true);

  metrics = metricArray;

  //////////////////////////////////////////////////////////
  // Figure out the global number of parts in use.
  // Verify vertex weight dim is the same everywhere.

  lno_t localNumObj = part.size();
  partId_t localNum[2], globalNum[2];
  localNum[0] = static_cast<partId_t>(vwgtDim);  
  localNum[1] = 0;

  for (lno_t i=0; i < localNumObj; i++)
    if (part[i] > localNum[1]) localNum[1] = part[i];

  try{
    reduceAll<int, partId_t>(*comm, Teuchos::REDUCE_MAX, 2, 
      localNum, globalNum);
  }
  Z2_THROW_OUTSIDE_ERROR(*env)

  env->globalBugAssertion(__FILE__, __LINE__, "inconsistent vertex dimension",
    globalNum[0] > 0 && globalNum[0] == localNum[0], 
    DEBUG_MODE_ASSERTION, comm);

  partId_t nparts = globalNum[1] + 1;

  int globalSumSize = nparts * numMetrics;
  scalar_t * sumBuf = new scalar_t [globalSumSize];
  env->localMemoryAssertion(__FILE__, __LINE__, globalSumSize, sumBuf);
  globalSums = arcp(sumBuf, 0, globalSumSize);

  //////////////////////////////////////////////////////////
  // Calculate the local totals by part.

  scalar_t *localBuf = new scalar_t [globalSumSize];
  env->localMemoryAssertion(__FILE__, __LINE__, globalSumSize, localBuf);
  memset(localBuf, 0, sizeof(scalar_t) * globalSumSize);

  scalar_t *obj = localBuf;              // # of objects

  for (lno_t i=0; i < localNumObj; i++)
    obj[part[i]]++;

  if (numMetrics > 1){

    scalar_t *wgt = localBuf + nparts; // single normed weight
    try{
      normedPartWeights<scalar_t, pnum_t, lno_t>(env, nparts, 
        part, vwgts, mcNorm, wgt);
    }
    Z2_FORWARD_EXCEPTIONS
  
//KDDKDD TODO  This code assumes the solution has the part ordered the
//KDDKDD TODO  same way as the user input.  That assumption is not
//KDDKDD TODO  currently true, although we plan to make it true.
//KDDKDD TODO  As a results, currently the weight metrics may be wrong.
//KDDKDD TODO  See bug 5891.  April 5, 2013
    if (vwgtDim > 1){
      wgt += nparts;         // individual weights
      for (int vdim = 0; vdim < vwgtDim; vdim++){
        if (vwgts[vdim].size()){
         for (lno_t i=0; i < localNumObj; i++)
           wgt[part[i]] += vwgts[vdim][i];
        }
        else{  // uniform weights
          for (int p=0; p < nparts; p++)
            wgt[p] = obj[p];
        }
        wgt += nparts;
      }
    }
  }