Exemple #1
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 #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
        private double PerformSurfaceQuadrature(Modes mode, IQuadRuleFactory <QuadRule> volumeFactory, IQuadRuleFactory <QuadRule> edgeFactory, SubGrid cutCellGrid, int order, Stopwatch timer)
        {
            using (new FuncTrace()) {
                CellQuadratureScheme volInstr = new CellQuadratureScheme(
                    volumeFactory, cutCellGrid.VolumeMask);
                CellBoundaryQuadratureScheme edgeInstr = new CellBoundaryQuadratureScheme(
                    new CellBoundaryFromEdgeRuleFactory <CellBoundaryQuadRule>(
                        GridData, Grid.RefElements[0], edgeFactory),
                    cutCellGrid.VolumeMask);

                ScalarFieldLevelSetIntegrator quadrature = new ScalarFieldLevelSetIntegrator(
                    levelSetTracker,
                    SinglePhaseField,
                    volInstr.Compile(GridData, order),
                    edgeInstr.Compile(GridData, order),
                    order,
                    cutCellGrid,
                    0);

                timer.Start();
                double result = quadrature.ExecuteA().Storage.Sum();
                timer.Stop();

                return(result);
            }
        }
Exemple #4
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 #5
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 #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);
            }
        }
Exemple #7
0
        /// <summary>
        /// Computes L2 distance between this field and
        /// <paramref name="other"/>
        /// </summary>
        /// <param name="other"></param>
        /// <param name="cm">
        /// Optional restriction of domain
        /// </param>
        /// <param name="overrideGridCheck">
        /// If this parameter is set to true, the error will be computed even
        /// though <see cref="DGField.GridDat"/> is not identical for both
        /// fields. Only do so if you are really sure that the grids are still
        /// equivalent.
        /// </param>
        public double L2Error(DGField other, CellMask cm = null, bool overrideGridCheck = false)
        {
            if (!overrideGridCheck && !object.ReferenceEquals(this.GridDat, other.GridDat))
            {
                throw new Exception(
                          "Cannot compute error between DG fields on different grids");
            }

            int order = Math.Max(this.Basis.Degree, other.Basis.Degree) * 2;
            CellQuadratureScheme cqs = new CellQuadratureScheme(domain: cm);

            return(LxError(other.Evaluate, null, cqs.Compile(this.GridDat, order)));
        }
Exemple #8
0
        /// <summary>
        /// computes the L2 norm of the Residual of the Eikonal equation in the
        /// domain <paramref name="K"/>, i.e. <br/>
        /// \f[
        /// \left\|
        /// \textrm{\textbf{1}}_K
        /// \cdot
        /// \left(  | \nabla \phi | - 1 \right)
        /// \right\|_2
        /// \f]
        /// </summary>
        /// <param name="K">
        /// optional restriction to a subdomain
        /// </param>
        public double SignedDistanceError(CellMask K)
        {
            var cqc = new CellQuadratureScheme(true, K);

            var q = new SignedDistanceErrorQuad(
                this, cqc.Compile(this.Basis.GridDat, this.Basis.Degree * 4));

            q.Execute();
            unsafe {
                double local = q.LocalErrorL2Accumulated;
                double global;
                csMPI.Raw.Allreduce((IntPtr)(&local), (IntPtr)(&global), 1, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD);
                return(global);
            }
        }
        /// <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 #10
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 #11
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 #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);
        }
Exemple #14
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 #15
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 #16
0
        /// <summary>
        /// L2 error of some quantity derived from the state vector (e.g.,
        /// entropy) with respect to given reference solution. The quadrature
        /// is determined from the settings in <see cref="IBMControl"/>
        /// </summary>
        /// <param name="quantityOfInterest"></param>
        /// <param name="referenceSolution"></param>
        /// <returns></returns>
        public static Query L2Error(Func <StateVector, double> quantityOfInterest, Func <double[], double, double> referenceSolution)
        {
            return(delegate(IApplication <AppControl> app, double time) {
                IProgram <CNSControl> program = app as IProgram <CNSControl>;
                if (program == null)
                {
                    throw new Exception();
                }

                ImmersedSpeciesMap speciesMap = program.SpeciesMap as ImmersedSpeciesMap;
                IBMControl control = program.Control as IBMControl;
                if (speciesMap == null || control == null)
                {
                    throw new Exception(
                        "Query is only valid for immersed boundary runs");
                }

                SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName);
                int order = control.LevelSetQuadratureOrder;
                CellQuadratureScheme scheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme(
                    species, true, speciesMap.SubGrid.VolumeMask);
                var composititeRule = scheme.Compile(program.GridData, order);
                IChunkRulePair <QuadRule>[] chunkRulePairs = composititeRule.ToArray();

                DGField density = program.WorkingSet.Density;
                VectorField <DGField> momentum = program.WorkingSet.Momentum;
                DGField energy = program.WorkingSet.Energy;

                // Construct dummy field since L2Error is currently only supported
                // for Field's; However, _avoid_ a projection.
                DGField dummy = new SinglePhaseField(new Basis(program.GridData, 0));
                Material material = speciesMap.GetMaterial(double.NaN);
                int index = 0;
                double value = dummy.LxError(
                    (ScalarFunctionEx) delegate(int j0, int Len, NodeSet nodes, MultidimensionalArray result) {
                    MultidimensionalArray input = program.GridData.GlobalNodes.GetValue_Cell(nodes, j0, Len);

                    Chunk chunk = chunkRulePairs[index].Chunk;
                    QuadRule rule = chunkRulePairs[index].Rule;

                    if (chunk.i0 != j0 || chunk.Len != Len)
                    {
                        throw new Exception();
                    }

                    if (rule.NoOfNodes != nodes.GetLength(0))
                    {
                        throw new Exception();
                    }

                    MultidimensionalArray rho = MultidimensionalArray.Create(chunk.Len, rule.NoOfNodes);
                    density.Evaluate(chunk.i0, chunk.Len, nodes, rho);

                    MultidimensionalArray[] m = new MultidimensionalArray[CNSEnvironment.NumberOfDimensions];
                    for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++)
                    {
                        m[d] = MultidimensionalArray.Create(chunk.Len, rule.NoOfNodes);
                        momentum[d].Evaluate(chunk.i0, chunk.Len, nodes, m[d]);
                    }

                    MultidimensionalArray rhoE = MultidimensionalArray.Create(chunk.Len, rule.NoOfNodes);
                    energy.Evaluate(chunk.i0, chunk.Len, nodes, rhoE);

                    double[] X = new double[CNSEnvironment.NumberOfDimensions];
                    Vector3D mVec = new Vector3D();
                    for (int i = 0; i < chunk.Len; i++)
                    {
                        for (int j = 0; j < rule.NoOfNodes; j++)
                        {
                            for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++)
                            {
                                X[d] = input[i, j, d];
                                mVec[d] = m[d][i, j];
                            }

                            StateVector state = new StateVector(material, rho[i, j], mVec, rhoE[i, j]);
                            double qoi = quantityOfInterest(state);

                            Debug.Assert(
                                !double.IsNaN(qoi),
                                "Encountered node with unphysical state"
                                + " (not able to determine quantity of interest)");

                            result[i, j] = qoi - referenceSolution(X, time);
                        }
                    }

                    index++;
                },
                    (X, a, b) => (a - b) * (a - b),
                    composititeRule);

                // No value is NaN, but the results. How can this be?
                // => All values around 0, but values in void region are a little
                // farther away from the exact solution
                // => weights in the void zone sum up to something slightly negative
                Debug.Assert(
                    value >= 0,
                    "Encountered unphysical norm even though individual values where valid."
                    + " This indicates a problem with cut-cell quadrature.");

                return Math.Sqrt(value);
            });
        }
Exemple #17
0
        //static void Main(string[] args) {
        //    Application<CNSControl>._Main(args, false, null, () => new ViscousShockProfile());
        //}

        protected override void SetInitial()
        {
            //base.SetInitial();
            WorkingSet.ProjectInitialValues(SpeciesMap, base.Control.InitialValues_Evaluators);
            string viscosityLaw = Control.ViscosityLaw.ToString();

            if (true)
            {
                DGField mpiRank = new SinglePhaseField(new Basis(GridData, 0), "rank");
                m_IOFields.Add(mpiRank);

                for (int j = 0; j < GridData.Cells.NoOfLocalUpdatedCells; j++)
                {
                    mpiRank.SetMeanValue(j, DatabaseDriver.MyRank);
                }
            }

            // exakte Lösung für 1D-Testfall
            int p = Control.MomentumDegree;
            CellQuadratureScheme scheme = new CellQuadratureScheme(true);
            int  order            = WorkingSet.Momentum[0].Basis.Degree * 2 + 2;
            int  noOfNodesPerCell = scheme.Compile(GridData, order).First().Rule.NoOfNodes;
            int  offset           = Grid.CellPartitioning.i0 * noOfNodesPerCell;
            long K = Grid.NumberOfCells;

            string pathToData;
            string initial;

            if (Grid.Description.Contains("Unsteady"))
            {
                pathToData = @"P:\ViscousTerms\NS_exact\data\M4_" + viscosityLaw + "_unsteady\\";
                initial    = "1";
            }
            else
            {
                pathToData = @"P:\ViscousTerms\NS_exact\data\M4_" + viscosityLaw + "_steady\\";
                initial    = "0";
            }

            ScalarFunction func = new ScalarFunction(
                (MultidimensionalArray arrIn, MultidimensionalArray arrOut) => {
                string filename = "m" + initial + "_" + K.ToString() + "_" + Control.MomentumDegree.ToString() + ".txt";
                double[] output;
                using (System.IO.StreamReader sr = new System.IO.StreamReader(pathToData + filename)) {
                    output = sr.ReadToEnd().
                             Split(',').
                             Select((str) => double.Parse(str, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)).
                             Skip(offset).
                             Take(Grid.CellPartitioning.LocalLength * noOfNodesPerCell).
                             ToArray();
                };
                output.CopyTo(arrOut.Storage, 0);
            }
                );

            WorkingSet.Momentum[0].ProjectField(1.0, func, scheme);

            p                = Control.EnergyDegree;
            scheme           = new CellQuadratureScheme(true);
            order            = WorkingSet.Energy.Basis.Degree * 2 + 2;
            noOfNodesPerCell = scheme.Compile(GridData, order).First().Rule.NoOfNodes;
            offset           = Grid.CellPartitioning.i0 * noOfNodesPerCell;

            func = new ScalarFunction(
                (MultidimensionalArray arrIn, MultidimensionalArray arrOut) => {
                string filename = "rhoE" + initial + "_" + K.ToString() + "_" + p.ToString() + ".txt";
                double[] output;
                using (System.IO.StreamReader sr = new System.IO.StreamReader(pathToData + filename)) {
                    output = sr.ReadToEnd().
                             Split(',').
                             Select((str) => double.Parse(str, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)).
                             Skip(offset).
                             Take(Grid.CellPartitioning.LocalLength * noOfNodesPerCell).
                             ToArray();
                };
                output.CopyTo(arrOut.Storage, 0);
            }
                );
            WorkingSet.Energy.ProjectField(func);


            p                = Control.DensityDegree;
            scheme           = new CellQuadratureScheme(true);
            order            = WorkingSet.Density.Basis.Degree * 2 + 2;
            noOfNodesPerCell = scheme.Compile(GridData, order).First().Rule.NoOfNodes;
            offset           = Grid.CellPartitioning.i0 * noOfNodesPerCell;

            func = new ScalarFunction(
                (MultidimensionalArray arrIn, MultidimensionalArray arrOut) => {
                string filename = "rho" + initial + "_" + K.ToString() + "_" + p.ToString() + ".txt";
                double[] output;
                using (System.IO.StreamReader sr = new System.IO.StreamReader(pathToData + filename)) {
                    output = sr.ReadToEnd().
                             Split(',').
                             Select((str) => double.Parse(str, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)).
                             Skip(offset).
                             Take(Grid.CellPartitioning.LocalLength * noOfNodesPerCell).
                             ToArray();
                };
                output.CopyTo(arrOut.Storage, 0);
            }
                );

            WorkingSet.Density.ProjectField(func);
            WorkingSet.UpdateDerivedVariables(this, CellMask.GetFullMask(GridData));

            //string guidString = "00000000-0000-0000-0000-000000000000";

            //switch (K) {
            //    case 32:
            //        guidString = "6725b9fc-d072-44cd-ae72-196e8a692735";
            //        break;
            //    case 64:
            //        guidString = "cb714aec-4b4a-4dae-9e70-32861daa195f";
            //        break;
            //    case 128:
            //        guidString = "678dc736-bbf6-4a1e-86eb-4f80b2354748";
            //        break;
            //}


            //Guid tsGuid = new Guid(guidString);
            //var db = this.GetDatabase();
            //string fieldName = "rho";
            //ITimestepInfo tsi = db.Controller.DBDriver.LoadTimestepInfo(tsGuid, null, db);
            //previousRho = (SinglePhaseField)db.Controller.DBDriver.LoadFields(tsi, GridData, new[] { fieldName }).Single().CloneAs();
            //diffRho = WorkingSet.Density.CloneAs();
            //diffRho.Clear();


            //fieldName = "rhoE";
            //previousRhoE = (SinglePhaseField)db.Controller.DBDriver.LoadFields(tsi, GridData, new[] { fieldName }).Single().CloneAs();
            //diffRhoE = WorkingSet.Energy.CloneAs();
            //diffRhoE.Clear();

            //fieldName = "m0";
            //previousM0 = (SinglePhaseField)db.Controller.DBDriver.LoadFields(tsi, GridData, new[] { fieldName }).Single().CloneAs();
            //diffM0 = WorkingSet.Momentum[0].CloneAs();
            //diffM0.Clear();

            //diffRho.Identification = "diffRho";
            //diffM0.Identification = "diffM0";
            //diffRhoE.Identification = "diffRhoE";
            //previousRho.Identification = "Rho_analy";
            //previousM0.Identification = "M0_analy";
            //previousRhoE.Identification = "RhoE_analy";
            //m_IOFields.Add(diffM0);
            //m_IOFields.Add(diffRho);
            //m_IOFields.Add(diffRhoE);
            //m_IOFields.Add(previousM0);
            //m_IOFields.Add(previousRho);
            //m_IOFields.Add(previousRhoE);
        }
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            IsPassed = true;
            try {
                int testcnt = 0;


                XQuadFactoryHelper.CheckQuadRules = true;

                while (this.test.NextTestCase())
                {
                    testcnt++;
                    if (testcnt % 100 == 0)
                    {
                        Console.WriteLine("Test {0}", testcnt);
                    }

                    this.Phi.ProjectField(this.test.GetLevelSet);
                    this.LsTrk.UpdateTracker(0.0);

                    //var schemes = new XQuadSchemeHelper(LsTrk, this.momentFittingVariant, LsTrk.SpeciesIdS.ToArray());
                    var schemes = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), this.QUAD_ORDER, 1).XQuadSchemeHelper;

                    var cutCells = LsTrk.Regions.GetCutCellSubGrid().VolumeMask;

                    var volSchemeA = schemes.GetVolumeQuadScheme(this.LsTrk.GetSpeciesId("A"), IntegrationDomain: cutCells);
                    var volSchemeB = schemes.GetVolumeQuadScheme(this.LsTrk.GetSpeciesId("B"), IntegrationDomain: cutCells);
                    CellQuadratureScheme surfScheme = schemes.GetLevelSetquadScheme(0, cutCells);
                    var edgeSchemeA = schemes.GetEdgeQuadScheme(this.LsTrk.GetSpeciesId("A"));
                    var edgeSchemeB = schemes.GetEdgeQuadScheme(this.LsTrk.GetSpeciesId("B"));


                    if (test.EdgeTestSupported)
                    {
                        /*
                         * var EdgeA = EdgeQuadrature(edgeSchemeA.Compile(this.GridDat, this.QUAD_ORDER));
                         * var EdgeAref = EdgeAreaRef("A");
                         * var EdgeAErr = EdgeA.CloneAs();
                         * EdgeAErr.Acc(-1.0, EdgeAref);
                         * double EdgeAL2err = EdgeAErr.L2Norm();
                         * Console.WriteLine("Edge error for species A: " + EdgeAL2err);
                         */

                        var EdgeB    = EdgeQuadrature(edgeSchemeB.Compile(this.GridData, this.QUAD_ORDER));
                        var EdgeBref = EdgeAreaRef("B");
                        var EdgeBErr = EdgeB.CloneAs();
                        EdgeBErr.Acc(-1.0, EdgeBref);
                        double EdgeBL2err = EdgeBErr.L2Norm();
                        if (EdgeBL2err >= 1.0e-5)
                        {
                            throw new ApplicationException("Edge error for species B: " + EdgeBL2err);
                        }
                        //Console.WriteLine("Edge error for species B: " + EdgeBL2err);
                    }

                    if (test.LevelsetTestSupported)
                    {
                        var Surf    = CellQuadrature(surfScheme.Compile(this.GridData, this.QUAD_ORDER));
                        var SurfRef = SurfAreaRef();
                        var surfErr = Surf.CloneAs();
                        surfErr.Acc(-1.0, SurfRef);
                        double surfL2err = surfErr.L2Norm();

                        if (surfL2err >= 1.0e-5)
                        {
                            //Console.WriteLine("Level-Set surface error " + surfL2err);
                            throw new ApplicationException("Level-Set surface error " + surfL2err);
                        }
                    }


                    if (test.VolumeTestSupported)
                    {
                        /*
                         * var VolA = CellQuadrature(volSchemeA.Compile(this.GridDat, this.QUAD_ORDER));
                         * var VolAref = CellVolumeRef(cutCells, "A");
                         * var volAErr = VolA.CloneAs();
                         * volAErr.Acc(-1.0, VolAref);
                         * double volAL2err = volAErr.L2Norm();
                         * Console.WriteLine("Volume error for species A: " + volAL2err);
                         */

                        var VolB    = CellQuadrature(volSchemeB.Compile(this.GridData, this.QUAD_ORDER));
                        var VolBref = CellVolumeRef(cutCells, "B");
                        var volBErr = VolB.CloneAs();
                        volBErr.Acc(-1.0, VolBref);
                        double volBL2err = volBErr.L2Norm();
                        if (volBL2err >= 1.0e-5)
                        {
                            throw new ApplicationException(string.Format("Volume error for species B: {0}", volBL2err));
                        }
                        //Console.WriteLine("Volume error for species B: {0}", volBL2err);
                    }


                    if (test.BoundaryPlusLevelsetTestSupported)
                    {
                        var LevelSetArea = CellQuadrature(surfScheme.Compile(this.GridData, this.QUAD_ORDER));
                        var BoundaryB    = EdgeQuadrature2CellBoundary(edgeSchemeB.Compile(this.GridData, this.QUAD_ORDER));
                        var RefAreaB     = CellBoundaryPlusLevelsetAreaRef(cutCells, "B");

                        var ErrB = RefAreaB.CloneAs();
                        ErrB.Acc(-1.0, BoundaryB);
                        ErrB.Acc(-1.0, LevelSetArea);
                        double areaBL2err = ErrB.L2Norm();
                        Console.WriteLine("levelset + cell-boundary error for species B: " + areaBL2err);
                    }

                    //break;
                }
            } catch (Exception e) {
                Console.WriteLine(e.GetType().Name + ": " + e.Message);
                Console.WriteLine(e.StackTrace);
                IsPassed = false;
            }



            base.TerminationKey = true;
            return(0.0);
        }
Exemple #19
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]);
            }
        }
 public ScalarFieldQuadrature(GridData gridData, DGField field, CellQuadratureScheme quadInstr, int quadOrder)
     : base(new int[] { 1 }, gridData, quadInstr.Compile(gridData, quadOrder))
 {
     this.field = field;
 }
        /// <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 #22
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 #23
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");
                }
            }
        }
Exemple #24
0
        /// <summary>
        /// Computes Cell-volumes and edge areas before agglomeration.
        /// </summary>
        void ComputeNonAgglomeratedMetrics()
        {
            var gd = XDGSpaceMetrics.GridDat;
            int JE = gd.Cells.NoOfCells;
            int J  = gd.Cells.NoOfLocalUpdatedCells;
            int D  = gd.SpatialDimension;
            int EE = gd.Edges.Count;

            SpeciesId[] species = this.SpeciesList.ToArray();
            int         NoSpc   = species.Count();

            int[,] E2C = gd.Edges.CellIndices;

            var schH = new XQuadSchemeHelper(XDGSpaceMetrics);

            double[] vec_cellMetrics = new double[JE * NoSpc * 2];

            // collect all per-cell-metrics in the same MultidimArry, for MPI-exchange
            // 1st index: cell
            // 2nd index: species
            // 3rd index: 0 for interface surface per cell, 1 for cut-cell-volume
            MultidimensionalArray cellMetrics = MultidimensionalArray.CreateWrapper(vec_cellMetrics, JE, NoSpc, 2);

            this.CutEdgeAreas   = new Dictionary <SpeciesId, MultidimensionalArray>();
            this.CutCellVolumes = new Dictionary <SpeciesId, MultidimensionalArray>();
            this.InterfaceArea  = new Dictionary <SpeciesId, MultidimensionalArray>();

            //var schS = new List<CellQuadratureScheme>();
            //var rulz = new List<ICompositeQuadRule<QuadRule>>();


            // edges and volumes
            // =================
            for (int iSpc = 0; iSpc < species.Length; iSpc++)
            {
                var cellVol = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1);
                var spc     = species[iSpc];

                MultidimensionalArray edgArea = MultidimensionalArray.Create(EE);
                this.CutEdgeAreas.Add(spc, edgArea);

                // compute cut edge area
                // ---------------------

                var edgeScheme = schH.GetEdgeQuadScheme(spc);
                var edgeRule   = edgeScheme.Compile(gd, this.CutCellQuadratureOrder);

                BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature(
                    new int[] { 1 }, gd,
                    edgeRule,
                    _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) //
                {
                    EvalResult.SetAll(1.0);
                },
                    _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) //
                {
                    for (int i = 0; i < Length; i++)
                    {
                        int iEdge = i + i0;
                        Debug.Assert(edgArea[iEdge] == 0);
                        edgArea[iEdge] = ResultsOfIntegration[i, 0];
                        Debug.Assert(!(double.IsNaN(edgArea[iEdge]) || double.IsInfinity(edgArea[iEdge])));
                    }
                }).Execute();

                // compute cut cell volumes
                // ------------------------

                var volScheme = schH.GetVolumeQuadScheme(spc);
                var volRule   = volScheme.Compile(gd, this.CutCellQuadratureOrder);

                //schS.Add(volScheme);
                //rulz.Add(volRule);

                BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature(
                    new int[] { 1 }, gd,
                    volRule,
                    _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) //
                {
                    EvalResult.SetAll(1.0);
                },
                    _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) //
                {
                    for (int i = 0; i < Length; i++)
                    {
                        int jCell = i + i0;
                        Debug.Assert(cellVol[jCell] == 0);
                        cellVol[jCell] = ResultsOfIntegration[i, 0];
                        Debug.Assert(!(double.IsNaN(cellVol[jCell]) || double.IsInfinity(cellVol[jCell])));
                    }
                }).Execute();
            }


            // interface surface
            // =================

            // loop over all possible pairs of species

            /*
             * for (int iSpcA = 0; iSpcA < species.Length; iSpcA++) {
             *  var SpeciesA = species[iSpcA];
             *  var SpeciesADom = lsTrk.GetSpeciesMask(SpeciesA);
             *  if (SpeciesADom.NoOfItemsLocally <= 0)
             *      continue;
             *
             *  for (int iSpcB = iSpcA + 1; iSpcB < species.Length; iSpcB++) {
             *      var SpeciesB = species[iSpcB];
             *      var SpeciesBDom = lsTrk.GetSpeciesMask(SpeciesB);
             *      if (SpeciesBDom.NoOfItemsLocally <= 0)
             *          continue;
             *
             *      var SpeciesCommonDom = SpeciesADom.Intersect(SpeciesBDom);
             *      if (SpeciesCommonDom.NoOfItemsLocally <= 0)
             *          continue;
             *
             *      // loop over level-sets
             *      int NoOfLs = lsTrk.LevelSets.Count;
             *      for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) {
             *
             *
             *          var LsDom = lsTrk.GetCutCellMask4LevSet(iLevSet);
             *          var IntegrationDom = LsDom.Intersect(SpeciesCommonDom);
             *
             *          if (IntegrationDom.NoOfItemsLocally > 0) {
             *              CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom);
             *              var rule = SurfIntegration.Compile(gd, this.HMForder);
             *
             *
             *              BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature(
             *                  new int[] { 1 }, gd,
             *                  rule,
             *                  _Evaluate: delegate (int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) //
             *                  {
             *                      EvalResult.SetAll(1.0);
             *                  },
             *                  _SaveIntegrationResults: delegate (int i0, int Length, MultidimensionalArray ResultsOfIntegration) //
             *                  {
             *                      for (int i = 0; i < Length; i++) {
             *                          int jCell = i + i0;
             *                          if (cellMetrics[jCell, iSpcA, 0] != 0.0)
             *                              throw new NotSupportedException("More than one zero-level-set per cell is not supported yet.");
             *                          if (cellMetrics[jCell, iSpcB, 0] != 0.0)
             *                              throw new NotSupportedException("More than one zero-level-set per cell is not supported yet.");
             *
             *                          cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0];
             *                          cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0];
             *                      }
             *                  }).Execute();
             *          }
             *      }
             *  }
             * }*/

            // loop over level-sets
            if (species.Length > 0)
            {
                // find domain of all species:
                CellMask SpeciesCommonDom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[0]);
                for (int iSpc = 1; iSpc < species.Length; iSpc++)
                {
                    SpeciesCommonDom = SpeciesCommonDom.Union(XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[iSpc]));
                }
                BitArray[] SpeciesBitMask = species.Select(spc => XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(spc).GetBitMask()).ToArray();

                int NoOfLs  = XDGSpaceMetrics.NoOfLevelSets;
                int NoOfSpc = species.Length;
                for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++)
                {
                    var LsDom          = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet);
                    var IntegrationDom = LsDom.Intersect(SpeciesCommonDom);

                    //if (IntegrationDom.NoOfItemsLocally > 0) { -> Doesn't work if Bjoerns HMF is used, eds up in an mpi dead lock
                    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                    // this level-set is actually relevant for someone in 'species'
                    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom);
                    var rule = SurfIntegration.Compile(gd, this.CutCellQuadratureOrder);

                    BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature(
                        new int[] { 1 }, gd,
                        rule,
                        _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                        EvalResult.SetAll(1.0);
                    },
                        _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                        for (int i = 0; i < Length; i++)
                        {
                            int jCell = i + i0;



                            //if (cellMetrics[jCell, iSpcA, 0] != 0.0)
                            //    throw new NotSupportedException("More than one zero-level-set per cell is not supported yet.");
                            //if (cellMetrics[jCell, iSpcB, 0] != 0.0)
                            //    throw new NotSupportedException("More than one zero-level-set per cell is not supported yet.");

                            //cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0];
                            //cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0];


                            for (int iSpc = 0; iSpc < NoOfSpc; iSpc++)
                            {
                                if (SpeciesBitMask[iSpc][jCell])
                                {
                                    cellMetrics[jCell, iSpc, 0] += ResultsOfIntegration[i, 0];
                                    Debug.Assert(!(double.IsNaN(cellMetrics[jCell, iSpc, 0]) || double.IsInfinity(cellMetrics[jCell, iSpc, 0])));
                                }
                            }
                        }
                    }).Execute();
                    //}
                }
            }

            // MPI exchange & store
            // ====================

            if (species.Length > 0)
            {
                vec_cellMetrics.MPIExchange(gd);
            }

            for (int iSpc = 0; iSpc < species.Length; iSpc++)
            {
                var spc = species[iSpc];
                this.InterfaceArea.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 0).CloneAs());
                this.CutCellVolumes.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1).CloneAs());
            }

            //Console.WriteLine("Erinn - debug code.");
            //for(int j = 0; j < J; j++) {
            //    double totVol = gd.Cells.GetCellVolume(j);

            //    double blaVol = 0;
            //    for(int iSpc = 0; iSpc < species.Length; iSpc++) {
            //        var spc = species[iSpc];
            //        var cellVolS = this.CutCellVolumes[spc][j];
            //        blaVol += cellVolS;
            //    }

            //    Debug.Assert(Math.Abs(totVol - blaVol) / totVol < 1.0e-8);

            //}
        }
        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 #26
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 #27
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);
        }
Exemple #28
0
        public void LimitFieldValues(IEnumerable <DGField> ConservativeVariables, IEnumerable <DGField> DerivedFields)
        {
            //IProgram<CNSControl> program;
            //CNSFieldSet fieldSet = program.WorkingSet;

            DGField Density    = ConservativeVariables.Single(f => f.Identification == Variables.Density.Name);
            DGField Momentum_0 = ConservativeVariables.Single(f => f.Identification == Variables.Momentum[0].Name);
            DGField Momentum_1 = ConservativeVariables.Single(f => f.Identification == Variables.Momentum[1].Name);
            DGField Energy     = ConservativeVariables.Single(f => f.Identification == Variables.Energy.Name);

            foreach (var chunkRulePair in quadRuleSet)
            {
                if (chunkRulePair.Chunk.Len > 1)
                {
                    throw new System.Exception();
                }

                MultidimensionalArray densityValues = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Density.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, densityValues);
                MultidimensionalArray m0Values = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Momentum_0.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m0Values);
                MultidimensionalArray m1Values = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Momentum_1.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m1Values);
                MultidimensionalArray energyValues = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Energy.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, energyValues);

                for (int i = 0; i < chunkRulePair.Chunk.Len; i++)
                {
                    int cell = i + chunkRulePair.Chunk.i0;

                    CellMask             singleCellMask   = new CellMask(speciesMap.Tracker.GridDat, chunkRulePair.Chunk);
                    CellQuadratureScheme singleCellScheme = new CellQuadratureScheme(
                        new FixedRuleFactory <QuadRule>(chunkRulePair.Rule), singleCellMask);
                    var singleCellRule = singleCellScheme.Compile(speciesMap.Tracker.GridDat, 99);

                    SpeciesId species = speciesMap.Tracker.GetSpeciesId(speciesMap.Control.FluidSpeciesName);
                    double    volume  = speciesMap.QuadSchemeHelper.NonAgglomeratedMetrics.CutCellVolumes[species][cell];

                    double integralDensity = Density.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanDensity     = integralDensity / volume;

                    if (meanDensity < epsilon)
                    {
                        throw new System.Exception();
                    }

                    double minDensity = double.MaxValue;
                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        minDensity = Math.Min(minDensity, densityValues[i, j]);
                    }

                    double thetaDensity = Math.Min(1.0, (meanDensity - epsilon) / (meanDensity - minDensity));
                    if (thetaDensity < 1.0)
                    {
                        Console.WriteLine("Scaled density in cell {0}!", cell);
                    }

                    // Scale for positive density (Beware: Basis is not orthonormal on sub-volume!)
                    for (int j = 0; j < Density.Basis.Length; j++)
                    {
                        Density.Coordinates[cell, j] *= thetaDensity;
                    }
                    Density.AccConstant(meanDensity * (1.0 - thetaDensity), singleCellMask);

                    // Re-evaluate since inner energy has changed
                    densityValues.Clear();
                    Density.Evaluate(cell, 1, chunkRulePair.Rule.Nodes, densityValues);

#if DEBUG
                    // Probe 1
                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        if (densityValues[i, j] - epsilon < -1e-15)
                        {
                            throw new System.Exception();
                        }
                    }
#endif

                    double integralMomentumX = Momentum_0.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanMomentumX     = integralMomentumX / volume;
                    double integralMomentumY = Momentum_1.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanMomentumY     = integralMomentumY / volume;
                    double integralEnergy    = Energy.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanEnergy        = integralEnergy / volume;

                    double meanInnerEnergy = meanEnergy - 0.5 * (meanMomentumX * meanMomentumX + meanMomentumY * meanMomentumY) / meanDensity;
                    if (meanInnerEnergy < epsilon)
                    {
                        throw new System.Exception();
                    }

                    double minInnerEnergy = double.MaxValue;
                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        double innerEnergy = energyValues[i, j] - 0.5 * (m0Values[i, j] * m0Values[i, j] + m1Values[i, j] * m1Values[i, j]) / densityValues[i, j];
                        minInnerEnergy = Math.Min(minInnerEnergy, innerEnergy);
                    }

                    // Scale for positive inner energy (Beware: Basis is not orthonormal on sub-volume!)
                    double thetaInnerEnergy = Math.Min(1.0, (meanInnerEnergy - epsilon) / (meanInnerEnergy - minInnerEnergy));
                    if (thetaInnerEnergy < 1.0)
                    {
                        Console.WriteLine("Scaled inner energy in cell {0}!", cell);
                    }


                    for (int j = 0; j < Density.Basis.Length; j++)
                    {
                        Density.Coordinates[chunkRulePair.Chunk.i0 + i, j]    *= thetaInnerEnergy;
                        Momentum_0.Coordinates[chunkRulePair.Chunk.i0 + i, j] *= thetaInnerEnergy;
                        Momentum_1.Coordinates[chunkRulePair.Chunk.i0 + i, j] *= thetaInnerEnergy;
                        Energy.Coordinates[chunkRulePair.Chunk.i0 + i, j]     *= thetaInnerEnergy;
                    }
                    Density.AccConstant(meanDensity * (1.0 - thetaInnerEnergy), singleCellMask);
                    Momentum_0.AccConstant(meanMomentumX * (1.0 - thetaInnerEnergy), singleCellMask);
                    Momentum_1.AccConstant(meanMomentumY * (1.0 - thetaInnerEnergy), singleCellMask);
                    Energy.AccConstant(meanEnergy * (1.0 - thetaInnerEnergy), singleCellMask);


#if DEBUG
                    // Probe 2
                    densityValues.Clear();
                    Density.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, densityValues);
                    m0Values.Clear();
                    Momentum_0.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m0Values);
                    m1Values.Clear();
                    Momentum_1.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m1Values);
                    energyValues.Clear();
                    Energy.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, energyValues);

                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        StateVector state = new StateVector(
                            speciesMap.GetMaterial(1.0),
                            densityValues[i, j],
                            new Vector(m0Values[i, j], m1Values[i, j], 0.0),
                            energyValues[i, j]);
                        if (!state.IsValid)
                        {
                            throw new System.Exception();
                        }
                    }
#endif
                }
            }
        }
Exemple #29
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 #30
0
        /// <summary>
        /// Computes Cell-volumes and edge areas before agglomeration.
        /// </summary>
        void ComputeNonAgglomeratedMetrics()
        {
            using (new FuncTrace()) {
                MPICollectiveWatchDog.Watch();
                var         gd      = XDGSpaceMetrics.GridDat;
                int         JE      = gd.iLogicalCells.Count;
                int         J       = gd.iLogicalCells.NoOfLocalUpdatedCells;
                int         D       = gd.SpatialDimension;
                int         EE      = gd.Edges.Count;
                SpeciesId[] species = this.SpeciesList.ToArray();
                int         NoSpc   = species.Count();
                int[,] E2C = gd.iLogicalEdges.CellIndices;

                var schH = new XQuadSchemeHelper(XDGSpaceMetrics);


                // collect all per-cell-metrics in the same MultidimArry, for MPI-exchange (only 1 exchange instead of three, saving some overhead)
                // 1st index: cell
                // 2nd index: species
                // 3rd index: 0 for interface surface per cell, 1 for cut-cell-volume, 2 for cut-cell surface
                double[] vec_cellMetrics          = new double[JE * NoSpc * 3];
                MultidimensionalArray cellMetrics = MultidimensionalArray.CreateWrapper(vec_cellMetrics, JE, NoSpc, 3);

                this.CutEdgeAreas   = new Dictionary <SpeciesId, MultidimensionalArray>();
                this.CutCellVolumes = new Dictionary <SpeciesId, MultidimensionalArray>();
                this.InterfaceArea  = new Dictionary <SpeciesId, MultidimensionalArray>();
                this.CellSurface    = new Dictionary <SpeciesId, MultidimensionalArray>();

                //var schS = new List<CellQuadratureScheme>();
                //var rulz = new List<ICompositeQuadRule<QuadRule>>();


                // edges and volumes
                // =================
                for (int iSpc = 0; iSpc < species.Length; iSpc++)
                {
                    var cellVol = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1);
                    var spc     = species[iSpc];


                    // compute cut edge area
                    // ---------------------
                    MultidimensionalArray edgArea = MultidimensionalArray.Create(EE);
                    this.CutEdgeAreas.Add(spc, edgArea);

                    var edgeScheme = schH.GetEdgeQuadScheme(spc);
                    var edgeRule   = edgeScheme.Compile(gd, this.CutCellQuadratureOrder);

                    BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature(
                        new int[] { 1 }, gd,
                        edgeRule,
                        _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) //
                    {
                        EvalResult.SetAll(1.0);
                    },
                        _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) //
                    {
                        for (int i = 0; i < Length; i++)
                        {
                            int iEdge = i + i0;
                            Debug.Assert(edgArea[iEdge] == 0);
                            edgArea[iEdge] = ResultsOfIntegration[i, 0];
                            Debug.Assert(!(double.IsNaN(edgArea[iEdge]) || double.IsInfinity(edgArea[iEdge])));
                        }
                    }).Execute();

                    // sum up edges for surface
                    // ------------------------

                    var cellSurf = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 2);

                    for (int e = 0; e < EE; e++)
                    {
                        double a      = edgArea[e];
                        int    jCell0 = E2C[e, 0];
                        int    jCell2 = E2C[e, 1];
                        cellSurf[jCell0] += a;
                        if (jCell2 >= 0)
                        {
                            cellSurf[jCell2] += a;
                        }
                    }

                    // compute cut cell volumes
                    // ------------------------

                    var volScheme = schH.GetVolumeQuadScheme(spc);
                    var volRule   = volScheme.Compile(gd, this.CutCellQuadratureOrder);

                    BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature(
                        new int[] { 1 }, gd,
                        volRule,
                        _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) //
                    {
                        EvalResult.SetAll(1.0);
                    },
                        _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) //
                    {
                        for (int i = 0; i < Length; i++)
                        {
                            int jCell = i + i0;
                            Debug.Assert(cellVol[jCell] == 0);
                            cellVol[jCell] = ResultsOfIntegration[i, 0];
                            Debug.Assert(!(double.IsNaN(cellVol[jCell]) || double.IsInfinity(cellVol[jCell])));
                        }
                    }).Execute();
                }


                // interface surface
                // =================

                // loop over level-sets
                if (species.Length > 0)
                {
                    // find domain of all species:
                    CellMask SpeciesCommonDom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[0]);
                    for (int iSpc = 1; iSpc < species.Length; iSpc++)
                    {
                        SpeciesCommonDom = SpeciesCommonDom.Union(XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[iSpc]));
                    }
                    BitArray[] SpeciesBitMask = species.Select(spc => XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(spc).GetBitMask()).ToArray();

                    int NoOfLs  = XDGSpaceMetrics.NoOfLevelSets;
                    int NoOfSpc = species.Length;
                    for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++)
                    {
                        var LsDom          = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet);
                        var IntegrationDom = LsDom.Intersect(SpeciesCommonDom);

                        //if (IntegrationDom.NoOfItemsLocally > 0) { -> Doesn't work if Bjoerns HMF is used, eds up in an mpi dead lock
                        // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                        // this level-set is actually relevant for someone in 'species'
                        // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                        CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom);
                        var rule = SurfIntegration.Compile(gd, this.CutCellQuadratureOrder);

                        BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature(
                            new int[] { 1 }, gd,
                            rule,
                            _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                            EvalResult.SetAll(1.0);
                        },
                            _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                            for (int i = 0; i < Length; i++)
                            {
                                int jCell = i + i0;



                                //if (cellMetrics[jCell, iSpcA, 0] != 0.0)
                                //    throw new NotSupportedException("More than one zero-level-set per cell is not supported yet.");
                                //if (cellMetrics[jCell, iSpcB, 0] != 0.0)
                                //    throw new NotSupportedException("More than one zero-level-set per cell is not supported yet.");

                                //cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0];
                                //cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0];


                                for (int iSpc = 0; iSpc < NoOfSpc; iSpc++)
                                {
                                    if (SpeciesBitMask[iSpc][jCell])
                                    {
                                        cellMetrics[jCell, iSpc, 0] += ResultsOfIntegration[i, 0];
                                        Debug.Assert(!(double.IsNaN(cellMetrics[jCell, iSpc, 0]) || double.IsInfinity(cellMetrics[jCell, iSpc, 0])));
                                    }
                                }
                            }
                        }).Execute();
                        //}
                    }
                }

                // MPI exchange & store
                // ====================

                if (species.Length > 0)
                {
#if DEBUG
                    int NoOfSpc       = species.Length;
                    var cellMetricsB4 = cellMetrics.ExtractSubArrayShallow(new[] { 0, 0, 0 }, new[] { J - 1, NoOfSpc - 1, 1 }).CloneAs();
#endif
                    vec_cellMetrics.MPIExchange(gd);
#if DEBUG
                    var cellMetricsComp = cellMetrics.ExtractSubArrayShallow(new[] { 0, 0, 0 }, new[] { J - 1, NoOfSpc - 1, 1 }).CloneAs();
                    cellMetricsComp.Acc(-1.0, cellMetricsB4);
                    Debug.Assert(cellMetricsComp.L2Norm() == 0.0);
#endif
                }
                for (int iSpc = 0; iSpc < species.Length; iSpc++)
                {
                    var spc = species[iSpc];
                    this.InterfaceArea.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 0).CloneAs());
                    this.CutCellVolumes.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1).CloneAs());
                    this.CellSurface.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 2).CloneAs());

                    this.CellSurface[spc].Acc(1.0, this.InterfaceArea[spc]);
                }
            }
        }