diff --git a/example/gmres/gmres.hpp b/example/gmres/gmres.hpp index 31b48e73a3..48a6e4ae0d 100644 --- a/example/gmres/gmres.hpp +++ b/example/gmres/gmres.hpp @@ -71,6 +71,19 @@ Kokkos::Experimental::half_t fabs( } #endif // KOKKOS_HALF_T_IS_FLOAT +#if !KOKKOS_BHALF_T_IS_FLOAT +Kokkos::Experimental::bhalf_t fabs(Kokkos::Experimental::bhalf_t arg) { + using AT = Kokkos::Details::ArithTraits; + return AT::abs(arg); +} + +Kokkos::Experimental::bhalf_t fabs( + Kokkos::complex arg) noexcept { + return Kokkos::Experimental::bhalf_t(Kokkos::abs( + Kokkos::complex((double)arg.real(), (double)arg.imag()))); +} +#endif // KOKKOS_BHALF_T_IS_FLOAT + // This fabs wrapper was added to resolve: // https://github.com/kokkos/kokkos-kernels/issues/1172 template diff --git a/example/gmres/test_cmplx_A.cpp b/example/gmres/test_cmplx_A.cpp index a19d6ad7e1..0a75c53d62 100644 --- a/example/gmres/test_cmplx_A.cpp +++ b/example/gmres/test_cmplx_A.cpp @@ -53,7 +53,7 @@ #include "gmres.hpp" int main(int /*argc*/, char** /*argv[]*/) { - typedef Kokkos::complex ST; + typedef Kokkos::complex ST; typedef int OT; typedef Kokkos::DefaultExecutionSpace EXSP; diff --git a/example/gmres/test_real_A.cpp b/example/gmres/test_real_A.cpp index 1a0bb09683..e7e2a34e31 100644 --- a/example/gmres/test_real_A.cpp +++ b/example/gmres/test_real_A.cpp @@ -42,19 +42,19 @@ //@HEADER */ -#include -#include"KokkosKernels_IOUtils.hpp" -#include -#include -#include -#include -#include +#include +#include "KokkosKernels_IOUtils.hpp" +#include +#include +#include +#include +#include #include -#include"gmres.hpp" +#include "gmres.hpp" -int main(int /*argc*/, char ** /*argv[]*/) { - typedef double ST; +int main(int /*argc*/, char** /*argv[]*/) { + typedef Kokkos::Experimental::bhalf_t ST; typedef int OT; typedef Kokkos::DefaultExecutionSpace EXSP; @@ -70,101 +70,111 @@ int main(int /*argc*/, char ** /*argv[]*/) { GmresOpts solverOpts; solverOpts.ortho = "CGS2"; // orthog type solverOpts.m = 15; // Max subspace size before restarting. - solverOpts.tol = 1e-10; //Relative residual convergence tolerance. + solverOpts.tol = 1e-10; // Relative residual convergence tolerance. solverOpts.maxRestart = 50; - bool pass1 = false; - bool pass2 = false; + bool pass1 = false; + bool pass2 = false; std::cout << "Convergence tolerance is: " << solverOpts.tol << std::endl; // Initialize Kokkos AFTER parsing parameters: Kokkos::initialize(); { - // Create a diagonally dominant sparse matrix to test: - ncST nnz; - cOT n = 5000; - cOT numRows = n; - cOT numCols = n; - cOT diagDominance = 1; - nnz = 10 * numRows; - sp_matrix_type A = KokkosKernels::Impl::kk_generate_diagonally_dominant_sparse_matrix - (numRows, numCols, nnz, 0, ncOT(0.01 * numRows), diagDominance); - - // Set initial vectors: - ViewVectorType X("X",n); //Solution and initial guess - ViewVectorType Wj("Wj",n); //For checking residuals at end. - ViewVectorType B(Kokkos::view_alloc(Kokkos::WithoutInitializing, "B"),n);//right-hand side vec - - // Make rhs ones so that results are repeatable: - Kokkos::deep_copy(B,1.0); - - std::cout << "Testing GMRES with CGS2 ortho:" << std::endl; - GmresStats solveStats = gmres(A, B, X, solverOpts); - - // Double check residuals at end of solve: - double nrmB = static_cast(KokkosBlas::nrm2(B)); - KokkosSparse::spmv("N", ST(1.0), A, X, ST(0.0), Wj); // wj = Ax - KokkosBlas::axpy(ST(-1.0), Wj, B); // b = b-Ax. - double endRes = KokkosBlas::nrm2(B)/nrmB; - std::cout << "=======================================" << std::endl; - std::cout << "Verify from main: Ending residual is " << endRes << std::endl; - std::cout << "Number of iterations is: " << solveStats.numIters << std::endl; - std::cout << "Diff of residual from main - residual from solver: " << solveStats.endRelRes - endRes << std::endl; - std::cout << "Convergence flag is : " << solveStats.convFlag() << std::endl; - - if (solveStats.numIters < 40 && solveStats.numIters > 20 && - endRes < static_cast(solverOpts.tol)) { - std::cout << "Test CGS2 Passed!" << std::endl; - pass1 = true; - } else { - std::cout - << "Solver did not converge within the expected number of iterations. " - << std::endl - << "CGS2 Test Failed." << std::endl; - } - std::cout << "=======================================" << std::endl << std::endl << std::endl; - - solverOpts.ortho = "MGS"; - Kokkos::deep_copy(X,0.0); - Kokkos::deep_copy(B,1.0); - - std::cout << "Testing GMRES with MGS ortho:" << std::endl; - solveStats = gmres(A, B, X, solverOpts); - - // Double check residuals at end of solve: - nrmB = static_cast(KokkosBlas::nrm2(B)); - KokkosSparse::spmv("N", ST(1.0), A, X, ST(0.0), Wj); // wj = Ax - KokkosBlas::axpy(ST(-1.0), Wj, B); // b = b-Ax. - endRes = KokkosBlas::nrm2(B)/nrmB; - std::cout << "=======================================" << std::endl; - std::cout << "Verify from main: Ending residual is " << endRes << std::endl; - std::cout << "Number of iterations is: " << solveStats.numIters << std::endl; - std::cout << "Diff of residual from main - residual from solver: " << solveStats.endRelRes - endRes << std::endl; - std::cout << "Convergence flag is : " << solveStats.convFlag() << std::endl; - - if (solveStats.numIters < 40 && solveStats.numIters > 20 && - endRes < static_cast(solverOpts.tol)) { - std::cout << "Test MGS Passed!" << std::endl; - if (pass1) { - pass2 = true; - }; - } else { - std::cout - << "Solver did not converge within the expected number of iterations. " - << std::endl - << "MGS Test Failed." << std::endl; - } - std::cout << "=======================================" << std::endl << std::endl << std::endl; - + // Create a diagonally dominant sparse matrix to test: + ncST nnz; + cOT n = 5000; + cOT numRows = n; + cOT numCols = n; + cOT diagDominance = 1; + nnz = 10 * numRows; + sp_matrix_type A = + KokkosKernels::Impl::kk_generate_diagonally_dominant_sparse_matrix< + sp_matrix_type>(numRows, numCols, nnz, 0, ncOT(0.01 * numRows), + diagDominance); + + // Set initial vectors: + ViewVectorType X("X", n); // Solution and initial guess + ViewVectorType Wj("Wj", n); // For checking residuals at end. + ViewVectorType B(Kokkos::view_alloc(Kokkos::WithoutInitializing, "B"), + n); // right-hand side vec + + // Make rhs ones so that results are repeatable: + Kokkos::deep_copy(B, 1.0); + + std::cout << "Testing GMRES with CGS2 ortho:" << std::endl; + GmresStats solveStats = + gmres(A, B, X, solverOpts); + + // Double check residuals at end of solve: + double nrmB = static_cast(KokkosBlas::nrm2(B)); + KokkosSparse::spmv("N", ST(1.0), A, X, ST(0.0), Wj); // wj = Ax + KokkosBlas::axpy(ST(-1.0), Wj, B); // b = b-Ax. + double endRes = KokkosBlas::nrm2(B) / nrmB; + std::cout << "=======================================" << std::endl; + std::cout << "Verify from main: Ending residual is " << endRes << std::endl; + std::cout << "Number of iterations is: " << solveStats.numIters + << std::endl; + std::cout << "Diff of residual from main - residual from solver: " + << solveStats.endRelRes - endRes << std::endl; + std::cout << "Convergence flag is : " << solveStats.convFlag() << std::endl; + + if (solveStats.numIters < 40 && solveStats.numIters > 20 && + endRes < static_cast(solverOpts.tol)) { + std::cout << "Test CGS2 Passed!" << std::endl; + pass1 = true; + } else { + std::cout << "Solver did not converge within the expected number of " + "iterations. " + << std::endl + << "CGS2 Test Failed." << std::endl; + } + std::cout << "=======================================" << std::endl + << std::endl + << std::endl; + + solverOpts.ortho = "MGS"; + Kokkos::deep_copy(X, 0.0); + Kokkos::deep_copy(B, 1.0); + + std::cout << "Testing GMRES with MGS ortho:" << std::endl; + solveStats = gmres(A, B, X, solverOpts); + + // Double check residuals at end of solve: + nrmB = static_cast(KokkosBlas::nrm2(B)); + KokkosSparse::spmv("N", ST(1.0), A, X, ST(0.0), Wj); // wj = Ax + KokkosBlas::axpy(ST(-1.0), Wj, B); // b = b-Ax. + endRes = KokkosBlas::nrm2(B) / nrmB; + std::cout << "=======================================" << std::endl; + std::cout << "Verify from main: Ending residual is " << endRes << std::endl; + std::cout << "Number of iterations is: " << solveStats.numIters + << std::endl; + std::cout << "Diff of residual from main - residual from solver: " + << solveStats.endRelRes - endRes << std::endl; + std::cout << "Convergence flag is : " << solveStats.convFlag() << std::endl; + + if (solveStats.numIters < 40 && solveStats.numIters > 20 && + endRes < static_cast(solverOpts.tol)) { + std::cout << "Test MGS Passed!" << std::endl; + if (pass1) { + pass2 = true; + }; + } else { + std::cout << "Solver did not converge within the expected number of " + "iterations. " + << std::endl + << "MGS Test Failed." << std::endl; + } + std::cout << "=======================================" << std::endl + << std::endl + << std::endl; } Kokkos::finalize(); - if(pass2){ - std::cout << "Both tests have passed!!" << std::endl; - } - else{ + if (pass2) { + std::cout << "Both tests have passed!!" << std::endl; + } else { std::cout << "One or more tests has failed." << std::endl; } - return ( pass2 ? EXIT_SUCCESS : EXIT_FAILURE ); + return (pass2 ? EXIT_SUCCESS : EXIT_FAILURE); }