Пример #1
0
        public static bool ComplexSolvePreconditionedBiCGSTAB(
            out System.Numerics.Complex[] X,
            ComplexSparseMatrix A, System.Numerics.Complex[] B, ComplexSparseMatrix LU,
            double convRatioTolerance)
        {
            System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength);
            int n = A.RowLength;

            System.Diagnostics.Debug.Assert(B.Length == n);
            double    convRatio = convRatioTolerance;
            double    tolerance = convRatio;
            const int maxIter   = IvyFEM.Linear.Constants.MaxIter;

            System.Numerics.Complex[] r  = new System.Numerics.Complex[n];
            System.Numerics.Complex[] r0 = new System.Numerics.Complex[n];
            System.Numerics.Complex[] x  = new System.Numerics.Complex[n];
            System.Numerics.Complex[] p  = new System.Numerics.Complex[n];
            System.Numerics.Complex[] s  = new System.Numerics.Complex[n];
            System.Numerics.Complex[] Mp = new System.Numerics.Complex[n];
            System.Numerics.Complex[] Ms = new System.Numerics.Complex[n];
            int iter = 0;

            B.CopyTo(r, 0);
            double sqInvNorm0;

            {
                double sqNorm0 = IvyFEM.Lapack.Functions.zdotc(r, r).Real;
                if (sqNorm0 < IvyFEM.Constants.PrecisionLowerLimit)
                {
                    convRatio = 0;
                    X         = x;
                    System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio);
                    return(true);
                }
                sqInvNorm0 = 1.0 / sqNorm0;
            }

            r.CopyTo(r0, 0);
            r.CopyTo(p, 0);

            for (iter = 0; iter < maxIter; iter++)
            {
                ComplexSolveLU(out Mp, LU, p);
                System.Numerics.Complex r0r = IvyFEM.Lapack.Functions.zdotc(r0, r);

                System.Numerics.Complex[] AMp = A * Mp;
                System.Numerics.Complex   alpha;
                {
                    System.Numerics.Complex denominator = IvyFEM.Lapack.Functions.zdotc(r0, AMp);
                    alpha = r0r / denominator;
                }
                s = IvyFEM.Lapack.Functions.zaxpy(-alpha, AMp, r);

                ComplexSolveLU(out Ms, LU, s);

                System.Numerics.Complex[] AMs = A * Ms;
                System.Numerics.Complex   omega;
                {
                    System.Numerics.Complex denominator = IvyFEM.Lapack.Functions.zdotc(AMs, AMs);
                    System.Numerics.Complex numerator   = IvyFEM.Lapack.Functions.zdotc(s, AMs);
                    omega = numerator / denominator;
                }

                x = IvyFEM.Lapack.Functions.zaxpy(alpha, Mp, x);
                x = IvyFEM.Lapack.Functions.zaxpy(omega, Ms, x);
                r = IvyFEM.Lapack.Functions.zaxpy(-omega, AMs, s);

                {
                    double sqNorm = IvyFEM.Lapack.Functions.zdotc(r, r).Real;
                    if (sqNorm * sqInvNorm0 < tolerance * tolerance)
                    {
                        convRatio = Math.Sqrt(sqNorm * sqInvNorm0);
                        X         = x;
                        System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio);
                        return(true);
                    }
                }

                System.Numerics.Complex beta;
                {
                    System.Numerics.Complex r0rPrev = r0r;
                    r0r  = IvyFEM.Lapack.Functions.zdotc(r0, r);
                    beta = (r0r * alpha) / (r0rPrev * omega);
                }
                p = IvyFEM.Lapack.Functions.zaxpy(beta, p, r);
                p = IvyFEM.Lapack.Functions.zaxpy(-beta * omega, AMp, p);
            }

            {
                double sqNormRes = IvyFEM.Lapack.Functions.zdotc(r, r).Real;
                convRatio = Math.Sqrt(sqNormRes * sqInvNorm0);
                System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio);
                X = x;
            }
            System.Diagnostics.Debug.WriteLine("Not converged");
            return(false);
        }
        public static bool ComplexSolveNoPreconCOCG(
            out System.Numerics.Complex[] X,
            ComplexSparseMatrix A, System.Numerics.Complex[] B,
            double convRatioTolerance)
        {
            System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength);
            int n = A.RowLength;

            System.Diagnostics.Debug.Assert(B.Length == n);
            double    convRatio    = convRatioTolerance;
            double    convRatioTol = convRatio;
            const int maxIter      = IvyFEM.Linear.Constants.MaxIter;

            System.Numerics.Complex[] r = new System.Numerics.Complex[n];
            System.Numerics.Complex[] x = new System.Numerics.Complex[n];
            System.Numerics.Complex[] p = new System.Numerics.Complex[n];
            int iter = 0;

            B.CopyTo(r, 0);
            double sqInvNorm0;

            {
                double sqNorm0 = IvyFEM.Lapack.Functions.zdotc(r, r).Real;
                if (sqNorm0 < IvyFEM.Constants.PrecisionLowerLimit)
                {
                    convRatio = 0;
                    X         = x;
                    System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio);
                    return(true);
                }
                sqInvNorm0 = 1.0 / sqNorm0;
            }

            r.CopyTo(p, 0);
            System.Numerics.Complex rr = IvyFEM.Lapack.Functions.zdotu(r, r);

            for (iter = 0; iter < maxIter; iter++)
            {
                System.Numerics.Complex[] Ap = A * p;
                System.Numerics.Complex   alpha;
                {
                    System.Numerics.Complex pAp = IvyFEM.Lapack.Functions.zdotu(p, Ap);
                    alpha = rr / pAp;
                }
                r = IvyFEM.Lapack.Functions.zaxpy(-alpha, Ap, r);
                x = IvyFEM.Lapack.Functions.zaxpy(alpha, p, x);

                {
                    double sqNorm = IvyFEM.Lapack.Functions.zdotc(r, r).Real;
                    if (sqNorm * sqInvNorm0 < convRatioTol * convRatioTol)
                    {
                        convRatio = Math.Sqrt(sqNorm * sqInvNorm0);
                        X         = x;
                        System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio);
                        return(true);
                    }
                }

                System.Numerics.Complex rrPrev = rr;
                rr = IvyFEM.Lapack.Functions.zdotu(r, r);
                System.Numerics.Complex beta = rr / rrPrev;

                p = IvyFEM.Lapack.Functions.zaxpy(beta, p, r);
            }

            {
                double sqNormRes = IvyFEM.Lapack.Functions.zdotc(r, r).Real;
                convRatio = Math.Sqrt(sqNormRes * sqInvNorm0);
                System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio);
                X = x;
            }
            System.Diagnostics.Debug.WriteLine("Not converged");
            return(false);
        }