コード例 #1
0
        /// <summary>
        /// performs <paramref name="acc"/> = <paramref name="acc"/>*<paramref name="beta"/> + <paramref name="alpha"/>*this*<paramref name="a"/>;
        /// </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>
        /// <remarks>
        /// works only in unlocked matrix state (see <see cref="LockAbleObject.Lock"/>, <see cref="LockAbleObject.Unlock"/>);
        /// </remarks>
        virtual public void SpMV <VectorType1, VectorType2>(double alpha, VectorType1 a, double beta, VectorType2 acc)
            where VectorType1 : IList <double>
            where VectorType2 : IList <double>
        {
            if (acc.Count < this.RowPartitioning.LocalLength)
            {
                throw new ArgumentException("array is too short - must be as least as big as the local length of the row partition.", "acc");
            }
            if (a.Count < this.ColPartition.LocalLength)
            {
                throw new ArgumentException("array is too short - must be as least as big as the local length of the column partition.", "a");
            }
            if (object.ReferenceEquals(a, acc))
            {
                throw new ArgumentException("in-place computation is not supported.", "a,acc");
            }

            // create vector objects
            bool       dummy;
            VectorBase _a = CreateVec(a, this.ColPartition, out dummy);

            using (VectorBase.CommVector _a_comm = _a.CreateCommVector(this)) {
                bool       notWriteBackReq;
                VectorBase _acc = CreateVec(acc, this.RowPartitioning, out notWriteBackReq);

                // lock objects
                this.Lock();
                _a.Lock();
                _acc.Lock();

                // check args
                if (!_a.Part.Equals(this.ColPartition))
                {
                    throw new ArgumentException("mismatch between column partition and partition of a.", "a");
                }
                if (!_acc.Part.Equals(this.RowPartitioning))
                {
                    throw new ArgumentException("mismatch between row partition and partition of acc.", "acc");
                }

                // real work:
                SpMV_Expert(alpha, _a_comm, beta, _acc);

                // unlock
                _a.Unlock();
                _acc.Unlock();
                this.Unlock();

                // copy back result (if required)
                if (!notWriteBackReq)
                {
                    _acc.GetValues(acc, 0, 0, this.RowPartitioning.LocalLength);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// see <see cref="IMonkeyImplicitPrecond.ReleaseTempObjects"/>
        /// </summary>
        public override void ReleaseTempObjects()
        {
            // unlock
            // ======
            tmp.Unlock();
            tmp.Dispose();
            tmp = null;

            m_InvDiag.Unlock();

            _xComm.Dispose();
            _xComm = null;
        }
コード例 #3
0
ファイル: NeumannSeries.cs プロジェクト: xyuan/BoSSS
        /// <summary>
        /// The used temporary objects are unlocked and set to null
        /// </summary>
        public override void ReleaseTempObjects()
        {
            //unlock
            yOld.Unlock();
            yOld.Dispose();
            yOld = null;

            _yComm.Dispose();
            _yComm = null;

            yNew.Unlock();
            yNew.Dispose();
            yNew = null;
        }
コード例 #4
0
ファイル: Jacobi.cs プロジェクト: xyuan/BoSSS
        /// <summary>
        /// executes the Jacobi iteration
        /// </summary>
        protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats)
        {
            // create objects
            // ==============

            VectorBase.CommVector _xComm  = x.CreateCommVector(m_Matrix);
            VectorBase            tmp     = Device.CreateVector(x.Part);
            VectorBase            InvDiag = CreateInvDiag();

            // lock objects
            // ============
            x.Lock();
            m_Matrix.Lock();
            rhs.Lock();
            tmp.Lock();
            InvDiag.Lock();


            // iterate
            // =======
            stats.Converged      = false;
            stats.NoOfIterations = 0;
            double residualNorm = double.MaxValue;
            double r_0          = double.NaN;

            while (true)
            {
                // loop termination
                // ================
                if (stats.NoOfIterations >= m_MinIterations)   // do at least the minimum number of iterations

                {
                    if (residualNorm <= m_Tolerance)
                    {
                        // success
                        stats.Converged = true;
                        break;
                    }

                    if (stats.NoOfIterations >= m_MaxIterations)
                    {
                        // terminate
                        break;
                    }
                }

                // Jacobi iteration
                // ================
                m_Matrix.SpMV_Expert(-1.0, _xComm, 0.0, tmp); // tmp = -M*x
                tmp.Acc(1.0, rhs);                            // tmp = -M*x + rhs
                if (m_UnderRelaxationFactor != 1.0)
                {
                    tmp.Scale(m_UnderRelaxationFactor);
                }

                double r = Math.Sqrt(tmp.TwoNormSquare());
                if (stats.NoOfIterations == 0)
                {
                    r_0 = r;
                }
                if (m_ConvergenceType == ConvergenceTypes.Absolute)
                {
                    residualNorm = r;
                }
                else
                {
                    residualNorm = r / r_0;
                }
                //Console.WriteLine("JACOBI: " + residualNorm);

                if (m_UnderRelaxationFactor != 1.0)
                {
                    tmp.Scale(m_UnderRelaxationFactor);
                }
                tmp.MultiplyElementWise(InvDiag);

                x.Acc(1.0, tmp);

                stats.NoOfIterations++;
            }


            // unlock
            // ======
            x.Unlock();
            m_Matrix.Unlock();
            rhs.Unlock();
            InvDiag.Unlock();
        }
コード例 #5
0
        /// <summary>
        /// see <see cref="ISparseSolverExt.Solve{Tdiag, Tunknowns, Trhs}(double,Tdiag,Tunknowns,Trhs)"/>;
        /// </summary>
        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 (var tr = new ilPSP.Tracing.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);
                        }
                    }
                }

                // pass values to monkey
                // =====================
                bool       shallow, dummy2;
                VectorBase X   = Device.CreateVector(m_Matrix.ColPartition, x, out shallow);
                VectorBase Rhs = Device.CreateVector(m_Matrix.RowPartitioning, rhs, out dummy2);

                // scale rhs
                // =========

                if (ooScale != 1.0)
                {
                    Rhs.Lock();
                    Rhs.Scale(ooScale);
                    Rhs.Unlock();
                }

                // call Solver
                // ===========

                CallSolver(X, Rhs, ref res);

                if (res.Converged != true)
                {
                    Logger.Warn("Solver did NOT CONVERGE: " + res.ToString());
                }


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

                if (!shallow)
                {
                    X.GetValues(x, 0, 0, m_Matrix.ColPartition.LocalLength);
                }
                X.Dispose();
                Rhs.Dispose();

                st.Stop();
                res.RunTime = st.Elapsed;
                return(res);
            }
        }
コード例 #6
0
        //[DllImport("Kernel32.dll")]
        //static extern bool QueryPerformanceCounter(out long lpPerformanceCount);


        /// <summary>
        /// implementation of the CG algorithm
        /// </summary>
        /// <param name="x"></param>
        /// <param name="rhs"></param>
        /// <param name="stats"></param>
        protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats)
        {
            VectorBase P = Device.CreateVector(x.Part);

            VectorBase.CommVector commP = P.CreateCommVector(m_Matrix);

            VectorBase R = rhs; // rhs is only needed once, so we can use it to store residuals
            VectorBase V = Device.CreateVector(x.Part);

            // lock objects
            // ============
            x.Lock();
            P.Lock();
            R.Lock();
            V.Lock();

            m_Matrix.Lock();


            // compute P0, R0
            // ==============

            // we only need to multiply x once by the Matrix, so we don't want to create
            // a seperate VectorBase.CommVector - object for x;
            // Instead, we're temporatily exchangeing the roles of x and P;
            P.Swap(x);
            x.CopyFrom(rhs);                               // x = rhs
            m_Matrix.SpMV_Expert(-1.0, commP, 1.0, x);     // x = rhs - M*x
            P.Swap(x);
            R.CopyFrom(P);

            double alpha   = R.TwoNormSquare();
            double alpha_0 = alpha;
            double ResNorm;

            if (m_ConvergenceType == ConvergenceTypes.Absolute)
            {
                ResNorm = Math.Sqrt(alpha);
            }
            else if (m_ConvergenceType == ConvergenceTypes.Relative)
            {
                ResNorm = 1.0;
            }
            else
            {
                throw new NotImplementedException("unknown convergence type: " + m_ConvergenceType.ToString());
            }

            //long total = 0;
            //long gemv = 0;
            //long rest = 0;
            //long st, en;

            // iterate
            // =======
            stats.Converged      = false;
            stats.NoOfIterations = 1; // one iteration has already been performed (P0, R0)
            for (int n = m_MaxIterations - 2; n >= 0; n--)
            {
                if (ResNorm <= m_Tolerance && stats.NoOfIterations >= base.m_MinIterations)
                {
                    stats.Converged = true;
                    break;
                }

                if (Math.Abs(alpha) <= double.Epsilon)
                {
                    // numerical breakdown
                    break;
                }

                m_Matrix.SpMV_Expert(1.0, commP, 0, V);
                double lambda = alpha / V.InnerProd(P);


                x.Acc(lambda, P);

                R.Acc(-lambda, V);

                double alpha_neu = R.TwoNormSquare();

                // compute residual norm
                if (m_ConvergenceType == ConvergenceTypes.Absolute)
                {
                    ResNorm = Math.Sqrt(alpha);
                }
                else
                {
                    ResNorm = Math.Sqrt(alpha / alpha_0);
                }


                P.Scale(alpha_neu / alpha);
                P.Acc(1.0, R);

                alpha = alpha_neu;
                stats.NoOfIterations++;
                //QueryPerformanceCounter(out st);
                //rest += (st - en);
            }

            //Console.WriteLine("CG: R" + stats.NoOfIterations + " = " + ResNorm);

            // unlock objects
            // ==============
            x.Unlock();
            P.Unlock();
            R.Unlock();
            V.Unlock();

            m_Matrix.Unlock();

            commP.Dispose();
            P.Dispose();
            V.Dispose();
        }
コード例 #7
0
        /// <summary>
        /// implementation of the CG algorithm
        /// </summary>
        /// <param name="x"></param>
        /// <param name="rhs"></param>
        /// <param name="stats"></param>
        protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats)
        {
            VectorBase P = Device.CreateVector(x.Part);

            VectorBase.CommVector commP = P.CreateCommVector(m_Matrix);

            VectorBase R = rhs; // rhs is only needed once, so we can use it to store residuals
            VectorBase V = Device.CreateVector(x.Part);
            VectorBase Z = Device.CreateVector(x.Part);

            // lock objects
            // ============
            x.Lock();
            P.Lock();
            R.Lock();
            V.Lock();
            Z.Lock();

            m_Matrix.Lock();


            // configure Precond
            // =================

            if (m_NestedPrecond != null)
            {
                m_NestedPrecond.CreateTempObjects(Z, R, m_Matrix, this.Device);
            }


            // compute P0, R0
            // ==============
            P.Swap(x);
            m_Matrix.SpMV_Expert(-1.0, commP, 1.0, R);
            P.Swap(x);
            if (m_NestedPrecond != null)
            {
                m_NestedPrecond.DoPrecond();
                P.CopyFrom(Z);
            }
            else
            {
                P.CopyFrom(R);
            }

            double alpha   = R.InnerProd(P);
            double alpha_0 = alpha;
            double ResNorm;

            if (m_ConvergenceType == ConvergenceTypes.Absolute)
            {
                ResNorm = Math.Sqrt(alpha);
            }
            else if (m_ConvergenceType == ConvergenceTypes.Relative)
            {
                ResNorm = 1.0;
            }
            else
            {
                throw new NotImplementedException("unknown convergence type: " + m_ConvergenceType.ToString());
            }

            //long total = 0;
            //long gemv = 0;
            //long rest = 0;
            //long st, en;

            // iterate
            // =======
            stats.Converged      = false;
            stats.NoOfIterations = 1; // one iteration has allready been performed (P0, R0)
            for (int n = m_MaxIterations - 2; n >= 0; n--)
            {
                if (ResNorm <= m_Tolerance && stats.NoOfIterations >= base.m_MinIterations)
                {
                    stats.Converged = true;
                    break;
                }

                if (Math.Abs(alpha) <= double.Epsilon)
                {
                    // numerical breakdown
                    break;
                }

                m_Matrix.SpMV_Expert(1.0, commP, 0, V);
                double lambda = alpha / V.InnerProd(P);

                x.Acc(lambda, P);

                R.Acc(-lambda, V);

                if (m_IterationCallback != null)
                {
                    // pass approx. sol and residual to callback function

                    x.Unlock();
                    R.Unlock();

                    double[] x_approx = new double[x.Part.LocalLength];
                    x.CopyTo(x_approx, 0);

                    double[] R_curr = new double[R.Part.LocalLength];
                    R.CopyTo(R_curr, 0);

                    m_IterationCallback(stats.NoOfIterations, x_approx, R_curr);


                    x.Lock();
                    R.Lock();
                }

                if (m_NestedPrecond != null)
                {
                    Z.Clear();
                    m_NestedPrecond.DoPrecond();
                }
                else
                {
                    Z.CopyFrom(R);
                }

                double alpha_neu = R.InnerProd(Z);

                // compute residual norm
                if (m_ConvergenceType == ConvergenceTypes.Absolute)
                {
                    ResNorm = Math.Sqrt(alpha);
                }
                else
                {
                    ResNorm = Math.Sqrt(alpha / alpha_0);
                }
                ResNorm = Math.Sqrt(R.TwoNormSquare());

                P.Scale(alpha_neu / alpha);
                P.Acc(1.0, Z);

                alpha = alpha_neu;
                stats.NoOfIterations++;
            }

            // unlock objects
            // ==============

            if (m_NestedPrecond != null)
            {
                m_NestedPrecond.ReleaseTempObjects();
            }

            x.Unlock();
            P.Unlock();
            R.Unlock();
            V.Unlock();

            m_Matrix.Unlock();

            commP.Dispose();
            P.Dispose();
        }