/// <summary>
		/// Create new sparse solve instance
		/// </summary>
		public CudaSolveSparse()
		{
			_handle = new cusolverSpHandle();
			res = CudaSolveNativeMethods.Sparse.cusolverSpCreate(ref _handle);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpDestroy", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// Create new refactorization solve instance
		/// </summary>
		public CudaSolveRefactorization()
		{
			_handle = new cusolverRfHandle();
			res = CudaSolveNativeMethods.Refactorization.cusolverRfCreate(ref _handle);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfCreate", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
Exemple #3
0
        /// <summary>
        /// This routine allows direct access to the lower L and upper U triangular factors stored in
        /// the cuSolverRF library handle. The factors are compressed into a single matrix M=(LI)+
        /// U, where the unitary diagonal of L is not stored. It is assumed that a prior call to the
        /// cusolverRfRefactor() was done in order to generate these triangular factors.
        /// </summary>
        /// <param name="n">Size of Matrix M (n x n)</param>
        /// <param name="h_nnzM">the number of non-zero elements of matrix M.</param>
        /// <param name="h_Mp">the array of offsets corresponding to the start of each row in the arrays Mi and Mx.
        /// This array has also an extra entry at the end that stores the number of non-zero elements in the matrix $M$. The array size is n+1.</param>
        /// <param name="h_Mi">the array of column indices corresponding to the non-zero elements in the matrix M. It is assumed that this array is sorted by row and by column within each row. The array size is nnzM.</param>
        /// <param name="h_Mx">the array of values corresponding to the non-zero elements in the matrix M. It is assumed that this array is sorted by row and by column within each row. The array size is nnzM.</param>
        public void ExtractBundledFactorsHost(int n, out int h_nnzM, out int[] h_Mp, out int[] h_Mi, out double[] h_Mx)
        {
            h_nnzM = 0;
            IntPtr mp = new IntPtr();
            IntPtr mi = new IntPtr();
            IntPtr mx = new IntPtr();

            res = CudaSolveNativeMethods.Refactorization.cusolverRfExtractBundledFactorsHost(_handle, ref h_nnzM, ref mp, ref mi, ref mx);
            Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfExtractBundledFactorsHost", res));
            if (res != cusolverStatus.Success)
            {
                throw new CudaSolveException(res);
            }

            if (h_nnzM == 0)
            {
                h_Mp = null;
                h_Mi = null;
                h_Mx = null;
            }
            else
            {
                h_Mp = new int[n + 1];
                h_Mi = new int[h_nnzM];
                h_Mx = new double[h_nnzM];
                Marshal.Copy(mp, h_Mp, 0, n + 1);
                Marshal.Copy(mi, h_Mi, 0, h_nnzM);
                Marshal.Copy(mx, h_Mx, 0, h_nnzM);
            }
        }
Exemple #4
0
        /// <summary>
        /// To solve A_j * x_j = b_j, first we reform the equation by M_j * Q * x_j = P * b_j. Then do refactorization by
        /// cusolverRfBatch_Refactor(). Further cusolverRfBatch_Solve() takes over the remaining steps.
        /// </summary>
        /// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
        /// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
        /// <param name="nrhs">the number right-hand-sides to be solved.</param>
        /// <param name="Temp">the dense matrix that contains temporary workspace (of size ldt*nrhs).</param>
        /// <param name="ldt">the leading dimension of dense matrix Temp (ldt &gt;= n).</param>
        /// <param name="XF_array">array of pointers of size batchSize, each pointer points to the dense matrix that contains the right-hand-sides F and solutions X (of size ldxf*nrhs).</param>
        /// <param name="ldxf">the leading dimension of dense matrix XF (ldxf &gt;= n).</param>
        public void cusolverRfBatchSolve(CudaDeviceVariable <int> P, CudaDeviceVariable <int> Q, int nrhs, double[] Temp, int ldt, double[][] XF_array, int ldxf)
        {
            int batchSize = XF_array.Length;

            IntPtr[]   XF      = new IntPtr[batchSize];
            GCHandle[] handles = new GCHandle[batchSize];

            try
            {
                for (int i = 0; i < batchSize; i++)
                {
                    handles[i] = GCHandle.Alloc(XF_array[i], GCHandleType.Pinned);
                    XF[i]      = handles[i].AddrOfPinnedObject();
                }

                res = CudaSolveNativeMethods.Refactorization.cusolverRfBatchSolve(_handle, P.DevicePointer, Q.DevicePointer, nrhs, Temp, ldt, XF, ldxf);
                Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfBatchSolve", res));
            }
            catch
            {
                throw;
            }
            finally
            {
                for (int i = 0; i < batchSize; i++)
                {
                    handles[i].Free();
                }
            }
            if (res != cusolverStatus.Success)
            {
                throw new CudaSolveException(res);
            }
        }
Exemple #5
0
		/// <summary>
		/// </summary>
		public CsrQrInfo()
		{
			_info = new csrqrInfo();
			res = CudaSolveNativeMethods.Sparse.cusolverSpCreateCsrqrInfo(ref _info);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpCreateCsrqrInfo", res));
			if (res != cusolverStatus.Success)
				throw new CudaSolveException(res);
		}
Exemple #6
0
 /// <summary>
 /// </summary>
 public void SetSolverLowestPrecision(cusolverPrecType solver_main_precision)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsSetSolverLowestPrecision(_params, solver_main_precision);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsSetSolverLowestPrecision", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #7
0
 /// <summary>
 /// </summary>
 public void DisableFallback()
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsDisableFallback(_params);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsDisableFallback", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #8
0
 /// <summary>
 /// This routine sets the matrix format used in the cusolverRfSetup(),
 /// cusolverRfSetupHost(), cusolverRfResetValues(), cusolverRfExtractBundledFactorsHost() and cusolverRfExtractSplitFactorsHost() routines.
 /// </summary>
 /// <param name="format">the enumerated matrix format type.</param>
 /// <param name="diag">the enumerated unit diagonal type.</param>
 public void SetMatrixFormat(MatrixFormat format, UnitDiagonal diag)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfSetMatrixFormat(_handle, format, diag);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSetMatrixFormat", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #9
0
 /// <summary>
 /// </summary>
 public void SetSortEig(int sort_eig)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnXsyevjSetSortEig(_info, sort_eig);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnXsyevjSetSortEig", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #10
0
 /// <summary>
 /// </summary>
 public void SetTol(double val)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsSetTol(_params, val);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsSetTol", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #11
0
 /// <summary>
 /// This routine sets the mode used in the cusolverRfResetValues routine.
 /// </summary>
 /// <param name="fastMode">the enumerated mode type.</param>
 public void SetResetValuesFastMode(ResetValuesFastMode fastMode)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfSetResetValuesFastMode(_handle, fastMode);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSetResetValuesFastMode", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #12
0
 /// <summary>
 /// This routine performs the LU re-factorization
 /// </summary>
 public void Refactor(cusolverRfHandle handle)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfRefactor(_handle);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfRefactor", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #13
0
 /// <summary>
 /// This routine performs the forward and backward solve with the lower and upper
 /// triangular factors resulting from the LU re-factorization
 /// </summary>
 /// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
 /// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
 /// <param name="nrhs">the number right-hand-sides to be solved.</param>
 /// <param name="Temp">the dense matrix that contains temporary workspace (of size ldt*nrhs).</param>
 /// <param name="ldt">the leading dimension of dense matrix Temp (ldt &gt;= n).</param>
 /// <param name="XF">the dense matrix that contains the righthand-sides F and solutions X (of size ldxf*nrhs).</param>
 /// <param name="ldxf">the leading dimension of dense matrix XF (ldxf &gt;= n).</param>
 public void Solve(CudaDeviceVariable <int> P, CudaDeviceVariable <int> Q, int nrhs, double[] Temp, int ldt, double[] XF, int ldxf)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfSolve(_handle, P.DevicePointer, Q.DevicePointer, nrhs, Temp, ldt, XF, ldxf);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSolve", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #14
0
 /// <summary>
 /// The user can query which matrix failed LU refactorization by checking
 /// corresponding value in position array. The input parameter position is an integer array of size batchSize.
 /// </summary>
 /// <param name="position">integer array of size batchSize. The value of position(j) reports singularity
 /// of matrix Aj, -1 if no structural / numerical zero, k &gt;= 0 if Aj(k,k) is either structural zero or numerical zero.</param>
 public void BatchZeroPivot(int[] position)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfBatchZeroPivot(_handle, position);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfBatchZeroPivot", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #15
0
 /// <summary>
 /// </summary>
 public void SetMaxItersInner(int maxiters)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsSetMaxItersInner(_params, maxiters);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsSetMaxItersInner", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #16
0
 /// <summary>
 /// </summary>
 public void SetRefinementSolver(cusolverIRSRefinement refinement_solver)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsSetRefinementSolver(_params, refinement_solver);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsSetRefinementSolver", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #17
0
 public void SetAdvOptions(cusolverDnFunction function, cusolverAlgMode algo)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnSetAdvOptions(_params, function, algo);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnSetAdvOptions", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #18
0
 /// <summary>
 /// </summary>
 public void RequestResidual()
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnIRSInfosRequestResidual(_infos);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSInfosRequestResidual", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #19
0
 /// <summary>
 /// This routine gets the algorithm used for the refactorization in cusolverRfRefactor()
 /// and the triangular solve in cusolverRfSolve(). It may be called once prior to
 /// cusolverRfAnalyze() routine.
 /// </summary>
 /// <param name="factAlg">the enumerated algorithm type.</param>
 /// <param name="solveAlg">the enumerated algorithm type.</param>
 public void GetAlgs(ref Factorization factAlg, ref TriangularSolve solveAlg)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfGetAlgs(_handle, ref factAlg, ref solveAlg);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetAlgs", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #20
0
 /// <summary>
 /// This routine gets the report whether numeric boosting was used in the
 /// cusolverRfRefactor() and cusolverRfSolve() routines.
 /// </summary>
 /// <param name="report">the enumerated boosting report type.</param>
 public void GetNumericBoostReport(ref NumericBoostReport report)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfGetNumericBoostReport(_handle, ref report);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetNumericBoostReport", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #21
0
 /// <summary>
 /// This routine gets the numeric values used for checking for "zero" pivot and for boosting
 /// it in the cusolverRfRefactor() and cusolverRfSolve() routines. It may be called
 /// multiple times prior to cusolverRfRefactor() and cusolverRfSolve() routines.
 /// The numeric boosting will be used only if boost &gt; 0.0.
 /// </summary>
 /// <param name="zero">the value below which zero pivot is flagged.</param>
 /// <param name="boost">the value which is substituted for zero pivot (if the later is flagged).</param>
 public void GetNumericProperties(ref double zero, ref double boost)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfGetNumericProperties(_handle, ref zero, ref boost);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetNumericProperties", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #22
0
 /// <summary>
 /// </summary>
 public void SetMaxSweeps(int max_sweeps)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnXsyevjSetMaxSweeps(_info, max_sweeps);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnXsyevjSetMaxSweeps", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #23
0
 /// <summary>
 /// </summary>
 public void SetTolerance(double tolerance)
 {
     res = CudaSolveNativeMethods.Dense.cusolverDnXsyevjSetTolerance(_info, tolerance);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnXsyevjSetTolerance", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #24
0
 /// <summary>
 /// </summary>
 public CsrQrInfo()
 {
     _info = new csrqrInfo();
     res   = CudaSolveNativeMethods.Sparse.cusolverSpCreateCsrqrInfo(ref _info);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpCreateCsrqrInfo", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #25
0
 /// <summary>
 /// </summary>
 public IRSParams()
 {
     _params = new cusolverDnIRSParams();
     res     = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsCreate(ref _params);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsCreate", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #26
0
 /// <summary>
 /// Create new refactorization solve instance
 /// </summary>
 public CudaSolveRefactorization()
 {
     _handle = new cusolverRfHandle();
     res     = CudaSolveNativeMethods.Refactorization.cusolverRfCreate(ref _handle);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfCreate", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #27
0
 /// <summary>
 /// </summary>
 public GesvdjInfo()
 {
     _info = new gesvdjInfo();
     res   = CudaSolveNativeMethods.Dense.cusolverDnCreateGesvdjInfo(ref _info);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnCreateGesvdjInfo", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
		/// <summary>
		/// For IDisposable
		/// </summary>
		/// <param name="fDisposing"></param>
		protected virtual void Dispose(bool fDisposing)
		{
			if (fDisposing && !disposed)
			{
				res = CudaSolveNativeMethods.Refactorization.cusolverRfDestroy(_handle);
				Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfDestroy", res));
				disposed = true;
			}
			if (!fDisposing && !disposed)
				Debug.WriteLine(String.Format("ManagedCUDA not-disposed warning: {0}", this.GetType()));
		}
Exemple #29
0
 /// <summary>This routine assembles the internal data structures of the cuSolverRF library. It is often
 /// the first routine to be called after the call to the cusolverRfCreate() routine.
 /// </summary>
 /// <param name="n">the number of rows (and columns) of matrix A.</param>
 /// <param name="nnzA">the number of non-zero elements of matrix A.</param>
 /// <param name="h_csrRowPtrA">the array of offsets corresponding to
 /// the start of each row in the arrays h_csrColIndA and h_csrValA. This
 /// array has also an extra entry at the end that stores the number of non-zero
 /// elements in the matrix. The array size is n+1.</param>
 /// <param name="h_csrColIndA">the array of column indices corresponding
 /// to the non-zero elements in the matrix. It is assumed that this array is sorted by row
 /// and by column within each row. The array size is nnzA.</param>
 /// <param name="h_csrValA">the array of values corresponding to the
 /// non-zero elements in the matrix. It is assumed that this array is sorted by row
 /// and by column within each row. The array size is nnzA.</param>
 /// <param name="nnzL">the number of non-zero elements of matrix L.</param>
 /// <param name="h_csrRowPtrL">the array of offsets corresponding to
 /// the start of each row in the arrays h_csrColIndL and h_csrValL. This
 /// array has also an extra entry at the end that stores the number of non-zero
 /// elements in the matrix L. The array size is n+1.</param>
 /// <param name="h_csrColIndL">the array of column indices corresponding
 /// to the non-zero elements in the matrix L. It is assumed that this array is sorted by
 /// row and by column within each row. The array size is nnzL.</param>
 /// <param name="h_csrValL">the array of values corresponding to the
 /// non-zero elements in the matrix L. It is assumed that this array is sorted by row
 /// and by column within each row. The array size is nnzL.</param>
 /// <param name="nnzU">the number of non-zero elements of matrix U.</param>
 /// <param name="h_csrRowPtrU">the array of offsets corresponding to
 /// the start of each row in the arrays h_csrColIndU and h_csrValU. This
 /// array has also an extra entry at the end that stores the number of non-zero elements in the matrix U. The array size is n+1.</param>
 /// <param name="h_csrColIndU">the array of column indices corresponding
 /// to the non-zero elements in the matrix U. It is assumed that this array is sorted by row and by column within each row. The array size is nnzU.</param>
 /// <param name="h_csrValU">the array of values corresponding to the non-zero elements in the matrix U. It is
 /// assumed that this array is sorted by row and by column within each row. The array size is nnzU.</param>
 /// <param name="h_P">the left permutation (often associated with pivoting). The array size in n.</param>
 /// <param name="h_Q">the right permutation (often associated with reordering). The array size in n.</param>
 public void SetupHost(int n, int nnzA, int[] h_csrRowPtrA, int[] h_csrColIndA, double[] h_csrValA, int nnzL, int[] h_csrRowPtrL, int[] h_csrColIndL,
                       double[] h_csrValL, int nnzU, int[] h_csrRowPtrU, int[] h_csrColIndU, double[] h_csrValU, int[] h_P, int[] h_Q)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfSetupHost(n, nnzA, h_csrRowPtrA, h_csrColIndA, h_csrValA, nnzL, h_csrRowPtrL, h_csrColIndL, h_csrValL,
                                                                      nnzU, h_csrRowPtrU, h_csrColIndU, h_csrValU, h_P, h_Q, _handle);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSetupHost", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #30
0
 /// <summary>
 /// This routine updates internal data structures with the values of the new coefficient
 /// matrix. It is assumed that the arrays csrRowPtrA, csrColIndA, P and Q have not
 /// changed since the last call to the cusolverRfSetup[Host] routine. This assumption
 /// reflects the fact that the sparsity pattern of coefficient matrices as well as reordering to
 /// minimize fill-in and pivoting remain the same in the set of linear systems
 /// </summary>
 /// <param name="n">the number of rows (and columns) of matrix A.</param>
 /// <param name="nnzA">the number of non-zero elements of matrix A.</param>
 /// <param name="csrRowPtrA">the array of offsets corresponding to the start of each row in the arrays
 /// csrColIndA and csrValA. This array has also an extra entry at the end that stores the number of non-zero elements in the
 /// matrix. The array size is n+1.</param>
 /// <param name="csrColIndA">the array of column indices corresponding to the non-zero elements in the matrix. It
 /// is assumed that this array is sorted by row and by column within each row. The array size is nnzA.</param>
 /// <param name="csrValA">the array of values corresponding to the non-zero elements in the matrix. It is assumed that this array is sorted by row
 /// and by column within each row. The array size is nnzA.</param>
 /// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
 /// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
 public void ResetValues(int n, int nnzA, CudaDeviceVariable <int> csrRowPtrA, CudaDeviceVariable <int> csrColIndA, CudaDeviceVariable <double> csrValA,
                         CudaDeviceVariable <double> P, CudaDeviceVariable <double> Q)
 {
     res = CudaSolveNativeMethods.Refactorization.cusolverRfResetValues(n, nnzA, csrRowPtrA.DevicePointer, csrColIndA.DevicePointer,
                                                                        csrValA.DevicePointer, P.DevicePointer, Q.DevicePointer, _handle);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfResetValues", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #31
0
 /// <summary>
 /// </summary>
 internal IRSInfos(IRSParams aParams)
 {
     _params = aParams;
     _infos  = new cusolverDnIRSInfos();
     res     = CudaSolveNativeMethods.Dense.cusolverDnIRSInfosCreate(aParams.Params, ref _infos);
     Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSInfosCreate", res));
     if (res != cusolverStatus.Success)
     {
         throw new CudaSolveException(res);
     }
 }
Exemple #32
0
        /// <summary>
        /// </summary>
        public int GetMaxIters()
        {
            int val = 0;

            res = CudaSolveNativeMethods.Dense.cusolverDnIRSParamsGetMaxIters(_params, ref val);
            Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSParamsGetMaxIters", res));
            if (res != cusolverStatus.Success)
            {
                throw new CudaSolveException(res);
            }
            return(val);
        }
Exemple #33
0
        /// <summary>
        /// </summary>
        public IntPtr GetResidualHistory()
        {
            IntPtr val = new IntPtr();

            res = CudaSolveNativeMethods.Dense.cusolverDnIRSInfosGetResidualHistory(_infos, ref val);
            Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverDnIRSInfosGetResidualHistory", res));
            if (res != cusolverStatus.Success)
            {
                throw new CudaSolveException(res);
            }
            return(val);
        }
Exemple #34
0
		/// <summary>
		/// For IDisposable
		/// </summary>
		/// <param name="fDisposing"></param>
		protected virtual void Dispose(bool fDisposing)
		{
			if (fDisposing && !disposed)
			{
				//Ignore if failing
				res = CudaSolveNativeMethods.Sparse.cusolverSpDestroyCsrqrInfo(_info);
				Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpDestroyCsrqrInfo", res));
				disposed = true;
			}
			if (!fDisposing && !disposed)
				Debug.WriteLine(String.Format("ManagedCUDA not-disposed warning: {0}", this.GetType()));
		}
Exemple #35
0
 /// <summary>
 /// For IDisposable
 /// </summary>
 /// <param name="fDisposing"></param>
 protected virtual void Dispose(bool fDisposing)
 {
     if (fDisposing && !disposed)
     {
         res = CudaSolveNativeMethods.Refactorization.cusolverRfDestroy(_handle);
         Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfDestroy", res));
         disposed = true;
     }
     if (!fDisposing && !disposed)
     {
         Debug.WriteLine(String.Format("ManagedCUDA not-disposed warning: {0}", this.GetType()));
     }
 }
		/// <summary>
		/// This routine gets the report whether numeric boosting was used in the
		/// cusolverRfRefactor() and cusolverRfSolve() routines.
		/// </summary>
		/// <param name="report">the enumerated boosting report type.</param>
		public void GetNumericBoostReport(ref NumericBoostReport report)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfGetNumericBoostReport(_handle, ref report);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetNumericBoostReport", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine gets the algorithm used for the refactorization in cusolverRfRefactor()
		/// and the triangular solve in cusolverRfSolve(). It may be called once prior to
		/// cusolverRfAnalyze() routine.
		/// </summary>
		/// <param name="factAlg">the enumerated algorithm type.</param>
		/// <param name="solveAlg">the enumerated algorithm type.</param>
		public void GetAlgs(ref Factorization factAlg, ref TriangularSolve solveAlg)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfGetAlgs(_handle, ref factAlg, ref solveAlg);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetAlgs", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine performs the forward and backward solve with the lower and upper
		/// triangular factors resulting from the LU re-factorization
		/// </summary>
		/// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
		/// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
		/// <param name="nrhs">the number right-hand-sides to be solved.</param>
		/// <param name="Temp">the dense matrix that contains temporary workspace (of size ldt*nrhs).</param>
		/// <param name="ldt">the leading dimension of dense matrix Temp (ldt &gt;= n).</param>
		/// <param name="XF">the dense matrix that contains the righthand-sides F and solutions X (of size ldxf*nrhs).</param>
		/// <param name="ldxf">the leading dimension of dense matrix XF (ldxf &gt;= n).</param>
		public void Solve(CudaDeviceVariable<int> P, CudaDeviceVariable<int> Q, int nrhs, double[] Temp, int ldt, double[] XF, int ldxf)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfSolve(_handle, P.DevicePointer, Q.DevicePointer, nrhs, Temp, ldt, XF, ldxf);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSolve", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This function solves the following least-square problem x = argmin||A*z-b||
		/// </summary>
		/// <param name="m">number of rows of matrix A.</param>
		/// <param name="n">number of columns of matrix A.</param>
		/// <param name="nnz">number of nonzeros of matrix A.</param>
		/// <param name="descrA">the descriptor of matrix A. The supported matrix type is
		/// CUSPARSE_MATRIX_TYPE_GENERAL. Also, the supported index bases are CUSPARSE_INDEX_BASE_ZERO and CUSPARSE_INDEX_BASE_ONE.</param>
		/// <param name="csrValA">array of nnz (= csrRowPtrA(n) * csrRowPtrA(0)) nonzero elements of matrix A.</param>
		/// <param name="csrRowPtrA">integer array of n + 1 elements that contains the start of every row and the end of the last row plus one.</param>
		/// <param name="csrColIndA">integer array of nnz (=csrRowPtrA(n) * csrRowPtrA(0)) column indices of the nonzero elements of matrix A.</param>
		/// <param name="b">right hand side vector of size m.</param>
		/// <param name="tol">tolerance to decide rank of A.</param>
		/// <param name="rankA">numerical rank of A.</param>
		/// <param name="x">solution vector of size n, x=pinv(A)*b.</param>
		/// <param name="p">a vector of size n, which represents the permuation matrix P satisfying A*P^T=Q*R.</param>
		/// <param name="min_norm">||A*x-b||, x=pinv(A)*b.</param>
		public void CsrlsqvqrHost(int m, int n, int nnz, CudaSparseMatrixDescriptor descrA, cuDoubleComplex[] csrValA, int[] csrRowPtrA, int[] csrColIndA, cuDoubleComplex[] b, double tol, ref int rankA, cuDoubleComplex[] x, int[] p, ref double min_norm)
		{
			res = CudaSolveNativeMethods.Sparse.cusolverSpZcsrlsqvqrHost(_handle, m, n, nnz, descrA.Descriptor, csrValA, csrRowPtrA, csrColIndA, b, tol, ref rankA, x, p, ref min_norm);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpZcsrlsqvqrHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine gets the matrix format used in the cusolverRfSetup(),
		/// cusolverRfSetupHost(), cusolverRfResetValues(), cusolverRfExtractBundledFactorsHost() and cusolverRfExtractSplitFactorsHost() routines.
		/// </summary>
		/// <param name="format">the enumerated matrix format type.</param>
		/// <param name="diag">the enumerated unit diagonal type.</param>
		public void GetMatrixFormat(ref MatrixFormat format, ref UnitDiagonal diag)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfGetMatrixFormat(_handle, ref format, ref diag);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetMatrixFormat", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary/>
		public void CsreigsHost(int m, int nnz, CudaSparseMatrixDescriptor descrA, cuDoubleComplex[] csrValA, int[] csrRowPtrA, int[] csrColIndA, cuDoubleComplex left_bottom_corner, cuDoubleComplex right_upper_corner, ref int num_eigs)
		{
			res = CudaSolveNativeMethods.Sparse.cusolverSpZcsreigsHost(_handle, m, nnz, descrA.Descriptor, csrValA, csrRowPtrA, csrColIndA, left_bottom_corner, right_upper_corner, ref num_eigs);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpZcsreigsHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="error"></param>
		public CudaSolveException(cusolverStatus error)
			: base(GetErrorMessageFromCUResult(error))
		{
			this._solverStatus = error;
		}
		/// <summary>
		/// This routine performs the LU re-factorization
		/// </summary>
		public void Refactor(cusolverRfHandle handle)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfRefactor(_handle);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfRefactor", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine allows direct access to the lower L and upper U triangular factors stored in
		/// the cuSolverRF library handle. The factors are compressed into a single matrix M=(LI)+
		/// U, where the unitary diagonal of L is not stored. It is assumed that a prior call to the
		/// cusolverRfRefactor() was done in order to generate these triangular factors.
		/// </summary>
		/// <param name="nnzM">the number of non-zero elements of matrix M.</param>
		/// <param name="Mp">the array of offsets corresponding to the start of each row in the arrays Mi and Mx.
		/// This array has also an extra entry at the end that stores the number of non-zero elements in the matrix $M$. The array size is n+1.</param>
		/// <param name="Mi">the array of column indices corresponding to the non-zero elements in the matrix M. It is assumed that this array is sorted by row and by column within each row. The array size is nnzM.</param>
		/// <param name="Mx">the array of values corresponding to the non-zero elements in the matrix M. It is assumed that this array is sorted by row and by column within each row. The array size is nnzM.</param>
		public void AccessBundledFactorsDevice(out int nnzM, out CudaDeviceVariable<int> Mp, out CudaDeviceVariable<int> Mi, out CudaDeviceVariable<double> Mx)
		{
			CUdeviceptr d_mp = new CUdeviceptr();
			CUdeviceptr d_mi = new CUdeviceptr();
			CUdeviceptr d_mx = new CUdeviceptr();
			nnzM = 0;

			res = CudaSolveNativeMethods.Refactorization.cusolverRfAccessBundledFactorsDevice(_handle, ref nnzM, ref d_mp, ref d_mi, ref d_mx);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfAccessBundledFactorsDevice", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);

			Mp = new CudaDeviceVariable<int>(d_mp);
			Mi = new CudaDeviceVariable<int>(d_mi);
			Mx = new CudaDeviceVariable<double>(d_mx);
		}
		/// <summary>
		/// This routine allows direct access to the lower L and upper U triangular factors stored in
		/// the cuSolverRF library handle. The factors are compressed into a single matrix M=(LI)+
		/// U, where the unitary diagonal of L is not stored. It is assumed that a prior call to the
		/// cusolverRfRefactor() was done in order to generate these triangular factors.
		/// </summary>
		/// <param name="n">Size of Matrix M (n x n)</param>
		/// <param name="h_nnzM">the number of non-zero elements of matrix M.</param>
		/// <param name="h_Mp">the array of offsets corresponding to the start of each row in the arrays Mi and Mx.
		/// This array has also an extra entry at the end that stores the number of non-zero elements in the matrix $M$. The array size is n+1.</param>
		/// <param name="h_Mi">the array of column indices corresponding to the non-zero elements in the matrix M. It is assumed that this array is sorted by row and by column within each row. The array size is nnzM.</param>
		/// <param name="h_Mx">the array of values corresponding to the non-zero elements in the matrix M. It is assumed that this array is sorted by row and by column within each row. The array size is nnzM.</param>
		public void ExtractBundledFactorsHost(int n, out int h_nnzM, out int[] h_Mp, out int[] h_Mi, out double[] h_Mx)
		{
			h_nnzM = 0;
			IntPtr mp = new IntPtr();
			IntPtr mi = new IntPtr();
			IntPtr mx = new IntPtr();

			res = CudaSolveNativeMethods.Refactorization.cusolverRfExtractBundledFactorsHost(_handle, ref h_nnzM, ref mp, ref mi, ref mx);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfExtractBundledFactorsHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);

			if (h_nnzM == 0)
			{
				h_Mp = null;
				h_Mi = null;
				h_Mx = null;
			}
			else
			{
				h_Mp = new int[n+1];
				h_Mi = new int[h_nnzM];
				h_Mx = new double[h_nnzM];
				Marshal.Copy(mp, h_Mp, 0, n + 1);
				Marshal.Copy(mi, h_Mi, 0, h_nnzM);
				Marshal.Copy(mx, h_Mx, 0, h_nnzM);
			}

		}
		/// <summary>
		/// This routine extracts lower (L) and upper (U) triangular factors from the
		/// cuSolverRF library handle into the host memory. It is assumed that a prior call to the
		/// cusolverRfRefactor() was done in order to generate these triangular factors.
		/// </summary>
		/// <param name="n">Size of Matrix M (n x n)</param>
		/// <param name="h_nnzL">the number of non-zero elements of matrix L.</param>
		/// <param name="h_csrRowPtrL">the array of offsets corresponding to the start of each row in the arrays h_Li and
		/// h_Lx. This array has also an extra entry at the end that stores the number of nonzero elements in the matrix L. The array size is n+1.</param>
		/// <param name="h_csrColIndL">the array of column indices corresponding to the non-zero elements in the matrix L. It is assumed that this array is sorted by
		/// row and by column within each row. The array size is h_nnzL.</param>
		/// <param name="h_csrValL">the array of values corresponding to the non-zero elements in the matrix L. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is h_nnzL.</param>
		/// <param name="h_nnzU">the number of non-zero elements of matrix U.</param>
		/// <param name="h_csrRowPtrU">the array of offsets corresponding to the start of each row in the arrays h_Ui and h_Ux. This array has also an extra entry
		/// at the end that stores the number of nonzero elements in the matrix U. The array size is n+1.</param>
		/// <param name="h_csrColIndU">the array of column indices corresponding to the non-zero elements in the matrix U. It is assumed that this array is sorted by
		/// row and by column within each row. The array size is h_nnzU.</param>
		/// <param name="h_csrValU">the array of values corresponding to the non-zero elements in the matrix U. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is h_nnzU.</param>
		public void ExtractSplitFactorsHost(int n, out int h_nnzL, out int[] h_csrRowPtrL, out int[] h_csrColIndL, out double[] h_csrValL, out int h_nnzU, out int[] h_csrRowPtrU, out int[] h_csrColIndU, out double[] h_csrValU)
		{
			h_nnzL = 0;
			h_nnzU = 0;
			IntPtr RowPtrL = new IntPtr();
			IntPtr ColIndL = new IntPtr();
			IntPtr ValL = new IntPtr();
			IntPtr RowPtrU = new IntPtr();
			IntPtr ColIndU = new IntPtr();
			IntPtr ValU = new IntPtr();

			res = CudaSolveNativeMethods.Refactorization.cusolverRfExtractSplitFactorsHost(_handle, ref h_nnzL, ref RowPtrL, ref ColIndL, ref ValL, ref h_nnzU, ref RowPtrU, ref ColIndU, ref ValU);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfExtractSplitFactorsHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);

			if (h_nnzL == 0)
			{
				h_csrRowPtrL = null;
				h_csrColIndL = null;
				h_csrValL = null;
			}
			else
			{
				h_csrRowPtrL = new int[n + 1];
				h_csrColIndL = new int[h_nnzL];
				h_csrValL = new double[h_nnzL];
				Marshal.Copy(RowPtrL, h_csrRowPtrL, 0, n + 1);
				Marshal.Copy(ColIndL, h_csrColIndL, 0, h_nnzL);
				Marshal.Copy(ValL, h_csrValL, 0, h_nnzL);
			}
			if (h_nnzU == 0)
			{
				h_csrRowPtrU = null;
				h_csrColIndU = null;
				h_csrValU = null;
			}
			else
			{
				h_csrRowPtrU = new int[n + 1];
				h_csrColIndU = new int[h_nnzU];
				h_csrValU = new double[h_nnzU];
				Marshal.Copy(RowPtrU, h_csrRowPtrU, 0, n + 1);
				Marshal.Copy(ColIndU, h_csrColIndU, 0, h_nnzU);
				Marshal.Copy(ValU, h_csrValU, 0, h_nnzU);
			}
		}
		/// <summary>
		/// This routine updates internal data structures with the values of the new coefficient
		/// matrix. It is assumed that the arrays csrRowPtrA, csrColIndA, P and Q have not 
		/// changed since the last call to the cusolverRfbatch_setup_host routine.
		/// </summary>
		/// <param name="batchSize">the number of matrices in batched mode.</param>
		/// <param name="n">the number of rows (and columns) of matrix A.</param>
		/// <param name="nnzA">the number of non-zero elements of matrix A.</param>
		/// <param name="csrRowPtrA">the array of offsets corresponding to the start of each row in the arrays csrColIndA and csrValA. 
		/// This array has also an extra entry at the end that stores the number of non-zero elements in the matrix. The array size is n+1.</param>
		/// <param name="csrColIndA">the array of column indices corresponding to the non-zero elements in the matrix. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzA.</param>
		/// <param name="csrValA_array">array of pointers of size batchSize, each pointer points to the array of values corresponding to the non-zero elements in the matrix.</param>
		/// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
		/// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
		public void BatchResetValues(int batchSize, int n, int nnzA, CudaDeviceVariable<int> csrRowPtrA, CudaDeviceVariable<int> csrColIndA, CudaDeviceVariable<double>[] csrValA_array, CudaDeviceVariable<int> P, CudaDeviceVariable<int> Q)
		{
			if (batchSize > csrValA_array.Length)
			{
				throw new ArgumentException("batchSize must be smaller or equal to the length of csrValA_array.");
			}

			CUdeviceptr[] valA = new CUdeviceptr[batchSize];
			for (int i = 0; i < batchSize; i++)
			{
				valA[i] = csrValA_array[i].DevicePointer;
			}

			res = CudaSolveNativeMethods.Refactorization.cusolverRfBatchResetValues(batchSize, n, nnzA, csrRowPtrA.DevicePointer, csrColIndA.DevicePointer, valA, P.DevicePointer, Q.DevicePointer, _handle);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfBatchResetValues", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine gets the numeric values used for checking for "zero" pivot and for boosting
		/// it in the cusolverRfRefactor() and cusolverRfSolve() routines. It may be called 
		/// multiple times prior to cusolverRfRefactor() and cusolverRfSolve() routines.
		/// The numeric boosting will be used only if boost &gt; 0.0.
		/// </summary>
		/// <param name="zero">the value below which zero pivot is flagged.</param>
		/// <param name="boost">the value which is substituted for zero pivot (if the later is flagged).</param>
		public void GetNumericProperties(ref double zero, ref double boost)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfGetNumericProperties(_handle, ref zero, ref boost);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfGetNumericProperties", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// Symmetric Approximate minimum degree algorithm based on quotient graph.<para/>
		/// This function implements Symmetric Approximate Minimum Degree Algorithm based
		/// on Quotient Graph. It returns a permutation vector p such that A(p,p) would have less
		/// zero fill-in during Cholesky factorization.
		/// </summary>
		/// <param name="n">number of rows and columns of matrix A.</param>
		/// <param name="nnzA">number of nonzeros of matrix A. It is the size of csrValA and csrColIndA.</param>
		/// <param name="descrA">the descriptor of matrix A. The supported matrix type is
		/// CUSPARSE_MATRIX_TYPE_GENERAL. Also, the supported index bases are CUSPARSE_INDEX_BASE_ZERO and CUSPARSE_INDEX_BASE_ONE.</param>
		/// <param name="csrRowPtrA">integer array of n + 1 elements that contains the start of every row and the end of the last row plus one.</param>
		/// <param name="csrColIndA">integer array of nnz (=csrRowPtrA(n) * csrRowPtrA(0)) column indices of the nonzero elements of matrix A.</param>
		/// <param name="p">permutation vector of size n.</param>
		public void CsrsymamdHost(int n, int nnzA, CudaSparseMatrixDescriptor descrA, int[] csrRowPtrA, int[] csrColIndA, int[] p)
		{
			res = CudaSolveNativeMethods.Sparse.cusolverSpXcsrsymamdHost(_handle, n, nnzA, descrA.Descriptor, csrRowPtrA, csrColIndA, p);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpXcsrsymamdHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// To solve A_j * x_j = b_j, first we reform the equation by M_j * Q * x_j = P * b_j. Then do refactorization by
		/// cusolverRfBatch_Refactor(). Further cusolverRfBatch_Solve() takes over the remaining steps.
		/// </summary>
		/// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
		/// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
		/// <param name="nrhs">the number right-hand-sides to be solved.</param>
		/// <param name="Temp">the dense matrix that contains temporary workspace (of size ldt*nrhs).</param>
		/// <param name="ldt">the leading dimension of dense matrix Temp (ldt &gt;= n).</param>
		/// <param name="XF_array">array of pointers of size batchSize, each pointer points to the dense matrix that contains the right-hand-sides F and solutions X (of size ldxf*nrhs).</param>
		/// <param name="ldxf">the leading dimension of dense matrix XF (ldxf &gt;= n).</param>
		public void cusolverRfBatchSolve(CudaDeviceVariable<int> P, CudaDeviceVariable<int> Q, int nrhs, double[] Temp, int ldt, double[][] XF_array, int ldxf)
		{
			int batchSize = XF_array.Length;

			IntPtr[] XF = new IntPtr[batchSize];
			GCHandle[] handles = new GCHandle[batchSize];

			try
			{
				for (int i = 0; i < batchSize; i++)
				{
					handles[i] = GCHandle.Alloc(XF_array[i], GCHandleType.Pinned);
					XF[i] = handles[i].AddrOfPinnedObject();
				}

				res = CudaSolveNativeMethods.Refactorization.cusolverRfBatchSolve(_handle, P.DevicePointer, Q.DevicePointer, nrhs, Temp, ldt, XF, ldxf);
				Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfBatchSolve", res));
			}
			catch
			{
				throw;
			}
			finally
			{
				for (int i = 0; i < batchSize; i++)
				{
					handles[i].Free();
				}
			}
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		private static string GetErrorMessageFromCUResult(cusolverStatus error)
		{
			string message = string.Empty;
			string correct = string.Empty;

			switch (error)
			{
				case cusolverStatus.Success:
					message = "No Error.";
					break;
				case cusolverStatus.NotInititialized:
					message = "The cuSolver library was not initialized. This is usually caused by the lack of a prior call, an error in the CUDA Runtime API called by the cuSolver routine, or an error in the hardware setup.";
					correct = "\nTo correct: call cusolverCreate() prior to the function call; and check that the hardware, an appropriate version of the driver, and the cuSolver library are correctly installed.";
					break;
				case cusolverStatus.AllocFailed:
					message = "Resource allocation failed inside the cuSolver library. This is usually caused by a cudaMalloc() failure.";
					correct = "\nTo correct: prior to the function call, deallocate previously allocated memory as much as possible.";
					break;
				case cusolverStatus.InvalidValue:
					message = "An unsupported value or parameter was passed to the function (a negative vector size, for example).";
					correct = "\nTo correct: ensure that all the parameters being passed have valid values.";
					break;
				case cusolverStatus.ArchMismatch:
					message = "The function requires a feature absent from the device architecture; usually caused by the lack of support for atomic operations or double precision.";
					correct = "\nTo correct: compile and run the application on a device with compute capability 2.0 or above.";
					break;
				case cusolverStatus.MappingError:
					message = "";
					correct = "";
					break;
				case cusolverStatus.ExecutionFailed:
					message = "The GPU program failed to execute. This is often caused by a launch failure of the kernel on the GPU, which can be caused by multiple reasons.";
					correct = "\nTo correct: check that the hardware, an appropriate version of the driver, and the cuSolver library are correctly installed.";
					break;
				case cusolverStatus.InternalError:
					message = "An internal cuSolver operation failed. This error is usually caused by a cudaMemcpyAsync() failure.";
					correct = "\nTo correct: check that the hardware, an appropriate version of the driver, and the cuSolver library are correctly installed. Also, check that the memory passed as a parameter to the routine is not being deallocated prior to the routine’s completion.";
					break;
				case cusolverStatus.MatrixTypeNotSupported:
					message = "The matrix type is not supported by this function. This is usually caused by passing an invalid matrix descriptor to the function.";
					correct = "\nTo correct: check that the fields in descrA were set correctly.";
					break;
				case cusolverStatus.NotSupported:
					message = "";
					correct = "";
					break;
				case cusolverStatus.ZeroPivot:
					message = "";
					correct = "";
					break;
				case cusolverStatus.InvalidLicense:
					message = "";
					correct = "";
					break;
				default:
					break;
			}

			return error.ToString() + ": " + message + correct;
		}
		/// <summary>This routine assembles the internal data structures of the cuSolverRF library. It is often
		/// the first routine to be called after the call to the cusolverRfCreate() routine.
		/// </summary>
		/// <param name="n">the number of rows (and columns) of matrix A.</param>
		/// <param name="nnzA">the number of non-zero elements of matrix A.</param>
		/// <param name="h_csrRowPtrA">the array of offsets corresponding to 
		/// the start of each row in the arrays h_csrColIndA and h_csrValA. This
		/// array has also an extra entry at the end that stores the number of non-zero
		/// elements in the matrix. The array size is n+1.</param>
		/// <param name="h_csrColIndA">the array of column indices corresponding
		/// to the non-zero elements in the matrix. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzA.</param>
		/// <param name="h_csrValA">the array of values corresponding to the
		/// non-zero elements in the matrix. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzA.</param>
		/// <param name="nnzL">the number of non-zero elements of matrix L.</param>
		/// <param name="h_csrRowPtrL">the array of offsets corresponding to
		/// the start of each row in the arrays h_csrColIndL and h_csrValL. This
		/// array has also an extra entry at the end that stores the number of non-zero
		/// elements in the matrix L. The array size is n+1.</param>
		/// <param name="h_csrColIndL">the array of column indices corresponding
		/// to the non-zero elements in the matrix L. It is assumed that this array is sorted by
		/// row and by column within each row. The array size is nnzL.</param>
		/// <param name="h_csrValL">the array of values corresponding to the
		/// non-zero elements in the matrix L. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzL.</param>
		/// <param name="nnzU">the number of non-zero elements of matrix U.</param>
		/// <param name="h_csrRowPtrU">the array of offsets corresponding to
		/// the start of each row in the arrays h_csrColIndU and h_csrValU. This
		/// array has also an extra entry at the end that stores the number of non-zero elements in the matrix U. The array size is n+1.</param>
		/// <param name="h_csrColIndU">the array of column indices corresponding 
		/// to the non-zero elements in the matrix U. It is assumed that this array is sorted by row and by column within each row. The array size is nnzU.</param>
		/// <param name="h_csrValU">the array of values corresponding to the non-zero elements in the matrix U. It is
		/// assumed that this array is sorted by row and by column within each row. The array size is nnzU.</param>
		/// <param name="h_P">the left permutation (often associated with pivoting). The array size in n.</param>
		/// <param name="h_Q">the right permutation (often associated with reordering). The array size in n.</param>
		public void SetupHost(int n, int nnzA, int[] h_csrRowPtrA, int[] h_csrColIndA, double[] h_csrValA, int nnzL, int[] h_csrRowPtrL, int[] h_csrColIndL,
			double[] h_csrValL, int nnzU, int[] h_csrRowPtrU, int[] h_csrColIndU, double[] h_csrValU, int[] h_P, int[] h_Q)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfSetupHost(n, nnzA, h_csrRowPtrA, h_csrColIndA, h_csrValA, nnzL, h_csrRowPtrL, h_csrColIndL, h_csrValL,
				nnzU, h_csrRowPtrU, h_csrColIndU, h_csrValU, h_P, h_Q, _handle);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSetupHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This function solves the simple eigenvalue problem A*x=lambda*x by shift-inverse method.
		/// </summary>
		/// <param name="m">number of rows and columns of matrix A.</param>
		/// <param name="nnz">number of nonzeros of matrix A.</param>
		/// <param name="descrA">the descriptor of matrix A. The supported matrix type is
		/// CUSPARSE_MATRIX_TYPE_GENERAL. Also, the supported index bases are CUSPARSE_INDEX_BASE_ZERO and CUSPARSE_INDEX_BASE_ONE.</param>
		/// <param name="csrValA">array of nnz (= csrRowPtrA(n) * csrRowPtrA(0)) nonzero elements of matrix A.</param>
		/// <param name="csrRowPtrA">integer array of n + 1 elements that contains the start of every row and the end of the last row plus one.</param>
		/// <param name="csrColIndA">integer array of nnz (=csrRowPtrA(n) * csrRowPtrA(0)) column indices of the nonzero elements of matrix A.</param>
		/// <param name="mu0">initial guess of eigenvalue.</param>
		/// <param name="x0">initial guess of eigenvector, a vecotr of size m.</param>
		/// <param name="maxite">maximum iterations in shift-inverse method.</param>
		/// <param name="tol">tolerance for convergence.</param>
		/// <param name="mu">approximated eigenvalue nearest mu0 under tolerance.</param>
		/// <param name="x">approximated eigenvector of size m.</param>
		public void Csreigvsi(int m, int nnz, CudaSparseMatrixDescriptor descrA, CudaDeviceVariable<cuDoubleComplex> csrValA, CudaDeviceVariable<int> csrRowPtrA, CudaDeviceVariable<int> csrColIndA, cuDoubleComplex mu0, CudaDeviceVariable<cuDoubleComplex> x0, int maxite, double tol, ref cuDoubleComplex mu, CudaDeviceVariable<cuDoubleComplex> x)
		{
			res = CudaSolveNativeMethods.Sparse.cusolverSpZcsreigvsi(_handle, m, nnz, descrA.Descriptor, csrValA.DevicePointer, csrRowPtrA.DevicePointer, csrColIndA.DevicePointer, mu0, x0.DevicePointer, maxite, tol, ref mu, x.DevicePointer);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpZcsreigvsi", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="error"></param>
		/// <param name="message"></param>
		/// <param name="exception"></param>
		public CudaSolveException(cusolverStatus error, string message, Exception exception)
			: base(message, exception)
		{
			this._solverStatus = error;
		}
		/// <summary>
		/// This function solves the simple eigenvalue problem A*x=lambda*x by shift-inverse method.
		/// </summary>
		/// <param name="m">number of rows and columns of matrix A.</param>
		/// <param name="nnz">number of nonzeros of matrix A.</param>
		/// <param name="descrA">the descriptor of matrix A. The supported matrix type is
		/// CUSPARSE_MATRIX_TYPE_GENERAL. Also, the supported index bases are CUSPARSE_INDEX_BASE_ZERO and CUSPARSE_INDEX_BASE_ONE.</param>
		/// <param name="csrValA">array of nnz (= csrRowPtrA(n) * csrRowPtrA(0)) nonzero elements of matrix A.</param>
		/// <param name="csrRowPtrA">integer array of n + 1 elements that contains the start of every row and the end of the last row plus one.</param>
		/// <param name="csrColIndA">integer array of nnz (=csrRowPtrA(n) * csrRowPtrA(0)) column indices of the nonzero elements of matrix A.</param>
		/// <param name="mu0">initial guess of eigenvalue.</param>
		/// <param name="x0">initial guess of eigenvector, a vecotr of size m.</param>
		/// <param name="maxite">maximum iterations in shift-inverse method.</param>
		/// <param name="tol">tolerance for convergence.</param>
		/// <param name="mu">approximated eigenvalue nearest mu0 under tolerance.</param>
		/// <param name="x">approximated eigenvector of size m.</param>
		public void CsreigvsiHost(int m, int nnz, CudaSparseMatrixDescriptor descrA, cuDoubleComplex[] csrValA, int[] csrRowPtrA, int[] csrColIndA, cuDoubleComplex mu0, cuDoubleComplex[] x0, int maxite, double tol, ref cuDoubleComplex mu, cuDoubleComplex[] x)
		{
			res = CudaSolveNativeMethods.Sparse.cusolverSpZcsreigvsiHost(_handle, m, nnz, descrA.Descriptor, csrValA, csrRowPtrA, csrColIndA, mu0, x0, maxite, tol, ref mu, x);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpZcsreigvsiHost", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine sets the mode used in the cusolverRfResetValues routine.
		/// </summary>
		/// <param name="fastMode">the enumerated mode type.</param>
		public void SetResetValuesFastMode(ResetValuesFastMode fastMode)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfSetResetValuesFastMode(_handle, fastMode);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfSetResetValuesFastMode", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This function solves the linear system A*x=b
		/// </summary>
		/// <param name="m">number of rows and columns of matrix A.</param>
		/// <param name="nnz">number of nonzeros of matrix A.</param>
		/// <param name="descrA">the descriptor of matrix A. The supported matrix type is
		/// CUSPARSE_MATRIX_TYPE_GENERAL. Also, the supported index bases are CUSPARSE_INDEX_BASE_ZERO and CUSPARSE_INDEX_BASE_ONE.</param>
		/// <param name="csrValA">array of nnz (= csrRowPtrA(n) * csrRowPtrA(0)) nonzero elements of matrix A.</param>
		/// <param name="csrRowPtrA">integer array of n + 1 elements that contains the start of every row and the end of the last row plus one.</param>
		/// <param name="csrColIndA">integer array of nnz (=csrRowPtrA(n) * csrRowPtrA(0)) column indices of the nonzero elements of matrix A.</param>
		/// <param name="b">right hand side vector of size m.</param>
		/// <param name="tol">tolerance to decide singularity.</param>
		/// <param name="reorder">no effect.</param>
		/// <param name="x">solution vector of size m, x = inv(A)*b.</param>
		/// <returns>-1 if A is invertible. Otherwise, first index j such that U(j,j)≈0</returns>
		public int Csrlsvchol(int m, int nnz, CudaSparseMatrixDescriptor descrA, CudaDeviceVariable<cuDoubleComplex> csrValA, CudaDeviceVariable<int> csrRowPtrA, CudaDeviceVariable<int> csrColIndA, CudaDeviceVariable<cuDoubleComplex> b, float tol, int reorder, CudaDeviceVariable<cuDoubleComplex> x)
		{
			int singularity = 0;
			res = CudaSolveNativeMethods.Sparse.cusolverSpZcsrlsvchol(_handle, m, nnz, descrA.Descriptor, csrValA.DevicePointer, csrRowPtrA.DevicePointer, csrColIndA.DevicePointer, b.DevicePointer, tol, reorder, x.DevicePointer, ref singularity);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverSpZcsrlsvchol", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
			return singularity;
		}
		/// <summary>
		/// This routine assembles the internal data structures of the cuSolverRF library for batched
		/// operation. It is called after the call to the cusolverRfCreate() routine, and before any
		/// other batched routines.
		/// </summary>
		/// <param name="batchSize">the number of matrices in the batched mode.</param>
		/// <param name="n">the number of rows (and columns) of matrix A.</param>
		/// <param name="nnzA">the number of non-zero elements of matrix A.</param>
		/// <param name="h_csrRowPtrA">the array of offsets corresponding to 
		/// the start of each row in the arrays h_csrColIndA and h_csrValA. This array has also an extra entry at the
		/// end that stores the number of non-zero elements in the matrix. The array size is n+1.</param>
		/// <param name="h_csrColIndA">the array of column indices corresponding 
		/// to the non-zero elements in the matrix. It is assumed that this array is sorted by row and by column within each row. The array size is nnzA.</param>
		/// <param name="h_csrValA_array">array of pointers of size batchSize, each pointer points to the array of values corresponding to the non-zero elements in the matrix.</param>
		/// <param name="nnzL">the number of non-zero elements of matrix L.</param>
		/// <param name="h_csrRowPtrL">the array of offsets corresponding to the start of each row in the arrays h_csrColIndL and h_csrValL. This
		/// array has also an extra entry at the end that stores the number of non-zero elements in the matrix L. The array size is n+1.</param>
		/// <param name="h_csrColIndL">the array of column indices corresponding to the non-zero elements in the matrix L. It is assumed that this array is sorted by
		/// row and by column within each row. The array size is nnzL.</param>
		/// <param name="h_csrValL">the array of values corresponding to the non-zero elements in the matrix L. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzL.</param>
		/// <param name="nnzU">the number of non-zero elements of matrix U.</param>
		/// <param name="h_csrRowPtrU">the array of offsets corresponding to the start of each row in the arrays h_csrColIndU and h_csrValU. This
		/// array has also an extra entry at the end that stores the number of non-zero elements in the matrix U. The array size is n+1.</param>
		/// <param name="h_csrColIndU">the array of column indices corresponding to the non-zero elements in the matrix U. It is assumed that this array is sorted by
		/// row and by column within each row. The array size is nnzU.</param> 
		/// <param name="h_csrValU">the array of values corresponding to the non-zero elements in the matrix U. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzU.</param>
		/// <param name="h_P">the left permutation (often associated with pivoting). The array size in n.</param>
		/// <param name="h_Q">the right permutation (often associated with reordering). The array size in n.</param>
		/// <param name="handle">the pointer to the cuSolverRF library handle.</param>
		public void BatchSetupHost(int batchSize, int n, int nnzA, int[] h_csrRowPtrA, int[] h_csrColIndA, double[][] h_csrValA_array, int nnzL,
			int[] h_csrRowPtrL, int[] h_csrColIndL, double[] h_csrValL, int nnzU, int[] h_csrRowPtrU, int[] h_csrColIndU, double[] h_csrValU, int[] h_P, int[] h_Q, cusolverRfHandle handle)
		{
			if (batchSize > h_csrValA_array.Length)
			{
				throw new ArgumentException("batchSize must be smaller or equal to the length of h_csrValA_array.");
			}

			IntPtr[] valA = new IntPtr[batchSize];
			GCHandle[] handles = new GCHandle[batchSize];

			try
			{
				for (int i = 0; i < batchSize; i++)
				{
					handles[i] = GCHandle.Alloc(h_csrValA_array[i], GCHandleType.Pinned);
					valA[i] = handles[i].AddrOfPinnedObject();
				}

				res = CudaSolveNativeMethods.Refactorization.cusolverRfBatchSetupHost(batchSize, n, nnzA, h_csrRowPtrA, h_csrColIndA, valA, nnzL,
				h_csrRowPtrL, h_csrColIndL, h_csrValL, nnzU, h_csrRowPtrU, h_csrColIndU, h_csrValU, h_P, h_Q, _handle);
				Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfBatchSetupHost", res));
			}
			catch
			{
				throw;
			}
			finally
			{
				for (int i = 0; i < batchSize; i++)
				{
					handles[i].Free();
				}
			}
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// This routine updates internal data structures with the values of the new coefficient
		/// matrix. It is assumed that the arrays csrRowPtrA, csrColIndA, P and Q have not
		/// changed since the last call to the cusolverRfSetup[Host] routine. This assumption
		/// reflects the fact that the sparsity pattern of coefficient matrices as well as reordering to
		/// minimize fill-in and pivoting remain the same in the set of linear systems
		/// </summary>
		/// <param name="n">the number of rows (and columns) of matrix A.</param>
		/// <param name="nnzA">the number of non-zero elements of matrix A.</param>
		/// <param name="csrRowPtrA">the array of offsets corresponding to the start of each row in the arrays
		/// csrColIndA and csrValA. This array has also an extra entry at the end that stores the number of non-zero elements in the
		/// matrix. The array size is n+1.</param>
		/// <param name="csrColIndA">the array of column indices corresponding to the non-zero elements in the matrix. It
		/// is assumed that this array is sorted by row and by column within each row. The array size is nnzA.</param>
		/// <param name="csrValA">the array of values corresponding to the non-zero elements in the matrix. It is assumed that this array is sorted by row
		/// and by column within each row. The array size is nnzA.</param>
		/// <param name="P">the left permutation (often associated with pivoting). The array size in n.</param>
		/// <param name="Q">the right permutation (often associated with reordering). The array size in n.</param>
		public void ResetValues(int n, int nnzA, CudaDeviceVariable<int> csrRowPtrA, CudaDeviceVariable<int> csrColIndA, CudaDeviceVariable<double> csrValA,
			CudaDeviceVariable<double> P, CudaDeviceVariable<double> Q)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfResetValues(n, nnzA, csrRowPtrA.DevicePointer, csrColIndA.DevicePointer, 
				csrValA.DevicePointer, P.DevicePointer, Q.DevicePointer, _handle);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfResetValues", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}
		/// <summary>
		/// The user can query which matrix failed LU refactorization by checking
		/// corresponding value in position array. The input parameter position is an integer array of size batchSize.
		/// </summary>
		/// <param name="position">integer array of size batchSize. The value of position(j) reports singularity
		/// of matrix Aj, -1 if no structural / numerical zero, k &gt;= 0 if Aj(k,k) is either structural zero or numerical zero.</param>
		public void BatchZeroPivot(int[] position)
		{
			res = CudaSolveNativeMethods.Refactorization.cusolverRfBatchZeroPivot(_handle, position);
			Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cusolverRfBatchZeroPivot", res));
			if (res != cusolverStatus.Success) throw new CudaSolveException(res);
		}