Exemplo n.º 1
0
        /// <summary>
        /// Solves a symmetric, definite system using the conjugate gradient algorithm.
        /// </summary>
        /// <param name="Matrix">the matrix of the linear problem.</param>
        /// <param name="X">Output, (hopefully) the solution.</param>
        /// <param name="B">Input, the right-hand-side.</param>
        /// <param name="MaxIterations"></param>
        /// <param name="Tolerance"></param>
        /// <returns>Actual number of iterations.</returns>
        static public int Solve_CG <V, W>(this IMutableMatrixEx Matrix, V X, W B, int MaxIterations = 100000, double Tolerance = 1.0e-10)
            where V : IList <double>
            where W : IList <double> //
        {
            using (var slv = new ilPSP.LinSolvers.monkey.CG()) {
                slv.MaxIterations = MaxIterations;
                slv.Tolerance     = Tolerance;
                slv.DevType       = monkey.DeviceType.CPU;

                slv.DefineMatrix(Matrix);

                var SolRes = slv.Solve(X, B.ToArray());
                return(SolRes.NoOfIterations);
            }
        }
Exemplo n.º 2
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            using (new FuncTrace()) {
                base.NoOfTimesteps  = -1;
                base.TerminationKey = true;
                int D = this.GridData.SpatialDimension;

                this.Err.Clear();
                this.Err.Acc(-1.0, this.U);

                // compare linear vs. nonlinear evaluation
                // =======================================

                LinearNonlinComparisonTest();

                // call solver
                // ===========
                if (this.mode == TestMode.Solve)
                {
                    var solver = new ilPSP.LinSolvers.monkey.CG();
                    solver.MaxIterations = 20000;
                    solver.Tolerance     = 1.0e-12;
                    solver.DevType       = ilPSP.LinSolvers.monkey.DeviceType.CPU;

                    solver.DefineMatrix(this.OperatorMtx);

                    double[] _rhs = this.RHS.CoordinateVector.ToArray();
                    _rhs.AccV(-1.0, this.bnd.CoordinateVector);

                    var solRes = solver.Solve(this.U.CoordinateVector, _rhs);

                    Console.WriteLine("sparse solver result: " + solRes.ToString());
                    Assert.IsTrue(solRes.Converged);
                }
                else if (this.mode == TestMode.CheckResidual)
                {
                    // residual computation is done anyway...
                }
                else
                {
                    throw new NotImplementedException();
                }

                // Residual computation
                // ====================
                {
                    this.Residual.Clear();
                    this.Residual.Acc(1.0, this.bnd);
                    this.OperatorMtx.SpMVpara(1.0, this.U.CoordinateVector, 1.0, this.Residual.CoordinateVector);

                    this.Residual.Acc(-1.0, this.RHS);

                    L2ResidualNorm = D.ForLoop(delegate(int i) {
                        var f         = this.Residual[i];
                        double L2Norm = f.L2Norm();
                        Console.WriteLine("L2 " + f.Identification + ": " + L2Norm);
                        return(L2Norm);
                    });
                }

                // Error computation
                // =================
                {
                    this.Err.Acc(1.0, this.U);

                    L2ErrorNorm = D.ForLoop(delegate(int i) {
                        var f         = this.Err[i];
                        double L2Norm = f.L2Norm();
                        Console.WriteLine("L2 " + f.Identification + ": " + L2Norm);
                        return(L2Norm);
                    });
                }

                return(0.0);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// projects some DG field onto this
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="_cm">optional restriction to computational domain</param>
        /// <remarks>
        /// This method computes an exact
        /// L2-projection of the DG-field onto the SpecFEM-space, so a global linear system, which contains all
        /// DOF's, has to be solved.
        /// In contrast, <see cref="ProjectDGFieldCheaply"/> performs an approximate projection which only involves
        /// local operations for each cell.
        /// </remarks>
        public void ProjectDGField(double alpha, ConventionalDGField DGField, CellMask _cm = null)
        {
            using (var trx = new Transceiver(this.Basis)) {
                CellMask cm = _cm;
                if (cm == null)
                {
                    cm = CellMask.GetFullMask(this.Basis.GridDat);
                }


                int J        = m_Basis.GridDat.Cells.NoOfLocalUpdatedCells;
                var Trafo    = m_Basis.GridDat.ChefBasis.Scaling;
                var C2N      = m_Basis.CellNode_To_Node;
                var MtxM2N   = m_Basis.m_Modal2Nodal;
                var CellData = this.Basis.GridDat.Cells;

                // compute RHS
                // ===========

                var b = MultidimensionalArray.Create(this.m_Basis.NoOfLocalNodes);
                {
                    int[]      _K = m_Basis.NodesPerCell;
                    int        L  = m_Basis.ContainingDGBasis.Length;
                    double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray(); // temporary storage for nodal coordinates per cell
                                                                                            // 1st idx: ref. elm., 2nd idx: node index
                    double[] ModalCoordinates = new double[L];

                    foreach (Chunk cnk in cm)
                    {
                        int j0 = cnk.i0;
                        int jE = cnk.JE;
                        for (int j = j0; j < jE; j++)   // loop over cells...
                        {
                            int      iKref            = CellData.GetRefElementIndex(j);
                            double[] NodalCoordinates = _NodalCoordinates[iKref];
                            int      K = _K[iKref];

                            if (!CellData.IsCellAffineLinear(j))
                            {
                                throw new NotSupportedException();
                            }

                            // Get DG coordinates
                            Array.Clear(ModalCoordinates, 0, L);
                            int Lmin = Math.Min(L, DGField.Basis.GetLength(j));
                            for (int l = 0; l < Lmin; l++)
                            {
                                ModalCoordinates[l] = DGField.Coordinates[j, l];
                            }

                            var tr = 1.0 / Trafo[j];

                            // transform
                            //DGField.Coordinates.GetRow(j, ModalCoordinates);
                            ModalCoordinates.ClearEntries();
                            for (int l = 0; l < Lmin; l++)
                            {
                                ModalCoordinates[l] = DGField.Coordinates[j, l];
                            }
                            MtxM2N[iKref].GEMV(tr, ModalCoordinates, 0.0, NodalCoordinates, transpose: true);

                            // collect coordinates for cell 'j':
                            for (int k = 0; k < K; k++)
                            {
                                int _c2n = C2N[j, k];
                                b[_c2n] += NodalCoordinates[k];
                            }
                        }
                    }
                }

                trx.AccumulateGather(b);

                /*
                 *
                 * var bcheck = new double[b.Length];
                 * {
                 *  var polys = this.Basis.NodalBasis;
                 *
                 *
                 *  CellQuadrature.GetQuadrature(new int[] { K },
                 *      this.Basis.GridDat.Context,
                 *      (new CellQuadratureScheme()).Compile(this.Basis.GridDat, this.Basis.ContainingDGBasis.Degree*2),
                 *      delegate(MultidimensionalArray NodesUntransformed) { // Del_CreateNodeSetFamily
                 *          var NSC = this.Basis.GridDat.Context.NSC;
                 *          return new NodeSetController.NodeSetContainer[] { NSC.CreateContainer(NodesUntransformed) };
                 *      },
                 *      delegate(int i0, int Length, int _NoOfNodes, MultidimensionalArray EvalResult) {
                 *          var PolyAtNode = MultidimensionalArray.Create(K, _NoOfNodes);
                 *          for (int k = 0; k < K; k++) {
                 *              polys[k].Evaluate(PolyAtNode.ExtractSubArrayShallow(k, -1), this.Basis.GridDat.Context.NSC.Current_NodeSetFamily[0].NodeSet);
                 *          }
                 *
                 *          var DGFatNodes = MultidimensionalArray.Create(Length, _NoOfNodes);
                 *          DGField.Evaluate(i0, Length, 0, DGFatNodes);
                 *
                 *          //for(int i = 0; i < Length; i++) {
                 *          //    for (int n = 0; n < _NoOfNodes; n++) {
                 *          //        for (int k = 0; k < K; k++) {
                 *          //            for (int l = 0; l < K; l++) {
                 *          //                EvalResult[i, n, k, l] = PolyAtNode[k, n]*PolyAtNode[l, n];
                 *          //            }
                 *          //        }
                 *          //    }
                 *          //}
                 *
                 *          EvalResult.Multiply(1.0, PolyAtNode, DGFatNodes, 0.0, "jnk", "kn", "jn");
                 *
                 *          //double errSum = 0;
                 *          //for (int i = 0; i < Length; i++) {
                 *          //    for (int n = 0; n < _NoOfNodes; n++) {
                 *          //        for (int k = 0; k < K; k++) {
                 *          //            for (int l = 0; l < K; l++) {
                 *          //                double soll = PolyAtNode[k, n]*PolyAtNode[l, n];
                 *          //                errSum += Math.Abs(soll - EvalResult[i, n, k, l]);
                 *          //            }
                 *          //        }
                 *          //    }
                 *          //}
                 *          //Console.WriteLine("errsum = " + errSum);
                 *      },
                 *      delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                 *          for (int i = 0; i < Length; i++) {
                 *              int jCell = i + i0;
                 *
                 *              for (int k = 0; k < K; k++) {
                 *                  bcheck[C2N[jCell, k]] += ResultsOfIntegration[i, k];
                 *              }
                 *
                 *              //CellMass[jCell] = new FullMatrix(K, K);
                 *              //CellMass[jCell].Initialize(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
                 *          }
                 *      }).Execute();
                 *
                 *
                 *  double f**k = GenericBlas.L2Dist(b, bcheck);
                 *  Console.WriteLine("Distance error = " + f**k);
                 *
                 * }
                 *
                 *
                 */

                if (_cm == null)
                {
                    // full domain projection branch
                    // +++++++++++++++++++++++++++++


                    var x       = new double[this.Basis.NoOfLocalOwnedNodes];
                    var solStat = m_Basis.MassSolver.Solve(x, b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray());

                    {
                        if (solStat.Converged == false)
                        {
                            throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge.");
                        }


                        double[] chk = b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray();
                        this.Basis.MassMatrix.SpMVpara(-1.0, x, 1.0, chk);
                        double chk_nomr = chk.L2Norm();

                        if (chk_nomr >= 1.0e-8)
                        {
                            throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot()));
                        }
                    }

                    //m_Basis.MassMatrix.SpMV(1.0, b, 0.0, x);
                    m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x);
                    //m_Coordinates.AccV(alpha, b);
                }
                else
                {
                    // restricted domain projection branch
                    // +++++++++++++++++++++++++++++++++++

                    List <int> OccupiedRows_Global = new List <int>();
                    //List<int> OccupiedRows_Local = new List<int>();

                    var MM = Basis.ComputeMassMatrix(cm);
                    int i0 = MM.RowPartitioning.i0, iE = MM.RowPartitioning.iE;
                    for (int i = i0; i < iE; i++)
                    {
                        if (MM.GetNoOfNonZerosPerRow(i) > 0)
                        {
                            OccupiedRows_Global.Add(i);
                            //OccupiedRows_Local.Add(i - i0);
                        }
                    }

                    var CompressedPart = new Partitioning(OccupiedRows_Global.Count);
                    var CompressedMM   = new MsrMatrix(CompressedPart);

                    MM.WriteSubMatrixTo(CompressedMM, OccupiedRows_Global, default(int[]), OccupiedRows_Global, default(int[]));

                    var b_sub = new double[OccupiedRows_Global.Count];
                    //try {
                    b_sub.AccV(1.0, b.To1DArray(), default(int[]), OccupiedRows_Global, b_index_shift: -i0);
                    //} catch(Exception e) {
                    //    Debugger.Launch();
                    //}
                    //csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);

                    var x_sub = new double[b_sub.Length];

                    var solver = new ilPSP.LinSolvers.monkey.CG();
                    solver.MatrixType      = ilPSP.LinSolvers.monkey.MatrixType.CCBCSR;
                    solver.DevType         = ilPSP.LinSolvers.monkey.DeviceType.CPU;
                    solver.ConvergenceType = ConvergenceTypes.Absolute;
                    solver.Tolerance       = 1.0e-12;
                    solver.DefineMatrix(CompressedMM);

                    var solStat = solver.Solve(x_sub, b_sub.CloneAs());
                    {
                        if (solStat.Converged == false)
                        {
                            throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge.");
                        }

                        var chk = b_sub;
                        CompressedMM.SpMVpara(-1.0, x_sub, 1.0, chk);
                        double chk_nomr = chk.L2Norm();

                        if (chk_nomr >= 1.0e-8)
                        {
                            throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot()));
                        }
                    }

                    double[] x = new double[this.Basis.NoOfLocalOwnedNodes];
                    x.AccV(1.0, x_sub, OccupiedRows_Global, default(int[]), acc_index_shift: -i0);
                    m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x);
                }

                trx.Scatter(this.m_Coordinates);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Solution of the system
        /// <see cref="LaplaceMtx"/>*<see cref="T"/> + <see cref="LaplaceAffine"/> = <see cref="RHS"/>
        /// using a black-box solver
        /// </summary>
        private void ClassicSolve(out double mintime, out double maxtime, out bool Converged, out int NoOfIter)
        {
            mintime   = double.MaxValue;
            maxtime   = double.MinValue;
            Converged = false;
            NoOfIter  = int.MaxValue;

            for (int i = 0; i < base.Control.NoOfSolverRuns; i++)
            {
                // create sparse solver
                // --------------------
                ISparseSolver    ipSolver;
                LinearSolverCode solvercodes = LinearSolverCode.classic_pardiso;

                switch (solvercodes)
                {
                case LinearSolverCode.classic_pardiso:
                    ipSolver = new ilPSP.LinSolvers.PARDISO.PARDISOSolver()
                    {
                        CacheFactorization = true,
                        UseDoublePrecision = true
                    };
                    break;

                case LinearSolverCode.classic_mumps:
                    ipSolver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver();
                    break;

                case LinearSolverCode.classic_cg:
                    ipSolver = new ilPSP.LinSolvers.monkey.CG()
                    {
                        MaxIterations = 1000000,
                        Tolerance     = 1.0e-10,
                        DevType       = ilPSP.LinSolvers.monkey.DeviceType.Cuda
                    };
                    break;

                default:
                    throw new ArgumentException();
                }
                ipSolver.DefineMatrix(LaplaceMtx);

                // call solver
                // -----------
                T.Clear();

                Console.WriteLine("RUN " + i + ": solving system...");

                var RHSvec = RHS.CoordinateVector.ToArray();
                BLAS.daxpy(RHSvec.Length, -1.0, this.LaplaceAffine, 1, RHSvec, 1);

                T.Clear();
                SolverResult solRes = ipSolver.Solve(T.CoordinateVector, RHSvec);
                mintime = Math.Min(solRes.RunTime.TotalSeconds, mintime);
                maxtime = Math.Max(solRes.RunTime.TotalSeconds, maxtime);

                Converged = solRes.Converged;
                NoOfIter  = solRes.NoOfIterations;

                Console.WriteLine("Pardiso phase 11: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_11.Elapsed.TotalSeconds);
                Console.WriteLine("Pardiso phase 22: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_22.Elapsed.TotalSeconds);
                Console.WriteLine("Pardiso phase 33: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_33.Elapsed.TotalSeconds);

                ipSolver.Dispose();
            }
        }