Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add verbosity parameter to GMRES example. Turn off for testing. #1385

Merged
merged 2 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 86 additions & 70 deletions example/gmres/ex_real_A.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,100 +42,116 @@
//@HEADER
*/

#include<math.h>
#include"KokkosKernels_IOUtils.hpp"
#include<Kokkos_Core.hpp>
#include<Kokkos_Random.hpp>
#include<KokkosBlas.hpp>
#include<KokkosBlas3_trsm.hpp>
#include<KokkosSparse_spmv.hpp>
#include <math.h>
#include "KokkosKernels_IOUtils.hpp"
#include <Kokkos_Core.hpp>
#include <Kokkos_Random.hpp>
#include <KokkosBlas.hpp>
#include <KokkosBlas3_trsm.hpp>
#include <KokkosSparse_spmv.hpp>

#include"gmres.hpp"
#include "gmres.hpp"

int main(int argc, char *argv[]) {
int main(int argc, char* argv[]) {
typedef double ST;
typedef int OT;
typedef Kokkos::DefaultExecutionSpace EXSP;
typedef Kokkos::DefaultExecutionSpace EXSP;

using ViewVectorType = Kokkos::View<ST*,Kokkos::LayoutLeft, EXSP>;
using ViewVectorType = Kokkos::View<ST*, Kokkos::LayoutLeft, EXSP>;

std::string filename("bcsstk09.mtx"); // example matrix
std::string ortho("CGS2"); //orthog type
int m = 50; //Max subspace size before restarting.
double convTol = 1e-10; //Relative residual convergence tolerance.
int cycLim = 50; //Maximum number of times to restart the solver.
bool rand_rhs = false; //Generate random right-hand side.
std::string filename("bcsstk09.mtx"); // example matrix
std::string ortho("CGS2"); // orthog type
int m = 50; // Max subspace size before restarting.
double convTol = 1e-10; // Relative residual convergence tolerance.
int cycLim = 50; // Maximum number of times to restart the solver.
bool rand_rhs = false; // Generate random right-hand side.

for (int i=1;i<argc;++i) {
for (int i = 1; i < argc; ++i) {
const std::string& token = argv[i];
if (token == std::string("--filename")) filename = argv[++i];
if (token == std::string("--max-subsp")) m = std::atoi(argv[++i]);
if (token == std::string("--max-restarts")) cycLim = std::atoi(argv[++i]);
if (token == std::string("--tol")) convTol = std::stod(argv[++i]);
if (token == std::string("--ortho")) ortho = argv[++i];
if (token == std::string("--rand_rhs")) rand_rhs = true;
if (token == std::string("--help") || token == std::string("-h")){
std::cout << "Kokkos GMRES solver options:" << std::endl
<< "--filename : The name of a matrix market (.mtx) file for matrix A (Default bcsstk09.mtx)." << std::endl
<< "--max-subsp : The maximum size of the Kyrlov subspace before restarting (Default 50)." << std::endl
<< "--max-restarts: Maximum number of GMRES restarts (Default 50)." << std::endl
<< "--tol : Convergence tolerance. (Default 1e-10)." << std::endl
<< "--ortho : Type of orthogonalization. Use 'CGS2' or 'MGS'. (Default 'CGS2')" << std::endl
<< "--rand_rhs : Generate a random right-hand side b. (Else, default uses b = vector of ones.)" << std::endl
<< "--help -h : Display this help message." << std::endl
<< "Example Call : ./Gmres.exe --filename Laplace3D100.mtx --tol 1e-5 --max-subsp 100 " << std::endl << std::endl;
return 0; }
if (token == std::string("--help") || token == std::string("-h")) {
std::cout
<< "Kokkos GMRES solver options:" << std::endl
<< "--filename : The name of a matrix market (.mtx) file for "
"matrix A (Default bcsstk09.mtx)."
<< std::endl
<< "--max-subsp : The maximum size of the Kyrlov subspace before "
"restarting (Default 50)."
<< std::endl
<< "--max-restarts: Maximum number of GMRES restarts (Default 50)."
<< std::endl
<< "--tol : Convergence tolerance. (Default 1e-10)."
<< std::endl
<< "--ortho : Type of orthogonalization. Use 'CGS2' or 'MGS'. "
"(Default 'CGS2')"
<< std::endl
<< "--rand_rhs : Generate a random right-hand side b. (Else, "
"default uses b = vector of ones.)"
<< std::endl
<< "--help -h : Display this help message." << std::endl
<< "Example Call : ./Gmres.exe --filename Laplace3D100.mtx --tol "
"1e-5 --max-subsp 100 "
<< std::endl
<< std::endl;
return 0;
}
}
std::cout << "File to process is: " << filename << std::endl;
std::cout << "Convergence tolerance is: " << convTol << std::endl;

// Set GMRES options:
GmresOpts<ST> solverOpts;
solverOpts.tol = convTol;
solverOpts.m = m;
solverOpts.tol = convTol;
solverOpts.m = m;
solverOpts.maxRestart = cycLim;
solverOpts.ortho = ortho;
solverOpts.ortho = ortho;
solverOpts.verbose = false; // No verbosity needed for most testing

//Initialize Kokkos AFTER parsing parameters:
// Initialize Kokkos AFTER parsing parameters:
Kokkos::initialize();
{

// Read in a matrix Market file and use it to test the Kokkos Operator.
KokkosSparse::CrsMatrix<ST, OT, EXSP> A =
KokkosKernels::Impl::read_kokkos_crst_matrix<KokkosSparse::CrsMatrix<ST, OT, EXSP>>(filename.c_str());

int n = A.numRows();
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

if(rand_rhs){
// Make rhs random.
int rand_seed = 123;
Kokkos::Random_XorShift64_Pool<> pool(rand_seed);
Kokkos::fill_random(B, pool, -1,1);
}
else{
// Make rhs ones so that results are repeatable:
Kokkos::deep_copy(B,1.0);
}

// Run GMRS solve:
GmresStats solveStats = gmres<ST, Kokkos::LayoutLeft, EXSP>(A, B, X, solverOpts);

// Double check residuals at end of solve:
ST nrmB = KokkosBlas::nrm2(B);
KokkosSparse::spmv("N", 1.0, A, X, 0.0, Wj); // wj = Ax
KokkosBlas::axpy(-1.0, Wj, B); // b = b-Ax.
ST 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;

// Read in a matrix Market file and use it to test the Kokkos Operator.
KokkosSparse::CrsMatrix<ST, OT, EXSP> A =
KokkosKernels::Impl::read_kokkos_crst_matrix<
KokkosSparse::CrsMatrix<ST, OT, EXSP>>(filename.c_str());

int n = A.numRows();
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

if (rand_rhs) {
// Make rhs random.
int rand_seed = 123;
Kokkos::Random_XorShift64_Pool<> pool(rand_seed);
Kokkos::fill_random(B, pool, -1, 1);
} else {
// Make rhs ones so that results are repeatable:
Kokkos::deep_copy(B, 1.0);
}

// Run GMRS solve:
GmresStats solveStats =
gmres<ST, Kokkos::LayoutLeft, EXSP>(A, B, X, solverOpts);

// Double check residuals at end of solve:
ST nrmB = KokkosBlas::nrm2(B);
KokkosSparse::spmv("N", 1.0, A, X, 0.0, Wj); // wj = Ax
KokkosBlas::axpy(-1.0, Wj, B); // b = b-Ax.
ST 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;
}
Kokkos::finalize();

}

46 changes: 32 additions & 14 deletions example/gmres/gmres.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,12 @@ struct GmresOpts {
typename Kokkos::Details::ArithTraits<ScalarType>::mag_type tol;
int m;
int maxRestart;
bool verbose;
std::string ortho;
std::string precSide;

GmresOpts<ScalarType>() : tol(1e-8), m(50), maxRestart(50), ortho("CGS2") {}
GmresOpts<ScalarType>()
: tol(1e-8), m(50), maxRestart(50), verbose(true), ortho("CGS2") {}
};

template <class ScalarType, class Layout, class EXSP, class OrdinalType = int>
Expand Down Expand Up @@ -182,7 +184,9 @@ GmresStats gmres(
MT nrmB, trueRes, relRes, shortRelRes;
GmresStats myStats;

std::cout << "Convergence tolerance is: " << opts.tol << std::endl;
if (opts.verbose) {
std::cout << "Convergence tolerance is: " << opts.tol << std::endl;
}

ViewVectorType Xiter(
"Xiter", n); // Intermediate solution at iterations before restart.
Expand Down Expand Up @@ -229,7 +233,9 @@ GmresStats gmres(
relRes = 0;
}
shortRelRes = relRes;
std::cout << "Initial relative residual is: " << relRes << std::endl;
if (opts.verbose) {
std::cout << "Initial relative residual is: " << relRes << std::endl;
}
if (relRes < opts.tol) {
converged = true;
}
Expand Down Expand Up @@ -311,8 +317,10 @@ GmresStats gmres(
GVec_h(j) = GVec_h(j) * CosVal_h(j);
shortRelRes = fabs(GVec_h(j + 1)) / nrmB;

std::cout << "Shortcut relative residual for iteration "
<< j + (cycle * m) << " is: " << shortRelRes << std::endl;
if (opts.verbose) {
std::cout << "Shortcut relative residual for iteration "
<< j + (cycle * m) << " is: " << shortRelRes << std::endl;
}
if (tmpNrm <= 1e-14 && shortRelRes >= opts.tol) {
throw std::runtime_error(
"GMRES has experienced lucky breakdown, but the residual has not converged.\n\
Expand Down Expand Up @@ -359,8 +367,10 @@ GmresStats gmres(
KokkosBlas::axpy(-one, Wj, Res); // r = b-Ax.
trueRes = KokkosBlas::nrm2(Res);
relRes = trueRes / nrmB;
std::cout << "True relative residual for iteration " << j + (cycle * m)
<< " is : " << relRes << std::endl;
if (opts.verbose) {
std::cout << "True relative residual for iteration "
<< j + (cycle * m) << " is : " << relRes << std::endl;
}
numIters = j + 1;

if (relRes < opts.tol) {
Expand Down Expand Up @@ -390,24 +400,32 @@ GmresStats gmres(
std::cout << "Ending relative residual is: " << relRes << std::endl;
myStats.endRelRes = static_cast<double>(relRes);
if (converged) {
std::cout << "Solver converged! " << std::endl;
if (opts.verbose) {
std::cout << "Solver converged! " << std::endl;
}
myStats.convFlagVal = GmresStats::FLAG::Conv;
} else if (shortRelRes < opts.tol) {
std::cout << "Shortcut residual converged, but solver experienced a loss "
"of accuracy."
<< std::endl;
if (opts.verbose) {
std::cout << "Shortcut residual converged, but solver experienced a loss "
"of accuracy."
<< std::endl;
}
myStats.convFlagVal = GmresStats::FLAG::LOA;
} else {
std::cout << "Solver did not converge. :( " << std::endl;
if (opts.verbose) {
std::cout << "Solver did not converge. :( " << std::endl;
}
myStats.convFlagVal = GmresStats::FLAG::NoConv;
}
if (cycle > 0) {
myStats.numIters = (cycle - 1) * m + numIters;
} else {
myStats.numIters = 0;
}
std::cout << "The solver completed " << myStats.numIters << " iterations."
<< std::endl;
if (opts.verbose) {
std::cout << "The solver completed " << myStats.numIters << " iterations."
<< std::endl;
}

Kokkos::Profiling::popRegion();
return myStats;
Expand Down
1 change: 1 addition & 0 deletions example/gmres/test_cmplx_A.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ int main(int /*argc*/, char** /*argv[]*/) {
solverOpts.tol = 1e-05; // Relative residual convergence tolerance.
solverOpts.maxRestart = 60;
solverOpts.ortho = "CGS2"; // orthog type
solverOpts.verbose = false; // No verbosity needed for most testing
bool pass1 = false;
bool pass2 = false;

Expand Down
Loading