/// <summary>
            /// For each edge \f$ E\f$  of each cell in
            /// the given range and for each
            /// \f$ \vec{\Lambda}\f$  in
            /// <see cref="LevelSetEdgeVolumeQuadRuleFactory.lambdaBasis"/>:
            /// Computes
            /// \f$
            /// \int_{ \{ \vec{x}; \varphi(\vec{x}) = 0 \}  \cap E} \vec{\Lambda} \cdot \vec{n}_I \;ds,
            /// \f$
            /// where \f$ \varphi\f$  is the level set
            /// function and \f$ \vec{n}_I\f$  denotes the
            /// unit normal vector on
            /// \f$ \varphi \cap E\f$
            /// (<b>not</b> \f$ E\f$ !)
            /// </summary>
            /// <param name="i0"></param>
            /// <param name="Length"></param>
            /// <param name="NoOfNodes"></param>
            /// <param name="EvalResult"></param>
            protected override void Evaluate(int i0, int Length, CellBoundaryQuadRule CBQR, MultidimensionalArray EvalResult)
            {
                NodeSet QuadNodes = CBQR.Nodes;
                int     D         = gridData.SpatialDimension;

                for (int i = 0; i < Length; i++)
                {
                    MultidimensionalArray lambdaValues = owner.EvaluateLambdas(i0 + i, CurrentRule);
                    int nodeIndex = -1;

                    for (int e = 0; e < gridData.iGeomCells.RefElements[0].NoOfFaces; e++)
                    {
                        MultidimensionalArray levelSetNormals =
                            LevelSetEdgeSurfaceQuadRuleFactory.EvaluateRefNormalsOnEdge(this.owner.LevelSetData, i0 + i, CurrentRule, e);
                        //MultidimensionalArray metrics = LevelSetEdgeSurfaceQuadRuleFactory.GetMetricTermsOnEdge(
                        //    owner.tracker, owner.levSetInd, CurrentRule, i0 + i, e);

                        for (int j = 0; j < CurrentRule.NumbersOfNodesPerFace[e]; j++)
                        {
                            nodeIndex++;

                            for (int k = 0; k < IntegralCompDim[0]; k++)
                            {
                                for (int d = 0; d < D; d++)
                                {
                                    EvalResult[i, nodeIndex, k] += lambdaValues[nodeIndex, k, d] * levelSetNormals[j, d];
                                }

                                //EvalResult[i, nodeIndex, k] *= metrics[j];
                            }
                        }
                    }
                }
            }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="lsData"></param>
        /// <param name="rootFindingAlgorithm">
        /// One-dimensional root-finding algorithm for determining roots of the
        /// level set function on edges of the edges of the volume simplex.
        /// Default is <see cref="LineSegment.DefaultRootFindingAlgorithm"/>
        /// </param>
        /// <param name="jumpType">
        /// Determines the level set region to be integrated over (negative
        /// level set values, positive level set values, or both)
        /// </param>
        public LevelSetEdgeVolumeQuadRuleFactory(
            LevelSetTracker.LevelSetData lsData, LineSegment.IRootFindingAlgorithm rootFindingAlgorithm = null, JumpTypes jumpType = JumpTypes.Heaviside)
        {
            if (lsData.GridDat.Cells.RefElements.Length > 1)
            {
                throw new NotImplementedException(
                          "Multiple reference elements currently not supported");
            }
            this.LevelSetData      = lsData;
            this.jumpType          = jumpType;
            this.levelSetIndex     = lsData.LevelSetIndex;
            CoFaceQuadRuleFactory  = new CutLineOnEdgeQuadRuleFactory(lsData, rootFindingAlgorithm, jumpType);
            edgeSurfaceRuleFactory = new LevelSetEdgeSurfaceQuadRuleFactory(lsData, CoFaceQuadRuleFactory, jumpType);

            // Use vertices; Since it is only used on edges that are considered
            // uncut, they _should_ all have the same sign
            RefElement simplex      = LevelSetData.GridDat.Grid.RefElements[0];
            RefElement edgeSimplex  = simplex.FaceRefElement;
            QuadRule   signEdgeRule = new QuadRule()
            {
                Nodes   = edgeSimplex.Vertices,
                Weights = MultidimensionalArray.Create(edgeSimplex.NoOfVertices)
            };

            signTestRule = new CellBoundaryFromEdgeRuleFactory <CellBoundaryQuadRule>(
                LevelSetData.GridDat, simplex, new FixedRuleFactory <QuadRule>(signEdgeRule)).
                           GetQuadRuleSet(new CellMask(LevelSetData.GridDat, Chunk.GetSingleElementChunk(0)), -1).
                           First().Rule;
        }
 public PhiQuadrature(LevelSetTracker.LevelSetData lsData, LevelSetEdgeSurfaceQuadRuleFactory owner, int maxPhiDegree, int element)
     : base(
         new int[] { owner.GetNumberOfPhis() },
         lsData.GridDat,
         new CellEdgeBoundaryQuadratureScheme(
             false,
             owner.edgeRuleFactory,
             new CellMask(lsData.GridDat, Chunk.GetSingleElementChunk(element), MaskType.Geometrical))
         .Compile(lsData.GridDat, maxPhiDegree),
         CoordinateSystem.Reference)
 {
     this.LevelSetData = lsData;
     this.owner        = owner;
     if (lsData.GridDat.Cells.RefElements.Length > 1)
     {
         throw new NotSupportedException();
     }
 }