예제 #1
0
        protected GmresSolver(ILogger logger, INativeMemoryProvider memoryProvider, GmresParams parameters)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (memoryProvider == null)
            {
                throw new ArgumentNullException(nameof(memoryProvider));
            }

            Logger     = logger;
            Parameters = parameters;
            _nloc      = Parameters.LocalDimensionSize;
            _m         = Parameters.BufferSize;

            _dotProducts = Parameters.GramSchmidtType == GramSchmidtType.IterativeClassical ?
                           new NativeVector(memoryProvider, _m) :
                           new NativeVector(memoryProvider, 1);

            var krylovSize = Parameters.ResidualAtRestart == ResidualAtRestart.ComputeTheTrue ? _m : _m + 1;

            _krylovBasis = new FortranMatrix(memoryProvider, _nloc, krylovSize);
            _hessenberg  = new FortranMatrix(memoryProvider, _m + 1, _m + 1);

            _w        = new NativeVector(memoryProvider, _nloc);
            _r0       = new NativeVector(memoryProvider, _nloc);
            _xCurrent = new NativeVector(memoryProvider, _nloc);
            _yCurrent = new NativeVector(memoryProvider, _m);

            _givensRotSin = new Complex[_m];
            _givensRotCos = new double[_m];
        }
예제 #2
0
        protected override void ApplyPreconditionerRight(NativeVector src, NativeVector dst, int jH)
        {
            var col = _precondKrylovBasis.GetColumnVector(jH);

            OnRightPreconditionerRequest(new RightPreconditionerRequestEventArgs(src, col));
            UnsafeNativeMethods.Zcopy(Parameters.LocalDimensionSize, col.Ptr, dst.Ptr);
        }
예제 #3
0
 public static void Sub(NativeVector v1, NativeVector v2, NativeVector result)
 {
     for (int i = 0; i < result.Length; i++)
     {
         result[i] = v1[i] - v2[i];
     }
 }
예제 #4
0
        private double PrepareRestart(NativeVector rhs, NativeVector x, int jH)
        {
            ConstructCurrentSolution(jH, x);

            double beta;

            if (Parameters.ResidualAtRestart == ResidualAtRestart.ComputeTheTrue)
            {
                UnsafeNativeMethods.Zcopy(_nloc, x.Ptr, _w.Ptr);
                CalculateMatrixVectorMult(_w, _r0);
                NativeVector.Sub(rhs, _r0, _r0);

                if (Parameters.Preconditioning != Preconditioning.None)
                {
                    throw new NotImplementedException();
                }


                UnsafeNativeMethods.Zcopy(_nloc, _r0.Ptr, _w.Ptr);
                beta = CalculateVectorNorm(_w);
            }
            else
            {
                beta = _hessenberg[_m, _m].Magnitude;
                for (int j = _m - 1; j >= 0; j--)
                {
                    _hessenberg[j, _m] = Zero;
                    Zrot(_hessenberg.GetPointer(j, _m), _hessenberg.GetPointer(j + 1, _m), _givensRotCos[j], -_givensRotSin[j]);
                    UnsafeNativeMethods.ZgemvNotTrans(_nloc, _m + 1, One, _krylovBasis.Ptr, _hessenberg.GetColumn(_m), Zero, _w.Ptr);
                }
            }

            return(beta);
        }
예제 #5
0
        private double CalculateVectorNorm(NativeVector vector)
        {
            CalculateDotProduct(vector.Ptr, vector.Ptr);

            var vectorNorm = Sqrt(_dotProducts[0].Real);

            return(vectorNorm);
        }
예제 #6
0
 public static void Mult(double alpha, NativeVector v, NativeVector result)
 {
     for (int i = 0; i < result.Length; i++)
     {
         result[i] = alpha * v[i];
     }
     ;
 }
예제 #7
0
        private void ApplyPreconditionerLeft(NativeVector x, NativeVector result)
        {
            if (Parameters.Preconditioning != Preconditioning.None)
            {
                throw new NotImplementedException();
            }

            UnsafeNativeMethods.Zcopy(_nloc, x.Ptr, result.Ptr);
        }
예제 #8
0
        protected override void ApplyPreconditionerRight(NativeVector src, NativeVector dst, int jH)
        {
            if (Parameters.Preconditioning != Preconditioning.None)
            {
                throw new NotImplementedException();
            }

            UnsafeNativeMethods.Zcopy(Parameters.LocalDimensionSize, src.Ptr, dst.Ptr);
        }
예제 #9
0
        private void ConstructCurrentSolution(int jH, NativeVector result)
        {
            UnsafeNativeMethods.Zcopy(jH, _hessenberg.GetColumn(_m), _yCurrent.Ptr);
            UnsafeNativeMethods.SimplifiedZtrsv(jH, _hessenberg.Ptr, _m + 1, _yCurrent.Ptr);

            CalculateSolutionProjectionToKrylovSubspace(jH);

            NativeVector.Add(result, _r0, _xCurrent);
            UnsafeNativeMethods.Zcopy(_nloc, _xCurrent.Ptr, result.Ptr);
        }
예제 #10
0
        private double FinalActions(int jH, double sPb, NativeVector rhs, NativeVector result)
        {
            ConstructCurrentSolution(jH, result);

            if (Parameters.BackwardErrorChecking != BackwardErrorChecking.CheckArnoldiOnly)
            {
                return(CheckBackwardError(sPb, rhs));
            }

            return(-1);
        }
예제 #11
0
        private double CheckBackwardError(double sPb, NativeVector rhs)
        {
            UnsafeNativeMethods.Zcopy(_nloc, _xCurrent.Ptr, _r0.Ptr);

            CalculateMatrixVectorMult(_r0, _w);

            for (int i = 0; i < _w.Length; i++)
            {
                _w[i] = rhs[i] - _w[i];
            }

            var trueNormRes = CalculateVectorNorm(_w);

            if (Parameters.Preconditioning != Preconditioning.None)
            {
                throw new NotImplementedException();
            }

            var dnormres = trueNormRes;

            var be = dnormres / sPb;

            if (be >= Parameters.Tolerance)
            {
                var messageString = $"be = {be}, tolerance = {Parameters.Tolerance}";

                if (Parameters.BackwardErrorChecking == BackwardErrorChecking.CheckWithException)
                {
                    throw new BackwardErrorException(messageString);
                }

                if (Parameters.BackwardErrorChecking == BackwardErrorChecking.CheckWithWarning)
                {
                    Logger.WriteWarning(messageString);
                }
            }

            return(be);
        }
예제 #12
0
        private void CalculateMatrixVectorMult(NativeVector x, NativeVector result)
        {
            var args = new MatrixVectorMultRequestEventArgs(x, result);

            OnMatrixVectorMultRequest(args);
        }
예제 #13
0
 public MatrixVectorMultRequestEventArgs(NativeVector x, NativeVector result)
 {
     X      = x;
     Result = result;
 }
 public RightPreconditionerRequestEventArgs(NativeVector src, NativeVector dst)
 {
     Src = src;
     Dst = dst;
 }
예제 #15
0
 protected abstract void ApplyPreconditionerRight(NativeVector src, NativeVector dst, int jH);
예제 #16
0
 public ResultInfo Solve(NativeVector rightHandSide, NativeVector initialGuess, NativeVector result)
 {
     return(_flexibleGmres.Solve(rightHandSide, initialGuess, result));
 }
예제 #17
0
        public ResultInfo Solve(NativeVector rightHandSide, NativeVector initialGuess, NativeVector result)
        {
            _iterationCounter = 0;
            var bn = CalculateVectorNorm(rightHandSide);

            if (CheckRightHandSideForZero(bn))
            {
                return(ResultInfo.Converged(0, 0, 0));
            }

            var sb  = CalculateScaleFactorsForBackwardErrorUnprecond(bn);
            var sPb = CalculateScaleFactorsForBackwardErrorPrecond(bn);

            if (Parameters.InitialGuess == InitialGuess.EqualsZero)
            {
                initialGuess.SetAllValuesToZero();
                for (int i = 0; i < _r0.Length; i++)
                {
                    _r0[i] = rightHandSide[i];
                }
            }
            else
            {
                CalculateMatrixVectorMult(initialGuess, _r0);
                for (int i = 0; i < _r0.Length; i++)
                {
                    _r0[i] = rightHandSide[i] - _r0[i];
                }
            }


            ApplyPreconditionerLeft(_r0, _w);
            var beta = CalculateVectorNorm(_w);

            if (CheckForExactSolution(beta))
            {
                UnsafeNativeMethods.Zcopy(_nloc, initialGuess.Ptr, result.Ptr);
                return(ResultInfo.Converged(0, 0, 1));
            }

            double bea  = -1;
            double be   = -1;
            int    iter = 0;

            UnsafeNativeMethods.Zcopy(initialGuess.Length, initialGuess.Ptr, result.Ptr);

            while (true)
            {
                NativeVector.Mult(1 / beta, _w, _krylovBasis.GetColumnVector(0));

                _hessenberg[0, _m] = beta;
                for (int i = 1; i <= _m; i++)
                {
                    _hessenberg[i, _m] = Zero;
                }

                int jH = 0;
                bea = KrylovSubspaceConstruction(bn, ref jH);

                if (bea < Parameters.Tolerance)
                {
                    be = FinalActions(jH, sPb, rightHandSide, result);
                    return(ResultInfo.Converged(bea, be, _iterationCounter));
                }

                iter++;


                if (iter >= Parameters.MaxRepeatNumber)
                {
                    break;
                }

                beta = PrepareRestart(rightHandSide, result, jH);
            }

            be = FinalActions(_m, sPb, rightHandSide, result);//ConstructCurrentSolution(_m, result);
            return(ResultInfo.NonConverged(bea, be, _iterationCounter));
        }