int main(int argc, char* argv[]) { // // Get a default output stream from the Teuchos::VerboseObjectBase // Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); Teuchos::GlobalMPISession mpiSession(&argc,&argv); #ifdef HAVE_COMPLEX typedef std::complex<double> ST; // Scalar-type typedef #elif HAVE_COMPLEX_H typedef std::complex<double> ST; // Scalar-type typedef #else typedef double ST; // Scalar-type typedef #endif typedef Teuchos::ScalarTraits<ST>::magnitudeType MT; // Magnitude-type typedef typedef int OT; // Ordinal-type typedef ST one = Teuchos::ScalarTraits<ST>::one(); ST zero = Teuchos::ScalarTraits<ST>::zero(); #ifdef HAVE_MPI MPI_Comm mpiComm = MPI_COMM_WORLD; const Tpetra::MpiPlatform<OT,OT> ordinalPlatform(mpiComm); const Tpetra::MpiPlatform<OT,ST> scalarPlatform(mpiComm); #else const Tpetra::SerialPlatform<OT,OT> ordinalPlatform; const Tpetra::SerialPlatform<OT,ST> scalarPlatform; #endif // // Get the data from the HB file // // Name of input matrix file std::string matrixFile = "mhd1280b.cua"; int info=0; int dim,dim2,nnz; MT *dvals; int *colptr,*rowind; ST *cvals; nnz = -1; info = readHB_newmat_double(matrixFile.c_str(),&dim,&dim2,&nnz, &colptr,&rowind,&dvals); if (info == 0 || nnz < 0) { *out << "Error reading '" << matrixFile << "'" << std::endl; } #ifdef HAVE_MPI MPI_Finalize(); #endif // Convert interleaved doubles to std::complex values cvals = new ST[nnz]; for (int ii=0; ii<nnz; ii++) { cvals[ii] = ST(dvals[ii*2],dvals[ii*2+1]); } // Declare global dimension of the linear operator OT globalDim = dim; // Create the element space and std::vector space const Tpetra::ElementSpace<OT> elementSpace(globalDim,0,ordinalPlatform); const Tpetra::VectorSpace<OT,ST> vectorSpace(elementSpace,scalarPlatform); // Create my implementation of a Tpetra::Operator RCP<Tpetra::Operator<OT,ST> > tpetra_A = rcp( new MyOperator<OT,ST>(vectorSpace,dim,colptr,nnz,rowind,cvals) ); // Create a Thyra linear operator (A) using the Tpetra::CisMatrix (tpetra_A). RCP<Thyra::LinearOpBase<ST> > A = Teuchos::rcp( new Thyra::TpetraLinearOp<OT,ST>(tpetra_A) ); // // Set the parameters for the Belos LOWS Factory and create a parameter list. // int blockSize = 1; int maxIterations = globalDim; int maxRestarts = 15; int gmresKrylovLength = 50; int outputFrequency = 100; bool outputMaxResOnly = true; MT maxResid = 1e-5; Teuchos::RCP<Teuchos::ParameterList> belosLOWSFPL = Teuchos::rcp( new Teuchos::ParameterList() ); belosLOWSFPL->set("Solver Type","Block GMRES"); Teuchos::ParameterList& belosLOWSFPL_solver = belosLOWSFPL->sublist("Solver Types"); Teuchos::ParameterList& belosLOWSFPL_gmres = belosLOWSFPL_solver.sublist("Block GMRES"); belosLOWSFPL_gmres.set("Maximum Iterations",int(maxIterations)); belosLOWSFPL_gmres.set("Convergence Tolerance",MT(maxResid)); belosLOWSFPL_gmres.set("Maximum Restarts",int(maxRestarts)); belosLOWSFPL_gmres.set("Block Size",int(blockSize)); belosLOWSFPL_gmres.set("Num Blocks",int(gmresKrylovLength)); belosLOWSFPL_gmres.set("Output Frequency",int(outputFrequency)); belosLOWSFPL_gmres.set("Show Maximum Residual Norm Only",bool(outputMaxResOnly)); // Whether the linear solver succeeded. // (this will be set during the residual check at the end) bool success = true; // Number of random right-hand sides we will be solving for. int numRhs = 1; // Get the domain space for the Thyra linear operator Teuchos::RCP<const Thyra::VectorSpaceBase<ST> > domain = A->domain(); // Create the Belos LOWS factory. Teuchos::RCP<Thyra::LinearOpWithSolveFactoryBase<ST> > belosLOWSFactory = Teuchos::rcp(new Thyra::BelosLinearOpWithSolveFactory<ST>()); // Set the parameter list to specify the behavior of the factory. belosLOWSFactory->setParameterList( belosLOWSFPL ); // Set the output stream and the verbosity level (prints to std::cout by defualt) // NOTE: Set to VERB_NONE for no output from the solver. belosLOWSFactory->setVerbLevel(Teuchos::VERB_LOW); // Create a BelosLinearOpWithSolve object from the Belos LOWS factory. Teuchos::RCP<Thyra::LinearOpWithSolveBase<ST> > nsA = belosLOWSFactory->createOp(); // Initialize the BelosLinearOpWithSolve object with the Thyra linear operator. Thyra::initializeOp<ST>( *belosLOWSFactory, A, &*nsA ); // Create a right-hand side with numRhs vectors in it. Teuchos::RCP< Thyra::MultiVectorBase<ST> > b = Thyra::createMembers(domain, numRhs); // Create an initial std::vector with numRhs vectors in it and initialize it to one. Teuchos::RCP< Thyra::MultiVectorBase<ST> > x = Thyra::createMembers(domain, numRhs); Thyra::assign(&*x, one); // Initialize the right-hand side so that the solution is a std::vector of ones. A->apply( Thyra::NONCONJ_ELE, *x, &*b ); Thyra::assign(&*x, zero); // Perform solve using the linear operator to get the approximate solution of Ax=b, // where b is the right-hand side and x is the left-hand side. Thyra::SolveStatus<ST> solveStatus; solveStatus = Thyra::solve( *nsA, Thyra::NONCONJ_ELE, *b, &*x ); // Print out status of solve. *out << "\nBelos LOWS Status: "<< solveStatus << std::endl; // // Compute residual and ST check convergence. // std::vector<MT> norm_b(numRhs), norm_res(numRhs); Teuchos::RCP< Thyra::MultiVectorBase<ST> > y = Thyra::createMembers(domain, numRhs); // Compute the column norms of the right-hand side b. Thyra::norms_2( *b, &norm_b[0] ); // Compute y=A*x, where x is the solution from the linear solver. A->apply( Thyra::NONCONJ_ELE, *x, &*y ); // Compute A*x-b = y-b Thyra::update( -one, *b, &*y ); // Compute the column norms of A*x-b. Thyra::norms_2( *y, &norm_res[0] ); // Print out the final relative residual norms. MT rel_res = 0.0; *out << "Final relative residual norms" << std::endl; for (int i=0; i<numRhs; ++i) { rel_res = norm_res[i]/norm_b[i]; if (rel_res > maxResid) success = false; *out << "RHS " << i+1 << " : " << std::setw(16) << std::right << rel_res << std::endl; } return ( success ? 0 : 1 ); }
int main(int argc, char *argv[]) { int M, N, nonzeros, Nrhs; int *colptr, *rowind; double *val = NULL; double *rhs; int rhsentries = 0; double *guess; double *exact = NULL; char *Type; char Ptrfmt[]="(13I6)"; char Indfmt[]="(16I5)"; char Valfmt[]="(3E26.18)"; char Rhsfmt[]="(3E26.18)"; int i=0; if (argc < 3) { fprintf(stderr,"Usage: %s HBfile HBfileout\n", argv[0]); exit(-1); } /* Get information about the array stored in the file specified in the */ /* argument list: */ fprintf(stderr,"Reading matrix info from %s...\n",argv[1]); readHB_info(argv[1], &M, &N, &nonzeros, &Type, &Nrhs); fprintf(stderr,"Matrix in file %s is %d x %d, with %d nonzeros with type %s;\n", argv[1], M, N, nonzeros, Type); fprintf(stderr,"%d right-hand-side(s) available.\n",Nrhs); /* Read the matrix information, generating the associated storage arrays */ fprintf(stderr,"Reading the matrix from %s...\n",argv[1]); readHB_newmat_double(argv[1], &M, &N, &nonzeros, &colptr, &rowind, &val); /* If a rhs is specified in the file, read one, generating the associate storage */ if (Nrhs > 0) { fprintf(stderr,"Reading right-hand-side vector(s) from %s...\n",argv[1]); readHB_newaux_double(argv[1], 'F', &rhs); } /* Generate a new Guess vector (all zeros) */ if ( Type[0] == 'R' ) rhsentries = M*Nrhs; else if ( Type[0] == 'C' ) rhsentries = 2*M*Nrhs; guess = (double *) malloc(rhsentries*sizeof(double)); for (i = 0; i < rhsentries ;i++) guess[i] = 0; if (Nrhs > 0) { fprintf( stderr, "Writing the matrix and right-hand-side/guess vector(s) from %s...\n", argv[1] ); } else { fprintf( stderr, "Writing the matrix from %s...\n", argv[1] ); } writeHB_mat_double(argv[2], M, N, nonzeros, colptr, rowind, val, Nrhs, rhs, guess, exact, "Test Title", "Test Key", Type, Ptrfmt,Indfmt,Valfmt,Rhsfmt,"FGN"); fprintf(stderr,"**** Successful completion of %s. Generated %s. ****\n",argv[0],argv[2]); return 0; }