Beispiel #1
0
        /// <summary>
        /// Solve flow field equations, i.e.
        /// Predictor for velocity and
        /// Corrector for pressure correction.
        /// </summary>
        /// <param name="SIMPLEStatus"></param>
        /// <param name="dt"></param>
        /// <param name="ResLogger"></param>
        protected void SolveFlowFieldEquations(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger)
        {
            // Update flow field SIMPLE operators (first!) and matrix assemblies (second!)
            // ===========================================================================

            UpdateApproximations = (!MatrixAssembliesFlowField.PredictorApprox[0].IsConstant &&
                                    ((SIMPLEStatus.SIMPLEStepNo - 1) % SolverConf.Control.PredictorApproximationUpdateCycle == 0)) ? true : false;

            for (int i = 0; i < SolverConf.SpatialDimension; i++)
            {
                OperatorsFlowField.Convection[i].Update();
                OperatorsFlowField.Visc[i].Update();
                OperatorsFlowField.Swip2[i].Update();
                if (SolverConf.Control.PhysicsMode == PhysicsMode.LowMach)
                {
                    OperatorsFlowField.Swip3[i].Update();
                    OperatorsFlowField.DivergenceConti[i].Update();
                }
                for (int j = 0; j < SolverConf.SpatialDimension; j++)
                {
                    MatrixAssembliesFlowField.ViscSplit[i, j].Update();
                }
                MatrixAssembliesFlowField.Predictor[i].Update();
            }

            if (UpdateApproximations)
            {
                for (int i = 0; i < SolverConf.SpatialDimension; i++)
                {
                    MatrixAssembliesFlowField.PredictorApprox[i].Update();
                    MatrixAssembliesFlowField.PredictorApproxInv[i].Update();
                }
                if (SolverConf.Control.PhysicsMode == PhysicsMode.Multiphase)
                {
                    MatrixAssembliesFlowField.Corrector.Update();
                }
            }

            if (SolverConf.Control.PhysicsMode == PhysicsMode.LowMach)
            {
                // For Low-Mach flows the corrector is never constant
                // due to the density in the divergence operator.
                MatrixAssembliesFlowField.Corrector.Update();
            }

            // Predictor
            // =========

            for (int comp = 0; comp < SolverConf.SpatialDimension; comp++)
            {
                SIMPLESolver Predictor;

                VariableDensitySIMPLEControl varDensConf = SolverConf.Control as VariableDensitySIMPLEControl;
                Predictor = new VariableDensitySolverPredictor(
                    SolverConf,
                    SolverConf.Control.PredictorSolverFactory(),
                    WorkingSetMatrices.Rho.Matrix,
                    MatrixAssembliesFlowField.Predictor[comp],
                    MatrixAssembliesFlowField.PredictorApprox[comp],
                    OperatorsFlowField.PressureGradient,
                    WorkingSet.Pressure,
                    MatrixAssembliesFlowField.ViscSplit,
                    OperatorsFlowField.BuoyantForce,
                    WorkingSet.Velocity,
                    this.GetScalarField(),
                    varDensConf.EoS,
                    BDF);

                Predictor.Solve(WorkingSet.Velocity_Intrmed[comp].CoordinateVector, dt, comp);



                Predictor.Dispose();
            }

            // Corrector
            // =========

            if ((SIMPLEStatus.SIMPLEStepNoTotal == 1) || UpdateApproximations)
            {
                if (Corrector != null)
                {
                    Corrector.Dispose();
                }

                Corrector = this.GetCorrectorSolver();
            }
            Corrector.Solve(WorkingSet.Pressure_Correction.CoordinateVector, dt);

            // Update flow field variables
            // ===========================

            SIMPLEStepUtils.UpdateFlowFieldVariables(dt, SolverConf, OperatorsFlowField.PressureGradient, WorkingSet, BDF, MatrixAssembliesFlowField.PredictorApproxInv);
            if (WorkingSet.DivAfter != null)
            {
                WorkingSet.DivAfter.Clear();
                SolverUtils.CalculateMassDefect_Divergence(OperatorsFlowField.DivergenceConti, WorkingSet.Velocity.Current, WorkingSet.DivAfter);
            }

            // Calculate residuals flow field
            // ==============================

            ResLogger.ComputeL2Norm(WorkingSet.Pressure_Correction, "p'");
            ResLogger.ComputeL2Norm(WorkingSet.VelRes);
        }
        /// <summary>
        /// One SIMPLE iteration for incompressible flows.
        /// </summary>
        /// <param name="SIMPLEStatus"></param>
        /// <param name="dt"></param>
        /// <param name="ResLogger"></param>
        public void OverallIteration(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger)
        {
            using (new FuncTrace()) {
                //Update SIMPLE operators (first!) and matrix assemblies (second!)
                //================================================================

                for (int d = 0; d < m_SolverConf.SpatialDimension; d++)
                {
                    m_IncompressibleOperators.Convection[d].Update();
                    m_IncompressibleMatrixAssemblies.Predictor[d].Update();
                }

                //Determination whether approximation of predictor needs to be updated
                bool UpdatePredictorApprox;
                bool SetPredictorApproxAsConstant = false;
                switch (m_SolverConf.Control.PredictorApproximation)
                {
                case PredictorApproximations.Identity:
                case PredictorApproximations.Identity_IP1:
                    // For unsteady cases the approximation is
                    // gamma * dt / (beta_0 + gamma * dt) * I,
                    // where gamma and beta_0 might not be constant for the first time steps
                    // depending on the current BDF order.
                    if (!m_IncompressibleMatrixAssemblies.PredictorApprox.IsConstant && (SIMPLEStatus.SIMPLEStepNo == 1))
                    {
                        if (m_SolverConf.BDFOrder < m_SolverConf.Control.TimeOrder)
                        {
                            UpdatePredictorApprox = true;
                        }
                        else if (m_SolverConf.BDFOrder == m_SolverConf.Control.TimeOrder)
                        {
                            UpdatePredictorApprox        = true;
                            SetPredictorApproxAsConstant = true;
                        }
                        else
                        {
                            throw new ApplicationException("Should not happen.");
                        }
                    }
                    else
                    {
                        UpdatePredictorApprox = false;
                    }
                    break;

                case PredictorApproximations.Diagonal:
                case PredictorApproximations.BlockDiagonal:
                    UpdatePredictorApprox = (!m_IncompressibleMatrixAssemblies.PredictorApprox.IsConstant &&
                                             ((SIMPLEStatus.SIMPLEStepNo - 1) % m_SolverConf.Control.PredictorApproximationUpdateCycle == 0)) ? true : false;
                    break;

                default:
                    throw new NotImplementedException();
                }

                if (UpdatePredictorApprox)
                {
                    m_IncompressibleMatrixAssemblies.PredictorApprox.Update();
                    m_IncompressibleMatrixAssemblies.PredictorApproxInv.Update();
                    m_IncompressibleMatrixAssemblies.Corrector.Update();
                    if (SetPredictorApproxAsConstant)
                    {
                        m_IncompressibleMatrixAssemblies.PredictorApprox.IsConstant    = true;
                        m_IncompressibleMatrixAssemblies.PredictorApproxInv.IsConstant = true;
                        m_IncompressibleMatrixAssemblies.Corrector.IsConstant          = true;
                    }
                }

                //Predictor
                //=========

                SIMPLESolver Predictor = new SolverPredictor(
                    m_SolverConf,
                    m_SolverConf.Control.PredictorSolverFactory(),
                    m_IncompressibleMatrixAssemblies.Predictor,
                    m_IncompressibleMatrixAssemblies.PredictorApprox,
                    m_IncompressibleOperators.PressureGradient,
                    m_BDF,
                    m_WorkingSet.Velocity,
                    m_WorkingSet.Pressure);

                for (int comp = 0; comp < m_SolverConf.SpatialDimension; comp++)
                {
                    Predictor.Solve(m_WorkingSet.Velocity_Intrmed[comp].CoordinateVector, dt, comp);
                }

                Predictor.Dispose();

                //Corrector
                //=========

                if ((SIMPLEStatus.SIMPLEStepNoTotal == 1) || UpdatePredictorApprox)
                {
                    if (m_Corrector != null)
                    {
                        m_Corrector.Dispose();
                    }

                    m_Corrector = new SolverCorrector(
                        m_SolverConf, m_SolverConf.Control.CorrectorSolverFactory(),
                        m_IncompressibleMatrixAssemblies.Corrector, m_IncompressibleOperators.VelocityDivergence,
                        m_BDF, m_WorkingSet.Velocity_Intrmed, m_WorkingSet.DivB4,
                        m_IncompressibleOperators.PressureStabilization, m_WorkingSet.Pressure);
                }

                m_Corrector.Solve(m_WorkingSet.Pressure_Correction.CoordinateVector, dt);

                //Update variables
                //================

                SIMPLEStepUtils.UpdateFlowFieldVariables(dt, m_SolverConf, m_IncompressibleOperators.PressureGradient, m_WorkingSet, m_BDF, m_IncompressibleMatrixAssemblies.PredictorApproxInv);
                if (m_WorkingSet.DivAfter != null)
                {
                    m_WorkingSet.DivAfter.Clear();
                    SolverUtils.CalculateMassDefect_Divergence(m_IncompressibleOperators.VelocityDivergence, m_WorkingSet.Velocity.Current, m_WorkingSet.DivAfter);
                }

                //Calculate residuals
                //===================

                ResLogger.ComputeL2Norm(m_WorkingSet.Pressure_Correction, "p'");
                ResLogger.ComputeL2Norm(m_WorkingSet.VelRes);

                //Check convergence
                //=================

                if (ResLogger.Residuals["L2Norm p'"] < m_SolverConf.Control.L2NormPressureCorrection &&
                    ResLogger.Residuals["L2Norm u_res"] < m_SolverConf.Control.L2NormVelocityResidual &&
                    ResLogger.Residuals["L2Norm v_res"] < m_SolverConf.Control.L2NormVelocityResidual)
                {
                    if (m_SolverConf.SpatialDimension == 2)
                    {
                        SIMPLEStatus.IsConverged = true;
                    }
                    else if (ResLogger.Residuals["L2Norm w_res"] < m_SolverConf.Control.L2NormVelocityResidual)
                    {
                        SIMPLEStatus.IsConverged = true;
                    }
                }

                //Set SIMPLEStatus
                //================

                if (m_SolverConf.Control.MaxNoSIMPLEsteps == SIMPLEStatus.SIMPLEStepNo)
                {
                    SIMPLEStatus.TerminateSIMPLE = true;
                }

                if ((m_SolverConf.Control.Algorithm == SolutionAlgorithms.Steady_SIMPLE) && (SIMPLEStatus.SIMPLEStepNo % m_SolverConf.Control.SavePeriodSIMPLE == 0))
                {
                    SIMPLEStatus.SaveStep = true;
                }
            }
        }