示例#1
0
        /// <summary>
        /// Solves the linear system A * x = b by solving the preconditioned system inv(P) * A * inv(P)^T * y = inv(P) * b,
        /// where A = <paramref name="matrix"/>, b = <paramref name="rhsVector"/>, x is the solution, y = P^T * x,
        /// P*P^T = <paramref name="preconditioner"/>.
        /// Initially x = <paramref name="initialGuess"/> and then it converges to the solution.
        /// </summary>
        /// <param name="matrix">
        /// Represents the matrix A of the linear system A * x = b, which must be symmetric positive definite.
        /// </param>
        /// <param name="rhs">
        /// The right hand side vector b of the linear system A * x = b. Constraints:
        /// <paramref name="rhs"/>.<see cref="IIndexable1D.Length"/>
        /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumRows"/>.
        /// </param>
        /// <param name="preconditioner">
        /// A preconditioner matrix that is also symmetric positive definite and has the same dimensions as A.
        /// </param>
        /// <param name="solution">
        /// The vector from which to start refining the solution vector x. Constraints:
        /// <paramref name="solution"/>.<see cref="IIndexable1D.Length"/>
        /// == <paramref name="matrix"/>.<see cref="IIndexable2D.NumColumns"/>.
        /// </param>
        /// <param name="initialGuessIsZero">
        /// If <paramref name="solution"/> is 0, then set <paramref name="initialGuessIsZero"/> to true to avoid performing the
        /// operation b-A*0 before starting.
        /// </param>
        /// <exception cref="NonMatchingDimensionsException">
        /// Thrown if <paramref name="rhs"/> or <paramref name="solution"/> violate the described constraints.
        /// </exception>
        public IterativeStatistics Solve(ILinearTransformation matrix, IPreconditioner preconditioner, IVectorView rhs,
                                         IVector solution, bool initialGuessIsZero, Func <IVector> zeroVectorInitializer)
        {
            //TODO: find a better way to handle optimizations for the case x0=0, than using an initialGuessIsZero flag

            Preconditions.CheckMultiplicationDimensions(matrix.NumColumns, solution.Length);
            Preconditions.CheckSystemSolutionDimensions(matrix.NumRows, rhs.Length);

            this.Matrix         = matrix;
            this.Preconditioner = preconditioner;
            this.Rhs            = rhs;
            this.solution       = solution;

            // r = b - A * x
            if (initialGuessIsZero)
            {
                residual = rhs.Copy();
            }
            else
            {
                residual = ExactResidual.Calculate(matrix, rhs, solution);
            }
            return(SolveInternal(maxIterationsProvider.GetMaxIterations(matrix.NumColumns), zeroVectorInitializer));
        }
示例#2
0
        internal IterativeStatistics Solve(IInterfaceFlexibilityMatrix matrix, IFetiPreconditioner preconditioner,
                                           IInterfaceProjection projector, Vector rhs, Vector lagrangeMultipliers)
        {
            int n             = matrix.Order;
            int maxIterations = maxIterationsProvider.GetMaxIterations(matrix.Order);

            // r0 = d - F * λ0
            var residual = matrix.Multiply(lagrangeMultipliers);

            residual.LinearCombinationIntoThis(-1.0, rhs, 1.0);

            // Other allocations
            var    w                          = Vector.CreateZero(n);
            var    y                          = Vector.CreateZero(n);
            var    z                          = Vector.CreateZero(n);
            var    direction                  = Vector.CreateZero(n);
            var    matrixTimesDirection       = Vector.CreateZero(n);
            double residualDotProductPrevious = double.NaN;
            double residualNormRatio          = double.NaN;
            double beta                       = double.NaN;

            for (int iter = 1; iter <= maxIterations; ++iter)
            {
                // w(m-1) = P * r(m-1)
                projector.ProjectVector(residual, w, false);

                // z(m-1) = preconditioner * w(m-1)
                preconditioner.SolveLinearSystem(w, z);

                // Check convergence: usually if ||z|| / ||f|| < tolerance
                residualNormRatio = convergence.EstimateResidualNormRatio(lagrangeMultipliers, z);
                if (residualNormRatio <= residualTolerance)
                {
                    //TODO: is it correct to check for convergence here? How many iterations should I return?
                    return(new IterativeStatistics
                    {
                        AlgorithmName = name,
                        HasConverged = true,
                        NumIterationsRequired = iter - 1, //TODO: not sure about this.
                        ResidualNormRatioEstimation = residualNormRatio
                    });
                }

                // y(m-1) = P * z(m-1)
                projector.ProjectVector(z, y, false);

                double residualDotProductCurrent = y.DotProduct(w);

                if (iter == 1)
                {
                    // β(1) = 0
                    beta = 0;

                    // p(1) = y0
                    direction.CopyFrom(y);
                }
                else
                {
                    // β(m) = (y(m-1) * w(m-1)) / (y(m-2) * w(m-2))
                    beta = residualDotProductCurrent / residualDotProductPrevious;

                    // p(m) = y(m-1) + β(m) * p(m-1), if m > 1
                    direction.LinearCombinationIntoThis(beta, y, 1.0);
                }
                residualDotProductPrevious = residualDotProductCurrent;

                // γ(m) = (y(m-1) * w(m-1)) / (p(m) * F * p(m))
                matrix.Multiply(direction, matrixTimesDirection);
                double stepSize = (y * w) / (direction * matrixTimesDirection);

                // λ(m) = λ(m-1) + γ(m) * p(m)
                lagrangeMultipliers.AxpyIntoThis(direction, stepSize);

                // r(m) = r(m-1) -γ(m) * F * p(m)
                residual.AxpyIntoThis(matrixTimesDirection, -stepSize);
            }

            return(new IterativeStatistics
            {
                AlgorithmName = name,
                HasConverged = false,
                NumIterationsRequired = maxIterations,
                ResidualNormRatioEstimation = residualNormRatio
            });
        }