//============================================================================== int Ifpack_AMDReordering::Compute(const Ifpack_Graph& Graph) { using std::cout; using std::endl; IsComputed_ = false; NumMyRows_ = Graph.NumMyRows(); int NumNz = Graph.NumMyNonzeros(); if (NumMyRows_ == 0) IFPACK_CHK_ERR(-1); // strange graph this one // Extract CRS format std::vector<int> ia(NumMyRows_+1,0); std::vector<int> ja(NumNz); int cnt; for( int i = 0; i < NumMyRows_; ++i ) { int * tmpP = &ja[ia[i]]; Graph.ExtractMyRowCopy( i, NumNz-ia[i], cnt, tmpP ); ia[i+1] = ia[i] + cnt; } // Trim down to local only std::vector<int> iat(NumMyRows_+1); std::vector<int> jat(NumNz); int loc = 0; for( int i = 0; i < NumMyRows_; ++i ) { iat[i] = loc; for( int j = ia[i]; j < ia[i+1]; ++j ) { if( ja[j] < NumMyRows_ ) jat[loc++] = ja[j]; else break; } } iat[NumMyRows_] = loc; // Compute AMD permutation Reorder_.resize(NumMyRows_); std::vector<double> info(AMD_INFO); trilinos_amd_order( NumMyRows_, &iat[0], &jat[0], &Reorder_[0], NULL, &info[0] ); if( info[AMD_STATUS] == AMD_INVALID ) cout << "AMD ORDERING: Invalid!!!!" << endl; // Build inverse reorder (will be used by ExtractMyRowCopy() InvReorder_.resize(NumMyRows_); for (int i = 0 ; i < NumMyRows_ ; ++i) InvReorder_[i] = -1; for (int i = 0 ; i < NumMyRows_ ; ++i) InvReorder_[Reorder_[i]] = i; for (int i = 0 ; i < NumMyRows_ ; ++i) { if (InvReorder_[i] == -1) IFPACK_CHK_ERR(-1); } IsComputed_ = true; return(0); }
//============================================================================== int Ifpack_RCMReordering::Compute(const Ifpack_Graph& Graph) { IsComputed_ = false; NumMyRows_ = Graph.NumMyRows(); if ((RootNode_ < 0) || (RootNode_ >= NumMyRows_)) RootNode_ = 0; Reorder_.resize(NumMyRows_); // the case where one processor holds no chunk of the graph happens... if (!NumMyRows_) { InvReorder_.resize(NumMyRows_); IsComputed_ = true; return(0); } for (int i = 0 ; i < NumMyRows_ ; ++i) Reorder_[i] = -1; std::vector<int> tmp; tmp.push_back(RootNode_); int count = NumMyRows_ - 1; int Length = Graph.MaxMyNumEntries(); std::vector<int> Indices(Length); Reorder_[RootNode_] = count; count--; // stop when no nodes have been added in the previous level while (tmp.size()) { std::vector<int> tmp2; // for each node in the previous level, look for non-marked // neighbors. for (int i = 0 ; i < (int)tmp.size() ; ++i) { int NumEntries; IFPACK_CHK_ERR(Graph.ExtractMyRowCopy(tmp[i], Length, NumEntries, &Indices[0])); if (Length > 1) std::sort(Indices.begin(), Indices.begin() + Length); for (int j = 0 ; j < NumEntries ; ++j) { int col = Indices[j]; if (col >= NumMyRows_) continue; if (Reorder_[col] == -1) { Reorder_[col] = count; count--; if (col != tmp[i]) { tmp2.push_back(col); } } } } // if no nodes have been found but we still have // rows to walk through, to localize the next -1 // and restart. // FIXME: I can replace with STL if ((tmp2.size() == 0) && (count != -1)) { for (int i = 0 ; i < NumMyRows_ ; ++i) if (Reorder_[i] == -1) { tmp2.push_back(i); Reorder_[i] = count--; break; } } // prepare for the next level tmp = tmp2; } // check nothing went wrong for (int i = 0 ; i < NumMyRows_ ; ++i) { if (Reorder_[i] == -1) IFPACK_CHK_ERR(-1); } // build inverse reorder (will be used by ExtractMyRowCopy() InvReorder_.resize(NumMyRows_); for (int i = 0 ; i < NumMyRows_ ; ++i) InvReorder_[i] = -1; for (int i = 0 ; i < NumMyRows_ ; ++i) InvReorder_[Reorder_[i]] = i; for (int i = 0 ; i < NumMyRows_ ; ++i) { if (InvReorder_[i] == -1) IFPACK_CHK_ERR(-1); } IsComputed_ = true; return(0); }