// ================================================ ====== ==== ==== == = // Constructor ML_Epetra::ML_RefMaxwell_11_Operator::ML_RefMaxwell_11_Operator(const Epetra_CrsMatrix& SM_Matrix, //S+M const Epetra_CrsMatrix& D0_Matrix, //T or D0 const Epetra_CrsMatrix& M0inv_Matrix, //M0^{-1} const Epetra_CrsMatrix& M1_Matrix): //M1(1) SM_Matrix_(&SM_Matrix),Addon_Matrix_(0),D0T_Matrix_(0) { Label_=new char [80]; strcpy(Label_,"ML_RefMaxwell_11_Operator"); Comm_ = &(SM_Matrix_->Comm()); DomainMap_ = &(SM_Matrix_->OperatorDomainMap()); RangeMap_ = &(SM_Matrix_->OperatorRangeMap()); /* Transpose D0 */ #ifdef MANUALLY_TRANSPOSE_D0 D0_Matrix_Transposer_= new EpetraExt::RowMatrix_Transpose((Epetra_Map*)&M0inv_Matrix.OperatorRangeMap()); D0T_Matrix_= dynamic_cast<Epetra_CrsMatrix*>( & ((*D0_Matrix_Transposer_)((Epetra_CrsMatrix&)D0_Matrix))); D0T_Matrix_= dynamic_cast<Epetra_CrsMatrix*>(ModifyEpetraMatrixColMap(*D0T_Matrix_,D0T_Matrix_Trans_,"D0T",false)); #endif /* Build the Epetra_Multi_CrsMatrix */ Addon_Matrix_=new Epetra_CrsMatrix*[5]; Addon_Matrix_[0]=Addon_Matrix_[4]=(Epetra_CrsMatrix*)&M1_Matrix; Addon_Matrix_[1]=(Epetra_CrsMatrix*)&D0_Matrix; #ifdef MANUALLY_TRANSPOSE_D0 Addon_Matrix_[3]=D0T_Matrix_; #else Addon_Matrix_[3]=(Epetra_CrsMatrix*)&D0_Matrix;//HAQ #endif Addon_Matrix_[2]=(Epetra_CrsMatrix*)&M0inv_Matrix; Addon_=new Epetra_Multi_CrsMatrix(5,Addon_Matrix_); }/*end Constructor*/
// ================================================ ====== ==== ==== == = //! Build the face-to-node prolongator described by Bochev, Siefert, Tuminaro, Xu and Zhu (2007). int ML_Epetra::FaceMatrixFreePreconditioner::BuildProlongator() { /* Wrap TMT_Matrix in a ML_Operator */ ML_Operator* TMT_ML = ML_Operator_Create(ml_comm_); ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix*>(&*TMT_Matrix_),TMT_ML); /* Nodal Aggregation */ ML_Aggregate_Struct *MLAggr=0; ML_Operator *P=0; int NumAggregates; int rv=ML_Epetra::RefMaxwell_Aggregate_Nodes(*TMT_Matrix_,List_,ml_comm_,std::string("FMFP (level 0) :"),MLAggr,P,NumAggregates); if(rv || !P) {if(!Comm_->MyPID()) printf("ERROR: Building nodal P\n");ML_CHK_ERR(-1);} /* Build 1-unknown sparsity of prolongator */ Epetra_CrsMatrix *Psparse=0; PBuildSparsity(P,Psparse); if(!Psparse) {if(!Comm_->MyPID()) printf("ERROR: Building Psparse\n");ML_CHK_ERR(-2);} /* Build the "nullspace" */ Epetra_MultiVector *nullspace; BuildNullspace(nullspace); if(!nullspace) {if(!Comm_->MyPID()) printf("ERROR: Building Nullspace\n");ML_CHK_ERR(-3);} /* Build the DomainMap of the new operator*/ const Epetra_Map & FineColMap = Psparse->ColMap(); CoarseMap_=new Epetra_Map(-1,NumAggregates*dim,0,*Comm_); /* Allocate the Prolongator_ */ int max_nz_per_row=Psparse->MaxNumEntries(); Prolongator_=new Epetra_CrsMatrix(Copy,*FaceRangeMap_,0); int ne1, *idx1, *idx2; idx2=new int [dim*max_nz_per_row]; double *vals1, *vals2; vals2=new double[dim*max_nz_per_row]; int nonzeros; for(int i=0;i<Prolongator_->NumMyRows();i++){ Psparse->ExtractMyRowView(i,ne1,vals1,idx1); nonzeros=0; for(int j=0;j<ne1;j++) nonzeros+=ABS(vals1[j])>0; for(int j=0;j<ne1;j++){ for(int k=0;k<dim;k++) { idx2[j*dim+k]=FineColMap.GID(idx1[j])*dim+k; //FIX: This works only because there's an implicit linear mapping which //we're exploiting. if(idx2[j*dim+k]==-1) printf("[%d] ERROR: idx1[j]=%d / idx1[j]*dim+k=%d does not have a GID!\n",Comm_->MyPID(),idx1[j],idx1[j]*dim+k); if(vals1[j]==0 ) vals2[j*dim+k]=0; else vals2[j*dim+k]=(*nullspace)[k][i] / nonzeros; }/*end for*/ }/*end for*/ Prolongator_->InsertGlobalValues(FaceRangeMap_->GID(i),dim*ne1,vals2,idx2); }/*end for*/ /* FillComplete / OptimizeStorage for Prolongator*/ Prolongator_->FillComplete(*CoarseMap_,*FaceRangeMap_); Prolongator_->OptimizeStorage(); #ifndef NO_OUTPUT /* DEBUG: Dump aggregates */ Epetra_IntVector AGG(View,*NodeDomainMap_,MLAggr->aggr_info[0]); IVOUT(AGG,"agg.dat"); EpetraExt::RowMatrixToMatlabFile("fmfp_psparse.dat",*Psparse); EpetraExt::RowMatrixToMatlabFile("fmfp_prolongator.dat",*Prolongator_); EpetraExt::VectorToMatrixMarketFile("fmfp_null0.dat",*(*nullspace)(0)); EpetraExt::VectorToMatrixMarketFile("fmfp_null1.dat",*(*nullspace)(1)); EpetraExt::VectorToMatrixMarketFile("fmfp_null2.dat",*(*nullspace)(2)); #endif /* EXPERIMENTAL: Normalize Prolongator Columns */ bool normalize_prolongator=List_.get("face matrix free: normalize prolongator",false); if(normalize_prolongator){ Epetra_Vector n_vector(*CoarseMap_,false); Prolongator_->InvColSums(n_vector); Prolongator_->RightScale(n_vector); }/*end if*/ /* Post-wrapping to convert to ML indexing */ #ifdef HAVE_ML_EPETRAEXT Prolongator_ = dynamic_cast<Epetra_CrsMatrix*>(ModifyEpetraMatrixColMap(*Prolongator_,ProlongatorColMapTrans_,"Prolongator",(verbose_&&!Comm_->MyPID()))); #endif /* Cleanup */ ML_qr_fix_Destroy(); ML_Aggregate_Destroy(&MLAggr); ML_Operator_Destroy(&TMT_ML); ML_Operator_Destroy(&P); delete nullspace; delete Psparse; delete [] idx2; delete [] vals2; return 0; }/*end BuildProlongator_*/