예제 #1
0
        public void Init(MultigridOperator op)
        {
            var M     = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_mgop = op;

            if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            Mtx = M;
            int L = M.RowPartitioning.LocalLength;

            diag = new double[L];
            int i0 = Mtx.RowPartitioning.i0;

            for (int i = 0; i < L; i++)
            {
                diag[i] = Mtx[i0 + i, i0 + i];
            }
        }
예제 #2
0
        /// <summary>
        /// defines the problem matrix
        /// </summary>
        public void Init(MultigridOperator op)
        {
            // init & check
            // ============

            this.m_MgOperator = op;
            //OpMatrix = op.OperatorMatrix;
            OpMatrix = new ilPSP.LinSolvers.monkey.CPU.RefMatrix(op.OperatorMatrix.ToMsrMatrix());
            var MgMap = op.Mapping;

            if (!OpMatrix.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!OpMatrix.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            // init solver chain
            // =================
            if (SolverChain == null || SolverChain.Length <= 0)
            {
                throw new NotSupportedException("Illegal configuration.");
            }
            for (int i = 0; i < SolverChain.Length; i++)
            {
                SolverChain[i].Init(op);
            }
        }
예제 #3
0
        /// <summary>
        /// Updating the <see cref="CurrentLin"/> -- operator;
        /// </summary>
        /// <param name="CurrentState">linearization point</param>
        protected void Update(IEnumerable <DGField> CurrentState)
        {
            if (!(this.ProblemMapping.BasisS.Count == CurrentState.Count()))
            {
                throw new ArgumentException("missmatch in number of fields.");
            }

            BlockMsrMatrix OpMtxRaw, MassMtxRaw;

            double[] OpAffineRaw;
            this.m_AssembleMatrix(out OpMtxRaw, out OpAffineRaw, out MassMtxRaw, CurrentState.ToArray());

            CurrentLin = new MultigridOperator(this.m_AggBasisSeq, this.ProblemMapping,
                                               OpMtxRaw.CloneAs(), MassMtxRaw,
                                               this.m_MultigridOperatorConfig);

            OpAffineRaw = OpAffineRaw.CloneAs();

            if (this.RHSRaw != null)
            {
                OpAffineRaw.AccV(-1.0, this.RHSRaw);
            }
            if (LinearizationRHS == null || LinearizationRHS.Length != this.CurrentLin.Mapping.LocalLength)
            {
                LinearizationRHS = new double[this.CurrentLin.Mapping.LocalLength];
            }
            else
            {
                LinearizationRHS.ClearEntries();
            }
            CurrentLin.TransformRhsInto(OpAffineRaw, this.LinearizationRHS);
            this.LinearizationRHS.ScaleV(-1.0);
        }
예제 #4
0
        ilPSP.LinSolvers.monkey.CPU.RefMatrix m_Matrix; // im Moment schneller, ca 5X
        //BlockMsrMatrix m_Matrix;


        public void Init(MultigridOperator op)
        {
            using (new FuncTrace()) {
                var M     = op.OperatorMatrix;
                var MgMap = op.Mapping;
                this.m_MgOp = op;

                if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
                {
                    throw new ArgumentException("Row partitioning mismatch.");
                }
                if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
                {
                    throw new ArgumentException("Column partitioning mismatch.");
                }

                //this.m_Matrix = M;
                this.m_Matrix = new ilPSP.LinSolvers.monkey.CPU.RefMatrix(M.ToMsrMatrix());

                /*
                 * int n = m_Matrix.RowPartitioning.LocalLength;
                 * if(n > 50000) {
                 *  var _Matrix = new ilPSP.LinSolvers.monkey.CPU.RefMatrix(M.ToMsrMatrix());
                 *
                 *  double[] xTest = new double[n];
                 *  double[] bTest = new double[n];
                 *  Random r = new Random(123);
                 *  for(int i = 0; i < n; i++) {
                 *      xTest[i] = r.NextDouble();
                 *      bTest[i] = r.NextDouble();
                 *  }
                 *
                 *
                 *  double[] b1 = bTest.CloneAs();
                 *  double[] x1 = bTest.CloneAs();
                 *  Stopwatch monkey = new Stopwatch();
                 *  monkey.Start();
                 *  for (int i = 0; i < 100; i++)
                 *      _Matrix.SpMV(1.0, x1, -0.1, b1);
                 *  monkey.Stop();
                 *
                 *  double[] b2 = bTest.CloneAs();
                 *  double[] x2 = bTest.CloneAs();
                 *  Stopwatch block = new Stopwatch();
                 *  block.Start();
                 *  for (int i = 0; i < 100; i++)
                 *      m_Matrix.SpMV(1.0, x1, -0.1, b1);
                 *  block.Stop();
                 *
                 *  Console.WriteLine("SPMV monkey:    " + monkey.Elapsed.TotalSeconds);
                 *  Console.WriteLine("SPMV block MSR: " + block.Elapsed.TotalSeconds);
                 * }
                 */
                if (Precond != null)
                {
                    Precond.Init(op);
                }
            }
        }
예제 #5
0
        public void Init(MultigridOperator op)
        {
            int D = op.GridData.SpatialDimension;

            CodName = new string[] { "momX", "momY", "div", "constitutiveXX", "constitutiveXY", "constitutiveYY" };
            Params  = new string[] { "VelocityX_GradientX", "VelocityX_GradientY", "VelocityY_GradientX", "VelocityY_GradientY" };
            DomName = new string[] { "VelocityX", "VelocityY", "Pressure", "StressXX", "StressXY", "StressYY" };

            LocalOp = new SpatialOperator(DomName, Params, CodName, (A, B, C) => 4);

            LocalOp.EquationComponents["constitutiveXX"].Add(new LocalJacobiFlux()
            {
                m_component = 0, We = m_We
            });
            LocalOp.EquationComponents["constitutiveXY"].Add(new LocalJacobiFlux()
            {
                m_component = 1, We = m_We
            });
            LocalOp.EquationComponents["constitutiveYY"].Add(new LocalJacobiFlux()
            {
                m_component = 2, We = m_We
            });

            LocalOp.Commit();

            var   U0      = ((BoSSS.Foundation.CoordinateMapping)op.Mapping.ProblemMapping).Fields.GetSubVector(0, 2);
            Basis U0Basis = new Basis(op.Mapping.GridData, 0);

            VectorField <SinglePhaseField> VelocityXGradient = new VectorField <SinglePhaseField>(D, U0Basis, "VelocityX_Gradient", SinglePhaseField.Factory);
            VectorField <SinglePhaseField> VelocityYGradient = new VectorField <SinglePhaseField>(D, U0Basis, "VelocityY_Gradient", SinglePhaseField.Factory);

            VelocityXGradient.Clear();
            VelocityXGradient.GradientByFlux(1.0, U0[0]);
            VelocityYGradient.Clear();
            VelocityYGradient.GradientByFlux(1.0, U0[1]);

            var Parameters = ArrayTools.Cat <DGField>(VelocityXGradient, VelocityYGradient);

            LocalMatrix = LocalOp.ComputeMatrix(op.BaseGridProblemMapping, Parameters, op.BaseGridProblemMapping);

            ConstEqIdx = op.Mapping.ProblemMapping.GetSubvectorIndices(true, 3, 4, 5);

            P = (BlockMsrMatrix)op.MassMatrix.Clone();

            for (int i = ConstEqIdx[0]; i <= ConstEqIdx.Length; i++)
            {
                for (int j = ConstEqIdx[0]; j <= ConstEqIdx.Length; j++)
                {
                    if (LocalMatrix[i, j] != 0)
                    {
                        P[i, j] = LocalMatrix[i, j];
                    }
                }
            }

            LocalMatrix.SaveToTextFileSparse("LocalMatrix");
            op.MassMatrix.SaveToTextFileSparse("MassMatrix");
            P.SaveToTextFileSparse("PrecondMatrix");
        }
예제 #6
0
        public IList <double[]> OrthonormalMultigridDecomposition(double[] Vec, bool decompose = true)
        {
            // vector length on level 0
            int L0 = DecompositionOperator.Mapping.LocalLength;

            if (Vec.Length != L0)
            {
                throw new ArgumentException("Mismatch in vector length.", "Vec");
            }


            List <double[]> OrthoVecs = new List <double[]>();

            OrthoVecs.Add(Vec.CloneAs());

            double l2pow2_Vec = OrthoVecs[0].L2NormPow2().MPISum();

            MultigridOperator coarsest = null;

            for (var mgop = this.DecompositionOperator.CoarserLevel; mgop != null; mgop = mgop.CoarserLevel)
            {
                int L      = mgop.Mapping.LocalLength;
                int iLevel = mgop.LevelIndex;
                OrthoVecs.Add(new double[L]);

                mgop.Restrict(OrthoVecs[iLevel - 1], OrthoVecs[iLevel]);

                coarsest = mgop;
            }

            double Check_l2pow2_OrthoVecsTotal = 0.0;

            for (var mgop = this.DecompositionOperator.CoarserLevel; mgop != null; mgop = mgop.CoarserLevel)
            {
                int iLevel = mgop.LevelIndex;


                if (decompose)
                {
                    mgop.Prolongate(-1.0, OrthoVecs[iLevel - 1], 1.0, OrthoVecs[iLevel]);
                }


                coarsest = mgop;
            }
            foreach (double[] OrthoVec in OrthoVecs)
            {
                Check_l2pow2_OrthoVecsTotal += OrthoVec.L2NormPow2().MPISum();
            }

            // if the vectors are really orthonormal, their squared L2-norms must be additive!
            if (decompose && this.DecompositionOperator_IsOrthonormal)
            {
                Debug.Assert((Math.Abs(Check_l2pow2_OrthoVecsTotal - l2pow2_Vec) / l2pow2_Vec < 1.0e-8), "something wrong with orthonormal decomposition");
            }

            return(OrthoVecs);
        }
예제 #7
0
            /// <summary>
            /// Returns the multigrid blocking.
            /// </summary>
            internal override IEnumerable <List <int> > GetBlocking(MultigridOperator op)
            {
                AggregationGrid thisLevel = op.Mapping.AggGrid;

                List <AggregationGrid> blockLevelS = new List <AggregationGrid>();

                blockLevelS.Add(thisLevel);
                MultigridOperator blokOp = op;

                for (int i = 0; i < this.Depth; i++)
                {
                    if (blokOp.CoarserLevel == null)
                    {
                        throw new NotSupportedException("Not enough multigrid levels set to support a depth of " + m_Depht + ".");
                    }
                    blokOp = blokOp.CoarserLevel;
                    blockLevelS.Add(blokOp.Mapping.AggGrid);
                }
                AggregationGrid blckLevel = blockLevelS.Last();                            // the cells of this level form the additive-Schwarz blocks
                int             NoBlocks  = blckLevel.iLogicalCells.NoOfLocalUpdatedCells; // each cell of 'blckLevel' forms a block

                List <int>[] Blocks = NoBlocks.ForLoop(l => new List <int>());

#if DEBUG
                bool[] checkOnce = new bool[thisLevel.iLogicalCells.NoOfLocalUpdatedCells];
#endif
                for (int iBlk = 0; iBlk < NoBlocks; iBlk++)
                {
                    if (blockLevelS.Count == 0)
                    {
                        Blocks[iBlk].Add(iBlk); // the cell itself is the multigrid block (either Depth is 0, or no more MG level available).
                    }
                    else
                    {
                        int[] CoarseCell = blckLevel.jCellCoarse2jCellFine[iBlk];
                        CollectBlock(Blocks[iBlk], blockLevelS, 0, CoarseCell);
                    }
#if DEBUG
                    foreach (int j in Blocks[iBlk])
                    {
                        Debug.Assert(j >= 0);
                        Debug.Assert(j < checkOnce.Length);
                        Debug.Assert(checkOnce[j] == false);
                        checkOnce[j] = true;
                    }
#endif
                }

#if DEBUG
                for (int j = 0; j < checkOnce.Length; j++)
                {
                    Debug.Assert(checkOnce[j] == true);
                }
#endif

                return(Blocks);
            }
예제 #8
0
        public ConvergenceObserver(MultigridOperator muop, BlockMsrMatrix MassMatrix, double[] __ExactSolution)
        {
            if (__ExactSolution != null)
            {
                if (__ExactSolution.Length != muop.BaseGridProblemMapping.LocalLength)
                {
                    throw new ArgumentException();
                }
            }
            this.SolverOperator = muop;

            List <AggregationGridBasis[]> aggBasisSeq = new List <AggregationGridBasis[]>();

            for (var mo = muop; mo != null; mo = mo.CoarserLevel)
            {
                aggBasisSeq.Add(mo.Mapping.AggBasis);
            }

            this.ExactSolution = __ExactSolution;
            int[] Degrees = muop.BaseGridProblemMapping.BasisS.Select(b => b.Degree).ToArray();

            BlockMsrMatrix DummyOpMatrix = new BlockMsrMatrix(muop.BaseGridProblemMapping, muop.BaseGridProblemMapping);

            DummyOpMatrix.AccEyeSp(123);


            MultigridOperator.ChangeOfBasisConfig[][] config = new MultigridOperator.ChangeOfBasisConfig[1][];
            config[0] = new MultigridOperator.ChangeOfBasisConfig[muop.BaseGridProblemMapping.BasisS.Count];
            for (int iVar = 0; iVar < config[0].Length; iVar++)
            {
                config[0][iVar] = new MultigridOperator.ChangeOfBasisConfig()
                {
                    Degree   = Degrees[iVar],
                    mode     = MultigridOperator.Mode.IdMass_DropIndefinite,
                    VarIndex = new int[] { iVar }
                };
            }

            //this.DecompositionOperator = muop; this.DecompositionOperator_IsOrthonormal = false;
            this.DecompositionOperator = new MultigridOperator(aggBasisSeq, muop.BaseGridProblemMapping, DummyOpMatrix, MassMatrix, config); this.DecompositionOperator_IsOrthonormal = true;

            ResNormTrend = new Dictionary <Tuple <int, int, int>, List <double> >();
            ErrNormTrend = new Dictionary <Tuple <int, int, int>, List <double> >();
            for (var mgop = this.DecompositionOperator; mgop != null; mgop = mgop.CoarserLevel)
            {
                int[] _Degrees = mgop.Mapping.DgDegree;
                for (int iVar = 0; iVar < _Degrees.Length; iVar++)
                {
                    for (int p = 0; p <= _Degrees[iVar]; p++)
                    {
                        ResNormTrend.Add(new Tuple <int, int, int>(mgop.LevelIndex, iVar, p), new List <double>());
                        ErrNormTrend.Add(new Tuple <int, int, int>(mgop.LevelIndex, iVar, p), new List <double>());
                    }
                }
            }
        }
예제 #9
0
        public void Init(MultigridOperator op)
        {
            this.m_OpThisLevel = op;

            if (op.CoarserLevel == null)
            {
                throw new NotSupportedException("Multigrid algorithm cannot be used as a solver on the finest level.");
            }

            this.CoarserLevelSolver.Init(op.CoarserLevel);
        }
예제 #10
0
파일: DirectSolver.cs 프로젝트: xyuan/BoSSS
        public void Init(MultigridOperator op)
        {
            var Mtx   = op.OperatorMatrix;
            var MgMap = op.Mapping;

            m_MultigridOp = op;

            if (!Mtx.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!Mtx.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            m_Mtx = Mtx;
        }
예제 #11
0
        public void Init(MultigridOperator op)
        {
            BlockMsrMatrix M     = op.OperatorMatrix;
            var            MgMap = op.Mapping;

            this.m_MultigridOp = op;


            if (!M.RowPartitioning.Equals(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.Equals(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            Mtx = M;
            int L = M.RowPartitioning.LocalLength;

            /*
             * diag = new double[L];
             * int i0 = Mtx.RowPartitioning.i0;
             *
             * for(int i = 0; i < L; i++) {
             *  diag[i] = Mtx[i0 + i, i0 + i];
             * }
             */

            if (op.Mapping.MaximalLength != op.Mapping.MinimalLength)
            {
                // 'BlockDiagonalMatrix' should be completely replaced by 'BlockMsrMatrix'
                throw new NotImplementedException("todo - Block Jacobi for variable block Sizes");
            }


            int Nblk = op.Mapping.MaximalLength;

            Diag    = new BlockDiagonalMatrix(M.ToMsrMatrix(), Nblk, Nblk);
            invDiag = Diag.Invert();
            invDiag.CheckForNanOrInfM();
        }
예제 #12
0
 static public ISolverSmootherTemplate InitMultigridChain(MultigridOperator MgOp,
                                                          Func <int, ISolverSmootherTemplate> PreSmootherFactory,
                                                          Func <int, ISolverSmootherTemplate> PostSmootherFactory,
                                                          Action <int, ClassicMultigrid> ParamsSeter,
                                                          Func <ISolverSmootherTemplate> CoarsestSolverFactory) //
 {
     if (MgOp.CoarserLevel == null)
     {
         return(CoarsestSolverFactory());
     }
     else
     {
         var MgTop = new ClassicMultigrid();
         ParamsSeter(MgOp.LevelIndex, MgTop);
         MgTop.PreSmoother        = PreSmootherFactory(MgOp.LevelIndex);
         MgTop.PostSmoother       = PostSmootherFactory(MgOp.LevelIndex);
         MgTop.CoarserLevelSolver = InitMultigridChain(MgOp.CoarserLevel, PreSmootherFactory, PostSmootherFactory, ParamsSeter, CoarsestSolverFactory);
         return(MgTop);
     }
 }
예제 #13
0
        static public ISolverSmootherTemplate InitMultigridChain(MultigridOperator MgOp,
                                                                 Action <int, SoftPCG> ParamsSeter,
                                                                 Func <ISolverSmootherTemplate> CoarsestSolverFactory)
        {
            //
            if (MgOp.CoarserLevel == null)
            {
                return(CoarsestSolverFactory());
            }
            else
            {
                var MgTop = new SoftPCG();
                ParamsSeter(MgOp.LevelIndex, MgTop);

                var R = new GenericRestriction();
                MgTop.Precond        = R;
                R.CoarserLevelSolver = InitMultigridChain(MgOp.CoarserLevel, ParamsSeter, CoarsestSolverFactory);

                return(MgTop);
            }
        }
예제 #14
0
파일: SoftGMRES.cs 프로젝트: octwanna/BoSSS
        public void Init(MultigridOperator op)
        {
            var Mtx   = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_mgop = op;

            if (!Mtx.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!Mtx.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }
            this.Matrix = Mtx;
            if (Precond != null)
            {
                Precond.Init(op);
            }
        }
예제 #15
0
        public void Init(MultigridOperator op)
        {
            var M     = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_mgop = op;

            if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            foreach (var pc in PrecondS)
            {
                pc.Init(m_mgop);
            }
        }
예제 #16
0
        public void Init(MultigridOperator op)
        {
            var M     = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_MgOp = op;

            if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }
            this.m_Matrix = M;
            m_OptMatrix   = new ilPSP.LinSolvers.monkey.CPU.RefMatrix(M.ToMsrMatrix());
            if (Precond != null)
            {
                Precond.Init(op);
            }
        }
예제 #17
0
        /// <summary>
        /// Decomposition of some solution vector <paramref name="vec"/> into the different multigrid levels.
        /// </summary>
        public void PlotDecomposition <V>(V vec, string plotName)
            where V : IList <double> //
        {
            int L0 = this.DecompositionOperator.Mapping.LocalLength;

            double[] Vec0 = new double[L0];
            this.DecompositionOperator.TransformSolInto(vec, Vec0);

            var Decomp = this.OrthonormalMultigridDecomposition(Vec0, false);

            List <DGField> DecompFields = new List <DGField>();

            MultigridOperator op = this.DecompositionOperator;

            for (int iLevel = 0; iLevel < Decomp.Count; iLevel++)
            {
                double[] vec_i     = Decomp[iLevel];
                var      DecompVec = this.InitProblemDGFields("Level" + iLevel);

                MultigridOperator opi = op;
                for (int k = iLevel; k > 0; k--)
                {
                    int      Lk1    = Decomp[k - 1].Length;
                    double[] vec_i1 = new double[Lk1];
                    opi.Prolongate(1.0, vec_i1, 0.0, vec_i);
                    vec_i = vec_i1;
                    opi   = opi.FinerLevel;
                }

                this.DecompositionOperator.TransformSolFrom(DecompVec, vec_i);

                DecompFields.AddRange(DecompVec.Mapping.Fields);

                op = op.CoarserLevel;
            }


            Tecplot.Tecplot.PlotFields(DecompFields, plotName, 0.0, 3);
        }
예제 #18
0
        private MultigridOperator(MultigridOperator __FinerLevel, IEnumerable <AggregationGridBasis[]> basisES, UnsetteledCoordinateMapping _pm, IEnumerable <ChangeOfBasisConfig[]> cobc)
        {
            if (basisES.Count() <= 0)
            {
                throw new ArgumentException("At least one multigrid level is required.");
            }

            this.BaseGridProblemMapping = _pm;
            if (cobc.Count() < 1)
            {
                throw new ArgumentException();
            }
            this.m_Config   = cobc.First();
            this.FinerLevel = __FinerLevel;
            this.Mapping    = new MultigridMapping(_pm, basisES.First(), this.Degrees);

            if (this.Mapping.LocalLength > this.BaseGridProblemMapping.LocalLength)
            {
                throw new ApplicationException("Something wrong.");
            }


            if (basisES.Count() > 1)
            {
                this.CoarserLevel = new MultigridOperator(this, basisES.Skip(1), _pm, cobc.Count() > 1 ? cobc.Skip(1) : cobc);
            }

            if (this.LevelIndex == 0 && this.Mapping.AggBasis.Any(agb => agb.ReqModeIndexTrafo))
            {
                int J = this.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                Debug.Assert(J == this.BaseGridProblemMapping.GridDat.iLogicalCells.NoOfLocalUpdatedCells);
                IndexIntoProblemMapping_Local = new int[this.Mapping.LocalLength];
#if DEBUG
                IndexIntoProblemMapping_Local.SetAll(-23456);
#endif

                AggregationGridBasis[] AgBss = this.Mapping.AggBasis;
                int[] Degrees = this.Mapping.DgDegree;
                int   NoFlds  = Degrees.Length;

                for (int j = 0; j < J; j++)   // loop over cells

                {
                    for (int iFld = 0; iFld < NoFlds; iFld++)
                    {
                        int N = AgBss[iFld].GetLength(j, Degrees[iFld]); // By using the length of the aggregate grid mapping,
                        //                                            we exclude XDG agglomerated cells.

                        if (N > 0)
                        {
                            int k0 = this.Mapping.ProblemMapping.LocalUniqueCoordinateIndex(iFld, j, 0);
                            int i0 = this.Mapping.LocalUniqueIndex(iFld, j, 0);
                            for (int n = 0; n < N; n++)
                            {
                                //X[i0 + n] = INOUT_X[k0 + n];
                                //B[i0 + n] = IN_RHS[k0 + n];

                                int n_trf = AgBss[iFld].N_Murks(j, n, N);
                                Debug.Assert(n_trf >= 0);
#if DEBUG
                                Debug.Assert(IndexIntoProblemMapping_Local[i0 + n] < 0);
#endif
                                IndexIntoProblemMapping_Local[i0 + n] = k0 + n_trf;
                                //Debug.Assert(i0 + n == 0 || IndexIntoProblemMapping_Local[i0 + n] > IndexIntoProblemMapping_Local[i0 + n - 1]);
                                Debug.Assert(IndexIntoProblemMapping_Local[i0 + n] >= 0);
                                Debug.Assert(IndexIntoProblemMapping_Local[i0 + n] < this.Mapping.ProblemMapping.LocalLength);
                            }
                        }
                        else
                        {
                            // should be a cell without any species.

                            Debug.Assert(this.Mapping.AggBasis.Where(b => !(b is XdgAggregationBasis)).Count() == 0, "all must be XDG");
                            Debug.Assert(this.Mapping.AggBasis.Where(b => ((XdgAggregationBasis)b).GetNoOfSpecies(j) != 0).Count() == 0, "no species in any cell allowed");

                            //Debug.Assert();
                        }
                    }
                }

#if DEBUG
                Debug.Assert(IndexIntoProblemMapping_Local.Any(i => i < 0) == false);
#endif

                if (this.Mapping.ProblemMapping.MpiSize == 1)
                {
                    this.IndexIntoProblemMapping_Global = this.IndexIntoProblemMapping_Local;
                }
                else
                {
                    this.IndexIntoProblemMapping_Global = this.IndexIntoProblemMapping_Local.CloneAs();
                    int i0Proc = this.Mapping.ProblemMapping.i0;
                    int L      = this.IndexIntoProblemMapping_Global.Length;
                    for (int i = 0; i < L; i++)
                    {
                        this.IndexIntoProblemMapping_Global[i] += i0Proc;
                    }
                }
            }
#if DEBUG
            if (IndexIntoProblemMapping_Local != null)
            {
                int i0 = this.Mapping.ProblemMapping.i0;
                int L  = this.Mapping.ProblemMapping.LocalLength;

                int[] UseCount = new int[L];
                foreach (int i in IndexIntoProblemMapping_Global)
                {
                    UseCount[i - i0]++;
                }

                for (int l = 0; l < L; l++)
                {
                    Debug.Assert(UseCount[l] <= 1);
                }
            }
#endif
        }
예제 #19
0
        /// <summary>
        /// defines the problem matrix
        /// </summary>
        public void Init(MultigridOperator op)
        {
            this.m_MgOperator = op;
            var Mtx   = op.OperatorMatrix;
            var MgMap = op.Mapping;

            if (!Mtx.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!Mtx.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }


            double Dim = MgMap.ProblemMapping.GridDat.SpatialDimension;

            // set operator
            // ============
            if (op.CoarserLevel == null)
            {
                throw new NotSupportedException("Multigrid algorithm cannot be used as a solver on the finest level.");
            }
            this.OpMatrix = Mtx;


            /*
             * // construct restriction and prolongation
             * // ======================================
             *
             * var thisLevel = MgMap.AggBasis;
             * var lowerLevel = MgMap.CoarserLevel.AggBasis;
             *
             * int[] this_p = MgMap.DgDegree;
             * int[] low_p = MgMap.CoarserLevel.DgDegree;
             *
             * var __PrlgOperator = thisLevel.FromOtherLevelMatrix(MgMap.ProblemMapping, this_p, lowerLevel, low_p);
             * Debug.Assert(__PrlgOperator.RowPartitioning.LocalLength == MgMap.LocalLength);
             * Debug.Assert(__PrlgOperator.ColPartition.LocalLength == MgMap.CoarserLevel.LocalLength);
             #if DEBUG
             * var __RestOperator = lowerLevel.FromOtherLevelMatrix(MgMap.ProblemMapping, low_p, thisLevel, this_p);
             * {
             *  var __RestOperator2 = __PrlgOperator.Transpose();
             *  __RestOperator2.Acc(-1.0, __RestOperator);
             *  double dingsNorm = __RestOperator2.InfNorm();
             *  Debug.Assert(dingsNorm <= 1.0e-10);
             * }
             #else
             * var __RestOperator = __PrlgOperator.Transpose();
             #endif
             * int iLevel = MgMap.LevelIndex;
             *
             * if(this.UseSmoothedInterpolation) {
             *  MsrMatrix DinvA;
             *  double specRadius = Utils.rhoDinvA(OpMatrix, out DinvA);
             *  Console.WriteLine("Level {0} spectral radius = {1}", iLevel, specRadius);
             *  double omega = ((Dim + 1) / Dim) * (1.0 / specRadius);
             *
             *  DinvA.Scale(-omega);
             *  //DinvA.Clear();
             *  DinvA.AccEyeSp(1.0);
             *
             *  PrologateOperator = MsrMatrix.Multiply(DinvA, __PrlgOperator);
             *  RestrictionOperator = this.PrologateOperator.Transpose();
             * } else {
             *  PrologateOperator = __PrlgOperator;
             *  RestrictionOperator = __RestOperator;
             *
             *  var RX = this.RestrictionOperator.CloneAs();
             *  RX.Acc(-1.0, m_MgOperator.RestrictionOperator);
             *  double tst = RX.InfNorm();
             *  Debug.Assert(tst <= 1.0e-10);
             *
             *  var PX = this.PrologateOperator.CloneAs();
             *  PX.Acc(-1.0, m_MgOperator.PrologateOperator);
             *  double tst2 = PX.InfNorm();
             *  Debug.Assert(tst2 <= 1.0e-10);
             * }
             * //*/

            // initiate coarser level
            // ======================
            //var M1 = MsrMatrix.Multiply(this.OpMatrix, this.PrologateOperator);
            //var CoarseMtx = MsrMatrix.Multiply(this.RestrictionOperator, M1);
            if (this.CoarserLevelSolver == null)
            {
                throw new NotSupportedException("Missing coarse level solver.");
            }
            this.CoarserLevelSolver.Init(op.CoarserLevel);


            // init pre&post smoother
            // ======================
            if (this.PreSmoother != null)
            {
                this.PreSmoother.Init(op);
            }
            if (this.PostSmoother != null)
            {
                this.PostSmoother.Init(op);
            }
        }
예제 #20
0
 /// <summary>
 /// Number of blocs returned by <see cref="GetBlocking(MultigridOperator)"/>
 /// </summary>
 internal abstract int GetNoOfBlocks(MultigridOperator op);
예제 #21
0
 /// <summary>
 /// Returns lists which form the blocks of the additive-Schwarz domain decomposition.
 /// </summary>
 /// <param name="op"></param>
 /// <returns>
 /// - outer enumeration: correcponts to domain-decomposition blocks
 /// - inner index: indices within the sub-blocks
 /// - content: local cell indices which form the respective additive-Schwarz block (<see cref="MultigridOperator."/>
 /// </returns>
 abstract internal IEnumerable <List <int> > GetBlocking(MultigridOperator op);
예제 #22
0
        public void Init(MultigridOperator op)
        {
            using (new FuncTrace()) {
                if (m_MgOp != null)
                {
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                    // someone is trying to re-use this solver: see if the settings permit that
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    if (op.LevelIndex != m_MgOp.LevelIndex)
                    {
                        throw new ArgumentException("Re-use on different level not possible.");
                    }
                    if (!this.MtxFull._RowPartitioning.EqualsPartition(op.OperatorMatrix._RowPartitioning))
                    {
                        throw new ArgumentException("Matrix has changed, unable to re-use");
                    }
                    if (!this.MtxFull._ColPartitioning.EqualsPartition(op.OperatorMatrix._ColPartitioning))
                    {
                        throw new ArgumentException("Matrix has changed, unable to re-use");
                    }
#if DEBUG
                    if (!object.ReferenceEquals(this.MtxFull, op.OperatorMatrix))
                    {
                        BlockMsrMatrix Check = this.MtxFull.CloneAs();
                        Check.Acc(-1.0, op.OperatorMatrix);
                        if (Check.InfNorm() != 0.0)
                        {
                            throw new ArgumentException("Matrix has changed, unable to re-use");
                        }
                    }
#endif
                    if (this.m_BlockingStrategy.GetNoOfBlocks(op) != this.blockSolvers.Count())
                    {
                        throw new ArgumentException("Blocking, unable to re-use");
                    }


                    return;
                }

                var Mop   = op.OperatorMatrix;
                var MgMap = op.Mapping;
                this.m_MgOp = op;
                int myMpiRank = MgMap.MpiRank;
                int myMpisize = MgMap.MpiSize;

                if (!Mop.RowPartitioning.EqualsPartition(MgMap.Partitioning))
                {
                    throw new ArgumentException("Row partitioning mismatch.");
                }
                if (!Mop.ColPartition.EqualsPartition(MgMap.Partitioning))
                {
                    throw new ArgumentException("Column partitioning mismatch.");
                }

                var ag = MgMap.AggGrid;

                int JComp  = ag.iLogicalCells.NoOfLocalUpdatedCells;
                int JGhost = ag.iLogicalCells.NoOfExternalCells;

#if DEBUG
                ilPSP.Connectors.Matlab.BatchmodeConnector matlab;
                if (m_MatlabParalellizationCheck)
                {
                    matlab = new ilPSP.Connectors.Matlab.BatchmodeConnector();
                }
                else
                {
                    matlab = null;
                }
#endif

                //Mop.Clear();
                //for(int i = Mop.RowPartitioning.i0; i < Mop.RowPartitioning.iE; i++) {
                //    Mop[i, i] = i + 1;
                //}


                // get cell blocks
                // ===============

                var _Blocks         = this.m_BlockingStrategy.GetBlocking(op);
                int NoOfSchwzBlocks = _Blocks.Count();

                // test cell blocks
                // ================
#if DEBUG
                {
                    // ensure that each cell is used exactly once, among all blocks
                    bool[] test = new bool[ag.iLogicalCells.NoOfLocalUpdatedCells];
                    foreach (var bi in _Blocks)
                    {
                        foreach (int j in bi)
                        {
                            Debug.Assert(test[j] == false);
                            test[j] = true;
                        }
                        ;
                    }
                    for (int i = 0; i < test.Length; i++)
                    {
                        Debug.Assert(test[i] == true);
                    }
                }
#endif

                // extend blocks according to desired overlap
                // ==========================================
                {
                    BitArray marker = new BitArray(JComp + JGhost);

                    if (Overlap < 0)
                    {
                        throw new ArgumentException();
                    }
                    if (Overlap > 0)
                    {
                        if (Overlap > 1 && Mop.RowPartitioning.MpiSize > 1)
                        {
                            throw new NotSupportedException("In MPI parallel runs, the maximum supported overlap for the Schwarz preconditioner is 1.");
                        }

                        foreach (List <int> bi in _Blocks) // loop over blocks...
                        {
                            marker.SetAll(false);          // marks all cells which are members of the block
                            foreach (int jcomp in bi)
                            {
                                marker[jcomp] = true;
                            }

                            // determine overlap regions
                            for (int k = 0; k < Overlap; k++)
                            {
                                int Jblock = bi.Count;
                                for (int j = 0; j < Jblock; j++)
                                {
                                    int   jCell  = bi[j];
                                    int[] Neighs = ag.iLogicalCells.CellNeighbours[jCell];
                                    foreach (int jNeigh in Neighs)
                                    {
                                        if (marker[jNeigh] == false)
                                        {
                                            // neighbor cell is not already a member of the block
                                            // => add it.
                                            bi.Add(jNeigh);
                                            marker[jNeigh] = true;
                                        }
                                    }
                                }
                            }

                            bi.Sort();
                        }
                    }

                    BlockCells = _Blocks.Select(list => list.ToArray()).ToArray();
                }


                // convert cell blocks to DOF blocks
                // =================================

                List <int>[] BlkIdx_gI_lR;                  //  for each Schwarz block, (global) indices in the local range
                List <int>[] BlkIdx_gI_eR;                  //  for each Schwarz block, (global) indices of external rows and columns
                List <int>[] TempRowIdx_gI;                 // for each Schwarz block, (global) indices into the temporary matrix
                List <int>[] BlkIdx_lI_eR;                  //  for each Schwarz block, (local)  indices of external rows and columns
                List <int>[] LocalBlocks_i0, LocalBlocks_N; // blocking of the Schwarz-Blocks.

                // for matrix 'ExternalRowsTemp': which rows of 'Mop' are required locally
                List <int> ExternalRowsIndices, ExternalRows_BlockI0, ExternalRows_BlockN;
                {
                    int Jup = MgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                    int Jgh = MgMap.AggGrid.iLogicalCells.NoOfExternalCells;

                    int LocalizedBlockCounter = 0;

                    BlkIdx_gI_lR   = NoOfSchwzBlocks.ForLoop(iPart => new List <int>(BlockCells[iPart].Length * MgMap.MaximalLength));
                    BlkIdx_gI_eR   = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());
                    LocalBlocks_i0 = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());
                    LocalBlocks_N  = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());

                    TempRowIdx_gI = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());
                    BlkIdx_lI_eR  = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());


                    ExternalRowsIndices  = new List <int>();
                    ExternalRows_BlockI0 = new List <int>();
                    ExternalRows_BlockN  = new List <int>();

                    for (int iPart = 0; iPart < NoOfSchwzBlocks; iPart++)   // loop over parts...
                    {
                        int[] bc    = BlockCells[iPart];
                        var   biI   = BlkIdx_gI_lR[iPart];
                        var   biE   = BlkIdx_gI_eR[iPart];
                        var   l1    = TempRowIdx_gI[iPart];
                        var   l2    = BlkIdx_lI_eR[iPart];
                        var   LBBi0 = LocalBlocks_i0[iPart];
                        var   LBBN  = LocalBlocks_N[iPart];


                        int Jblock         = bc.Length;
                        int anotherCounter = 0;

                        for (int jblk = 0; jblk < Jblock; jblk++)   // loop over cells in blocks...
                        {
                            int j = bc[jblk];
                            int N = MgMap.GetLength(j);

                            if (j < Jup)
                            {
                                // locally updated cell
                                int i0 = MgMap.GlobalUniqueIndex(0, j, 0);

                                for (int n = 0; n < N; n++)
                                {
                                    biI.Add(i0 + n);
                                }
                            }
                            else
                            {
                                // external cell
                                int i0E = MgMap.GlobalUniqueIndex(0, j, 0); //
                                int i0L = MgMap.LocalUniqueIndex(0, j, 0);  //
                                ExternalRows_BlockI0.Add(LocalizedBlockCounter);
                                ExternalRows_BlockN.Add(N);
                                //LEBi0.Add(LocalizedBlockCounter);
                                //LEBn.Add(N);
                                for (int n = 0; n < N; n++)
                                {
                                    biE.Add(i0E + n);
                                    ExternalRowsIndices.Add(i0E + n);
                                    l1.Add(LocalizedBlockCounter + n);
                                    l2.Add(i0L + n);
                                    Debug.Assert(Mop._RowPartitioning.FindProcess(i0E + n) != myMpiRank);
                                }

                                LocalizedBlockCounter += N;
                            }

                            LBBi0.Add(anotherCounter);
                            LBBN.Add(N);

                            anotherCounter += N;
                        }
                    }

                    //this.BlockIndices = _LocallyStoredBlockIndices.Select(bi => bi.ToArray()).ToArray();
                }


                // get rows for blocks that use external cells
                // ===========================================

#if DEBUG
                {
                    if (Overlap == 0)
                    {
                        Debug.Assert(ExternalRowsIndices.Count == 0);
                        Debug.Assert(ExternalRows_BlockI0.Count == 0);
                        Debug.Assert(ExternalRows_BlockN.Count == 0);
                    }

                    foreach (var bi in BlkIdx_gI_lR)
                    {
                        foreach (int idx in bi)
                        {
                            Debug.Assert(idx >= m_MgOp.Mapping.i0);
                            Debug.Assert(idx < m_MgOp.Mapping.iE);
                        }
                    }

                    foreach (var ei in BlkIdx_gI_eR)
                    {
                        foreach (int idx in ei)
                        {
                            Debug.Assert(idx < m_MgOp.Mapping.i0 || idx >= m_MgOp.Mapping.iE);
                        }
                    }


                    int LL   = m_MgOp.Mapping.LocalLength;
                    int jMax = m_MgOp.Mapping.AggGrid.iLogicalCells.NoOfCells - 1;
                    int LE   = m_MgOp.Mapping.LocalUniqueIndex(0, jMax, 0) + m_MgOp.Mapping.GetLength(jMax);


                    foreach (var ci in BlkIdx_lI_eR)
                    {
                        foreach (int idx in ci)
                        {
                            Debug.Assert(idx >= LL);
                            Debug.Assert(idx < LE);
                        }
                    }

                    if (m_MatlabParalellizationCheck)
                    {
                        int globalBlockCounter = 0;
                        for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                        {
                            int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                            if (rankCounter == myMpiRank)
                            {
                                Debug.Assert(rank_NoBlks == NoOfSchwzBlocks);
                            }

                            for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                            {
                                double[] vec;
                                if (rankCounter == myMpiRank)
                                {
                                    vec = ArrayTools.Cat(BlkIdx_gI_lR[iBlock], BlkIdx_gI_eR[iBlock]).Select(ii => ((double)(ii + 1))).ToArray();
                                }
                                else
                                {
                                    vec = new double[0];
                                }

                                matlab.PutVector(vec, string.Format("BlockIdx{0}", globalBlockCounter));

                                globalBlockCounter++;
                                csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);
                            }
                        }
                    }
                }
#endif


                BlockMsrMatrix ExternalRowsTemp;
                if (myMpisize > 1 && Overlap > 0)
                {
                    //int NoOfLocalRows = _ExternalBlockIndices.Sum(L => L.Count);

                    BlockPartitioning PermRow = new BlockPartitioning(ExternalRowsIndices.Count, ExternalRows_BlockI0, ExternalRows_BlockN, Mop.MPI_Comm, i0isLocal: true);

                    // Remark: we use a permutation matrix for MPI-exchange of rows

                    BlockMsrMatrix Perm = new BlockMsrMatrix(PermRow, Mop._RowPartitioning);
                    for (int iRow = 0; iRow < ExternalRowsIndices.Count; iRow++)
                    {
                        Debug.Assert(Mop._RowPartitioning.IsInLocalRange(ExternalRowsIndices[iRow]) == false);
                        Perm[iRow + PermRow.i0, ExternalRowsIndices[iRow]] = 1;
                    }

                    ExternalRowsTemp = BlockMsrMatrix.Multiply(Perm, Mop);

#if DEBUG
                    if (m_MatlabParalellizationCheck)
                    {
                        matlab.PutSparseMatrix(Perm, "Perm");
                        matlab.PutSparseMatrix(ExternalRowsTemp, "ExternalRowsTemp");
                    }
#endif
                }
                else
                {
                    ExternalRowsTemp = null;
                }

                ExternalRowsIndices  = null;
                ExternalRows_BlockI0 = null;
                ExternalRows_BlockN  = null;



                // create solvers
                // ==============


                {
                    blockSolvers = new ISparseSolver[NoOfSchwzBlocks];

#if DEBUG
                    List <BlockMsrMatrix> Blocks = new List <BlockMsrMatrix>();
#endif
                    for (int iPart = 0; iPart < NoOfSchwzBlocks; iPart++)
                    {
                        var bi = BlkIdx_gI_lR[iPart];

                        int Bsz;
                        if (MgMap.MinimalLength == MgMap.MaximalLength)
                        {
                            Bsz = MgMap.MaximalLength;
                        }
                        else
                        {
                            Bsz = 1;
                        }

                        var l1 = TempRowIdx_gI[iPart];

                        //if (M.RowPartitioning.MpiSize > 1) {
                        //    int i0Proc = M.RowPartitioning.i0;
                        //    bi = bi.CloneAs();
                        //    for (int i = 0; i < bi.Length; i++) {
                        //        bi[i] += i0Proc;
                        //    }
                        //}

                        BlockPartitioning localBlocking = new BlockPartitioning(bi.Count + l1.Count, LocalBlocks_i0[iPart], LocalBlocks_N[iPart], csMPI.Raw._COMM.SELF);

                        if (l1.Count > 0)
                        {
                            // convert the indices into 'ExternalRowsTemp' to global indices
                            int l1L    = l1.Count;
                            int offset = ExternalRowsTemp._RowPartitioning.i0;
                            for (int i = 0; i < l1L; i++)
                            {
                                l1[i] += offset;
                            }
                        }

                        BlockMsrMatrix Block = new BlockMsrMatrix(localBlocking, localBlocking);// bi.Length, bi.Length, Bsz, Bsz);
                        Mop.WriteSubMatrixTo(Block, bi, default(int[]), bi, default(int[]));
                        if (l1.Count > 0)
                        {
                            int   offset   = bi.Count;
                            int[] targRows = l1.Count.ForLoop(i => i + offset);

                            var   biE         = BlkIdx_gI_eR[iPart];
                            int[] extTargCols = biE.Count.ForLoop(i => i + offset);

                            Mop.AccSubMatrixTo(1.0, Block, bi, default(int[]), new int[0], default(int[]), biE, extTargCols);
                            ExternalRowsTemp.AccSubMatrixTo(1.0, Block, l1, targRows, bi, default(int[]), biE, extTargCols);
                        }
#if DEBUG
                        if (m_MatlabParalellizationCheck)
                        {
                            Blocks.Add(Block);
                        }
#endif
                        blockSolvers[iPart] = new PARDISOSolver()
                        {
                            CacheFactorization = true,
                            UseDoublePrecision = false
                        };
                        //blockSolvers[iPart] = new FullDirectSolver();
                        //blockSolvers[iPart] = new ilPSP.LinSolvers.MUMPS.MUMPSSolver();
                        blockSolvers[iPart].DefineMatrix(Block);
                    }

#if DEBUG
                    if (m_MatlabParalellizationCheck)
                    {
                        int globalBlockCounter = 0;
                        for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                        {
                            int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                            for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                            {
                                BlockMsrMatrix Block;
                                if (rankCounter == myMpiRank)
                                {
                                    Block = Blocks[iBlock];
                                }
                                else
                                {
                                    Block = null;
                                }

                                matlab.PutSparseMatrix(Block, string.Format("Block{0}", globalBlockCounter));

                                globalBlockCounter++;
                                csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);
                            }
                        }
                    }
#endif
                }

                // Record required indices
                // =======================
                {
                    this.BlockIndices_Local    = new int[NoOfSchwzBlocks][];
                    this.BlockIndices_External = new int[NoOfSchwzBlocks][];
                    int LocalI0     = MgMap.i0;
                    int LocalLength = MgMap.LocalLength;

                    for (int iBlock = 0; iBlock < NoOfSchwzBlocks; iBlock++)
                    {
                        var   _bi = BlkIdx_gI_lR[iBlock];
                        int   L   = _bi.Count;
                        int[] bil = new int[L];
                        this.BlockIndices_Local[iBlock] = bil;

                        for (int l = 0; l < L; l++)
                        {
                            bil[l] = _bi[l] - LocalI0;
                            Debug.Assert(bil[l] >= 0);
                            Debug.Assert(bil[l] < MgMap.LocalLength);
                        }

                        var _biE = BlkIdx_lI_eR[iBlock];
                        if (_biE.Count > 0)
                        {
                            this.BlockIndices_External[iBlock] = _biE.ToArray();
                        }
                    }
                }


                this.MtxFull = Mop;

                if (CoarseSolver != null)
                {
                    CoarseSolver.Init(op.CoarserLevel);
                }

                // Debug & Test-Code
                // =================
#if DEBUG
                if (m_MatlabParalellizationCheck)
                {
                    Console.WriteLine("Matlab dir: " + matlab.WorkingDirectory);

                    matlab.PutSparseMatrix(Mop, "Full");
                    int GlobalNoOfBlocks = NoOfSchwzBlocks.MPISum();



                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        matlab.Cmd("BlockErr({0} + 1, 1) = norm( Block{0} - Full( BlockIdx{0}, BlockIdx{0} ), inf );", iGlbBlock);
                    }

                    Random   rnd     = new Random(myMpiRank);
                    double[] testRHS = new double[MgMap.LocalLength];
                    for (int i = 0; i < testRHS.Length; i++)
                    {
                        testRHS[i] = rnd.NextDouble();
                    }
                    matlab.PutVector(testRHS, "testRHS");

                    MPIexchange <double[]> ResExchange = new MPIexchange <double[]>(MgMap, testRHS);
                    ResExchange.TransceiveStartImReturn();
                    ResExchange.TransceiveFinish(0.0);

                    int offset = MgMap.LocalLength;

                    int g = 0;
                    for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                    {
                        int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                        for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                        {
                            double[] SubVec;
                            if (rankCounter == myMpiRank)
                            {
                                int LL = this.BlockIndices_Local[iBlock].Length;
                                int LE;
                                if (this.BlockIndices_External[iBlock] != null)
                                {
                                    LE = this.BlockIndices_External[iBlock].Length;
                                }
                                else
                                {
                                    LE = 0;
                                }
                                int L = LL + LE;

                                SubVec = new double[L];
                                for (int i = 0; i < LL; i++)
                                {
                                    SubVec[i] = testRHS[this.BlockIndices_Local[iBlock][i]];
                                }
                                if (LE > 0)
                                {
                                    for (int i = 0; i < LE; i++)
                                    {
                                        SubVec[i + LL] = ResExchange.Vector_Ext[this.BlockIndices_External[iBlock][i] - offset];
                                    }
                                }
                            }
                            else
                            {
                                SubVec = new double[0];
                            }

                            matlab.PutVector(SubVec, "SubVec" + g);

                            g++;
                        }
                    }

                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        matlab.Cmd("RhsErr({0} + 1, 1) = norm( SubVec{0} - testRHS( BlockIdx{0} ), inf );", iGlbBlock);
                    }

                    double[] testX = new double[testRHS.Length];
                    MPIexchangeInverse <double[]> XExchange = new MPIexchangeInverse <double[]>(MgMap, testX);

                    g = 0;
                    for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                    {
                        int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                        for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                        {
                            if (rankCounter == myMpiRank)
                            {
                                int LL = this.BlockIndices_Local[iBlock].Length;
                                int LE;
                                if (this.BlockIndices_External[iBlock] != null)
                                {
                                    LE = this.BlockIndices_External[iBlock].Length;
                                }
                                else
                                {
                                    LE = 0;
                                }
                                int L = LL + LE;


                                for (int i = 0; i < LL; i++)
                                {
                                    testX[this.BlockIndices_Local[iBlock][i]] += (g + 1);
                                }
                                if (LE > 0)
                                {
                                    for (int i = 0; i < LE; i++)
                                    {
                                        XExchange.Vector_Ext[this.BlockIndices_External[iBlock][i] - offset] += (g + 1);
                                    }
                                }
                            }
                            else
                            {
                                //nop
                            }

                            g++;
                        }
                    }
                    XExchange.TransceiveStartImReturn();
                    XExchange.TransceiveFinish(1.0);

                    matlab.Cmd("testXref = zeros({0},1);", MgMap.TotalLength);
                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        matlab.Cmd("testXref(BlockIdx{0},1) = testXref(BlockIdx{0},1) + ({0} + 1);", iGlbBlock);
                    }

                    matlab.PutVector(testX, "testX");
                    matlab.Cmd("testXErr = norm(testX - testXref, inf);");

                    MultidimensionalArray BlockErr = MultidimensionalArray.Create(GlobalNoOfBlocks, 1);
                    MultidimensionalArray RhsErr   = MultidimensionalArray.Create(GlobalNoOfBlocks, 1);
                    MultidimensionalArray testXErr = MultidimensionalArray.Create(1, 1);

                    matlab.GetMatrix(BlockErr, "BlockErr");
                    matlab.GetMatrix(RhsErr, "RhsErr");
                    matlab.GetMatrix(testXErr, "testXErr");

                    matlab.Execute();

                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        Console.WriteLine("Block #{0} Error (external? ) " + BlockErr[iGlbBlock, 0], iGlbBlock);
                        Console.WriteLine("RHS #{0} Error " + RhsErr[iGlbBlock, 0], iGlbBlock);
                        Debug.Assert(BlockErr[iGlbBlock, 0] == 0);
                        Debug.Assert(RhsErr[iGlbBlock, 0] == 0);
                    }

                    Console.WriteLine("X Error " + testXErr[0, 0]);
                    Debug.Assert(testXErr[0, 0] == 0.0);

                    matlab.Dispose();
                }
#endif
            }
        }
예제 #23
0
 /// <summary>
 /// %
 /// </summary>
 internal override int GetNoOfBlocks(MultigridOperator op)
 {
     return(NoOfPartsPerProcess);
 }
예제 #24
0
            internal override IEnumerable <List <int> > GetBlocking(MultigridOperator op)
            {
                var MgMap = op.Mapping;

                //if(!M.RowPartitioning.Equals(MgMap.Partitioning))
                //    throw new ArgumentException("Row partitioning mismatch.");
                //if(!M.ColPartition.Equals(MgMap.Partitioning))
                //    throw new ArgumentException("Column partitioning mismatch.");

                var ag = MgMap.AggGrid;

                int JComp = ag.iLogicalCells.NoOfLocalUpdatedCells; // number of local cells

                int[]      xadj   = new int[JComp + 1];
                List <int> adjncy = new List <int>();

                for (int j = 0; j < JComp; j++)
                {
                    int[] neigh_j = ag.iLogicalCells.CellNeighbours[j];
                    foreach (int jNeigh in neigh_j)
                    {
                        //adjncy.AddRange(neigh_j);
                        if (jNeigh < JComp)
                        {
                            adjncy.Add(jNeigh);
                        }
                        else
                        {
                            //Console.WriteLine("Skipping external cell");
                        }
                    }
                    xadj[j + 1] = xadj[j] + neigh_j.Length;
                }

                int MPIrank, MPIsize;

                MPI.Wrappers.csMPI.Raw.Comm_Rank(MPI.Wrappers.csMPI.Raw._COMM.WORLD, out MPIrank);
                MPI.Wrappers.csMPI.Raw.Comm_Size(MPI.Wrappers.csMPI.Raw._COMM.WORLD, out MPIsize);
                //if (MPIrank == 1)
                //    NoOfParts = 1;
                //Debugger.Launch();

                int[] part = new int[JComp];
                {
                    if (NoOfPartsPerProcess > 1)
                    {
                        int   ncon    = 1;
                        int   edgecut = 0;
                        int[] options = null; //new int[] { 0, 0, 0, 0, 0 };
                        METIS.PartGraphKway(
                            ref JComp, ref ncon,
                            xadj,
                            adjncy.ToArray(),
                            null,
                            null,
                            null,
                            ref NoOfPartsPerProcess,
                            null,
                            null,
                            options,
                            ref edgecut,
                            part);
                    }
                    else
                    {
                        part.SetAll(0);
                    }
                }

                {
                    var _Blocks = NoOfPartsPerProcess.ForLoop(i => new List <int>((int)Math.Ceiling(1.1 * JComp / NoOfPartsPerProcess)));
                    for (int j = 0; j < JComp; j++)
                    {
                        _Blocks[part[j]].Add(j);
                    }

                    return(_Blocks);
                }
            }
예제 #25
0
 /// <summary>
 /// %
 /// </summary>
 internal override int GetNoOfBlocks(MultigridOperator op)
 {
     return(GetBlocking(op).Count());
 }
예제 #26
0
 /// <summary>
 /// Triggers <see cref="IterationCallback"/>.
 /// </summary>
 protected void OnIterationCallback(int iterIndex, double[] currentSol, double[] currentRes, MultigridOperator Mgop)
 {
     if (IterationCallback != null)
     {
         IterationCallback(iterIndex, currentSol, currentRes, Mgop);
     }
 }
예제 #27
0
        public void Init(MultigridOperator op)
        {
            int D = op.GridData.SpatialDimension;

            CodName = (new string[] { "mom0", "mom1" });
            Params  = ArrayTools.Cat(
                VariableNames.Velocity0Vector(D));
            DomName = ArrayTools.Cat(VariableNames.VelocityVector(D));

            LocalOp = new SpatialOperator(DomName, Params, CodName, (A, B, C) => 4);

            for (int d = 0; d < D; d++)
            {
                LocalOp.EquationComponents["mom" + d].Add(new LocalDiffusiveFlux()
                {
                    m_component = d, dt = m_dt, muA = m_muA
                });
            }

            LocalOp.Commit();

            //LocalMatrix = op.MassMatrix.CloneAs().ToMsrMatrix();
            //LocalMatrix.Clear();

            //var U0 = new VectorField<SinglePhaseField>(op.BaseGridProblemMapping Take(D).Select(F => (SinglePhaseField)F).ToArray());

            UnsetteledCoordinateMapping test = new UnsetteledCoordinateMapping(op.BaseGridProblemMapping.BasisS.GetSubVector(0, D));

            var U0 = ((BoSSS.Foundation.CoordinateMapping)op.Mapping.ProblemMapping).Fields.GetSubVector(0, 2);

            var empty = new SinglePhaseField[D];

            LocalMatrix = LocalOp.ComputeMatrix(test, empty, test, time: m_dt);


            Uidx = op.Mapping.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i));
            Pidx = op.Mapping.ProblemMapping.GetSubvectorIndices(true, D);

            int Upart = Uidx.Length;
            int Ppart = Pidx.Length;

            ConvDiff = new MsrMatrix(Upart, Upart, 1, 1);
            pGrad    = new MsrMatrix(Upart, Ppart, 1, 1);
            divVel   = new MsrMatrix(Ppart, Upart, 1, 1);
            var VelocityMass        = new MsrMatrix(Upart, Upart, 1, 1);
            var leftChangeBasesVel  = new MsrMatrix(Upart, Upart, 1, 1);
            var rightChangeBasesVel = new MsrMatrix(Upart, Upart, 1, 1);

            op.MassMatrix.AccSubMatrixTo(1.0, VelocityMass, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[]));

            op.LeftChangeOfBasis.AccSubMatrixTo(1.0, leftChangeBasesVel, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[]));
            op.RightChangeOfBasis.AccSubMatrixTo(1.0, rightChangeBasesVel, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[]));

            var temp = MsrMatrix.Multiply(leftChangeBasesVel, LocalMatrix);

            LocalMatrix = MsrMatrix.Multiply(temp, rightChangeBasesVel);

            var M = op.OperatorMatrix;

            M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[]));
            M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[]), default(int[]), default(int[]));
            M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[]));

            LocalMatrix.SaveToTextFileSparse("LocalConvDiffMatrix");
            ConvDiff.SaveToTextFileSparse("ConvDiff");
            op.MassMatrix.SaveToTextFileSparse("MassMatrix");
            VelocityMass.SaveToTextFileSparse("VelocityMass");
        }
예제 #28
0
        /// <summary>
        /// Callback routine, see <see cref="ISolverWithCallback.IterationCallback"/> or <see cref="NonlinearSolver.IterationCallback"/>.
        /// </summary>
        public void IterationCallback(int iter, double[] xI, double[] rI, MultigridOperator mgOp)
        {
            if (xI.Length != SolverOperator.Mapping.LocalLength)
            {
                throw new ArgumentException();
            }
            if (rI.Length != SolverOperator.Mapping.LocalLength)
            {
                throw new ArgumentException();
            }

            int Lorg = SolverOperator.BaseGridProblemMapping.LocalLength;

            // transform residual and solution back onto the orignal grid
            // ==========================================================

            double[] Res_Org = new double[Lorg];
            double[] Sol_Org = new double[Lorg];

            SolverOperator.TransformRhsFrom(Res_Org, rI);
            SolverOperator.TransformSolFrom(Sol_Org, xI);

            double[] Err_Org = Sol_Org.CloneAs();
            Err_Org.AccV(-1.0, this.ExactSolution);

            if (TecplotOut != null)
            {
                var ErrVec = InitProblemDGFields("Err");
                var ResVec = InitProblemDGFields("Res");
                var SolVec = InitProblemDGFields("Sol");

                ErrVec.SetV(Err_Org);
                ResVec.SetV(Res_Org);
                SolVec.SetV(Sol_Org);
                List <DGField> ErrResSol = new List <DGField>();
                ErrResSol.AddRange(ErrVec.Mapping.Fields);
                ErrResSol.AddRange(ResVec.Mapping.Fields);
                ErrResSol.AddRange(SolVec.Mapping.Fields);

                Tecplot.Tecplot.PlotFields(ErrResSol, TecplotOut + "." + iter, iter, 4);
            }


            // Console out
            // ===========
            double l2_RES = rI.L2NormPow2().MPISum().Sqrt();
            double l2_ERR = Err_Org.L2NormPow2().MPISum().Sqrt();

            Console.WriteLine("Iter: {0}\tRes: {1:0.##E-00}\tErr: {2:0.##E-00}", iter, l2_RES, l2_ERR);


            // decompose error and residual into orthonormal vectors
            // =====================================================


            int L0 = DecompositionOperator.Mapping.LocalLength;

            double[] Err_0 = new double[L0], Res_0 = new double[L0];
            DecompositionOperator.TransformSolInto(Err_Org, Err_0);
            DecompositionOperator.TransformRhsInto(Res_Org, Res_0);

            IList <double[]> Err_OrthoLevels = OrthonormalMultigridDecomposition(Err_0);
            IList <double[]> Res_OrthoLevels = OrthonormalMultigridDecomposition(Res_0);


            // compute L2 norms on each level
            // ==============================
            for (var mgop = this.DecompositionOperator; mgop != null; mgop = mgop.CoarserLevel)
            {
                int[] _Degrees = mgop.Mapping.DgDegree;

                double[] Resi = Res_OrthoLevels[mgop.LevelIndex];
                double[] Errr = Err_OrthoLevels[mgop.LevelIndex];
                int      JAGG = mgop.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;


                for (int iVar = 0; iVar < _Degrees.Length; iVar++)
                {
                    for (int p = 0; p <= _Degrees[iVar]; p++)
                    {
                        List <double> ResNorm = this.ResNormTrend[new Tuple <int, int, int>(mgop.LevelIndex, iVar, p)];
                        List <double> ErrNorm = this.ErrNormTrend[new Tuple <int, int, int>(mgop.LevelIndex, iVar, p)];

                        double ResNormAcc = 0.0;
                        double ErrNormAcc = 0.0;

                        for (int jagg = 0; jagg < JAGG; jagg++)
                        {
                            int[] NN = mgop.Mapping.AggBasis[iVar].ModeIndexForDegree(jagg, p, _Degrees[iVar]);

                            foreach (int n in NN)
                            {
                                int idx = mgop.Mapping.LocalUniqueIndex(iVar, jagg, n);

                                ResNormAcc += Resi[idx].Pow2();
                                ErrNormAcc += Errr[idx].Pow2();
                            }
                        }

                        ResNorm.Add(ResNormAcc.Sqrt());
                        ErrNorm.Add(ErrNormAcc.Sqrt());
                    }
                }
            }
        }
예제 #29
0
        public void Init(MultigridOperator op)
        {
            int D     = op.Mapping.GridData.SpatialDimension;
            var M     = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_mgop = op;

            if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            Uidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i));
            Pidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D);

            int Upart = Uidx.Length;
            int Ppart = Pidx.Length;

            ConvDiff = new MsrMatrix(Upart, Upart, 1, 1);
            pGrad    = new MsrMatrix(Upart, Ppart, 1, 1);
            divVel   = new MsrMatrix(Ppart, Upart, 1, 1);
            var PxP = new MsrMatrix(Ppart, Ppart, 1, 1);

            M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[]));
            M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[]));
            M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[]));
            M.AccSubMatrixTo(1.0, PxP, Pidx, default(int[]), Pidx, default(int[]));

            Mtx = M;

            int L = M.RowPartitioning.LocalLength;

            int i0 = Mtx.RowPartitioning.i0;

            P = new MsrMatrix(Mtx);
            P.Clear();

            // Debugging output
            //ConvDiff.SaveToTextFileSparse("ConvDiff");
            //divVel.SaveToTextFileSparse("divVel");
            //pGrad.SaveToTextFileSparse("pGrad");
            //PxP.SaveToTextFileSparse("PxP");


            velMassMatrix = new MsrMatrix(Upart, Upart, 1, 1);
            op.MassMatrix.AccSubMatrixTo(1.0, velMassMatrix, Uidx, default(int[]), Uidx, default(int[]));

            switch (SchurOpt)
            {
            case SchurOptions.exact:
            {
                // Building complete Schur and Approximate Schur
                MultidimensionalArray Poisson       = MultidimensionalArray.Create(Pidx.Length, Pidx.Length);
                MultidimensionalArray SchurConvPart = MultidimensionalArray.Create(Pidx.Length, Pidx.Length);
                MultidimensionalArray Schur         = MultidimensionalArray.Create(Pidx.Length, Pidx.Length);
                using (BatchmodeConnector bmc = new BatchmodeConnector())
                {
                    bmc.PutSparseMatrix(ConvDiff, "ConvDiff");
                    bmc.PutSparseMatrix(velMassMatrix, "MassMatrix");
                    bmc.PutSparseMatrix(divVel, "divVel");
                    bmc.PutSparseMatrix(pGrad, "pGrad");
                    bmc.Cmd("Qdiag = diag(diag(MassMatrix))");
                    bmc.Cmd("invT= inv(Qdiag)");
                    bmc.Cmd("Poisson = full(invT)*pGrad");
                    bmc.Cmd("ConvPart = ConvDiff*Poisson");
                    bmc.Cmd("ConvPart= full(invT)*ConvPart");
                    bmc.Cmd("ConvPart= divVel*ConvPart");
                    bmc.Cmd("Poisson = divVel*Poisson");
                    bmc.Cmd("ConvDiffInv = inv(full(ConvDiff))");
                    bmc.Cmd("Schur = divVel*ConvDiffInv");
                    bmc.Cmd("Schur = Schur*pGrad");
                    bmc.GetMatrix(Poisson, "Poisson");
                    bmc.GetMatrix(SchurConvPart, "ConvPart");
                    bmc.GetMatrix(Schur, "-Schur");
                    bmc.Execute(false);
                }
                PoissonMtx_T = Poisson.ToMsrMatrix();
                PoissonMtx_H = Poisson.ToMsrMatrix();
                SchurConvMtx = SchurConvPart.ToMsrMatrix();
                SchurMtx     = Schur.ToMsrMatrix();
                SchurMtx.Acc(PxP, 1);

                ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx);
                pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx);
                SchurMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx);
                return;
            }

            case SchurOptions.decoupledApprox:
            {
                // Do assembly for approximate Schur inverse
                invVelMassMatrix = velMassMatrix.CloneAs();
                invVelMassMatrix.Clear();
                invVelMassMatrixSqrt = invVelMassMatrix.CloneAs();
                for (int i = velMassMatrix.RowPartitioning.i0; i < velMassMatrix.RowPartitioning.iE; i++)
                {
                    if (ApproxScaling)
                    {
                        invVelMassMatrix.SetDiagonalElement(i, 1 / (velMassMatrix[i, i]));
                        invVelMassMatrixSqrt.SetDiagonalElement(i, 1 / (Math.Sqrt(velMassMatrix[i, i])));
                    }
                    else
                    {
                        invVelMassMatrix.SetDiagonalElement(i, 1);
                        invVelMassMatrixSqrt.SetDiagonalElement(i, 1);
                    }
                }

                //invVelMassMatrix.SaveToTextFileSparse("invVelMassMatrix");
                //velMassMatrix.SaveToTextFileSparse("velMassMatrix");


                //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiff, pGrad);
                //ConvDiffPoissonMtx = MsrMatrix.Multiply(divVel, ConvDiffPoissonMtx);

                // Inverse of mass matrix in Matlab
                //MultidimensionalArray temp = MultidimensionalArray.Create(Uidx.Length, Uidx.Length);
                //using (BatchmodeConnector bmc = new BatchmodeConnector())
                //{
                //    bmc.PutSparseMatrix(velMassMatrix, "velMassMatrix");
                //    bmc.Cmd("invVelMassMatrix = inv(full(velMassMatrix))");
                //    bmc.GetMatrix(temp, "invVelMassMatrix");
                //    bmc.Execute(false);
                //}
                //invVelMassMatrix = temp.ToMsrMatrix();

                //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiffPoissonMtx, PoissonMtx);
                //ConvDiffPoissonMtx = MsrMatrix.Multiply(PoissonMtx, ConvDiffPoissonMtx);

                //ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx);
                //pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx);
                //ConvDiffPoissonMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx);

                //op.MassMatrix.SaveToTextFileSparse("MassMatrix");
                //velMassMatrix.SaveToTextFileSparse("velMassMatrix2");


                // Possion scaled by inverse of the velocity mass matrix
                PoissonMtx_T = MsrMatrix.Multiply(invVelMassMatrix, pGrad);
                PoissonMtx_T = MsrMatrix.Multiply(divVel, PoissonMtx_T);
                ////PoissonMtx_T.Acc(PxP, 1); // p.379

                // Poisson scaled by sqrt of inverse of velocity mass matrix
                PoissonMtx_H = MsrMatrix.Multiply(invVelMassMatrixSqrt, pGrad);
                PoissonMtx_H = MsrMatrix.Multiply(divVel, PoissonMtx_H);
                //PoissonMtx_H.Acc(PxP, 1); // p.379
                return;
            }

            case SchurOptions.SIMPLE:
            {
                var invdiag_ConvDiff = ConvDiff.CloneAs();
                invdiag_ConvDiff.Clear();
                for (int i = ConvDiff.RowPartitioning.i0; i < ConvDiff.RowPartitioning.iE; i++)
                {
                    invdiag_ConvDiff[i, i] = 1 / ConvDiff[i, i];
                }

                simpleSchur = MsrMatrix.Multiply(invdiag_ConvDiff, pGrad);
                simpleSchur = MsrMatrix.Multiply(divVel, simpleSchur);

                return;
            }

            default:
                throw new NotImplementedException("SchurOption");
            }


            //var ConvDiffInvMtx = ConvDiffInv.ToMsrMatrix();


            //// x= inv(P)*b !!!!! To be done with approximate Inverse
            // P.SpMV(1, B, 0, X);
        }
예제 #30
0
파일: Schwarz.cs 프로젝트: octwanna/BoSSS
        public void Init(MultigridOperator op)
        {
            var M     = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_MgOp = op;

            if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            var ag = MgMap.AggGrid;

            int JComp  = ag.iLogicalCells.NoOfLocalUpdatedCells;
            int JGhost = ag.iLogicalCells.NoOfExternalCells;

            // get cell blocks
            // ===============

            var _Blocks = this.m_BlockingStrategy.GetBlocking(op);
            int NoParts = _Blocks.Count();

            // test cell blocks
            // ================
#if DEBUG
            {
                // ensure that each cell is used exactly once, among all blocks
                bool[] test = new bool[ag.iLogicalCells.NoOfLocalUpdatedCells];
                foreach (var bi in _Blocks)
                {
                    foreach (int j in bi)
                    {
                        Debug.Assert(test[j] == false);
                        test[j] = true;
                    }
                    ;
                }
                for (int i = 0; i < test.Length; i++)
                {
                    Debug.Assert(test[i] == true);
                }
            }
#endif

            // extend blocks according to desired overlap
            // ==========================================
            {
                BitArray marker = new BitArray(JComp + JGhost);

                if (overlap < 0)
                {
                    throw new ArgumentException();
                }
                if (overlap > 0)
                {
                    foreach (List <int> bi in _Blocks) // loop over blocks...
                    {
                        marker.SetAll(false);          // marks all cells which are members of the block
                        foreach (int jcomp in bi)
                        {
                            marker[jcomp] = true;
                        }

                        // determine overlap regions
                        for (int k = 0; k < overlap; k++)
                        {
                            int Jblock = bi.Count;
                            for (int j = 0; j < Jblock; j++)
                            {
                                int   jCell  = bi[j];
                                int[] Neighs = ag.iLogicalCells.CellNeighbours[jCell];
                                foreach (int jNeigh in Neighs)
                                {
                                    if (marker[jNeigh] == false)
                                    {
                                        // neighbor cell is not already a member of the block
                                        // => add it.
                                        bi.Add(jNeigh);
                                        marker[jNeigh] = true;
                                    }
                                }
                            }
                        }

                        bi.Sort();
                    }
                }


                BlockCells = _Blocks.Select(list => list.ToArray()).ToArray();
            }


            // convert cell blocks to DOF blocks
            // =================================

            {
                int Jup = MgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                int Jgh = MgMap.AggGrid.iLogicalCells.NoOfExternalCells;


                var _BlockIndices = NoParts.ForLoop(iPart => new List <int>(BlockCells[iPart].Length * MgMap.MaximalLength));
                for (int iPart = 0; iPart < NoParts; iPart++)   // loop over parts...
                {
                    int[] bc     = BlockCells[iPart];
                    var   bi     = _BlockIndices[iPart];
                    int   Jblock = bc.Length;


                    for (int jblk = 0; jblk < Jblock; jblk++)
                    {
                        int j = bc[jblk];

                        if (j < Jup)
                        {
                            int N  = MgMap.GetLength(j);
                            int i0 = MgMap.LocalUniqueIndex(0, j, 0);

                            for (int n = 0; n < N; n++)
                            {
                                bi.Add(i0 + n);
                            }
                        }
                        else
                        {
                            throw new NotImplementedException("todo: MPI parallelization;");
                        }
                    }
                }

                this.BlockIndices = _BlockIndices.Select(bi => bi.ToArray()).ToArray();
            }


            // test DOF blocks
            // ===============
            {
                int L  = M.RowPartitioning.LocalLength;
                int i0 = M.RowPartitioning.i0;

                // ensure that each cell is used exactly once, among all blocks

                BitArray test = new BitArray(L);
                foreach (var bi in BlockIndices)
                {
                    bi.ForEach(delegate(int i) {
                        if (i < L)
                        {
                            Debug.Assert(test[i] == false || this.overlap > 0);
                            test[i] = true;
                        }
                    });
                }
                for (int i = 0; i < L; i++)
                {
                    Debug.Assert(test[i] == true);
                }
            }


            // create solvers
            // ==============

            {
                blockSolvers = new ISparseSolver[NoParts];

                for (int iPart = 0; iPart < NoParts; iPart++)
                {
                    int[] bi = BlockIndices[iPart];

                    int Bsz;
                    if (MgMap.MinimalLength == MgMap.MaximalLength)
                    {
                        Bsz = MgMap.MaximalLength;
                    }
                    else
                    {
                        Bsz = 1;
                    }

                    if (M.RowPartitioning.MpiSize > 1)
                    {
                        int i0Proc = M.RowPartitioning.i0;
                        bi = bi.CloneAs();
                        for (int i = 0; i < bi.Length; i++)
                        {
                            bi[i] += i0Proc;
                        }
                    }


                    MsrMatrix Block = new MsrMatrix(bi.Length, bi.Length, Bsz, Bsz);
                    M.WriteSubMatrixTo(Block, bi, default(int[]), bi, default(int[]));

                    //blockSolvers[iPart] = new PARDISOSolver();
                    //blockSolvers[iPart].CacheFactorization = true;
                    //blockSolvers[iPart].DefineMatrix(Block);
                    //blockSolvers[iPart] = new FullDirectSolver();
                    //blockSolvers[iPart].DefineMatrix(Block);

                    blockSolvers[iPart] = new ilPSP.LinSolvers.MUMPS.MUMPSSolver();
                    blockSolvers[iPart].DefineMatrix(Block);
                }
            }

            this.MtxFull = new ilPSP.LinSolvers.monkey.CPU.RefMatrix(M.ToMsrMatrix());

            if (CoarseSolver != null)
            {
                CoarseSolver.Init(op.CoarserLevel);
            }
        }