// ================================================ ====== ==== ==== == = // Computes C= <me> * A int ML_Epetra::ML_RefMaxwell_11_Operator::MatrixMatrix_Multiply(const Epetra_CrsMatrix & A, ML_Comm *comm, ML_Operator **C) const { ML_Operator *SM_ML,*A_ML,*temp1,*temp2; /* General Stuff */ ML_Comm* temp = global_comm; A_ML = ML_Operator_Create(comm); *C = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)&A,A_ML); /* Do the SM part */ SM_ML = ML_Operator_Create(comm); temp1 = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)SM_Matrix_,SM_ML); ML_2matmult(SM_ML,A_ML,temp1,ML_CSR_MATRIX); ML_Matrix_Print(temp1,*Comm_,*RangeMap_,"smp.dat"); /* Do the Addon part */ Addon_->MatrixMatrix_Multiply(A,comm,&temp2); ML_Matrix_Print(temp2,*Comm_,*RangeMap_,"add_p.dat"); /* Add the matrices together */ ML_Operator_Add(temp2,temp1,*C,ML_CSR_MATRIX,1.0); ML_Matrix_Print(*C,*Comm_,*RangeMap_,"tfinal.dat"); /* Cleanup */ global_comm = temp; ML_Operator_Destroy(&A_ML); ML_Operator_Destroy(&SM_ML); ML_Operator_Destroy(&temp1); ML_Operator_Destroy(&temp2); return 0; }/*end MatrixMatrix_Multiply*/
// ================================================ ====== ==== ==== == = // Forms the coarse matrix, given the prolongator int ML_Epetra::FaceMatrixFreePreconditioner::FormCoarseMatrix() { CoarseMat_ML = ML_Operator_Create(ml_comm_); CoarseMat_ML->data_destroy=free; ML_Operator *Temp_ML=0; ML_Operator *R= ML_Operator_Create(ml_comm_); ML_Operator *P= ML_Operator_Create(ml_comm_); /* Build ML_Operator version of Prolongator_, Restriction Operator */ ML_CHK_ERR(ML_Operator_WrapEpetraCrsMatrix(Prolongator_,P,verbose_)); P->num_rigid=P->num_PDEs=dim; //NTS: ML_CHK_ERR won't work on this: it returns 1 ML_Operator_Transpose_byrow(P, R); /* OPTION: Disable the addon */ const Epetra_CrsMatrix *Op11crs = dynamic_cast<const Epetra_CrsMatrix*>(&*Operator_); const Epetra_Operator_With_MatMat *Op11mm = dynamic_cast<const Epetra_Operator_With_MatMat*>(&*Operator_); /* Do the A*P with or without addon*/ if(Op11crs){ if(verbose_ && !Comm_->MyPID()) printf("FMFP: Running *without* addon\n"); ML_Operator *SM_ML = ML_Operator_Create(ml_comm_); Temp_ML = ML_Operator_Create(ml_comm_); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Op11crs,SM_ML,verbose_); ML_2matmult(SM_ML,P,Temp_ML,ML_CSR_MATRIX); ML_Operator_Destroy(&SM_ML); } else if(Op11mm){ if(verbose_ && !Comm_->MyPID()) printf("FMFP: Running with addon\n"); ML_CHK_ERR(Op11mm->MatrixMatrix_Multiply(*Prolongator_,ml_comm_,&Temp_ML)); } else{ if(!Comm_->MyPID()) printf("ERROR: FMFP Illegal Operator\n"); delete R; ML_CHK_ERR(-1); } /* Do R * AP */ R->num_rigid=R->num_PDEs=dim; ML_2matmult_block(R, Temp_ML,CoarseMat_ML,ML_CSR_MATRIX); /* Wrap to Epetra-land */ int nnz=100; double time; ML_Operator2EpetraCrsMatrix(CoarseMat_ML,CoarseMatrix,nnz,true,time,0,verbose_); // NTS: This is a hack to get around the sticking ones on the diagonal issue; /* Cleanup */ ML_Operator_Destroy(&P); ML_Operator_Destroy(&R); ML_Operator_Destroy(&Temp_ML); ML_Operator_Destroy(&CoarseMat_ML);CoarseMat_ML=0;//HAX return 0; }/*end FormCoarseMatrix*/
// ================================================ ====== ==== ==== == = //! Build the face-to-node prolongator described by Bochev, Siefert, Tuminaro, Xu and Zhu (2007). int ML_Epetra::FaceMatrixFreePreconditioner::PBuildSparsity(ML_Operator *P, Epetra_CrsMatrix *&Psparse){ /* Create wrapper to do abs(T) */ // NTS: Assume D0 has already been reindexed by now. ML_Operator* AbsFN_ML = ML_Operator_Create(ml_comm_); ML_CHK_ERR(ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix*>(&*FaceNode_Matrix_),AbsFN_ML,verbose_)); ML_Operator_Set_Getrow(AbsFN_ML,AbsFN_ML->outvec_leng,CSR_getrow_ones); /* Form abs(T) * P_n */ ML_Operator* AbsFNP = ML_Operator_Create(ml_comm_); ML_2matmult(AbsFN_ML,P,AbsFNP, ML_CSR_MATRIX); /* Wrap P_n into Epetra-land */ Epetra_CrsMatrix_Wrap_ML_Operator(AbsFNP,*Comm_,*FaceRangeMap_,&Psparse,Copy,0); /* Nuke the rows in Psparse */ if(BCfaces_.size()>0) Apply_BCsToMatrixRows(BCfaces_.get(),BCfaces_.size(),*Psparse); // Cleanup ML_Operator_Destroy(&AbsFN_ML); ML_Operator_Destroy(&AbsFNP); return 0; }
// ================================================ ====== ==== ==== == = // Computes C= <me> * A int ML_Epetra::Epetra_Multi_CrsMatrix::MatrixMatrix_Multiply(const Epetra_CrsMatrix & A, ML_Comm *comm, ML_Operator **C) const { int rv=0; ML_Comm* temp = global_comm; /* Setup for 1st Matmat */ ML_Operator * MV[2]={0,0},*CV; MV[(NumMatrices_-1)%2]= ML_Operator_Create(comm); rv=ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)&A,MV[(NumMatrices_-1)%2]); ML_CHK_ERR(rv); /* Do the matmats */ for(int i=NumMatrices_-1;rv==0 && i>=0;i--){ /* Do pre-wraps */ if(MV[(i+1)%2] && i!=NumMatrices_-1) ML_Operator_Destroy(&MV[(i+1)%2]); MV[(i+1)%2]=ML_Operator_Create(comm); CV=ML_Operator_Create(comm); rv=ML_Operator_WrapEpetraCrsMatrix(CrsMatrices_[i],CV); ML_CHK_ERR(rv); /* Do matmat */ ML_2matmult(CV,MV[i%2],MV[(i+1)%2],ML_CSR_MATRIX); ML_Operator_Destroy(&CV); }/*end for*/ global_comm = temp; /* Final Postwrap */ *C=MV[1]; /* Cleanup */ if(MV[0]) ML_Operator_Destroy(&MV[0]); return rv; }/*end MatrixMatrix_Multiply*/
// ================================================ ====== ==== ==== == = // Computes C= A^T * <me> * A. OptimizeStorage *must* be called for both A and the // matrices in *this, before this routine can work. int ML_Epetra::ML_RefMaxwell_11_Operator::PtAP(const Epetra_CrsMatrix & P, ML_Comm *comm, ML_Operator **C) const{ ML_Operator *SM_ML,*P_ML,*R_ML,*PtSMP_ML,*temp1,*temp2,*opwrap,*D0_M1_P_ML; /* General Stuff */ ML_Comm* temp = global_comm; P_ML = ML_Operator_Create(comm); R_ML = ML_Operator_Create(comm);; ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)&P,P_ML); ML_Operator_Transpose_byrow(P_ML,R_ML); /* Do the SM part */ SM_ML = ML_Operator_Create(comm); temp1 = ML_Operator_Create(comm); PtSMP_ML = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)SM_Matrix_,SM_ML); ML_2matmult(SM_ML,P_ML,temp1,ML_CSR_MATRIX); ML_2matmult_block(R_ML,temp1,PtSMP_ML,ML_CSR_MATRIX); ML_Operator_Destroy(&temp1); ML_Operator_Destroy(&SM_ML); #ifdef MANUALLY_TRANSPOSE_D0 ML_Operator_Destroy(&R_ML); #endif ML_Matrix_Print(PtSMP_ML,*Comm_,*RangeMap_,"ptsmp.dat"); #ifdef MANUALLY_TRANSPOSE_D0 /* Do the Addon: Step #1: M1 * P*/ opwrap = ML_Operator_Create(comm); temp1 = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Addon_Matrix_[4],opwrap); ML_2matmult(opwrap,P_ML,temp1,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); ML_Operator_Destroy(&P_ML); /* Do the Addon: Step #2: D0^T *(M1 * P)*/ opwrap = ML_Operator_Create(comm); D0_M1_P_ML = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Addon_Matrix_[3],opwrap); ML_2matmult(opwrap,temp1,D0_M1_P_ML,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); ML_Operator_Destroy(&temp1); /* Do the Addon: Step #3: M0^{-1} * (D0^T * M1 * P)*/ opwrap = ML_Operator_Create(comm); temp1 = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Addon_Matrix_[2],opwrap); ML_2matmult(opwrap,D0_M1_P_ML,temp1,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); /* Do the Addon: Step #4: Transpose (D0^T * M1 * P) & multiply by output from Step 3*/ opwrap = ML_Operator_Create(comm); temp2 = ML_Operator_Create(comm); ML_Operator_Transpose_byrow(D0_M1_P_ML,opwrap); ML_2matmult(opwrap,temp1,temp2,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); ML_Operator_Destroy(&temp1); ML_Operator_Destroy(&D0_M1_P_ML); ML_Matrix_Print(temp2,*Comm_,*RangeMap_,"pt_add_p.dat"); #else ML_Operator *P_M1_D0_ML; /* Do the Addon: Step #1: P^T * M1 */ opwrap = ML_Operator_Create(comm); temp1 = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Addon_Matrix_[0],opwrap); ML_2matmult_block(R_ML,opwrap,temp1,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); ML_Operator_Destroy(&P_ML); ML_Operator_Destroy(&R_ML); /* Do the Addon: Step #2: (P^T * M1) * D0*/ opwrap = ML_Operator_Create(comm); P_M1_D0_ML = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Addon_Matrix_[1],opwrap); ML_2matmult_block(temp1,opwrap,P_M1_D0_ML,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); ML_Operator_Destroy(&temp1); /* Do the Addon: Step #3: (P^T * M1 * D0) * M0^{-1} */ opwrap = ML_Operator_Create(comm); temp1 = ML_Operator_Create(comm); ML_Operator_WrapEpetraCrsMatrix((Epetra_CrsMatrix*)Addon_Matrix_[2],opwrap); ML_2matmult(P_M1_D0_ML,opwrap,temp1,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); /* Do the Addon: Step #4: Transpose (P^T * M1 * D0) & multiply by output from Step 3*/ opwrap = ML_Operator_Create(comm); temp2 = ML_Operator_Create(comm); ML_Operator_Transpose_byrow(P_M1_D0_ML,opwrap); ML_2matmult(temp1,opwrap,temp2,ML_CSR_MATRIX); ML_Operator_Destroy(&opwrap); ML_Operator_Destroy(&temp1); ML_Operator_Destroy(&P_M1_D0_ML); ML_Matrix_Print(temp2,*Comm_,*RangeMap_,"pt_add_p_rev.dat"); #endif /* Add the matrices together */ ML_Operator_Add(PtSMP_ML,temp2,*C,ML_CSR_MATRIX,1.0); ML_Matrix_Print(*C,*Comm_,*RangeMap_,"ptap.dat"); /* Cleanup */ global_comm = temp; ML_Operator_Destroy(&temp2); ML_Operator_Destroy(&PtSMP_ML); return 0; }