示例#1
0
        public Vector Multiply(Vector vector)
        {
            var result = Vector.CreateZero(vector.Length);

            preconditioner.SolveLinearSystem(vector, result);
            return(result);
        }
            public void SolveLinearSystem(IVectorView rhsVector, IVector lhsVector)
            {
                //TODO: remove casts. I think PCG, LinearTransformation and preconditioners should be generic, bounded by
                //      IVectorView and IVector
                var lhs = (Vector)lhsVector;
                var rhs = (Vector)rhsVector;

                fetiPreconditioner.SolveLinearSystem(rhs, lhs);
            }
示例#3
0
 private PcgPreconditioner DefinePcgPreconditioner(IFetiPreconditioner preconditioner, Feti1Projection projection)
 {
     if (projectionSidePreconditioner == ProjectionSide.None)
     {
         // x = prec(A) * y => x = prec(F) * y
         return(new PcgPreconditioner((x, y) => preconditioner.SolveLinearSystem(y, x)));
     }
     else if (projectionSidePreconditioner == ProjectionSide.Left)
     {
         // x = prec(A) * y => x = (P * prec(F)) * y => x = P * (prec(F) * y)
         return(new PcgPreconditioner((y, x) =>
         {
             int order = y.Length;
             var temp = Vector.CreateZero(order);
             preconditioner.SolveLinearSystem(y, temp);
             projection.ProjectVector(temp, x, false);
         }));
     }
     else if (projectionSidePreconditioner == ProjectionSide.Both)
     {
         // x = prec(A) * y => x = (P * prec(F) * P^T) * y => x = P * (prec(F) * (P^T * y))
         return(new PcgPreconditioner((y, x) =>
         {
             int order = y.Length;
             var temp1 = Vector.CreateZero(order);
             projection.ProjectVector(y, temp1, true);
             var temp2 = Vector.CreateZero(order);
             preconditioner.SolveLinearSystem(temp1, temp2);
             projection.ProjectVector(temp2, x, false);
         }));
     }
     else
     {
         throw new ArgumentException(
                   "The FETI-1 preconditioner can be multiplied from the left side, both sides or not at all.");
     }
 }
示例#4
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
            });
        }