protected override SayeQuadRule SetGaussQuadratureNodes(SayeSquare arg)
        {
            //Aquire needed data
            //------------------------------------------------------------------------------------------------------------
            QuadRule gaussRule_2D = Square.Instance.GetQuadratureRule(order);
            MultidimensionalArray nodes_GaussRule_2D   = ((MultidimensionalArray)gaussRule_2D.Nodes).CloneAs();
            MultidimensionalArray weights_GaussRule_2D = gaussRule_2D.Weights.CloneAs();

            double[] diameters = arg.Diameters;
            MultidimensionalArray centerArr = arg.GetCellCenter().ExtractSubArrayShallow(new int[] { 0, -1 });
            double jacobian = diameters[0] * diameters[1];

            //AffineTransformation of nodes, scale weights
            //------------------------------------------------------------------------------------------------------------
            //Scale Nodes
            for (int i = 0; i < 2; ++i)
            {
                nodes_GaussRule_2D.ColScale(i, diameters[i]);
            }
            //Scale Weights
            weights_GaussRule_2D.Scale(jacobian);
            //Move Nodes
            int[] index = new int[] { 0, -1 };
            for (int i = 0; i < gaussRule_2D.NoOfNodes; ++i)
            {
                index[0] = i;
                nodes_GaussRule_2D.AccSubArray(1, centerArr, index);
            }

            //Set return data
            //------------------------------------------------------------------------------------------------------------
            SayeQuadRule transformed_GaussRule_2D = new SayeQuadRule(nodes_GaussRule_2D, weights_GaussRule_2D);

            return(transformed_GaussRule_2D);
        }
        public SayeSquare Subdivide()
        {
            subdivided = true;
            double[][] newBoundary = boundaries.Copy();

            //Figure out new Boundaries
            int k;

            if (diameters[0] > diameters[1])
            {
                k = 0;
            }
            else
            {
                k = 1;
            }
            double[] maxBounds = boundaries[k];
            double   newBound  = (maxBounds[0] + maxBounds[1]) / 2;

            maxBounds[1] = newBound;
            SetBoundaries(boundaries);

            newBoundary[k][0] = newBound;

            SayeSquare sibling = new SayeSquare(newBoundary);

            sibling.psiAndS     = new List <Tuple <LinearPSI <Square>, int> >(this.psiAndS);
            sibling.removedDims = this.removedDims.CloneAs();
            sibling.subdivided  = true;
            sibling.Surface     = this.surface;

            return(sibling);
        }
        public SayeSquare DeriveNew()
        {
            double[][] newBoundary = boundaries.Copy();
            SayeSquare arg         = new SayeSquare(newBoundary);

            arg.subdivided = this.subdivided;
            arg.Surface    = this.surface;
            return(arg);
        }
        public SayeSquare CreateStartSetup()
        {
            bool IsSurfaceIntegral = (quadratureMode == QuadratureMode.Surface);
            int  domainSign        = (quadratureMode == QuadratureMode.NegativeVolume) ? -1 : 1;
            LinearPSI <Square> psi = new LinearPSI <Square>(Square.Instance);
            Tuple <LinearPSI <Square>, int> psi_i_s_i = new Tuple <LinearPSI <Square>, int>(psi, domainSign);
            SayeSquare arg = new SayeSquare(psi_i_s_i, IsSurfaceIntegral);

            arg.Reset();
            return(arg);
        }
        protected override bool HeightDirectionIsSuitable(SayeSquare arg, LinearPSI <Square> psi, NodeSet x_center,
                                                          int heightDirection, MultidimensionalArray gradient, int cell)
        {
            //Determine bounds
            //-----------------------------------------------------------------------------------------------------------------
            double[] arr = arg.Diameters;
            psi.SetInactiveDimsToZero(arr);
            MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, new int[] { 2, 1 });

            NodeSet nodeOnPsi             = psi.ProjectOnto(x_center);
            MultidimensionalArray hessian = lsData.GetLevelSetReferenceHessian(nodeOnPsi, cell, 1);

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

            MultidimensionalArray jacobian = grid.InverseJacobian.GetValue_Cell(nodeOnPsi, cell, 1);

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

            hessian.ApplyAll(x => Math.Abs(x));

            //abs(Hessian) * diameters = delta
            MultidimensionalArray delta = hessian * diameters;

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

            //Check if suitable
            //-----------------------------------------------------------------------------------------------------------------

            //|gk| > δk
            if (Math.Abs(gradient[heightDirection]) > delta[heightDirection])
            {
                bool suitable = true;
                // Sum_j( g_j + delta_j)^2 / (g_k - delta_k)^2 < 20
                double sum = 0;

                for (int j = 0; j < delta.Length; ++j)
                {
                    sum += Math.Pow(gradient[j] + delta[j], 2);
                }
                sum /= Math.Pow(gradient[heightDirection] - delta[heightDirection], 2);

                suitable &= sum < 20;

                return(suitable);
            }
            return(false);
        }
        /// <summary>
        /// First order approximation of  delta >= sup_x|psi(x) - psi(x_center)|
        /// </summary>
        /// <param name="Arg"></param>
        /// <param name="psi"></param>
        /// <param name="x_center"></param>
        /// <param name="cell"></param>
        /// <returns></returns>
        protected override double EvaluateBounds(SayeSquare Arg, LinearPSI <Square> psi, NodeSet x_center, int cell)
        {
            double[] arr = new double[Arg.Dimension];
            Arg.Diameters.CopyTo(arr, 0);
            psi.SetInactiveDimsToZero(arr);
            MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, new int[] { 2 });

            NodeSet nodeOnPsi = psi.ProjectOnto(x_center);


            MultidimensionalArray grad = ScaledReferenceGradient(nodeOnPsi, cell);

            grad.ApplyAll(x => Math.Abs(x));
            double delta = grad.InnerProduct(diameters) * sqrt_2;

            return(delta);
        }
        public QuadRule[] ComboEvaluate(int Cell)
        {
            SayeSquare startArg = CreateStartSetup();

            return(ComboEvaluate(Cell, startArg));
        }
 public override double[] GetBoundaries(SayeSquare arg, int heightDirection)
 {
     return(arg.Boundaries[heightDirection]);
 }
 protected override SayeQuadRule SetLowOrderQuadratureNodes(SayeSquare arg)
 {
     throw new NotImplementedException();
 }
 protected override SayeSquare DeriveNewArgument(SayeSquare OldSquare)
 {
     return(OldSquare.DeriveNew());
 }
 protected override bool SubdivideSuitable(SayeSquare arg)
 {
     return(true);
 }
        protected override SayeSquare Subdivide(SayeSquare Arg)
        {
            SayeSquare newArg = Arg.Subdivide();

            return(newArg);
        }
        protected override LinearPSI <Square>[] ExtractSubPsis(LinearPSI <Square> psi, SayeSquare arg, int heightDirection)
        {
            double[]           bounds = arg.GetBoundaries(heightDirection);
            double             x_U    = bounds[1];
            double             x_L    = bounds[0];
            LinearPSI <Square> Psi_U  = psi.ReduceDim(heightDirection, x_U);
            LinearPSI <Square> Psi_L  = psi.ReduceDim(heightDirection, x_L);

            return(new LinearPSI <Square>[] { Psi_L, Psi_U });
        }