// ====================================================================== 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]; } }
// ====================================================================== // 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; }
// ====================================================================== void Krylov(const Operator& A, const MultiVector& LHS, const MultiVector& RHS, const BaseOperator& Prec, Teuchos::ParameterList& List) { #ifndef HAVE_ML_AZTECOO std::cerr << "Please configure ML with --enable-aztecoo to use" << std::endl; std::cerr << "MLAPI Krylov solvers" << std::endl; exit(EXIT_FAILURE); #else if (LHS.GetNumVectors() != 1) ML_THROW("FIXME: only one vector is currently supported", -1); Epetra_LinearProblem Problem; const Epetra_RowMatrix& A_Epetra = *(A.GetRowMatrix()); Epetra_Vector LHS_Epetra(View,A_Epetra.OperatorDomainMap(), (double*)&(LHS(0))); Epetra_Vector RHS_Epetra(View,A_Epetra.OperatorRangeMap(), (double*)&(RHS(0))); // FIXME: this works only for Epetra-based operators Problem.SetOperator((const_cast<Epetra_RowMatrix*>(&A_Epetra))); Problem.SetLHS(&LHS_Epetra); Problem.SetRHS(&RHS_Epetra); AztecOO solver(Problem); EpetraBaseOperator Prec_Epetra(A_Epetra.OperatorDomainMap(),Prec); solver.SetPrecOperator(&Prec_Epetra); // get options from List int NumIters = List.get("krylov: max iterations", 1550); double Tol = List.get("krylov: tolerance", 1e-9); std::string type = List.get("krylov: type", "gmres"); int output = List.get("krylov: output level", GetPrintLevel()); // set options in `solver' if (type == "cg") solver.SetAztecOption(AZ_solver, AZ_cg); else if (type == "cg_condnum") solver.SetAztecOption(AZ_solver, AZ_cg_condnum); else if (type == "gmres") solver.SetAztecOption(AZ_solver, AZ_gmres); else if (type == "gmres_condnum") solver.SetAztecOption(AZ_solver, AZ_gmres_condnum); else if (type == "fixed point") solver.SetAztecOption(AZ_solver, AZ_fixed_pt); else ML_THROW("krylov: type has incorrect value (" + type + ")", -1); solver.SetAztecOption(AZ_output, output); solver.Iterate(NumIters, Tol); #endif }
// ====================================================================== Operator GetPtent1D(const MultiVector& D, const int offset = 0) { if (D.GetNumVectors() != 1) ML_THROW("D.GetNumVectors() != 1", -1); int size = D.GetMyLength(); if (size == 0) ML_THROW("empty diagonal vector in input", -1); double* diag = new double[size]; for (int i = 0 ; i < size ; ++i) diag[i] = D(i); // creates the ML operator and store the diag pointer, // as well as the function pointers ML_Operator* MLDiag = ML_Operator_Create(GetML_Comm()); int invec_leng = size / 3 + size % 3; int outvec_leng = size; MLDiag->invec_leng = invec_leng; MLDiag->outvec_leng = outvec_leng; MLDiag->data = (void*)diag; MLDiag->data_destroy = Ptent1D_destroy; MLDiag->matvec->func_ptr = Ptent1D_matvec; MLDiag->matvec->ML_id = ML_NONEMPTY; MLDiag->matvec->Nrows = outvec_leng; MLDiag->from_an_ml_operator = 0; MLDiag->getrow->func_ptr = Ptent1D_getrows; MLDiag->getrow->ML_id = ML_NONEMPTY; MLDiag->getrow->Nrows = outvec_leng; // creates the domain space vector<int> MyGlobalElements(invec_leng); for (int i = 0 ; i < invec_leng ; ++i) MyGlobalElements[i] = D.GetVectorSpace()(i * 3) / 3; Space DomainSpace(invec_leng, -1, &MyGlobalElements[0]); Space RangeSpace = D.GetVectorSpace(); // creates the MLAPI wrapper Operator Diag(DomainSpace,RangeSpace,MLDiag,true); return(Diag); }
int InverseOperator::Apply(const MultiVector& x, MultiVector& y) const { ResetTimer(); StackPush(); if (GetDomainSpace() != x.GetVectorSpace()) ML_THROW("DomainSpace and x.GetVectorSpace() differ", -1); if (GetRangeSpace() != y.GetVectorSpace()) ML_THROW("RangeSpace and y.GetVectorSpace() differ", -1); int x_nv = x.GetNumVectors(); int y_nv = y.GetNumVectors(); double FL = 0.0; if (RCPData_ != Teuchos::null) FL = RCPData_->ComputeFlops(); if (x_nv != y_nv) ML_THROW("Number of vectors of x and y differ (" + GetString(x_nv) + " vs. " + GetString(x_nv), -1); for (int v = 0 ; v < x_nv ; ++v) { Epetra_Vector x_Epetra(View,RowMatrix()->OperatorDomainMap(), (double*)&(x(0,v))); Epetra_Vector y_Epetra(View,RowMatrix()->OperatorRangeMap(), (double*)&(y(0,v))); if (RCPData_ != Teuchos::null) RCPData_->ApplyInverse(x_Epetra,y_Epetra); else if (RCPMLPrec_ != Teuchos::null) RCPMLPrec_->ApplyInverse(x_Epetra,y_Epetra); else ML_THROW("Neither Ifpack nor ML smoother is properly set up", -1); } StackPop(); if (RCPData_ != Teuchos::null) UpdateFlops(RCPData_->ComputeFlops() - FL); UpdateTime(); return(0); }
// ====================================================================== MultiVector Extract(const MultiVector& y, const int v) { if ((v < 0) || v >= y.GetNumVectors()) ML_THROW("Wrong input parameter v (" + GetString(v) + ")", -1); MultiVector x(y.GetVectorSpace(), y.GetRCPValues(v)); return(x); }
// ====================================================================== MultiVector Redistribute(const MultiVector& y, const int NumEquations) { StackPush(); if (y.GetMyLength() % NumEquations) ML_THROW("NumEquations does not divide MyLength()", -1); if (y.GetNumVectors() != 1) ML_THROW("Redistribute() works with single vectors only", -1); Space NewSpace(y.GetMyLength() / NumEquations); MultiVector y2(NewSpace, NumEquations); for (int i = 0 ; i < y2.GetMyLength() ; ++i) for (int j = 0 ; j < NumEquations ; ++j) y2(i, j) = y(j + NumEquations * i); StackPop(); return(y2); }
// ====================================================================== MultiVector Duplicate(const MultiVector& y, const int v) { if ((v < 0) || v >= y.GetNumVectors()) ML_THROW("Wrong input parameter v (" + GetString(v) + ")", -1); // FIXME: use Extract MultiVector x(y.GetVectorSpace(), 1); for (int i = 0 ; i < x.GetMyLength() ; ++i) x(i) = y(i,v); return(x); }
// ====================================================================== 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); }
// ====================================================================== Operator GetDiagonal(const MultiVector& D) { if (D.GetNumVectors() != 1) ML_THROW("D.GetNumVectors() != 1", -1); int size = D.GetMyLength(); if (size == 0) ML_THROW("empty diagonal vector in input", -1); double* diag = new double[size]; for (int i = 0 ; i < size ; ++i) diag[i] = D(i); // creates the ML operator and store the diag pointer, // as well as the function pointers ML_Operator* MLDiag = ML_Operator_Create(GetML_Comm()); MLDiag->invec_leng = size; MLDiag->outvec_leng = size; MLDiag->data = (void*)diag; MLDiag->matvec->func_ptr = diag_matvec; MLDiag->matvec->ML_id = ML_NONEMPTY; MLDiag->matvec->Nrows = size; MLDiag->from_an_ml_operator = 0; MLDiag->data_destroy = diag_destroy; MLDiag->getrow->func_ptr = diag_getrows; MLDiag->getrow->ML_id = ML_NONEMPTY; MLDiag->getrow->Nrows = size; // creates the MLAPI wrapper Operator Diag(D.GetVectorSpace(),D.GetVectorSpace(),MLDiag,true); return(Diag); }
// ====================================================================== double MaxEigAnasazi(const Operator& Op, const bool DiagonalScaling) { double MaxEigen = 0.0; #if defined(HAVE_ML_EPETRA) && defined(HAVE_ML_ANASAxI) && defined(HAVE_ML_TEUCHOS) bool DiagScal; if (DiagonalScaling) DiagScal = ML_TRUE; else DiagScal = ML_FALSE; ML_Anasazi_Get_SpectralNorm_Anasazi(Op.GetML_Operator(), 0, 10, 1e-5, ML_FALSE, DiagScal, &MaxEigen); #else //ML_THROW("Configure w/ --enable-epetra --enable-anasazi --enable-teuchos", -1); ML_THROW("Anasazi is no longer supported", -1); #endif return(MaxEigen); }
// ====================================================================== void GetPtent(const Operator& A, Teuchos::ParameterList& List, const MultiVector& ThisNS, Operator& Ptent, MultiVector& NextNS) { std::string CoarsenType = List.get("aggregation: type", "Uncoupled"); /* old version int NodesPerAggr = List.get("aggregation: per aggregate", 64); */ double Threshold = List.get("aggregation: threshold", 0.0); int NumPDEEquations = List.get("PDE equations", 1); ML_Aggregate* agg_object; ML_Aggregate_Create(&agg_object); ML_Aggregate_Set_MaxLevels(agg_object,2); ML_Aggregate_Set_StartLevel(agg_object,0); ML_Aggregate_Set_Threshold(agg_object,Threshold); //agg_object->curr_threshold = 0.0; ML_Operator* ML_Ptent = 0; ML_Ptent = ML_Operator_Create(GetML_Comm()); if (ThisNS.GetNumVectors() == 0) ML_THROW("zero-dimension null space", -1); int size = ThisNS.GetMyLength(); double* null_vect = 0; ML_memory_alloc((void **)(&null_vect), sizeof(double) * size * ThisNS.GetNumVectors(), "ns"); int incr = 1; for (int v = 0 ; v < ThisNS.GetNumVectors() ; ++v) DCOPY_F77(&size, (double*)ThisNS.GetValues(v), &incr, null_vect + v * ThisNS.GetMyLength(), &incr); ML_Aggregate_Set_NullSpace(agg_object, NumPDEEquations, ThisNS.GetNumVectors(), null_vect, ThisNS.GetMyLength()); if (CoarsenType == "Uncoupled") agg_object->coarsen_scheme = ML_AGGR_UNCOUPLED; else if (CoarsenType == "Uncoupled-MIS") agg_object->coarsen_scheme = ML_AGGR_HYBRIDUM; else if (CoarsenType == "MIS") { /* needed for MIS, otherwise it sets the number of equations to * the null space dimension */ agg_object->max_levels = -7; agg_object->coarsen_scheme = ML_AGGR_MIS; } else if (CoarsenType == "METIS") agg_object->coarsen_scheme = ML_AGGR_METIS; else { ML_THROW("Requested aggregation scheme (" + CoarsenType + ") not recognized", -1); } int NextSize = ML_Aggregate_Coarsen(agg_object, A.GetML_Operator(), &ML_Ptent, GetML_Comm()); /* This is the old version int NextSize; if (CoarsenType == "Uncoupled") { NextSize = ML_Aggregate_CoarsenUncoupled(agg_object, A.GetML_Operator(), } else if (CoarsenType == "MIS") { NextSize = ML_Aggregate_CoarsenMIS(agg_object, A.GetML_Operator(), &ML_Ptent, GetML_Comm()); } else if (CoarsenType == "METIS") { ML ml_object; ml_object.ML_num_levels = 1; // crap for line below ML_Aggregate_Set_NodesPerAggr(&ml_object,agg_object,0,NodesPerAggr); NextSize = ML_Aggregate_CoarsenMETIS(agg_object, A.GetML_Operator(), &ML_Ptent, GetML_Comm()); } else { ML_THROW("Requested aggregation scheme (" + CoarsenType + ") not recognized", -1); } */ ML_Operator_ChangeToSinglePrecision(ML_Ptent); int NumMyElements = NextSize; Space CoarseSpace(-1,NumMyElements); Ptent.Reshape(CoarseSpace,A.GetRangeSpace(),ML_Ptent,true); assert (NextSize * ThisNS.GetNumVectors() != 0); NextNS.Reshape(CoarseSpace, ThisNS.GetNumVectors()); size = NextNS.GetMyLength(); for (int v = 0 ; v < NextNS.GetNumVectors() ; ++v) DCOPY_F77(&size, agg_object->nullspace_vect + v * size, &incr, NextNS.GetValues(v), &incr); ML_Aggregate_Destroy(&agg_object); ML_memory_free((void**)(&null_vect)); }
// ====================================================================== void GetPtent(const Epetra_RowMatrix& A, Teuchos::ParameterList& List, double* thisns, Teuchos::RCP<Epetra_CrsMatrix>& Ptent, Teuchos::RCP<Epetra_MultiVector>& NextNS, const int domainoffset) { const int nsdim = List.get<int>("null space: dimension",-1); if (nsdim<=0) ML_THROW("null space dimension not given",-1); const Epetra_Map& rowmap = A.RowMatrixRowMap(); const int mylength = rowmap.NumMyElements(); // wrap nullspace into something more handy Epetra_MultiVector ns(View,rowmap,thisns,mylength,nsdim); // vector to hold aggregation information Epetra_IntVector aggs(rowmap,false); // aggregation with global aggregate numbering int naggregates = GetGlobalAggregates(const_cast<Epetra_RowMatrix&>(A),List,thisns,aggs); // build a domain map for Ptent // find first aggregate on proc int firstagg = -1; int offset = -1; for (int i=0; i<mylength; ++i) if (aggs[i]>=0) { offset = firstagg = aggs[i]; break; } offset *= nsdim; if (offset<0) ML_THROW("could not find any aggregate on proc",-2); std::vector<int> coarsegids(naggregates*nsdim); for (int i=0; i<naggregates; ++i) for (int j=0; j<nsdim; ++j) { coarsegids[i*nsdim+j] = offset + domainoffset; ++offset; } Epetra_Map pdomainmap(-1,naggregates*nsdim,&coarsegids[0],0,A.Comm()); // loop aggregates and build ids for dofs std::map<int,std::vector<int> > aggdofs; std::map<int,std::vector<int> >::iterator fool; for (int i=0; i<naggregates; ++i) { std::vector<int> gids(0); aggdofs.insert(std::pair<int,std::vector<int> >(firstagg+i,gids)); } for (int i=0; i<mylength; ++i) { if (aggs[i]<0) continue; std::vector<int>& gids = aggdofs[aggs[i]]; gids.push_back(aggs.Map().GID(i)); } #if 0 // debugging output for (int proc=0; proc<A.Comm().NumProc(); ++proc) { if (proc==A.Comm().MyPID()) { for (fool=aggdofs.begin(); fool!=aggdofs.end(); ++fool) { std::cout << "Proc " << proc << " Aggregate " << fool->first << " Dofs "; std::vector<int>& gids = fool->second; for (int i=0; i<(int)gids.size(); ++i) std::cout << gids[i] << " "; std::cout << std::endl; } } fflush(stdout); A.Comm().Barrier(); } #endif // coarse level nullspace to be filled NextNS = Teuchos::rcp(new Epetra_MultiVector(pdomainmap,nsdim,true)); Epetra_MultiVector& nextns = *NextNS; // matrix Ptent Ptent = Teuchos::rcp(new Epetra_CrsMatrix(Copy,rowmap,nsdim)); // loop aggregates and extract the appropriate slices of the nullspace. // do QR and assemble Q and R to Ptent and NextNS for (fool=aggdofs.begin(); fool!=aggdofs.end(); ++fool) { // extract aggregate-local junk of nullspace const int aggsize = (int)fool->second.size(); Epetra_SerialDenseMatrix Bagg(aggsize,nsdim); for (int i=0; i<aggsize; ++i) for (int j=0; j<nsdim; ++j) Bagg(i,j) = (*ns(j))[ns.Map().LID(fool->second[i])]; // Bagg = Q*R int m = Bagg.M(); int n = Bagg.N(); int lwork = n*10; int info = 0; int k = std::min(m,n); if (k!=n) ML_THROW("Aggregate too small, fatal!",-1); std::vector<double> work(lwork); std::vector<double> tau(k); Epetra_LAPACK lapack; lapack.GEQRF(m,n,Bagg.A(),m,&tau[0],&work[0],lwork,&info); if (info) ML_THROW("Lapack dgeqrf returned nonzero",info); if (work[0]>lwork) { lwork = (int)work[0]; work.resize(lwork); } // get R (stored on Bagg) and assemble it into nextns int agg_cgid = fool->first*nsdim; if (!nextns.Map().MyGID(agg_cgid+domainoffset)) ML_THROW("Missing coarse column id on this proc",-1); for (int i=0; i<n; ++i) for (int j=i; j<n; ++j) (*nextns(j))[nextns.Map().LID(domainoffset+agg_cgid+i)] = Bagg(i,j); // get Q and assemble it into Ptent lapack.ORGQR(m,n,k,Bagg.A(),m,&tau[0],&work[0],lwork,&info); if (info) ML_THROW("Lapack dorgqr returned nonzero",info); for (int i=0; i<aggsize; ++i) { const int actgrow = fool->second[i]; for (int j=0; j<nsdim; ++j) { int actgcol = fool->first*nsdim+j+domainoffset; int errone = Ptent->SumIntoGlobalValues(actgrow,1,&Bagg(i,j),&actgcol); if (errone>0) { int errtwo = Ptent->InsertGlobalValues(actgrow,1,&Bagg(i,j),&actgcol); if (errtwo<0) ML_THROW("Epetra_CrsMatrix::InsertGlobalValues returned negative nonzero",errtwo); } else if (errone) ML_THROW("Epetra_CrsMatrix::SumIntoGlobalValues returned negative nonzero",errone); } } // for (int i=0; i<aggsize; ++i) } // for (fool=aggdofs.begin(); fool!=aggdofs.end(); ++fool) int err = Ptent->FillComplete(pdomainmap,rowmap); if (err) ML_THROW("Epetra_CrsMatrix::FillComplete returned nonzero",err); err = Ptent->OptimizeStorage(); if (err) ML_THROW("Epetra_CrsMatrix::OptimizeStorage returned nonzero",err); return; }
// ====================================================================== int GetAggregates(Epetra_RowMatrix& A, Teuchos::ParameterList& List, double* thisns, Epetra_IntVector& aggrinfo) { if (!A.RowMatrixRowMap().SameAs(aggrinfo.Map())) ML_THROW("map of aggrinfo must match row map of operator", -1); std::string CoarsenType = List.get("aggregation: type", "Uncoupled"); double Threshold = List.get("aggregation: threshold", 0.0); int NumPDEEquations = List.get("PDE equations", 1); int nsdim = List.get("null space: dimension",-1); if (nsdim==-1) ML_THROW("dimension of nullspace not set", -1); int size = A.RowMatrixRowMap().NumMyElements(); ML_Aggregate* agg_object; ML_Aggregate_Create(&agg_object); ML_Aggregate_KeepInfo(agg_object,1); ML_Aggregate_Set_MaxLevels(agg_object,2); ML_Aggregate_Set_StartLevel(agg_object,0); ML_Aggregate_Set_Threshold(agg_object,Threshold); //agg_object->curr_threshold = 0.0; ML_Operator* ML_Ptent = 0; ML_Ptent = ML_Operator_Create(GetML_Comm()); if (!thisns) ML_THROW("nullspace is NULL", -1); ML_Aggregate_Set_NullSpace(agg_object, NumPDEEquations, nsdim, thisns,size); if (CoarsenType == "Uncoupled") agg_object->coarsen_scheme = ML_AGGR_UNCOUPLED; else if (CoarsenType == "Uncoupled-MIS") agg_object->coarsen_scheme = ML_AGGR_HYBRIDUM; else if (CoarsenType == "MIS") { /* needed for MIS, otherwise it sets the number of equations to * the null space dimension */ agg_object->max_levels = -7; agg_object->coarsen_scheme = ML_AGGR_MIS; } else if (CoarsenType == "METIS") agg_object->coarsen_scheme = ML_AGGR_METIS; else { ML_THROW("Requested aggregation scheme (" + CoarsenType + ") not recognized", -1); } ML_Operator* ML_A = ML_Operator_Create(GetML_Comm()); ML_Operator_WrapEpetraMatrix(&A,ML_A); int NextSize = ML_Aggregate_Coarsen(agg_object, ML_A, &ML_Ptent, GetML_Comm()); int* aggrmap = NULL; ML_Aggregate_Get_AggrMap(agg_object,0,&aggrmap); if (!aggrmap) ML_THROW("aggr_info not available", -1); #if 0 // debugging fflush(stdout); for (int proc=0; proc<A.GetRowMatrix()->Comm().NumProc(); ++proc) { if (A.GetRowMatrix()->Comm().MyPID()==proc) { std::cout << "Proc " << proc << ":" << std::endl; std::cout << "aggrcount " << aggrcount << std::endl; std::cout << "NextSize " << NextSize << std::endl; for (int i=0; i<size; ++i) std::cout << "aggrmap[" << i << "] = " << aggrmap[i] << std::endl; fflush(stdout); } A.GetRowMatrix()->Comm().Barrier(); } #endif assert (NextSize * nsdim != 0); for (int i=0; i<size; ++i) aggrinfo[i] = aggrmap[i]; ML_Aggregate_Destroy(&agg_object); return (NextSize/nsdim); }
void InverseOperator::Reshape(const Operator& Op, const string Type, Teuchos::ParameterList& List, Teuchos::ParameterList* pushlist) { ResetTimer(); StackPush(); Op_ = Op; RCPRowMatrix_ = Op.GetRCPRowMatrix(); // FIXME: to add overlap and level-of-fill int NumSweeps = List.get("smoother: sweeps", 1); double Damping = List.get("smoother: damping factor", 0.67); int LOF_ilu = List.get("smoother: ilu fill", 0); double LOF_ict = List.get("smoother: ilut fill", 1.0); double LOF_ilut = List.get("smoother: ict fill", 1.0); string reorder = List.get("schwarz: reordering type","rcm"); Teuchos::ParameterList IFPACKList; // any parameters from the main list List are overwritten by the pushlist IFPACKList.set("relaxation: sweeps", NumSweeps); IFPACKList.set("relaxation: damping factor", Damping); IFPACKList.set("fact: level-of-fill", LOF_ilu); IFPACKList.set("fact: ict level-of-fill", LOF_ict); IFPACKList.set("fact: ilut level-of-fill", LOF_ilut); IFPACKList.set("relaxation: zero starting solution", false); IFPACKList.set("schwarz: reordering type",reorder); IFPACKList.set("fact: relative threshold",1.0); // if present, the pushlist is assumed to be a preconstructed ifpack list // that is copied straight to the ifpack list here // entries in pushlist overwrite previous list entries if (pushlist) IFPACKList.setParameters(*pushlist); bool verbose = false; //(GetMyPID() == 0 && GetPrintLevel() > 5); // the ML smoother RCPMLPrec_ = Teuchos::null; // The Ifpack smoother Ifpack_Preconditioner* Prec = NULL; if (Type == "Jacobi") { if (verbose) { cout << "Damping factor = " << Damping << ", sweeps = " << NumSweeps << endl; cout << endl; } IFPACKList.set("relaxation: type", "Jacobi"); Prec = new Ifpack_PointRelaxation(RowMatrix()); } else if (Type == "Gauss-Seidel") { if (verbose) { cout << "Damping factor = " << Damping << ", sweeps = " << NumSweeps << endl; cout << endl; } IFPACKList.set("relaxation: type", "Gauss-Seidel"); Prec = new Ifpack_PointRelaxation(RowMatrix()); } else if (Type == "symmetric Gauss-Seidel") { if (verbose) { cout << "Damping factor = " << Damping << ", sweeps = " << NumSweeps << endl; cout << endl; } IFPACKList.set("relaxation: type", "symmetric Gauss-Seidel"); Prec = new Ifpack_PointRelaxation(RowMatrix()); } else if (Type == "ILU") { if (verbose) { cout << "ILU factorization, ov = 0, no reordering, LOF = " << LOF_ilu << endl; cout << endl; } // use the Additive Schwarz class because it does reordering Prec = new Ifpack_AdditiveSchwarz<Ifpack_ILU>(RowMatrix()); } else if (Type == "ILUT") { if (verbose) { cout << "ILUT factorization, ov = 0, no reordering, LOF = " << LOF_ilu << endl; cout << endl; } Prec = new Ifpack_ILUT(RowMatrix()); } else if (Type == "IC") { if (verbose) { cout << "IC factorization, ov = 0, no reordering, LOF = " << LOF_ilu << endl; cout << endl; } Prec = new Ifpack_IC(RowMatrix()); } else if (Type == "ICT") { if (verbose) { cout << "ICT factorization, ov = 0, no reordering, LOF = " << LOF_ilu << endl; cout << endl; } Prec = new Ifpack_ICT(RowMatrix()); } else if (Type == "LU") { if (verbose) { cout << "LU factorization, ov = 0, local solver = KLU" << endl; cout << endl; } Prec = new Ifpack_AdditiveSchwarz<Ifpack_Amesos>(RowMatrix()); } else if (Type == "Amesos" || Type == "Amesos-KLU") { if (verbose) { cout << "Amesos-KLU direct solver" << endl; cout << endl; } Prec = new Ifpack_Amesos(RowMatrix()); } else if (Type == "MLS" || Type == "ML MLS" || Type == "ML symmetric Gauss-Seidel" || Type == "ML Gauss-Seidel") { if (verbose) { cout << "ML's MLS smoother" << endl; cout << endl; } Teuchos::ParameterList mlparams; ML_Epetra::SetDefaults("SA",mlparams); int output = List.get("ML output",-47); if (output == -47) output = List.get("output",-1); if (output != -1) mlparams.set("ML output",output); mlparams.set("max levels",1); int sweeps = List.get("smoother: sweeps",1); mlparams.set("coarse: sweeps",sweeps); double damp = List.get("smoother: damping factor",0.67); mlparams.set("coarse: damping factor",damp); mlparams.set("zero starting solution", false); if (Type == "MLS" || Type == "ML MLS") { mlparams.set("coarse: type","MLS"); // MLS symmetric Gauss-Seidel Amesos-KLU int poly = List.get("smoother: MLS polynomial order",3); mlparams.set("coarse: MLS polynomial order",poly); } else if (Type == "ML symmetric Gauss-Seidel") mlparams.set("coarse: type","symmetric Gauss-Seidel"); // MLS symmetric Gauss-Seidel Amesos-KLU else if (Type == "ML Gauss-Seidel") mlparams.set("coarse: type","Gauss-Seidel"); else if (Type == "ML Jacobi") mlparams.set("coarse: type","Jacobi"); else ML_THROW("Requested type (" + Type + ") not recognized", -1); RCPMLPrec_ = Teuchos::rcp(new ML_Epetra::MultiLevelPreconditioner(*RowMatrix(),mlparams,true)); } else ML_THROW("Requested type (" + Type + ") not recognized", -1); if (Prec) { RCPData_ = Teuchos::rcp(Prec); RCPData_->SetParameters(IFPACKList); RCPData_->Initialize(); RCPData_->Compute(); UpdateFlops(RCPData_->InitializeFlops()); UpdateFlops(RCPData_->ComputeFlops()); } else RCPData_ = Teuchos::null; StackPop(); UpdateTime(); }