Ejemplo n.º 1
0
        /// <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();
        }
Ejemplo n.º 2
0
        /// <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);
            }
        }