/// <summary> /// The non-linear equation F=0 to be solved /// </summary> /// <param name="density"></param> /// <param name="r"></param> /// <param name="eos"></param> /// <param name="c1"></param> /// <returns></returns> private static double F(double density, double r, CovolumeGas eos, double c1) { double gamma = eos.HeatCapacityRatio; double covolume = eos.Covolume; return((gamma - covolume * density) / (gamma - 1.0) / density * Math.Pow(density / (1.0 - covolume * density), gamma) - c1 + 0.5 * Math.Exp(1.0 - r * r)); }
/// <summary> /// Computes the density from a non-linear equation using a simple /// bisection method /// </summary> /// <param name="r"></param> /// <param name="eos"></param> /// <param name="c1"></param> /// <returns></returns> private static double GetDensity(double r, CovolumeGas eos, double c1) { double gamma = eos.HeatCapacityRatio; double covolume = eos.Covolume; double densityLeft = 0.0 + 1e-14; double densityRight = 1.0 / covolume - 1e-14; double fOld = double.PositiveInfinity; int maxIterations = 1000; double density = double.NaN; double f = double.NaN; int n = 0; while (true) { if (n >= maxIterations) { throw new Exception("No convergence"); } density = 0.5 * (densityRight + densityLeft); f = F(density, r, eos, c1); if (Math.Abs(fOld - f) < 1e-13) { break; } else if (f > 0.0) { densityRight = density; } else { densityLeft = density; } fOld = f; n++; } return(density); }
/// <summary> /// Computes the solution at (x, t). /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="u"></param> /// <param name="t"></param> /// <param name="c"></param> /// <param name="c1"></param> /// <returns></returns> public static StateVector GetSolution(double x, double y, double u, double t, CNSControl c, double c1) { double xBar = x - u * t; double r = Math.Sqrt(xBar * xBar + y * y); double theta = Math.Atan2(y, xBar); CovolumeGas eos = c.EquationOfState as CovolumeGas; double gamma = eos.HeatCapacityRatio; double covolume = eos.Covolume; double rho = GetDensity(r, eos, c1); double p = Math.Pow(rho / (1 - covolume * rho), gamma); double normU = r * Math.Exp(0.5 * (1.0 - r * r)); Vector3D U = new Vector3D( u - Math.Sin(theta) * normU, Math.Cos(theta) * normU, 0.0); return(new StateVector( new Material(c), rho, rho * U, p * (1.0 - covolume * rho) / (gamma - 1.0) + 0.5 * rho * U * U)); }
/// <summary> /// Test case using <see cref="CovolumeGas"/> in combination with the /// <see cref="RusanovFlux"/>. /// </summary> /// <returns></returns> public static VortexControl IsentropicVortexCovolumeGasRusanov() { VortexControl c = Template(1, 2); CovolumeGas eos = new CovolumeGas(1.4, 0.1); double integrationConstant = 3.6; c.EquationOfState = eos; c.ConvectiveFluxType = ConvectiveFluxTypes.Rusanov; Func <double[], double, StateVector> solution = (X, t) => CovolumeVortexExactSolution.GetSolution(X[0], X[1], c.VortexSpeed, t, c, integrationConstant); c.InitialValues_Evaluators.Add(Variables.Density, X => solution(X, 0.0).Density); c.InitialValues_Evaluators.Add(Variables.Velocity.xComponent, X => solution(X, 0.0).Velocity[0]); c.InitialValues_Evaluators.Add(Variables.Velocity.yComponent, X => solution(X, 0.0).Velocity[1]); c.InitialValues_Evaluators.Add(Variables.Pressure, X => solution(X, 0.0).Pressure); c.Queries.Add("L2ErrorDensity", QueryLibrary.L2Error(Variables.Density, (X, t) => solution(X, t).Density, 10)); c.Queries.Add("L2ErrorPressure", QueryLibrary.L2Error(Variables.Pressure, (X, t) => solution(X, t).Pressure, 10)); c.Queries.Add("L2ErrorEntropy", QueryLibrary.L2Error(Variables.Entropy, (X, t) => 1.0, 10)); return(c); }