44 #include "Epetra_ConfigDefs.h"
47 #include "Epetra_MultiVector.h"
48 #include "Epetra_Import.h"
49 #include "Epetra_Export.h"
50 #include "Epetra_Comm.h"
55 #define MAX(x,y) ((x)>(y)?(x):(y))
61 PurelyLocalMode_(true),
62 ContiguousBlockMode_(false),
63 ContiguousBlockSize_(0),
67 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
85 if(BDMap_)
delete BDMap_;
86 if(CompatibleMap_)
delete CompatibleMap_;
87 if(BDMat_)
delete BDMat_;
88 if(Importer_)
delete Importer_;
89 if(Exporter_)
delete Exporter_;
90 if(ImportVector_)
delete ImportVector_;
91 if(ExportVector_)
delete ExportVector_;
96 template<
typename int_type>
97 int EpetraExt_PointToBlockDiagPermute::TSetParameters(Teuchos::ParameterList & List){
101 ContiguousBlockSize_=List_.get(
"contiguous block size",0);
102 if(ContiguousBlockSize_!=0){
103 ContiguousBlockMode_=
true;
104 PurelyLocalMode_=
false;
108 NumBlocks_=List_.get(
"number of local blocks",0);
109 Blockstart_=List_.get(
"block start index",(
int*)0);
110 Blockids_ref<int>()=List_.get(
"block entry lids",(
int*)0);
111 if(Blockids_const_ptr<int>())
112 PurelyLocalMode_=
true;
114 Blockids_ref<int_type>()=List_.get(
"block entry gids",(int_type*)0);
115 if(Blockids_const_ptr<int_type>()) {
116 PurelyLocalMode_=
false;
117 if(
sizeof(
int) !=
sizeof(int_type)) {
124 if(ContiguousBlockMode_){
126 if(NumBlocks_ || Blockstart_ || Blockids_const_ptr<int>() || Blockids_const_ptr<int_type>()) EPETRA_CHK_ERR(-4);
129 if(NumBlocks_ <= 0) EPETRA_CHK_ERR(-1);
130 if(!Blockstart_) EPETRA_CHK_ERR(-2);
131 if(!Blockids_const_ptr<int>() && !Blockids_const_ptr<int_type>()) EPETRA_CHK_ERR(-3);
138 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
140 return TSetParameters<int>(List);
144 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
146 return TSetParameters<long long>(List);
150 throw "EpetraExt_PointToBlockDiagPermute::SetParameters: ERROR, GlobalIndices type unknown.";
156 int rv=ExtractBlockDiagonal();
171 int NumVectors = X.NumVectors();
172 if (NumVectors!=Y.NumVectors()) {
181 if (&X==&Y && Importer_==0 && Exporter_==0) {
186 UpdateImportVector(NumVectors);
187 UpdateExportVector(NumVectors);
191 EPETRA_CHK_ERR(ImportVector_->Import(X, *Importer_,
Insert));
206 Y.Export(*ExportVector_, *Exporter_,
Add);
222 if(Importer_) std::cout<<*Importer_<<std::endl;
223 if(Exporter_) std::cout<<*Exporter_<<std::endl;
224 if(BDMat_) std::cout<<*BDMat_<<std::endl;
229 template<
typename int_type>
230 int EpetraExt_PointToBlockDiagPermute::TExtractBlockDiagonal(){
232 std::vector<int_type> ExtRows;
234 int ExtSize=0,ExtCols=0,MainCols=0;
236 int *l2b,*block_offset;
239 int index,col,row_in_block,col_in_block,length,*colind;
242 bool verbose=(bool)(List_.get(
"output",0) > 0);
245 SetupContiguousMode();
248 int *bsize=
new int[NumBlocks_];
249 for(i=0;i<NumBlocks_;i++)
250 bsize[i]=Blockstart_[i+1]-Blockstart_[i];
254 int_type NumBlocks_int_type = NumBlocks_;
255 Matrix_->
Comm().
ScanSum(&NumBlocks_int_type,&MyMinGID, 1);
256 MyMinGID-=NumBlocks_;
257 int_type *MyBlockGIDs=
new int_type[NumBlocks_];
258 for(i=0;i<NumBlocks_;i++)
259 MyBlockGIDs[i]=MyMinGID+i;
268 if(!PurelyLocalMode_){
271 ExtRows.reserve(ExtSize);
273 for(i=0;i<Blockstart_[NumBlocks_];i++){
274 if(RowMap.
LID(Blockids_const_ptr<int_type>()[i])==-1)
275 ExtRows.push_back(Blockids_const_ptr<int_type>()[i]);
280 ExtSize=ExtRows.size();
283 if(verbose && !Matrix_->
Comm().
MyPID()) printf(
"EpetraExt_PointToBlockDiagPermute: Switching to purely local mode\n");
284 PurelyLocalMode_=
true;
285 for(i=0;i<Blockstart_[NumBlocks_];i++){
286 Blockids_ref<int>()[i]=RowMap.
LID(Blockids_const_ptr<int_type>()[i]);
291 if(PurelyLocalMode_){
295 block_offset=
new int[Nrows];
298 for(i=0;i<NumBlocks_;i++) {
299 for(j=Blockstart_[i];j<Blockstart_[i+1];j++){
300 block_offset[Blockids_const_ptr<int>()[j]]=j-Blockstart_[i];
301 l2b[Blockids_const_ptr<int>()[j]]=i;
306 for(i=0;i<Nrows;i++) {
307 int block_num = l2b[i];
308 if(block_num>=0 && block_num<NumBlocks_) {
309 row_in_block=block_offset[i];
312 for (j = 0; j < length; j++) {
314 if(col < Nrows && l2b[col]==block_num){
316 col_in_block = block_offset[col];
317 index = col_in_block * bsize[block_num] + row_in_block;
318 (*BDMat_)[block_num][index]=values[j];
324 index = row_in_block * bsize[block_num] + row_in_block;
325 (*BDMat_)[block_num][index]=1.0;
331 l2blockid=
new int_type[Nrows];
333 l2blockid[Blockstart_[l2b[i]]+block_offset[i]]= (int_type) Matrix_->
RowMap().GID64(i);
336 CompatibleMap_=
new Epetra_Map(-1,Nrows,l2blockid,0,Matrix_->
Comm());
343 int_type* ExtRowsPtr = ExtRows.size()>0 ? &ExtRows[0] : NULL;
344 Epetra_Map TmpMap((int_type) -1,ExtSize, ExtRowsPtr,0,Matrix_->
Comm());;
348 TmpMatrix.Import(*Matrix_,TmpImporter,Insert);
349 TmpMatrix.FillComplete();
351 ExtCols=TmpMatrix.NumMyCols();
356 LocalColIDS=
new int[MainCols+ExtCols];
357 for(i=0;i<MainCols;i++){
358 int_type GID= (int_type) Matrix_->GCID64(i);
359 int MainLID=RowMap.
LID(GID);
360 if(MainLID!=-1) LocalColIDS[i]=MainLID;
362 int ExtLID=TmpMatrix.LRID(GID);
363 if(ExtLID!=-1) LocalColIDS[i]=Nrows+ExtLID;
364 else LocalColIDS[i]=-1;
369 for(i=0;i<ExtCols;i++){
370 int_type GID= (int_type) TmpMatrix.GCID64(i);
371 int MainLID=RowMap.
LID(GID);
372 if(MainLID!=-1) LocalColIDS[MainCols+i]=MainLID;
374 int ExtLID=TmpMatrix.LRID(GID);
375 if(ExtLID!=-1) LocalColIDS[MainCols+i]=Nrows+ExtLID;
376 else LocalColIDS[MainCols+i]=-1;
381 l2b=
new int[Nrows+ExtSize];
382 block_offset=
new int[Nrows+ExtSize];
387 for(i=0;i<Nrows+ExtSize;i++) block_offset[i]=l2b[i]=-1;
389 for(i=0;i<NumBlocks_;i++) {
390 for(j=Blockstart_[i];j<Blockstart_[i+1];j++){
391 int LID=RowMap.
LID(Blockids_const_ptr<int_type>()[j]);
392 if(LID==-1) {LID=Nrows+ext_idx;ext_idx++;}
393 block_offset[LID]=j-Blockstart_[i];
399 for(i=0;i<Nrows;i++) {
400 int block_num = l2b[i];
401 if(block_num>=0 && block_num<NumBlocks_) {
402 row_in_block=block_offset[i];
405 for (j = 0; j < length; j++) {
406 col = LocalColIDS[colind[j]];
407 if(col!=-1 && l2b[col]==block_num){
409 col_in_block = block_offset[col];
410 index = col_in_block * bsize[block_num] + row_in_block;
411 (*BDMat_)[block_num][index]=values[j];
417 index = row_in_block * bsize[block_num] + row_in_block;
418 (*BDMat_)[block_num][index]=values[j];
424 for(i=0;i<ExtSize;i++) {
425 int block_num = l2b[Nrows+i];
426 if(block_num>=0 && block_num<NumBlocks_) {
427 row_in_block=block_offset[Nrows+i];
428 TmpMatrix.ExtractMyRowView(i,length,values,colind);
430 for (j = 0; j < length; j++) {
431 col = LocalColIDS[MainCols+colind[j]];
432 if(col!=-1 && l2b[col]==block_num){
434 col_in_block = block_offset[col];
435 index = col_in_block * bsize[block_num] + row_in_block;
436 (*BDMat_)[block_num][index]=values[j];
442 index = row_in_block * bsize[block_num] + row_in_block;
443 (*BDMat_)[block_num][index]=1.0;
449 l2blockid=
new int_type[Blockstart_[NumBlocks_]];
450 for(i=0;i<Nrows;i++){
452 if(bkid>-1) l2blockid[Blockstart_[bkid]+block_offset[i]]= (int_type) RowMap.GID64(i);
455 for(i=0;i<ExtSize;i++)
456 l2blockid[Blockstart_[l2b[Nrows+i]]+block_offset[Nrows+i]]= (int_type) TmpMatrix.GRID64(i);
459 CompatibleMap_=
new Epetra_Map(-1,Blockstart_[NumBlocks_],l2blockid,0,Matrix_->
Comm());
464 Teuchos::ParameterList dummy,inList;
465 inList=List_.get(
"blockdiagmatrix: list",dummy);
466 BDMat_->SetParameters(inList);
476 delete [] LocalColIDS;
477 delete [] block_offset;
481 delete [] MyBlockGIDs;
484 CleanupContiguousMode();
489 int EpetraExt_PointToBlockDiagPermute::ExtractBlockDiagonal(){
490 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
492 return TExtractBlockDiagonal<int>();
496 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
498 return TExtractBlockDiagonal<long long>();
502 throw "EpetraExt_PointToBlockDiagPermute::ExtractBlockDiagonal: ERROR, GlobalIndices type unknown.";
506 template<
typename int_type>
507 int EpetraExt_PointToBlockDiagPermute::TSetupContiguousMode(){
508 if(!ContiguousBlockMode_)
return 0;
512 int_type MinMyGID= (int_type) RowMap.MinMyGID64();
513 int_type MaxMyGID= (int_type) RowMap.MaxMyGID64();
514 int_type Base= (int_type) Matrix_->IndexBase64();
517 int_type MyFirstBlockGID=ContiguousBlockSize_*(int_type)ceil(((
double)(MinMyGID - Base))/ContiguousBlockSize_)+Base;
518 NumBlocks_=(int)ceil((
double)((MaxMyGID-MyFirstBlockGID+1.0)) / ContiguousBlockSize_);
521 Blockstart_=
new int[NumBlocks_+1];
522 Blockids_ref<int_type>()=
new int_type[NumBlocks_*ContiguousBlockSize_];
523 if(
sizeof(
int) !=
sizeof(int_type))
524 Blockids_ref<int>()=
new int[NumBlocks_*ContiguousBlockSize_];
525 Blockstart_[NumBlocks_]=NumBlocks_*ContiguousBlockSize_;
528 for(
int i=0,ct=0;i<NumBlocks_;i++){
530 for(
int j=0;j<ContiguousBlockSize_;j++,ct++){
531 Blockids_ref<int_type>()[ct]=MyFirstBlockGID+ct;
538 int EpetraExt_PointToBlockDiagPermute::SetupContiguousMode(){
539 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
541 return TSetupContiguousMode<int>();
545 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
547 return TSetupContiguousMode<long long>();
551 throw "EpetraExt_PointToBlockDiagPermute::SetupContiguousMode: ERROR, GlobalIndices type unknown.";
555 int EpetraExt_PointToBlockDiagPermute::CleanupContiguousMode(){
556 if(!ContiguousBlockMode_)
return 0;
558 if(Blockstart_) {
delete [] Blockstart_; Blockstart_=0;}
559 if(Blockids_int_) {
delete [] Blockids_int_; Blockids_int_=0;}
560 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
561 if(Blockids_LL_) {
delete [] Blockids_LL_; Blockids_LL_=0;}
569 template<
typename int_type>
576 const int *xlist=BlockMap.FirstPointInElementList();
577 const int *blocksize=BlockMap.ElementSizeList();
578 const double *values=BDMat_->Values();
579 int NumBlocks=BDMat_->NumMyBlocks();
582 std::vector<int_type> GIDs;
583 GIDs.resize(BlockMap.MaxMyElementSize());
586 for(
int i=0;i<NumBlocks;i++){
591 for(
int j=0;j<Nb;j++)
592 GIDs[j]= (int_type) CompatibleMap_->GID64(xidx0+j);
595 int ierr=NewMat->
InsertGlobalValues(Nb,&GIDs[0],&values[vidx0],Epetra_FECrsMatrix::COLUMN_MAJOR);
596 if(ierr < 0)
throw "CreateFECrsMatrix: ERROR in InsertGlobalValues";
603 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
605 return TCreateFECrsMatrix<int>();
609 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
611 return TCreateFECrsMatrix<long long>();
615 throw "EpetraExt_PointToBlockDiagPermute::CreateFECrsMatrix: ERROR, GlobalIndices type unknown.";
619 void EpetraExt_PointToBlockDiagPermute::UpdateImportVector(
int NumVectors)
const {
621 if(ImportVector_ != 0) {
622 if(ImportVector_->NumVectors() != NumVectors) {
623 delete ImportVector_;
627 if(ImportVector_ == 0)
633 void EpetraExt_PointToBlockDiagPermute::UpdateExportVector(
int NumVectors)
const {
635 if(ExportVector_ != 0) {
636 if(ExportVector_->NumVectors() != NumVectors) {
637 delete ExportVector_;
641 if(ExportVector_ == 0)
virtual int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Returns the result of a Epetra_Operator inverse applied to an Epetra_MultiVector X in Y...
const Epetra_Map & RangeMap() const
virtual int SetParameters(Teuchos::ParameterList &List)
Sets the parameter list.
bool GlobalIndicesLongLong() const
bool SameAs(const Epetra_BlockMap &Map) const
virtual int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Returns the result of a Epetra_Operator inverse applied to an Epetra_MultiVector X in Y...
bool GlobalIndicesInt() const
int * FirstPointInElementList() const
virtual int MyPID() const =0
int InsertGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
EpetraExt_BlockDiagMatrix: A class for storing distributed block matrices.
virtual int UnpackAndCombine(const Epetra_SrcDistObject &Source, int NumImportIDs, int *ImportLIDs, int LenImports, char *Imports, int &SizeOfPacket, Epetra_Distributor &Distor, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex *Indexor)
Perform any unpacking and combining after call to DoTransfer().
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const
const Epetra_Map & RowMap() const
virtual int SumAll(double *PartialSums, double *GlobalSums, int Count) const =0
int NumMyElements() const
virtual int CheckSizes(const Epetra_SrcDistObject &Source)
Allows the source and target (this) objects to be compared for compatibility, return nonzero if not...
int GlobalAssemble(bool callFillComplete=true, Epetra_CombineMode combineMode=Add, bool save_off_and_reuse_map_exporter=false)
virtual int CopyAndPermute(const Epetra_SrcDistObject &Source, int NumSameIDs, int NumPermuteIDs, int *PermuteToLIDs, int *PermuteFromLIDs, const Epetra_OffsetIndex *Indexor, Epetra_CombineMode CombineMode=Zero)
Perform ID copies and permutations that are on processor.
const Epetra_Comm & Comm() const
virtual ~EpetraExt_PointToBlockDiagPermute()
Destructor.
EpetraExt_PointToBlockDiagPermute(const Epetra_CrsMatrix &MAT)
@ Name Constructors
virtual int Compute()
Extracts the block-diagonal, builds maps, etc.
virtual int PackAndPrepare(const Epetra_SrcDistObject &Source, int NumExportIDs, int *ExportLIDs, int &LenExports, char *&Exports, int &SizeOfPacket, int *Sizes, bool &VarSizes, Epetra_Distributor &Distor)
Perform any packing or preparation required for call to DoTransfer().
virtual Epetra_FECrsMatrix * CreateFECrsMatrix()
Create an Epetra_FECrsMatrix from the BlockDiagMatrix.
const Epetra_Map & DomainMap() const
virtual void Print(std::ostream &os) const
Print information about this object to the given output stream.
virtual int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Returns the result of a Epetra_Operator applied to a Epetra_MultiVector X in Y.
const Epetra_Comm & Comm() const
virtual int ScanSum(double *MyVals, double *ScanSums, int Count) const =0
int Import(const Epetra_SrcDistObject &A, const Epetra_Import &Importer, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex *Indexor=0)
Imports an Epetra_DistObject using the Epetra_Import object.
int Export(const Epetra_SrcDistObject &A, const Epetra_Import &Importer, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex *Indexor=0)
Exports an Epetra_DistObject using the Epetra_Import object.