// ====================================================================== void Eig(const Operator& Op, MultiVector& ER, MultiVector& EI) { int ierr; if (Op.GetDomainSpace() != Op.GetRangeSpace()) ML_THROW("Matrix is not square", -1); ER.Reshape(Op.GetDomainSpace()); EI.Reshape(Op.GetDomainSpace()); Epetra_LinearProblem Problem; Problem.SetOperator(const_cast<Epetra_RowMatrix*>(Op.GetRowMatrix())); Amesos_Lapack Lapack(Problem); Epetra_Vector ER_Epetra(Op.GetRowMatrix()->RowMatrixRowMap()); Epetra_Vector EI_Epetra(Op.GetRowMatrix()->RowMatrixRowMap()); ierr = Lapack.GEEV(ER_Epetra, EI_Epetra); if (ierr) ML_THROW("GEEV returned error code = " + GetString(ierr), -1); for (int i = 0 ; i < ER.GetMyLength() ; ++i) { ER(i) = ER_Epetra[i]; EI(i) = EI_Epetra[i]; } }
// ====================================================================== Operator GetJacobiIterationOperator(const Operator& Amat, double Damping) { struct ML_AGG_Matrix_Context* widget = new struct ML_AGG_Matrix_Context; widget->near_bdry = 0; widget->aggr_info = 0; widget->drop_tol = 0.0; widget->Amat = Amat.GetML_Operator(); widget->omega = Damping; ML_Operator* tmp_ML = ML_Operator_Create(GetML_Comm()); ML_Operator_Set_ApplyFuncData(tmp_ML, widget->Amat->invec_leng, widget->Amat->outvec_leng, widget, widget->Amat->matvec->Nrows, NULL, 0); tmp_ML->data_destroy = widget_destroy; ML_Operator_Set_Getrow(tmp_ML, widget->Amat->getrow->Nrows, ML_AGG_JacobiSmoother_Getrows); // Creates a new copy of pre_comm, so that the old pre_comm // can be destroyed without worry ML_CommInfoOP_Clone(&(tmp_ML->getrow->pre_comm), widget->Amat->getrow->pre_comm); Operator tmp(Amat.GetDomainSpace(), Amat.GetRangeSpace(), tmp_ML, true, Amat.GetRCPOperatorBox()); return(tmp); }
// ====================================================================== void GetPtent(const Operator& A, Teuchos::ParameterList& List, Operator& Ptent) { MultiVector FineNS(A.GetDomainSpace(),1); FineNS = 1.0; MultiVector CoarseNS; GetPtent(A, List, FineNS, Ptent, CoarseNS); }
// ====================================================================== // FIXME: Add List void Eigs(const Operator& A, int NumEigenvalues, MultiVector& ER, MultiVector& EI) { if (A.GetDomainSpace() != A.GetRangeSpace()) ML_THROW("Input Operator is not square", -1); double time; time = GetClock(); int length = NumEigenvalues; double tol = 1e-3; int restarts = 1; int output = 10; bool PrintStatus = true; // 1.- set parameters for Anasazi Teuchos::ParameterList AnasaziList; // MatVec should be either "A" or "ML^{-1}A" AnasaziList.set("eigen-analysis: matrix operation", "A"); AnasaziList.set("eigen-analysis: use diagonal scaling", false); AnasaziList.set("eigen-analysis: symmetric problem", false); AnasaziList.set("eigen-analysis: length", length); AnasaziList.set("eigen-analysis: block-size",1); AnasaziList.set("eigen-analysis: tolerance", tol); AnasaziList.set("eigen-analysis: restart", restarts); AnasaziList.set("eigen-analysis: output", output); AnasaziList.get("eigen-analysis: print current status",PrintStatus); // data to hold real and imag for eigenvalues and eigenvectors Space ESpace(-1, NumEigenvalues); ER.Reshape(ESpace); EI.Reshape(ESpace); // this is the starting value -- random Epetra_MultiVector EigenVectors(A.GetRowMatrix()->OperatorDomainMap(), NumEigenvalues); EigenVectors.Random(); #ifdef HAVE_ML_ANASAxI //int NumRealEigenvectors, NumImagEigenvectors; #endif AnasaziList.set("eigen-analysis: action", "LM"); #ifdef HAVE_ML_ANASAxI ML_THROW("fixme...", -1); /* FIXME ML_Anasazi::Interface(A.GetRowMatrix(),EigenVectors,ER.GetValues(), EI.GetValues(), AnasaziList, 0, 0, &NumRealEigenvectors, &NumImagEigenvectors, 0); */ #else ML_THROW("Anasazi is no longer supported", -1); #endif return; }
// ====================================================================== Operator GetTranspose(const Operator& A, const bool byrow = true) { ML_Operator* ML_transp; ML_transp = ML_Operator_Create(GetML_Comm()); if (byrow) ML_Operator_Transpose_byrow(A.GetML_Operator(),ML_transp); else ML_Operator_Transpose(A.GetML_Operator(),ML_transp); Operator transp(A.GetRangeSpace(),A.GetDomainSpace(), ML_transp,true); return(transp); }
Operator GetRAP(const Operator& R, const Operator& A, const Operator& P) { ML_Operator* Rmat = R.GetML_Operator(); ML_Operator* Amat = A.GetML_Operator(); ML_Operator* Pmat = P.GetML_Operator(); ML_Operator* result = 0; result = ML_Operator_Create (Rmat->comm); /* The fixing of coarse matrix only works if it is in MSR format */ int myMatrixType = ML_MSR_MATRIX; ML_rap(Rmat, Amat, Pmat, result, myMatrixType); result->num_PDEs = Pmat->num_PDEs; #ifdef MB_MODIF_QR ML_fixCoarseMtx(result, myMatrixType); #endif/*MB_MODIF_QR*/ Operator op(P.GetDomainSpace(),P.GetDomainSpace(), result); return(op); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc,&argv); #endif Init(); try { int NX = 10; // number of nodes on the X-axis int NY = 10; // number of nodes on the Y-axis double conv = 1.0; // convection coefficient double diff = 1e-5; // diffusion coefficient Operator A = GetRecirc2D(NX, NY, conv, diff); Teuchos::ParameterList List; List.set("smoother: type", "symmetric Gauss-Seidel"); List.set("smoother: sweeps", 1); List.set("aggregation: damping factor", 0.0); List.set("coarse: max size", 32); MultiLevelNonSymmetricSA Prec(A, List); MultiVector LHS(A.GetRangeSpace()); MultiVector RHS(A.GetDomainSpace()); LHS.Random(); RHS = 0.0; List.set("krylov: type", "gmres"); Krylov(A, LHS, RHS, Prec, List); Finalize(); } catch (const int e) { cerr << "Caught integer exception, code = " << e << endl; } catch (...) { cerr << "Caught exception..." << endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return(0); }
// ====================================================================== MultiVector GetDiagonal(const Operator& A, const int offset) { // FIXME if (A.GetDomainSpace() != A.GetRangeSpace()) ML_THROW("Currently only square matrices are supported", -1); MultiVector D(A.GetDomainSpace()); D = 0.0; ML_Operator* matrix = A.GetML_Operator(); if (matrix->getrow == NULL) ML_THROW("getrow() not set!", -1); int row_length; int allocated = 128; int* bindx = (int *) ML_allocate(allocated*sizeof(int )); double* val = (double *) ML_allocate(allocated*sizeof(double)); for (int i = 0 ; i < matrix->getrow->Nrows; i++) { int GlobalRow = A.GetGRID(i); ML_get_matrix_row(matrix, 1, &i, &allocated, &bindx, &val, &row_length, 0); for (int j = 0; j < row_length; j++) { D(i) = 0.0; if (A.GetGCID(bindx[j]) == GlobalRow + offset) { D(i) = val[j]; break; } } } ML_free(val); ML_free(bindx); return (D); }
// ====================================================================== Operator GetScaledOperator(const Operator& A, const double alpha) { ML_Operator* ScaledA = 0; ScaledA = ML_Operator_ExplicitlyScale(A.GetML_Operator(), (double)alpha); if (ScaledA == 0) ML_THROW("ML_Operator_ExplicitlyScale returned 0", -1); Operator res; res.Reshape(A.GetDomainSpace(), A.GetRangeSpace(), ScaledA, true, A.GetRCPOperatorBox()); return(res); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc,&argv); #endif if (argc != 2) { fprintf(stderr, "Usage: `%s InputFile'\n", argv[0]); fprintf(stderr, "An example of input file is reported\n"); fprintf(stderr, "in the source of this example\n"); exit(EXIT_SUCCESS); } string InputFile = argv[1]; // Initialize the workspace and set the output level Init(); try { int NumPDEEqns; Operator A; ReadSAMISMatrix("mtx.dat", A, NumPDEEqns); Teuchos::ParameterList List = ReadParameterList(InputFile.c_str()); int MaxLevels = List.get("max levels", 10); int AdditionalCandidates = List.get("additional candidates", 2); int limKer = List.get("limit kernel", -1); if (AdditionalCandidates == 0 && limKer == 0) limKer = -1; // create multilevel preconditioner, do not compute hierarchy MultiLevelAdaptiveSA Prec(A, List, NumPDEEqns); if (limKer) { MultiVector NS; ReadSAMISKernel("ker.dat", NS, limKer); Prec.SetNullSpace(NS); Prec.AdaptCompute(true, AdditionalCandidates); } else { Prec.AdaptCompute(false, AdditionalCandidates); } MultiVector LHS(A.GetDomainSpace()); MultiVector RHS(A.GetRangeSpace()); LHS.Random(); RHS = 0.0; // Set krylov: type unless specified in the config. file if (List.isParameter("krylov: type") == 0) List.set("krylov: type","cg_condnum"); Krylov(A, LHS, RHS, Prec, List); Finalize(); } catch (const int e) { cerr << "Caught integer exception, code = " << e << endl; } catch (...) { cerr << "Caught exception..." << endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return(0); }
/*----------------------------------------------------------------------* | compute the preconditioner (public) m.gee 03/06| *----------------------------------------------------------------------*/ bool MOERTEL::Mortar_ML_Preconditioner::Compute() { iscomputed_ = false; MLAPI::Init(); // get parameters int maxlevels = mlparams_.get("max levels",10); int maxcoarsesize = mlparams_.get("coarse: max size",10); double* nullspace = mlparams_.get("null space: vectors",(double*)NULL); int nsdim = mlparams_.get("null space: dimension",1); int numpde = mlparams_.get("PDE equations",1); double damping = mlparams_.get("aggregation: damping factor",1.33); std::string eigenanalysis = mlparams_.get("eigen-analysis: type", "Anorm"); std::string smoothertype = mlparams_.get("smoother: type","symmetric Gauss-Seidel"); std::string coarsetype = mlparams_.get("coarse: type","Amesos-KLU"); std::string ptype = mlparams_.get("prolongator: type","mod_full"); // create the missing rowmap Arrmap_ Arrmap_ = Teuchos::rcp(MOERTEL::SplitMap(A_->RowMap(),*Annmap_)); Teuchos::RCP<Epetra_Map> map1 = Arrmap_; Teuchos::RCP<Epetra_Map> map2 = Annmap_; // split Atilde // // Atilde11 Atilde12 // Atilde21 Atilde22 // Teuchos::RCP<Epetra_CrsMatrix> Atilde11; Teuchos::RCP<Epetra_CrsMatrix> Atilde12; Teuchos::RCP<Epetra_CrsMatrix> Atilde21; Teuchos::RCP<Epetra_CrsMatrix> Atilde22; MOERTEL::SplitMatrix2x2(Atilde_,map1,map2,Atilde11,Atilde12,Atilde21,Atilde22); // build Atildesplit // // Atilde11 0 // 0 I // Atildesplit_ = Teuchos::rcp(new Epetra_CrsMatrix(Copy,A_->RowMap(),50,false)); MOERTEL::MatrixMatrixAdd(*Atilde11,false,1.0,*Atildesplit_,0.0); Teuchos::RCP<Epetra_CrsMatrix> tmp = Teuchos::rcp(MOERTEL::PaddedMatrix(*map2,1.0,1)); tmp->FillComplete(); MOERTEL::MatrixMatrixAdd(*tmp,false,1.0,*Atildesplit_,1.0); Atildesplit_->FillComplete(); Atildesplit_->OptimizeStorage(); // split A // // A11 A12 // A21 A22 // Teuchos::RCP<Epetra_CrsMatrix> A11; Teuchos::RCP<Epetra_CrsMatrix> A12; Teuchos::RCP<Epetra_CrsMatrix> A21; Teuchos::RCP<Epetra_CrsMatrix> A22; MOERTEL::SplitMatrix2x2(A_,map1,map2,A11,A12,A21,A22); // build Asplit_ // // A11 0 // 0 A22 // Asplit_ = Teuchos::rcp(new Epetra_CrsMatrix(Copy,A_->RowMap(),50,false)); MOERTEL::MatrixMatrixAdd(*A11,false,1.0,*Asplit_,0.0); MOERTEL::MatrixMatrixAdd(*A22,false,1.0,*Asplit_,1.0); Asplit_->FillComplete(); Asplit_->OptimizeStorage(); // build BWT (padded to full size) // // 0 Mr Dinv // 0 I // Teuchos::RCP<Epetra_CrsMatrix> BWT = Teuchos::rcp(MOERTEL::MatMatMult(*B_,false,*WT_,false,10)); tmp = Teuchos::rcp(MOERTEL::PaddedMatrix(BWT->RowMap(),0.0,25)); MOERTEL::MatrixMatrixAdd(*BWT,false,1.0,*tmp,0.0); tmp->FillComplete(BWT->DomainMap(),BWT->RangeMap()); BWT = tmp; tmp = Teuchos::null; // split BWT to obtain M = Mr Dinv Teuchos::RCP<Epetra_CrsMatrix> Zero11; Teuchos::RCP<Epetra_CrsMatrix> M; Teuchos::RCP<Epetra_CrsMatrix> Zero21; Teuchos::RCP<Epetra_CrsMatrix> I22; MOERTEL::SplitMatrix2x2(BWT,map1,map2,Zero11,M,Zero21,I22); // build matrix Ahat11 = Atilde11 - M Atilde22 M^T Teuchos::RCP<Epetra_CrsMatrix> Ahat11 = Teuchos::rcp(new Epetra_CrsMatrix(Copy,*map1,50,false)); MOERTEL::MatrixMatrixAdd(*Atilde11,false,1.0,*Ahat11,0.0); Teuchos::RCP<Epetra_CrsMatrix> tmp1 = Teuchos::rcp(MOERTEL::MatMatMult(*Atilde22,false,*M,true,10)); Teuchos::RCP<Epetra_CrsMatrix> tmp2 = Teuchos::rcp(MOERTEL::MatMatMult(*M,false,*tmp1,false,10)); MOERTEL::MatrixMatrixAdd(*tmp2,false,-1.0,*Ahat11,1.0); Ahat11->FillComplete(); Ahat11->OptimizeStorage(); // build matrix Ahat // // Ahat11 0 = Atilde11 - M Atilde22 M^T 0 // 0 0 0 0 // Ahat_ = Teuchos::rcp(MOERTEL::PaddedMatrix(A_->RowMap(),0.0,25)); MOERTEL::MatrixMatrixAdd(*Ahat11,false,1.0,*Ahat_,0.0); Ahat_->FillComplete(); Ahat_->OptimizeStorage(); // build mlapi objects Space space(A_->RowMatrixRowMap()); Operator mlapiAsplit(space,space,Asplit_.get(),false); Operator mlapiAtildesplit(space,space,Atildesplit_.get(),false); Operator mlapiAhat(space,space,Ahat_.get(),false); Operator mlapiBWT(space,space,BWT.get(),false); Operator mlapiBWTcoarse; Operator ImBWTfine = GetIdentity(space,space) - mlapiBWT; Operator ImBWTcoarse; Operator Ptent; Operator P; Operator Pmod; Operator Rtent; Operator R; Operator Rmod; Operator IminusA; Operator C; InverseOperator S; mlapiAtildesplit_.resize(maxlevels); mlapiAhat_.resize(maxlevels); mlapiImBWT_.resize(maxlevels); mlapiImWBT_.resize(maxlevels); mlapiRmod_.resize(maxlevels); mlapiPmod_.resize(maxlevels); mlapiS_.resize(maxlevels); mlapiAtildesplit_[0] = mlapiAtildesplit; mlapiAhat_[0] = mlapiAhat; mlapiImBWT_[0] = ImBWTfine; mlapiImWBT_[0] = GetTranspose(ImBWTfine); // build nullspace MultiVector NS; MultiVector NextNS; NS.Reshape(mlapiAsplit.GetRangeSpace(),nsdim); if (nullspace) { for (int i=0; i<nsdim; ++i) for (int j=0; j<NS.GetMyLength(); ++j) NS(j,i) = nullspace[i*NS.GetMyLength()+j]; } else { if (numpde==1) NS = 1.0; else { NS = 0.0; for (int i=0; i<NS.GetMyLength(); ++i) for (int j=0; j<numpde; ++j) if ( i % numpde == j) NS(i,j) = 1.0; } } double lambdamax; // construct the hierarchy int level=0; for (level=0; level<maxlevels-1; ++level) { // this level's smoothing operator mlapiAtildesplit = mlapiAtildesplit_[level]; // build smoother if (Comm().MyPID()==0) { ML_print_line("-", 78); std::cout << "MOERTEL/ML : creating smoother level " << level << std::endl; fflush(stdout); } S.Reshape(mlapiAtildesplit,smoothertype,mlparams_); if (level) mlparams_.set("PDE equations", NS.GetNumVectors()); if (Comm().MyPID()==0) { ML_print_line("-", 80); std::cout << "MOERTEL/ML : creating level " << level+1 << std::endl; ML_print_line("-", 80); fflush(stdout); } mlparams_.set("workspace: current level",level); // get tentative prolongator based on decoupled original system GetPtent(mlapiAsplit,mlparams_,NS,Ptent,NextNS); NS = NextNS; // do prolongator smoothing if (damping) { if (eigenanalysis == "Anorm") lambdamax = MaxEigAnorm(mlapiAsplit,true); else if (eigenanalysis == "cg") lambdamax = MaxEigCG(mlapiAsplit,true); else if (eigenanalysis == "power-method") lambdamax = MaxEigPowerMethod(mlapiAsplit,true); else ML_THROW("incorrect parameter (" + eigenanalysis + ")", -1); IminusA = GetJacobiIterationOperator(mlapiAsplit,damping/lambdamax); P = IminusA * Ptent; R = GetTranspose(P); Rtent = GetTranspose(Ptent); } else { P = Ptent; Rtent = GetTranspose(Ptent); R = Rtent; lambdamax = -1.0; } // do variational coarse grid of split original matrix Asplit C = GetRAP(R,mlapiAsplit,P); // compute the mortar projections on coarse grid mlapiBWTcoarse = GetRAP(Rtent,mlapiBWT,Ptent); ImBWTcoarse = GetIdentity(C.GetDomainSpace(),C.GetRangeSpace()); ImBWTcoarse = ImBWTcoarse - mlapiBWTcoarse; // do modified prolongation and restriction if (ptype=="mod_full") Rmod = ImBWTcoarse * ( R * ImBWTfine ) + mlapiBWTcoarse * ( R * mlapiBWT ); else if (ptype=="mod_middle") Rmod = ImBWTcoarse * ( R * ImBWTfine ); else if (ptype=="mod_simple") Rmod = R * ImBWTfine; else if (ptype=="original") Rmod = R; else ML_THROW("incorrect parameter ( " + ptype + " )", -1); Pmod = GetTranspose(Rmod); // store matrix for construction of next level mlapiAsplit = C; // make coarse smoothing operator // make coarse residual operator mlapiAtildesplit_[level+1] = GetRAP(Rmod,mlapiAtildesplit,Pmod); mlapiAhat_[level+1] = GetRAP(Rmod,mlapiAhat_[level],Pmod); mlapiImBWT_[level] = ImBWTfine; mlapiImBWT_[level+1] = ImBWTcoarse; mlapiImWBT_[level] = GetTranspose(ImBWTfine); mlapiImWBT_[level+1] = GetTranspose(ImBWTcoarse); mlapiRmod_[level] = Rmod; mlapiPmod_[level] = Pmod; mlapiS_[level] = S; // prepare for next level mlapiBWT = mlapiBWTcoarse; ImBWTfine = ImBWTcoarse; // break if coarsest level is below specified size if (mlapiAsplit.GetNumGlobalRows() <= maxcoarsesize) { ++level; break; } } // for (level=0; level<maxlevels-1; ++level) // do coarse smoother S.Reshape(mlapiAtildesplit_[level],coarsetype,mlparams_); mlapiS_[level] = S; // store max number of levels maxlevels_ = level+1; iscomputed_ = true; return true; }