Пример #1
0
            /// <summary>
            /// <see cref="Quadrature{U,V}.CreateNodeSetFamily"/>
            /// </summary>
            /// <param name="NoOfItems"></param>
            /// <param name="rule"></param>
            protected override void AllocateBuffers(int NoOfItems, NodeSet rule)
            {
                base.AllocateBuffers(NoOfItems, rule);
                int NoOfNodes = rule.GetLength(0);

                int D = m_phi.GridDat.SpatialDimension;

                m_gradPhi.Allocate(NoOfItems, NoOfNodes, D);
            }
Пример #2
0
            protected override void AllocateBuffers(int NoOfItems, NodeSet rule)
            {
                base.AllocateBuffers(NoOfItems, rule);

                int NoOfNodes = rule.GetLength(0);

                if (m_func != null || m_Map != null)
                {
                    m_NodesTransformed.Allocate(new int[] { NoOfItems, NoOfNodes, GridDat.SpatialDimension });
                }
            }
Пример #3
0
        /// <summary>
        /// Evaluates the modified integrand which is
        /// \f$
        /// \vec{g} = g \frac{\nabla \Phi}{|\nabla \Phi|}
        /// \f$
        /// where g represents <see cref="m_Field"/>.
        /// </summary>
        /// <param name="j0">
        /// <see cref="LevelSetIntegrator.EvaluateIntegrand"/>
        /// </param>
        /// <param name="Length">
        /// <see cref="LevelSetIntegrator.EvaluateIntegrand"/>
        /// </param>
        /// <param name="EvalResult">
        /// <see cref="LevelSetIntegrator.EvaluateIntegrand"/>
        /// </param>
        public override void EvaluateIntegrand(NodeSet N, int j0, int Length, MultidimensionalArray EvalResult)
        {
            using (new FuncTrace()) {
                int D         = base.m_LevSetTrk.GridDat.SpatialDimension; // spatial dimension
                int noOfNodes = EvalResult.GetLength(1);                   // number of nodes

                if (m_LevelSetGradientBuffer.GetLength(0) != Length || m_LevelSetGradientBuffer.GetLength(1) != noOfNodes)
                {
                    m_IntegrandBuffer.Allocate(Length, noOfNodes);
                    m_LevelSetGradientBuffer.Allocate(Length, noOfNodes, D);
                }

                m_Field.Evaluate(j0, Length, N, m_IntegrandBuffer, 0.0);
                m_levSet.EvaluateGradient(j0, Length, N, m_LevelSetGradientBuffer);

                for (int i = 0; i < Length; i++)
                {
                    for (int j = 0; j < noOfNodes; j++)
                    {
                        double AbsGradPhi = 0;

                        for (int d = 0; d < D; d++)
                        {
                            double GradPhi_d = m_LevelSetGradientBuffer[i, j, d];
                            AbsGradPhi += GradPhi_d * GradPhi_d;
                        }
                        AbsGradPhi = Math.Sqrt(AbsGradPhi);
                        double ooAbsGradPhi = 1.0 / AbsGradPhi;

                        for (int d = 0; d < D; d++)
                        {
                            EvalResult[i, j, 0, d] = ooAbsGradPhi * m_LevelSetGradientBuffer[i, j, d] * m_IntegrandBuffer[i, j];
                        }
                    }
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Ctr
        /// </summary>
        public PlanarFourierLevSet(FourierLevSetControl Control) : base(Control)
        {
            setProjectingFourierModes();

            // set the material sample points
            current_interfaceP = new MultidimensionalArray(2);
            current_interfaceP.Allocate(numFp, 2);
            for (int sp = 0; sp < numFp; sp++)
            {
                current_interfaceP[sp, 0] = FourierP[sp];
                current_interfaceP[sp, 1] = current_samplP[sp];
            }
            setInterfaceLength(current_interfaceP);
            InterfaceResolution = interfaceLength / numFp;
        }
Пример #5
0
        protected override SayeQuadRule BuildSurfaceQuadRule(MultidimensionalArray X, double X_weight, int heightDirection, int cell)
        {
            double weight = X_weight;

            NodeSet node = new NodeSet(RefElement, X.To2DArray());
            MultidimensionalArray gradient = lsData.GetLevelSetGradients(node, cell, 1);

            gradient = gradient.ExtractSubArrayShallow(new int[] { 0, 0, -1 });

            MultidimensionalArray jacobian = grid.Jacobian.GetValue_Cell(node, cell, 1).ExtractSubArrayShallow(0, 0, -1, -1);

            //Scale weight
            weight *= gradient.L2Norm() / Math.Abs(gradient[heightDirection]);
            weight /= jacobian[heightDirection, heightDirection];

            MultidimensionalArray weightArr = new MultidimensionalArray(1);

            weightArr.Allocate(1);
            weightArr[0] = weight;
            return(new SayeQuadRule(node, weightArr));
        }
Пример #6
0
            public void Evaluate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
            {
                // Del_Evaluate
                // ~~~~~~~~~~~~~
                NodeSet NS        = QR.Nodes;
                int     NoOfNodes = NS.NoOfNodes;
                var     BasisVal  = b.CellEval(NS, i0, Length);

                EvalResult.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { Length - 1, NoOfNodes - 1, Nnx - 1, Nnx - 1 })
                .Multiply(1.0, BasisVal, BasisVal, 0.0, "ikmn", "ikm", "ikn");

                if (UevalBuf == null)
                {
                    UevalBuf = MultidimensionalArray.Create(Length, NoOfNodes);
                }
                if (UevalBuf.GetLength(0) < Length || UevalBuf.GetLength(1) != NoOfNodes)
                {
                    UevalBuf.Allocate(Length, NoOfNodes);
                }
                MultidimensionalArray _UevalBuf;

                if (UevalBuf.GetLength(0) > Length)
                {
                    _UevalBuf = UevalBuf.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Length - 1, NoOfNodes - 1 });
                }
                else
                {
                    Debug.Assert(UevalBuf.GetLength(0) == Length);
                    _UevalBuf = UevalBuf;
                }

                for (int d = 0; d < D; d++)
                {
                    _UevalBuf.Clear();
                    Uin[d].Evaluate(i0, Length, NS, _UevalBuf);

                    EvalResult.ExtractSubArrayShallow(new int[] { 0, 0, Nnx + d, 0 }, new int[] { Length - 1, NoOfNodes - 1, Nnx + d - 1, Nnx - 1 })
                    .Multiply(1.0, BasisVal, _UevalBuf, 0.0, "ikm", "ikm", "ik");
                }
            }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ctrl"></param>
        public PolarFourierLevSet(FourierLevSetControl ctrl) : base(ctrl)
        {
            this.DomainSize = 2 * Math.PI;

            this.center = new MultidimensionalArray(2);
            this.center.Allocate(1, 2);
            this.center[0, 0] = ctrl.center[0];
            this.center[0, 1] = ctrl.center[1];

            this.CenterMove = ctrl.centerMove;

            this.LevSetForm = ctrl.PLevSetForm;

            this.curvComp_extended = ctrl.curvComp_extended;

            // set material polar coordinates
            interfaceP_polar = new MultidimensionalArray(2);
            interfaceP_polar.Allocate(numFp, 2);
            for (int sp = 0; sp < numFp; sp++)
            {
                interfaceP_polar[sp, 0] = FourierP[sp];
                interfaceP_polar[sp, 1] = current_samplP[sp];
            }

            setProjectingFourierModes();

            // set the material sample points (cartesian)
            current_interfaceP = new MultidimensionalArray(2);
            current_interfaceP.Allocate(numFp, 2);
            for (int sp = 0; sp < numFp; sp++)
            {
                current_interfaceP[sp, 0] = center[0, 0] + (interfaceP_polar[sp, 1] * Math.Cos(interfaceP_polar[sp, 0]));
                current_interfaceP[sp, 1] = center[0, 1] + (interfaceP_polar[sp, 1] * Math.Sin(interfaceP_polar[sp, 0]));
            }
            setInterfaceLength(current_interfaceP);
            InterfaceResolution = interfaceLength / numFp;
        }
Пример #8
0
        void ExtractMatrices()
        {
            // dispose old solver, if required
            // ===============================

            if (this.m_PressureSolver != null)
            {
                this.m_PressureSolver.Dispose();
                this.m_PressureSolver = null;
            }


            // sub-matrices for the Potential Solver
            // =====================================
            int VelocityLength = this.USubMatrixIdx_Row.Length;
            int PressureLength = this.PSubMatrixIdx_Row.Length;


            this.PressureGrad = new MsrMatrix(VelocityLength, PressureLength, 1, 1);
            this.VelocityDiv  = new MsrMatrix(PressureLength, VelocityLength, 1, 1);
            this.Stab         = new MsrMatrix(PressureLength, PressureLength, 1, 1);

            var WholeSystemMatrix = this.m_MgOp.OperatorMatrix;

            WholeSystemMatrix.WriteSubMatrixTo(PressureGrad, USubMatrixIdx_Row, default(int[]), PSubMatrixIdx_Row, default(int[]));
            WholeSystemMatrix.WriteSubMatrixTo(VelocityDiv, PSubMatrixIdx_Row, default(int[]), USubMatrixIdx_Row, default(int[]));
            WholeSystemMatrix.WriteSubMatrixTo(Stab, PSubMatrixIdx_Row, default(int[]), PSubMatrixIdx_Row, default(int[]));



            // inverse mass matrix
            // ===================

            if (this.m_SIMPLEOptions.PotentialSolver_UseMassMatrix)
            {
                // extract the mass-matrix block for the velocity part
                // ---------------------------------------------------
                MsrMatrix MM = new MsrMatrix(this.PressureGrad.RowPartitioning, this.VelocityDiv.ColPartition);
                this.m_MgOp.MassMatrix.WriteSubMatrixTo(MM, this.USubMatrixIdx_Row, default(int[]), this.USubMatrixIdx_Row, default(int[]));

                // invert mass matrix
                // ------------------

                int D = this.LsTrk.GridDat.SpatialDimension;
                this.invMM = new MsrMatrix(MM.RowPartitioning, MM.ColPartition);

                MultidimensionalArray Block    = new MultidimensionalArray(2);
                MultidimensionalArray InvBlock = new MultidimensionalArray(2);

                int   iRow0   = MM.RowPartitioning.i0;
                int   JAGG    = this.m_MgOp.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                int[] DegreeS = this.m_MgOp.Mapping.DgDegree;
                for (int jagg = 0; jagg < JAGG; jagg++) // loop over aggregate cells...
                {
                    for (int d = 0; d < D; d++)         // loop over velocity components...
                    {
                        int N = this.m_MgOp.Mapping.AggBasis[d].GetLength(jagg, DegreeS[d]);
                        if (Block.GetLength(0) != N)
                        {
                            Block.Allocate(N, N);
                            InvBlock.Allocate(N, N);
                        }

                        for (int n = 0; n < N; n++)
                        {
                            CheckMatrix(MM, iRow0, N, iRow0 + n);
                            for (int m = 0; m < N; m++)
                            {
                                Block[n, m] = MM[iRow0 + n, iRow0 + m];
                            }
                        }

                        Block.InvertTo(InvBlock);

                        for (int n = 0; n < N; n++)
                        {
                            for (int m = 0; m < N; m++)
                            {
                                this.invMM[iRow0 + n, iRow0 + m] = InvBlock[n, m];
                            }
                        }

                        iRow0 += N;
                    }
                }

                Debug.Assert(iRow0 == MM.RowPartitioning.iE);

#if DEBUG
                var    CheckMX = MM * invMM;
                double TRESH   = Math.Max(MM.InfNorm(), invMM.InfNorm()) * 1.0e-10;
                for (int iRow = CheckMX.RowPartitioning.i0; iRow < CheckMX.RowPartitioning.iE; iRow++)
                {
                    if (Math.Abs(CheckMX.GetDiagonalElement(iRow) - 1.0) > TRESH)
                    {
                        throw new ArithmeticException("AapproxInverse is not the Inverse of the Aapprox-Matrix");
                    }
                }
#endif
            }
        }
Пример #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="Flds">
        /// a list of <em>M</em> DG fields.
        /// </param>
        /// <param name="Points">
        /// 2-dimensional: <br/>
        ///  - 1st index: point index, from 0 (including) to <em>N</em> (excluding)<br/>
        ///  - 2nd index: spatial dimension/direction
        /// </param>
        /// <param name="Result">
        /// result of the evaluation of the DG fields <paramref name="Flds"/> at points <paramref name="Points"/>.
        ///  - 1st index: point index, from 0 (including) to <em>N</em> (excluding)
        ///  - 2nd index: DG field, from 0 (including) to <em>M</em> (excluding).
        /// the result will be accumulated.
        /// </param>
        /// <param name="UnlocatedPoints">
        /// Optional, can be null; otherwise, an array of length <em>N</em>.
        /// On exit, in the latter case, true for every point that is not within the grid.
        /// </param>
        /// <param name="LocalCellIndices">
        /// Optional, can be null; otherwise, an array of length <em>N</em>.
        /// On exit, in the latter case, the <em>n</em>-th entry contains the local index of the cell
        /// where the <em>n</em>-th point is found.
        /// </param>
        /// <param name="beta">
        /// pre-scaling of <paramref name="Result"/> on entry, i.e. before accumulation
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="Flds"/> for evaluation
        /// </param>
        /// <returns>
        /// the number of points that are not within the grid;
        /// </returns>
        public int Evaluate(double alpha, IEnumerable <DGField> Flds, MultidimensionalArray Points, double beta, MultidimensionalArray Result, BitArray UnlocatedPoints = null, int[] LocalCellIndices = null)
        {
            // init / check args
            // =================

            int D = m_Context.Grid.SpatialDimension;
            int J = m_Context.Grid.NoOfUpdateCells;

            if (Points.Dimension != 2)
            {
                throw new ArgumentException("must be 2-dimensional", "Points");
            }
            int N = Points.GetLength(0);

            if (Result.Dimension != 2)
            {
                throw new ArgumentException("must be 2-dimensional", "Result");
            }
            if (Result.GetLength(0) != N)
            {
                throw new ArgumentException("mismatch in 1st dimension", "Points,Result");
            }
            DGField[] Fields = Flds.ToArray();
            int       M      = Fields.Length;

            for (int m = 0; m < M; m++)
            {
                if (!object.ReferenceEquals(this.m_Context, Fields[m].GridDat))
                {
                    throw new ArgumentException($"Mismatch in grid: field #{m} is defined on a different grid.");
                }
            }

            if (Result.GetLength(1) != Fields.Length)
            {
                throw new ArgumentException("2nd dimension of 'Result' and length of 'Flds' must be equal");
            }


            if (UnlocatedPoints == null)
            {
                UnlocatedPoints = new BitArray(N, false);
            }
            else
            {
                UnlocatedPoints.SetAll(false);
            }

            if (LocalCellIndices != null)
            {
                if (LocalCellIndices.Length != N)
                {
                    throw new ArgumentException("2nd dimension of 'Result' and length of 'LocalCellIndices' must be equal");
                }
                for (int n = 0; n < N; n++)
                {
                    LocalCellIndices[n] = int.MinValue;
                }
            }

            if (UnlocatedPoints.Length != N)
            {
                throw new ArgumentException("2nd dimension of 'Result' and length of 'UnlocatedPoints' must be equal");
            }

            double[] pt = new double[D];

            Result.Scale(beta);

            // build point localization
            // ========================

            // filter points that are outside the grid bounding box
            int[] Perm2 = new int[N];
            {
                int cnt = 0;
                var bb  = CellLoc.GridBB;
                for (int n = 0; n < N; n++)
                {
                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = Points[n, d];
                    }

                    if (!bb.Contains(pt))
                    {
                        UnlocatedPoints[n] = true;
                    }
                    else
                    {
                        Perm2[cnt] = n;
                        cnt++;
                    }
                }

                Array.Resize(ref Perm2, cnt);
            }

            if (Perm2.Length <= 0)
            {
                UnlocatedPoints.SetAll(true);
                return(N); // we are done
            }

            int _cnt = 0;
            MultidimensionalArray pts = MultidimensionalArray.Create(Perm2.Length, D);

            for (int n = 0; n < N; n++)
            {
                if (!UnlocatedPoints[n])
                {
                    for (int d = 0; d < D; d++)
                    {
                        pts[_cnt, d] = Points[n, d];
                    }
                    _cnt++;
                }
            }
            int NU = N - Perm2.Length;

            UnlocatedPoints.SetAll(true);
            N = Perm2.Length;
            int[]             Perm = new int[N];
            int               NoOfUnassignedNodes = N;
            PointLocalization pl = new PointLocalization(pts, CellLoc.GridBB, Perm);

            pts = null; // not required anymore

            // localize Points / evaluate at
            // =============================

            MultidimensionalArray vertGlobalSupect1 = new MultidimensionalArray(2);
            MultidimensionalArray vertGlobalSupect  = new MultidimensionalArray(2);
            MultidimensionalArray vertLocalSuspect  = new MultidimensionalArray(3);
            NodeSet vertLocal = null;

            MultidimensionalArray[] fieldVal = new MultidimensionalArray[M];
            for (int m = 0; m < M; m++)
            {
                fieldVal[m] = new MultidimensionalArray(2);
            }

            //Console.WriteLine("debgcode akt.");
            //int[] bbsfound = new int[Points.GetLength(0)];
            BoundingBox CellTreeBB = new BoundingBox(D);
            BoundingBox CellBB     = new BoundingBox(D);


            // loop over cells ...
            for (int j = 0; j < J; j++)
            {
                // code of the cell: all bounding boxes in the tree that
                // share a point with the cell
                GeomBinTreeBranchCode bbcode; int bbBits;
                {
                    BoundingBoxCode __b = CellLoc.GetCellBoundingBoxCode(j);
                    bbcode = __b.Branch;
                    bbBits = (int)__b.SignificantBits;
                    CellLoc.GridBB.SubBoxFromCode(CellTreeBB, __b);
                }

                // cell bounding box is smaller than the bounding box in the tree
                m_Context.Cells.GetCellBoundingBox(j, CellBB);
                if (!CellTreeBB.Contains(CellBB)) // test
                {
                    throw new ApplicationException("internal error: should not happen");
                }
                CellBB.ExtendByFactor(0.001); // safety factor

                // determine all points in cell
                int iP0, Len;
                pl.GetPointsInBranch(bbcode, bbBits, out iP0, out Len);
                if (Len <= 0)
                {
                    // no points in cell j
                    continue;
                }

                // transform points to cell-local coordinates
                vertGlobalSupect1.Allocate(Len, D);
                double[] tempPt  = new double[D];
                int      tempLen = 0;
                int[]    nPts    = new int[Len];

                for (int n = 0; n < Len; n++)
                {
                    int nPt = Perm2[Perm[n + iP0]];
                    if (!UnlocatedPoints[nPt])
                    {
                        continue;
                    }

                    for (int d = 0; d < D; d++)
                    {
                        tempPt[d] = pl.Points[n + iP0, d];
                    }

                    if (CellBB.Contains(tempPt))
                    {
                        for (int d = 0; d < D; d++)
                        {
                            vertGlobalSupect1[tempLen, d] = tempPt[d];
                        }
                        nPts[tempLen] = nPt;
                        tempLen++;
                    }
                }
                Len = tempLen;
                if (Len <= 0)
                {
                    // no points in cell j
                    continue;
                }

                vertGlobalSupect.Allocate(Len, D);
                vertGlobalSupect.Set(vertGlobalSupect1.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Len - 1, D - 1 }));

                vertLocalSuspect.Allocate(1, Len, D);
                CellLoc.GrdDat.TransformGlobal2Local(vertGlobalSupect, vertLocalSuspect, j, 1, 0);

                // test
                //for (int n = 0; n < Len; n++) {
                //    for (int d = 0; d < D; d++)
                //        pt[d] = vertGlobalSupect[n, d];

                //    if (!CellBB.Contains(pt))
                //        Console.WriteLine("Huramnet");
                //}

                var splx = m_Context.Cells.GetRefElement(j);

                // test whether the points in the bounding box of cell j
                // are also in cell j
                bool[] tatsaechlich = new bool[Len];
                int    Z            = 0;
                for (int n = 0; n < Len; n++)
                {
                    int nPt = nPts[n];

                    if (!UnlocatedPoints[nPt])
                    {
                        // point was already located in/assigned to another cell
                        continue;
                    }

                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = vertGlobalSupect[n, d];
                    }
                    if (!CellBB.Contains(pt))
                    {
                        continue; // cell bounding box is usually smaller than the bounding box in the tree ('bbcode')
                    }

                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = vertLocalSuspect[0, n, d];
                    }
                    if (splx.IsWithin(pt, 1.0e-8))
                    {
                        UnlocatedPoints[nPt] = false;
                        NoOfUnassignedNodes--;

                        if (LocalCellIndices != null)
                        {
                            LocalCellIndices[nPt] = j;
                        }

                        Z++;
                        tatsaechlich[n] = true;
                    }
                }
                if (Z <= 0)
                {
                    // no points in bb
                    continue;
                }

                // collect all vertices that are really in cell j
                vertLocal = new NodeSet(m_Context.Cells.GetRefElement(j), Z, D);
                int z = 0;
                for (int n = 0; n < Len; n++)
                {
                    if (!tatsaechlich[n])
                    {
                        continue;
                    }

                    for (int d = 0; d < D; d++)
                    {
                        vertLocal[z, d] = vertLocalSuspect[0, n, d];
                    }
                    z++;
                }
                vertLocal.LockForever();

                // evaluate Velocity Field there
                for (int m = 0; m < M; m++)
                {
                    fieldVal[m].Allocate(1, Z);
                }

                for (int m = 0; m < M; m++)
                {
                    Fields[m].Evaluate(j, 1, vertLocal, fieldVal[m]);
                }


                // store result of evaluation
                z = 0;
                for (int n = 0; n < Len; n++)
                {
                    //int nPt = Perm2[Perm[n + iP0]];
                    int nPt = nPts[n];

                    if (!tatsaechlich[n])
                    {
                        continue;
                    }

                    for (int m = 0; m < M; m++)
                    {
                        Result[nPt, m] += alpha * fieldVal[m][0, z];
                    }

                    z++;
                }
            }

            // return
            // ======
            return(NoOfUnassignedNodes + NU);
        }
Пример #10
0
        private void ApproximationMatrix()
        {
            this.Aapprox        = null;
            this.AapproxInverse = null;

            //MsrMatrix AapproxComp = null;

            /*
             * switch(m_SIMPLEOptions.Option_Approximation_Predictor) {
             *  case ApproxPredictor.MassMatrix:
             *  case ApproxPredictor.LocalizedOperator: { break; }
             *  default: {
             *      Aapprox = ConvDiff.CloneAs();
             *      //switch (m_SIMPLEOptions.Option_Timestepper) {
             *      //    case Timestepper.Steady: break;
             *      //    case Timestepper.ImplicitEuler: {
             *      //            Aapprox.Acc(1.0 / dt, MassMatrix);
             *      //            break;
             *      //        }
             *      //    default: {
             *      //            throw new NotImplementedException("Unknown Timestepper");
             *      //        }
             *      //}
             *      AapproxComp = new MsrMatrix(USubMatrixIdx.Length, USubMatrixIdx.Length, MassMatrix.RowPartitioning.BlockSize / (2 * D), MassMatrix.ColPartition.BlockSize / (2 * D));
             *      Aapprox.WriteSubMatrixTo(AapproxComp, USubMatrixIdx, default(int[]), USubMatrixIdx, default(int[]));
             *      break;
             *  }
             * }
             */
            switch (m_SIMPLEOptions.Option_Approximation_Predictor)
            {
            case ApproxPredictor.MassMatrix: {
                BlockMsrMatrix MM;
                if (!double.IsPositiveInfinity(this.m_SIMPLEOptions.dt))
                {
                    // instationary SIMPLE

                    //MM = this.m_MgOp.MassMatrix.CloneAs();


                    // hier muss ich mir nochmal was überlegen --
                    // für einige Präkond.-Optionen
                    // (genau jene, welche die XDG-Basen für beide Phasen in Cut-Zellen mischen),
                    // wie etwa
                    //   MultigridOperator.Mode.SymPart_DiagBlockEquilib
                    // ist eine Block-Skalierung mit rho_A und rho_B
                    // inkonsistent!
                    //

                    throw new NotImplementedException("todo");
                }
                else
                {
                    MM = this.m_MgOp.MassMatrix;
                }
                Aapprox = new MsrMatrix(this.ConvDiff.RowPartitioning);
                this.m_MgOp.MassMatrix.WriteSubMatrixTo(Aapprox, this.USubMatrixIdx_Row, default(int[]), this.USubMatrixIdx_Row, default(int[]));

                //AapproxInverse = MassMatrixInv._ToMsrMatrix();// Aapprox.Invert();
                //switch(m_SIMPLEOptions.Option_Timestepper) {
                //    case Timestepper.Steady: break;
                //    case Timestepper.ImplicitEuler: {
                //        Aapprox.Scale(1 + 1.0 / dt);
                //        AapproxInverse.Scale(1 / (1 + 1.0 / dt));
                //        /*#if DEBUG
                //                                            var CheckMX = AapproxInverse * Aapprox;
                //                                            foreach (int i in USubMatrixIdx) {
                //                                                if (Math.Abs(CheckMX.GetDiagonalElement(i) - 1.0) > 1e-10) throw new ArithmeticException("AapproxInverse is not the Inverse of the Aapprox-Matrix");
                //                                            }

                //        #endif*/
                //        break;
                //    }
                //    default: {
                //        throw new NotImplementedException("Unknown Timestepper");
                //    }
                //}
                break;
            }

            case ApproxPredictor.Exact: {
                if (this.LsTrk.GridDat.CellPartitioning.MpiSize > 1)
                {
                    throw new NotSupportedException("Not implemented for MPI-parallel runs.");
                }

                //RowIdx = VelocityMapping.GetSubvectorIndices(this.LsTrk, D.ForLoop(d => d), _SpcIds: this.LsTrk.SpeciesIdS, drk: this.TransportAgglomerator);
                //ColIdx = RowIdx;

                if (USubMatrixIdx_Row.Length > 4500)
                {
                    Console.WriteLine(string.Format("WARNING: you don't really want to invert a {0}x{0} matrix.", USubMatrixIdx_Row.Length));
                }

                this.Aapprox = this.ConvDiff;

                MultidimensionalArray AapproxFull        = Aapprox.ToFullMatrixOnProc0();
                MultidimensionalArray AapproxInverseFull = AapproxFull.GetInverse();
                this.AapproxInverse = new MsrMatrix(new Partitioning(USubMatrixIdx_Row.Length));
                this.AapproxInverse.AccDenseMatrix(1.0, AapproxInverseFull);
                break;
            }

            case ApproxPredictor.Diagonal: {
                /*
                 * Aapprox = new MsrMatrix(ConvDiff.RowPartitioning, ConvDiff.ColPartition);
                 * AapproxInverse = new MsrMatrix(ConvDiff.RowPartitioning, ConvDiff.ColPartition);
                 * foreach(int i in USubMatrixIdx) {
                 *  int[] j = new int[] { i };
                 *  double Value = ConvDiff.GetValues(i, j)[0];
                 *  //Value += MassMatrix.GetValues(i, j)[0];
                 *  Aapprox.SetDiagonalElement(i, Value);
                 *  if(Value == 0) {
                 *      AapproxInverse.SetDiagonalElement(i, 0);
                 *  } else {
                 *      AapproxInverse.SetDiagonalElement(i, 1 / Value);
                 *  }
                 * }
                 #if DEBUG
                 * Aapprox.VerifyDataStructure();
                 * AapproxInverse.VerifyDataStructure();
                 * var CheckMX = AapproxInverse * Aapprox;
                 * foreach(int i in USubMatrixIdx) {
                 *  if(Math.Abs(CheckMX.GetDiagonalElement(i) - 1.0) > 1e-13) throw new ArithmeticException("AapproxInverse is not the Inverse of the Operator Matrix");
                 * }
                 #endif
                 * break;
                 */
                throw new NotImplementedException("todo");
            }

            case ApproxPredictor.BlockDiagonal: {
                /*
                 * AapproxInverse = new MsrMatrix(Aapprox.RowPartitioning, Aapprox.ColPartition);
                 * var AapproxCompBD = new BlockDiagonalMatrix(AapproxComp);
                 * var AapproxCompInvBD = AapproxCompBD.Invert();
                 * AapproxCompBD._ToMsrMatrix().WriteSubMatrixTo(Aapprox, default(int[]), USubMatrixIdx, default(int[]), USubMatrixIdx);
                 * AapproxCompInvBD._ToMsrMatrix().WriteSubMatrixTo(AapproxInverse, default(int[]), USubMatrixIdx, default(int[]), USubMatrixIdx);
                 * //#if DEBUG
                 * Aapprox.VerifyDataStructure();
                 * AapproxInverse.VerifyDataStructure();
                 * var CheckMX = AapproxInverse * Aapprox;
                 * foreach(int i in USubMatrixIdx) {
                 *  if(Math.Abs(CheckMX.GetDiagonalElement(i) - 1.0) > 1e-12) throw new ArithmeticException("AapproxInverse is not the Inverse of the Operator Matrix");
                 * }
                 * //#endif
                 *
                 * break;
                 */
                throw new NotImplementedException("todo");
            }

            case ApproxPredictor.BlockSum: {
                /*
                 * Console.WriteLine("BlockSum is not properly tested yet and did not work in previous tests");
                 * int AccdBlockSize = ConvDiff.RowPartitioning.BlockSize / (2 * D);
                 * var AapproxBD = new BlockDiagonalMatrix(ConvDiff.RowPartitioning);
                 * var Aapprox = new MsrMatrix(ConvDiff.RowPartitioning);
                 * int[] indexer = new int[AccdBlockSize];
                 * for(int i = 0; i < indexer.Length; i++) {
                 *  indexer[i] = i;
                 * }
                 * int[] rowindexer = indexer.CloneAs();
                 *
                 *
                 * for(int i = 0; i < ConvDiff.NoOfRows / AccdBlockSize; i++) {
                 *  int[] colindexer = indexer.CloneAs();
                 *  for(int j = 0; j < ConvDiff.NoOfCols / AccdBlockSize; j++) {
                 *      ConvDiff.AccSubMatrixTo(1.0, Aapprox, rowindexer, rowindexer, colindexer, rowindexer);
                 *      for(int r = 0; r < indexer.Length; r++) {
                 *          colindexer[r] += AccdBlockSize;
                 *      }
                 *  }
                 *  for(int r = 0; r < indexer.Length; r++) {
                 *      rowindexer[r] += AccdBlockSize;
                 *  }
                 * }
                 * //if (m_SIMPLEOptions.Option_Timestepper == Timestepper.ImplicitEuler) {
                 * //    Aapprox.Acc(1 / dt, MassMatrix);
                 * //}
                 * AapproxComp = new MsrMatrix(USubMatrixIdx.Length, USubMatrixIdx.Length, AccdBlockSize, AccdBlockSize);
                 * Aapprox.WriteSubMatrixTo(AapproxComp, USubMatrixIdx, default(int[]), USubMatrixIdx, default(int[]));
                 * AapproxInverse = new MsrMatrix(Aapprox.RowPartitioning, Aapprox.ColPartition);
                 * var AapproxCompBD = new BlockDiagonalMatrix(AapproxComp);
                 * var AapproxCompInvBD = AapproxCompBD.Invert();
                 * AapproxCompInvBD._ToMsrMatrix().WriteSubMatrixTo(AapproxInverse, default(int[]), USubMatrixIdx, default(int[]), USubMatrixIdx);
                 #if DEBUG
                 * Aapprox.VerifyDataStructure();
                 * AapproxInverse.VerifyDataStructure();
                 *
                 * // Check copying back and forth
                 * var CheckAapproxComp = new MsrMatrix(Aapprox.RowPartitioning, Aapprox.ColPartition);
                 * AapproxComp.WriteSubMatrixTo(CheckAapproxComp, default(int[]), USubMatrixIdx, default(int[]), USubMatrixIdx);
                 * CheckAapproxComp.Acc(-1.0, Aapprox);
                 * if(CheckAapproxComp.InfNorm() > 1e-14) throw new ArithmeticException("Something went wrong while copying the Aapprox Matrix");
                 *
                 * //Check Transformation to BlockdiagonalMatrix
                 * var CheckAapproxCompBD = new MsrMatrix(Aapprox.RowPartitioning, Aapprox.ColPartition);
                 * AapproxCompBD._ToMsrMatrix().WriteSubMatrixTo(CheckAapproxCompBD, default(int[]), USubMatrixIdx, default(int[]), USubMatrixIdx);
                 * CheckAapproxCompBD.Acc(-1.0, Aapprox);
                 * if(CheckAapproxCompBD.InfNorm() > 1e-14) throw new ArithmeticException("Something went wrong while copying the Aapprox Matrix");
                 *
                 * //Check Matrix Inversion
                 * var CheckMX = AapproxInverse * Aapprox;
                 * foreach(int i in USubMatrixIdx) {
                 *  if(Math.Abs(CheckMX.GetDiagonalElement(i) - 1.0) > 1e-12) throw new ArithmeticException("AapproxInverse is not the Inverse of the Operator Matrix");
                 * }
                 #endif
                 * break;
                 */
                throw new NotImplementedException("todo");
            }

            case ApproxPredictor.Neumann: {
                /*
                 * Console.WriteLine("Neumann did not work in previous Tests, Series does typically not converge");
                 * int serieslength = 10;
                 *
                 * Aapprox = ConvDiff.CloneAs();
                 * //if (m_SIMPLEOptions.Option_Timestepper != Timestepper.Steady) {
                 * //    Aapprox.Acc(1.0 / dt, MassMatrix);
                 * //}
                 * var B = Aapprox.CloneAs();
                 * double ScalingFactor = Aapprox.InfNorm();
                 * B.Scale((-1.0 / ScalingFactor.Pow(0))); //Scaling Power up to 4 tried
                 * B.AccEyeSp(1.0);
                 * AapproxInverse = B;
                 * AapproxInverse.AccEyeSp(1.0);
                 * MsrMatrix OldMoment = B;
                 * for(int i = 0; i <= serieslength; i++) {
                 *  var NewMoment = OldMoment * B;
                 *  AapproxInverse.Acc(1.0, NewMoment);
                 *  //Debug
                 *  Console.WriteLine("MomentNumber #{0}, InfNormOf Inverse #{1}", i, NewMoment.InfNorm());
                 *  OldMoment = NewMoment;
                 * }
                 * AapproxInverse.Scale((1.0 / ScalingFactor.Pow(0))); //Scaling Power up to 4 tried
                 * break;
                 */
                throw new NotImplementedException("todo");
            }

            case ApproxPredictor.LocalizedOperator: {
                /*
                 * Console.WriteLine("Localized Operator did not work in previous Tests");
                 * double[] LocalizedOpAffine;
                 * MultiphaseCellAgglomerator LocalizedAgglomerator;
                 * Aapprox = new MsrMatrix(MassMatrix.RowPartitioning, MassMatrix.ColPartition);
                 * TransportOpLocalized.AssembleMatrix(
                 *  out Aapprox, out LocalizedOpAffine,
                 *  out LocalizedAgglomerator, out TransportMassFact,
                 *  this.Velocity.Current, null,
                 *  this.LevSet, null, Curv,
                 *  VelocityMapping, VelocityMapping);
                 * if(Option_Timestepper == Timestepper.ImplicitEuler) {
                 *  Aapprox.Acc(1 / dt, MassMatrix);
                 * }
                 *
                 * var DiagAverage = Aapprox.GetDiagVector().Average();
                 * foreach(int i in RowIdx) {
                 *  if(Aapprox.GetDiagonalElement(i) == 0.0) {
                 *      //Aapprox.SetDiagonalElement(i, MassMatrix.GetDiagonalElement(i));
                 *      Aapprox.SetDiagonalElement(i, DiagAverage);
                 *  }
                 * }
                 * AapproxComp = new MsrMatrix(RowIdx.Length, RowIdx.Length, MassMatrix.RowPartitioning.BlockSize / (2 * D), MassMatrix.ColPartition.BlockSize / (2 * D));
                 * Aapprox.WriteSubMatrixTo(AapproxComp, RowIdx, default(int[]), ColIdx, default(int[]));
                 * AapproxInverse = new MsrMatrix(Aapprox.RowPartitioning, Aapprox.ColPartition);
                 * var AapproxCompBD = new BlockDiagonalMatrix(AapproxComp);
                 * var AapproxCompInvBD = AapproxCompBD.Invert();
                 * AapproxCompInvBD._ToMsrMatrix().WriteSubMatrixTo(AapproxInverse, default(int[]), RowIdx, default(int[]), ColIdx);
                 * //AapproxComp._ToMsrMatrix().WriteSubMatrixTo(Aapprox, default(int[]), RowIdx, default(int[]), ColIdx);
                 *
                 *
                 #if DEBUG
                 * Aapprox.VerifyDataStructure();
                 * AapproxInverse.VerifyDataStructure();
                 * var CheckAapproxCompBD = new MsrMatrix(Aapprox.RowPartitioning, Aapprox.ColPartition);
                 * AapproxCompBD._ToMsrMatrix().WriteSubMatrixTo(CheckAapproxCompBD, default(int[]), RowIdx, default(int[]), ColIdx);
                 * CheckAapproxCompBD.Acc(-1.0, Aapprox);
                 * if(CheckAapproxCompBD.InfNorm() > 1e-14) throw new ArithmeticException("Something went wrong while copying the Aapprox Matrix");
                 * var CheckMX = AapproxInverse * Aapprox;
                 * foreach(int i in RowIdx) {
                 *  if(Math.Abs(CheckMX.GetDiagonalElement(i) - 1.0) > 1e-12) throw new ArithmeticException("AapproxInverse is not the Inverse of the Operator Matrix");
                 * }
                 #endif
                 * break;
                 */
                throw new NotImplementedException("todo");
            }

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


            if (this.AapproxInverse == null)
            {
                // block-inversion is required.
                // ++++++++++++++++++++++++++++

                int D = this.LsTrk.GridDat.SpatialDimension;
                this.AapproxInverse = new MsrMatrix(this.Aapprox.RowPartitioning, this.Aapprox.ColPartition);

                //int N = this.m_MgOp.Mapping.AggBasis.GetMinimalLength(this.m_MgOp.Mapping.DgDegree[0]);
                //Debug.Assert(this.Aapprox.RowPartitioning.LocalLength % N == 0);
                MultidimensionalArray Block    = new MultidimensionalArray(2);
                MultidimensionalArray InvBlock = new MultidimensionalArray(2);


                int   iRow0   = this.Aapprox.RowPartitioning.i0;
                int   JAGG    = this.m_MgOp.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                int[] DegreeS = this.m_MgOp.Mapping.DgDegree;
                for (int jagg = 0; jagg < JAGG; jagg++) // loop over aggregate cells...
                {
                    for (int d = 0; d < D; d++)         // loop over velocity components...
                    {
                        int N = this.m_MgOp.Mapping.AggBasis[d].GetLength(jagg, DegreeS[d]);
                        if (Block.GetLength(0) != N)
                        {
                            Block.Allocate(N, N);
                            InvBlock.Allocate(N, N);
                        }

                        for (int n = 0; n < N; n++)
                        {
#if DEBUG
                            int iRow = iRow0 + n;
                            {
                                int[]    Cols = null;
                                double[] Vals = null;
                                int      LR   = Aapprox.GetRow(iRow, ref Cols, ref Vals);
                                int      cMin = int.MaxValue;
                                int      cMax = int.MinValue;
                                for (int lr = 0; lr < LR; lr++)
                                {
                                    if (Vals[lr] != 0.0)
                                    {
                                        cMin = Math.Min(cMin, Cols[lr]);
                                        cMax = Math.Max(cMax, Cols[lr]);
                                    }
                                }
                                Debug.Assert(cMin >= iRow0);
                                Debug.Assert(cMax < iRow0 + N);
                            }
#endif
                            for (int m = 0; m < N; m++)
                            {
                                Block[n, m] = this.Aapprox[iRow0 + n, iRow0 + m];
                            }
                        }

                        Block.InvertTo(InvBlock);

                        for (int n = 0; n < N; n++)
                        {
                            for (int m = 0; m < N; m++)
                            {
                                this.AapproxInverse[iRow0 + n, iRow0 + m] = InvBlock[n, m];
                            }
                        }

                        iRow0 += N;
                    }
                }

                Debug.Assert(iRow0 == this.Aapprox.RowPartitioning.iE);
            }

#if DEBUG
            var    CheckMX = AapproxInverse * Aapprox;
            double TRESH   = Math.Max(AapproxInverse.InfNorm(), Aapprox.InfNorm()) * 1.0e-10;
            for (int iRow = CheckMX.RowPartitioning.i0; iRow < CheckMX.RowPartitioning.iE; iRow++)
            {
                if (Math.Abs(CheckMX.GetDiagonalElement(iRow) - 1.0) > TRESH)
                {
                    throw new ArithmeticException("AapproxInverse is not the Inverse of the Aapprox-Matrix");
                }
            }
#endif
        }
Пример #11
0
        private double[] ComputeBenchmarkQuantities()
        {
            int order = 0;

            if (CorrectionLsTrk.GetCachedOrders().Count > 0)
            {
                order = CorrectionLsTrk.GetCachedOrders().Max();
            }
            else
            {
                order = 1;
            }
            var SchemeHelper = CorrectionLsTrk.GetXDGSpaceMetrics(CorrectionLsTrk.SpeciesIdS.ToArray(), order, 1).XQuadSchemeHelper;

            // area of bubble
            double    area  = 0.0;
            SpeciesId spcId = CorrectionLsTrk.SpeciesIdS[1];
            var       vqs   = SchemeHelper.GetVolumeQuadScheme(spcId);

            CellQuadrature.GetQuadrature(new int[] { 1 }, CorrectionLsTrk.GridDat,
                                         vqs.Compile(CorrectionLsTrk.GridDat, order),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                EvalResult.SetAll(1.0);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    area += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            area = area.MPISum();

            // surface
            double surface = 0.0;
            //CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());
            var surfElemVol = SchemeHelper.Get_SurfaceElement_VolumeQuadScheme(spcId);

            CellQuadrature.GetQuadrature(new int[] { 1 }, CorrectionLsTrk.GridDat,
                                         surfElemVol.Compile(CorrectionLsTrk.GridDat, this.m_HMForder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                EvalResult.SetAll(1.0);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    surface += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            surface = surface.MPISum();

            // circularity
            double diamtr_c  = Math.Sqrt(4 * area / Math.PI);
            double perimtr_b = surface;

            double circ = Math.PI * diamtr_c / perimtr_b;

            // total concentration, careful above values are "old" when CorrectionTracker is not updated, this value is always "new"
            double concentration = 0.0;
            var    tqs           = new CellQuadratureScheme();

            CellQuadrature.GetQuadrature(new int[] { 1 }, phi.GridDat,
                                         tqs.Compile(phi.GridDat, phi.Basis.Degree * 2 + 2),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                phi.Evaluate(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    concentration += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            concentration = concentration.MPISum();

            // total mixing energy
            double energy = 0.0;
            var    eqs    = new CellQuadratureScheme();

            int D = phi.GridDat.SpatialDimension;

            SinglePhaseField[] PhiGrad = new SinglePhaseField[D];
            for (int d = 0; d < D; d++)
            {
                PhiGrad[d] = new SinglePhaseField(phi.Basis, string.Format("G_{0}", d));
                PhiGrad[d].Derivative(1.0, phi, d);
            }

            MultidimensionalArray _Phi      = new MultidimensionalArray(2);
            MultidimensionalArray _GradPhi  = new MultidimensionalArray(3);
            MultidimensionalArray _NormGrad = new MultidimensionalArray(2);

            CellQuadrature.GetQuadrature(new int[] { 1 }, phi.GridDat,
                                         eqs.Compile(phi.GridDat, phi.Basis.Degree * 2 + 2),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                int K = EvalResult.GetLength(1);
                // alloc buffers
                // -------------

                if (_Phi.GetLength(0) != Length || _Phi.GetLength(1) != K)
                {
                    _Phi.Allocate(Length, K);
                    _GradPhi.Allocate(Length, K, D);
                    _NormGrad.Allocate(Length, K);
                }
                else
                {
                    _Phi.Clear();
                    _GradPhi.Clear();
                    _NormGrad.Clear();
                }

                // chemical potential
                phi.Evaluate(i0, Length, QR.Nodes, _Phi.ExtractSubArrayShallow(-1, -1));
                _Phi.ApplyAll(x => 0.25 / (this.Control.cahn.Pow2()) * (x.Pow2() - 1.0).Pow2());

                for (int d = 0; d < D; d++)
                {
                    PhiGrad[d].Evaluate(i0, Length, QR.Nodes, _GradPhi.ExtractSubArrayShallow(-1, -1, d));
                }

                // free surface energy
                for (int d = 0; d < D; d++)
                {
                    var GradPhi_d = _GradPhi.ExtractSubArrayShallow(-1, -1, d);
                    _NormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                }
                _NormGrad.ApplyAll(x => 0.5 * x);

                EvalResult.ExtractSubArrayShallow(-1, -1, 0).Acc(1.0, _Phi);
                EvalResult.ExtractSubArrayShallow(-1, -1, 0).Acc(1.0, _NormGrad);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    energy += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            energy = energy.MPISum();

            // replace 1.96 (RB_TC2) with actual surface tension
            // see Yue (2004)
            double lambda = this.Control.cahn.Pow2() * 1.96 * surface / energy;

            return(new double[] { area, surface, circ, concentration, energy, lambda, this.Control.diff });
        }
Пример #12
0
 /// <summary>
 /// Allocates memory for <see cref="m_WeightBuffer"/>.
 /// </summary>
 protected override void AllocateBuffers(int NoOfItems, NodeSet ruleNodes)
 {
     base.AllocateBuffers(NoOfItems, ruleNodes);
     m_WeightBuffer.Allocate(NoOfItems, ruleNodes.GetLength(0));
 }
Пример #13
0
        /// <summary>
        /// for a cloud of points, this method finds the cells which contain the points
        /// </summary>
        /// <param name="_pts">
        /// Input: a cloud of points; 1st index: point index, 2nd index: spatial dimension;
        /// </param>
        /// <param name="LocalCellIdx">
        /// Output: for each point in <paramref name="_pts"/>, the the (local) index of the cell which contains the specific point
        /// </param>
        /// <param name="NoOfUnassigned">
        /// on exit, the number of points which cannot be assigned to one cell
        /// </param>
        public void LocalizePointsWithinGrid <T>(MultidimensionalArray _pts, T LocalCellIdx, out int NoOfUnassigned) where T : IList <int>
        {
            using (new FuncTrace()) {
                // init and check
                // ==============

                NoOfUnassigned = 0;

                GridData grd     = this.GrdDat;
                var      CellLoc = this;
                var      splxS   = grd.Grid.RefElements;

                int D = grd.SpatialDimension;
                int N = _pts.GetLength(0);
                if (_pts.Dimension != 2)
                {
                    throw new ArgumentException();
                }
                if (_pts.GetLength(0) != LocalCellIdx.Count)
                {
                    throw new ArgumentException();
                }
                if (_pts.GetLength(1) != D)
                {
                    throw new ArgumentException();
                }

                var UnlocatedPoints = new BitArray(N, false);

                int J = grd.Cells.NoOfLocalUpdatedCells;

                double[] pt = new double[D];


                // build point localization
                // ========================

                // filter points that are outside the grid bounding box
                int[] Perm2 = new int[N];
                {
                    int cnt = 0;
                    var bb  = CellLoc.GridBB;
                    for (int n = 0; n < N; n++)
                    {
                        _pts.ExtractVector(pt, 1, 0, D, n, 0);
                        //for (int d = 0; d < D; d++)
                        //    pt[d] = Points[n, d];

                        if (!bb.Contains(pt))
                        {
                            UnlocatedPoints[n] = true;
                            NoOfUnassigned++;
                        }
                        else
                        {
                            Perm2[cnt] = n;
                            cnt++;
                        }
                    }

                    Array.Resize(ref Perm2, cnt);
                }

                if (Perm2.Length <= 0)
                {
                    // all points are outside the bounding box of the grid !
                    LocalCellIdx.SetAll(int.MinValue);
                    return; // we are done
                }

                int _cnt = 0;
                MultidimensionalArray pts = MultidimensionalArray.Create(Perm2.Length, D);
                for (int n = 0; n < N; n++)
                {
                    if (!UnlocatedPoints[n])
                    {
                        for (int d = 0; d < D; d++)
                        {
                            pts[_cnt, d] = _pts[n, d];
                        }
                        _cnt++;
                    }
                }
                int NU = N - Perm2.Length;

                UnlocatedPoints.SetAll(true);
                N = Perm2.Length;
                int[]             Perm = new int[N];
                int               NoOfUnassignedNodes = N;
                PointLocalization pl = new PointLocalization(pts, CellLoc.GridBB, Perm);
                pts = null; // not required anymore


                // localize Points / evaluate at
                // =============================

                MultidimensionalArray vertGlobalSupect = new MultidimensionalArray(2);
                MultidimensionalArray vertLocalSuspect = new MultidimensionalArray(3);


                BoundingBox CellTreeBB = new BoundingBox(D);
                BoundingBox CellBB     = new BoundingBox(D);


                // loop over cells ...
                for (int j = 0; j < J; j++)
                {
                    // code of the cell: all bounding boxes in the tree that
                    // share a point with the cell
                    GeomBinTreeBranchCode bbcode; int bbBits;
                    {
                        BoundingBoxCode __b = CellLoc.GetCellBoundingBoxCode(j);
                        bbcode = __b.Branch;
                        bbBits = (int)__b.SignificantBits;
                        CellLoc.GridBB.SubBoxFromCode(CellTreeBB, __b);
                    }

                    // cell bounding box is smaller than the bounding box in the tree
                    grd.Cells.GetCellBoundingBox(j, CellBB);
                    if (!CellTreeBB.Contains(CellBB)) // test
                    {
                        throw new ApplicationException("internal error: should not happen");
                    }
                    CellBB.ExtendByFactor(0.001); // safety factor

                    // determine all points in cell
                    int iP0, Len;
                    pl.GetPointsInBranch(bbcode, bbBits, out iP0, out Len);
                    if (Len <= 0)
                    {
                        // no points in cell j
                        continue;
                    }

                    // transform points to cell-local coordinates
                    vertGlobalSupect.Allocate(Len, D);
                    vertLocalSuspect.Allocate(1, Len, D);
                    for (int n = 0; n < Len; n++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            vertGlobalSupect[n, d] = pl.Points[n + iP0, d];
                        }
                    }
                    CellLoc.GrdDat.TransformGlobal2Local(vertGlobalSupect, vertLocalSuspect, j, 1, 0);

                    var Kref = grd.Cells.GetRefElement(j);

                    // test whether the points in the bounding box of cell j
                    // are also in cell j
                    for (int n = 0; n < Len; n++)
                    {
                        int nPt = Perm2[Perm[n + iP0]];

                        if (!UnlocatedPoints[nPt])
                        {
                            // point was already located in/assigned to another cell
                            continue;
                        }

                        for (int d = 0; d < D; d++)
                        {
                            pt[d] = vertGlobalSupect[n, d];
                        }
                        if (!CellBB.Contains(pt))
                        {
                            continue; // cell bounding box is usually smaller than the bounding box in the tree ('bbcode')
                        }

                        for (int d = 0; d < D; d++)
                        {
                            pt[d] = vertLocalSuspect[0, n, d];
                        }
                        if (Kref.IsWithin(pt))
                        {
                            UnlocatedPoints[nPt] = false;
                            NoOfUnassignedNodes--;

                            LocalCellIdx[nPt] = j;
                        }
                    }
                }

                // return
                NoOfUnassigned += NoOfUnassignedNodes;
            }
        }
Пример #14
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);
                    }
                }
            }
        }
Пример #15
0
        /// <summary>
        /// Evaluates the divergence of the modified integrand
        /// \f$
        /// \nabla \cdot \vec{g} = \nabla \cdot (g \frac{\nabla \Phi}{|\nabla \Phi|})
        /// \f$
        /// which can be expanded to
        /// \f$
        /// \nabla \cdot \vec{g} = \nabla g \frac{\nabla \Phi}{|\nabla \Phi|} + g (
        /// \frac{\Delta \Phi}{|\nabla \Phi|}
        /// - \frac{\nabla \Phi}{|\nabla \Phi|} \frac{H(\Phi)}{|\nabla \Phi|} \frac{\nabla \Phi}{|\nabla \Phi|})
        /// \f$
        /// using the chain rule. HEre, \f$ H(\Phi)\f$
        /// denotes the Hessian of the level set (i.e., the second derivatives)
        /// </summary>
        /// <param name="j0">
        /// <see cref="LevelSetIntegrator.EvaluateDivergenceOfIntegrand"/>
        /// </param>
        /// <param name="Length">
        /// <see cref="LevelSetIntegrator.EvaluateDivergenceOfIntegrand"/>
        /// </param>
        /// <param name="EvalResult">
        /// <see cref="LevelSetIntegrator.EvaluateDivergenceOfIntegrand"/>
        /// </param>
        public override void EvaluateDivergenceOfIntegrand(NodeSet nodes, int j0, int Length, MultidimensionalArray EvalResult)
        {
            using (new FuncTrace()) {
                int D         = base.m_LevSetTrk.GridDat.SpatialDimension; // spatial dimension
                int noOfNodes = EvalResult.GetLength(1);                   // number of nodes

                if (m_WeighFunctionBuffer.GetLength(0) != Length || m_WeighFunctionBuffer.GetLength(1) != noOfNodes)
                {
                    m_IntegrandBuffer.Allocate(Length, noOfNodes);
                    m_IntegrandGradientBuffer.Allocate(Length, noOfNodes, D);
                    m_WeighFunctionBuffer.Allocate(Length, noOfNodes);
                    m_LevelSetGradientBuffer.Allocate(Length, noOfNodes, D);
                    m_LevelSetHessianBuffer.Allocate(Length, noOfNodes, D, D);
                }

                m_Field.Evaluate(j0, Length, nodes, m_IntegrandBuffer);
                m_Field.EvaluateGradient(j0, Length, nodes, m_IntegrandGradientBuffer, 0, 0.0);
                m_levSet.EvaluateGradient(j0, Length, nodes, m_LevelSetGradientBuffer);
                m_levSet.EvaluateHessian(j0, Length, nodes, m_LevelSetHessianBuffer);

                EvaluateWeightFunction(nodes, j0, Length, m_WeighFunctionBuffer);

                double[] Buf = new double[D];

                for (int i = 0; i < Length; i++)
                {
                    for (int j = 0; j < noOfNodes; j++)
                    {
                        if (m_WeighFunctionBuffer[i, j] == 0.0)
                        {
                            continue;
                        }

                        double AbsGradPhi = 0.0;

                        for (int d = 0; d < D; d++)
                        {
                            double GradPhi_d = m_LevelSetGradientBuffer[i, j, d];
                            AbsGradPhi += GradPhi_d * GradPhi_d;
                        }
                        AbsGradPhi = Math.Sqrt(AbsGradPhi);
                        if (AbsGradPhi < 1e-11)
                        {
                            // Assume zero since gradient is nearly zero
                            continue;
                        }

                        double ooAbsGradPhi = 1.0 / AbsGradPhi;

                        double term1 = 0.0;
                        for (int d = 0; d < D; d++)
                        {
                            term1 += m_IntegrandGradientBuffer[i, j, d] * m_LevelSetGradientBuffer[i, j, d];
                        }
                        term1 *= ooAbsGradPhi;

                        double term2 = 0;
                        for (int d = 0; d < D; d++)
                        {
                            term2 += m_LevelSetHessianBuffer[i, j, d, d];
                        }
                        term2 *= ooAbsGradPhi;

                        double term3 = 0;
                        {
                            for (int d1 = 0; d1 < D; d1++)
                            {
                                double a = 0;
                                for (int d2 = 0; d2 < D; d2++)
                                {
                                    a += m_LevelSetHessianBuffer[i, j, d1, d2] * m_LevelSetGradientBuffer[i, j, d2];
                                }
                                Buf[d1] = a;
                            }

                            for (int d = 0; d < D; d++)
                            {
                                term3 += Buf[d] * m_LevelSetGradientBuffer[i, j, d];
                            }

                            term3 *= (ooAbsGradPhi * ooAbsGradPhi * ooAbsGradPhi);
                        }

                        EvalResult[i, j, 0] = term1 + m_IntegrandBuffer[i, j] * (term2 - term3);
                    }
                }
            }
        }
Пример #16
0
        /// <summary>
        /// Computation of mean curvature according to Bonnet's formula.
        /// </summary>
        /// <param name="scale"></param>
        /// <param name="Output">
        /// output.
        /// </param>
        /// <param name="quadScheme"></param>
        /// <param name="UseCenDiffUpTo">
        /// Either 0, 1, or 2:
        /// If 0, all derivatives are computed locally (broken derivative);
        /// if 1, the first order derivatives are computed by central
        /// differences, while the second order ones are computed locally,
        /// based on the first order ones;
        /// if 2, all derivatives are computed by central differences.
        /// </param>
        /// <param name="_1stDerivDegree">
        /// Relative DG polynomial degree for the 1st order derivatives, i.e.
        /// degree is <paramref name="_1stDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field.
        /// Only active if <paramref name="UseCenDiffUpTo"/> is greater than 0.
        /// </param>
        /// <param name="_2ndDerivDegree">
        /// Relative DG polynomial degree for the 2nd order derivatives, i.e.
        /// degree is <paramref name="_2ndDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field. Only active if
        /// <paramref name="UseCenDiffUpTo"/> is greater than 1.
        /// </param>
        /// <remarks>
        /// using central differences causes memory allocation: <em>D</em>
        /// fields for <paramref name="UseCenDiffUpTo"/>=1, and
        /// <em>D</em>*(<em>D</em>+1) for <paramref name="UseCenDiffUpTo"/>=2,
        /// where <em>D</em> notates the spatial dimension.
        /// </remarks>
        public void ProjectTotalcurvature2(
            double scale,
            SinglePhaseField Output,
            int UseCenDiffUpTo,
            int _1stDerivDegree             = 0,
            int _2ndDerivDegree             = 0,
            CellQuadratureScheme quadScheme = null)
        {
            using (new FuncTrace()) {
                if (UseCenDiffUpTo < 0 || UseCenDiffUpTo > 2)
                {
                    throw new ArgumentOutOfRangeException();
                }

                //int M = Output.Basis.Length;
                //int N = this.Basis.Length;
                int D = this.GridDat.SpatialDimension;
                //var NSC = m_context.NSC;

                SubGrid sgrd = null;
                SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.InnerEdge;
                if (UseCenDiffUpTo >= 1 && quadScheme != null && quadScheme.Domain != null)
                {
                    sgrd    = new SubGrid(quadScheme.Domain);
                    bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary;
                }

                // compute 1st order derivatives by central differences, if desired
                // ================================================================
                Basis B2 = new Basis(this.GridDat, this.Basis.Degree + _1stDerivDegree);

                SinglePhaseField[] GradientVector = null;
                if (UseCenDiffUpTo >= 1)
                {
                    GradientVector = new SinglePhaseField[D];
                    for (int d = 0; d < D; d++)
                    {
                        GradientVector[d] = new SinglePhaseField(B2);
                        GradientVector[d].DerivativeByFlux(1.0, this, d, sgrd, bndMode);
                    }
                }

                // compute 2nd order derivatives by central differences, if desired
                // ===============================================================
                Basis B3 = new Basis(this.GridDat, this.Basis.Degree + _2ndDerivDegree);

                SinglePhaseField[,] HessianTensor = null;
                if (UseCenDiffUpTo >= 2)
                {
                    HessianTensor = new SinglePhaseField[D, D];
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        for (int d2 = 0; d2 < D; d2++)
                        {
                            HessianTensor[d1, d2] = new SinglePhaseField(B3);
                            HessianTensor[d1, d2].DerivativeByFlux(1.0, GradientVector[d1], d2, sgrd, bndMode);
                        }
                    }
                }

                // compute and project
                // ===================

                // buffers:
                MultidimensionalArray Phi     = new MultidimensionalArray(2);
                MultidimensionalArray GradPhi = new MultidimensionalArray(3);
                MultidimensionalArray HessPhi = new MultidimensionalArray(4);

                MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
                MultidimensionalArray Laplace    = new MultidimensionalArray(2);
                MultidimensionalArray Q          = new MultidimensionalArray(3);

                // evaluate/project:
                //double Erracc = 0;
                Output.ProjectField(scale,
                                    (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // ScalarFunction2
                    Debug.Assert(result.Dimension == 2);
                    Debug.Assert(Len == result.GetLength(0));
                    int K = result.GetLength(1); // number of nodes


                    // alloc buffers
                    // -------------

                    if (Phi.GetLength(0) != Len || Phi.GetLength(1) != K)
                    {
                        Phi.Allocate(Len, K);
                        GradPhi.Allocate(Len, K, D);
                        HessPhi.Allocate(Len, K, D, D);
                        ooNormGrad.Allocate(Len, K);
                        Laplace.Allocate(Len, K);
                        Q.Allocate(Len, K, D);
                    }
                    else
                    {
                        Phi.Clear();
                        GradPhi.Clear();
                        HessPhi.Clear();
                        ooNormGrad.Clear();
                        Laplace.Clear();
                        Q.Clear();
                    }

                    // evaluate Gradient and Hessian
                    // -----------------------------

                    if (UseCenDiffUpTo >= 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            GradientVector[d].Evaluate(j0, Len, NodeSet, GradPhi.ExtractSubArrayShallow(-1, -1, d));
                        }
                    }
                    else
                    {
                        this.EvaluateGradient(j0, Len, NodeSet, GradPhi);
                    }

                    if (UseCenDiffUpTo == 2)
                    {
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                HessianTensor[d1, d2].Evaluate(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d1, d2));
                            }
                        }
                    }
                    else if (UseCenDiffUpTo == 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            var GradientVector_d = GradientVector[d];
                            GradientVector_d.EvaluateGradient(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0);
                        }
                    }
                    else if (UseCenDiffUpTo == 0)
                    {
                        this.EvaluateHessian(j0, Len, NodeSet, HessPhi);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    // compute the monstrous formula
                    // -----------------------------

                    // norm of Gradient:
                    for (int d = 0; d < D; d++)
                    {
                        var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                        ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                    }
                    ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

                    // laplacian of phi:
                    for (int d = 0; d < D; d++)
                    {
                        var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                        Laplace.Acc(1.0, HessPhi_d_d);
                    }

                    // result = Laplacian(phi)/|Grad phi|
                    result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


                    // result = Grad(1/|Grad(phi)|)
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                        for (int d2 = 0; d2 < D; d2++)
                        {
                            var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                            var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                            Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                        }
                    }

                    ooNormGrad.ApplyAll(x => x * x * x);

                    result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");

                    //for (int i = 0; i < Len; i++) {
                    //    for (int k = 0; k < K; k++) {
                    //        double acc = 0;
                    //        for (int d = 0; d < D; d++) {
                    //            acc += GradPhi[i,k,d]*Q[i,k,d]*ooNormGrad[i,k];
                    //        }

                    //        Erracc += (acc - result[i,k]).Abs();
                    //    }
                    //}
                },
                                    quadScheme.SaveCompile(this.GridDat, (Output.Basis.Degree + this.m_Basis.Degree * (this.m_Basis.Degree - 1) * D) * 2)
                                    );
            }
        }
Пример #17
0
        /// <summary>
        /// curvature computation according to Bonnet's formula
        /// Copy-Paste from <see cref="LevelSet.EvaluatetotalCurvature"/>, since there is no analytic formula for the curvature of an ellipse
        /// </summary>
        public void EvaluateTotalCurvature(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result)
        {
            // (siehe FK, persoenliche Notizen, 08mar13)


            // checks
            // ------

            int K = NodeSet.NoOfNodes;

            if (result.Dimension != 2)
            {
                throw new ArgumentException();
            }
            if (result.GetLength(0) != Len)
            {
                throw new ArgumentException();
            }
            if (result.GetLength(1) != K)
            {
                throw new ArgumentException();
            }
            int D = NodeSet.SpatialDimension;
            //Debug.Assert(D == this.GridDat.SpatialDimension);


            // buffers:
            // --------
            //MultidimensionalArray Phi = new MultidimensionalArray(2);
            MultidimensionalArray GradPhi = new MultidimensionalArray(3);
            MultidimensionalArray HessPhi = new MultidimensionalArray(4);

            MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
            MultidimensionalArray Laplace    = new MultidimensionalArray(2);
            MultidimensionalArray Q          = new MultidimensionalArray(3);

            //Phi.Allocate(Len, K);
            GradPhi.Allocate(Len, K, D);
            HessPhi.Allocate(Len, K, D, D);
            ooNormGrad.Allocate(Len, K);
            Laplace.Allocate(Len, K);
            Q.Allocate(Len, K, D);

            // derivatives
            // -----------

            // evaluate gradient
            this.EvaluateGradient(j0, Len, NodeSet, GradPhi);

            // evaluate Hessian
            this.EvaluateHessian(j0, Len, NodeSet, HessPhi);


            // compute the monstrous formula
            // -----------------------------

            // norm of Gradient:
            for (int d = 0; d < D; d++)
            {
                var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
            }
            ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

            // laplacian of phi:
            for (int d = 0; d < D; d++)
            {
                var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                Laplace.Acc(1.0, HessPhi_d_d);
            }

            // result = Laplacian(phi)/|Grad phi|
            result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


            // result += Grad(1/|Grad(phi)|)
            for (int d1 = 0; d1 < D; d1++)
            {
                var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                for (int d2 = 0; d2 < D; d2++)
                {
                    var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                    var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                    Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                }
            }

            ooNormGrad.ApplyAll(x => x * x * x);

            result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");
        }
Пример #18
0
        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="QuadNodes">
        /// quad nodes outside the grid are ignored, i.e. the integrand is assumed to be 0
        /// </param>
        /// <param name="quadweights">
        /// </param>
        public Integrator(CellLocalization loc, double[,] QuadNodes, double[] quadweights)
        {
            int N = QuadNodes.GetLength(0);

            if (N != quadweights.Length)
            {
                throw new ArgumentException("length of 0-th dimension of arrays must match.");
            }
            int D = QuadNodes.GetLength(1);

            if (D != loc.GridBB.D)
            {
                throw new ArgumentException("mismatch in spatial dimension.");
            }
            int J = loc.GrdDat.Cells.NoOfLocalUpdatedCells;

            GridData gdat = loc.GrdDat;

            grdDat = gdat;

            // filter quad nodes outside of the bounding box
            // =============================================
            MultidimensionalArray QuadNodes2;

            double[] quadweights2;
            int[]    orgindex;
            {
                double[] pt     = new double[D];
                BitArray inside = new BitArray(N);

                int Found = 0;
                for (int n = 0; n < N; n++)
                {
                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = QuadNodes[n, d];
                    }
                    bool ins = loc.GridBB.Contains(pt);

                    inside[n] = ins;
                    if (ins)
                    {
                        Found++;
                    }
                }

                QuadNodes2   = MultidimensionalArray.Create(Found, D);
                quadweights2 = new double[Found];
                orgindex     = new int[Found];

                int cnt = 0;
                for (int n = 0; n < N; n++)
                {
                    if (inside[n])
                    {
                        for (int d = 0; d < D; d++)
                        {
                            QuadNodes2[cnt, d] = QuadNodes[n, d];
                        }
                        quadweights2[cnt] = quadweights[cnt];
                        orgindex[cnt]     = n;
                        cnt++;
                    }
                }

                QuadNodes   = null;
                quadweights = null;
                N           = Found;
            }

            // build tree of quad nodes
            // ========================
            int[]             Perm = new int[N];
            PointLocalization qn   = new PointLocalization(QuadNodes2, loc.GridBB, Perm);

            double[] quadwegtNew  = new double[N];
            int[]    origindexNew = new int[N];
            for (int n = 0; n < N; n++)
            {
                quadwegtNew[n]  = quadweights2[Perm[n]];
                origindexNew[n] = orgindex[Perm[n]];
            }
            quadweights2 = null;

            // 1st index: cell index
            // 2nd index: quad node index within cell
            // 3rd index: spatial coordinate
            List <List <double[]> > QuadNodesPerCell = new List <List <double[]> >();

            // 1st index: cell index
            // 2nd index: quad node index within cell
            List <List <double> > QuadWeightsPerCell = new List <List <double> >();

            // 1st index: cell index
            // 2nd index: quad node index within cell
            List <List <int> > OrigIndexPerCell = new List <List <int> >();

            for (int j = 0; j < J; j++)
            {
                QuadNodesPerCell.Add(new List <double[]>());
                QuadWeightsPerCell.Add(new List <double>());
                OrigIndexPerCell.Add(new List <int>());
            }

            // try to assign the quad nodes to cells
            // =====================================
            BitArray PointsLocatedMarker = new BitArray(N); // mark every node, that we assign to a cell with
            int      NoOfUnassignedNodes = N;

            //int[] Cell4Quadnodes = new int[N];

            // loop over cells ...
            MultidimensionalArray vertGlobal = new MultidimensionalArray(2);
            MultidimensionalArray vertLocal  = new MultidimensionalArray(3);

            for (int j = 0; j < J; j++)
            {
                //if (loc.CellMaxCode[j] < Locations[0])
                //    continue; // skip the cell: contains none of the searched points
                //if (loc.CellMinCode[j] > Locations[N - 1])
                //    continue; // skip the cell: contains none of the searched points

                GeomBinTreeBranchCode bbcode; int bbBits;
                {
                    BoundingBoxCode __b = loc.GetCellBoundingBoxCode(j);
                    bbcode = __b.Branch;
                    bbBits = (int)__b.SignificantBits;
                }

                int iP0, Len;
                qn.GetPointsInBranch(bbcode, bbBits, out iP0, out Len);
                if (Len <= 0)
                {
                    continue;
                }

                vertGlobal.Allocate(Len, D);
                vertLocal.Allocate(1, Len, D);
                for (int n = 0; n < Len; n++)
                {
                    for (int d = 0; d < D; d++)
                    {
                        vertGlobal[n, d] = qn.Points[n + iP0, d];
                    }
                }
                gdat.TransformGlobal2Local(vertGlobal, vertLocal, j, 1, 0);


                var splx = gdat.Cells.GetRefElement(j);
                for (int n = 0; n < Len; n++)
                {
                    int nPt = n + iP0;
                    if (PointsLocatedMarker[nPt])
                    {
                        continue;
                    }

                    double[] pt = new double[D];
                    for (int d = 0; d < D; d++)
                    {
                        pt[d] = vertLocal[0, n, d];
                    }
                    if (splx.IsWithin(pt))
                    {
                        PointsLocatedMarker[nPt] = true;
                        NoOfUnassignedNodes--;
                        //Cell4Quadnodes[nPt] = j;

                        QuadNodesPerCell[j].Add(pt);
                        QuadWeightsPerCell[j].Add(quadwegtNew[nPt]);
                        OrigIndexPerCell[j].Add(origindexNew[nPt]);
                    }
                }
            }

            // record final data structures
            // ============================
            //m_QuadNodesPerCell = new MultidimensionalArray[J];
            m_QuadNodesPerCell       = new NodeSet[J];
            m_QuadWeightsPerCell     = new double[J][];
            m_OriginalQuadNodesIndex = new int[J][];
            MaxNumberOfNodes         = 0;
            for (int j = 0; j < J; j++)
            {
                List <double[]> NodesInCellj = QuadNodesPerCell[j];

                m_QuadWeightsPerCell[j]     = QuadWeightsPerCell[j].ToArray();
                m_OriginalQuadNodesIndex[j] = OrigIndexPerCell[j].ToArray();

                int NJ = NodesInCellj.Count;
                if (NJ > 0)
                {
                    var _QuadNodesPerCell_j = new NodeSet(grdDat.Cells.GetRefElement(j), NJ, D);
                    MaxNumberOfNodes = Math.Max(MaxNumberOfNodes, NJ);
                    for (int nn = 0; nn < NJ; nn++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            _QuadNodesPerCell_j[nn, d] = NodesInCellj[nn][d];
                        }
                    }
                    _QuadNodesPerCell_j.LockForever();

                    m_QuadNodesPerCell[j] = _QuadNodesPerCell_j;
                }
                else
                {
                    m_QuadNodesPerCell[j] = null;
                }
            }
        }