/// <summary> /// calls the PCG solver /// </summary> /// <param name="Converged">true if converged</param> /// <param name="NoOfIter">no of iterations done by solver</param> /// <param name="Unknowns"></param> /// <param name="Rhs"></param> protected override void CallSolver(out int NoOfIter, out bool Converged, IJVector Unknowns, IJVector Rhs) { if (m_Solver.p == IntPtr.Zero) { throw new ApplicationException("solver not initialized"); } HypreException.Check(Wrappers.PCG.Setup(m_Solver, m_Matrix.m_ParCSR_matrix, Rhs.ParCRS_vector, Unknowns.ParCRS_vector)); Wrappers.PCG.Solve(m_Solver, m_Matrix.m_ParCSR_matrix, Rhs.ParCRS_vector, Unknowns.ParCRS_vector); // We don't want to raise an exception for // a 'method did not converge'- or 'numerical breakdown' - Error // that may occur in HYPRE Wrappers.Utilities.HYPRE_ClearAllErrors(); int Con; HypreException.Check(Wrappers.PCG.GetConverged(m_Solver, out Con)); if (Con != 0) { Converged = true; } else { Converged = false; } HypreException.Check(Wrappers.PCG.GetNumIterations(m_Solver, out NoOfIter)); }
/// <summary> /// general matrix/vector product; see <see cref="ISparseMatrix.SpMV"/>; /// </summary> /// <typeparam name="VectorType1"></typeparam> /// <typeparam name="VectorType2"></typeparam> /// <param name="alpha"></param> /// <param name="a"></param> /// <param name="beta"></param> /// <param name="acc"></param> public void SpMV <VectorType1, VectorType2>(double alpha, VectorType1 a, double beta, VectorType2 acc) where VectorType1 : System.Collections.Generic.IList <double> where VectorType2 : System.Collections.Generic.IList <double> { if (a.Count < ColPartition.LocalLength) { throw new ArgumentException("length/count of 'a' must be equal to local length of column partition", "a"); } if (acc.Count < RowPartitioning.LocalLength) { throw new ArgumentException("length/count of 'acc' must be greater or equal to local length of row partition", "acc"); } if (object.ReferenceEquals(a, acc)) { throw new ArgumentException("in-place computation is not supported.", "a,acc"); } IJVector _acc = new IJVector(RowPartitioning); if (beta != 0.0) { _acc.SetValues(acc); } IJVector _a = new IJVector(ColPartition); _a.SetValues(a); HypreException.Check(Wrappers.ParCSRMatrix.ParCSRMatrixMatvec(alpha, m_ParCSR_matrix, _a.ParCRS_vector, beta, _acc.ParCRS_vector)); _acc.GetValues(acc); _acc.Dispose(); _a.Dispose(); }
/// <summary> /// see <see cref="Solver.CallSolver"/> /// </summary> /// <remarks> /// ParaSails should be used only as aa implicit preconditioner, this method /// exists only for reasons of compability and completeness. /// </remarks> protected override void CallSolver(out int NoOfIter, out bool Converged, IJVector Unknowns, IJVector Rhs) { if (m_Solver.p == IntPtr.Zero) { throw new ApplicationException("solver not initialized"); } HypreException.Check(Wrappers.ParaSails.__HYPRE_ParaSailsSetup(m_Solver, m_Matrix.m_ParCSR_matrix, Rhs.ParCRS_vector, Unknowns.ParCRS_vector)); Wrappers.ParaSails.__HYPRE_ParaSailsSolve(m_Solver, m_Matrix.m_ParCSR_matrix, Rhs.ParCRS_vector, Unknowns.ParCRS_vector); // We dont want to raise an exception for // a 'method did not converge'- or 'nomerical breakdown' - Error // that may occur in HYPRE Wrappers.Utilities.HYPRE_ClearAllErrors(); NoOfIter = 1; Converged = true; }
/// <summary> /// calls the corresponding HYPRE solver function /// </summary> /// <param name="Converged">true if converged</param> /// <param name="NoOfIter">no of iterations done by solver</param> /// <param name="Unknowns">on input, the starting value for the iterative process; /// on output, an approximpate solution to the linear problem.</param> /// <param name="Rhs"> /// on input, the right-hand-side of the problem. /// </param> protected abstract void CallSolver(out int NoOfIter, out bool Converged, IJVector Unknowns, IJVector Rhs);
/// <summary> /// solves the equation system /// (diag(<paramref name="d"/>) + <paramref name="Scale"/>*M)*<paramref name="x"/>=<paramref name="rhs"/>, /// where diag(<paramref name="d"/>) denotes a diagonal matrix with the diagonal vector <paramref name="d"/>; /// </summary> /// <typeparam name="Tunknowns"></typeparam> /// <typeparam name="Trhs"></typeparam> /// <typeparam name="Tdiag"></typeparam> /// <param name="Scale"> /// scaling of the matrix (does not apply to <paramref name="d"/>); /// must be unequal to 0; /// this scaling does not alter the matrix-it's the same after the return of this method. /// </param> /// <param name="d"> /// diagonal vector; can be null; /// length must be equal to the Nupdate-length of the matrix mapping; /// may be altered during execution; /// </param> /// <param name="x">on exit, the approximate solution to the equation system; /// </param> /// <param name="rhs"> /// right hand side of the equation system; may be overwritten; /// </param> public SolverResult Solve <Tdiag, Tunknowns, Trhs>(double Scale, Tdiag d, Tunknowns x, Trhs rhs) where Tdiag : IList <double> where Tunknowns : IList <double> where Trhs : IList <double> { using (new FuncTrace()) { SolverResult res = new SolverResult(); Stopwatch st = new Stopwatch(); st.Reset(); st.Start(); // modify diagonal // =============== // truly, we're not solving (diag(d) + Scale*M)*x = rhs, // but ((1.0/Scale)*diag(d) + M) = (1.0/Scale)*rhs double ooScale = 1.0 / Scale; int N = int.MinValue; if (d != null) { int i0 = (int)m_Matrix.RowPartitioning.i0; N = m_Matrix.RowPartitioning.LocalLength; int Nd = d.Count; if (d.Count > N || N % Nd != 0) { throw new ArgumentException("length must be equal to or a factor of the number of rows stored on this processor", "d"); } int ix = 0; for (int i = 0; i < N; i++) { double vadd = d[ix]; ix++; if (ix >= Nd) { ix = 0; } if (vadd != 0.0) { int iglob = i + i0; double v = m_Matrix.GetDiagonalElement(iglob); v += ooScale * vadd; m_Matrix.SetDiagonalElement(iglob, v); } } } // scale rhs // ========= if (ooScale != 1.0) { for (int i = 0; i < N; i++) { rhs[i] *= ooScale; } } // pass values to HYPRE // ==================== IJVector Unknowns = new IJVector(m_Matrix.ColPartition); IJVector Rhs = new IJVector(m_Matrix.RowPartitioning); Unknowns.SetValues <Tunknowns>(x); Rhs.SetValues <Trhs>(rhs); CallSolver(out res.NoOfIterations, out res.Converged, Unknowns, Rhs); // return // ====== if (d != null) { int ix = 0; int Nd = d.Count; int i0 = (int)m_Matrix.RowPartitioning.i0; for (int i = 0; i < N; i++) { double vadd = d[ix]; ix++; if (ix >= Nd) { ix = 0; } if (vadd != 0.0) { int iglob = i + i0; double v = m_Matrix.GetDiagonalElement(iglob); v -= ooScale * vadd; m_Matrix.SetDiagonalElement(iglob, v); } } } Unknowns.GetValues <Tunknowns>(x); Unknowns.Dispose(); Rhs.Dispose(); st.Stop(); res.RunTime = st.Elapsed; return(res); } }