/// <summary> /// Computes the exact solution of the Riemann problem, samples it at /// <paramref name="x"/> (coordinate normal to discontinuity position) /// at time <paramref name="t"/> /// </summary> /// <param name="meanPressure"></param> /// <param name="meanVelocity"></param> /// <param name="x"></param> /// <param name="t"></param> /// <returns></returns> public StateVector GetState(double meanPressure, double meanVelocity, double x, double t) { double S = x / t; Sample(meanPressure, meanVelocity, S, out densityStar, out normalVelocityStar, out pressureStar); // Return exact solution in conservative variables Vector u; Material material; if (S <= meanVelocity) { // left of the interface u = velocityLeft; material = stateLeft.Material; } else { // right of the interface u = velocityRight; material = stateRight.Material; } u[0] = normalVelocityStar; return(StateVector.FromPrimitiveQuantities( material, densityStar, u.FromEdgeCoordinates(edgeNormal), pressureStar)); }
/// <summary> /// Calculates the boundary value for an isolating slip wall according /// to the first variant described in VegtVen2002. The basic idea is to /// impose \f$ \vec{u} \cdot \vec{n} = 0\f$ (slip wall) by /// setting the edge momentum to /// \f$ \vec{m}^+ = \vec{m}^- - 2((\rho \vec{u})^- \cdot \vec{n})\vec{n}\f$ /// which mimics a mirrored flow at the other side of the wall. /// </summary> /// <param name="time"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="stateIn"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <returns> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </returns> public override StateVector GetBoundaryState(double time, double[] x, double[] normal, StateVector stateIn) { Vector3D normalVector = GetNormalVector(normal); StateVector stateOut; if (WallVelocities == null) { // VegtVen2002, page 14, second equation Vector3D mOut = stateIn.Momentum - 2.0 * (stateIn.Momentum * normalVector) * normalVector; stateOut = new StateVector(stateIn.Material, stateIn.Density, mOut, stateIn.Energy); } else { Vector3D uWall = new Vector3D(); for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++) { uWall[d] = WallVelocities[d](x, time); } Vector3D uOut = stateIn.Velocity - 2.0 * ((stateIn.Velocity - uWall) * normalVector) * normalVector; stateOut = StateVector.FromPrimitiveQuantities( stateIn.Material, stateIn.Density, uOut, stateIn.Pressure); } return(stateOut); }
/// <summary> /// Calculates the boundary value for an isolating slip wall according /// to the first variant described in VegtVen2002. The basic idea is to /// impose \f$ \vec{u} \cdot \vec{n} = 0\f$ (slip wall) by /// setting the edge momentum to /// \f$ \vec{m}^+ = \vec{m}^- - 2((\rho \vec{u})^- \cdot \vec{n})\vec{n}\f$ /// which mimics a mirrored flow at the other side of the wall. /// </summary> /// <param name="time"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="stateIn"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <returns> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </returns> public override StateVector GetBoundaryState(double time, double[] x, double[] normal, StateVector stateIn) { Vector normalVector = GetNormalVector(normal); Debug.Assert(normal.Length == stateIn.Dimension); int D = normal.Length; StateVector stateOut; if (WallVelocities == null) { // VegtVen2002, page 14, second equation Vector mOut = stateIn.Momentum - 2.0 * (stateIn.Momentum * normalVector) * normalVector; stateOut = new StateVector(stateIn.Material, stateIn.Density, mOut, stateIn.Energy); } else { Vector uWall = new Vector(D); for (int d = 0; d < D; d++) { uWall[d] = WallVelocities[d](x, time); } Vector uOut = stateIn.Velocity - 2.0 * ((stateIn.Velocity - uWall) * normalVector) * normalVector; stateOut = StateVector.FromPrimitiveQuantities( stateIn.Material, stateIn.Density, uOut, stateIn.Pressure); } return(stateOut); }
/// <summary> /// Calculates the boundary values for a subsonic outlet (Mach number /// smaller than 1). We have to impose one condition (here, we choose /// the pressure <see cref="pressureFunction"/>) and extrapolate the /// other values following FerzigerPeric2001 (p. 315ff) /// </summary> /// <param name="time"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="stateIn"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <returns> /// \f$ /// (\rho^-, u^-, p^*)^T /// \f$ /// </returns> public override StateVector GetBoundaryState(double time, double[] x, double[] normal, StateVector stateIn) { return(StateVector.FromPrimitiveQuantities( stateIn.Material, stateIn.Density, stateIn.Velocity, pressureFunction(x, time))); }
/// <summary> /// Calculates the boundary values for a subsonic inlet (Mach number /// smaller than 1). Theoretically, we have to impose four conditions /// (in the inviscid as well as in the viscid case!) which is why we /// extrapolate the fifth value (in this case: the energy) to the /// boundary. /// </summary> /// <param name="time"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="stateIn"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <returns> /// \f$ (\rho^*, \vec{u}^*, p^-)^T\f$ /// </returns> public override StateVector GetBoundaryState(double time, double[] x, double[] normal, StateVector stateIn) { double rhoOut = densityFunction(x, time); Vector3D uOut = new Vector3D(); for (int i = 0; i < CNSEnvironment.NumberOfDimensions; i++) { uOut[i] = velocityFunctions[i](x, time); } return(StateVector.FromPrimitiveQuantities(stateIn.Material, rhoOut, uOut, stateIn.Pressure)); }
/// <summary> /// Calculates the boundary values for a subsonic inlet (Mach number /// smaller than 1). Theoretically, we have to impose four conditions /// (in the inviscid as well as in the viscid case!) which is why we /// extrapolate the fifth value (in this case: the energy) to the /// boundary. /// </summary> /// <param name="time"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="stateIn"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <returns> /// \f$ (\rho^*, \vec{u}^*, p^-)^T\f$ /// </returns> public override StateVector GetBoundaryState(double time, double[] x, double[] normal, StateVector stateIn) { double rhoOut = densityFunction(x, time); Debug.Assert(x.Length == stateIn.Dimension); int D = x.Length; Vector uOut = new Vector(stateIn.Dimension); for (int i = 0; i < D; i++) { uOut[i] = velocityFunctions[i](x, time); } return(StateVector.FromPrimitiveQuantities(stateIn.Material, rhoOut, uOut, stateIn.Pressure)); }
//private static int count = 0; //private static StreamWriter writer; /// <summary> /// Calculates the boundary value for an isolating slip wall according /// to the first variant described in VegtVen2002. The basic idea is to /// impose \f$ \vec{u} \cdot \vec{n} = 0\f$ (slip wall) by /// setting the edge momentum to /// \f$ \vec{m}^+ = \vec{m}^- - 2((\rho \vec{u})^- \cdot \vec{n})\vec{n}\f$ /// which mimics a mirrored flow at the other side of the wall. /// </summary> public override StateVector GetBoundaryState(double time, Vector x, Vector normal, StateVector stateIn) { //Convection.OptimizedHLLCFlux.AdiabaticSlipWall.Start(); Vector normalVector = normal; Debug.Assert(normal.Dim == stateIn.Dimension); int D = normal.Dim; StateVector stateOut; if (WallVelocities == null) { // VegtVen2002, page 14, second equation ilPSP.Vector mOut = stateIn.Momentum - 2.0 * (stateIn.Momentum * normalVector) * normalVector; stateOut = new StateVector(stateIn.Material, stateIn.Density, mOut, stateIn.Energy); } else { ilPSP.Vector uWall = new ilPSP.Vector(D); for (int d = 0; d < D; d++) { uWall[d] = WallVelocities[d](x, time); } ilPSP.Vector uOut = stateIn.Velocity - 2.0 * ((stateIn.Velocity - uWall) * normalVector) * normalVector; stateOut = StateVector.FromPrimitiveQuantities( stateIn.Material, stateIn.Density, uOut, stateIn.Pressure); } //Console.WriteLine(String.Format("{0}: \t x = ({1:0.0000}, {2:0.0000}) \t stateOut = ({3:0.0000}, {4:0.0000}, {5:0.0000}, {6:0.0000}) \t normal = ({7:0.0000}, {8:0.0000})", count, x.x, x.y, stateOut.Density, stateOut.Momentum.x, stateOut.Momentum.y, stateOut.Energy, normal.x, normal.y)); //count++; //// StreamWriter //if (writer == null) { // writer = new StreamWriter("QuadraturePoints.txt"); //} //string resultLine; //resultLine = x.x + "\t" + x.y + "\t" + stateOut.Density + "\t" + stateOut.Momentum.x + "\t" + stateOut.Momentum.y + "\t" + stateOut.Energy + "\t" + normal.x + "\t" + normal.y; //writer.WriteLine(resultLine); //writer.Flush(); //Convection.OptimizedHLLCFlux.AdiabaticSlipWall.Stop(); return(stateOut); }
/// <summary> /// Calculates the state at the boundary from the prescribed stagnation /// pressure and the prescribed stagnation temperature. The calculation /// follows FerzigerPeric2001 (p. 315ff). The flow is prescribed to be /// normal to the edge. /// </summary> /// <param name="time"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="x"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="normal"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <param name="stateIn"> /// <see cref="BoundaryCondition.GetBoundaryState"/> /// </param> /// <returns> /// \f$ /// T^+ = T_t(x) \frac{p_t(x)}{p^-}^{\frac{1.0 - \gamma}{\gamma}} /// \f$ /// \f$ /// |\vec{u^+}| = \sqrt{\frac{2 T^+}{(\gamma - 1) \mathrm{Ma}_\infty^2} \left(\frac{T_t(x)}{T^+} -1\right)} /// \f$ /// \f$ \rho^+ = \frac{p^- }{T^+}\f$ /// \f$ /// (\rho^+, -\rho^+ |\vec{u^+}| \vec{n}, \frac{p}{\kappa - 1} + \frac{rho^+ |\vec{u^+}|^2}{2})^T /// \f$ /// </returns> public override StateVector GetBoundaryState(double time, double[] x, double[] normal, StateVector stateIn) { double gamma = config.EquationOfState.HeatCapacityRatio; double Mach = config.MachNumber; Vector3D inwardNormal = new Vector3D(); for (int i = 0; i < normal.Length; i++) { inwardNormal[i] = -normal[i]; } double p0 = TotalPressureFunction(x, time); double T0 = TotalTemperatureFunction(x, time); double p = stateIn.Pressure; double T = TotalTemperatureFunction(x, time) * Math.Pow(p0 / p, (1.0 - gamma) / gamma); double rho = p / T; double VelocitySquare = 2.0 * T / ((gamma - 1.0) * (Mach * Mach)) * (T0 / T - 1.0); Vector3D velocityOut = Math.Sqrt(VelocitySquare) * inwardNormal; return(StateVector.FromPrimitiveQuantities(stateIn.Material, rho, velocityOut, p)); }
/// <summary> /// Calculates the boundary values for a supersonic inlet (Mach number /// greater than 1). Theoretically, we have to impose five conditions /// (in the inviscid as well as in the viscid case!) which is why /// calculate the complete state from the given density, momentum and /// pressure /// </summary> /// <returns> /// \f$ (\rho^*, u_0^*[, u_1^*[, u_2^*]], p*)^T\f$ /// </returns> public override StateVector GetBoundaryState(double time, Vector x, Vector normal, StateVector stateIn) { //Convection.OptimizedHLLCFlux.SupersonicInlet.Start(); Debug.Assert(x.Dim == stateIn.Dimension); int D = x.Dim; Vector uOut = new Vector(D); for (int i = 0; i < D; i++) { uOut[i] = VelocityFunctions[i](x, time); } StateVector retval = StateVector.FromPrimitiveQuantities( stateIn.Material, DensityFunction(x, time), uOut, PressureFunction(x, time)); //Convection.OptimizedHLLCFlux.SupersonicInlet.Stop(); return(retval); }
/// <summary> /// Template for all shock tube tests /// </summary> /// <param name="convectiveFlux"></param> /// <param name="densityLeft"></param> /// <param name="velocityLeft"></param> /// <param name="pressureLeft"></param> /// <param name="densityRight"></param> /// <param name="velocityRight"></param> /// <param name="pressureRight"></param> /// <param name="discontinuityPosition"></param> /// <returns></returns> private static CNSControl GetShockTubeControlTemplate(ConvectiveFluxTypes convectiveFlux, double densityLeft, double velocityLeft, double pressureLeft, double densityRight, double velocityRight, double pressureRight, double discontinuityPosition) { CNSControl c = new CNSControl(); c.DbPath = null; c.savetodb = false; c.ActiveOperators = Operators.Convection; c.ConvectiveFluxType = convectiveFlux; c.EquationOfState = IdealGas.Air; c.MachNumber = 1.0 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio); c.ExplicitScheme = ExplicitSchemes.RungeKutta; c.ExplicitOrder = 1; int dgDegree = 0; c.AddVariable(Variables.Density, dgDegree); c.AddVariable(Variables.Momentum.xComponent, dgDegree); c.AddVariable(Variables.Energy, dgDegree); c.AddVariable(Variables.Pressure, dgDegree); c.AddVariable(Variables.Velocity.xComponent, dgDegree); c.GridFunc = delegate { double[] xNodes = GenericBlas.Linspace(0.0, 1.0, 201); var grid = Grid1D.LineGrid(xNodes, false); grid.EdgeTagNames.Add(1, "supersonicOutlet"); grid.DefineEdgeTags(X => 1); return(grid); }; // Take inner values everywhere c.AddBoundaryCondition("supersonicOutlet"); Material material = new Material(c); StateVector stateLeft = StateVector.FromPrimitiveQuantities( material, densityLeft, new Vector3D(velocityLeft, 0.0, 0.0), pressureLeft); StateVector stateRight = StateVector.FromPrimitiveQuantities( material, densityRight, new Vector3D(velocityRight, 0.0, 0.0), pressureRight); c.InitialValues_Evaluators.Add( Variables.Density, X => stateLeft.Density + (stateRight.Density - stateLeft.Density) * (X[0] - discontinuityPosition).Heaviside()); c.InitialValues_Evaluators.Add( Variables.Velocity.xComponent, X => stateLeft.Velocity.x + (stateRight.Velocity.x - stateLeft.Velocity.x) * (X[0] - discontinuityPosition).Heaviside()); c.InitialValues_Evaluators.Add( Variables.Pressure, X => stateLeft.Pressure + (stateRight.Pressure - stateLeft.Pressure) * (X[0] - discontinuityPosition).Heaviside()); var riemannSolver = new ExactRiemannSolver(stateLeft, stateRight, new Vector3D(1.0, 0.0, 0.0)); double pStar, uStar; riemannSolver.GetStarRegionValues(out pStar, out uStar); c.Queries.Add("L2ErrorDensity", QueryLibrary.L2Error( Variables.Density, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Density)); c.Queries.Add("L2ErrorVelocity", QueryLibrary.L2Error( Variables.Velocity.xComponent, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Velocity.x)); c.Queries.Add("L2ErrorPressure", QueryLibrary.L2Error( Variables.Pressure, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Pressure)); c.dtMin = 0.0; c.dtMax = 1.0; c.CFLFraction = 0.5; c.NoOfTimesteps = int.MaxValue; c.PrintInterval = 50; return(c); }
private static CNSControl ShockTubeToro1Template(int dgDegree, ExplicitSchemes explicitScheme, int explicitOrder, int noOfCells = 50, double gridStretching = 0.0, bool twoD = false) { double densityLeft = 1.0; double velocityLeft = 0.0; double pressureLeft = 1.0; double densityRight = 0.125; double velocityRight = 0.0; double pressureRight = 0.1; double discontinuityPosition = 0.5; CNSControl c = new CNSControl(); c.DbPath = null; //c.DbPath = @"c:\bosss_db\"; c.savetodb = false; c.ActiveOperators = Operators.Convection; c.ConvectiveFluxType = ConvectiveFluxTypes.OptimizedHLLC; c.EquationOfState = IdealGas.Air; c.MachNumber = 1.0 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio); c.ReynoldsNumber = 1.0; c.PrandtlNumber = 0.71; c.ExplicitScheme = explicitScheme; c.ExplicitOrder = explicitOrder; c.AddVariable(CompressibleVariables.Density, dgDegree); c.AddVariable(CompressibleVariables.Momentum.xComponent, dgDegree); c.AddVariable(CompressibleVariables.Energy, dgDegree); c.AddVariable(CNSVariables.Velocity.xComponent, dgDegree); c.AddVariable(CNSVariables.Pressure, dgDegree); c.AddVariable(CNSVariables.Rank, 0); c.GridFunc = delegate { double xMin = 0.0; double xMax = 1.0; double yMin = 0.0; double yMax = 1.0; double[] xNodes; double[] yNodes; if (gridStretching > 0.0) { xNodes = Grid1D.TanhSpacing(xMin, xMax, noOfCells + 1, gridStretching, true); yNodes = Grid1D.TanhSpacing(yMin, yMax, 1 + 1, gridStretching, true); } else { xNodes = GenericBlas.Linspace(xMin, xMax, noOfCells + 1); yNodes = GenericBlas.Linspace(yMin, yMax, 1 + 1); } GridCommons grid; if (twoD) { grid = Grid2D.Cartesian2DGrid(xNodes, yNodes, periodicX: false, periodicY: false); } else { grid = Grid1D.LineGrid(xNodes, periodic: false); } // Boundary conditions grid.EdgeTagNames.Add(1, "AdiabaticSlipWall"); grid.DefineEdgeTags(delegate(double[] _X) { return(1); }); return(grid); }; c.AddBoundaryValue("AdiabaticSlipWall"); Material material = c.GetMaterial(); StateVector stateLeft = StateVector.FromPrimitiveQuantities( material, densityLeft, new Vector(velocityLeft, 0.0, 0.0), pressureLeft); StateVector stateRight = StateVector.FromPrimitiveQuantities( material, densityRight, new Vector(velocityRight, 0.0, 0.0), pressureRight); c.InitialValues_Evaluators.Add( CompressibleVariables.Density, X => stateLeft.Density + (stateRight.Density - stateLeft.Density) * (X[0] - discontinuityPosition).Heaviside()); c.InitialValues_Evaluators.Add( CNSVariables.Velocity.xComponent, X => stateLeft.Velocity.x + (stateRight.Velocity.x - stateLeft.Velocity.x) * (X[0] - discontinuityPosition).Heaviside()); c.InitialValues_Evaluators.Add( CNSVariables.Pressure, X => stateLeft.Pressure + (stateRight.Pressure - stateLeft.Pressure) * (X[0] - discontinuityPosition).Heaviside()); if (twoD) { c.InitialValues_Evaluators.Add(CNSVariables.Velocity.yComponent, X => 0); } if (!twoD) { var riemannSolver = new ExactRiemannSolver(stateLeft, stateRight, new Vector(1.0, 0.0, 0.0)); riemannSolver.GetStarRegionValues(out double pStar, out double uStar); c.Queries.Add("L2ErrorDensity", QueryLibrary.L2Error( CompressibleVariables.Density, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Density)); c.Queries.Add("L2ErrorVelocity", QueryLibrary.L2Error( CNSVariables.Velocity.xComponent, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Velocity.x)); c.Queries.Add("L2ErrorPressure", QueryLibrary.L2Error( CNSVariables.Pressure, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Pressure)); } c.dtMin = 0.0; c.dtMax = 1.0; //c.dtFixed = 1.0e-6; c.CFLFraction = 0.1; c.Endtime = 0.2; c.NoOfTimesteps = int.MaxValue; // Use METIS since ParMETIS is not installed on build server c.GridPartType = GridPartType.METIS; return(c); }
/// <summary> /// Template of the control file for all shock tube tests using artificial viscosity /// </summary> /// <param name="convectiveFlux"></param> /// <param name="densityLeft"></param> /// <param name="velocityLeft"></param> /// <param name="pressureLeft"></param> /// <param name="densityRight"></param> /// <param name="velocityRight"></param> /// <param name="pressureRight"></param> /// <param name="discontinuityPosition"></param> /// <param name="explicitScheme"></param> /// <param name="explicitOrder"></param> /// <param name="numOfClusters"></param> /// <returns></returns> private static CNSControl GetArtificialViscosityShockTubeControlTemplate(ConvectiveFluxTypes convectiveFlux, double densityLeft, double velocityLeft, double pressureLeft, double densityRight, double velocityRight, double pressureRight, double discontinuityPosition, ExplicitSchemes explicitScheme, int explicitOrder, int numOfClusters) { CNSControl c = new CNSControl(); c.DbPath = null; c.savetodb = false; //c.DbPath = @"c:\bosss_db\"; //c.savetodb = true; //c.saveperiod = 100; //c.PrintInterval = 100; c.ActiveOperators = Operators.Convection | Operators.ArtificialViscosity; c.ConvectiveFluxType = convectiveFlux; c.EquationOfState = IdealGas.Air; c.MachNumber = 1.0 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio); c.ReynoldsNumber = 1.0; c.PrandtlNumber = 0.71; // Time stepping scheme c.ExplicitScheme = explicitScheme; c.ExplicitOrder = explicitOrder; if (explicitScheme == ExplicitSchemes.LTS) { c.NumberOfSubGrids = numOfClusters; c.ReclusteringInterval = 1; c.FluxCorrection = false; } int dgDegree = 3; int noOfCellsPerDirection = 50; double sensorLimit = 1e-4; double epsilon0 = 1.0; double kappa = 0.5; Variable sensorVariable = Variables.Density; c.ShockSensor = new PerssonSensor(sensorVariable, sensorLimit); c.ArtificialViscosityLaw = new SmoothedHeavisideArtificialViscosityLaw(c.ShockSensor, dgDegree, sensorLimit, epsilon0, kappa); c.AddVariable(Variables.Density, dgDegree); c.AddVariable(Variables.Momentum.xComponent, dgDegree); c.AddVariable(Variables.Energy, dgDegree); c.AddVariable(Variables.Velocity.xComponent, dgDegree); c.AddVariable(Variables.Pressure, dgDegree); c.AddVariable(Variables.Entropy, dgDegree); c.AddVariable(Variables.Viscosity, dgDegree); c.AddVariable(Variables.ArtificialViscosity, 1); //c.AddVariable(Variables.Sensor, dgDegree); c.AddVariable(Variables.LocalMachNumber, dgDegree); if (c.ExplicitScheme.Equals(ExplicitSchemes.LTS)) { c.AddVariable(Variables.LTSClusters, 0); } c.GridFunc = delegate { double[] xNodes = GenericBlas.Linspace(0.0, 1.0, noOfCellsPerDirection + 1); var grid = Grid1D.LineGrid(xNodes, periodic: false); // Boundary conditions grid.EdgeTagNames.Add(1, "AdiabaticSlipWall"); grid.DefineEdgeTags(delegate(double[] _X) { return(1); }); return(grid); }; c.AddBoundaryCondition("AdiabaticSlipWall"); Material material = new Material(c); StateVector stateLeft = StateVector.FromPrimitiveQuantities( material, densityLeft, new Vector3D(velocityLeft, 0.0, 0.0), pressureLeft); StateVector stateRight = StateVector.FromPrimitiveQuantities( material, densityRight, new Vector3D(velocityRight, 0.0, 0.0), pressureRight); c.InitialValues_Evaluators.Add( Variables.Density, X => stateLeft.Density + (stateRight.Density - stateLeft.Density) * (X[0] - discontinuityPosition).Heaviside()); c.InitialValues_Evaluators.Add( Variables.Velocity.xComponent, X => stateLeft.Velocity.x + (stateRight.Velocity.x - stateLeft.Velocity.x) * (X[0] - discontinuityPosition).Heaviside()); c.InitialValues_Evaluators.Add( Variables.Pressure, X => stateLeft.Pressure + (stateRight.Pressure - stateLeft.Pressure) * (X[0] - discontinuityPosition).Heaviside()); var riemannSolver = new ExactRiemannSolver(stateLeft, stateRight, new Vector3D(1.0, 0.0, 0.0)); double pStar, uStar; riemannSolver.GetStarRegionValues(out pStar, out uStar); c.Queries.Add("L2ErrorDensity", QueryLibrary.L2Error( Variables.Density, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Density)); c.Queries.Add("L2ErrorVelocity", QueryLibrary.L2Error( Variables.Velocity.xComponent, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Velocity.x)); c.Queries.Add("L2ErrorPressure", QueryLibrary.L2Error( Variables.Pressure, (X, t) => riemannSolver.GetState(pStar, uStar, X[0] - discontinuityPosition, t).Pressure)); c.dtMin = 0.0; c.dtMax = 1.0; c.dtFixed = 1.0e-6; c.Endtime = 5e-04; //c.NoOfTimesteps = 500; c.NoOfTimesteps = int.MaxValue; return(c); }
/// <summary> /// Vectorized implementation of <see cref="GetBoundaryState(double, Vector, Vector, StateVector)"/> /// </summary> public override void GetBoundaryState(MultidimensionalArray[] StateOut, double time, MultidimensionalArray X, MultidimensionalArray Normals, MultidimensionalArray[] StateIn, int Offset, int NoOfEdges, bool normalFlipped, Material material) { //Convection.OptimizedHLLCFlux.SupersonicInlet.Start(); if (X.Dimension != 3) { throw new ArgumentException(); } int D = X.GetLength(2); int NoOfNodes = X.GetLength(1); if (StateIn.Length != D + 2) { throw new ArgumentException(); } if (StateOut.Length != D + 2) { throw new ArgumentException(); } bool is3D = D >= 3; if (D < 2) { // base-implementation supports also 1D; // The implementation here is (a bit) tuned for performance, we only support 2D and 3D; // in 1D, performance is not so relevant anyway. base.GetBoundaryState(StateOut, time, X, Normals, StateIn, Offset, NoOfEdges, normalFlipped, material); return; } var Density = StateOut[0]; var Energy = StateOut[D + 1]; var MomentumX = StateOut[1]; var MomentumY = StateOut[2]; var MomentumZ = is3D ? StateOut[3] : null; var DensityIn = StateIn[0]; //var EnergyIn = StateIn[D + 1]; //var MomentumXin = StateIn[1]; //var MomentumYin = StateIn[2]; //var MomentumZin = is3D ? StateIn[3] : null; double MachScaling = material.EquationOfState.HeatCapacityRatio * material.MachNumber * material.MachNumber; double[] xLocal = new double[D]; //Vector uOut = new Vector(D); for (int e = 0; e < NoOfEdges; e++) { int edge = e + Offset; // Loop over nodes for (int n = 0; n < NoOfNodes; n++) { xLocal[0] = X[edge, n, 0]; xLocal[1] = X[edge, n, 1]; double uOut_x = VelocityFunctions[0](xLocal, time); double uOut_y = VelocityFunctions[1](xLocal, time); double uOut_z = 0.0; double velocity_AbsSquare = uOut_x * uOut_x + uOut_y * uOut_y; if (is3D) { xLocal[2] = X[edge, n, 2]; uOut_z = VelocityFunctions[2](xLocal, time); velocity_AbsSquare += uOut_z * uOut_z; } #if DEBUG var uOutVec = new Vector(D); uOutVec.x = uOut_x; uOutVec.y = uOut_y; uOutVec.z = uOut_z; StateVector stateBoundary = StateVector.FromPrimitiveQuantities( material, DensityFunction(xLocal, time), uOutVec, PressureFunction(xLocal, time)); #endif double density = DensityFunction(xLocal, time); double pressure = PressureFunction(xLocal, time); Density[edge, n] = density; MomentumX[edge, n] = uOut_x * density; MomentumY[edge, n] = uOut_y * density; if (is3D) { MomentumZ[edge, n] = uOut_z * density; } Energy[edge, n] = material.EquationOfState.GetInnerEnergy(density, pressure) + 0.5 * MachScaling * density * velocity_AbsSquare; #if DEBUG Debug.Assert(Density[edge, n].RelErrorSmallerEps(stateBoundary.Density), "density error"); for (int d = 0; d < D; d++) { Debug.Assert(StateOut[d + 1][edge, n].RelErrorSmallerEps(stateBoundary.Momentum[d]), "momentum error"); } Debug.Assert(Energy[edge, n].RelErrorSmallerEps(stateBoundary.Energy), "energy error"); #endif } } //Convection.OptimizedHLLCFlux.SupersonicInlet.Stop(); }
protected override void SetInitial() { int D = CompressibleEnvironment.NumberOfDimensions; CellQuadratureScheme scheme = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData)); // Level set this.LevelSet.ProjectField(1.0, this.Control.LevelSetPos, scheme); this.LevelSetTracker.UpdateTracker(); if (this.Control.uAInitPrimitive != null && this.Control.uBInitPrimitive != null) { // Initial conditions are specified in primitive variables // Density this.Density.Clear(); this.Density.GetSpeciesShadowField("A").ProjectField(1.0, this.Control.uAInitPrimitive[0]); this.Density.GetSpeciesShadowField("B").ProjectField(1.0, this.Control.uBInitPrimitive[0]); // Momentum (rho * momentum vector) for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { this.Momentum[d].Clear(); this.Momentum[d].GetSpeciesShadowField("A").ProjectField(1.0, X => this.Control.uAInitPrimitive[0](X) * this.Control.uAInitPrimitive[d + 1](X), scheme); this.Momentum[d].GetSpeciesShadowField("B").ProjectField(1.0, X => this.Control.uBInitPrimitive[0](X) * this.Control.uBInitPrimitive[d + 1](X), scheme); } // Energy this.Energy.Clear(); Energy.GetSpeciesShadowField("A").ProjectField( 1.0, delegate(double[] X) { double rho = this.Control.uAInitPrimitive[0](X); double p = this.Control.uAInitPrimitive[D + 1](X); Vector u = new Vector(D); for (int d = 0; d < D; d++) { u[d] = this.Control.uAInitPrimitive[d + 1](X); } StateVector state = StateVector.FromPrimitiveQuantities(this.Control.GetMaterial(), rho, u, p); return(state.Energy); }, scheme); Energy.GetSpeciesShadowField("B").ProjectField( 1.0, delegate(double[] X) { double rho = this.Control.uBInitPrimitive[0](X); double p = this.Control.uBInitPrimitive[D + 1](X); Vector u = new Vector(D); for (int d = 0; d < D; d++) { u[d] = this.Control.uBInitPrimitive[d + 1](X); } StateVector state = StateVector.FromPrimitiveQuantities(this.Control.GetMaterial(), rho, u, p); return(state.Energy); }, scheme); } else { // Initial conditions are specified in conservative variables // Density this.Density.Clear(); this.Density.GetSpeciesShadowField("A").ProjectField(1.0, this.Control.uAInitConservative[0]); this.Density.GetSpeciesShadowField("B").ProjectField(1.0, this.Control.uBInitConservative[0]); // Momentum for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { this.Momentum[d].Clear(); this.Momentum[d].GetSpeciesShadowField("A").ProjectField(1.0, this.Control.uAInitConservative[d + 1]); this.Momentum[d].GetSpeciesShadowField("B").ProjectField(1.0, this.Control.uBInitConservative[d + 1]); } // Energy this.Energy.Clear(); this.Energy.GetSpeciesShadowField("A").ProjectField(1.0, this.Control.uAInitConservative[D + 1]); this.Energy.GetSpeciesShadowField("B").ProjectField(1.0, this.Control.uBInitConservative[D + 1]); } // Update sensor values this.Sensor?.UpdateSensorValues(this.Density); // Update artificial viscosity if (this.ArtificialViscosityField != null) { UpdateArtificialViscosity(); } }