/// <summary> /// ... /// </summary> public override void PostRestart(double time, TimestepNumber timestep) { //InitLogEnergyOrrSommerfeld(); WorkingSet.Initialize(Control); // Create WorkingSetMatrices switch (Control.PhysicsMode) { case PhysicsMode.Incompressible: break; case PhysicsMode.LowMach: LowMachSIMPLEControl lowMachConf = Control as LowMachSIMPLEControl; m_WorkingSetMatrices = new VariableMatrices(base.GridData, WorkingSet.VelBasis, WorkingSet.PressureBasis, lowMachConf.EoS, WorkingSet.Temperature.Current); break; case PhysicsMode.Multiphase: MultiphaseSIMPLEControl multiphaseConf = Control as MultiphaseSIMPLEControl; m_WorkingSetMatrices = new VariableMatrices(base.GridData, WorkingSet.VelBasis, WorkingSet.PressureBasis, multiphaseConf.EoS, WorkingSet.Phi.Current); break; default: throw new NotImplementedException(); } WorkingSet.CheckForNanOrInf(Control); // push start values to history WorkingSet.Push(Control); }
/// <summary> /// Calculate Nusselt number for Low-Mach number flows. /// </summary> /// <param name="Timestep"></param> /// <param name="GridDat"></param> /// <param name="Temperature"></param> /// <param name="SolverConf"></param> void CalculateNusselt(TimestepNumber Timestep, IGridData GridDat, SinglePhaseField Temperature, SIMPLEControl SolverConf) { // Initialize calculation of Nusselt number. if (NusseltNum == null) { LowMachSIMPLEControl lowMachConf = SolverConf as LowMachSIMPLEControl; NusseltNum = new NusseltNumber(GridDat, Temperature, lowMachConf.EoS, lowMachConf.EdgeTagsNusselt); if ((base.MPIRank == 0) && (CurrentSessionInfo.ID != Guid.Empty)) { LogNusselt = base.DatabaseDriver.FsDriver.GetNewLog("Nusselt", CurrentSessionInfo.ID); LogNusselt.Write("Timestep"); for (int bc = 0; bc < NusseltNum.Nusselt.Length; bc++) { LogNusselt.Write("\t" + lowMachConf.EdgeTagsNusselt[bc]); } LogNusselt.WriteLine(); } } // Calculate Nusselt number NusseltNum.CalculateNusseltNumber(); // Write result to text file if ((base.MPIRank == 0) && (LogNusselt != null)) { LogNusselt.Write(Timestep.ToString()); for (int bc = 0; bc < NusseltNum.Nusselt.Length; bc++) { LogNusselt.Write("\t" + NusseltNum.Nusselt[bc].ToString("0.0000000000E+00", NumberFormatInfo.InvariantInfo)); } LogNusselt.WriteLine(); LogNusselt.Flush(); } }
/// <summary> /// Ctor. /// </summary> /// <param name="SolverConf"></param> /// <param name="WorkingSet"></param> /// <param name="WorkingSetMatrices"></param> public SIMPLEStepLowMach(SolverConfiguration SolverConf, VariableSet WorkingSet, VariableMatrices WorkingSetMatrices) : base(SolverConf, WorkingSet, WorkingSetMatrices) { this.LowMachControl = SolverConf.Control as LowMachSIMPLEControl; if (this.LowMachControl == null) { throw new ArgumentException("Invalid config", nameof(SolverConf)); } // Construct SIMPLEOperators UnsetteledCoordinateMapping TemperatureMapping = new UnsetteledCoordinateMapping(WorkingSet.TemperatureBasis); UnsetteledCoordinateMapping PressureMapping = new UnsetteledCoordinateMapping(WorkingSet.PressureBasis); OperatorsTemperature = new OperatorFactoryTemperature( TemperatureMapping, PressureMapping, base.WorkingSet.Velocity.Current, base.WorkingSet.VelocityMean, base.WorkingSet.Temperature.Current, base.WorkingSet.TemperatureMean, SolverConf); // Construct matrix assemblies MatrixAssembliesTemperature = new MatrixFactoryTemperature( OperatorsTemperature, TemperatureMapping.GridDat.iLogicalCells.NoOfLocalUpdatedCells, WorkingSetMatrices.Rho.Matrix, SolverConf, base.BDF); }
protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection) { LowMachSIMPLEControl lowMachControl = SolverConf.Control as LowMachSIMPLEControl; return((new swipHeatConduction(lowMachControl.Reynolds, lowMachControl.Prandtl, lowMachControl.EoS, SolverConf.PenaltyHeatConduction, base.GridData.Cells.cj, SolverConf.BcMap)).Operator()); }
/// <summary> /// Ctor. /// </summary> public MatrixFactoryTemperature(OperatorFactoryTemperature TemperatureOperators, int LocalNoOfCells, BlockDiagonalMatrix Rho, SolverConfiguration solverConf, BDFScheme BDF) { Temperature = new MatrixAssemblyTemperature(TemperatureOperators.TemperatureConvection, TemperatureOperators.HeatConduction); LowMachSIMPLEControl lowMachControl = solverConf.Control as LowMachSIMPLEControl; if (lowMachControl.RelaxationModeTemperature == RelaxationTypes.Implicit) { TemperatureApprox = new MatrixAssemblyApprox( solverConf, LocalNoOfCells, Temperature, BDF, Rho, 2 * lowMachControl.PredictorApproximationUpdateCycle); } }
/// <summary> /// /// </summary> protected override void CreateFields() { using (new FuncTrace()) { // create fields for flow field WorkingSet = new VariableSet(base.GridData, Control, base.m_IOFields, base.m_RegisteredFields); // create extended fields for variable density solvers WorkingSet.CreateExtendedVariables(Control); // read settings for SIMPLE-algorithm SolverConf = new SolverConfiguration( Control, GridData, WorkingSet, base.MPIRank); // Plot analytic solution PlotAnalyticSolution(Control.AnalyticVelocityX, WorkingSet.VelBasis, "VelocityX_Ana"); PlotAnalyticSolution(Control.AnalyticVelocityY, WorkingSet.VelBasis, "VelocityY_Ana"); if (SolverConf.SpatialDimension == 3) { PlotAnalyticSolution(Control.AnalyticVelocityZ, WorkingSet.VelBasis, "VelocityZ_Ana"); } PlotAnalyticSolution(Control.AnalyticPressure, WorkingSet.PressureBasis, "Pressure_Ana"); switch (Control.PhysicsMode) { case PhysicsMode.Incompressible: break; case PhysicsMode.LowMach: LowMachSIMPLEControl lowMachConf = Control as LowMachSIMPLEControl; PlotAnalyticSolution(lowMachConf.AnalyticTemperature, WorkingSet.TemperatureBasis, "Temperature_Ana"); PlotAnalyticSolution(lowMachConf.AnalyticDensity, WorkingSet.TemperatureBasis, "Density_Ana"); break; case PhysicsMode.Multiphase: MultiphaseSIMPLEControl multiphaseConf = Control as MultiphaseSIMPLEControl; PlotAnalyticSolution(multiphaseConf.AnalyticLevelSet, WorkingSet.LevelSetBasis, "LevelSet_Ana"); PlotAnalyticSolution(multiphaseConf.AnalyticDensity, WorkingSet.LevelSetBasis, "Density_Ana"); break; default: throw new NotImplementedException(); } } }
public SolverConfiguration( SIMPLEControl control, IGridData GridDat, VariableSet workingSet, int MPIRank) { this.SpatialDimension = GridDat.SpatialDimension; this.MPIRank = MPIRank; this.Control = control; this.BcMap = new IncompressibleBoundaryCondMap(GridDat, Control.BoundaryValues, Control.PhysicsMode); CheckSetupPressure(SpatialDimension); if (Control.PressureReferencePoint != null) { UnsetteledCoordinateMapping MappingPressure = new UnsetteledCoordinateMapping( new Basis(GridDat, workingSet.Pressure.Basis.Degree)); PressureReferencePointIndex = BoSSS.Solution.NSECommon.SolverUtils.GetIndexOfPressureReferencePoint(Control.PressureReferencePoint, MappingPressure, 0); if (PressureReferencePointIndex < 0) { throw new ApplicationException("Unknown error finding index for pressure reference point."); } } // SIP penalty for viscous part of momentum equation this.PenaltyViscMomentum = Control.ViscousPenaltyScaling; // SIP penalty for SIP pressure correction if ((Control.PredictorApproximation == PredictorApproximations.Identity_IP1)) { this.PenaltyPressureCorrection = Control.PressureCorrectionPenaltyScaling * GetSIPPenaltyBase(workingSet.Pressure.Basis.Degree, GridDat); } else if (Control.PressureCorrectionPenaltyScaling != 1.0) { throw new NotSupportedException("Extended property 'penalty_PressureCorrection' is only available for Identity_IP option."); } if (control.PhysicsMode == PhysicsMode.LowMach) { LowMachSIMPLEControl lowMachControl = control as LowMachSIMPLEControl; this.PenaltyHeatConduction = lowMachControl.PenaltyHeatConductionScaling * GetSIPPenaltyBase(workingSet.Pressure.Basis.Degree, GridDat); } this.Velocity = workingSet.Velocity; dt = control.Endtime / control.NoOfTimesteps; }
/// <summary> /// Ctor. /// </summary> /// <param name="solverConfig"></param> /// <param name="_sparseSolver"></param> /// <param name="DensityMatrix"></param> /// <param name="MatAsmblyTemperature"></param> /// <param name="MatAsmblyTemperatureApprox"></param> /// <param name="Temperature"></param> /// <param name="BDF"></param> /// <param name="EoS"></param> /// <param name="ThermodynamicPressure"></param> public LowMachSolverTemperature(SolverConfiguration solverConfig, ISparseSolver _sparseSolver, BlockDiagonalMatrix DensityMatrix, SIMPLEMatrixAssembly MatAsmblyTemperature, SIMPLEMatrixAssembly MatAsmblyTemperatureApprox, ScalarFieldHistory <SinglePhaseField> Temperature, BDFScheme BDF, MaterialLaw EoS, ScalarFieldHistory <SinglePhaseField> ThermodynamicPressure) : base(solverConfig, _sparseSolver) { this.DensityMatrix = DensityMatrix; this.MatAsmblyTemperature = MatAsmblyTemperature; this.MatAsmblyTemperatureApprox = MatAsmblyTemperatureApprox; LowMachSIMPLEControl lowMachControl = solverConfig.Control as LowMachSIMPLEControl; this.ModeRelaxTemperature = lowMachControl.RelaxationModeTemperature; this.RelaxFactor = (1.0 - lowMachControl.RelexationFactorTemperature) / lowMachControl.RelexationFactorTemperature; this.Temperature = Temperature; this.BDF = BDF; this.EoS = EoS; this.gamma = lowMachControl.Gamma; this.ThermodynamicPressure = ThermodynamicPressure; }
/// <summary> /// Initializes velocity and pressure /// </summary> protected override void SetInitial() { //WriteQuadNodesOrrSommerfeld(); //InitOrrSommerfeld(); base.SetInitial(); //TaylorVortexHack(); WorkingSet.Initialize(Control); // Create WorkingSetMatrices switch (Control.PhysicsMode) { case PhysicsMode.Incompressible: break; case PhysicsMode.LowMach: LowMachSIMPLEControl lowMachConf = Control as LowMachSIMPLEControl; m_WorkingSetMatrices = new VariableMatrices(base.GridData, WorkingSet.VelBasis, WorkingSet.PressureBasis, lowMachConf.EoS, WorkingSet.Temperature.Current); break; case PhysicsMode.Multiphase: MultiphaseSIMPLEControl multiphaseConf = Control as MultiphaseSIMPLEControl; m_WorkingSetMatrices = new VariableMatrices(base.GridData, WorkingSet.VelBasis, WorkingSet.PressureBasis, multiphaseConf.EoS, WorkingSet.Phi.Current); break; default: throw new NotImplementedException(); } WorkingSet.CheckForNanOrInf(Control); // push start values to history WorkingSet.Push(Control); }
/// <summary> /// /// </summary> protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { using (var tr = new FuncTrace()) { tr.Info("Performing time iteration No. " + TimestepNo); // Set dt and SIMPLEStatus switch (Control.Algorithm) { case SolutionAlgorithms.Steady_SIMPLE: { dt = 0.0; break; } case SolutionAlgorithms.Unsteady_SIMPLE: { dt = SolverConf.dt; SIMPLEStatus.NextTimestep(); break; } } // some console-output if (base.MPIRank == 0) { switch (Control.Algorithm) { case SolutionAlgorithms.Steady_SIMPLE: Console.WriteLine("Starting steady calculation...\n"); Console.WriteLine("Starting SIMPLE-Iterations...\n"); break; case SolutionAlgorithms.Unsteady_SIMPLE: Console.WriteLine("Starting time step #" + TimestepNo + "...\n"); Console.WriteLine("Starting SIMPLE-Iterations...\n"); break; default: throw new NotImplementedException(); } } do { // do one SIMPLE iteration SIMPLEStatus.NextSIMPLEIteration(); SIMPLEStep.OverallIteration(ref SIMPLEStatus, dt, ResLogger); TerminationKey = WorkingSet.CheckForNanOrInf(Control); if (TerminationKey) { m_Logger.Warn("Found Nan in some field."); if (base.MPIRank == 0) { Console.WriteLine("ERROR: Found Nan in some field."); } Console.ReadKey(); } if ((Control.PhysicsMode == PhysicsMode.LowMach) && (SolverConf.Control.As <LowMachSIMPLEControl>().EdgeTagsNusselt != null)) { CalculateNusselt(SIMPLEStatus.Timestep, base.GridData, WorkingSet.Temperature.Current, Control); } // save to database if (SIMPLEStatus.SaveStep) { SaveToDatabase(SIMPLEStatus.Timestep, phystime); } // calculate errors int QuadDegreePressure = 20; int QuadDegreeVel = 20; ResLogger.ComputeL2Error(WorkingSet.Pressure, Control.AnalyticPressure, QuadDegreePressure, "p_ana"); ResLogger.ComputeL2Error(WorkingSet.Velocity.Current[0], Control.AnalyticVelocityX, QuadDegreeVel, "u_ana"); ResLogger.ComputeL2Error(WorkingSet.Velocity.Current[1], Control.AnalyticVelocityY, QuadDegreeVel, "v_ana"); if (SolverConf.SpatialDimension == 3) { ResLogger.ComputeL2Error(WorkingSet.Velocity.Current[2], Control.AnalyticVelocityZ, QuadDegreeVel, "w_ana"); } switch (Control.PhysicsMode) { case PhysicsMode.Incompressible: break; case PhysicsMode.LowMach: LowMachSIMPLEControl lowMachConf = Control as LowMachSIMPLEControl; ResLogger.ComputeL2Error(WorkingSet.Temperature.Current, lowMachConf.AnalyticTemperature, QuadDegreeVel, "T_ana"); ResLogger.ComputeL2Error(WorkingSet.Rho, lowMachConf.AnalyticDensity, QuadDegreeVel, "Rho_ana"); break; case PhysicsMode.Multiphase: MultiphaseSIMPLEControl multiphaseConf = Control as MultiphaseSIMPLEControl; ResLogger.ComputeL2Error(WorkingSet.Phi.Current, multiphaseConf.AnalyticLevelSet, QuadDegreeVel, "Phi_ana"); ResLogger.ComputeL2Error(WorkingSet.Rho, multiphaseConf.AnalyticDensity, QuadDegreeVel, "Rho_ana"); break; default: throw new NotImplementedException(); } // terminate SIMPLE in case of divergence if (ResLogger.Residuals["L2Norm p'"] > 1.0E+10) { TerminationKey = true; } // push residual logger to next iteration switch (Control.Algorithm) { case SolutionAlgorithms.Steady_SIMPLE: ResLogger.NextIteration(false); break; case SolutionAlgorithms.Unsteady_SIMPLE: ResLogger.NextIteration(true); break; default: throw new NotImplementedException(); } }while (!SIMPLEStatus.IsConverged && !SIMPLEStatus.TerminateSIMPLE && !TerminationKey); // determine cause for end of SIMPLE iterations if (SIMPLEStatus.IsConverged) { tr.Info("Solution converged."); } else if (SIMPLEStatus.TerminateSIMPLE) { if (SIMPLEStatus.SIMPLEStepNo == Control.MaxNoSIMPLEsteps) { SIMPLEStatus.CntMaxNoSIMPLEsteps++; m_Logger.Warn("MaxNoSIMPLEsteps are reached."); } else { m_Logger.Warn("Unknown reason for terminating SIMPLE iterations - should not happen."); } } else { m_Logger.Error("Solution diverged."); } // save the new timestep switch (Control.Algorithm) { case SolutionAlgorithms.Steady_SIMPLE: break; case SolutionAlgorithms.Unsteady_SIMPLE: WorkingSet.Push(Control); ResLogger.NextTimestep(false); break; default: throw new NotImplementedException(); } // some console-output if (SIMPLEStatus.IsConverged) { Console.WriteLine("\nINFO: Done SIMPLE-Iterations - Solution converged.\n"); } else if (SIMPLEStatus.SIMPLEStepNo == Control.MaxNoSIMPLEsteps) { Console.WriteLine("\nWARNING: Done SIMPLE-Iterations - Maximum number of SIMPLE steps was reached.\n"); } else { Console.WriteLine("\nERROR: Calculation was terminated - Solution diverged.\n"); } switch (Control.Algorithm) { case SolutionAlgorithms.Steady_SIMPLE: Console.WriteLine("Done steady calculation."); break; case SolutionAlgorithms.Unsteady_SIMPLE: Console.WriteLine("Done time step #" + TimestepNo + ".\n"); break; default: throw new NotImplementedException(); } //LogEnergyOrrSommerfeld(TimestepNo, phystime, dt); if (Control.EdgeTagsDragAndLift != null) { CalculateDragAndLift(phystime); } //Log temperature history tall cavity //LogTemperature(phystime, this.WorkingSet.Temperature.Current); return(dt); } }
/// <summary> /// Update scalar field variables after solving scalar equation. /// </summary> /// <param name="SolverConf"></param> /// <param name="ModeRelaxScalar"></param> /// <param name="relax_scalar"></param> /// <param name="Scalar"></param> /// <param name="ScalarRes"></param> /// <param name="ScalarMean"></param> /// <param name="Rho"></param> /// <param name="Eta"></param> /// <param name="RhoMatrix"></param> /// <param name="EoS"></param> /// <param name="ThermodynamicPressure">Null for multiphase flows.</param> public static void UpdateScalarFieldVariables(SIMPLEControl SolverConf, RelaxationTypes ModeRelaxScalar, double relax_scalar, ScalarFieldHistory <SinglePhaseField> Scalar, SinglePhaseField ScalarRes, SinglePhaseField ScalarMean, SinglePhaseField Rho, SinglePhaseField Eta, QuadratureMatrix RhoMatrix, MaterialLaw EoS, SinglePhaseField ThermodynamicPressure, bool UpdateRhoVisc = true) { using (new FuncTrace()) { // Explicit Under-Relaxation of scalar variable // ============================================ if (ModeRelaxScalar == RelaxationTypes.Explicit) { // phi = alpha * phi_new + (1-alpha) * phi_old Scalar.Current.Scale(relax_scalar); Scalar.Current.Acc((1.0 - relax_scalar), ScalarRes); } // Scalar residual // =============== ScalarRes.Scale(-1.0); ScalarRes.Acc(1.0, Scalar.Current); // ScalarMean // ========== ScalarMean.Clear(); ScalarMean.AccLaidBack(1.0, Scalar.Current); // Thermodynamic pressure - only for Low-Mach number flows // ======================================================= switch (SolverConf.PhysicsMode) { case PhysicsMode.LowMach: LowMachSIMPLEControl lowMachConf = SolverConf as LowMachSIMPLEControl; if (lowMachConf.ThermodynamicPressureMode == ThermodynamicPressureMode.MassDetermined) { ThermodynamicPressure.Clear(); ThermodynamicPressure.AccConstant(((MaterialLawLowMach)EoS).GetMassDeterminedThermodynamicPressure(lowMachConf.InitialMass.Value, Scalar.Current)); } break; case PhysicsMode.Multiphase: break; default: throw new ApplicationException(); } if (UpdateRhoVisc) { // Density // ======= Rho.Clear(); Rho.ProjectFunction(1.0, EoS.GetDensity, null, Scalar.Current); RhoMatrix.Update(); // Viscosity // ========= Eta.Clear(); Eta.ProjectFunction(1.0, EoS.GetViscosity, null, Scalar.Current); } } }
protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection) { LowMachSIMPLEControl lowMachControl = SolverConf.Control as LowMachSIMPLEControl; return((new Divergence_CentralDifference(SpatialComponent, SolverConf.BcMap, lowMachControl.EoS)).Operator()); }
protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection) { LowMachSIMPLEControl lowMachControl = SolverConf.Control as LowMachSIMPLEControl; return((new LinearizedScalarConvection(SolverConf.SpatialDimension, SolverConf.BcMap, lowMachControl.EoS)).Operator()); }
/// <summary> /// Initialize all variables, which are not /// initialized by the control-file. /// Has to be called after <see cref="Application.SetInitial()"/> /// </summary> public void Initialize(SIMPLEControl SolverConf) { // Set history length according to time order if (SolverConf.Algorithm == SolutionAlgorithms.Unsteady_SIMPLE) { this.Velocity.IncreaseHistoryLength(SolverConf.TimeOrder); } this.VelocityMean.Clear(); this.VelocityMean.AccLaidBack(1.0, this.Velocity.Current); switch (SolverConf.PhysicsMode) { case PhysicsMode.Incompressible: break; case PhysicsMode.LowMach: { LowMachSIMPLEControl lowMachConf = SolverConf as LowMachSIMPLEControl; // Set history length according to time order if (SolverConf.Algorithm == SolutionAlgorithms.Unsteady_SIMPLE) { this.Temperature.IncreaseHistoryLength(SolverConf.TimeOrder); } // Initialize TemperatureMean this.TemperatureMean.Clear(); this.TemperatureMean.AccLaidBack(1.0, this.Temperature.Current); // Initialize ThermodynamicPressure this.ThermodynamicPressure.Current.Clear(); switch (lowMachConf.ThermodynamicPressureMode) { case ThermodynamicPressureMode.Constant: this.ThermodynamicPressure.Current.AccConstant(1.0); break; case ThermodynamicPressureMode.MassDetermined: if (SolverConf.Algorithm == SolutionAlgorithms.Unsteady_SIMPLE) { this.ThermodynamicPressure.IncreaseHistoryLength(SolverConf.TimeOrder); } this.ThermodynamicPressure.Current.AccConstant( lowMachConf.EoS.GetMassDeterminedThermodynamicPressure( lowMachConf.InitialMass.Value, this.Temperature.Current)); break; default: throw new NotImplementedException(); } // Initialize EoS lowMachConf.EoS.Initialize(this.ThermodynamicPressure); // Initialize Density this.Rho.Clear(); this.Rho.ProjectFunction(1.0, lowMachConf.EoS.GetDensity, null, this.Temperature.Current); // Initialize Viscosity this.Eta.Clear(); this.Eta.ProjectFunction(1.0, lowMachConf.EoS.GetViscosity, null, this.Temperature.Current); } break; case PhysicsMode.Multiphase: { MultiphaseSIMPLEControl multiphaseConf = SolverConf as MultiphaseSIMPLEControl; // Set history length according to time order if (SolverConf.Algorithm == SolutionAlgorithms.Unsteady_SIMPLE) { this.Phi.IncreaseHistoryLength(SolverConf.TimeOrder); } // Initialize PhiMean this.PhiMean.Clear(); this.PhiMean.AccLaidBack(1.0, this.Phi.Current); // Initialize Density this.Rho.Clear(); this.Rho.ProjectFunction(1.0, multiphaseConf.EoS.GetDensity, null, this.Phi.Current); // Initialize Viscosity this.Eta.Clear(); this.Eta.ProjectFunction(1.0, multiphaseConf.EoS.GetViscosity, null, this.Phi.Current); } break; default: throw new NotImplementedException(); } }