Exemple #1
0
        public GMRESResult solve(Vector b, Vector x0 = null)
        {
            GMRESResult result = solveImpl(b, x0);

            Utils.QL_REQUIRE(result.Errors.Last() < relTol_, () => "could not converge");

            return(result);
        }
Exemple #2
0
        public GMRESResult solveWithRestart(int restart, Vector b, Vector x0 = null)
        {
            GMRESResult result = solveImpl(b, x0);

            List <double> errors = result.Errors;

            for (int i = 0; i < restart - 1 && result.Errors.Last() >= relTol_; ++i)
            {
                result = solveImpl(b, result.X);
                errors.AddRange(result.Errors);
            }

            Utils.QL_REQUIRE(errors.Last() < relTol_, () => "could not converge");

            result.Errors = errors;
            return(result);
        }
Exemple #3
0
        protected GMRESResult solveImpl(Vector b, Vector x0)
        {
            double      bn = Vector.Norm2(b);
            GMRESResult result;

            if (bn.IsEqual(0.0))
            {
                result = new GMRESResult(new InitializedList <double>(1, 0.0), b);
                return(result);
            }

            Vector x = !x0.empty() ? x0 : new Vector(b.size(), 0.0);
            Vector r = b - A_(x);

            double g = Vector.Norm2(r);

            if (g / bn < relTol_)
            {
                result = new GMRESResult(new InitializedList <double>(1, g / bn), x);
                return(result);
            }

            List <Vector> v = new InitializedList <Vector>(1, r / g);
            List <Vector> h = new InitializedList <Vector>(1, new Vector(maxIter_, 0.0));
            List <double> c = new List <double>(maxIter_ + 1),
                          s = new List <double>(maxIter_ + 1),
                          z = new List <double>(maxIter_ + 1);

            z[0] = g;

            List <double> errors = new InitializedList <double>(1, g / bn);

            for (int j = 0; j < maxIter_ && errors.Last() >= relTol_; ++j)
            {
                h.Add(new Vector(maxIter_, 0.0));
                Vector w = A_((M_ != null) ? M_(v[j]) : v[j]);

                for (int i = 0; i <= j; ++i)
                {
                    h[i][j] = Vector.DotProduct(w, v[i]);
                    w      -= h[i][j] * v[i];
                }

                h[j + 1][j] = Vector.Norm2(w);

                if (h[j + 1][j] < Const.QL_EPSILON * Const.QL_EPSILON)
                {
                    break;
                }

                v.Add(w / h[j + 1][j]);

                for (int i = 0; i < j; ++i)
                {
                    double h0 = c[i] * h[i][j] + s[i] * h[i + 1][j];
                    double h1 = -s[i] * h[i][j] + c[i] * h[i + 1][j];

                    h[i][j]     = h0;
                    h[i + 1][j] = h1;
                }

                double nu = Math.Sqrt((h[j][j]) * (h[j][j])
                                      + (h[j + 1][j]) * (h[j + 1][j]));

                c[j] = h[j][j] / nu;
                s[j] = h[j + 1][j] / nu;

                h[j][j]     = nu;
                h[j + 1][j] = 0.0;

                z[j + 1] = -s[j] * z[j];
                z[j]     = c[j] * z[j];

                errors.Add(Math.Abs(z[j + 1] / bn));
            }

            int k = v.Count - 1;

            Vector y = new Vector(k, 0.0);

            y[k - 1] = z[k - 1] / h[k - 1][k - 1];

            for (int i = k - 2; i >= 0; --i)
            {
                y[i] = (z[i] - h[i].inner_product(
                            i + 1, k, i + 1, y, 0.0)) / h[i][i];
            }

            Vector xm = new Vector(x.Count, 0.0);

            for (int i = 0; i < x.Count; i++)
            {
                xm[i] = v[i].inner_product(0, k, 0, y, 0.0);
            }

            xm = x + ((M_ != null) ? M_(xm) : xm);

            result = new GMRESResult(errors, xm);
            return(result);
        }