TridiagonalCrsMatrix( const Epetra_Map & Map, double a, double diag, double c ) : Epetra_CrsMatrix(Copy,Map,3) { // global number of rows int NumGlobalElements = Map.NumGlobalElements(); // local number of rows int NumMyElements = Map.NumMyElements(); // get update list int * MyGlobalElements = new int [NumMyElements]; Map.MyGlobalElements( MyGlobalElements ); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 double *Values = new double[2]; Values[0] = a; Values[1] = c; int *Indices = new int[2]; int NumEntries; for( int i=0 ; i<NumMyElements; ++i ) { if (MyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (MyGlobalElements[i] == NumGlobalElements-1) { Indices[0] = NumGlobalElements-2; NumEntries = 1; } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; NumEntries = 2; } InsertGlobalValues(MyGlobalElements[i], NumEntries, Values, Indices); // Put in the diagonal entry InsertGlobalValues(MyGlobalElements[i], 1, &diag, MyGlobalElements+i); } // Finish up FillComplete(); delete [] MyGlobalElements; delete [] Values; delete [] Indices; }
int Epetra_FEVbrMatrix::GlobalAssemble(bool callFillComplete) { if(Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) { if(callFillComplete) { EPETRA_CHK_ERR(FillComplete()); } return(0); } int i; //In this method we need to gather all the non-local (overlapping) data //that's been input on each processor, into the //non-overlapping distribution defined by the map that 'this' matrix was //constructed with. //Need to build a map that describes our nonlocal data. //First, create a list of the sizes (point-rows per block-row) of the //nonlocal rows we're holding. int* pointRowsPerNonlocalBlockRow = numNonlocalBlockRows_>0 ? new int[numNonlocalBlockRows_] : NULL; for(i=0; i<numNonlocalBlockRows_; ++i) { pointRowsPerNonlocalBlockRow[i] = nonlocalCoefs_[i][0]->M(); } //We'll use the arbitrary distribution constructor of BlockMap. Epetra_BlockMap sourceMap(-1, numNonlocalBlockRows_, nonlocalBlockRows_, // CJ TODO FIXME long long pointRowsPerNonlocalBlockRow, RowMap().IndexBase(), RowMap().Comm()); delete [] pointRowsPerNonlocalBlockRow; //If sourceMap has global size 0, then no nonlocal data exists and we can //skip most of this function. if(sourceMap.NumGlobalElements64() < 1) { if(callFillComplete) { EPETRA_CHK_ERR(FillComplete()); } return(0); } //We also need to build a column-map, containing the columns in our //nonlocal data. To do that, create a list of all column-indices that //occur in our nonlocal rows. int numCols = 0, allocLen = 0; int* cols = NULL; int* pointColsPerBlockCol = NULL; int ptColAllocLen = 0; int insertPoint = -1; for(i=0; i<numNonlocalBlockRows_; ++i) { for(int j=0; j<nonlocalBlockRowLengths_[i]; ++j) { int col = nonlocalBlockCols_[i][j]; int offset = Epetra_Util_binary_search(col, cols, numCols, insertPoint); if (offset < 0) { EPETRA_CHK_ERR( Epetra_Util_insert(col, insertPoint, cols, numCols, allocLen) ); int tmpNumCols = numCols-1; EPETRA_CHK_ERR( Epetra_Util_insert(nonlocalCoefs_[i][j]->N(), insertPoint, pointColsPerBlockCol, tmpNumCols, ptColAllocLen) ); } } } Epetra_BlockMap colMap(-1, numCols, cols, // CJ TODO FIXME long long pointColsPerBlockCol, RowMap().IndexBase(), RowMap().Comm()); delete [] cols; delete [] pointColsPerBlockCol; numCols = 0; allocLen = 0; //now we need to create a matrix with sourceMap and colMap, and fill it with //our nonlocal data so we can then export it to the correct owning //processors. Epetra_VbrMatrix tempMat(Copy, sourceMap, colMap, nonlocalBlockRowLengths_); //Next we need to make sure the 'indices-are-global' attribute of tempMat's //graph is set to true, in case this processor doesn't end up calling the //InsertGlobalValues method... const Epetra_CrsGraph& graph = tempMat.Graph(); Epetra_CrsGraph& nonconst_graph = const_cast<Epetra_CrsGraph&>(graph); nonconst_graph.SetIndicesAreGlobal(true); for(i=0; i<numNonlocalBlockRows_; ++i) { EPETRA_CHK_ERR( tempMat.BeginInsertGlobalValues(nonlocalBlockRows_[i], nonlocalBlockRowLengths_[i], nonlocalBlockCols_[i]) ); for(int j=0; j<nonlocalBlockRowLengths_[i]; ++j) { Epetra_SerialDenseMatrix& subblock = *(nonlocalCoefs_[i][j]); EPETRA_CHK_ERR( tempMat.SubmitBlockEntry(subblock.A(), subblock.LDA(), subblock.M(), subblock.N()) ); } EPETRA_CHK_ERR( tempMat.EndSubmitEntries() ); } //Now we need to call FillComplete on our temp matrix. We need to //pass a DomainMap and RangeMap, which are not the same as the RowMap //and ColMap that we constructed the matrix with. EPETRA_CHK_ERR(tempMat.FillComplete(RowMap(), sourceMap)); //Finally, we're ready to create the exporter and export non-local data to //the appropriate owning processors. Epetra_Export exporter(sourceMap, RowMap()); EPETRA_CHK_ERR( Export(tempMat, exporter, Add) ); if(callFillComplete) { EPETRA_CHK_ERR(FillComplete()); } destroyNonlocalData(); return(0); }
int Epetra_FECrsMatrix::GlobalAssemble(const Epetra_Map& domain_map, const Epetra_Map& range_map, bool callFillComplete, Epetra_CombineMode combineMode, bool save_off_and_reuse_map_exporter) { if (Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) { if (callFillComplete) { EPETRA_CHK_ERR( FillComplete(domain_map, range_map) ); } return(0); } std::vector<int_type>& nonlocalRows_var = nonlocalRows<int_type>(); std::vector<std::vector<int_type> >& nonlocalCols_var = nonlocalCols<int_type>(); if (useNonlocalMatrix_) { tempMat_ = nonlocalMatrix_; } else { //In this method we need to gather all the non-local (overlapping) data //that's been input on each processor, into the //non-overlapping distribution defined by the map that 'this' matrix was //constructed with. //First build a map that describes our nonlocal data. //We'll use the arbitrary distribution constructor of Map. int_type* nlr_ptr = nonlocalRows_var.size() > 0 ? &nonlocalRows_var[0] : 0; if (sourceMap_ == NULL) sourceMap_ = new Epetra_Map((int_type) -1, (int) nonlocalRows_var.size(), nlr_ptr, (int_type) Map().IndexBase64(), Map().Comm()); //If sourceMap has global size 0, then no nonlocal data exists and we can //skip most of this function. if (sourceMap_->NumGlobalElements64() < 1) { if (callFillComplete) { EPETRA_CHK_ERR( FillComplete(domain_map, range_map) ); } if (!save_off_and_reuse_map_exporter) { delete sourceMap_; sourceMap_ = NULL; } return(0); } //We also need to build a column-map, containing the columns in our //nonlocal data. To do that, create a list of all column-indices that //occur in our nonlocal rows. bool first_time=!save_off_and_reuse_map_exporter; if ( colMap_ == NULL ) { first_time = true; std::vector<int_type> cols; for(size_t i=0; i<nonlocalRows_var.size(); ++i) { for(size_t j=0; j<nonlocalCols_var[i].size(); ++j) { int_type col = nonlocalCols_var[i][j]; typename std::vector<int_type>::iterator it = std::lower_bound(cols.begin(), cols.end(), col); if (it == cols.end() || *it != col) { cols.insert(it, col); } } } int_type* cols_ptr = cols.size() > 0 ? &cols[0] : 0; colMap_ = new Epetra_Map((int_type) -1, (int) cols.size(), cols_ptr, (int_type) Map().IndexBase64(), Map().Comm()); } //now we need to create a matrix with sourceMap and colMap, and fill it with //our nonlocal data so we can then export it to the correct owning processors. std::vector<int> nonlocalRowLengths(nonlocalRows_var.size()); for(size_t i=0; i<nonlocalRows_var.size(); ++i) { nonlocalRowLengths[i] = (int) nonlocalCols_var[i].size(); } int* nlRLptr = nonlocalRowLengths.size()>0 ? &nonlocalRowLengths[0] : NULL; if ( first_time && tempMat_ == NULL ) tempMat_ = new Epetra_CrsMatrix(Copy, *sourceMap_, *colMap_, nlRLptr); else tempMat_->PutScalar(0.); for(size_t i=0; i<nonlocalRows_var.size(); ++i) { if ( first_time ) { EPETRA_CHK_ERR( tempMat_->InsertGlobalValues(nonlocalRows_var[i], (int) nonlocalCols_var[i].size(), &nonlocalCoefs_[i][0], &nonlocalCols_var[i][0]) ); } else { EPETRA_CHK_ERR( tempMat_->SumIntoGlobalValues(nonlocalRows_var[i], (int) nonlocalCols_var[i].size(), &nonlocalCoefs_[i][0], &nonlocalCols_var[i][0]) ); } } if (!save_off_and_reuse_map_exporter) { delete sourceMap_; delete colMap_; sourceMap_ = colMap_ = NULL; } //Next we need to make sure the 'indices-are-global' attribute of tempMat's //graph is set to true, in case this processor doesn't end up calling the //InsertGlobalValues method... if (first_time) { const Epetra_CrsGraph& graph = tempMat_->Graph(); Epetra_CrsGraph& nonconst_graph = const_cast<Epetra_CrsGraph&>(graph); nonconst_graph.SetIndicesAreGlobal(true); } } //Now we need to call FillComplete on our temp matrix. We need to //pass a DomainMap and RangeMap, which are not the same as the RowMap //and ColMap that we constructed the matrix with. EPETRA_CHK_ERR(tempMat_->FillComplete(domain_map, range_map)); if (exporter_ == NULL) exporter_ = new Epetra_Export(tempMat_->RowMap(), RowMap()); EPETRA_CHK_ERR(Export(*tempMat_, *exporter_, combineMode)); if(callFillComplete) { EPETRA_CHK_ERR(FillComplete(domain_map, range_map)); } //now reset the values in our nonlocal data if (!useNonlocalMatrix_) { for(size_t i=0; i<nonlocalRows_var.size(); ++i) { nonlocalCols_var[i].resize(0); nonlocalCoefs_[i].resize(0); } } if (!save_off_and_reuse_map_exporter) { delete exporter_; exporter_ = NULL; if (!useNonlocalMatrix_) delete tempMat_; tempMat_ = NULL; } return(0); }