Exemple #1
0
        /// <summary>
        /// evaluation of DG field; may be used in derived classes to implement <see cref="DGField.Evaluate(int,int,NodeSet,MultidimensionalArray,int,double)"/>.
        /// </summary>
        protected static void EvaluateInternal(int j0, int L, NodeSet NS, Basis basis, MultidimensionalArray Coördinates, int coördOffset, MultidimensionalArray ResultAcc, double ResultPreScale)
        {
            int  D, N, NumNodes;
            bool AffineLinear;

            CheckArgs(j0, L, NS, basis, Coördinates, ResultAcc, out D, out N, out NumNodes, out AffineLinear);
            Debug.Assert(ResultAcc.Dimension == 2);
            Debug.Assert(L == ResultAcc.GetLength(0));
            Debug.Assert(NumNodes == ResultAcc.GetLength(1));

            /*
             * MultidimensionalArray BasisValues;
             * BasisValues = basis.CellEval(NS, j0, L);
             * Debug.Assert(BasisValues.GetLength(0) == L, "No. of. cells mismatch");
             * Debug.Assert(BasisValues.GetLength(1) == M, "No. of. nodes mismatch");
             * Debug.Assert(BasisValues.GetLength(2) == N, "No. of. basis elements mismatch");
             *
             * ResultAcc.Multiply(1.0, Coördinates, BasisValues, ResultPreScale, "jm", "jn", "jmn");
             */

            //int[] geom2log = basis.GridDat.iGeomCells.GeomCell2LogicalCell;

            MultidimensionalArray BasisValues = basis.Evaluate(NS);

            if (L == 1 && AffineLinear)
            {
                // Special optimization for single-cell evaluation:
                // this happens very often for edge quadrature, so it is quite relevant.
                double scale0 = basis.GridDat.ChefBasis.Scaling[j0];
                Debug.Assert(basis.GridDat.iGeomCells.GeomCell2LogicalCell == null || basis.GridDat.iGeomCells.GeomCell2LogicalCell[j0] == j0);
                MultidimensionalArray Coördinates_j;
                if (coördOffset == 0 && Coördinates.GetLength(0) == 1)
                {
                    Coördinates_j = Coördinates;
                }
                else
                {
                    Coördinates_j = Coördinates.ExtractSubArrayShallow(new int[] { coördOffset, 0 }, new int[] { coördOffset, N - 1 });
                }
                ResultAcc.Multiply(scale0, Coördinates_j, BasisValues, ResultPreScale, ref mp_jk_jm_km); //"jk", "jm", "km");
            }
            else
            {
                int iBuf;
                MultidimensionalArray trfCoördinates = TempBuffer.GetTempMultidimensionalarray(out iBuf, L, N);
                TransformCoördinates(j0, L, basis, Coördinates, coördOffset, N, AffineLinear, trfCoördinates);

                if (ResultAcc.IsContinious && trfCoördinates.IsContinious && BasisValues.IsContinious)
                {
                    unsafe
                    {
                        fixed(double *_pResultAcc = ResultAcc.Storage, _ptrfCoördinates = trfCoördinates.Storage, _pBasisValues = BasisValues.Storage)
                        {
                            double *pResultAcc      = _pResultAcc + ResultAcc.Index(0, 0);
                            double *ptrfCoördinates = _ptrfCoördinates + trfCoördinates.Index(0, 0);
                            double *pBasisValues    = _pBasisValues + BasisValues.Index(0, 0);


//#if DEBUG
//                            MultidimensionalArray check = ResultAcc.CloneAs();

//#endif

                            int _M = ResultAcc.GetLength(1);   // entspricht k   (node    index)
                            int _N = ResultAcc.GetLength(0);   // entspricht j   (cell    index)
                            int _K = BasisValues.GetLength(1); // entspricht m   (DG mode index)

                            // NOTE: dimensions in FORTRAN order:
                            // pBasisValues     :  _K x _M
                            // ptrfCoördinates  :  _K x _N
                            // pResultAcc       :  _M x _N
                            //
                            // => FORTRAN GEMM
                            // pResultAcc = pBasisValues^T * ptrfCoördinates

                            int TRANSA = 'T';
                            int TRANSB = 'N';

                            BLAS.dgemm(TRANSA, TRANSB, _M, _N, _K,
                                       1.0,
                                       pBasisValues, _K,
                                       ptrfCoördinates, _K,
                                       ResultPreScale,
                                       pResultAcc, _M);

//#if DEBUG
//                            check.Multiply(1.0, trfCoördinates, BasisValues, ResultPreScale, ref mp_jk_jm_km);
//                            check.Acc(-1.0, ResultAcc);
//                            double error = check.L2Norm();
//                            Console.WriteLine("GEMM error: " + error);
//                            Debug.Assert(error < 1.0);
//#endif
                        }
                    }
                }
                else
                {
                    ResultAcc.Multiply(1.0, trfCoördinates, BasisValues, ResultPreScale, ref mp_jk_jm_km); //"jk", "jm", "km");
                }


                TempBuffer.FreeTempBuffer(iBuf);
            }
        }
Exemple #2
0
        protected static void EvaluateEdgeInternal(int e0, int Len, NodeSet NS, Basis _Basis, MultidimensionalArray Coord,
                                                   MultidimensionalArray valIN, MultidimensionalArray valOT,
                                                   MultidimensionalArray meanValIN, MultidimensionalArray meanValOT,
                                                   MultidimensionalArray gradIN, MultidimensionalArray gradOT,
                                                   double ResultPreScale)
        {
            // checks and init
            // ===============

            var  grd          = _Basis.GridDat;
            int  NoOfNodes    = NS.NoOfNodes;
            bool AffineLinear = grd.iGeomEdges.IsEdgeAffineLinear(e0);

            Debug.Assert(NS.GetNodeCoordinateSystem(grd) == NodeCoordinateSystem.EdgeCoord);
            Debug.Assert(valIN == null || valIN.Dimension == 2);
            Debug.Assert(valOT == null || valOT.Dimension == 2);
            Debug.Assert(valIN == null || valIN.GetLength(0) == Len);
            Debug.Assert(valOT == null || valOT.GetLength(0) == Len);
            Debug.Assert(valIN == null || valIN.GetLength(1) == NoOfNodes);
            Debug.Assert(valOT == null || valOT.GetLength(1) == NoOfNodes);

            int[,] trfIdx = grd.iGeomEdges.Edge2CellTrafoIndex;
            int[,] E2Cl   = grd.iGeomEdges.LogicalCellIndices;
            int[,] E2Cg   = grd.iGeomEdges.CellIndices;



            // transform DG coördinates
            // ========================

            int Nin = _Basis.GetLength(E2Cl[e0, 0]);
            int Not = Nin;

#if DEBUG
            for (int e = 0; e < Len; e++)
            {
                int iEdge   = e + e0;
                int jCellIN = E2Cl[iEdge, 0];
                int jCellOT = E2Cl[iEdge, 1];
                Debug.Assert(_Basis.GetLength(jCellIN) == Nin);
                if (jCellOT >= 0)
                {
                    Debug.Assert(_Basis.GetLength(jCellOT) == Not);
                }
            }
#endif
            int iBufIN, iBufOT = 0;
            MultidimensionalArray trfCoördinatesIN = TempBuffer.GetTempMultidimensionalarray(out iBufIN, Len, Nin);
            MultidimensionalArray trfCoördinatesOT = Not > 0 ? TempBuffer.GetTempMultidimensionalarray(out iBufOT, Len, Not) : null;
            TransformCoördinatesEdge(e0, Len, grd, Coord, Nin, Not, _Basis.Degree, AffineLinear, trfCoördinatesIN, trfCoördinatesOT);

            // Evaluate
            // ========

            unsafe
            {
                fixed(int *pTrfIndex = trfIdx)
                {
                    MultidimensionalArray BasisValues = null;

                    Debug.Assert((valIN != null) == (valOT != null));
                    if (valIN != null)
                    {
                        // compute the values
                        // -------------------

                        BasisValues = grd.ChefBasis.EdgeEval.GetValues(NS, e0, Len, _Basis.Degree);
                        Debug.Assert(BasisValues.Dimension == 3);

                        MultidimensionalArray BasisValuesIN, BasisValuesOT;
                        if (BasisValues.GetLength(2) > Nin)
                        {
                            BasisValuesIN = BasisValues.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { BasisValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1 });
                        }
                        else
                        {
                            BasisValuesIN = BasisValues;
                        }
                        if (BasisValues.GetLength(2) > Not)
                        {
                            if (Nin == Not)
                            {
                                BasisValuesOT = BasisValuesIN;
                            }
                            else
                            {
                                BasisValuesOT = BasisValues.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { BasisValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1 });
                            }
                        }
                        else
                        {
                            BasisValuesOT = BasisValues;
                        }

                        {
                            valIN.Multiply(1.0, trfCoördinatesIN, BasisValuesIN, ResultPreScale, ref mp_ik_im_Tikm,
                                           pTrfIndex, pTrfIndex,
                                           trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0);
                        }
                        if (Not > 0)
                        {
                            valOT.Multiply(1.0, trfCoördinatesOT, BasisValuesOT, ResultPreScale, ref mp_ik_im_Tikm,
                                           pTrfIndex, pTrfIndex,
                                           trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0);
                        }
                    }

                    Debug.Assert((meanValIN != null) == (meanValOT != null));
                    if (meanValIN != null)
                    {
                        // compute the mean values
                        // -----------------------

                        var _Basis0Values = BasisValues;
                        if (_Basis0Values == null)
                        {
                            _Basis0Values = grd.ChefBasis.EdgeEval.GetValues(NS, e0, Len, 0);
                        }
                        // assume the 0-th basis polynomial \f$ \phi_0 \f$ is constant!
                        _Basis0Values = _Basis0Values.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { BasisValues.GetLength(0) - 1, -1, -1 });

                        // DG coördinates for the 0-th mode:
                        var _trfCoördinatesIN = trfCoördinatesIN.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Len - 1, -1 });
                        var _trfCoördinatesOT = trfCoördinatesOT.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Len - 1, -1 });

                        {
                            meanValIN.Multiply(1.0, _trfCoördinatesIN, _Basis0Values, ResultPreScale, ref mp_i_i_Ti,
                                               pTrfIndex, pTrfIndex,
                                               trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0);
                        }
                        if (Not > 0)
                        {
                            meanValOT.Multiply(1.0, _trfCoördinatesOT, _Basis0Values, ResultPreScale, ref mp_i_i_Ti,
                                               pTrfIndex, pTrfIndex,
                                               trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0);
                        }
                    }

                    Debug.Assert((gradIN != null) == (gradOT != null));
                    if (gradIN != null)
                    {
                        // compute gradient values
                        // -----------------------

                        int D = grd.SpatialDimension;
                        int iBuf2;
                        MultidimensionalArray GradientRef = TempBuffer.GetTempMultidimensionalarray(out iBuf2, Len, NoOfNodes, D);

                        MultidimensionalArray BasisGradValues = grd.ChefBasis.EdgeGradientEval.GetValues(NS, e0, Len, _Basis.Degree);
                        Debug.Assert(BasisGradValues.Dimension == 4);

                        MultidimensionalArray BasisGradValuesIN, BasisGradValuesOT;
                        if (BasisGradValues.GetLength(2) > Nin)
                        {
                            BasisGradValuesIN = BasisGradValues.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { BasisGradValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1, D - 1 });
                        }
                        else
                        {
                            BasisGradValuesIN = BasisGradValues;
                        }
                        if (BasisGradValues.GetLength(2) > Not)
                        {
                            if (Nin == Not)
                            {
                                BasisGradValuesOT = BasisGradValuesIN;
                            }
                            else
                            {
                                BasisGradValuesOT = BasisGradValues.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { BasisGradValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1, D - 1 });
                            }
                        }
                        else
                        {
                            BasisGradValuesOT = BasisGradValues;
                        }


                        if (AffineLinear)
                        {
                            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            // affine-linear-cell:
                            // Inverse Jacobian different for each cell, but constant among nodes
                            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                            var InvJacobi = grd.iGeomCells.InverseTransformation;

                            Debug.Assert(grd is Grid.Classic.GridData, "implementation only valid for classic grid");
                            Debug.Assert(object.ReferenceEquals(E2Cg, E2Cl));

                            fixed(int *pE2Cl = E2Cl)
                            {
                                {
                                    GradientRef.Multiply(1.0, trfCoördinatesIN, BasisGradValuesIN, 0.0, ref mp_ike_im_Tikme,
                                                         pTrfIndex, pTrfIndex,
                                                         trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates

                                    gradIN.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_ikd_Tied_ike,
                                                    pE2Cl, pE2Cl,
                                                    trfPreOffset_A: (2 * e0), trfCycle_A: 2, trfPostOffset_A: 0, trfPreOffset_B: 0, trfCycle_B: 0, trfPostOffset_B: 0);
                                }

                                if (Not > 0)
                                {
                                    GradientRef.Multiply(1.0, trfCoördinatesOT, BasisGradValuesOT, 0.0, ref mp_ike_im_Tikme,
                                                         pTrfIndex, pTrfIndex,
                                                         trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates

                                    gradOT.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_ikd_Tied_ike,
                                                    pE2Cl, pE2Cl,
                                                    trfPreOffset_A: (2 * e0 + 1), trfCycle_A: 2, trfPostOffset_A: 0, trfPreOffset_B: 0, trfCycle_B: 0, trfPostOffset_B: 0);
                                }
                            }
                        }
                        else
                        {
                            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            // curved-cell:
                            // Inverse Jacobian different for each node and each cell
                            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++

                            MultidimensionalArray invJacobiIN, invJacobiOT;
                            var TiJ = grd.InverseJacobian.GetValue_EdgeDV(NS, e0, Len);
                            invJacobiIN = TiJ.Item1;
                            invJacobiOT = TiJ.Item2;


                            {
                                GradientRef.Multiply(1.0, trfCoördinatesIN, BasisGradValuesIN, 0.0, ref mp_ike_im_Tikme,
                                                     pTrfIndex, pTrfIndex,
                                                     trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates, i.e. \f$ \nabla_{\vec{xi}} \f$

                                gradIN.Multiply(1.0, invJacobiIN, GradientRef, ResultPreScale, ref mp_ikd_iked_ike);                                                     // gradient in physical coördinates, i.e. \f$ \nabla_{\vec{x}}n \f$
                            }

                            if (Not > 0)
                            {
                                GradientRef.Multiply(1.0, trfCoördinatesOT, BasisGradValuesOT, 0.0, ref mp_ike_im_Tikme,
                                                     pTrfIndex, pTrfIndex,
                                                     trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates, i.e. \f$ \nabla_{\vec{xi}} \f$

                                gradOT.Multiply(1.0, invJacobiOT, GradientRef, ResultPreScale, ref mp_ikd_iked_ike);                                                         // gradient in physical coördinates, i.e. \f$ \nabla_{\vec{x}} \f$
                            }
                        }

                        TempBuffer.FreeTempBuffer(iBuf2);
                    }
                }
            }


            TempBuffer.FreeTempBuffer(iBufIN);
            if (Not > 0)
            {
                TempBuffer.FreeTempBuffer(iBufOT);
            }

            /*
             * {
             *  var _BasisValues = grd.ChefBasis.EdgeEval.GetValues(NS, e0, Len, _Basis.Degree);
             *
             *
             *  var resultINAccCheck = valIN.CloneAs();
             *  var resultOTAccCheck = valOT.CloneAs();
             *
             *  for(int e = 0; e < Len; e++) {
             *      int iEdge = e + e0;
             *      int jCellIN = E2C[iEdge, 0];
             *      int jCellOT = E2C[iEdge, 1];
             *      int iTrfIN = trfIdx[iEdge, 0];
             *      int iTrfOT = trfIdx[iEdge, 1];
             *
             *      for(int k = 0; k < NoOfNodes; k++) {
             *          int BN = _Basis.GetLength(jCellIN);
             *
             *          resultINAccCheck[e, k] *= ResultPreScale;
             *          resultOTAccCheck[e, k] *= ResultPreScale;
             *
             *          for(int n = 0; n < BN; n++) {
             *              double Cinerr = trfCoördinatesIN[e, n] - Coord[jCellIN, n];
             *              double Coterr = jCellOT >= 0 ? trfCoördinatesOT[e, n] - Coord[jCellOT, n] : 0.0;
             *
             *              if(Math.Abs(Cinerr) > 1.0e-5)
             *                  Console.WriteLine("44fuckIN" + e);
             *              if(Math.Abs(Coterr) > 1.0e-5)
             *                  Console.WriteLine("44fuckOT" + e);
             *
             *
             *              resultINAccCheck[e, k] += Coord[jCellIN, n] * _BasisValues[iTrfIN, k, n];
             *              if(jCellOT >= 0)
             *                  resultOTAccCheck[e, k] += Coord[jCellOT, n] * _BasisValues[iTrfOT, k, n];
             *
             *          }
             *
             *          double Vinerr = resultINAccCheck[e, k] - valIN[e, k];
             *          double Voterr = jCellOT >= 0 ? resultOTAccCheck[e, k] - valOT[e, k] : 0.0;
             *
             *
             *
             *          if(Math.Abs(Vinerr) > 1.0e-5)
             *              Console.WriteLine("44fuckIN" + e);
             *          if(Math.Abs(Voterr) > 1.0e-5)
             *              Console.WriteLine("44fuckOT" + e);
             *      }
             *
             *  }
             *
             *  //resultINAcc.Set(resultINAccCheck);
             *  //resultOTAcc.Set(resultOTAccCheck);
             * }  */
        }
Exemple #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="CellPairs">
        /// 1st index: list of cells <br/>
        /// 2nd index: in {0, 1}
        /// </param>
        /// <param name="M">
        /// 1st index: corresponds with 1st index of <paramref name="CellPairs"/><br/>
        /// 2nd index: matrix row index <br/>
        /// 3rd index: matrix column index
        /// </param>
        /// <param name="Minv">the inverse of <paramref name="M"/></param>
        /// <remarks>
        /// Let \f$ K_j \f$ and \f$ K_i \f$ be two different cells with a linear-affine
        /// transformation to the reference element.
        /// Here, \f$ j \f$=<paramref name="CellPairs"/>[a,0] and \f$ i \f$=<paramref name="CellPairs"/>[a,1].
        /// The DG-basis in these cells can uniquely be represented as
        /// \f[
        /// \phi_{j n} (\vec{x}) = p_n (\vec{x}) \vec{1}_{K_j} (\vec{x})
        /// \textrm{ and }
        /// \phi_{i m} (\vec{x}) = q_m (\vec{x}) \vec{1}_{K_i} (\vec{x})
        /// \f]
        /// where \f$ \vec{1}_X \f$ denotes the characteristic function for set \f$ X \f$
        /// and \f$ p_n\f$  and \f$ p_m\f$  are polynomials.
        /// Then, for the output \f$ M \f$ =<paramref name="M"/>[a,-,-] fulfills
        /// \f[
        /// \phi_{j n} + \sum_{m} M_{m n} \phi_{i m}
        /// =
        /// p_n \vec{1}_{K_j \cup K_i}
        /// \f]
        /// </remarks>
        public void GetExtrapolationMatrices(int[,] CellPairs, MultidimensionalArray M, MultidimensionalArray Minv = null)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int Esub      = CellPairs.GetLength(0);
            int JE        = this.GridDat.iLogicalCells.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (CellPairs.GetLength(1) != 2)
            {
                throw new ArgumentOutOfRangeException("second dimension is expected to be 2!");
            }
            if (M.Dimension != 3)
            {
                throw new ArgumentException();
            }
            if (M.GetLength(0) != Esub)
            {
                throw new ArgumentException();
            }
            if (M.GetLength(1) != N || M.GetLength(2) != N)
            {
                throw new ArgumentException();
            }
            if (Minv != null)
            {
                if (Minv.GetLength(0) != Esub)
                {
                    throw new ArgumentException();
                }
                if (Minv.GetLength(1) != N || Minv.GetLength(2) != N)
                {
                    throw new ArgumentException();
                }
            }

            MultidimensionalArray NodesGlobal = new MultidimensionalArray(3);
            MultidimensionalArray Minv_tmp    = MultidimensionalArray.Create(N, N);
            MultidimensionalArray M_tmp       = MultidimensionalArray.Create(N, N);


            for (int esub = 0; esub < Esub; esub++)   // loop over the cell pairs...

            {
                int jCell0 = CellPairs[esub, 0];
                int jCell1 = CellPairs[esub, 1];
                if (jCell0 < 0 || jCell0 >= JE)
                {
                    throw new ArgumentOutOfRangeException("Cell index out of range.");
                }
                if (jCell1 < 0 || jCell1 >= JE)
                {
                    throw new ArgumentOutOfRangeException("Cell index out of range.");
                }

                bool swap;
                if (jCell0 >= J)
                {
                    //if(true) {
                    swap = true;
                    int a = jCell0;
                    jCell0 = jCell1;
                    jCell1 = a;
                }
                else
                {
                    swap = false;
                }


                if (!m_Context.iGeomCells.IsCellAffineLinear(jCell0))
                {
                    throw new NotSupportedException("Currently not supported for curved cells.");
                }
                if (!m_Context.iGeomCells.IsCellAffineLinear(jCell1))
                {
                    throw new NotSupportedException("Currently not supported for curved cells.");
                }

                Debug.Assert(jCell0 < J);

                var cellMask = new CellMask(m_Context, new[] { new Chunk()
                                                               {
                                                                   i0 = jCell0, Len = 1
                                                               } }, MaskType.Geometrical);

                // we project the basis function from 'jCell1' onto 'jCell0'

                CellQuadrature.GetQuadrature(new int[2] {
                    N, N
                }, m_Context,
                                             (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree * 2), // integrate over target cell
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) {
                    NodeSet nodes_Cell0 = QR.Nodes;
                    Debug.Assert(Length == 1);

                    NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                    m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0);
                    var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                    m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null);
                    nodes_Cell1.LockForever();


                    var phi_0 = this.CellEval(nodes_Cell0, jCell0, 1).ExtractSubArrayShallow(0, -1, -1);
                    var phi_1 = this.CellEval(nodes_Cell1, jCell1, 1).ExtractSubArrayShallow(0, -1, -1);

                    var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1);

                    EvalResult.Multiply(1.0, phi_1, phi_0, 0.0, "kmn", "kn", "km");
                },
                                             /*_SaveIntegrationResults:*/ delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    Debug.Assert(Length == 1);

                    var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1);
                    Minv_tmp.Clear();
                    Minv_tmp.Acc(1.0, res);
                }).Execute();

                // compute the inverse
                Minv_tmp.InvertTo(M_tmp);

                // store
                if (!swap)
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    }
                }
                else
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// evaluation of DG field gradient; may be used in derived classes to implement <see cref="EvaluateGradient"/>.
        /// </summary>
        protected static void EvaluateGradientInternal(int j0, int L, NodeSet NS, Basis basis, MultidimensionalArray Coördinates, int coördOffset, MultidimensionalArray ResultAcc, double ResultPreScale)
        {
            int  D, N, K;
            bool AffineLinear;

            CheckArgs(j0, L, NS, basis, Coördinates, ResultAcc, out D, out N, out K, out AffineLinear);
            Debug.Assert(ResultAcc.Dimension == 3);
            Debug.Assert(L == ResultAcc.GetLength(0));
            Debug.Assert(K == ResultAcc.GetLength(1));
            Debug.Assert(D == ResultAcc.GetLength(2));

            /*
             * MultidimensionalArray BasisGradValues;
             * BasisGradValues = basis.CellEvalGradient(NS, j0, L);
             *
             * ResultAcc.Multiply(1.0, Coördinates, BasisGradValues, ResultPreScale, "jmd", "jn", "jmnd");
             */

            MultidimensionalArray BasisGradValues = basis.EvaluateGradient(NS);
            int iBuf1, iBuf2;

            if (AffineLinear)
            {
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                // affine-linear-cell:
                // Inverse Jacobian different for each cell, but constant among nodes
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                if (L == 1)
                {
                    // Special optimization for single-cell evaluation:
                    // this happens very often for edge quadrature, so it is quite relevant.
                    double scale0 = basis.GridDat.ChefBasis.Scaling[j0];
                    MultidimensionalArray GradientRef = TempBuffer.GetTempMultidimensionalarray(out iBuf2, L, K, D);
                    MultidimensionalArray InvJacobi   = basis.GridDat.iGeomCells.InverseTransformation.ExtractSubArrayShallow(j0, -1, -1);

                    Debug.Assert(basis.GridDat.iGeomCells.GeomCell2LogicalCell == null || basis.GridDat.iGeomCells.GeomCell2LogicalCell[j0] == j0);
                    MultidimensionalArray Coördinates_j;
                    if (coördOffset == 0 && Coördinates.GetLength(0) == 1)
                    {
                        Coördinates_j = Coördinates;
                    }
                    else
                    {
                        Coördinates_j = Coördinates.ExtractSubArrayShallow(new int[] { coördOffset, 0 }, new int[] { coördOffset, N - 1 });
                    }

                    GradientRef.Multiply(scale0, Coördinates_j, BasisGradValues, 0.0, ref mp_jke_jm_kme);  // gradient in reference coördinates
                    ResultAcc.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_jkd_ed_jke);

                    TempBuffer.FreeTempBuffer(iBuf2);
                }
                else
                {
                    MultidimensionalArray trfCoördinates = TempBuffer.GetTempMultidimensionalarray(out iBuf1, L, N);
                    MultidimensionalArray GradientRef    = TempBuffer.GetTempMultidimensionalarray(out iBuf2, L, K, D);
                    MultidimensionalArray InvJacobi      = basis.GridDat.iGeomCells.InverseTransformation.ExtractSubArrayShallow(new int[] { j0, 0, 0 }, new int[] { j0 + L - 1, D - 1, D - 1 });

                    TransformCoördinates(j0, L, basis, Coördinates, coördOffset, N, AffineLinear, trfCoördinates);
                    GradientRef.Multiply(1.0, trfCoördinates, BasisGradValues, 0.0, ref mp_jke_jm_kme);  // gradient in reference coördinates
                    ResultAcc.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_jkd_jed_jke);

                    TempBuffer.FreeTempBuffer(iBuf1);
                    TempBuffer.FreeTempBuffer(iBuf2);
                }
            }
            else
            {
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++
                // curved-cell:
                // Inverse Jacobian different for each node and each cell
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++

                MultidimensionalArray trfCoördinates = TempBuffer.GetTempMultidimensionalarray(out iBuf1, L, N);
                MultidimensionalArray GradientRef    = TempBuffer.GetTempMultidimensionalarray(out iBuf2, L, K, D);
                MultidimensionalArray InvJacobi      = basis.GridDat.InverseJacobian.GetValue_Cell(NS, j0, L);

                TransformCoördinates(j0, L, basis, Coördinates, coördOffset, N, AffineLinear, trfCoördinates);
                GradientRef.Multiply(1.0, trfCoördinates, BasisGradValues, 0.0, ref mp_jke_jm_kme);  // gradient in reference coördinates
                ResultAcc.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_jkd_jked_jke);

                TempBuffer.FreeTempBuffer(iBuf1);
                TempBuffer.FreeTempBuffer(iBuf2);
            }
        }
Exemple #5
0
            /// <summary>
            /// Integrand evaluation.
            /// </summary>
            protected override void Evaluate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult)
            {
                NodeSet NodesUntransformed = rule.Nodes;
                int     M = NodesUntransformed.GetLength(0);
                int     D = NodesUntransformed.GetLength(1);

                // evaluate scalar function ans store result in 'EvalResult'
                // =========================================================
                Debug.Assert(!((m_func != null) && (m_funcEx != null)));
                if (m_func != null || m_Map != null)
                {
                    GridDat.TransformLocal2Global(NodesUntransformed, i0, Length, m_NodesTransformed, 0);
                }

                if (m_func != null)
                {
                    MultidimensionalArray inp  = m_NodesTransformed.ResizeShallow(new int[] { Length *M, D });
                    MultidimensionalArray outp = EvalResult.ResizeShallow(new int[] { Length *M });
                    m_func(inp, outp);
                    Debug.Assert(m_funcEx == null);
                }
                if (m_funcEx != null)
                {
                    m_funcEx(i0, Length, NodesUntransformed, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                    Debug.Assert(m_func == null);
                }


                if (m_Map == null)
                {
                    // L2 error branch
                    // +++++++++++++++

                    MultidimensionalArray fieldvals = EvalResult.ResizeShallow(new int[] { Length, NodesUntransformed.GetLength(0) });
                    m_Owner.Evaluate(i0, Length, NodesUntransformed, fieldvals, -1.0);

                    for (int j = 0; j < Length; j++)
                    {
                        for (int m = 0; m < M; m++)
                        {
                            double e;
                            e = EvalResult[j, m, 0];
                            EvalResult[j, m, 0] = e * e;
                        }
                    }
                }
                else
                {
                    // arbitrary mapping branch
                    // ++++++++++++++++++++++++

                    MultidimensionalArray fieldvals = MultidimensionalArray.Create(new int[] { Length, NodesUntransformed.GetLength(0) });
                    m_Owner.Evaluate(i0, Length, NodesUntransformed, fieldvals, -1.0);

                    double[] X = new double[D];

                    for (int j = 0; j < Length; j++)
                    {
                        for (int m = 0; m < M; m++)
                        {
                            double e;
                            e = EvalResult[j, m, 0];

                            for (int d = 0; d < D; d++)
                            {
                                X[d] = m_NodesTransformed[j, m, d];
                            }

                            EvalResult[j, m, 0] = this.m_Map(X, fieldvals[j, m], e);
                        }
                    }
                }
            }
Exemple #6
0
        /// <summary>
        /// Returns the minimum and the maximum value of <paramref name="mod"/>(this DG field), for each cell;
        /// </summary>
        /// <param name="max">
        /// Vector, with the same number of entries as the cell mask <paramref name="cm"/>;
        /// On exit, the approximate local maximum within the cell.
        /// </param>
        /// <param name="min">
        /// Vector, with the same number of entries as the cell mask <paramref name="cm"/>;
        /// On exit, the approximate local minimum within the cell.
        /// </param>
        /// <param name="cm">
        /// optional domain restriction
        /// </param>
        /// <param name="mod">
        /// optimal modifier, which e.g. may select the absolute value; if null, the identity function;
        /// </param>
        public void GetCellwiseExtremalValues <T1, T2>(T1 min, T2 max, CellMask cm = null, Func <double, double> mod = null)
            where T1 : IList <double>
            where T2 : IList <double> //
        {
            using (new FuncTrace()) {
                int J   = Basis.GridDat.iLogicalCells.NoOfLocalUpdatedCells;
                int Jcm = cm == null ? J : cm.NoOfItemsLocally;
                if (min.Count != Jcm)
                {
                    throw new ArgumentException("wrong length of output vector", "min");
                }
                if (max.Count != Jcm)
                {
                    throw new ArgumentException("wrong length of output vector", "max");
                }
                min.SetAll(double.MaxValue);
                max.SetAll(double.MinValue);

                if (mod == null)
                {
                    mod = (x => x);
                }

                //int N = m_context.Grid.GridSimplex.NoOfVertices + 1;
                // find maximum on this processor
                // ------------------------------
                // create node set
                if (m_ExtremalProbeNS == null)
                {
                    // nodes for the evaluation of the velocity vector
                    // (all vertices an 0)
                    int D = Basis.GridDat.SpatialDimension;

                    var KrefS = Basis.GridDat.iGeomCells.RefElements;
                    m_ExtremalProbeNS = new NodeSet[KrefS.Length];
                    for (int i = 0; i < KrefS.Length; i++)
                    {
                        m_ExtremalProbeNS[i] = new NodeSet(KrefS[i], KrefS[i].Vertices);
                    }
                }

                // vectorisation of this method
                int VectorSize = -1;
                int N0         = m_ExtremalProbeNS[0].NoOfNodes; // number of nodes
                MultidimensionalArray fieldValues = new MultidimensionalArray(2);


                IEnumerable <Chunk> all_chunks;
                if (cm == null)
                {
                    var _ch = new Chunk[1];
                    _ch[0].i0  = 0;
                    _ch[0].Len = J;
                    all_chunks = _ch;
                }
                else
                {
                    all_chunks = cm;
                }

                int jSub = 0;
                foreach (Chunk chk in all_chunks)
                {
                    VectorSize = this.GridDat.iGeomCells.GetNoOfSimilarConsecutiveCells(CellInfo.RefElementIndex_Mask, chk.i0, Math.Min(100, chk.Len)); // try to be a little vectorized;

                    int _J = chk.Len + chk.i0;
                    for (int j0 = chk.i0; j0 < _J; j0 += VectorSize)
                    {
                        if (j0 + VectorSize > _J)
                        {
                            VectorSize = _J - j0;
                        }
                        int iKref = Basis.GridDat.iGeomCells.GetRefElementIndex(j0);
                        int N     = m_ExtremalProbeNS[iKref].NoOfNodes;

                        if (fieldValues.GetLength(0) != VectorSize || fieldValues.GetLength(1) != N)
                        {
                            fieldValues = MultidimensionalArray.Create(VectorSize, N);
                        }

                        this.Evaluate(j0, VectorSize, m_ExtremalProbeNS[iKref], fieldValues, 0.0);

                        // loop over cells ...
                        for (int jCell = j0; jCell < j0 + VectorSize; jCell++)
                        {
                            // loop over nodes ...
                            for (int n = 0; n < N; n++)
                            {
                                double vel = 0;
                                vel       = mod(fieldValues[jCell - j0, n]);
                                min[jSub] = Math.Min(min[jSub], vel);
                                max[jSub] = Math.Max(max[jSub], vel);
                            }

                            jSub++;
                        }
                    }
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Evaluates all 2nd derivatives (by cell-local analytic derivation of
        /// the basis polynomials) of this field;
        /// </summary>
        /// <param name="j0"></param>
        /// <param name="Len"></param>
        /// <param name="NS"></param>
        /// <param name="result">
        /// <list type="bullet">
        ///   <item>1st index: cell index <em>j</em></item>
        ///   <item>2nd index: node index <em>m</em> into nodeset #<paramref name="NodeSetIndex"/></item>
        ///   <item>3rd index: spatial direction of 1st derivation, <em>k</em></item>
        ///   <item>4th index: spatial direction of 2nd derivation, <em>l</em></item>
        /// </list>
        /// So, the entry [j,m,k,l] = \f$ \frac{\partial}{\partial x_k} \frac{\partial}{\partial x_l} \varphi (\vec{\xi}_m)\f$
        /// where \f$ \vec{xi}_m\f$  is the <em>m</em>-th
        /// vector in the node set #<paramref name="NodeSetIndex"/>, in the
        /// <em>j</em>-th cell.
        /// </param>
        /// <remarks>
        /// Because of 2 derivatives taken, this field needs to be at least of
        /// DG degree 2 to get a non-zero result from this method.
        /// </remarks>
        public void EvaluateHessian(int j0, int Len, NodeSet NS, MultidimensionalArray result)
        {
            int D = this.GridDat.SpatialDimension; // spatial dimension
            int N = m_Basis.GetLength(j0);         // number of coordinates per cell

            if (result.Dimension != 4)
            {
                throw new ArgumentException("dimension must be 4", "result");
            }
            if (Len > result.GetLength(0))
            {
                throw new ArgumentOutOfRangeException("mismatch between Len and 0-th length of result");
            }
            if (result.GetLength(2) != D || result.GetLength(3) != D)
            {
                throw new ArgumentOutOfRangeException("3rd and 4th length of result must be " + D + "x" + D + ";");
            }

            // not very optimized....

            MultidimensionalArray BasisHessian = this.Basis.CellEval2ndDeriv(NS, j0, Len);

            result.Multiply(1.0, this.m_Mda_Coordinates.ExtractSubArrayShallow(new int[] { j0, 0 }, new int[] { j0 + Len - 1, N - 1 }), BasisHessian, 0.0, "jkde", "jn", "jknde");


            /*
             * var scales = this.GridDat.ChefBasis.Scaling;
             * var Tinv = this.GridDat.Cells.InverseTransformation;
             *
             * MultidimensionalArray gbv = Basis.Evaluate2ndDeriv(NS);
             * int M = gbv.GetLength(0); // number of nodes per cell
             * if (result.GetLength(1) != M)
             *  throw new ArgumentException("length of dimension 1 must be " + M, "result");
             *
             * var Coordinates = (MultidimensionalArray)this.Coordinates;
             *
             * double[,] acc = new double[D, D];
             * double[,] Tinv_j = new double[D, D];
             *
             * // loop over cells...
             * for (int j = 0; j < Len; j++) {
             *  double sc = scales[j0 + j];
             *
             *  if (this.GridDat.Cells.IsCellAffineLinear(j0 + j)) {
             *
             *      // load transformation matrix for easier access
             *      for (int d1 = 0; d1 < D; d1++)
             *          for (int d2 = 0; d2 < D; d2++)
             *              Tinv_j[d1, d2] = Tinv[j + j0, d1, d2];
             *
             *      // loop over nodes ...
             *      for (int m = 0; m < M; m++) {
             *
             *          Array.Clear(acc, 0, D * D);
             *
             *          // sum up...
             *          for (int n = 0; n < N; n++) { // loop over basis functions
             *
             *              double coord = Coordinates[j + j0, n];
             *              for (int d1 = 0; d1 < D; d1++) { // 1st loop over spatial dimension
             *                  for (int d2 = 0; d2 < D; d2++) { // 1st loop over spatial dimension
             *                      acc[d1, d2] += gbv[m, n, d1, d2] * coord;
             *                  }
             *              }
             *          }
             *
             *          // transform...
             *          for (int d1 = 0; d1 < D; d1++) {
             *              for (int d2 = 0; d2 < D; d2++) {
             *                  double r = 0.0;
             *                  for (int k1 = 0; k1 < D; k1++) {
             *                      double rr = 0;
             *                      for (int k2 = 0; k2 < D; k2++) {
             *                          rr += acc[k1, k2] * Tinv_j[k2, d1];
             *                      }
             *                      r += rr * Tinv_j[k1, d2];
             *                  }
             *                  result[j, m, d1, d2] = r * sc;
             *              }
             *          }
             *      }
             *  } else {
             *      throw new NotImplementedException("nonlinear cell: todo");
             *  }
             */


            /*
             *
             * //Test code;
             *
             * var HessBasis = this.Basis.CellEval2ndDeriv(NodeSetIndex, j0, Len);
             * var CheckResult = result.CloneAs();
             *
             *
             * for (int j = 0; j < Len; j++) {
             *
             *  // loop over nodes ...
             *  for (int m = 0; m < M; m++) {
             *
             *      for (int d1 = 0; d1 < D; d1++) {
             *          for (int d2 = 0; d2 < D; d2++) {
             *              double accu = 0;
             *
             *              for (int n = 0; n < N; n++) {
             *                  accu += HessBasis[j, m, n, d1, d2]*Coordinates[j + j0, n];
             *              }
             *
             *              CheckResult[j, m, d1, d2] = accu;
             *          }
             *      }
             *
             *  }
             * }
             *
             * CheckResult.Acc(-1.0, result);
             * if (CheckResult.L2Norm() > 1.0e-8)
             *  throw new Exception();
             */
        }
Exemple #8
0
        /// <summary>
        /// Evaluates the field along edges.
        /// </summary>
        /// <param name="ResultIndexOffset">
        /// An offset for the first index of <paramref name="ValueIN"/> resp. <paramref name="ValueOT"/>,
        /// i.e. the first result will be written to
        /// <paramref name="ValueIN"/>[<paramref name="ResultIndexOffset"/>,*].
        /// </param>
        /// <param name="e0">Index of the first edge to evaluate.</param>
        /// <param name="Len">Number of edges to evaluate</param>
        /// <param name="NS">
        /// nodes to evaluate at
        /// </param>
        /// <param name="ValueIN">
        /// If not null, contains the following output:
        /// On exit, the value of the DG field at the given nodes are
        /// <em>accumulated</em> (!) there. Before the values are added,
        /// the original content is scaled by <paramref name="ResultPreScale"/>.<br/>
        /// The array is 2-dimensional:
        /// <list type="bullet">
        ///   <item>
        ///   1st index: edge index <i>j</i> - <paramref name="e0"/>;
        ///   </item>
        ///   <item>
        ///   2nd index: node index <i>k</i>, corresponds with 1st index of
        ///   the node set <paramref name="NS"/>;
        ///   </item>
        /// </list>
        /// </param>
        /// <param name="ValueOUT">
        /// Same as <paramref name="ValueIN"/>.
        /// </param>
        /// <param name="MeanValueIN">
        /// If not null, contains the following output:
        /// On exit, the mean values of the DG field at the given edges are
        /// <em>accumulated</em> (!) there. Before the values are added,
        /// the original content is scaled by <paramref name="ResultPreScale"/>.<br/>
        /// The array is 2-dimensional:
        /// <list type="bullet">
        ///   <item>
        ///   1st index: edge index <i>j</i> - <paramref name="e0"/>;
        ///   </item>
        ///   <item>
        ///   2nd index: node index <i>k</i>, corresponds with 1st index of
        ///   the node set <paramref name="NS"/>;
        ///   </item>
        /// </list>
        /// </param>
        /// <param name="MeanValueOT">
        /// Same as <paramref name="MeanValueIN"/>.
        /// </param>
        /// <param name="GradientIN">
        /// If not null, contains the following output:
        /// On exit, the value of the gradient of DG field at the given nodes
        /// are <em>accumulated</em> (!) there. Before the values are added,
        /// the original content is scaled by <paramref name="ResultPreScale"/>.<br/>
        /// The array is 3-dimensional:
        /// <list type="bullet">
        ///   <item>
        ///   1st index: edge index <i>j</i> - <paramref name="e0"/>;
        ///   </item>
        ///   <item>
        ///   2nd index: node index <i>k</i>, corresponds with 1st index of
        ///   the node set <paramref name="NS"/>;
        ///   </item>
        ///   <item>
        ///   2rd index: spatial dimension;
        ///   </item>
        /// </list>
        /// </param>
        /// <param name="GradientOT">
        /// Same as <paramref name="GradientIN"/>.
        /// </param>
        /// <param name="ResultPreScale">
        /// Scaling that is applied to <paramref name="ValueIN"/> and <paramref name="ValueOUT"/> before
        /// the field evaluation is added
        /// </param>
        public override void EvaluateEdge(int e0, int Len, NodeSet NS,
                                          MultidimensionalArray ValueIN, MultidimensionalArray ValueOT,
                                          MultidimensionalArray MeanValueIN = null, MultidimensionalArray MeanValueOT = null,
                                          MultidimensionalArray GradientIN  = null, MultidimensionalArray GradientOT  = null,
                                          int ResultIndexOffset             = 0, double ResultPreScale = 0.0) //
        {
            int D = GridDat.SpatialDimension;                                                                 // spatial dimension
            int N = m_Basis.Length;                                                                           // number of coordinates per cell
            int K = NS.NoOfNodes;                                                                             // number of nodes

            if ((ValueIN != null) != (ValueOT != null))
            {
                throw new ArgumentException();
            }
            if ((MeanValueIN != null) != (MeanValueOT != null))
            {
                throw new ArgumentException();
            }
            if ((GradientIN != null) != (GradientOT != null))
            {
                throw new ArgumentException();
            }

            if (ValueIN != null)
            {
                if (ValueIN.Dimension != 2)
                {
                    throw new ArgumentException("result", "dimension of result array must be 2");
                }
                if (Len > ValueIN.GetLength(0) + ResultIndexOffset)
                {
                    throw new ArgumentException("mismatch between Len and 0-th length of result");
                }
                if (ValueIN.GetLength(1) != K)
                {
                    throw new ArgumentException();
                }
                if (ValueOT.Dimension != 2)
                {
                    throw new ArgumentException("result", "dimension of result array must be 2");
                }
                if (Len > ValueOT.GetLength(0) + ResultIndexOffset)
                {
                    throw new ArgumentException("mismatch between Len and 0-th length of result");
                }
                if (ValueOT.GetLength(1) != K)
                {
                    throw new ArgumentException();
                }

                if (!(ResultIndexOffset == 0 && Len == ValueIN.GetLength(0)))
                {
                    ValueIN = ValueIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1 });
                }

                if (!(ResultIndexOffset == 0 && Len == ValueOT.GetLength(0)))
                {
                    ValueOT = ValueOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1 });
                }
            }

            if (MeanValueIN != null)
            {
                if (MeanValueIN.Dimension != 1)
                {
                    throw new ArgumentException("Dimension of mean-value result array must be 1.");
                }
                if (Len > MeanValueIN.GetLength(0) + ResultIndexOffset)
                {
                    throw new ArgumentException("mismatch between Len and 0-th length of result");
                }
                if (MeanValueOT.Dimension != 1)
                {
                    throw new ArgumentException("Dimension of mean-value result array must be 1.");
                }
                if (Len > MeanValueOT.GetLength(0) + ResultIndexOffset)
                {
                    throw new ArgumentException("mismatch between Len and 0-th length of result");
                }

                if (!(ResultIndexOffset == 0 && Len == MeanValueIN.GetLength(0)))
                {
                    MeanValueIN = MeanValueIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset }, new int[] { ResultIndexOffset + Len - 1 });
                }

                if (!(ResultIndexOffset == 0 && Len == MeanValueOT.GetLength(0)))
                {
                    MeanValueOT = MeanValueOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset }, new int[] { ResultIndexOffset + Len - 1 });
                }
            }

            if (GradientIN != null)
            {
                if (GradientIN.Dimension != 3)
                {
                    throw new ArgumentException("Dimension of gradient result array must be 3.");
                }
                if (Len > GradientIN.GetLength(0) + ResultIndexOffset)
                {
                    throw new ArgumentException("mismatch between Len and 0-th length of result");
                }
                if (GradientIN.GetLength(1) != K)
                {
                    throw new ArgumentException();
                }
                if (GradientIN.GetLength(2) != D)
                {
                    throw new ArgumentException();
                }
                if (GradientOT.Dimension != 3)
                {
                    throw new ArgumentException("Dimension of gradient result array must be 3.");
                }
                if (Len > GradientOT.GetLength(0) + ResultIndexOffset)
                {
                    throw new ArgumentException("mismatch between Len and 0-th length of result");
                }
                if (GradientOT.GetLength(1) != K)
                {
                    throw new ArgumentException();
                }
                if (GradientOT.GetLength(2) != D)
                {
                    throw new ArgumentException();
                }

                if (!(ResultIndexOffset == 0 && Len == GradientIN.GetLength(0)))
                {
                    GradientIN = GradientIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1, D - 1 });
                }

                if (!(ResultIndexOffset == 0 && Len == GradientOT.GetLength(0)))
                {
                    GradientOT = GradientOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1, D - 1 });
                }
            }


            var coöSys = NS.GetNodeCoordinateSystem(this.GridDat);

            if (coöSys != NodeCoordinateSystem.EdgeCoord)
            {
                throw new ArgumentOutOfRangeException();
            }

            DGField.EvaluateEdgeInternal(e0, Len, NS, this.m_Basis, this.m_Mda_Coordinates,
                                         ValueIN, ValueOT,
                                         MeanValueIN, MeanValueOT,
                                         GradientIN, GradientOT,
                                         ResultPreScale);
        }
Exemple #9
0
        /// <summary>
        /// Evaluates the gradient of all polynomials in this basis (see <see cref="Polynomials"/>) at specified edges.
        /// </summary>
        /// <param name="NS"></param>
        /// <param name="j0">index of first edge to evaluate</param>
        /// <param name="Len">number of cells to evaluate</param>
        /// <returns>
        /// For each 'in'- and 'out'-cell, arrays;<br/>
        /// <list type="bullet">
        ///   <item>1st index: cell index</item>
        ///   <item>2nd index: node index</item>
        ///   <item>3rd index: polynomial index</item>
        ///   <item>4th index: spatial dimension</item>
        /// </list>
        /// </returns>
        public virtual Tuple <MultidimensionalArray, MultidimensionalArray> EdgeEvalGradient(NodeSet NS, int j0, int Len)
        {
            var ret = this.GridDat.ChefBasis.CellBasisGradientValues.GetValue_EdgeDV(NS, j0, Len, this.Degree);

            if (ret.Item1.GetLength(0) != Len)
            {
                int M = ret.Item1.GetLength(1);
                int N = ret.Item1.GetLength(2);
                int D = ret.Item1.GetLength(3);

                ret = new Tuple <MultidimensionalArray, MultidimensionalArray>(
                    ret.Item1.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { Len - 1, M - 1, N - 1, D - 1 }),
                    ret.Item2.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { Len - 1, M - 1, N - 1, D - 1 }));
            }
            return(ret);
        }