Пример #1
0
        /// <summary>
        /// Creates a node-set and a corresponding set of nodal polynomials;
        /// </summary>
        public void SelectNodalPolynomials(int px, out NodeSet Nodes, out PolynomialList _NodalBasis, out int[] Type, out int[] EntityIndex, out MultidimensionalArray Nodal2Modal, out MultidimensionalArray Modal2Nodal, Func <Polynomial, bool> ModalBasisSelector = null, int[] NodeTypeFilter = null)
        {
            int D = this.SpatialDimension;

            if (ModalBasisSelector == null)
            {
                ModalBasisSelector = delegate(Polynomial p) {
                    Debug.Assert(p.Coeff.Length == p.Exponents.GetLength(0));
                    Debug.Assert(p.Exponents.GetLength(1) == D);


                    for (int l = 0; l < p.Coeff.Length; l++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            if (p.Exponents[l, d] > (px - 1))
                            {
                                return(false);
                            }
                        }
                    }

                    return(true);
                }
            }
            ;

            // Find node set
            // =============
            GetNodeSet(px, out Nodes, out Type, out EntityIndex, NodeTypeFilter);
            int NoOfNodes = Type.Length;

#if DEBUG
            double[,] DIST = new double[NoOfNodes, NoOfNodes];
            for (int j1 = 0; j1 < NoOfNodes; j1++)
            {
                for (int j2 = 0; j2 < NoOfNodes; j2++)
                {
                    if (j2 == j1)
                    {
                        continue;
                    }

                    var node_j1 = Nodes.GetRow(j1);
                    var node_j2 = Nodes.GetRow(j2);

                    DIST[j1, j2] = GenericBlas.L2Dist(node_j1, node_j2);
                    if (DIST[j1, j2] <= 1.0e-8)
                    {
                        throw new ApplicationException("internal error.");
                    }
                }
            }
#endif


            // Find modal basis of approximation space
            // =======================================

            var ortho_polys = this.OrthonormalPolynomials;

            List <Polynomial> Basis = new List <Polynomial>();
            int deg;
            if (px > 1)
            {
                for (deg = 0; deg <= (px - 1) * D; deg++)
                {
                    var r = ortho_polys.Where(p => ((p.AbsoluteDegree == deg) && ModalBasisSelector(p)));

                    Basis.AddRange(r);
                    if (Basis.Count >= NoOfNodes)
                    {
                        break;
                    }
                }
            }
            else
            {
                var r = ortho_polys.Where(pol => pol.AbsoluteDegree <= 1);
                Basis.AddRange(r);
                deg = 1;
            }


            if (Basis.Count != NoOfNodes)
            {
                throw new ApplicationException("Basis selection failed.");
            }


            // check for basis selection
            // ==========================

            // case Triangle, Tetra: the complete P_{px-1}(x,y) should be selected
            // case Quad, Cube: P_{px-1}(x)*P_{px-1)(y) subset of P_{px-1}(x,y) will be selected
            int NoOfPolys = NoOfNodes;


            int[] idx_Basis = new int[NoOfPolys];
            for (int i = 0; i < NoOfPolys; i++)
            {
                idx_Basis[i] = Array.IndexOf(ortho_polys, Basis[i]);
                Debug.Assert(idx_Basis[i] >= 0);
            }


            // Construct nodal Polynomials
            // ===========================

            MultidimensionalArray PolyAtNodes = MultidimensionalArray.Create(NoOfPolys, NoOfNodes);
            for (int i = 0; i < NoOfNodes; i++)
            {
                Basis[i].Evaluate(PolyAtNodes.ExtractSubArrayShallow(-1, i), Nodes);
            }

            //FullMatrix MtxPolyAtNodes = new FullMatrix(NoOfPolys, NoOfNodes);
            //MtxPolyAtNodes.Set(PolyAtNodes);

            Debug.Assert(!PolyAtNodes.ContainsNanOrInf(), "Nodal Poly generation, illegal value");
            var Sol = PolyAtNodes.GetInverse();
            Debug.Assert(!Sol.ContainsNanOrInf(), "Nodal Poly generation, solution, illegal value");

            Modal2Nodal = MultidimensionalArray.Create(ortho_polys.Where(p => p.AbsoluteDegree <= deg).Count(), NoOfPolys);
            Nodal2Modal = MultidimensionalArray.Create(Modal2Nodal.NoOfCols, Modal2Nodal.NoOfRows);
            MultidimensionalArray _Modal2Nodal = MultidimensionalArray.Create(NoOfPolys, NoOfPolys);
            MultidimensionalArray _Nodal2Modal = MultidimensionalArray.Create(NoOfPolys, NoOfPolys);

            var          b          = new double[NoOfPolys];
            var          rhs        = new double[NoOfNodes];
            Polynomial[] NodalBasis = new Polynomial[NoOfNodes];
            for (int k = 0; k < NoOfNodes; k++)
            {
                Array.Clear(rhs, 0, rhs.Length);
                rhs[k] = 1.0;

                Sol.GEMV(1.0, rhs, 0.0, b);

                for (int i = 0; i < NoOfPolys; i++)
                {
                    if (Math.Abs(b[i]) > 1.0e-12)
                    {
                        if (NodalBasis[k] == null)
                        {
                            NodalBasis[k] = b[i] * Basis[i];
                        }
                        else
                        {
                            NodalBasis[k] = NodalBasis[k] + b[i] * Basis[i];
                        }
                    }
                    else
                    {
                        //Console.WriteLine("tresh {0}, {1}", Math.Abs(b[i]), b[i]);
                    }

                    _Modal2Nodal[i, k] = b[i];
                }

                //Console.WriteLine("k: {0}, NoOfPolys {1}, isnull {2} ", k, NoOfPolys, NodalBasis[k] == null);
            }
            _NodalBasis = new PolynomialList(NodalBasis);
            Debug.Assert(ContainsZero(_NodalBasis), "interpolation poly not found, 5");

            _Modal2Nodal.InvertTo(_Nodal2Modal);

            for (int k = 0; k < NoOfNodes; k++)
            {
                for (int i = 0; i < NoOfPolys; i++)
                {
                    Modal2Nodal[idx_Basis[i], k] = _Modal2Nodal[i, k];
                    Nodal2Modal[i, idx_Basis[k]] = _Nodal2Modal[i, k];
                }
            }
        }
    }
Пример #2
0
        static internal void InvertMassMatrixBlocks(
            out Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocksInv,
            Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocks,
            int N)
        {
            using (new FuncTrace()) {
                MassMatrixBlocksInv = new Dictionary <SpeciesId, MassMatrixBlockContainer>();
                foreach (var Species in MassMatrixBlocks.Keys)
                {
                    var mblk = MassMatrixBlocks[Species].MassMatrixBlocks;
                    //var mblkB4agg = MassMatrixBlocks[Species].MassMatrixBlocks_B4Agglom;
                    var invmblk = MultidimensionalArray.Create(mblk.GetLength(0), N, N);
                    MassMatrixBlocksInv.Add(Species,
                                            new MassMatrixBlockContainer()
                    {
                        MassMatrixBlocks = invmblk,
                        //jCell2jSub = MassMatrixBlocks[Species].jCell2jSub,
                        jSub2jCell        = MassMatrixBlocks[Species].jSub2jCell,
                        IntegrationDomain = MassMatrixBlocks[Species].IntegrationDomain
                    });

                    int B = mblk.GetLength(0);
                    Debug.Assert(mblk.GetLength(2) >= N);

                    MultidimensionalArray blk     = MultidimensionalArray.Create(N, N);
                    MultidimensionalArray inv_Blk = MultidimensionalArray.Create(N, N);


                    // loop over all cut cells (mass matrix blocks)...
                    for (int b = 0; b < B; b++)
                    {
                        MultidimensionalArray _blk;
                        //if ((aggSw == true) || (mblkB4agg[b] == null)) {
                        _blk = mblk.ExtractSubArrayShallow(new int[] { b, 0, 0 }, new int[] { b - 1, N - 1, N - 1 });
                        //} else {
                        //    Debug.Assert(aggSw == false);
                        //    Debug.Assert(mblkB4agg[b] != null);
                        //    _blk = mblkB4agg[b].ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { N - 1, N - 1 });
                        //}

                        blk.Set(_blk);
                        if (blk.ContainsNanOrInf(true, true))
                        {
                            throw new ArithmeticException("NAN/INF in mass matrix.");
                        }

                        if (blk.InfNorm() == 0.0)
                        {
                            // a zero-block
                            invmblk.ExtractSubArrayShallow(b, -1, -1).Clear();
                        }
                        else
                        {
                            //blk.Invert(inv_Blk);
                            try {
                                inv_Blk.Clear();
                                inv_Blk.Acc(1.0, blk);
                                inv_Blk.InvertSymmetrical();

#if DEBUG
                                for (int n = 0; n < N; n++)
                                {
                                    for (int m = 0; m < N; m++)
                                    {
                                        Debug.Assert(inv_Blk[n, m] == inv_Blk[m, n]);
                                    }
                                }
#endif
                            } catch (ArithmeticException) {
                                Console.WriteLine("WARNING: indefinite mass matrix.");
                                blk.InvertTo(inv_Blk);
#if DEBUG
                                for (int n = 0; n < N; n++)
                                {
                                    for (int m = 0; m < N; m++)
                                    {
                                        Debug.Assert(Math.Abs(inv_Blk[n, m] - inv_Blk[m, n]) / (Math.Abs(inv_Blk[n, m]) + Math.Abs(inv_Blk[m, n])) <= 1.0e-9);
                                    }
                                }
#endif
                            }

                            if (blk.ContainsNanOrInf(true, true))
                            {
                                throw new ArithmeticException("NAN/INF in inverse mass matrix.");
                            }

                            invmblk.SetSubMatrix(inv_Blk, b, -1, -1);
                        }

                        /*
                         * bool Choleski_failed = false;
                         * bool Symmelim_failed = false;
                         * try {
                         *  blk.Initialize(_blk);
                         *  blk.InvertSymmetrical();
                         * } catch (ArithmeticException) {
                         *  Choleski_failed = true;
                         * }
                         * try {
                         *  blk.Initialize(_blk);
                         *  FullMatrix.TiredRoutine(blk);
                         * } catch (ArithmeticException) {
                         *  Symmelim_failed = true;
                         * }
                         *
                         * if (Choleski_failed || Symmelim_failed) {
                         *  Console.WriteLine("Mass matrix defect ({0},{1}): species {2}, jsub = {3};", Choleski_failed, Symmelim_failed,  LsTrk.GetSpeciesName(Species), b);
                         *
                         *  int J = LsTrk.Ctx.Grid.NoOfUpdateCells;
                         *  if (MassErrors == null) {
                         *      MassErrors = new Dictionary<SpeciesId, System.Collections.BitArray>();
                         *  }
                         *  if (!MassErrors.ContainsKey(Species)) {
                         *      MassErrors.Add(Species, new System.Collections.BitArray(J));
                         *  }
                         *  var _MassErrors = MassErrors[Species];
                         *
                         *  int[] globalIdx = cutted.SubgridIndex2LocalCellIndex;
                         *  int jCell = globalIdx[b];
                         *
                         *  _MassErrors[jCell] = true;
                         *
                         * }
                         * //*/
                    }
                }
            }
        }