Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        public void AssembleMatrix_Timestepper <T>(
            int CutCellQuadOrder,
            BlockMsrMatrix OpMatrix, double[] OpAffine,
            Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales,
            IEnumerable <T> CurrentState,
            VectorField <SinglePhaseField> SurfaceForce,
            VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature,
            UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping,
            double time, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField
        {
            if (ColMapping.BasisS.Count != this.Op.DomainVar.Count)
            {
                throw new ArgumentException();
            }
            if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count)
            {
                throw new ArgumentException();
            }

            // check:
            var Tracker = this.LsTrk;
            int D       = Tracker.GridDat.SpatialDimension;

            if (CurrentState != null && CurrentState.Count() != (D + 1))
            {
                throw new ArgumentException();
            }
            if (OpMatrix == null && CurrentState == null)
            {
                throw new ArgumentException();
            }
            DGField[] U0;
            if (CurrentState != null)
            {
                U0 = CurrentState.Take(D).ToArray();
            }
            else
            {
                U0 = null;
            }



            LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]);

            SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray();

            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea;


            // advanced settings for the navier slip boundary condition
            // ========================================================

            CellMask SlipArea;

            switch (this.dntParams.GNBC_Localization)
            {
            case NavierSlip_Localization.Bulk: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask;
                break;
            }

            case NavierSlip_Localization.ContactLine: {
                SlipArea = null;
                break;
            }

            case NavierSlip_Localization.Nearband: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth));
                break;
            }

            case NavierSlip_Localization.Prescribed: {
                throw new NotImplementedException();
            }

            default:
                throw new ArgumentException();
            }


            MultidimensionalArray SlipLengths;

            SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs();
            SlipLengths.Clear();
            //SlipLengths.AccConstant(-1.0);

            if (SlipArea != null)
            {
                foreach (Chunk cnk in SlipArea)
                {
                    for (int i = cnk.i0; i < cnk.JE; i++)
                    {
                        switch (this.dntParams.GNBC_SlipLength)
                        {
                        case NavierSlip_SlipLength.hmin_DG: {
                            int degU = ColMapping.BasisS.ToArray()[0].Degree;
                            SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1);
                            break;
                        }

                        case NavierSlip_SlipLength.hmin_Grid: {
                            SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i];
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_SlipLength: {
                            SlipLengths[i] = this.physParams.sliplength;
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_Beta: {
                            SlipLengths[i] = -1.0;
                            break;
                        }
                        }
                    }
                }
            }


            // parameter assembly
            // ==================

            // normals:
            SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions.
            if (this.NormalsRequired)
            {
                if (LevelSetGradient == null)
                {
                    LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory);
                    LevelSetGradient.Gradient(1.0, Phi);
                }
                Normals = LevelSetGradient.ToArray();
            }
            else
            {
                Normals = new SinglePhaseField[D];
            }

            // curvature:
            SinglePhaseField Curvature;

            if (this.CurvatureRequired)
            {
                Curvature = ExternalyProvidedCurvature;
            }
            else
            {
                Curvature = null;
            }

            // linearization velocity:
            DGField[] U0_U0mean;
            if (this.U0meanrequired)
            {
                XDGBasis U0meanBasis          = new XDGBasis(Tracker, 0);
                VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory);

                U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean);
            }
            else
            {
                U0_U0mean = new DGField[2 * D];
            }

            // Temperature gradient for evaporation
            VectorField <DGField> GradTemp = new VectorField <DGField>(D, U0[0].Basis, XDGField.Factory);

            if (CoupledCurrentState != null)
            {
                DGField Temp = CoupledCurrentState.ToArray()[0];
                GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory);
                XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk);
            }

            // concatenate everything
            var Params = ArrayTools.Cat <DGField>(
                U0_U0mean,
                Curvature,
                ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]),
                Normals,
                ((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]),
                ((evaporation) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]),
                ((evaporation) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1]));  //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]));

            // linearization velocity:
            if (this.U0meanrequired)
            {
                VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray());

                U0mean.Clear();
                if (this.physParams.IncludeConvection)
                {
                    ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
                }
            }



            // assemble the matrix & affine vector
            // ===================================

            // compute matrix
            if (OpMatrix != null)
            {
                //Op.ComputeMatrixEx(Tracker,
                //    ColMapping, Params, RowMapping,
                //    OpMatrix, OpAffine, false, time, true,
                //    AgglomeratedCellLengthScales,
                //    InterfaceLengths, SlipLengths,
                //    SpcToCompute);

                XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                }

                if (Op.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                mtxBuilder.time = time;

                mtxBuilder.ComputeMatrix(OpMatrix, OpAffine);
            }
            else
            {
                XSpatialOperatorMk2.XEvaluatorNonlin eval = Op.GetEvaluatorEx(Tracker,
                                                                              CurrentState.ToArray(), Params, RowMapping,
                                                                              SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                }

                if (Op.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                eval.time = time;

                eval.Evaluate(1.0, 1.0, OpAffine);

#if DEBUG
                // remark: remove this piece in a few months from now on (09may18) if no problems occur
                //{

                //    BlockMsrMatrix checkOpMatrix = new BlockMsrMatrix(RowMapping, ColMapping);
                //    double[] checkAffine = new double[OpAffine.Length];

                //    Op.ComputeMatrixEx(Tracker,
                //    ColMapping, Params, RowMapping,
                //    OpMatrix, OpAffine, false, time, true,
                //    AgglomeratedCellLengthScales,
                //    InterfaceLengths, SlipLengths,
                //    SpcToCompute);


                //    double[] checkResult = checkAffine.CloneAs();
                //    var currentVec = new CoordinateVector(CurrentState.ToArray());
                //    checkOpMatrix.SpMV(1.0, new CoordinateVector(CurrentState.ToArray()), 1.0, checkResult);

                //    double L2_dist = GenericBlas.L2DistPow2(checkResult, OpAffine).MPISum().Sqrt();
                //    double RefNorm = (new double[] { checkResult.L2NormPow2(), OpAffine.L2NormPow2(), currentVec.L2NormPow2() }).MPISum().Max().Sqrt();

                //    Assert.LessOrEqual(L2_dist, RefNorm * 1.0e-6);
                //    Debug.Assert(L2_dist < RefNorm * 1.0e-6);
                //}
#endif
            }


            // check
            // =====

            /*
             * {
             *  DGField[] testDomainFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
             *  CoordinateVector test = new CoordinateVector(testDomainFieldS);
             *
             *  DGField[] errFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
             *  CoordinateVector Err = new CoordinateVector(errFieldS);
             *
             *  var eval = Op.GetEvaluatorEx(LsTrk,
             *      testDomainFieldS, Params, RowMapping);
             *
             *  foreach (var s in this.LsTrk.SpeciesIdS)
             *      eval.SpeciesOperatorCoefficients[s].CellLengthScales = AgglomeratedCellLengthScales[s];
             *
             *  eval.time = time;
             *  int L = test.Count;
             *  Random r = new Random();
             *  for(int i = 0; i < L; i++) {
             *      test[i] = r.NextDouble();
             *  }
             *
             *
             *
             *  double[] R1 = new double[L];
             *  double[] R2 = new double[L];
             *  eval.Evaluate(1.0, 1.0, R1);
             *
             *  R2.AccV(1.0, OpAffine);
             *  OpMatrix.SpMV(1.0, test, 1.0, R2);
             *
             *  Err.AccV(+1.0, R1);
             *  Err.AccV(-1.0, R2);
             *
             *  double ErrDist = GenericBlas.L2DistPow2(R1, R2).MPISum().Sqrt();
             *
             *  double Ref = test.L2NormPow2().MPISum().Sqrt();
             *
             *  Debug.Assert(ErrDist <= Ref*1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix.");
             * }
             */
        }
Exemplo n.º 3
0
        /// <summary>
        /// Calculates the drag (x-component) and lift (y-component) forces acting on a IB contour
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="muA"></param>
        /// <returns></returns>
        static public double[] GetForces(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;

            //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);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Calculates the drag (x-component) and lift (y-component) forces acting on a cylinder wall of a boundary fitted grid. The definition of the wall is HARDCODED!
        /// </summary>
        static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> U, SinglePhaseField StressXX, //VectorField<SinglePhaseField> GradU, VectorField<SinglePhaseField> GradV
                                                        SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta, string EdgeTagName)
        {
            int D = LsTrk.GridDat.SpatialDimension;

            if (D > 2)
            {
                throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!");
            }
            // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            var UA = U.ToArray();
            //MultidimensionalArray Grad_U = new MultidimensionalArray(D);
            //var _GradU = GradU.ToArray();
            //var _GradV = GradV.ToArray();


            //int RequiredOrder = _GradU[0].Basis.Degree * 3 + 20;
            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();
            //Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            SinglePhaseField _StressXX = StressXX;
            SinglePhaseField _StressXY = StressXY;
            SinglePhaseField _StressYY = StressYY;

            SinglePhaseField pA = null;

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

            VectorField <SinglePhaseField>[] VelGread = new VectorField <SinglePhaseField> [D];
            for (int d = 0; d < D; d++)
            {
                VelGread[d] = new VectorField <SinglePhaseField>(D, U[d].Basis, (b, name) => new SinglePhaseField(b, name));
                VelGread[d].GradientByFlux(1.0, U[d]);
            }


            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_URes   = MultidimensionalArray.Create(Len, K, D);
                    MultidimensionalArray Grad_VRes   = MultidimensionalArray.Create(Len, K, D);
                    MultidimensionalArray pARes       = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K);

                    var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len);
                    //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1);
                    //var Normals = LsTrk.GridDat.Edges.NormalsForAffine;


                    for (int i = 0; i < D; i++)
                    {
                        VelGread[0][i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i),
                                                    Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1);

                        VelGread[1][i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i),
                                                    Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1);
                        //UA[0].EvaluateGradient(j0, Len, Ns, Grad_URes, 0, 1); //
                        //UA[1].EvaluateGradient(j0, Len, Ns, Grad_VRes, 0, 1); //
                        //UA[i].EvaluateGradient(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }



                    //pA.Evaluate(j0, Len, Ns, pARes);
                    pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1);


                    //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) * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0];
                                acc -= ((muA) * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1];
                                acc -= ((muA) * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1];
                                acc -= (muA) * StressXXRes[j, k] * Normals[j, k, 0];
                                acc -= (muA) * StressXYRes[j, k] * Normals[j, k, 1];

                                break;

                            case 1:
                                acc += pARes[j, k] * Normals[j, k, 1];
                                acc -= (2 * (muA) * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1];
                                acc -= ((muA) * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0];
                                acc -= ((muA) * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0];
                                acc -= (muA) * StressXYRes[j, k] * Normals[j, k, 0];
                                acc -= (muA) * StressYYRes[j, k] * Normals[j, k, 1];
                                break;

                            default:
                                throw new NotImplementedException();
                            }

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


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

                //EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_bottom");
                EdgeMask Mask = new EdgeMask(LsTrk.GridDat, EdgeTagName);

                EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask);

                EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             eqs.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);
        }
Exemplo n.º 5
0
            public XDGTestSetup(
                int p,
                double AggregationThreshold,
                int TrackerWidth,
                MultigridOperator.Mode mumo,
                XQuadFactoryHelper.MomentFittingVariants momentFittingVariant,
                ScalarFunction LevSetFunc = null)
            {
                // Level set, tracker and XDG basis
                // ================================

                if (LevSetFunc == null)
                {
                    LevSetFunc = ((_2D)((x, y) => 0.8 * 0.8 - x * x - y * y)).Vectorize();
                }
                LevSet = new LevelSet(new Basis(grid, 2), "LevelSet");
                LevSet.Clear();
                LevSet.ProjectField(LevSetFunc);
                LsTrk = new LevelSetTracker(grid, XQuadFactoryHelper.MomentFittingVariants.Classic, TrackerWidth, new string[] { "A", "B" }, LevSet);
                LsTrk.UpdateTracker();

                XB = new XDGBasis(LsTrk, p);

                XSpatialOperator Dummy = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "C1", "u");

                //Dummy.EquationComponents["c1"].Add(new
                Dummy.Commit();

                //Tecplot.PlotFields(new DGField[] { LevSet }, "agglo", 0.0, 3);


                // operator
                // ========

                Debug.Assert(p <= 4);
                XDGBasis opXB = new XDGBasis(LsTrk, 4); // we want to have a very precise quad rule
                var      map  = new UnsetteledCoordinateMapping(opXB);

                int quadOrder = Dummy.QuadOrderFunction(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray());

                //agg = new MultiphaseCellAgglomerator(new CutCellMetrics(momentFittingVariant, quadOrder, LsTrk, LsTrk.SpeciesIdS.ToArray()), AggregationThreshold, false);
                agg = LsTrk.GetAgglomerator(LsTrk.SpeciesIdS.ToArray(), quadOrder, __AgglomerationTreshold: AggregationThreshold);


                foreach (var S in LsTrk.SpeciesIdS)
                {
                    Console.WriteLine("Species {0}, no. of agglomerated cells {1} ",
                                      LsTrk.GetSpeciesName(S),
                                      agg.GetAgglomerator(S).AggInfo.SourceCells.Count());
                }

                // mass matrix factory
                // ===================

                // Basis maxB = map.BasisS.ElementAtMax(b => b.Degree);
                //MassFact = new MassMatrixFactory(maxB, agg);
                MassFact = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), quadOrder, 1).MassMatrixFactory;


                // Test field
                // ==========

                // set the test field: this is a polynomial function,
                // but different for each species; On this field, restriction followed by prolongation should be the identity
                this.uTest = new XDGField(this.XB, "uTest");
                Dictionary <SpeciesId, double> dumia = new Dictionary <SpeciesId, double>();
                int i = 2;

                foreach (var Spc in LsTrk.SpeciesIdS)
                {
                    dumia.Add(Spc, i);
                    i -= 1;
                }
                SetTestValue(uTest, dumia);

                // dummy operator matrix which fits polynomial degree p
                // ====================================================

                opMtx = new BlockMsrMatrix(uTest.Mapping, uTest.Mapping);
                opMtx.AccEyeSp(120.0);

                // XDG Aggregation BasiseS
                // =======================

                XAggB = MgSeq.Select(agGrd => new XdgAggregationBasis[] { new XdgAggregationBasis(uTest.Basis, agGrd) }).ToArray();
                for (int iLevel = 0; iLevel < XAggB.Length; iLevel++)
                {
                    var xab = XAggB[iLevel];
                    Debug.Assert(xab.Length == 1);
                    xab[0].Update(agg);
                }

                // Multigrid Operator
                // ==================



                opMtx = new BlockMsrMatrix(uTest.Mapping, uTest.Mapping);
                opMtx.AccEyeSp(120.0);

                MultigridOp = new MultigridOperator(XAggB, uTest.Mapping,
                                                    opMtx,
                                                    MassFact.GetMassMatrix(uTest.Mapping, false),
                                                    new MultigridOperator.ChangeOfBasisConfig[][] {
                    new MultigridOperator.ChangeOfBasisConfig[] {
                        new MultigridOperator.ChangeOfBasisConfig()
                        {
                            VarIndex = new int[] { 0 }, mode = mumo, Degree = p
                        }
                    }
                });
            }
Exemplo n.º 6
0
        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++;
            }
        }
Exemplo n.º 7
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
        }
Exemplo n.º 8
0
        /// <summary>
        ///
        /// </summary>
        public void AssembleMatrix_Timestepper <T>(
            int CutCellQuadOrder,
            BlockMsrMatrix OpMatrix, double[] OpAffine,
            Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales,
            IEnumerable <T> U0,
            VectorField <SinglePhaseField> SurfaceForce,
            VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature,
            UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping,
            double time) where T : DGField
        {
            if (ColMapping.BasisS.Count != this.Op.DomainVar.Count)
            {
                throw new ArgumentException();
            }
            if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count)
            {
                throw new ArgumentException();
            }

            // check:
            var Tracker = this.LsTrk;
            int D       = Tracker.GridDat.SpatialDimension;

            if (U0 != null && U0.Count() != D)
            {
                throw new ArgumentException();
            }


            LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]);

            SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray();


            // parameter assembly
            // ==================

            // normals:
            SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions.
            if (this.NormalsRequired)
            {
                if (LevelSetGradient == null)
                {
                    LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory);
                    LevelSetGradient.Gradient(1.0, Phi);
                }
                Normals = LevelSetGradient.ToArray();
            }
            else
            {
                Normals = new SinglePhaseField[D];
            }

            // curvature:
            SinglePhaseField Curvature;

            if (this.CurvatureRequired)
            {
                Curvature = ExternalyProvidedCurvature;
            }
            else
            {
                Curvature = null;
            }

            // linearization velocity:
            DGField[] U0_U0mean;
            if (this.U0meanrequired)
            {
                XDGBasis U0meanBasis          = new XDGBasis(Tracker, 0);
                VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory);

                U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean);
            }
            else
            {
                U0_U0mean = new DGField[2 * D];
            }

            // concatenate everything
            var Params = ArrayTools.Cat <DGField>(
                U0_U0mean,
                Curvature,
                ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]),
                Normals);

            // linearization velocity:
            if (this.U0meanrequired)
            {
                VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray());

                U0mean.Clear();
                if (this.physParams.IncludeConvection)
                {
                    ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
                }
            }

            // assemble the matrix & affine vector
            // ===================================

            // compute matrix
            Op.ComputeMatrixEx(Tracker,
                               ColMapping, Params, RowMapping,
                               OpMatrix, OpAffine, false, time, true,
                               AgglomeratedCellLengthScales,
                               SpcToCompute);
        }
Exemplo n.º 9
0
        /// <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");
            }
        }
Exemplo n.º 10
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]);
            }
        }