Exemple #1
0
        public static double EnergyBalanceNormAtInterface(XDGField P, VectorField <XDGField> U, ConventionalDGField[] Umean, SinglePhaseField C, double muA, double muB, double sigma, int momentFittingOrder)
        {
            LevelSetTracker LsTrk = P.Basis.Tracker;

            double energyBal_Norm = 0.0;

            ScalarFunctionEx energyBalFunc = GetEnergyBalanceFunc(P, U, Umean, C, muA, muB, sigma, true);

            var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingOrder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs.Compile(LsTrk.GridDat, momentFittingOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                energyBalFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    energyBal_Norm += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();

            return(energyBal_Norm.Sqrt());
        }
Exemple #2
0
        public static double CurvatureEnergy(LevelSetTracker LsTrk, SinglePhaseField Curvature, double sigma, ConventionalDGField[] uI, bool ExtVel, bool Norm, int momentFittingorder)
        {
            double EnergyCurv = 0.0;

            var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingorder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

            ScalarFunctionEx CurvEnergyFunc = GetCurvatureEnergyFunc(LsTrk, Curvature, sigma, uI, ExtVel, Norm);

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs.Compile(LsTrk.GridDat, momentFittingorder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                CurvEnergyFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    EnergyCurv += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();

            if (Norm)
            {
                EnergyCurv.Sqrt();
            }

            return(EnergyCurv);
        }
Exemple #3
0
        public static double EnergyJumpAtInterface(LevelSetTracker LsTrk, VectorField <XDGField> Velocity, XDGField Pressure, double muA, double muB, bool Norm, int momentFittingorder)
        {
            double EnergyJump = 0.0;

            ScalarFunctionEx EnergyJumpFunc = GetEnergyJumpFunc(LsTrk, Velocity, Pressure, muA, muB, Norm);

            var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingorder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs.Compile(LsTrk.GridDat, momentFittingorder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                EnergyJumpFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    EnergyJump += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();

            if (Norm)
            {
                EnergyJump.Sqrt();
            }

            return(EnergyJump);
        }
Exemple #4
0
        public static double SurfaceEnergyChangerate(LevelSetTracker LsTrk, ConventionalDGField[] uI, double sigma, bool Norm, int momentFittingorder)
        {
            double Changerate_Surface = 0.0;

            var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingorder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

            ScalarFunctionEx SurfaceChangerate = GetInterfaceDivergenceFunc(LsTrk, uI, Norm);

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs.Compile(LsTrk.GridDat, momentFittingorder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                SurfaceChangerate(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    Changerate_Surface += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();

            double Changerate_Esurf;

            if (Norm)
            {
                Changerate_Esurf = sigma * Changerate_Surface.Sqrt();
            }
            else
            {
                Changerate_Esurf = sigma * Changerate_Surface;
            }

            return(Changerate_Esurf);
        }
Exemple #5
0
        /// <summary>
        /// Change-of-basis, in cell 0
        /// </summary>
        /// <param name="jCell"></param>
        /// <param name="pl"></param>
        public MultidimensionalArray GetChangeofBasisMatrix(int jCell, PolynomialList pl)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int M         = pl.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (jCell < 0 || jCell >= J)
            {
                throw new ArgumentOutOfRangeException("cell index out of range");
            }
            MultidimensionalArray Mtx = MultidimensionalArray.Create(N, M);


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

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

            CellQuadrature.GetQuadrature(new int[2] {
                N, M
            }, m_Context,
                                         (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree + pl.MaxAbsoluteDegree), // 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, jCell, 1).ExtractSubArrayShallow(0, -1, -1);
                MultidimensionalArray R = MultidimensionalArray.Create(QR.NoOfNodes, pl.Count);
                pl.Evaluate(nodes_Cell0, R);

                var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1);
                EvalResult.Multiply(1.0, R, phi_0, 0.0, "knm", "km", "kn");
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                Debug.Assert(Length == 1);

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

            return(Mtx);
        }
Exemple #6
0
        /// <summary>
        /// Computes the Integral of a given function over the zero iso-contour of the Level-Set
        /// </summary>
        /// <param name="LsTrk">Level-Set tracker</param>
        /// <param name="func">function which is integrated</param>
        /// <param name="HMForder"></param>
        /// <param name="spc">species, over whose surface is integrated</param>
        /// <returns>Integral of <param name="func">func</param> over all MPI processors</returns>
        static public double GetIntegralOverZeroLevelSet(LevelSetTracker LsTrk, ScalarFunctionEx func, int HMForder, SpeciesId spc)
        {
            using (new FuncTrace()) {
                if (LsTrk.LevelSets.Count != 1)
                {
                    throw new NotImplementedException();
                }


                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { spc }, HMForder, 1).XQuadSchemeHelper;
                // new XQuadSchemeHelper(LsTrk, momentFittingVariant);

                // Classic HMF uses order+1 for Surface Integrals and additionally 1 order higher for the HMF system
                // e.g order-2 is the cached quad rule
                if (SchemeHelper.MomentFittingVariant == XQuadFactoryHelper.MomentFittingVariants.Classic)
                {
                    HMForder -= 2;
                }

                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

                double force = 0;

                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.GridDat, HMForder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    func(i0, Length, QR.Nodes, EvalResult);
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        force += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();

                double localForce = force;
                double globalForce;
                unsafe
                {
                    csMPI.Raw.Allreduce(
                        (IntPtr)(&localForce),
                        (IntPtr)(&globalForce),
                        1,
                        csMPI.Raw._DATATYPE.DOUBLE,
                        csMPI.Raw._OP.SUM,
                        csMPI.Raw._COMM.WORLD);
                }

                return(globalForce);
            }
        }
        /// <summary>
        /// Calculate Forces acting from fluid onto the particle
        /// </summary>
        internal double[] Forces(out List <double[]>[] stressToPrintOut, CellMask cutCells)
        {
            double[]          tempForces        = new double[m_SpatialDim];
            double[]          IntegrationForces = tempForces.CloneAs();
            List <double[]>[] stressToPrint     = new List <double[]> [m_SpatialDim];
            stressToPrint[0] = new List <double[]>();
            stressToPrint[1] = new List <double[]>();
            for (int d = 0; d < m_SpatialDim; d++)
            {
                void ErrFunc(int CurrentCellID, int Length, NodeSet Ns, MultidimensionalArray result)
                {
                    int K = result.GetLength(1);
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Length, K, m_SpatialDim, m_SpatialDim);
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Length, K);
                    MultidimensionalArray Normals    = m_LevelSetTracker.DataHistories[0].Current.GetLevelSetNormals(Ns, CurrentCellID, Length);

                    for (int i = 0; i < m_SpatialDim; i++)
                    {
                        m_U[i].EvaluateGradient(CurrentCellID, Length, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }
                    m_P.Evaluate(CurrentCellID, Length, Ns, pARes);
                    for (int j = 0; j < Length; j++)
                    {
                        for (int k = 0; k < K; k++)
                        {
                            result[j, k] = StressTensor(Grad_UARes, pARes, Normals, m_FluidViscosity, k, j, m_SpatialDim, d);
                            double t = Math.PI * (1 - Math.Sign(Normals[j, k, 1])) / 2 + Math.Acos(Normals[j, k, 0]);
                            stressToPrint[d].Add(new double[] { t, result[j, k] });
                        }
                    }
                }

                int[]                         noOfIntegrals = new int[] { 1 };
                XQuadSchemeHelper             SchemeHelper  = m_LevelSetTracker.GetXDGSpaceMetrics(new[] { m_LevelSetTracker.GetSpeciesId("A") }, m_RequiredOrder, 1).XQuadSchemeHelper;
                CellQuadratureScheme          cqs           = SchemeHelper.GetLevelSetquadScheme(0, cutCells);
                ICompositeQuadRule <QuadRule> surfaceRule   = cqs.Compile(m_LevelSetTracker.GridDat, m_RequiredOrder);

                CellQuadrature.GetQuadrature(noOfIntegrals, m_GridData, surfaceRule,
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { IntegrationForces[d] = ForceTorqueSummationWithNeumaierArray(IntegrationForces[d], ResultsOfIntegration, Length); }
                                             ).Execute();
            }
            stressToPrintOut = stressToPrint.CloneAs();
            return(tempForces = IntegrationForces.CloneAs());
        }
Exemple #8
0
        void OrthonormalityTest()
        {
            Basis B   = f1.Basis;
            int   N   = B.Length;
            var   Mtx = new FullMatrix(N, N);

            double TotErrSum = 0.0;

            CellQuadrature.GetQuadrature(new int[] { N, N }, this.GridDat,
                                         (new CellQuadratureScheme(true)).Compile(GridDat, Math.Min(B.Degree * 2, 16)),
                                         delegate(MultidimensionalArray NodesUntransformed, int iKref) {
                var ret = new NodeSetController.NodeSetContainer[] {
                    GridDat.NSC.CreateContainer(NodesUntransformed, iKref)
                };
                return(ret);
            },
                                         delegate(int i0, int Length, int NoOfNodes, MultidimensionalArray EvalResult) { // void Del_Evaluate
                var BasisVal = B.CellEval(0, i0, Length);

                EvalResult.Multiply(1.0, BasisVal, BasisVal, 0.0, "jknm", "jkn", "jkm");
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                for (int i = 0; i < Length; i++)
                {
                    var MassMtx = ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1);

                    double errsum = 0;
                    for (int n = 0; n < N; n++)
                    {
                        for (int m = 0; m < N; m++)
                        {
                            double soll = (n == m) ? 1.0 : 0.0;
                            errsum     += Math.Abs(MassMtx[m, n] - soll);
                        }
                    }

                    TotErrSum += errsum;
                }
            }).Execute();


            Console.WriteLine("orthonormality error sum:" + TotErrSum);
        }
Exemple #9
0
        public static double GetKineticDissipation(LevelSetTracker LsTrk, DGField[] Velocity, double[] mu, int momentFittingOrder, int HistInd = 1)
        {
            using (new FuncTrace()) {
                int D = LsTrk.GridDat.SpatialDimension;
                if (Velocity.Count() != D)
                {
                    throw new ArgumentException();
                }
                if (LsTrk.SpeciesIdS.Count != mu.Length)
                {
                    throw new ArgumentException();
                }

                double dE = 0.0;

                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), momentFittingOrder, HistInd).XQuadSchemeHelper;

                for (int iSpc = 0; iSpc < LsTrk.SpeciesIdS.Count; iSpc++)
                {
                    SpeciesId spcId = LsTrk.SpeciesIdS[iSpc];
                    double    _mu   = mu[iSpc];

                    var Uspc = Velocity.Select(u => (u as XDGField).GetSpeciesShadowField(spcId)).ToArray();
                    ScalarFunctionEx changerate_dEspc = GetSpeciesKineticDissipationFunc(Uspc, _mu);

                    CellQuadratureScheme vqs = SchemeHelper.GetVolumeQuadScheme(spcId);
                    CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                                 vqs.Compile(LsTrk.GridDat, momentFittingOrder),
                                                 delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                        changerate_dEspc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                    },
                                                 delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                        for (int i = 0; i < Length; i++)
                        {
                            dE += ResultsOfIntegration[i, 0];
                        }
                    }
                                                 ).Execute();
                }

                return(dE);
            }
        }
Exemple #10
0
        /// <summary>
        /// Computes the energy stored in the fluid interface of a two-phase flow.
        /// </summary>
        /// <param name="LsTrk"></param>
        /// <param name="sigma"></param>
        public static double GetSurfaceEnergy(LevelSetTracker LsTrk, double sigma)
        {
            using (new FuncTrace()) {
                if (LsTrk.LevelSets.Count != 1)
                {
                    throw new NotImplementedException();
                }

                double totSurface = 0;


                int order = 0;
                if (LsTrk.GetCachedOrders().Count > 0)
                {
                    order = LsTrk.GetCachedOrders().Max();
                }
                else
                {
                    order = 1;
                }

                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, order, 1).XQuadSchemeHelper;
                //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, LsTrk.GetSpeciesId("A"));
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.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++)
                    {
                        totSurface += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();

                return(totSurface * sigma);
            }
        }
        /// <summary>
        /// Calculate Forces acting from fluid onto the particle
        /// </summary>
        internal double Torque(double[] position, CellMask cutCells)
        {
            double tempTorque = new double();

            void ErrFunc2(int j0, int Len, NodeSet Ns, MultidimensionalArray result)
            {
                int K = result.GetLength(1);
                MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, m_SpatialDim, m_SpatialDim);;
                MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);
                MultidimensionalArray Normals    = m_LevelSetTracker.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                for (int i = 0; i < m_SpatialDim; i++)
                {
                    m_U[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                }
                m_P.Evaluate(j0, Len, Ns, pARes);
                for (int j = 0; j < Len; j++)
                {
                    MultidimensionalArray Ns_Global = Ns.CloneAs();
                    m_LevelSetTracker.GridDat.TransformLocal2Global(Ns, Ns_Global, j0 + j);
                    for (int k = 0; k < K; k++)
                    {
                        result[j, k] = TorqueStressTensor(Grad_UARes, pARes, Normals, Ns_Global, m_FluidViscosity, k, j, position);
                    }
                }
            }

            var SchemeHelper2         = m_LevelSetTracker.GetXDGSpaceMetrics(new[] { m_LevelSetTracker.GetSpeciesId("A") }, m_RequiredOrder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, cutCells);

            CellQuadrature.GetQuadrature(new int[] { 1 }, m_LevelSetTracker.GridDat, cqs2.Compile(m_LevelSetTracker.GridDat, m_RequiredOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                ErrFunc2(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                tempTorque = ForceTorqueSummationWithNeumaierArray(tempTorque, ResultsOfIntegration, Length);
            }
                                         ).Execute();
            return(tempTorque);
        }
Exemple #12
0
        public static void ProjectEnergyBalanceNorm(this SinglePhaseField err, double alpha, XDGField P, VectorField <XDGField> U, ConventionalDGField[] Umean, SinglePhaseField C,
                                                    double muA, double muB, double sigma, int momentFittingOrder)
        {
            var LsTrk = U[0].Basis.Tracker;
            int D     = LsTrk.GridDat.SpatialDimension;

            ScalarFunctionEx ErrFunc = GetEnergyBalanceFunc(P, U, Umean, C, muA, muB, sigma, true);

            var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingOrder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs.Compile(LsTrk.GridDat, momentFittingOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    err.SetMeanValue(i0 + i, ResultsOfIntegration[i, 0].Sqrt());
                }
            }
                                         ).Execute();
        }
Exemple #13
0
        public static double GetInterfaceShearViscosityEnergyCR(LevelSetTracker LsTrk, ConventionalDGField[] uI, double muI, int momentFittingOrder)
        {
            double shearViscEnergy = 0.0;

            ScalarFunctionEx shearViscEnergyFunc = GetInterfaceShearViscosityEnergyCRFunc(LsTrk, uI, false);

            var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingOrder, 1).XQuadSchemeHelper;
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs.Compile(LsTrk.GridDat, momentFittingOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                shearViscEnergyFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    shearViscEnergy += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();

            return(muI * shearViscEnergy);
        }
        void SpecialProjection(LevelSetTracker LsTrk, int order, DGField[] Uin, VectorField <SinglePhaseField> Uout)
        {
            var CC   = LsTrk.Regions.GetCutCellMask();
            var gDat = LsTrk.GridDat;

            // get quadrature rules
            // ====================

            //XQuadSchemeHelper H = new XQuadSchemeHelper(LsTrk, MomentFittingVariant);
            var H = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, order, 1).XQuadSchemeHelper;
            CellQuadratureScheme                      cqs      = H.GetLevelSetquadScheme(0, CC);
            ICompositeQuadRule <QuadRule>             surfRule = cqs.Compile(gDat, order);
            ICompositeQuadRule <CellBoundaryQuadRule> bndyRule = (new CellBoundaryQuadratureScheme(true, CC)).Compile(gDat, order);



            // Compute Mass matrix and RHS for the 'strange' projection
            // ========================================================
            int L = CC.NoOfItemsLocally;
            var Q = new QuadratureKernels(Uin, L);

            Q.BlockCnt = 0;
            CellQuadrature.GetQuadrature(
                new int[] { Q.Nnx + Q.D, Q.Nnx },
                gDat,
                surfRule,
                Q.Evaluate, Q.SaveIntegrationResults_surf).Execute();
            Debug.Assert(Q.BlockCnt == L);

            Q.BlockCnt = 0;
            CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(
                new int[] { Q.Nnx + Q.D, Q.Nnx },
                gDat,
                bndyRule,
                Q.Evaluate, Q.SaveIntegrationResults_bndy).Execute();

            Debug.Assert(Q.BlockCnt == L);

            // solve the non-diagonal mass matrix systems
            // ==========================================

            int BlkCnt = 0;

            foreach (int jCell in CC.ItemEnum)
            {
                var MassMatrix = Q.MassMatrix.ExtractSubArrayShallow(BlkCnt, -1, -1);
                var RHS        = Q.RHS.ExtractSubArrayShallow(BlkCnt, -1, -1);

                // Die "Massenmatrix" muss nicht unbedingt invbar sein, daher: Least-Squares solve
                MassMatrix.LeastSquareSolve(RHS);

                for (int d = 0; d < Q.D; d++)
                {
                    for (int n = 0; n < Q.Nnx; n++)
                    {
                        Uout[d].Coordinates[jCell, n] = RHS[n, d];
                    }
                }

                BlkCnt++;
            }
        }
Exemple #15
0
        /// <summary>
        /// Calculates the Torque around the center of mass
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="momentFittingVariant"></param>
        /// <param name="muA"></param>
        /// <param name="particleRadius"></param>
        /// <returns></returns>
        static public void GetCellValues(VectorField <XDGField> U, XDGField P,
                                         double muA, double particleRadius, SinglePhaseField P_atIB, SinglePhaseField gradU_atIB, SinglePhaseField gradUT_atIB)
        {
            var LsTrk = U[0].Basis.Tracker;
            int D     = LsTrk.GridDat.SpatialDimension;
            var UA    = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();

            if (D > 2)
            {
                throw new NotImplementedException("Currently only 2D cases supported");
            }

            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Cell values calculated by: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            ConventionalDGField pA = null;
            double circumference   = new double();

            pA = P.GetSpeciesShadowField("A");

            for (int n = 0; n < 4; n++)
            {
                ScalarFunctionEx ErrFunc_CellVal = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                    // Evaluate tangential velocity to level-set surface
                    var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                    for (int i = 0; i < D; i++)
                    {
                        UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1));
                    }

                    pA.Evaluate(j0, Len, Ns, pARes);

                    for (int j = 0; j < Len; j++)
                    {
                        for (int k = 0; k < K; k++)
                        {
                            double acc  = 0.0;
                            double acc2 = 0.0;
                            switch (n)
                            {
                            case 0:     // Pressure part


                                acc += pARes[j, k] * Normals[j, k, 0];
                                acc *= -Normals[j, k, 1] * particleRadius;


                                acc2 += pARes[j, k] * Normals[j, k, 1];
                                acc2 *= Normals[j, k, 0] * particleRadius;

                                result[j, k] = acc + acc2;
                                break;

                            case 1:                                                           // GradU part

                                acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times
                                acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                acc *= -Normals[j, k, 1] * particleRadius;

                                acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                acc2 *= Normals[j, k, 0] * particleRadius;

                                result[j, k] = acc + acc2;
                                break;

                            case 2:                                                           // GradU_T part

                                acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times
                                acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                acc *= -Normals[j, k, 1] * particleRadius;


                                acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // Attention was 2 times
                                acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                acc2 *= Normals[j, k, 0] * particleRadius;

                                result[j, k] = acc + acc2;
                                break;

                            case 3:     // Standardization with radians

                                result[j, k] = 1;
                                break;

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



                var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //   new XQuadSchemeHelper(LsTrk, momentFittingVariant, );
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.GridDat, RequiredOrder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc_CellVal(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        switch (n)
                        {
                        case 0:
                            P_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]);
                            break;

                        case 1:
                            gradU_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]);
                            break;

                        case 2:
                            gradUT_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]);
                            break;

                        case 3:
                            circumference += ResultsOfIntegration[i, 0];
                            P_atIB.SetMeanValue(i0, P_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]);
                            gradU_atIB.SetMeanValue(i0, gradU_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]);
                            gradUT_atIB.SetMeanValue(i0, gradUT_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]);
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                }

                                             ).Execute();
            }

            Console.WriteLine("Circle circumference: " + circumference);
        }
Exemple #16
0
        /// <summary>
        /// Update forces and torque acting from fluid onto the particle
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="LsTrk"></param>
        /// <param name="muA"></param>
        public void UpdateForcesAndTorque(VectorField <SinglePhaseField> U, SinglePhaseField P,
                                          LevelSetTracker LsTrk,
                                          double muA)
        {
            if (skipForceIntegration)
            {
                skipForceIntegration = false;
                return;
            }

            int D = LsTrk.GridDat.SpatialDimension;
            // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            var UA = U.ToArray();

            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max();
            //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder);

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);


            ConventionalDGField pA = null;

            //pA = P.GetSpeciesShadowField("A");
            pA = P;

            #region Force
            double[] forces = new double[D];
            for (int d = 0; d < D; d++)
            {
                ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                    // Evaluate tangential velocity to level-set surface
                    var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);


                    for (int i = 0; i < D; i++)
                    {
                        UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }

                    pA.Evaluate(j0, Len, Ns, pARes);

                    if (LsTrk.GridDat.SpatialDimension == 2)
                    {
                        for (int j = 0; j < Len; j++)
                        {
                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0.0;
                                // pressure
                                switch (d)
                                {
                                case 0:
                                    acc += (pARes[j, k]) * Normals[j, k, 0];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                    break;

                                case 1:
                                    acc += (pARes[j, k]) * Normals[j, k, 1];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }

                                result[j, k] = acc;
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0; j < Len; j++)
                        {
                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0.0;

                                // pressure
                                switch (d)
                                {
                                case 0:
                                    acc += pARes[j, k] * Normals[j, k, 0];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2];
                                    break;

                                case 1:
                                    acc += pARes[j, k] * Normals[j, k, 1];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2];
                                    break;

                                case 2:
                                    acc += pARes[j, k] * Normals[j, k, 2];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1];
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }

                                result[j, k] = acc;
                            }
                        }
                    }
                };

                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, );

                //CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, this.cutCells_P(LsTrk));


                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.GridDat, RequiredOrder), //  agg.HMForder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        forces[d] += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();
            }
            #endregion

            #region Torque
            double           torque   = 0;
            ScalarFunctionEx ErrFunc2 = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                int K = result.GetLength(1); // No nof Nodes
                MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                // Evaluate tangential velocity to level-set surface
                var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                for (int i = 0; i < D; i++)
                {
                    UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                }

                //var trafo = LsTrk.GridDat.Edges.Edge2CellTrafos;
                //var trafoIdx = LsTrk.GridDat.TransformLocal2Global(Ns)
                //var transFormed = trafo[trafoIdx].Transform(Nodes);
                //var newVertices = transFormed.CloneAs();
                //GridData.TransformLocal2Global(transFormed, newVertices, jCell);


                MultidimensionalArray tempArray = Ns.CloneAs();

                LsTrk.GridDat.TransformLocal2Global(Ns, tempArray, j0);

                pA.Evaluate(j0, Len, Ns, pARes);

                for (int j = 0; j < Len; j++)
                {
                    for (int k = 0; k < K; k++)
                    {
                        double acc  = 0.0;
                        double acc2 = 0.0;

                        // Calculate the torque around a circular particle with a given radius (Paper Wan and Turek 2005)

                        acc += (pARes[j, k] * Normals[j, k, 0]);
                        acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                        acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                        acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                        //acc *= -Normals[j, k, 1] * this.radius_P;
                        acc *= -Normals[j, k, 1] * (this.currentPos_P[0][1] - tempArray[k, 1]).Abs();


                        acc2 += pARes[j, k] * Normals[j, k, 1];
                        acc2 -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                        acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                        acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                        //acc2 *= Normals[j, k, 0] * this.radius_P;
                        acc2 *= Normals[j, k, 0] * (this.currentPos_P[0][0] - tempArray[k, 0]).Abs();

                        result[j, k] = acc + acc2;
                    }
                }
            };

            var SchemeHelper2 = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
            //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, );
            //CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());
            CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, this.cutCells_P(LsTrk));

            CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                         cqs2.Compile(LsTrk.GridDat, RequiredOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                ErrFunc2(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    torque += ResultsOfIntegration[i, 0];
                }
            }

                                         ).Execute();

            double   underrelaxationFT = 1.0;
            double[] temp_underR       = new double[D + 1];
            for (int k = 0; k < D + 1; k++)
            {
                temp_underR[k] = underrelaxation_factor;
            }
            if (iteration_counter_P == 0)
            {
                underrelaxationFT = 1;
            }
            else if (underrelaxationFT_constant == true)
            {
                underrelaxationFT = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
            }
            else if (underrelaxationFT_constant == false)
            {
                //double[] temp_underR = new double[D + 1];
                bool underrelaxation_ok = false;
                underrelaxationFT_exponent = 1;
                for (int j = 0; j < D; j++)
                {
                    underrelaxation_ok = false;
                    temp_underR[j]     = underrelaxation_factor;
                    for (int i = 0; underrelaxation_ok == false; i++)
                    {
                        if (Math.Abs(temp_underR[j] * forces[j]) > Math.Abs(forces_P[0][j]))
                        {
                            underrelaxationFT_exponent -= 1;
                            temp_underR[j]              = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                        }
                        else
                        {
                            underrelaxation_ok = true;
                            if (underrelaxationFT_exponent > -0)
                            {
                                underrelaxationFT_exponent = -0;
                                temp_underR[j]             = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                            }
                        }
                    }
                }
                underrelaxation_ok = false;
                temp_underR[D]     = underrelaxation_factor;
                for (int i = 0; underrelaxation_ok == false; i++)
                {
                    if (Math.Abs(temp_underR[D] * torque) > Math.Abs(torque_P[0]))
                    {
                        underrelaxationFT_exponent -= 1;
                        temp_underR[D]              = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                    }
                    else
                    {
                        underrelaxation_ok = true;
                        if (underrelaxationFT_exponent > -0)
                        {
                            underrelaxationFT_exponent = -0;
                            temp_underR[D]             = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                        }
                    }
                }
            }

            double[] forces_underR = new double[D];
            for (int i = 0; i < D; i++)
            {
                forces_underR[i] = temp_underR[i] * forces[i] + (1 - temp_underR[i]) * forces_P[0][i];
            }
            double torque_underR = temp_underR[D] * torque + (1 - temp_underR[D]) * torque_P[0];
            this.forces_P.Insert(0, forces_underR);
            forces_P.Remove(forces_P.Last());
            this.torque_P.Remove(torque_P.Last());
            this.torque_P.Insert(0, torque_underR);

            #endregion
        }
Exemple #17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="CellPairs">
        /// 1st index: list of cells <br/>
        /// 2nd index: in {0, 1}
        /// </param>
        /// <param name="M">
        /// 1st index: corresponds with 1st index of <paramref name="CellPairs"/><br/>
        /// 2nd index: matrix row index <br/>
        /// 3rd index: matrix column index
        /// </param>
        /// <param name="Minv">the inverse of <paramref name="M"/></param>
        /// <remarks>
        /// Let \f$ K_j \f$ and \f$ K_i \f$ be two different cells with a linear-affine
        /// transformation to the reference element.
        /// Here, \f$ j \f$=<paramref name="CellPairs"/>[a,0] and \f$ i \f$=<paramref name="CellPairs"/>[a,1].
        /// The DG-basis in these cells can uniquely be represented as
        /// \f[
        /// \phi_{j n} (\vec{x}) = p_n (\vec{x}) \vec{1}_{K_j} (\vec{x})
        /// \textrm{ and }
        /// \phi_{i m} (\vec{x}) = q_m (\vec{x}) \vec{1}_{K_i} (\vec{x})
        /// \f]
        /// where \f$ \vec{1}_X \f$ denotes the characteristic function for set \f$ X \f$
        /// and \f$ p_n\f$  and \f$ p_m\f$  are polynomials.
        /// Then, for the output \f$ M \f$ =<paramref name="M"/>[a,-,-] fulfills
        /// \f[
        /// \phi_{j n} + \sum_{m} M_{m n} \phi_{i m}
        /// =
        /// p_n \vec{1}_{K_j \cup K_i}
        /// \f]
        /// </remarks>
        public void GetExtrapolationMatrices(int[,] CellPairs, MultidimensionalArray M, MultidimensionalArray Minv = null)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int Esub      = CellPairs.GetLength(0);
            int JE        = this.GridDat.iLogicalCells.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

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

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


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

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

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


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

                Debug.Assert(jCell0 < J);

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

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

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

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


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

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

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

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

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

                // store
                if (!swap)
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    }
                }
                else
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    }
                }
            }
        }
Exemple #18
0
        static internal void ComputeMassMatrixBlocks(
            IEnumerable <SpeciesId> _SpeciesIds,
            out Dictionary <SpeciesId, MassMatrixBlockContainer> Result,
            Basis b,
            XDGSpaceMetrics homie)
        {
            using (var tracer = new FuncTrace()) {
                if (b is XDGBasis)
                {
                    throw new ArgumentException();
                }
                var ctx = homie.GridDat;

                Result = new Dictionary <SpeciesId, MassMatrixBlockContainer>();
                var schemeHelper = homie.XQuadSchemeHelper;
                int Nnx          = b.Length;

                int quadorder = homie.CutCellQuadOrder;


                // define domains and allocate memory
                // ==================================


                foreach (var Species in _SpeciesIds)   // loop over species...

                // interation dom
                {
                    var _IntegrationDomain = homie.LevelSetRegions.GetSpeciesMask(Species).Intersect(homie.LevelSetRegions.GetCutCellMask());

                    // domain for mass-matrix blocks (include agglomeration targets)
                    var _BlockDomain = _IntegrationDomain; //.Union(Agg.GetAgglomerator(Species).AggInfo.AllAffectedCells);

                    // alloc mem for blocks
                    var _MassMatrixBlocksSpc = MultidimensionalArray.Create(_BlockDomain.NoOfItemsLocally, Nnx, Nnx);

                    // Subgrid index to cell index
                    int[] _jSub2jCell = _BlockDomain.ItemEnum.ToArray();

                    // cell to subgrid index
                    //Dictionary<int, int> _jCell2jSub;
                    //if (Agg.GetAgglomerator(Species).AggInfo.AgglomerationPairs.Length > 0) {
                    //    _jCell2jSub = new Dictionary<int, int>();
                    //    for (int i = 0; i < _jSub2jCell.Length; i++) {
                    //        _jCell2jSub.Add(_jSub2jCell[i], i);
                    //    }
                    //} else {
                    //    _jCell2jSub = null;
                    //}

                    Result.Add(Species, new MassMatrixBlockContainer()
                    {
                        IntegrationDomain = _IntegrationDomain,
                        MassMatrixBlocks  = _MassMatrixBlocksSpc,
                        //jCell2jSub = _jCell2jSub,
                        jSub2jCell = _jSub2jCell
                    });
                }

                // compute blocks
                // ==============

                foreach (var Species in _SpeciesIds)
                {
                    // get quad scheme
                    CellQuadratureScheme scheme = schemeHelper.GetVolumeQuadScheme(Species, IntegrationDomain: Result[Species].IntegrationDomain);

                    // result storage
                    var MassMatrixBlocksSpc = Result[Species].MassMatrixBlocks;

                    tracer.Info("mass matrix quad order: " + quadorder);

                    // compute the products of the basis functions:
                    int      BlockCnt     = -1;
                    int[]    BlockCell    = Result[Species].jSub2jCell;
                    CellMask speciesCells = homie.LevelSetRegions.GetSpeciesMask(Species);
                    CellQuadrature.GetQuadrature(
                        new int[] { Nnx, Nnx },
                        ctx,
                        scheme.Compile(ctx, quadorder),
                        delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                        // Del_Evaluate
                        // ~~~~~~~~~~~~~
                        var BasisVal = b.CellEval(QR.Nodes, i0, Length);
                        EvalResult.Multiply(1.0, BasisVal, BasisVal, 0.0, "ikmn", "ikm", "ikn");
                    },
                        delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                        // Del_SaveIntegrationResults
                        // ~~~~~~~~~~~~~~~~~~~~~~~~~~

                        for (int i = 0; i < Length; i++)
                        {
                            int jCell = i0 + i;
                            BlockCnt++;

                            // insert ID block in agglomeration target cells (if necessary):
                            // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                            var Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1);
                            while (BlockCell[BlockCnt] < jCell)
                            {
                                // agglomeration source/target cell that is not cut
                                // mass matrix is identity (full) or zero (void)
                                Block.Clear();
                                if (speciesCells.Contains(BlockCell[BlockCnt]))
                                {
                                    // cell is full
                                    for (int nn = 0; nn < Nnx; nn++)
                                    {
                                        Block[nn, nn] = 1.0;
                                    }
                                }
                                BlockCnt++;
                                Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1);
                            }

                            // store computed block
                            // - - - - - - - - - - -
                            Debug.Assert(BlockCell[BlockCnt] == jCell);
                            MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1)
                            .Set(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
#if DEBUG
                            for (int n = 0; n < Nnx; n++)
                            {
                                for (int m = 0; m < Nnx; m++)
                                {
                                    Debug.Assert(Block[n, m] == Block[m, n]);
                                }
                            }
#endif
                        }
                    }).Execute();
                    // ------------------------------------ quadrature end.

                    BlockCnt++;
                    while (BlockCnt < MassMatrixBlocksSpc.GetLength(0))
                    {
                        // agglomeration source/target cell that is not cut
                        // mass matrix is identity (full) or zero (void)
                        var Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1);
                        Block.Clear();
                        if (speciesCells.Contains(BlockCell[BlockCnt]))
                        {
                            // cell is full
                            for (int nn = 0; nn < Nnx; nn++)
                            {
                                Block[nn, nn] = 1.0;
                            }
                        }
                        BlockCnt++;
                    }


                    /*
                     * // test mass matrix for positive definiteness
                     * {
                     *  int JSUB = MassMatrixBlocksSpc.GetLength(0);
                     *  SubGrid Idom = null;
                     *
                     *  int failCount = 0;
                     *  var PosDefiniteTest = new FullMatrix(Nnx, Nnx);
                     *
                     *  for (int jsub = 0; jsub < JSUB; jsub++) {
                     *      PosDefiniteTest.Clear();
                     *      PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), 1.0);
                     *
                     *      try {
                     *          PosDefiniteTest.Clear();
                     *          PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), 1.0);
                     *          PosDefiniteTest.InvertSymmetrical();
                     *
                     *          //PosDefiniteTest.Clear();
                     *          //PosDefiniteTest.AccEye(1.0);
                     *          //PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), -1.0);
                     *          //PosDefiniteTest.InvertSymmetrical();
                     *      } catch (ArithmeticException ae) {
                     *          if (Idom == null)
                     *              Idom = new SubGrid(scheme.Domain);
                     *
                     *          int jCell = Idom.SubgridIndex2LocalCellIndex[jsub];
                     *          long Gid = Tracker.GridDat.Cells.GetCell(jCell).GlobalID;
                     *
                     *
                     *          double volFrac = Tracker.GetSpeciesVolume(jCell, Species)/ctx.Cells.GetCellVolume(jCell);
                     *
                     *          var errString = string.Format("Indefinite mass matrix in cell: globalId = {0}, local index = {1}, species {2}; \n   cell volume fraction: {3};\n   [{4}]", Gid, jCell, Tracker.GetSpeciesName(Species), volFrac, ae.Message);
                     *          tracer.Logger.Error(errString);
                     *          //Console.WriteLine(errString);
                     *          failCount++;
                     *      }
                     *  }
                     *
                     *  if (failCount > 0) {
                     *      var errString = string.Format("Indefinite mass matrix in {0} of {1} cut cells", failCount, JSUB);
                     *      tracer.Logger.Error(errString);
                     *      Console.WriteLine(errString);
                     *  } else {
                     *      Console.WriteLine("No indefinite mass matrix blocks");
                     *  }
                     *
                     * }
                     * // */

                    // backup before agglomeration (required if we wanna treat e.g. velocity in DG and pressure in XDG)
                    //MultidimensionalArray[] massMatrixBlocksB4Agglom = new MultidimensionalArray[Result[Species].jSub2jCell.Length];
                    //Result[Species].MassMatrixBlocks_B4Agglom = massMatrixBlocksB4Agglom;
                    //var _jCell2jSub = Result[Species].jCell2jSub;
                    //int J = ctx.Cells.NoOfLocalUpdatedCells;
                    //foreach (var pair in Agg.GetAgglomerator(Species).AggInfo.AgglomerationPairs) {

                    //    foreach (int jCell in new int[] { pair.jCellSource, pair.jCellTarget }) { // create a backup of source and target cell
                    //        if (jCell >= J)
                    //            continue;

                    //        int jSub = _jCell2jSub[jCell];

                    //        if (massMatrixBlocksB4Agglom[jSub] == null) {
                    //            massMatrixBlocksB4Agglom[jSub] = MassMatrixBlocksSpc.ExtractSubArrayShallow(jSub, -1, -1).CloneAs();
                    //        }
                    //    }
                    //}

                    // agglomeration
                    //Agg.GetAgglomerator(Species).ManipulateMassMatrixBlocks(MassMatrixBlocksSpc, b, Result[Species].jSub2jCell, Result[Species].jCell2jSub);
                    //throw new NotImplementedException("todo");
                }
            }
        }
        /// <summary>
        /// Calculates the added damping tensor by integrating over the level set of the particle.
        /// </summary>
        /// <param name="particle">
        /// The current particle.
        /// </param>
        /// <param name="levelSetTracker">
        /// The level set tracker.
        /// </param>
        /// <param name="fluidViscosity"></param>
        /// <param name="fluidDensity"></param>
        /// <param name="dt"></param>
        /// <param name="currentPosition"></param>
        /// <returns></returns>
        internal double[,] IntegrationOverLevelSet(Particle particle, LevelSetTracker levelSetTracker, double fluidViscosity, double fluidDensity, double dt, double[] currentPosition)
        {
            double[,] addedDampingTensor = new double[6, 6];
            double alpha         = 0.5;
            int    RequiredOrder = 2;

            for (int DampingTensorID = 0; DampingTensorID < 4; DampingTensorID++)
            {
                for (int d1 = 0; d1 < 3; d1++)
                {
                    for (int d2 = 0; d2 < 3; d2++)
                    {
                        void evalfD(int j0, int Len, NodeSet Ns, MultidimensionalArray result)
                        {
                            int K = result.GetLength(1);
                            MultidimensionalArray Normals       = levelSetTracker.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);
                            MultidimensionalArray NodeSetGlobal = Ns.CloneAs();

                            if (levelSetTracker.GridDat.SpatialDimension == 2)
                            {
                                for (int j = 0; j < Len; j++)
                                {
                                    for (int k = 0; k < K; k++)
                                    {
                                        levelSetTracker.GridDat.TransformLocal2Global(Ns, NodeSetGlobal, j0 + j);
                                        double   dh    = CalculateNormalMeshSpacing(levelSetTracker, Ns, Normals, j, k);
                                        double   delta = dh * Math.Sqrt(fluidDensity) / (Math.Sqrt(alpha * fluidViscosity * dt));
                                        double   dn    = dh / (1 - Math.Exp(-delta));
                                        double[] R     = new double[3];
                                        R[0] = NodeSetGlobal[k, 0] - currentPosition[0];
                                        R[1] = NodeSetGlobal[k, 1] - currentPosition[1];
                                        R[2] = 0;
                                        double[] NormalComponent = new double[3];
                                        double   test            = NodeSetGlobal[k, 0];
                                        double   test2           = NodeSetGlobal[k, 1];
                                        NormalComponent[0] = Normals[j, k, 0];
                                        NormalComponent[1] = Normals[j, k, 1];
                                        NormalComponent[2] = 0;
                                        switch (DampingTensorID)
                                        {
                                        case 0:    //D^{vv}
                                            result[j, k] = d1 == d2 ? (1 - NormalComponent[d1] * NormalComponent[d2]) * fluidViscosity / dn : -NormalComponent[d1] * NormalComponent[d2] * fluidViscosity / dn;
                                            break;

                                        case 1:    //D^{vw}
                                            if (d1 == 2 && d2 != 2)
                                            {
                                                result[j, k] = R[1 - d2] * Math.Pow(-1, d2) * fluidViscosity / dn;
                                            }
                                            else if (d1 != 2 && d2 == 2)
                                            {
                                                result[j, k] = ((1 - NormalComponent[d1] * NormalComponent[d1]) * (-R[1 - d1]) - NormalComponent[d1] * NormalComponent[1 - d1] * R[d1]) * Math.Pow(-1, d1) * fluidViscosity / dn;
                                            }
                                            else
                                            {
                                                result[j, k] = 0;
                                            }
                                            break;

                                        case 2:    //D^{wv}
                                            if (d2 == 2 && d1 != 2)
                                            {
                                                result[j, k] = R[1 - d1] * Math.Pow(-1, d1) * fluidViscosity / dn;
                                            }
                                            else if (d2 != 2 && d1 == 2)
                                            {
                                                result[j, k] = ((1 - NormalComponent[d2] * NormalComponent[d2]) * (-R[1 - d2]) - NormalComponent[d2] * NormalComponent[1 - d2] * R[d2]) * Math.Pow(-1, d2) * fluidViscosity / dn;
                                            }
                                            else
                                            {
                                                result[j, k] = 0;
                                            }
                                            break;

                                        case 3:    //D^{ww}
                                            if (d1 == d2 && d1 != 2)
                                            {
                                                result[j, k] = R[1 - d1].Pow2() * fluidViscosity / dn;
                                            }
                                            else if (d1 != d2 && d1 != 2 && d2 != 2)
                                            {
                                                result[j, k] = -R[0] * R[1] * fluidViscosity / dn;
                                            }
                                            else if (d1 == 2 && d2 == 2)
                                            {
                                                result[j, k] = (((1 - NormalComponent[0] * NormalComponent[0]) * R[1] + NormalComponent[0] * NormalComponent[1] * R[0]) * R[1] + ((1 - NormalComponent[1] * NormalComponent[1]) * R[0] + NormalComponent[0] * NormalComponent[1] * R[1]) * R[0]) * fluidViscosity / dn;
                                            }
                                            else
                                            {
                                                result[j, k] = 0;
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                throw new NotImplementedException("Currently the calculation of the Damping tensors is only available for 2D");
                            }
                        }

                        var SchemeHelper         = levelSetTracker.GetXDGSpaceMetrics(new[] { levelSetTracker.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                        CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, particle.CutCells_P(levelSetTracker));
                        CellQuadrature.GetQuadrature(new int[] { 1 }, levelSetTracker.GridDat,
                                                     cqs.Compile(levelSetTracker.GridDat, RequiredOrder),
                                                     delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                            evalfD(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                        },
                                                     delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                            for (int l = 0; l < Length; l++)
                            {
                                switch (DampingTensorID)
                                {
                                case 0:
                                    addedDampingTensor[d1, d2] += ResultsOfIntegration[l, 0];
                                    break;

                                case 1:
                                    addedDampingTensor[d1, d2 + 3] += ResultsOfIntegration[l, 0];
                                    break;

                                case 2:
                                    addedDampingTensor[d1 + 3, d2] += ResultsOfIntegration[l, 0];
                                    break;

                                case 3:
                                    addedDampingTensor[d1 + 3, d2 + 3] += ResultsOfIntegration[l, 0];
                                    break;
                                }
                            }
                        }
                                                     ).Execute();
                    }
                }
            }
            if (levelSetTracker.GridDat.SpatialDimension == 2)
            {
                return(ModifyDampingTensor2D(addedDampingTensor));
            }
            else
            {
                throw new NotImplementedException("Currently the calculation of the Damping tensors is only available for 2D");
            }
        }
Exemple #20
0
        /// <summary>
        /// Update Forces and Torque acting from fluid onto the particle
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="LsTrk"></param>
        /// <param name="muA"></param>
        public void UpdateForcesAndTorque(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double dt, double fluidDensity, bool NotFullyCoupled)
        {
            if (skipForceIntegration)
            {
                skipForceIntegration = false;
                return;
            }
            HydrodynamicForces[0][0] = 0;
            HydrodynamicForces[0][1] = 0;
            HydrodynamicTorque[0]    = 0;
            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);
            double[]            Forces = new double[SpatialDim];
            SinglePhaseField[]  UA     = U.ToArray();
            ConventionalDGField pA     = null;

            pA = P;
            if (IncludeTranslation)
            {
                for (int d = 0; d < SpatialDim; d++)
                {
                    void ErrFunc(int CurrentCellID, int Length, NodeSet Ns, MultidimensionalArray result)
                    {
                        int NumberOfNodes = result.GetLength(1);
                        MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Length, NumberOfNodes, SpatialDim, SpatialDim);
                        MultidimensionalArray pARes      = MultidimensionalArray.Create(Length, NumberOfNodes);
                        var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, CurrentCellID, Length);

                        for (int i = 0; i < SpatialDim; i++)
                        {
                            UA[i].EvaluateGradient(CurrentCellID, Length, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                        }
                        pA.Evaluate(CurrentCellID, Length, Ns, pARes);
                        for (int j = 0; j < Length; j++)
                        {
                            for (int k = 0; k < NumberOfNodes; k++)
                            {
                                result[j, k] = ForceIntegration.CalculateStressTensor(Grad_UARes, pARes, Normals, muA, k, j, this.SpatialDim, d);
                            }
                        }
                    }

                    var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                    CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, CutCells_P(LsTrk));
                    CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                                 cqs.Compile(LsTrk.GridDat, RequiredOrder),
                                                 delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
                    {
                        ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                    },
                                                 delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration)
                    {
                        Forces[d] = ParticleAuxillary.ForceTorqueSummationWithNeumaierArray(Forces[d], ResultsOfIntegration, Length);
                    }
                                                 ).Execute();
                }
            }

            double Torque = 0;

            if (IncludeRotation)
            {
                void ErrFunc2(int j0, int Len, NodeSet Ns, MultidimensionalArray result)
                {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, SpatialDim, SpatialDim);;
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);
                    // Evaluate tangential velocity to level-set surface
                    var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                    for (int i = 0; i < SpatialDim; i++)
                    {
                        UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }
                    pA.Evaluate(j0, Len, Ns, pARes);
                    for (int j = 0; j < Len; j++)
                    {
                        MultidimensionalArray tempArray = Ns.CloneAs();
                        LsTrk.GridDat.TransformLocal2Global(Ns, tempArray, j0 + j);
                        for (int k = 0; k < K; k++)
                        {
                            result[j, k] = ForceIntegration.CalculateTorqueFromStressTensor2D(Grad_UARes, pARes, Normals, tempArray, muA, k, j, Position[0]);
                        }
                    }
                }

                var SchemeHelper2         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, CutCells_P(LsTrk));
                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs2.Compile(LsTrk.GridDat, RequiredOrder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
                {
                    ErrFunc2(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration)
                {
                    Torque = ParticleAuxillary.ForceTorqueSummationWithNeumaierArray(Torque, ResultsOfIntegration, Length);
                }
                                             ).Execute();
            }
            // add gravity
            {
                Forces[1] += (particleDensity - fluidDensity) * Area_P * GravityVertical;
            }
            // Sum forces and moments over all MPI processors
            // ==============================================
            {
                int      NoOfVars    = 1 + SpatialDim;
                double[] StateBuffer = new double[NoOfVars];
                StateBuffer[0] = Torque;
                for (int d = 0; d < SpatialDim; d++)
                {
                    StateBuffer[1 + d] = Forces[d];
                }
                double[] GlobalStateBuffer = StateBuffer.MPISum();
                Torque = GlobalStateBuffer[0];
                for (int d = 0; d < SpatialDim; d++)
                {
                    Forces[d] = GlobalStateBuffer[1 + d];
                }
            }
            if (neglectAddedDamping == false)
            {
                double fest = Forces[0];
                Forces[0] = Forces[0] + AddedDampingCoefficient * dt * (AddedDampingTensor[0, 0] * TranslationalAcceleration[0][0] + AddedDampingTensor[1, 0] * TranslationalAcceleration[0][1] + AddedDampingTensor[0, 2] * RotationalAcceleration[0]);
                Forces[1] = Forces[1] + AddedDampingCoefficient * dt * (AddedDampingTensor[0, 1] * TranslationalAcceleration[0][0] + AddedDampingTensor[1, 1] * TranslationalAcceleration[0][1] + AddedDampingTensor[1, 2] * RotationalAcceleration[0]);
                Torque   += AddedDampingCoefficient * dt * (AddedDampingTensor[2, 0] * TranslationalAcceleration[0][0] + AddedDampingTensor[2, 1] * TranslationalAcceleration[0][1] + AddedDampingTensor[2, 2] * RotationalAcceleration[0]);
            }

            if (iteration_counter_P == -1 || NotFullyCoupled || iteration_counter_P == 250 || stupidcounter == 0)
            {
                Console.WriteLine();
                if (iteration_counter_P == 1)
                {
                    Console.WriteLine("First iteration of the current timestep, all relaxation factors are set to 1");
                }
                if (iteration_counter_P == 250)
                {
                    Console.WriteLine("250 iterations, I'm trying to jump closer to the real solution");
                }
                for (int d = 0; d < SpatialDim; d++)
                {
                    HydrodynamicForces[0][d] = 0;
                    if (Math.Abs(Forces[d]) < ForceAndTorque_convergence * 1e-2 && ClearSmallValues == true)
                    {
                        Forces[d] = 0;
                    }
                    HydrodynamicForces[0][d] = Forces[d];
                }
                HydrodynamicTorque[0] = 0;
                if (Math.Abs(Torque) < ForceAndTorque_convergence * 1e-2 && ClearSmallValues == true)
                {
                    Torque = 0;
                }
                HydrodynamicTorque[0] = Torque;
                stupidcounter         = 1;
            }
            else
            {
                double[] RelaxatedForceAndTorque = Underrelaxation.RelaxatedForcesAndTorque(Forces, Torque, ForcesPrevIteration, TorquePrevIteration, ForceAndTorque_convergence, underrelaxation_factor, ClearSmallValues, AddaptiveUnderrelaxation, AverageDistance, iteration_counter_P);
                for (int d = 0; d < SpatialDim; d++)
                {
                    HydrodynamicForces[0][d] = RelaxatedForceAndTorque[d];
                }
                HydrodynamicTorque[0] = RelaxatedForceAndTorque[SpatialDim];
            }
            //for (int d = 0; d < SpatialDim; d++)// changes sign depending on the sign of Forces[d], should increase the convergence rate. (testing needed)
            //{
            //    if (Math.Abs(HydrodynamicForces[0][d] - Forces[0]) > Math.Abs(Forces[d]))
            //    {
            //        HydrodynamicForces[0][d] *= -1;
            //    }
            //}
            if (double.IsNaN(HydrodynamicForces[0][0]) || double.IsInfinity(HydrodynamicForces[0][0]))
            {
                throw new ArithmeticException("Error trying to calculate hydrodynamic forces (x). Value:  " + HydrodynamicForces[0][0]);
            }
            if (double.IsNaN(HydrodynamicForces[0][1]) || double.IsInfinity(HydrodynamicForces[0][1]))
            {
                throw new ArithmeticException("Error trying to calculate hydrodynamic forces (y). Value:  " + HydrodynamicForces[0][1]);
            }
            if (double.IsNaN(HydrodynamicTorque[0]) || double.IsInfinity(HydrodynamicTorque[0]))
            {
                throw new ArithmeticException("Error trying to calculate hydrodynamic torque. Value:  " + HydrodynamicTorque[0]);
            }
        }
Exemple #21
0
        private void ComputeAverageU <T>(IEnumerable <T> U0, VectorField <XDGField> U0mean, int order, XQuadSchemeHelper qh) where T : DGField
        {
            using (FuncTrace ft = new FuncTrace()) {
                var    CC     = this.LsTrk.Regions.GetCutCellMask();
                int    D      = this.LsTrk.GridDat.SpatialDimension;
                double minvol = Math.Pow(this.LsTrk.GridDat.Cells.h_minGlobal, D);


                //var qh = new XQuadSchemeHelper(agg);
                foreach (var Spc in this.LsTrk.SpeciesIdS)  // loop over species...
                //var Spc = this.LsTrk.GetSpeciesId("B"); {
                // shadow fields
                {
                    DGField[] U0_Spc     = U0.Select(U0_d => (U0_d is XDGField) ? ((DGField)((U0_d as XDGField).GetSpeciesShadowField(Spc))) : ((DGField)U0_d)).ToArray();
                    var       U0mean_Spc = U0mean.Select(U0mean_d => U0mean_d.GetSpeciesShadowField(Spc)).ToArray();


                    // normal cells:
                    for (int d = 0; d < D; d++)
                    {
                        U0mean_Spc[d].AccLaidBack(1.0, U0_Spc[d], this.LsTrk.Regions.GetSpeciesMask(Spc));
                    }

                    // cut cells
                    var scheme = qh.GetVolumeQuadScheme(Spc, IntegrationDomain: this.LsTrk.Regions.GetCutCellMask());
                    var rule   = scheme.Compile(this.LsTrk.GridDat, order);
                    CellQuadrature.GetQuadrature(new int[] { D + 1 }, // vector components: ( avg_vel[0], ... , avg_vel[D-1], cell_volume )
                                                 this.LsTrk.GridDat,
                                                 rule,
                                                 delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                        EvalResult.Clear();
                        for (int d = 0; d < D; d++)
                        {
                            U0_Spc[d].Evaluate(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, d));
                        }
                        var Vol = EvalResult.ExtractSubArrayShallow(-1, -1, D);
                        Vol.SetAll(1.0);
                    },
                                                 delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                        for (int i = 0; i < Length; i++)
                        {
                            int jCell = i + i0;

                            double Volume = ResultsOfIntegration[i, D];
                            if (Math.Abs(Volume) < minvol * 1.0e-12)
                            {
                                // keep current value
                                // since the volume of species 'Spc' in cell 'jCell' is 0.0, the value in this cell should have no effect
                            }
                            else
                            {
                                for (int d = 0; d < D; d++)
                                {
                                    double IntVal = ResultsOfIntegration[i, d];
                                    U0mean_Spc[d].SetMeanValue(jCell, IntVal / Volume);
                                }
                            }
                        }
                    }).Execute();
                }

#if DEBUG
                {
                    var Uncut = LsTrk.Regions.GetCutCellMask().Complement();


                    VectorField <SinglePhaseField> U0mean_check = new VectorField <SinglePhaseField>(D, new Basis(LsTrk.GridDat, 0), SinglePhaseField.Factory);
                    for (int d = 0; d < D; d++)
                    {
                        U0mean_check[d].ProjectField(1.0, U0.ElementAt(d).Evaluate,
                                                     new CellQuadratureScheme(false, Uncut).AddFixedOrderRules(LsTrk.GridDat, U0.ElementAt(d).Basis.Degree + 1));
                    }

                    foreach (var _Spc in this.LsTrk.SpeciesIdS)  // loop over species...
                    {
                        for (int d = 0; d < D; d++)
                        {
                            U0mean_check[d].AccLaidBack(-1.0, U0mean[d].GetSpeciesShadowField(_Spc), Uncut.Intersect(LsTrk.Regions.GetSpeciesMask(_Spc)));
                        }
                    }

                    double checkNorm = U0mean_check.L2Norm();
                    Debug.Assert(checkNorm < 1.0e-6);
                }
#endif


                U0mean.ForEach(F => F.CheckForNanOrInf(true, true, true));
            }
        }
Exemple #22
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 });
        }
Exemple #23
0
        /// <summary>
        /// Calculates the Torque around the center of mass
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="muA"></param>
        /// <param name="particleRadius"></param>
        /// <returns></returns>
        static public double GetTorque(VectorField <SinglePhaseField> U, SinglePhaseField P,
                                       LevelSetTracker LsTrk,
                                       double muA, double particleRadius)
        {
            var _LsTrk = LsTrk;
            int D      = _LsTrk.GridDat.SpatialDimension;
            var UA     = U.ToArray();

            //if (D > 2) throw new NotImplementedException("Currently only 2D cases supported");

            int RequiredOrder = U[0].Basis.Degree * 3;

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Torque coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            ConventionalDGField pA = null;
            double force           = new double();

            pA = P;

            ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                int K = result.GetLength(1); // No nof Nodes
                MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                // Evaluate tangential velocity to level-set surface
                var Normals = _LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                for (int i = 0; i < D; i++)
                {
                    UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                }

                pA.Evaluate(j0, Len, Ns, pARes);

                for (int j = 0; j < Len; j++)
                {
                    for (int k = 0; k < K; k++)
                    {
                        double acc  = 0.0;
                        double acc2 = 0.0;


                        // Calculate the torque around a circular particle with a given radius (Paper Wan and Turek 2005)

                        acc += pARes[j, k] * Normals[j, k, 0];
                        acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                        acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                        acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                        acc *= -Normals[j, k, 1] * particleRadius;


                        acc2 += pARes[j, k] * Normals[j, k, 1];
                        acc2 -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                        acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                        acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                        acc2 *= Normals[j, k, 0] * particleRadius;

                        result[j, k] = acc + acc2;
                    }
                }
            };

            var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
            //var SchemeHelper = new XQuadSchemeHelper(_LsTrk, momentFittingVariant, _LsTrk.GetSpeciesId("A"));
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, _LsTrk.Regions.GetCutCellMask());

            CellQuadrature.GetQuadrature(new int[] { 1 }, _LsTrk.GridDat,
                                         cqs.Compile(_LsTrk.GridDat, RequiredOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    force += ResultsOfIntegration[i, 0];
                }
            }

                                         ).Execute();


            return(force);
        }
        /// <summary>
        /// ctor.
        /// </summary>
        public NECQuadratureVolume(IGridData context,
                                   SpatialOperator DiffOp,
                                   IList <DGField> _DomainFields,
                                   IList <DGField> _ParameterFields,
                                   UnsetteledCoordinateMapping CodomainMapping,
                                   ICompositeQuadRule <QuadRule> domNrule)
            : base(context, DiffOp, _DomainFields, _ParameterFields, CodomainMapping)
        {
            // -----------------
            // quadrature object
            // -----------------

            m_Quad = CellQuadrature.GetQuadrature2(new int[] { CodomainMapping.NoOfCoordinatesPerCell }, context, domNrule,
                                                   this.EvaluateEx,
                                                   this.SaveIntegrationResults,
                                                   this.AllocateBuffers);

            int Gamma = _DomainFields.Count;

            // ------------------------
            // sort equation components
            // ------------------------

            m_NonlinSources = EquationComponentArgMapping <INonlinearSource> .GetArgMapping(DiffOp, true);

            m_NonlinFormV = EquationComponentArgMapping <INonlinVolumeForm_V> .GetArgMapping(DiffOp, true,
                                                                                             eq => ((eq.VolTerms & (TermActivationFlags.V | TermActivationFlags.UxV | TermActivationFlags.GradUxV)) != 0),
                                                                                             eq => (eq is IVolumeForm ? new NonlinVolumeFormVectorizer((IVolumeForm)eq) : null));

            m_NonlinFormGradV = EquationComponentArgMapping <INonlinVolumeForm_GradV> .GetArgMapping(DiffOp, true,
                                                                                                     eq => ((eq.VolTerms & (TermActivationFlags.UxGradV | TermActivationFlags.GradV | TermActivationFlags.GradUxGradV)) != 0),
                                                                                                     eq => (eq is IVolumeForm ? new NonlinVolumeFormVectorizer((IVolumeForm)eq) : null));

            Debug.Assert(base.m_DomainFields.Length >= Gamma);
            m_ValueRequired    = new bool[base.m_DomainFields.Length];
            m_GradientRequired = new bool[Gamma];

            // base.m_DomainFields may also contain parameter fields:
            for (int i = Gamma; i < base.m_DomainFields.Length; i++)
            {
                m_ValueRequired[i] = true;
            }

            this.m_NonlinFormV.DetermineReqFields(m_GradientRequired,
                                                  comp => ((comp.VolTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0));
            this.m_NonlinFormGradV.DetermineReqFields(m_GradientRequired,
                                                      comp => ((comp.VolTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0));
            this.m_NonlinFormV.DetermineReqFields(m_ValueRequired,
                                                  comp => ((comp.VolTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0));
            this.m_NonlinFormGradV.DetermineReqFields(m_ValueRequired,
                                                      comp => ((comp.VolTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0));
            this.m_NonlinSources.DetermineReqFields(m_ValueRequired, comp => true);
            base.m_NonlinFluxes.DetermineReqFields(m_ValueRequired, comp => true);
            base.m_NonlinFluxesEx.DetermineReqFields(m_ValueRequired, comp => true);

            // ---------
            // profiling
            // ---------

            var _CustomTimers       = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() };
            var _CustomTimers_Names = new string[] { "Flux-Eval", "Basis-Eval", "Field-Eval", "Loops", "ParametersAndNormals", "Flux-Trafo" };

            Flux_Eval                       = _CustomTimers[0];
            Flux_Trafo                      = _CustomTimers[5];
            Field_Eval                      = _CustomTimers[2];
            Basis_Eval                      = _CustomTimers[1];
            Loops                           = _CustomTimers[3];
            ParametersAndNormals            = _CustomTimers[4];
            m_Quad.CustomTimers             = m_Quad.CustomTimers.Cat(_CustomTimers);
            m_Quad.CustomTimers_Names       = m_Quad.CustomTimers_Names.Cat(_CustomTimers_Names);
            m_Quad.CustomTimers_RootPointer = new int[_CustomTimers_Names.Length];
            ArrayTools.SetAll(m_Quad.CustomTimers_RootPointer, -1);

            this.m_NonlinSources_watch   = this.m_NonlinSources.InitStopWatches(0, m_Quad);
            this.m_NonlinFormV_watch     = this.m_NonlinFormV.InitStopWatches(0, m_Quad);
            this.m_NonlinFormGradV_watch = this.m_NonlinFormGradV.InitStopWatches(0, m_Quad);
            base.m_NonlinFluxesWatches   = base.m_NonlinFluxes.InitStopWatches(0, m_Quad);
            base.m_NonlinFluxesExWatches = base.m_NonlinFluxesEx.InitStopWatches(0, m_Quad);

            // ---------------------
            // alloc multidim arrays
            // ---------------------

            m_FluxValues    = new MultidimensionalArray[m_CodomainBasisS.Length];
            m_FluxValuesTrf = new MultidimensionalArray[m_CodomainBasisS.Length];
            for (int i = 0; i < m_FluxValues.Length; i++)
            {
                if (m_NonlinFluxes[i].m_AllComponentsOfMyType.Length > 0 || m_NonlinFluxesEx[i].m_AllComponentsOfMyType.Length > 0 || m_NonlinFormGradV[i].m_AllComponentsOfMyType.Length > 0)
                {
                    m_FluxValues[i]    = new MultidimensionalArray(3);
                    m_FluxValuesTrf[i] = new MultidimensionalArray(3);

                    Basis GradBasis = base.m_CodomainBasisS[i];
                    if (m_MaxCodBasis_Gradient == null || m_MaxCodBasis_Gradient.Degree < GradBasis.Degree)
                    {
                        m_MaxCodBasis_Gradient = GradBasis;
                    }
                }
            }

            m_SourceValues = new MultidimensionalArray[m_CodomainBasisS.Length];
            for (int i = 0; i < m_SourceValues.Length; i++)
            {
                if (m_NonlinSources[i].m_AllComponentsOfMyType.Length > 0 || m_NonlinFormV[i].m_AllComponentsOfMyType.Length > 0)
                {
                    m_SourceValues[i] = new MultidimensionalArray(2);

                    Basis ValBasis = base.m_CodomainBasisS[i];
                    if (m_MaxCodBasis == null || m_MaxCodBasis.Degree < ValBasis.Degree)
                    {
                        m_MaxCodBasis = ValBasis;
                    }
                }
            }


            m_FieldValues    = new MultidimensionalArray[m_DomainFields.Length];
            m_FieldGradients = new MultidimensionalArray[Gamma];
            for (int i = 0; i < m_DomainFields.Length; i++)
            {
                if (m_ValueRequired[i])
                {
                    m_FieldValues[i] = new MultidimensionalArray(2);
                }
                if (i < Gamma && m_GradientRequired[i])
                {
                    m_FieldGradients[i] = new MultidimensionalArray(3);
                }
            }


            m_TestFuncWeighted     = new MultidimensionalArray(2);
            m_TestFuncGradWeighted = new MultidimensionalArray(3);
        }
Exemple #25
0
        static public double[] GetParticleForces(VectorField <SinglePhaseField> U, SinglePhaseField P,
                                                 LevelSetTracker LsTrk,
                                                 double muA)
        {
            int D = LsTrk.GridDat.SpatialDimension;
            // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            var UA = U.ToArray();

            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max();
            //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder);

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);


            ConventionalDGField pA = null;

            //pA = P.GetSpeciesShadowField("A");
            pA = P;

            double[] forces = new double[D];
            for (int d = 0; d < D; d++)
            {
                ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                    // Evaluate tangential velocity to level-set surface
                    var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);


                    for (int i = 0; i < D; i++)
                    {
                        UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }

                    pA.Evaluate(j0, Len, Ns, pARes);

                    if (LsTrk.GridDat.SpatialDimension == 2)
                    {
                        for (int j = 0; j < Len; j++)
                        {
                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0.0;

                                // pressure
                                switch (d)
                                {
                                case 0:
                                    acc += pARes[j, k] * Normals[j, k, 0];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                    break;

                                case 1:
                                    acc += pARes[j, k] * Normals[j, k, 1];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }

                                result[j, k] = acc;
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0; j < Len; j++)
                        {
                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0.0;

                                // pressure
                                switch (d)
                                {
                                case 0:
                                    acc += pARes[j, k] * Normals[j, k, 0];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2];
                                    break;

                                case 1:
                                    acc += pARes[j, k] * Normals[j, k, 1];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2];
                                    break;

                                case 2:
                                    acc += pARes[j, k] * Normals[j, k, 2];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1];
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }

                                result[j, k] = acc;
                            }
                        }
                    }
                };

                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, );
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.GridDat, RequiredOrder), //  agg.HMForder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        forces[d] += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();
            }

            for (int i = 0; i < D; i++)
            {
                forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]);
            }

            return(forces);
        }
Exemple #26
0
        /// <summary>
        /// computes derivatives in various ways and compares them against known values.
        /// </summary>
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            base.EndTime       = 0.0;
            base.NoOfTimesteps = 0;

            int D = this.GridData.SpatialDimension;
            int J = this.GridData.iLogicalCells.NoOfLocalUpdatedCells;

            Console.WriteLine("DerivativeTest.exe, test case #" + GRID_CASE + " ******************************");

            //var Fix = this.GridData.iGeomEdges.FaceIndices;
            //for(int iEdge = 0; iEdge < Fix.GetLength(0); iEdge++) {
            //    Debug.Assert(Fix[iEdge, 0] >= 0);
            //    Debug.Assert(Fix[iEdge, 1] >= 0);
            //}

            // sealing test
            // =================

            if (this.GridData is Foundation.Grid.Classic.GridData)
            {
                TestSealing(this.GridData);
            }

            // cell volume and edge area check, if possible
            // ===============================================


            if (this.CellVolume > 0)
            {
                double err      = 0;
                double Treshold = 1.0e-10;


                for (int j = 0; j < J; j++)
                {
                    err += Math.Abs(this.GridData.iLogicalCells.GetCellVolume(j) - this.CellVolume);
                }

                bool passed = (err < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine("Cell volume error: " + err + " passed? " + passed);
                Console.WriteLine("--------------------------------------------");
            }

            if (this.EdgeArea > 0)
            {
                double err      = 0;
                double Treshold = 1.0e-10;

                int E = this.GridData.iLogicalEdges.Count;

                for (int e = 0; e < E; e++)
                {
                    err += Math.Abs(this.GridData.iLogicalEdges.GetEdgeArea(e) - this.EdgeArea);
                }

                bool passed = (err < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine("Edge area error: " + err + " passed? " + passed);
                Console.WriteLine("--------------------------------------------");
            }

            // Orthonormality of basis in physical coords
            // ==========================================

            {
                Basis Bs      = this.f1.Basis;
                int   N       = Bs.Length;
                int   degQuad = this.GridData.iLogicalCells.GetInterpolationDegree(0) * D + Bs.Degree + 3;
                int[] jG2jL   = this.GridData.iGeomCells.GeomCell2LogicalCell;


                // mass matrix: should be identity!
                MultidimensionalArray MassMatrix = MultidimensionalArray.Create(J, N, N);

                // compute mass matrix by quadrature.
                var quad = CellQuadrature.GetQuadrature(new int[] { N, N }, base.GridData,
                                                        (new CellQuadratureScheme()).Compile(base.GridData, degQuad),
                                                        delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    NodeSet QuadNodes = QR.Nodes;
                    MultidimensionalArray BasisVals = Bs.CellEval(QuadNodes, i0, Length);
                    EvalResult.Multiply(1.0, BasisVals, BasisVals, 0.0, "jknm", "jkn", "jkm");
                },
                                                        delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    if (jG2jL != null)
                    {
                        for (int i = 0; i < Length; i++)
                        {
                            int jG = i + i0;
                            MassMatrix.ExtractSubArrayShallow(jG2jL[jG], -1, -1)
                            .Acc(1.0, ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
                        }
                    }
                    else
                    {
                        MassMatrix.SetSubArray(ResultsOfIntegration, new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, N - 1, N - 1 });
                    }
                },
                                                        cs: CoordinateSystem.Physical);
                quad.Execute();

                // check that mass matrix is Id.
                int    MaxErrorCell = -1;
                double MaxError     = -1;
                for (int j = 0; j < J; j++)
                {
                    MultidimensionalArray MassMatrix_j = MassMatrix.ExtractSubArrayShallow(j, -1, -1);
                    MassMatrix_j.AccEye(-1.0);

                    double Norm_j = MassMatrix_j.InfNorm();
                    if (Norm_j > MaxError)
                    {
                        MaxError     = Norm_j;
                        MaxErrorCell = j;
                    }
                }

                bool passed = (MaxError < 1.0e-8);
                m_passed = m_passed && passed;
                Console.WriteLine("Mass Matrix, maximum error in Cell #" + MaxErrorCell + ", mass matrix error norm: " + MaxError + " passed? " + passed);
            }

            // Broken Derivatives
            // =================

            double totalVolume = (new SubGrid(CellMask.GetFullMask(this.GridData))).Volume;

            for (int d = 0; d < D; d++)
            {
                // compute
                f1Gradient_Numerical[d].Clear();
                f1Gradient_Numerical[d].Derivative(1.0, f1, d);
                f2Gradient_Numerical[d].Clear();
                f2Gradient_Numerical[d].Derivative(1.0, f2, d);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Broken Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }

            // Flux Derivatives
            // =================
            for (int d = 0; d < D; d++)
            {
                // compute
                f1Gradient_Numerical[d].Clear();
                f1Gradient_Numerical[d].DerivativeByFlux(1.0, f1, d);
                f2Gradient_Numerical[d].Clear();
                f2Gradient_Numerical[d].DerivativeByFlux(1.0, f2, d);

                f1Gradient_Numerical[d].CheckForNanOrInf(true, true, true);
                f2Gradient_Numerical[d].CheckForNanOrInf(true, true, true);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Flux Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }


            // Linear flux Derivatives
            // =======================
            for (int d = 0; d < D; d++)
            {
                double[] korrekto = f1Gradient_Numerical[d].CoordinateVector.ToArray();

                // compute
                DerivativeByFluxLinear(f1, f1Gradient_Numerical[d], d, f1);
                DerivativeByFluxLinear(f2, f2Gradient_Numerical[d], d, f2);

                // subtract analytical
                var Errfield1 = f1Gradient_Numerical[d].CloneAs();
                Errfield1.Acc(-1, f1Gradient_Analytical[d]);

                var Errfield2 = f2Gradient_Numerical[d].CloneAs();
                Errfield2.Acc(-1, f2Gradient_Analytical[d]);

                Console.WriteLine("Linear Flux Derivatives: ");

                double Treshold = 1.0e-10;
                if (AltRefSol)
                {
                    Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold
                }
                double err1_dx = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err1_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed));

                double err2_dx = Errfield2.L2Norm() / totalVolume;
                passed   = (err2_dx < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed));

                Console.WriteLine("--------------------------------------------");
            }

            // Laplacian, nonlinear
            // ====================

            if (!AltRefSol)
            {
                var Laplace = (new ipLaplace()).Operator(1);

                Laplace.Evaluate(new DGField[] { this.f1 }, new DGField[] { this.Laplace_f1_Numerical });
                Laplace.Evaluate(new DGField[] { this.f2 }, new DGField[] { this.Laplace_f2_Numerical });

                double Treshold = 1.0e-8;

                // subtract analytical
                var Errfield1 = Laplace_f1_Numerical.CloneAs();
                Errfield1.Acc(-1, Laplace_f1_Analytical);

                var Errfield2 = Laplace_f2_Numerical.CloneAs();
                Errfield2.Acc(-1, Laplace_f2_Analytical);

                double err_Lf1 = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err_Lf1 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf1, passed));

                double err_Lf2 = Errfield2.L2Norm() / totalVolume;
                passed   = (err_Lf2 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf2, passed));

                Console.WriteLine("--------------------------------------------");
            }


            // Laplacian, linear
            // ====================

            if (!AltRefSol)
            {
                var Laplace = (new ipLaplace()).Operator(1);

                var LaplaceMtx    = new BlockMsrMatrix(this.f1.Mapping, this.Laplace_f1_Numerical.Mapping);
                var LaplaceAffine = new double[LaplaceMtx.RowPartitioning.LocalLength];

                Laplace.ComputeMatrix(this.f1.Mapping, null, this.Laplace_f1_Numerical.Mapping,
                                      LaplaceMtx, LaplaceAffine, false);

                this.Laplace_f1_Numerical.CoordinateVector.SetV(LaplaceAffine);
                LaplaceMtx.SpMV(1.0, this.f1.CoordinateVector, 1.0, this.Laplace_f1_Numerical.CoordinateVector);

                this.Laplace_f2_Numerical.CoordinateVector.SetV(LaplaceAffine);
                LaplaceMtx.SpMV(1.0, this.f2.CoordinateVector, 1.0, this.Laplace_f2_Numerical.CoordinateVector);

                // subtract analytical
                var Errfield1 = Laplace_f1_Numerical.CloneAs();
                Errfield1.Acc(-1, Laplace_f1_Analytical);

                var Errfield2 = Laplace_f2_Numerical.CloneAs();
                Errfield2.Acc(-1, Laplace_f2_Analytical);


                double Treshold = 1.0e-8;

                double err_Lf1 = Errfield1.L2Norm() / totalVolume;
                bool   passed  = (err_Lf1 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf1, passed));

                double err_Lf2 = Errfield2.L2Norm() / totalVolume;
                passed   = (err_Lf2 < Treshold);
                m_passed = m_passed && passed;
                Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf2, passed));


                // comparison of finite difference Jacobian and Operator matrix
                if (TestFDJacobian)
                {
                    this.f1.Clear();
                    var FDJbuilder = Laplace.GetFDJacobianBuilder(this.f1.Mapping.Fields, null, this.f1.Mapping,
                                                                  delegate(IEnumerable <DGField> U0, IEnumerable <DGField> Params) {
                        return;
                    });
                    var CheckMatrix = new BlockMsrMatrix(FDJbuilder.CodomainMapping, FDJbuilder.DomainMapping);
                    var CheckAffine = new double[FDJbuilder.CodomainMapping.LocalLength];
                    FDJbuilder.ComputeMatrix(CheckMatrix, CheckAffine);

                    var ErrMatrix = LaplaceMtx.CloneAs();
                    var ErrAffine = LaplaceAffine.CloneAs();
                    ErrMatrix.Acc(-1.0, CheckMatrix);
                    ErrAffine.AccV(-1.0, CheckAffine);
                    double LinfMtx = ErrMatrix.InfNorm();
                    double L2Aff   = ErrAffine.L2NormPow2().MPISum().Sqrt();
                    bool   passed1 = (LinfMtx < 1.0e-3);
                    bool   passed2 = (L2Aff < Treshold);
                    Console.WriteLine("Finite Difference Jacobian: Matrix/Affine delta norm {0} {1}, passed? {2} {3}", LinfMtx, L2Aff, passed1, passed2);
                    m_passed = m_passed && passed1;
                    m_passed = m_passed && passed2;
                }
                Console.WriteLine("--------------------------------------------");
            }



            // finally...
            // =================

            if (m_passed)
            {
                Console.WriteLine("All tests passed. *****************************");
            }
            else
            {
                Console.WriteLine("Some error above threshold. *******************");
            }

            return(0.0); // return some artificial timestep
        }