//========================================================================== int Ifpack_CrsIct::InitValues(const Epetra_CrsMatrix & A) { int ierr = 0; int i, j; int NumIn, NumL, NumU; bool DiagFound; int NumNonzeroDiags = 0; Teuchos::RefCountPtr<Epetra_CrsMatrix> OverlapA = Teuchos::rcp( (Epetra_CrsMatrix *) &A_ , false ); if (LevelOverlap_>0) { EPETRA_CHK_ERR(-1); // Not implemented yet //OverlapA = new Epetra_CrsMatrix(Copy, *Graph_.OverlapGraph()); //EPETRA_CHK_ERR(OverlapA->Import(A, *Graph_.OverlapImporter(), Insert)); //EPETRA_CHK_ERR(OverlapA->FillComplete()); } // Get Maximun Row length int MaxNumEntries = OverlapA->MaxNumEntries(); vector<int> InI(MaxNumEntries); // Allocate temp space vector<int> UI(MaxNumEntries); vector<double> InV(MaxNumEntries); vector<double> UV(MaxNumEntries); double *DV; ierr = D_->ExtractView(&DV); // Get view of diagonal // First we copy the user's matrix into diagonal vector and U, regardless of fill level int NumRows = OverlapA->NumMyRows(); for (i=0; i< NumRows; i++) { OverlapA->ExtractMyRowCopy(i, MaxNumEntries, NumIn, &InV[0], &InI[0]); // Get Values and Indices // Split into L and U (we don't assume that indices are ordered). NumL = 0; NumU = 0; DiagFound = false; for (j=0; j< NumIn; j++) { int k = InI[j]; if (k==i) { DiagFound = true; DV[i] += Rthresh_ * InV[j] + EPETRA_SGN(InV[j]) * Athresh_; // Store perturbed diagonal in Epetra_Vector D_ } else if (k < 0) return(-1); // Out of range else if (i<k && k<NumRows) { UI[NumU] = k; UV[NumU] = InV[j]; NumU++; } } // Check in things for this row of L and U if (DiagFound) NumNonzeroDiags++; if (NumU) U_->InsertMyValues(i, NumU, &UV[0], &UI[0]); } U_->FillComplete(A_.OperatorDomainMap(), A_.OperatorRangeMap()); SetValuesInitialized(true); SetFactored(false); int ierr1 = 0; if (NumNonzeroDiags<U_->NumMyRows()) ierr1 = 1; A_.Comm().MaxAll(&ierr1, &ierr, 1); EPETRA_CHK_ERR(ierr); return(0); }
//============================================================================== // NOTE: // - matrix is supposed to be localized, and passes through the // singleton filter. This means that I do not have to look // for Dirichlet nodes (singletons). Also, all rows and columns are // local. int Ifpack_METISPartitioner::ComputePartitions() { int ierr; #ifdef HAVE_IFPACK_METIS int nbytes = 0; int edgecut; #endif Teuchos::RefCountPtr<Epetra_CrsGraph> SymGraph ; Teuchos::RefCountPtr<Epetra_Map> SymMap; Teuchos::RefCountPtr<Ifpack_Graph_Epetra_CrsGraph> SymIFPACKGraph; Teuchos::RefCountPtr<Ifpack_Graph> IFPACKGraph = Teuchos::rcp( (Ifpack_Graph*)Graph_, false ); int Length = 2 * MaxNumEntries(); int NumIndices; std::vector<int> Indices; Indices.resize(Length); /* construct the CSR graph information of the LOCAL matrix using the get_row function */ std::vector<idxtype> wgtflag; wgtflag.resize(4); std::vector<int> options; options.resize(4); int numflag; if (UseSymmetricGraph_) { #if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES) // need to build a symmetric graph. // I do this in two stages: // 1.- construct an Epetra_CrsMatrix, symmetric // 2.- convert the Epetra_CrsMatrix into METIS format SymMap = Teuchos::rcp( new Epetra_Map(NumMyRows(),0,Graph_->Comm()) ); SymGraph = Teuchos::rcp( new Epetra_CrsGraph(Copy,*SymMap,0) ); #endif #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES if(SymGraph->RowMap().GlobalIndicesInt()) { for (int i = 0; i < NumMyRows() ; ++i) { ierr = Graph_->ExtractMyRowCopy(i, Length, NumIndices, &Indices[0]); IFPACK_CHK_ERR(ierr); for (int j = 0 ; j < NumIndices ; ++j) { int jj = Indices[j]; if (jj != i) { SymGraph->InsertGlobalIndices(i,1,&jj); SymGraph->InsertGlobalIndices(jj,1,&i); } } } } else #endif #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES if(SymGraph->RowMap().GlobalIndicesLongLong()) { for (int i = 0; i < NumMyRows() ; ++i) { long long i_LL = i; ierr = Graph_->ExtractMyRowCopy(i, Length, NumIndices, &Indices[0]); IFPACK_CHK_ERR(ierr); for (int j = 0 ; j < NumIndices ; ++j) { long long jj = Indices[j]; if (jj != i_LL) { SymGraph->InsertGlobalIndices(i_LL,1,&jj); SymGraph->InsertGlobalIndices(jj,1,&i_LL); } } } } else #endif throw "Ifpack_METISPartitioner::ComputePartitions: GlobalIndices type unknown"; IFPACK_CHK_ERR(SymGraph->FillComplete()); SymIFPACKGraph = Teuchos::rcp( new Ifpack_Graph_Epetra_CrsGraph(SymGraph) ); IFPACKGraph = SymIFPACKGraph; } // now work on IFPACKGraph, that can be the symmetric or // the non-symmetric one /* set parameters */ wgtflag[0] = 0; /* no weights */ numflag = 0; /* C style */ options[0] = 0; /* default options */ std::vector<idxtype> xadj; xadj.resize(NumMyRows() + 1); std::vector<idxtype> adjncy; adjncy.resize(NumMyNonzeros()); int count = 0; int count2 = 0; xadj[0] = 0; for (int i = 0; i < NumMyRows() ; ++i) { xadj[count2+1] = xadj[count2]; /* nonzeros in row i-1 */ ierr = IFPACKGraph->ExtractMyRowCopy(i, Length, NumIndices, &Indices[0]); IFPACK_CHK_ERR(ierr); for (int j = 0 ; j < NumIndices ; ++j) { int jj = Indices[j]; if (jj != i) { adjncy[count++] = jj; xadj[count2+1]++; } } count2++; } std::vector<idxtype> NodesInSubgraph; NodesInSubgraph.resize(NumLocalParts_); // some cases can be handled separately int ok; if (NumLocalParts() == 1) { for (int i = 0 ; i < NumMyRows() ; ++i) Partition_[i] = 0; } else if (NumLocalParts() == NumMyRows()) { for (int i = 0 ; i < NumMyRows() ; ++i) Partition_[i] = i; } else { ok = 0; // sometimes METIS creates less partitions than specified. // ok will check this problem, and recall metis, asking // for NumLocalParts_/2 partitions while (ok == 0) { for (int i = 0 ; i < NumMyRows() ; ++i) Partition_[i] = -1; #ifdef HAVE_IFPACK_METIS int j = NumMyRows(); if (NumLocalParts_ < 8) { int i = 1; /* optype in the METIS manual */ numflag = 0; METIS_EstimateMemory(&j, &xadj[0], &adjncy[0], &numflag, &i, &nbytes ); METIS_PartGraphRecursive(&j, &xadj[0], &adjncy[0], NULL, NULL, &wgtflag[0], &numflag, &NumLocalParts_, &options[0], &edgecut, &Partition_[0]); } else { numflag = 0; METIS_PartGraphKway (&j, &xadj[0], &adjncy[0], NULL, NULL, &wgtflag[0], &numflag, &NumLocalParts_, &options[0], &edgecut, &Partition_[0]); } #else numflag = numflag * 2; // avoid warning for unused variable if (Graph_->Comm().MyPID() == 0) { cerr << "METIS was not linked; now I put all" << endl; cerr << "the local nodes in the same partition." << endl; } for (int i = 0 ; i < NumMyRows() ; ++i) Partition_[i] = 0; NumLocalParts_ = 1; #endif ok = 1; for (int i = 0 ; i < NumLocalParts() ; ++i) NodesInSubgraph[i] = 0; for (int i = 0 ; i < NumMyRows() ; ++i) { int j = Partition_[i]; if ((j < 0) || (j>= NumLocalParts())) { ok = 0; break; } else NodesInSubgraph[j]++; } for (int i = 0 ; i < NumLocalParts() ; ++i) { if( NodesInSubgraph[i] == 0 ) { ok = 0; break; } } if (ok == 0) { cerr << "Specified number of subgraphs (" << NumLocalParts_ << ") generates empty subgraphs." << endl; cerr << "Now I recall METIS with NumLocalParts_ = " << NumLocalParts_ / 2 << "..." << endl; NumLocalParts_ = NumLocalParts_/2; } if (NumLocalParts() == 0) { IFPACK_CHK_ERR(-10); // something went wrong } if (NumLocalParts() == 1) { for (int i = 0 ; i < NumMyRows() ; ++i) Partition_[i] = 0; ok = 1; } } /* while( ok == 0 ) */ } /* if( NumLocalParts_ == 1 ) */ return(0); }