/*! * \brief Solve. */ void JacobiSolver::iterate( const int max_iters, const double tolerance ) { // Extract the linear problem. Epetra_CrsMatrix *A = dynamic_cast<Epetra_CrsMatrix*>( d_linear_problem->GetMatrix() ); Epetra_Vector *x = dynamic_cast<Epetra_Vector*>( d_linear_problem->GetLHS() ); const Epetra_Vector *b = dynamic_cast<Epetra_Vector*>( d_linear_problem->GetRHS() ); // Setup the residual. Epetra_Map row_map = A->RowMap(); Epetra_Vector residual( row_map ); // Iterate. Epetra_CrsMatrix H = buildH( A ); Epetra_Vector temp_vec( row_map ); d_num_iters = 0; double residual_norm = 1.0; double b_norm; b->NormInf( &b_norm ); double conv_crit = b_norm*tolerance; while ( residual_norm > conv_crit && d_num_iters < max_iters ) { H.Apply( *x, temp_vec ); x->Update( 1.0, temp_vec, 1.0, *b, 0.0 ); A->Apply( *x, temp_vec ); residual.Update( 1.0, *b, -1.0, temp_vec, 0.0 ); residual.NormInf( &residual_norm ); ++d_num_iters; } }
// B here is the "reduced" matrix. Square matrices w/ Row=Domain=Range only. double test_with_matvec_reduced_maps(const Epetra_CrsMatrix &A, const Epetra_CrsMatrix &B, const Epetra_Map & Bfullmap){ const Epetra_Map & Amap = A.DomainMap(); Epetra_Vector Xa(Amap), Ya(Amap), Diff(Amap); const Epetra_Map *Bmap = Bfullmap.NumMyElements() > 0 ? &B.DomainMap() : 0; Epetra_Vector *Xb = Bmap ? new Epetra_Vector(*Bmap) : 0; Epetra_Vector *Yb = Bmap ? new Epetra_Vector(*Bmap) : 0; Epetra_Vector Xb_alias(View,Bfullmap, Bmap ? Xb->Values(): 0); Epetra_Vector Yb_alias(View,Bfullmap, Bmap ? Yb->Values(): 0); Epetra_Import Ximport(Bfullmap,Amap); // Set the input vector Xa.SetSeed(24601); Xa.Random(); Xb_alias.Import(Xa,Ximport,Insert); // Do the multiplies A.Apply(Xa,Ya); if(Bmap) B.Apply(*Xb,*Yb); // Check solution Epetra_Import Yimport(Amap,Bfullmap); Diff.Import(Yb_alias,Yimport,Insert); Diff.Update(-1.0,Ya,1.0); double norm; Diff.Norm2(&norm); delete Xb; delete Yb; return norm; }
void PhcGeoMGPrec::GetBoundaryBulkResiduals (const Epetra_CrsMatrix & op, const Epetra_MultiVector & x, const Epetra_MultiVector & b, double & bndryRes, double & bulkRes, double & totalRes, int level) const { Epetra_MultiVector work(x); op.Apply(x, work); work.Update(-1., b, 1.); bndryRes=0.; bulkRes=0.; totalRes=0.; int numInds = x.Map().getNodeNumElements(); double * vals = work[0]; for (int i=0; i<numInds; i++) { double val = vals[i]; double afrac = (*dmAreas_[level])[i]; if ((afrac==0.) || (afrac==1.)) bulkRes += val*val; else { //std::cout << "afrac: " << afrac << std::endl; bndryRes += val*val; } totalRes += val*val; } bulkRes = sqrt(bulkRes); bndryRes = sqrt(bndryRes); totalRes = sqrt(totalRes); }
double MxGeoMultigridPrec::getResidual(const Epetra_CrsMatrix & op, const Epetra_MultiVector & x, const Epetra_MultiVector & b) const { Epetra_MultiVector work(x); op.Apply(x, work); work.Update(-1., b, 1.); double res; work.Norm2(&res); return res; }
double test_with_matvec(const Epetra_CrsMatrix &A, const Epetra_CrsMatrix &B){ const Epetra_Map & Xamap = A.DomainMap(); const Epetra_Map & Yamap = A.RangeMap(); const Epetra_Map & Xbmap = B.DomainMap(); const Epetra_Map & Ybmap = B.RangeMap(); Epetra_Vector Xa(Xamap), Xb(Xbmap), Ya(Yamap), Yb(Ybmap), Diff(Yamap); Xa.SetSeed(24601); Xa.Random(); // Handle domain map change if(!Xamap.SameAs(Xbmap)) { Epetra_Import Ximport(Xbmap,Xamap); Xb.Import(Xa,Ximport,Insert); } else { Xb=Xa; } // Do the multiplies A.Apply(Xa,Ya); B.Apply(Xb,Yb); // Handle Rangemap change if(!Yamap.SameAs(Ybmap)) { Epetra_Import Yimport(Yamap,Ybmap); Diff.Import(Yb,Yimport,Insert); } else { Diff=Yb; } // Check solution Diff.Update(-1.0,Ya,1.0); double norm; Diff.Norm2(&norm); return norm; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc,&argv); Epetra_MpiComm comm (MPI_COMM_WORLD); #else Epetra_SerialComm comm; #endif int MyPID = comm.MyPID(); bool verbose = false; bool verbose1 = false; // Check if we should print results to standard out if (argc > 1) { if ((argv[1][0] == '-') && (argv[1][1] == 'v')) { verbose1 = true; if (MyPID==0) verbose = true; } } if (verbose1) cout << comm << endl; // Uncomment the next three lines to debug in mpi mode //int tmp; //if (MyPID==0) cin >> tmp; //comm.Barrier(); Epetra_CrsMatrix * A; EPETRA_CHK_ERR(EpetraExt::MatlabFileToCrsMatrix("A.dat", comm, A)); Epetra_Vector x(A->OperatorDomainMap()); Epetra_Vector b(A->OperatorRangeMap()); x.Random(); A->Apply(x,b); // Generate RHS from x Epetra_Vector xx(x); // Copy x to xx for later use Epetra_LinearProblem problem(A, &x, &b); // Construct a solver object for this problem AztecOO solver(problem); solver.SetAztecOption(AZ_precond, AZ_none); if (!verbose1) solver.SetAztecOption(AZ_output, AZ_none); solver.SetAztecOption(AZ_kspace, A->NumGlobalRows()); AztecOO_Operator AOpInv(&solver, A->NumGlobalRows()); Epetra_InvOperator AInvOp(&AOpInv); EPETRA_CHK_ERR(EpetraExt::OperatorToMatlabFile("Ainv.dat", AInvOp)); comm.Barrier(); Epetra_CrsMatrix * AInv; EPETRA_CHK_ERR(EpetraExt::MatlabFileToCrsMatrix("Ainv.dat", comm, AInv)); EPETRA_CHK_ERR(AInv->Apply(b,x)); EPETRA_CHK_ERR(x.Update(1.0, xx, -1.0)); double residual = 0.0; EPETRA_CHK_ERR(x.Norm2(&residual)); if (verbose) cout << "Norm of difference between computed x and exact x = " << residual << endl; int ierr = checkValues(residual,0.0,"Norm of difference between computed A1x1 and A1x1 from file", verbose); delete A; delete AInv; #ifdef HAVE_MPI MPI_Finalize() ; #endif return(ierr); }