예제 #1
0
                protected override void ComputeValues(NodeSet NS, int j0, int Len, MultidimensionalArray output)
                {
                    MultidimensionalArray Phi     = m_owner.GetLevSetValues(NS, j0, Len);
                    MultidimensionalArray GradPhi = m_owner.GetLevelSetReferenceGradients(NS, j0, Len);
                    MultidimensionalArray HessPhi = m_owner.GetLevelSetReferenceHessian(NS, j0, Len);

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

                    int K = output.GetLength(1);
                    int D = GradPhi.GetLength(2);

                    Debug.Assert(D == this.m_owner.m_owner.GridDat.SpatialDimension);

                    ooNormGrad.Allocate(Len, K);
                    Laplace.Allocate(Len, K);
                    Q.Allocate(Len, K, D);


                    // 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|
                    output.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);

                    output.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");
                }
예제 #2
0
        /// <summary>
        /// Constructs a new flux builder.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="boundaryMap"></param>
        /// <param name="speciesMap"></param>
        /// <param name="gridData"></param>
        public OptimizedSIPGFluxBuilder(CNSControl control, IBoundaryConditionMap boundaryMap, ISpeciesMap speciesMap, GridData gridData)
            : base(control, boundaryMap, speciesMap)
        {
            this.gridData = gridData;

            //Create Functions for calculation the cell metric, needed as Func<> because
            //LevelSet field and HMF options are not known at this point
            if (speciesMap is IBM.ImmersedSpeciesMap)
            {
                // IBM case
                ImmersedSpeciesMap IBMspeciesMap = speciesMap as ImmersedSpeciesMap;
                cellMetricFunc = delegate() {
                    SpeciesId             species    = IBMspeciesMap.Tracker.GetSpeciesId(IBMspeciesMap.Control.FluidSpeciesName);
                    MultidimensionalArray cellMetric = IBMspeciesMap.CellAgglomeration.CellLengthScales[species].CloneAs();
                    cellMetric.ApplyAll(x => 1 / x);
                    // Needed, because 1/x produces NaN in void cells and can happen that penalty factor leads then to NaN
                    cellMetric.ApplyAll(delegate(double x) {
                        if (double.IsNaN(x) || double.IsInfinity(x))
                        {
                            return(0);
                        }
                        else
                        {
                            return(x);
                        }
                    });
                    return(cellMetric);
                };
            }
            else
            {
                // Non-IBM
                cellMetricFunc = () => gridData.Cells.cj;
            }
        }
예제 #3
0
 internal void Tf(int j0, int Len, NodeSet N, MultidimensionalArray result)
 {
     f(j0, Len, N, result);
     Debug.Assert(Len == result.GetLength(0));
     Debug.Assert(result.Dimension == 2);
     result.ApplyAll(this.T);
 }
예제 #4
0
        /// <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(LinearSayeSpace <Cube> Arg, LinearPSI <Cube> psi, NodeSet x_center, int cell)
        {
            double[] arr = new double[RefElement.SpatialDimension];
            Arg.Diameters.CopyTo(arr, 0);
            psi.SetInactiveDimsToZero(arr);
            MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, 3);

            NodeSet nodeOnPsi          = psi.ProjectOnto(x_center);
            MultidimensionalArray grad = ReferenceGradient(nodeOnPsi, cell);

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

            return(delta);
        }
예제 #5
0
        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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
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");
        }
예제 #8
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)
                                    );
            }
        }
예제 #9
0
        public void WriteTrendToTable(bool ErrorOrResidual, bool SepPoly, bool SepLev, out string[] Titels, out MultidimensionalArray ConvTrendData)
        {
            Dictionary <Tuple <int, int, int>, List <double> > data = ErrorOrResidual ? ErrNormTrend : ResNormTrend;


            List <string> titleS = new List <string>();
            int           iCol   = 0;
            Dictionary <Tuple <int, int, int>, int> ColumnIndex = new Dictionary <Tuple <int, int, int>, int>();

            foreach (var kv in data)
            {
                int iLevel = kv.Key.Item1;
                int pDG    = kv.Key.Item3;
                int iVar   = kv.Key.Item2;

                string title;
                if (SepPoly == false && SepLev == false)
                {
                    title = string.Format("(var#{0})", iVar);
                }
                else if (SepPoly == false && SepLev == true)
                {
                    title = string.Format("(var#{0},mg.lev.{1})", iVar, iLevel);
                }
                else if (SepPoly == true && SepLev == false)
                {
                    title = string.Format("(var#{0},p={2})", iVar, pDG);
                }
                else if (SepPoly == true && SepLev == true)
                {
                    title = string.Format("(var#{0},mg.lev.{1},p={2})", iVar, iLevel, pDG);
                }
                else
                {
                    throw new ApplicationException();
                }

                int iColKv = titleS.IndexOf(title);
                if (iColKv < 0)
                {
                    titleS.Add(title);
                    iColKv = iCol;
                    iCol++;
                }
                ColumnIndex.Add(kv.Key, iColKv);
            }
            Titels        = titleS.ToArray();
            ConvTrendData = MultidimensionalArray.Create(data.First().Value.Count, titleS.Count);

            foreach (var kv in data)
            {
                double[] Column = kv.Value.ToArray();
                for (int l = 0; l < Column.Length; l++)
                {
                    Column[l] = Column[l].Pow2();
                }

                if (ConvTrendData.GetLength(0) != Column.Length)
                {
                    throw new ApplicationException();
                }

                int iColkv = ColumnIndex[kv.Key];
                ConvTrendData.ExtractSubArrayShallow(-1, iColkv).AccVector(1.0, Column);
            }

            ConvTrendData.ApplyAll(x => Math.Sqrt(x));
        }
예제 #10
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 });
        }
예제 #11
0
        /// <summary>
        /// provides data collected during a solver run in tabular form
        /// </summary>
        /// <param name="ErrorOrResidual">
        /// - true: output is error against exact solution (if provided) during each iteration
        /// - false: output is residual against exact solution (if provided) during each iteration
        /// </param>
        /// <param name="SepVars">
        /// - true: separate column for each variable
        /// - false:  l2-norm over all variables
        /// </param>
        /// <param name="SepPoly">
        /// - true:   separate column for each polynomial degree
        /// - false:  l2-norm over all polynomial degrees
        /// </param>
        /// <param name="SepLev">
        /// - true:   separate column for each multi-grid level
        /// - false:  l2-norm over all multi-grid levels
        /// </param>
        /// <param name="Titels">
        /// Column names/titles
        /// </param>
        /// <param name="ConvTrendData">
        /// data table:
        /// - columns: correspond to <paramref name="Titels"/>
        /// - rows: solver iterations
        /// </param>
        public void WriteTrendToTable(bool ErrorOrResidual, bool SepVars, bool SepPoly, bool SepLev, out string[] Titels, out MultidimensionalArray ConvTrendData)
        {
            var data = ErrorOrResidual ? ErrNormTrend : ResNormTrend;

            List <string> titleS = new List <string>();
            int           iCol   = 0;
            Dictionary <(int MGlevel, int iVar, int deg), int> ColumnIndex = new Dictionary <(int, int, int), int>();

            foreach (var kv in data)
            {
                int iLevel = kv.Key.Item1;
                int pDG    = kv.Key.Item3;
                int iVar   = kv.Key.Item2;

                string title;
                {
                    if (SepVars)
                    {
                        title = $"Var{iVar}";
                    }
                    else
                    {
                        title = "";
                    }

                    if (SepLev)
                    {
                        if (title.Length > 0)
                        {
                            title = title + ",";
                        }
                        title = title + $"Mglv{iLevel}";
                    }

                    if (SepPoly)
                    {
                        if (title.Length > 0)
                        {
                            title = title + ",";
                        }
                        title = title + $"p={pDG}";
                    }

                    if (title.Length > 0)
                    {
                        title = "_" + title;
                    }

                    if (ErrorOrResidual)
                    {
                        title = "Err" + title;
                    }
                    else
                    {
                        title = "Res" + title;
                    }
                }

                /*
                 * if (SepPoly == false && SepLev == false) {
                 *  title = string.Format("(var#{0})", iVar);
                 * } else if (SepPoly == false && SepLev == true) {
                 *  title = string.Format("(var#{0},mg.lev.{1})", iVar, iLevel);
                 * } else if (SepPoly == true && SepLev == false) {
                 *  title = string.Format("(var#{0},p={1})", iVar, pDG);
                 * } else if (SepPoly == true && SepLev == true) {
                 *  title = string.Format("(var#{0},mg.lev.{1},p={2})", iVar, iLevel, pDG);
                 * } else {
                 *  throw new ApplicationException();
                 * }
                 */

                int iColKv = titleS.IndexOf(title);
                if (iColKv < 0)
                {
                    titleS.Add(title);
                    iColKv = iCol;
                    iCol++;
                }
                ColumnIndex.Add(kv.Key, iColKv);
            }
            Titels        = titleS.ToArray();
            ConvTrendData = MultidimensionalArray.Create(data.First().Value.Count, titleS.Count);

            foreach (var kv in data)   // over all data columns

            {
                double[] ColumnSquared = kv.Value.Select(val => val.Pow2()).ToArray();

                if (ConvTrendData.GetLength(0) != ColumnSquared.Length)
                {
                    throw new ApplicationException();
                }

                int iColkv = ColumnIndex[kv.Key]; // output column index in which we sum up the column
                ConvTrendData.ExtractSubArrayShallow(-1, iColkv).AccVector(1.0, ColumnSquared);
            }
            ConvTrendData.ApplyAll(x => Math.Sqrt(x));
        }
예제 #12
0
        protected override bool HeightDirectionIsSuitable(
            LinearSayeSpace <Cube> arg,
            LinearPSI <Cube> psi, NodeSet
            x_center,
            int heightDirection,
            MultidimensionalArray agradient, int cell)
        {
            //throw new NotImplementedException();

            //Determine bounds
            //-----------------------------------------------------------------------------------------------------------------
            NodeSet nodeOnPsi = psi.ProjectOnto(x_center);

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

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

            LevelSet levelSet             = lsData.LevelSet as LevelSet;
            MultidimensionalArray hessian = MultidimensionalArray.Create(1, 1, 3, 3);

            levelSet.EvaluateHessian(cell, 1, nodeOnPsi, hessian);
            hessian = hessian.ExtractSubArrayShallow(new int[] { 0, 0, -1, -1 }).CloneAs();

            //hessian = jacobian * hessian;
            hessian.ApplyAll(x => Math.Abs(x));

            MultidimensionalArray gradient = lsData.GetLevelSetGradients(nodeOnPsi, cell, 1);

            gradient = gradient.ExtractSubArrayShallow(0, 0, -1).CloneAs();



            //abs(Hessian) * 0,5 * diameters.^2 = delta ,( square each entry of diameters) ,
            //this bounds the second error term from taylor series
            //+ + + +
            double[] arr = arg.Diameters.CloneAs();
            psi.SetInactiveDimsToZero(arr);
            MultidimensionalArray diameters = MultidimensionalArray.CreateWrapper(arr, 3, 1);

            diameters = jacobian * diameters;
            diameters.ApplyAll(x => 0.5 * x * x);
            MultidimensionalArray delta = hessian * diameters;

            delta = delta.ExtractSubArrayShallow(-1, 0);

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

            //|gk| > δk
            //Gradient should be able to turn arround
            psi.SetInactiveDimsToZero(gradient.Storage);
            if (Math.Abs(gradient[heightDirection]) > delta[heightDirection])
            {
                bool suitable = true;
                // ||Grad + maxChange|| should be smaller than 20 *
                // 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(Math.Abs(gradient[j]) + delta[j], 2);
                }
                sum /= Math.Pow(Math.Abs(gradient[heightDirection]) - delta[heightDirection], 2);

                suitable &= sum < 20;

                return(suitable);
            }
            return(false);
        }