%===============================================================================
\section{CUDA example problems}\label{s:ex_cuda}
%===============================================================================


%-------------------------------------------------------------------------------

\subsection{An unpreconditioned Krylov example: cvAdvDiff\_kry\_cuda}\label{ss:cvAdvDiff_cuda}

The example program \id{cvAdvDiff\_kry\_cuda.cu} solves the same 2-D 
advection-diffusion equation as in Section \ref{ss:cvAdvDiff}, but
instead of using a banded direct solver, it uses unpreconditioned 
Krylov solver. Here we only highlight differences between the two 
examples. 

The \id{cvAdvDiff\_kry\_cuda.cu} program includes files
\id{sunlinsol\_spmgr.h} in order to use the {\spgmr}
Krylov linear solver. File \id{cvode.h} provides the prototypes for 
\id{CVodeSetLinearSolver}, which sets the iterative linear solver for
{\cvode}, and \id{CVodeSetJacTimes}, which sets the pointer to the user
supplied Jacobian-vector product function.
The file \id{nvector\_cuda.h} is included for the definition of the {\cuda}
\id{N\_Vector} type. The prototype vector is created
using \id{N\_VNew\_Cuda} function. 

In order to get a good performance and avoid moving data between host
and device at every iteration, it is recommended that user evaluates  
model at the device. In the example, model right hand side and Jacobian-vector
product are implemented as {\cuda} kernels \id{fKernel} and \id{jtvKernel},
respectively. User provided {\CC} functions \id{f} and \id{jtv}, which are called
directly by {\cvode}, set thread partitioning and launch thier respective 
{\cuda} kernels. Vector data on the device is accessed using 
\id{N\_VGetDeviceArrayPointer\_Cuda} function.

The output generated by \id{cvAdvDiff\_kry\_cuda} is shown below.

%%
\includeOutput{cvAdvDiff\_kry\_cuda}{../../examples/cvode/cuda/cvAdvDiff_kry_cuda.out}
%%

%-------------------------------------------------------------------------------

