/// <summary>
 /// the predefined, div-free flow field
 /// </summary>
 ilPSP.Vector FlowField(double[] x, double[] Uin, double[] Uot)
 {
     ilPSP.Vector u = new ilPSP.Vector(2);
     u.x = 0.5 * (Uin[1] + Uot[1]);
     u.y = 0.5 * (Uin[2] + Uot[2]);
     return(u);
 }
 /// <summary>
 /// <see cref="IEulerEquationComponent"/>
 /// </summary>
 /// <param name="momentumComponent">
 /// The index of the component of the momentum vector (0, 1 or 2)
 /// represented by a specific instance
 /// </param>
 /// <param name="heatCapacityRatio">
 /// The heat capacity ratio of the material
 /// </param>
 /// <param name="MachNumber">
 /// The reference Mach number
 /// </param>
 /// <param name="Dim">
 /// Spatial dimension
 /// </param>
 public EulerMomentumComponent(int momentumComponent, double heatCapacityRatio, double MachNumber, int Dim)
 {
     this.MomentumComponent = momentumComponent;
     ComponentVector        = ilPSP.Vector.StdBasis(momentumComponent, Dim);
     this.heatCapacityRatio = heatCapacityRatio;
     this.MachNumber        = MachNumber;
 }
Beispiel #3
0
        /// <summary>
        /// Returns scalar dependent dynamic viscosity.
        /// Implements <see cref="BoSSS.Foundation.Func"/>.
        /// </summary>
        /// <param name="X">Not used.</param>
        /// <param name="phi">scalar</param>
        /// <param name="jCell">Not used.</param>
        /// <returns>Dynamic viscosity</returns>
        public double GetViscosity(ilPSP.Vector X, double[] phi, int jCell)
        {
            if (phi.Length != 1)
            {
                throw new ArgumentException();
            }

            return(this.GetViscosity(phi[0]));
        }
        /// <summary>
        /// Constructor for the multiphase case, initializes values
        /// </summary>
        /// <param name="stateLeft">
        /// State left of the discontinuity
        /// </param>
        /// <param name="stateRight">
        /// State right of the discontinuity
        /// </param>
        /// <param name="edgeNormal">
        /// The normal vector of the edge between the 'left' and the 'right'
        /// state (pointing from 'left' to 'right').
        /// </param>
        public ExactRiemannSolver(StateVector stateLeft, StateVector stateRight, ilPSP.Vector edgeNormal)
        {
            IdealGas gasLeft  = stateLeft.Material.EquationOfState as IdealGas;
            IdealGas gasRight = stateRight.Material.EquationOfState as IdealGas;

            if (gasLeft == null || gasRight == null)
            {
                throw new ArgumentException(
                          "Exact Riemann solver only implemented for ideal gases");
            }

            this.edgeNormal    = edgeNormal;
            this.stateLeft     = stateLeft;
            this.stateRight    = stateRight;
            this.kappaLeft     = gasLeft.HeatCapacityRatio;
            this.kappaRight    = gasRight.HeatCapacityRatio;
            this.densityLeft   = stateLeft.Density;
            this.pressureLeft  = stateLeft.Pressure;
            this.densityRight  = stateRight.Density;
            this.pressureRight = stateRight.Pressure;

            velocityLeft             = stateLeft.Velocity.ToEdgeCoordinates(edgeNormal);
            velocityRight            = stateRight.Velocity.ToEdgeCoordinates(edgeNormal);
            this.normalVelocityLeft  = velocityLeft[0];
            this.normalVelocityRight = velocityRight[0];

            speedOfSoundLeft  = Math.Sqrt(kappaLeft * pressureLeft / densityLeft);
            speedOfSoundRight = Math.Sqrt(kappaRight * pressureRight / densityRight);

            // left side
            G1L = (kappaLeft - 1.0) / (2.0 * kappaLeft);
            G2L = (kappaLeft + 1.0) / (2.0 * kappaLeft);
            G3L = 2.0 * kappaLeft / (kappaLeft - 1.0);
            G4L = 2.0 / (kappaLeft - 1.0);
            G5L = 2.0 / (kappaLeft + 1.0);
            G6L = (kappaLeft - 1.0) / (kappaLeft + 1.0);
            G7L = (kappaLeft - 1.0) / 2.0;
            G8L = kappaLeft - 1.0;

            // right side
            G1R = (kappaRight - 1.0) / (2.0 * kappaRight);
            G2R = (kappaRight + 1.0) / (2.0 * kappaRight);
            G3R = 2.0 * kappaRight / (kappaRight - 1.0);
            G4R = 2.0 / (kappaRight - 1.0);
            G5R = 2.0 / (kappaRight + 1.0);
            G6R = (kappaRight - 1.0) / (kappaRight + 1.0);
            G7R = (kappaRight - 1.0) / 2.0;
            G8R = kappaRight - 1.0;

            // the pressure positivity condition is tested for
            if (G4L * (speedOfSoundLeft + speedOfSoundRight) <= (normalVelocityRight - normalVelocityLeft))
            {
                throw new ArgumentOutOfRangeException("the initial data is such that vacuum is generated");
            }
        }
Beispiel #5
0
        /// <summary>
        /// Converts <paramref name="Uin"/> and <paramref name="Uout"/> into
        /// instances of <see cref="StateVector"/> and calls
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </summary>
        /// <param name="time">
        /// <see cref="NonlinearFlux.InnerEdgeFlux(double, double[], double[],double[], double[], int)"/>
        /// </param>
        /// <param name="x">
        /// <see cref="NonlinearFlux.InnerEdgeFlux(double, double[], double[],double[], double[], int)"/>
        /// </param>
        /// <param name="normal">
        /// <see cref="NonlinearFlux.InnerEdgeFlux(double, double[], double[],double[], double[], int)"/>
        /// </param>
        /// <param name="Uin">
        /// <see cref="NonlinearFlux.InnerEdgeFlux(double, double[], double[],double[], double[], int)"/>
        /// </param>
        /// <param name="Uout">
        /// <see cref="NonlinearFlux.InnerEdgeFlux(double, double[], double[],double[], double[], int)"/>
        /// </param>
        /// <param name="jEdge">
        /// <see cref="NonlinearFlux.InnerEdgeFlux(double, double[], double[],double[], double[], int)"/>
        /// </param>
        /// <returns>
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </returns>
        protected override double InnerEdgeFlux(double time, double[] x, double[] normal, double[] Uin, double[] Uout, int jEdge)
        {
            StateVector stateIn  = new StateVector(Uin, material);
            StateVector stateOut = new StateVector(Uout, material);

            ilPSP.Vector Normal = new ilPSP.Vector(stateIn.Dimension);
            for (int i = 0; i < normal.Length; i++)
            {
                Normal[i] = normal[i];
            }

            double flux = InnerEdgeFlux(x, time, stateIn, stateOut, ref Normal, jEdge);

            Debug.Assert(!double.IsNaN(flux));
            return(flux);
        }
        /// <summary>
        /// calculating the inner edge fluxes by using a first oder upwind scheme
        /// </summary>
        protected override double InnerEdgeFlux(double time, double[] x, double[] normal, double[] Uin, double[] Uout, int jEdge)
        {
            ilPSP.Vector n = new ilPSP.Vector(2);
            n.x = normal[0];
            n.y = normal[1];

            var vel = FlowField(x, Uin, Uout);

            if (vel * n > 0)
            {
                return((vel * Uin[0]) * n);
            }
            else
            {
                return((vel * Uout[0]) * n);
            }
        }
Beispiel #7
0
        protected void EstimateWaveSpeeds(StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, out double waveSpeedIn, out double waveSpeedOut)
        {
            double normalVelocityIn  = stateIn.Velocity * normal;
            double normalVelocityOut = stateOut.Velocity * normal;

            double meanPressure     = 0.5 * (stateIn.Pressure + stateOut.Pressure);
            double meanDensity      = 0.5 * (stateIn.Density + stateOut.Density);
            double meanSpeedOfSound = 0.5 * (stateIn.SpeedOfSound + stateOut.SpeedOfSound);

            double velocityJump = normalVelocityOut - normalVelocityIn;
            double gamma        = config.EquationOfState.HeatCapacityRatio;
            double MachScaling  = gamma * config.MachNumber * config.MachNumber;

            // Calculate the pressure estimate at the edge and use it to
            // calculate the components of the correction factor qIn and qOut.
            // See Toro2009, equation 10.61 and corrected according to
            // dimensionless equations
            double pStar = meanPressure
                           - 0.5 * MachScaling * velocityJump * meanSpeedOfSound * meanDensity;

            pStar = Math.Max(0.0, pStar);

            double qIn = 1.0;

            if (pStar > stateIn.Pressure)
            {
                qIn = Math.Sqrt(
                    1.0 + 0.5 * (gamma + 1.0) * (pStar / stateIn.Pressure - 1.0) / gamma);
            }

            double qOut = 1.0;

            if (pStar > stateOut.Pressure)
            {
                qOut = Math.Sqrt(
                    1.0 + 0.5 * (gamma + 1.0) * (pStar / stateOut.Pressure - 1.0) / gamma);
            }

            // Finally determine the wave speeds
            waveSpeedIn  = normalVelocityIn - stateIn.SpeedOfSound * qIn;
            waveSpeedOut = normalVelocityOut + stateOut.SpeedOfSound * qOut;
        }
        protected override double BorderEdgeFlux(double time, double[] x, double[] normal, byte EdgeTag, double[] Uin, int jEdge)
        {
            ilPSP.Vector n = new ilPSP.Vector(2);
            n.x = normal[0];
            n.y = normal[1];

            var vel = FlowField(x, Uin, Uin);

            if (n * vel >= 0)
            {
                // flow from inside
                return((vel * Uin[0]) * n);
            }
            else
            {
                // flow from outside into the domain
                //return (vel * Uin[0]) * n;
                return((vel * inflow) * n);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Weakly imposes the specific boundary condition for this boundary
        /// type (defined by the edge tag) by calculating the outer value via a
        /// subclass of <see cref="BoundaryCondition"/> and
        /// inserting it into
        /// <see cref="InnerEdgeFlux(double, double[], double[], double[], double[], int)"/>
        /// </summary>
        protected override double BorderEdgeFlux(double time, double[] x, double[] normal, byte EdgeTag, double[] Uin, int jEdge)
        {
            StateVector stateIn = new StateVector(Uin, material);

            ilPSP.Vector Normal = new ilPSP.Vector(stateIn.Dimension);
            for (int i = 0; i < normal.Length; i++)
            {
                Normal[i] = normal[i];
            }

            // Get boundary condition on this edge
            BoundaryCondition boundaryCondition;

            if (this.boundaryMap is XDGCompressibleBoundaryCondMap xdgBoudaryMap)
            {
                boundaryCondition = xdgBoudaryMap.GetBoundaryConditionForSpecies(EdgeTag, this.speciesName);
            }
            else if (this.boundaryMap is CompressibleBoundaryCondMap boundaryMap)
            {
                boundaryCondition = boundaryMap.GetBoundaryCondition(EdgeTag);
            }
            else
            {
                throw new NotSupportedException("This type of boundary condition map is not supported.");
            }

            //StateVector stateBoundary = boundaryMap.GetBoundaryState(
            //    EdgeTag, time, x, normal, stateIn);

            StateVector stateBoundary = boundaryCondition.GetBoundaryState(time, x, normal, stateIn);

            double flux = InnerEdgeFlux(x, time, stateIn, stateBoundary, ref Normal, jEdge);

            Debug.Assert(!double.IsNaN(flux));
            return(flux);
        }
Beispiel #10
0
        /// <summary>
        /// Evaluates the HLLC flux according to Toro2009
        /// </summary>
        /// <returns>see Toro2009, equation 10.71</returns>
        public override double InnerEdgeFlux(double[] x, double time, StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, int edgeIndex)
        {
            double waveSpeedIn;
            double waveSpeedOut;

            EstimateWaveSpeeds(stateIn, stateOut, ref normal, out waveSpeedIn, out waveSpeedOut);

            double MachScaling = config.EquationOfState.HeatCapacityRatio * config.MachNumber * config.MachNumber;

            double normalVelocityIn  = stateIn.Velocity * normal;
            double normalVelocityOut = stateOut.Velocity * normal;

            double cIn  = stateIn.Density * (waveSpeedIn - normalVelocityIn);
            double cOut = stateOut.Density * (waveSpeedOut - normalVelocityOut);

            // cf. Toro2009, equation 10.70
            // corrected according to dimensionless equations
            double intermediateWaveSpeed = (cOut * normalVelocityOut - cIn * normalVelocityIn
                                            + (stateIn.Pressure - stateOut.Pressure) / MachScaling) / (cOut - cIn);

            double edgeFlux = 0.0;

            // cf. Toro2009, equation 10.71
            if (waveSpeedIn > 0.0)
            {
                edgeFlux = equationComponent.Flux(stateIn) * normal;
            }
            else if (waveSpeedIn <= 0.0 && 0.0 < intermediateWaveSpeed)
            {
                edgeFlux = equationComponent.Flux(stateIn) * normal + waveSpeedIn * (
                    GetModifiedVariableValue(stateIn, waveSpeedIn, normalVelocityIn, intermediateWaveSpeed, ref normal)
                    - equationComponent.VariableValue(stateIn));
            }
            else if (intermediateWaveSpeed <= 0.0 && 0.0 <= waveSpeedOut)
            {
                edgeFlux = equationComponent.Flux(stateOut) * normal + waveSpeedOut * (
                    GetModifiedVariableValue(stateOut, waveSpeedOut, normalVelocityOut, intermediateWaveSpeed, ref normal)
                    - equationComponent.VariableValue(stateOut));
            }
            else if (waveSpeedOut < 0.0)
            {
                edgeFlux = equationComponent.Flux(stateOut) * normal;
            }
            else
            {
                throw new Exception("Inconsistency in HLLC flux detected. Might the flow state be invalid?");
            }

            return(edgeFlux);
        }
Beispiel #11
0
        /// <summary>
        /// Evaluates the Rusanov flux (also known as the local Lax-Friedrichs
        /// flux as stated in Toro2009, equations 10.55 and 10.56.
        /// </summary>
        /// <returns>
        /// \f$
        /// \frac{1}{2} (F_L + F_R - S^+ (U_R - U_L))
        /// \f$
        /// where
        /// \f$
        /// S^+ = \max \{|u_L| + a_L, |u_r| + a_R\}
        /// \f$
        /// </returns>
        public override double InnerEdgeFlux(double[] x, double time, StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, int edgeIndex)
        {
            double waveSpeedIn  = Math.Abs(stateIn.Velocity * normal) + stateIn.SpeedOfSound;
            double waveSpeedOut = Math.Abs(stateOut.Velocity * normal) + stateOut.SpeedOfSound;
            double penalty      = Math.Max(waveSpeedIn, waveSpeedOut);

            double valueIn  = equationComponent.VariableValue(stateIn);
            double fluxIn   = equationComponent.Flux(stateIn) * normal;
            double valueOut = equationComponent.VariableValue(stateOut);
            double fluxOut  = equationComponent.Flux(stateOut) * normal;

            return(0.5 * (fluxIn + fluxOut - penalty * (valueOut - valueIn)));
        }
Beispiel #12
0
        /// <summary>
        /// Evaluates the HLL flux as described in BattenEtAl1997 in the form
        /// of equation 24.
        /// </summary>
        public override double InnerEdgeFlux(double[] x, double time, StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, int edgeIndex)
        {
            double waveSpeedIn;
            double waveSpeedOut;

            EstimateWaveSpeeds(stateIn, stateOut, ref normal, out waveSpeedIn, out waveSpeedOut);

            if (waveSpeedIn > 0.0)
            {
                return(equationComponent.Flux(stateIn) * normal);
            }
            else if (waveSpeedOut < 0.0)
            {
                return(equationComponent.Flux(stateOut) * normal);
            }
            else
            {
                double valueIn  = equationComponent.VariableValue(stateIn);
                double valueOut = equationComponent.VariableValue(stateOut);
                double fluxIn   = equationComponent.Flux(stateIn) * normal;
                double fluxOut  = equationComponent.Flux(stateOut) * normal;
                return((waveSpeedOut * fluxIn - waveSpeedIn * fluxOut + waveSpeedIn * waveSpeedOut * (valueOut - valueIn)) / (waveSpeedOut - waveSpeedIn));
            }
        }
Beispiel #13
0
 /// <summary>
 /// Actual calculation of flux across the edge.
 /// </summary>
 /// <param name="x">Evaluation point</param>
 /// <param name="time">Point in time</param>
 /// <param name="stateIn">The state inside the cell</param>
 /// <param name="stateOut">The state in the neighboring cell</param>
 /// <param name="normal">The unit normal vector</param>
 /// <param name="edgeIndex">
 /// Processor-local index of the current edge
 /// </param>
 /// <returns>See Toro2009 (p. 332)</returns>
 public abstract double InnerEdgeFlux(double[] x, double time, StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, int edgeIndex);
Beispiel #14
0
 /// <summary>
 /// Returns scalar dependent density.
 /// Implements <see cref="BoSSS.Foundation.Func"/>.
 /// </summary>
 /// <param name="X">Not used.</param>
 /// <param name="phi">scalar</param>
 /// <param name="jCell">Not used.</param>
 /// <returns>Density</returns>
 public double GetDensity(ilPSP.Vector X, double[] phi, int jCell)
 {
     return(this.GetDensity(phi));
 }
Beispiel #15
0
        /// <summary>
        /// Uses <see cref="ExactRiemannSolver"/> in order to compute the exact
        /// solution of the Riemann problem.
        /// </summary>
        /// <param name="x">
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </param>
        /// <param name="time">
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </param>
        /// <param name="stateIn">
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </param>
        /// <param name="stateOut">
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </param>
        /// <param name="normal">
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </param>
        /// <param name="edgeIndex">
        /// <see cref="InnerEdgeFlux(double[], double, StateVector, StateVector, ref Vector, int)"/>
        /// </param>
        /// <returns>
        /// <see cref="ExactRiemannSolver.GetCentralState"/>
        /// </returns>
        public override double InnerEdgeFlux(double[] x, double time, StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, int edgeIndex)
        {
            ExactRiemannSolver riemannSolver = new ExactRiemannSolver(
                stateIn, stateOut, normal);

            StateVector stateEdge = riemannSolver.GetCentralState();

            return(equationComponent.Flux(stateEdge) * normal);
        }
Beispiel #16
0
 /// <summary>
 /// See Toro2009, equation 10.73
 /// </summary>
 /// <param name="state">
 /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
 /// </param>
 /// <param name="cellWaveSpeed">
 /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
 /// </param>
 /// <param name="cellNormalVelocity">
 /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
 /// </param>
 /// <param name="intermediateWaveSpeed">
 /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
 /// </param>
 /// <param name="normal">
 /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
 /// </param>
 /// <returns>See Toro2009, equation 10.73</returns>
 protected override double GetModifiedVariableValue(StateVector state, double cellWaveSpeed, double cellNormalVelocity, double intermediateWaveSpeed, ref ilPSP.Vector normal)
 {
     return(state.Density
            * (cellWaveSpeed - cellNormalVelocity)
            / (cellWaveSpeed - intermediateWaveSpeed));
 }
Beispiel #17
0
 /// <summary>
 /// Implement this method for the different components of the Euler
 /// system by calculating the specific correction factor associated
 /// with the so called star region in the HLLC flux (see Toro2009)
 /// </summary>
 /// <param name="state">The flow state inside a cell</param>
 /// <param name="cellWaveSpeed">
 /// The fastest signal velocity in a cell
 /// </param>
 /// <param name="cellNormalVelocity">
 /// The velocity normal to the edge
 /// </param>
 /// <param name="intermediateWaveSpeed">
 /// An estimation for the signal velocity in the so called star region
 /// </param>
 /// <param name="normal">A unit vector normal to the edge</param>
 /// <returns>
 /// An estimate for the variable value in the star region
 /// </returns>
 abstract protected double GetModifiedVariableValue(StateVector state, double cellWaveSpeed, double cellNormalVelocity, double intermediateWaveSpeed, ref ilPSP.Vector normal);
Beispiel #18
0
        public override double InnerEdgeFlux(double[] x, double time, StateVector stateIn, StateVector stateOut, ref ilPSP.Vector normal, int edgeIndex)
        {
            // Version: Subtract -s * flux from upwind
            double uIn        = stateIn.Velocity * normal;
            double uOut       = stateOut.Velocity * normal;
            double correction = 0.0;

            if (edgeIndex < 0)
            {
                double s             = levelSetVelocity(x, time) * normal;
                double relativeSpeed = 0.5 * (uIn + uOut) - s;
                if (relativeSpeed > 0.0)
                {
                    correction = s * equationComponent.VariableValue(stateIn);
                }
                else
                {
                    correction = s * equationComponent.VariableValue(stateOut);
                }
            }

            double waveSpeedIn  = uIn + stateIn.SpeedOfSound;
            double waveSpeedOut = uOut + stateOut.SpeedOfSound;
            double penalty      = Math.Max(waveSpeedIn, waveSpeedOut);

            double valueIn  = equationComponent.VariableValue(stateIn);
            double fluxIn   = equationComponent.Flux(stateIn) * normal;
            double valueOut = equationComponent.VariableValue(stateOut);
            double fluxOut  = equationComponent.Flux(stateOut) * normal;

            return(0.5 * (fluxIn + fluxOut) - 0.5 * penalty * (valueOut - valueIn) - correction);
        }
Beispiel #19
0
        /// <summary>
        /// See Toro2009, equation 10.73
        /// </summary>
        /// <param name="state">
        /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
        /// </param>
        /// <param name="cellWaveSpeed">
        /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
        /// </param>
        /// <param name="cellNormalVelocity">
        /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
        /// </param>
        /// <param name="intermediateWaveSpeed">
        /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
        /// </param>
        /// <param name="normal">
        /// <see cref="HLLCFlux.GetModifiedVariableValue"/>
        /// </param>
        /// <returns>See Toro2009, equation 10.73</returns>
        protected override double GetModifiedVariableValue(StateVector state, double cellWaveSpeed, double cellNormalVelocity, double intermediateWaveSpeed, ref ilPSP.Vector normal)
        {
            // corrected according to dimensionless equations
            double MachScaling = config.EquationOfState.HeatCapacityRatio * config.MachNumber * config.MachNumber;
            double factor      = intermediateWaveSpeed * MachScaling
                                 + state.Pressure / (state.Density * (cellWaveSpeed - cellNormalVelocity));

            return(state.Density
                   * (cellWaveSpeed - cellNormalVelocity)
                   / (cellWaveSpeed - intermediateWaveSpeed)
                   * (state.Energy / state.Density + factor * (intermediateWaveSpeed - cellNormalVelocity)));
        }