/// ====================================================================================
 /// <summary>
 /// This method performs the integration in y-direction
 /// torque.
 /// </summary>
 /// <param name="Grad_UARes">
 /// The gradient of the velocity.
 /// </param>
 /// <param name="pARes">
 /// The pressure.
 /// </param>
 /// <param name="NormalVector">
 /// The normal vector at the current node in the current cell.
 /// </param>
 /// <param name="FluidViscosity">
 /// The viscosity of the fluid.
 /// </param>
 /// <param name="k">
 /// The current node ID.
 /// </param>
 /// <param name="j">
 /// The current cell ID
 /// </param>
 /// ====================================================================================
 private double CalculateStressTensorY(MultidimensionalArray Grad_UARes, MultidimensionalArray pARes, MultidimensionalArray NormalVector, double FluidViscosity, int k, int j)
 {
     double[] SummandsVelGradient = new double[3];
     double SummandsPressure;
     SummandsVelGradient[0] = -2 * Grad_UARes[j, k, 1, 1] * NormalVector[j, k, 1];
     SummandsVelGradient[1] = -Grad_UARes[j, k, 1, 0] * NormalVector[j, k, 0];
     SummandsVelGradient[2] = -Grad_UARes[j, k, 0, 1] * NormalVector[j, k, 0];
     SummandsPressure = pARes[j, k] * NormalVector[j, k, 1];
     return ParticleAuxillary.SummationWithNeumaier(SummandsVelGradient, SummandsPressure, FluidViscosity);
 }
 /// ====================================================================================
 /// <summary>
 /// This method calculates the stress tensor in case of a 3D-probem
 /// torque.
 /// </summary>
 /// <param name="Grad_UARes">
 /// The gradient of the velocity.
 /// </param>
 /// <param name="pARes">
 /// The pressure.
 /// </param>
 /// <param name="NormalVector">
 /// The normal vector at the current node in the current cell.
 /// </param>
 /// <param name="FluidViscosity">
 /// The viscosity of the fluid.
 /// </param>
 /// <param name="k">
 /// The current node ID.
 /// </param>
 /// <param name="j">
 /// The current cell ID
 /// </param>
 /// <param name="currentDimension">
 /// The current dimension to be calculated.
 /// </param>
 /// ====================================================================================
 private double CalculateStressTensor3D(MultidimensionalArray Grad_UARes, MultidimensionalArray pARes, MultidimensionalArray NormalVector, double FluidViscosity, int k, int j, int currentDimension)
 {
     double acc = 0.0;
     double[] SummandsVelGradient = new double[5];
     double SummandsPressure;
     switch (currentDimension)
     {
         case 0:
             SummandsPressure = pARes[j, k] * NormalVector[j, k, 0];
             SummandsVelGradient[0] = -2 * Grad_UARes[j, k, 0, 0] * NormalVector[j, k, 0];
             SummandsVelGradient[1] = -Grad_UARes[j, k, 0, 2] * NormalVector[j, k, 2];
             SummandsVelGradient[2] = -Grad_UARes[j, k, 0, 1] * NormalVector[j, k, 1];
             SummandsVelGradient[3] = -Grad_UARes[j, k, 1, 0] * NormalVector[j, k, 1];
             SummandsVelGradient[4] = -Grad_UARes[j, k, 2, 0] * NormalVector[j, k, 2];
             acc += ParticleAuxillary.SummationWithNeumaier(SummandsVelGradient, SummandsPressure, FluidViscosity);
             break;
         case 1:
             SummandsPressure = pARes[j, k] * NormalVector[j, k, 1];
             SummandsVelGradient[0] = -2 * Grad_UARes[j, k, 1, 1] * NormalVector[j, k, 1];
             SummandsVelGradient[1] = -Grad_UARes[j, k, 1, 2] * NormalVector[j, k, 2];
             SummandsVelGradient[2] = -Grad_UARes[j, k, 1, 0] * NormalVector[j, k, 0];
             SummandsVelGradient[3] = -Grad_UARes[j, k, 0, 1] * NormalVector[j, k, 0];
             SummandsVelGradient[4] = -Grad_UARes[j, k, 2, 1] * NormalVector[j, k, 2];
             acc += ParticleAuxillary.SummationWithNeumaier(SummandsVelGradient, SummandsPressure, FluidViscosity);
             break;
         case 2:
             SummandsPressure = pARes[j, k] * NormalVector[j, k, 2];
             SummandsVelGradient[0] = -2 * Grad_UARes[j, k, 2, 2] * NormalVector[j, k, 2];
             SummandsVelGradient[1] = -Grad_UARes[j, k, 2, 0] * NormalVector[j, k, 0];
             SummandsVelGradient[2] = -Grad_UARes[j, k, 2, 1] * NormalVector[j, k, 1];
             SummandsVelGradient[3] = -Grad_UARes[j, k, 0, 2] * NormalVector[j, k, 0];
             SummandsVelGradient[4] = -Grad_UARes[j, k, 1, 2] * NormalVector[j, k, 1];
             acc += ParticleAuxillary.SummationWithNeumaier(SummandsVelGradient, SummandsPressure, FluidViscosity);
             break;
         default:
             throw new NotImplementedException();
     }
     return acc;
 }
Esempio n. 3
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]);
            }
        }