/// <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> /// 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); } }