Skip to content

Commit

Permalink
Merge branch 'ODESolve' of github.com:jennloe/kokkos-kernels into ODE…
Browse files Browse the repository at this point in the history
…Solve
  • Loading branch information
jennloe committed Apr 22, 2022
2 parents 3f8c871 + a28f0f5 commit ec813c9
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 277 deletions.
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

0 comments on commit ec813c9

Please sign in to comment.