public override void OverallIteration(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger) { using (new FuncTrace()) { // Solve flow field and scalar field base.SolveFlowFieldEquations(ref SIMPLEStatus, dt, ResLogger); this.SolveScalarEquations(ref SIMPLEStatus, dt, ResLogger); // Check convergence if (ResLogger.Residuals["L2Norm p'"] < MultiphaseControl.L2NormPressureCorrection && ResLogger.Residuals["L2Norm u_res"] < MultiphaseControl.L2NormVelocityResidual && ResLogger.Residuals["L2Norm v_res"] < MultiphaseControl.L2NormVelocityResidual && ResLogger.Residuals["L2Norm Phi_res"] < MultiphaseControl.L2NormLevelSetResidual) { if (SolverConf.SpatialDimension == 2) { SIMPLEStatus.IsConverged = true; } else if (ResLogger.Residuals["L2Norm w_res"] < MultiphaseControl.L2NormVelocityResidual) { SIMPLEStatus.IsConverged = true; } } // Set SIMPLEStatus if (MultiphaseControl.MaxNoSIMPLEsteps == SIMPLEStatus.SIMPLEStepNo) { SIMPLEStatus.TerminateSIMPLE = true; } if ((MultiphaseControl.Algorithm == SolutionAlgorithms.Steady_SIMPLE) && (SIMPLEStatus.SIMPLEStepNo % MultiphaseControl.SavePeriodSIMPLE == 0)) { SIMPLEStatus.SaveStep = true; } } }
/// <summary> /// /// </summary> protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (new FuncTrace()) { // Create SIMPLEStatus SIMPLEStatus = new SIMPLEStepStatus(Control); // Create SIMPLEStep switch (Control.PhysicsMode) { case PhysicsMode.Incompressible: SIMPLEStep = new SIMPLEStepIncompressible(SolverConf, WorkingSet); break; case PhysicsMode.LowMach: SIMPLEStep = new SIMPLEStepLowMach(SolverConf, WorkingSet, WorkingSetMatrices); break; case PhysicsMode.Multiphase: SIMPLEStep = new SIMPLEStepMultiphase(SolverConf, WorkingSet, WorkingSetMatrices); break; default: throw new NotImplementedException(); } } }
protected override void SolveScalarEquations(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger) { // Update temperature field SIMPLE operators (first!) and matrix assemblies (second!) // ================================================================================== OperatorsTemperature.TemperatureConvection.Update(); OperatorsTemperature.HeatConduction.Update(); MatrixAssembliesTemperature.Temperature.Update(); if ((LowMachControl.RelaxationModeTemperature == RelaxationTypes.Implicit) && !MatrixAssembliesTemperature.TemperatureApprox.IsConstant && ((SIMPLEStatus.SIMPLEStepNo - 1) % LowMachControl.PredictorApproximationUpdateCycle == 0)) { MatrixAssembliesTemperature.TemperatureApprox.Update(); } // Temperature solver // ================== SIMPLESolver TemperatureSolver = new LowMachSolverTemperature( this.SolverConf, LowMachControl.TemperatureSolverFactory(), base.WorkingSetMatrices.Rho.Matrix, this.MatrixAssembliesTemperature.Temperature, this.MatrixAssembliesTemperature.TemperatureApprox, base.WorkingSet.Temperature, base.BDF, LowMachControl.EoS, base.WorkingSet.ThermodynamicPressure); base.WorkingSet.TemperatureRes.Clear(); base.WorkingSet.TemperatureRes.Acc(1.0, base.WorkingSet.Temperature.Current); TemperatureSolver.Solve(base.WorkingSet.Temperature.Current.CoordinateVector, dt); TemperatureSolver.Dispose(); // Update temperature field variables // ================================== SIMPLEStepUtils.UpdateScalarFieldVariables( LowMachControl, LowMachControl.RelaxationModeTemperature, LowMachControl.RelexationFactorTemperature, base.WorkingSet.Temperature, base.WorkingSet.TemperatureRes, base.WorkingSet.TemperatureMean, base.WorkingSet.Rho, base.WorkingSet.Eta, base.WorkingSetMatrices.Rho, LowMachControl.EoS, base.WorkingSet.ThermodynamicPressure.Current); // Calculate residuals temperature // =============================== ResLogger.ComputeL2Norm(base.WorkingSet.TemperatureRes); }
/// <summary> /// One segregated iteration, /// i.e. solving either flow field or temperature field in one iteration. /// </summary> /// <param name="SIMPLEStatus"></param> /// <param name="dt"></param> /// <param name="ResLogger"></param> private void SegregatedIteration(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger) { if (CntInnerIterSegregatedStep <= LowMachControl.MaxFlowSolverIterations) { // Solve equations flow field base.SolveFlowFieldEquations(ref SIMPLEStatus, dt, ResLogger); // Check convergence flow field if (ResLogger.Residuals["L2Norm p'"] < LowMachControl.L2NormPressureCorrection && ResLogger.Residuals["L2Norm u_res"] < LowMachControl.L2NormVelocityResidual && ResLogger.Residuals["L2Norm v_res"] < LowMachControl.L2NormVelocityResidual) { if (base.SolverConf.SpatialDimension == 2) { CntInnerIterSegregatedStep = LowMachControl.MaxFlowSolverIterations; } else if (ResLogger.Residuals["L2Norm w_res"] < LowMachControl.L2NormVelocityResidual) { CntInnerIterSegregatedStep = LowMachControl.MaxFlowSolverIterations; } } // Set SIMPLEStatus if (CntInnerIterSegregatedStep == LowMachControl.MaxFlowSolverIterations) { SIMPLEStatus.SaveStep = true; } // Workaround for plotting residuals ResLogger.ComputeL2Norm(base.WorkingSet.TemperatureRes); } else { // Solve temperature equation this.SolveScalarEquations(ref SIMPLEStatus, dt, ResLogger); // Check convergence temperature field if ((ResLogger.Residuals["L2Norm T_res"] < LowMachControl.L2NormTemperatureResidual) || (CntInnerIterSegregatedStep == LowMachControl.MaxFlowSolverIterations + LowMachControl.MaxTemperatureSolverIterations)) { CntInnerIterSegregatedStep = 0; SIMPLEStatus.NextSegregatedStep(); // Set SIMPLEStatus SIMPLEStatus.SaveStep = true; if (SIMPLEStatus.Timestep[1] > LowMachControl.MaxNoSIMPLEsteps) { SIMPLEStatus.IsConverged = true; } } // Workaround for plotting residuals ResLogger.ComputeL2Norm(WorkingSet.Pressure_Correction, "p'"); ResLogger.ComputeL2Norm(WorkingSet.VelRes); } CntInnerIterSegregatedStep++; }
public override void OverallIteration(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger) { if ((LowMachControl.MaxFlowSolverIterations == 1) && (LowMachControl.MaxTemperatureSolverIterations == 1)) { FullyCoupledIteration(ref SIMPLEStatus, dt, ResLogger); } else { SegregatedIteration(ref SIMPLEStatus, dt, ResLogger); } }
/// <summary> /// One fully coupled iteration, /// i.e. solving flow field and temperature field in one iteration. /// </summary> /// <param name="SIMPLEStatus"></param> /// <param name="dt"></param> /// <param name="ResLogger"></param> private void FullyCoupledIteration(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger) { // Solve flow field and temperature field base.SolveFlowFieldEquations(ref SIMPLEStatus, dt, ResLogger); this.SolveScalarEquations(ref SIMPLEStatus, dt, ResLogger); // Check convergence if (ResLogger.Residuals["L2Norm p'"] < LowMachControl.L2NormPressureCorrection && ResLogger.Residuals["L2Norm u_res"] < LowMachControl.L2NormVelocityResidual && ResLogger.Residuals["L2Norm v_res"] < LowMachControl.L2NormVelocityResidual && ResLogger.Residuals["L2Norm T_res"] < LowMachControl.L2NormTemperatureResidual) { if (base.SolverConf.SpatialDimension == 2) { SIMPLEStatus.IsConverged = true; } else if (ResLogger.Residuals["L2Norm w_res"] < LowMachControl.L2NormVelocityResidual) { SIMPLEStatus.IsConverged = true; } } // Set SIMPLEStatus if (LowMachControl.MaxNoSIMPLEsteps == SIMPLEStatus.SIMPLEStepNo) { SIMPLEStatus.TerminateSIMPLE = true; } if ((LowMachControl.Algorithm == SolutionAlgorithms.Steady_SIMPLE) && (SIMPLEStatus.SIMPLEStepNo % LowMachControl.SavePeriodSIMPLE == 0)) { SIMPLEStatus.SaveStep = true; } /* * // Solve only temperature equation (only used for debugging). * this.SolveScalarEquations(ref SIMPLEStatus, dt, ResLogger); * SIMPLEStatus.SaveStep = true; * * // Check convergence temperature field * if ((ResLogger.Residuals["L2Norm T_res"] < base.SolverConf.L2NormTemperatureRes) || (SolverConf.MaxNoSIMPLEsteps == SIMPLEStatus.SIMPLEStepNo)) { || || // Set SIMPLEStatus || SIMPLEStatus.TerminateSIMPLE = true; ||} || ||// Workaround for plotting residuals ||ResLogger.ComputeL2Norm(WorkingSet.Pressure_Correction, "p'"); ||ResLogger.ComputeL2Norm(WorkingSet.VelRes);*/ }
protected override void SolveScalarEquations(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger) { // Update level-set SIMPLE operators (first!) and matrix assemblies (second!) // ========================================================================== OperatorsLevelSet.LevelSetAdvection.Update(); MatrixAssembliesLevelSet.LevelSet.Update(); if (base.UpdateApproximations && (MultiphaseControl.LevelSetRelaxationType == RelaxationTypes.Implicit)) { MatrixAssembliesLevelSet.LevelSetApprox.Update(); } // Level-Set solver // ================ SIMPLESolver LevelSetSolver = new MultiphaseSolverLevelSet( SolverConf, MultiphaseControl.LevelSetSolverFactory(), MatrixAssembliesLevelSet.LevelSet, MatrixAssembliesLevelSet.LevelSetApprox, base.WorkingSet.Phi, base.BDF); base.WorkingSet.PhiRes.Clear(); base.WorkingSet.PhiRes.Acc(1.0, base.WorkingSet.Phi.Current); LevelSetSolver.Solve(base.WorkingSet.Phi.Current.CoordinateVector, dt); LevelSetSolver.Dispose(); // Update level-set variables // ========================== SIMPLEStepUtils.UpdateScalarFieldVariables( MultiphaseControl, MultiphaseControl.LevelSetRelaxationType, MultiphaseControl.RelaxationFactorLevelSet, base.WorkingSet.Phi, base.WorkingSet.PhiRes, base.WorkingSet.PhiMean, base.WorkingSet.Rho, base.WorkingSet.Eta, base.WorkingSetMatrices.Rho, MultiphaseControl.EoS, null); // Calculate residuals level-set // ============================= ResLogger.ComputeL2Norm(base.WorkingSet.PhiRes); }
/// <summary> /// Solve scalar equations, i.e. /// level-set equation for multiphase and /// temperature equation for Low-Mach. /// </summary> /// <param name="dt"></param> protected abstract void SolveScalarEquations(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger);
/// <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 low Mach number flows. /// </summary> /// <param name="SIMPLEStatus"></param> /// <param name="dt"></param> /// <param name="ResLogger"></param> public abstract void OverallIteration(ref SIMPLEStepStatus SIMPLEStatus, double dt, ResidualLogger ResLogger);
/// <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; } } }