/// <summary> /// <see cref="INonlinearFlux.InnerEdgeFlux"/> /// </summary> public void InnerEdgeFlux(double time, Vector2D x, Vector2D n, double[] FunctionMatrixIn, double[] FunctionMatrixOut, out double AffineOffset) { Array.Clear(m_Arguments, 0, m_Arguments.Length); Array.Clear(m_Arguments2, 0, m_Arguments.Length); AffineOffset = m_Flux.InnerEdgeFlux(time, x, n, m_Arguments, m_Arguments2); for (int i = m_Arguments.Length - 1; i >= 0; i--) { m_Arguments[i] = 1; FunctionMatrixIn[i] = m_Flux.InnerEdgeFlux(time, x, n, m_Arguments, m_Arguments2); FunctionMatrixIn[i] -= AffineOffset; m_Arguments[i] = 0; m_Arguments2[i] = 1; FunctionMatrixOut[i] = m_Flux.InnerEdgeFlux(time, x, n, m_Arguments, m_Arguments2); FunctionMatrixOut[i] -= AffineOffset; m_Arguments2[i] = 0; } if (!_Flux) { Array.Clear(FunctionMatrixIn, 0, FunctionMatrixIn.Length); Array.Clear(FunctionMatrixOut, 0, FunctionMatrixOut.Length); AffineOffset = 0.0; } //if (!Neighbour) { // Array.Clear(FunctionMatrixOut, 0, FunctionMatrixOut.Length); // AffineOffset = 0.0; //} //if (!Local) { // Array.Clear(FunctionMatrixIn, 0, FunctionMatrixIn.Length); // AffineOffset = 0.0; //} }
/// <summary> /// Evaluates the configured flux function (see /// <see cref="BoundaryConditionSourceFromINonlinearFlux.BoundaryConditionSourceFromINonlinearFlux(CNSControl, ISpeciesMap, BoundaryCondition, INonlinearFlux)"/> /// using the present flow state <paramref name="U"/> and the boundary /// value provided by the configured boundary condition. /// </summary> /// <param name="time"></param> /// <param name="x"></param> /// <param name="U"></param> /// <param name="IndexOffset"></param> /// <param name="FirstCellInd"></param> /// <param name="Lenght"></param> /// <param name="Output"></param> public void Source(double time, MultidimensionalArray x, MultidimensionalArray[] U, int IndexOffset, int FirstCellInd, int Lenght, MultidimensionalArray Output) { int D = CompressibleEnvironment.NumberOfDimensions; int noOfNodes = x.GetLength(1); int noOfVariables = D + 2; MultidimensionalArray normal = MultidimensionalArray.Create(Lenght, noOfNodes, D); MultidimensionalArray[] Uout = new MultidimensionalArray[noOfVariables]; for (int i = 0; i < noOfVariables; i++) { Uout[i] = MultidimensionalArray.Create(Lenght, noOfNodes); } double[] xLocal = new double[D]; Material material = speciesMap.GetMaterial(double.NaN); for (int i = 0; i < Lenght; i++) { for (int j = 0; j < noOfNodes; j++) { StateVector stateIn = new StateVector(material, U, i, j, CompressibleEnvironment.NumberOfDimensions); Vector levelSetNormal = new Vector(CompressibleEnvironment.NumberOfDimensions); int offset = CompressibleEnvironment.NumberOfDimensions + 2; for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { levelSetNormal[d] = U[offset + d][i + IndexOffset, j]; } levelSetNormal.Normalize(); Debug.Assert(Math.Abs(levelSetNormal.Abs() - 1.0) < 1e-13, "Abnormal normal vector"); for (int d = 0; d < D; d++) { xLocal[d] = x[i + IndexOffset, j, d]; normal[i, j, d] = levelSetNormal[d]; } StateVector stateOut = boundaryCondition.GetBoundaryState(time, xLocal, levelSetNormal, stateIn); Debug.Assert(stateOut.IsValid, "Invalid boundary state"); Uout[0][i, j] = stateOut.Density; for (int d = 0; d < D; d++) { Uout[d + 1][i, j] = stateOut.Momentum[d]; } Uout[D + 1][i, j] = stateOut.Energy; } } fluxFunction.InnerEdgeFlux(time, -1, x, normal, U, Uout, IndexOffset, Lenght, Output); }
/// <summary> /// Affine-linear flux function on an inner edge. An affine-linear flux /// must implemented as two matrices and an offset vector: The linear /// flux, in a mathematical notation is defined as InnerFlux(Uin,Uout) = /// BorderFlux(U) = M_in*Uin + M_out*Uout + b /// where Uin and Uout are column vectors containing function values of /// other fields on the respective side of the concerned edge. Which /// fields in which order is specified by /// <see cref="IEquationComponent.ArgumentOrdering" /> property. In /// this implementation, the resulting flux solely depends on the /// implementation of <see cref="INonlinearFlux.InnerEdgeFlux"/> that /// has been supplied to the constructor. /// </summary> /// <param name="inp"> /// A set of input parameters such as time, coordinate and values of /// parameters. Given as reference for performance reasons; DO NOT /// WRITE to this structure. /// </param> /// <param name="Uin"></param> /// <param name="Uout"></param> protected override double InnerEdgeFlux(ref CommonParams inp, double[] Uin, double[] Uout) { MultidimensionalArray refFlux = MultidimensionalArray.Create(1, 1); baseFlux.InnerEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.D), MultidimensionalArray.CreateWrapper(inp.Normal, 1, inp.D), inp.Parameters_IN.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), inp.Parameters_OUT.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, refFlux); double[] FunctionMatrixIn = new double[inp.Parameters_IN.Length]; for (int i = 0; i < inp.Parameters_IN.Length; i++) { double[] perturbedParameters = inp.Parameters_IN.CloneAs(); double stepSize = GetStepSize(perturbedParameters[i]); perturbedParameters[i] += stepSize; MultidimensionalArray perturbedFlux = MultidimensionalArray.Create(1, 1); baseFlux.InnerEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.D), MultidimensionalArray.CreateWrapper(inp.Normal, 1, inp.D), perturbedParameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), inp.Parameters_OUT.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, perturbedFlux); FunctionMatrixIn[i] = (perturbedFlux[0, 0] - refFlux[0, 0]) / stepSize; } double[] FunctionMatrixOut = new double[inp.Parameters_OUT.Length]; for (int i = 0; i < inp.Parameters_OUT.Length; i++) { double[] perturbedParameters = inp.Parameters_OUT.CloneAs(); double stepSize = GetStepSize(perturbedParameters[i]); perturbedParameters[i] += stepSize; MultidimensionalArray perturbedFlux = MultidimensionalArray.Create(1, 1); baseFlux.InnerEdgeFlux( 0.0, inp.iEdge, MultidimensionalArray.CreateWrapper(inp.X, 1, 1, inp.D), MultidimensionalArray.CreateWrapper(inp.Normal, 1, inp.D), inp.Parameters_IN.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), perturbedParameters.Select(p => MultidimensionalArray.CreateWrapper(new double[] { p }, 1, 1)).ToArray(), 0, 1, perturbedFlux); FunctionMatrixOut[i] = (perturbedFlux[0, 0] - refFlux[0, 0]) / stepSize; } double result = refFlux[0, 0]; for (int i = 0; i < inp.Parameters_IN.Length; i++) { result += FunctionMatrixIn[i] * (Uin[i] - inp.Parameters_IN[i]) + FunctionMatrixOut[i] * (Uout[i] - inp.Parameters_OUT[i]); } return(result); }
//private static StreamWriter writer; /// <summary> /// Evaluates the configured flux function (see /// <see cref="BoundaryConditionSourceFromINonlinearFlux.BoundaryConditionSourceFromINonlinearFlux(CNSControl, ISpeciesMap, BoundaryCondition, INonlinearFlux)"/> /// using the present flow state <paramref name="U"/> and the boundary /// value provided by the configured boundary condition. /// </summary> /// <param name="time"></param> /// <param name="x"></param> /// <param name="U"></param> /// <param name="IndexOffset"></param> /// <param name="FirstCellInd"></param> /// <param name="Lenght"></param> /// <param name="Output"></param> public void Source(double time, MultidimensionalArray x, MultidimensionalArray[] U, int IndexOffset, int FirstCellInd, int Lenght, MultidimensionalArray Output) { int D = CompressibleEnvironment.NumberOfDimensions; int noOfNodes = x.GetLength(1); int noOfVariables = D + 2; MultidimensionalArray normal = MultidimensionalArray.Create(Lenght, noOfNodes, D); MultidimensionalArray[] Uout = new MultidimensionalArray[noOfVariables]; for (int i = 0; i < noOfVariables; i++) { Uout[i] = MultidimensionalArray.Create(Lenght, noOfNodes); } //bool writeFluxes = false; double[] xLocal = new double[D]; Material material = speciesMap.GetMaterial(double.NaN); for (int i = 0; i < Lenght; i++) { for (int j = 0; j < noOfNodes; j++) { StateVector stateIn = new StateVector(material, U, i, j, CompressibleEnvironment.NumberOfDimensions); Vector levelSetNormal = new Vector(CompressibleEnvironment.NumberOfDimensions); int offset = CompressibleEnvironment.NumberOfDimensions + 2; for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { levelSetNormal[d] = U[offset + d][i + IndexOffset, j]; } levelSetNormal.Normalize(); Debug.Assert(Math.Abs(levelSetNormal.Abs() - 1.0) < 1e-13, "Abnormal normal vector"); for (int d = 0; d < D; d++) { xLocal[d] = x[i + IndexOffset, j, d]; normal[i, j, d] = levelSetNormal[d]; } StateVector stateOut = boundaryCondition.GetBoundaryState(time, xLocal, levelSetNormal, stateIn); Debug.Assert(stateOut.IsValid, "Invalid boundary state"); Uout[0][i, j] = stateOut.Density; for (int d = 0; d < D; d++) { Uout[d + 1][i, j] = stateOut.Momentum[d]; } Uout[D + 1][i, j] = stateOut.Energy; //if (boundaryCondition is AdiabaticSlipWall) { // writeFluxes = true; //} } } fluxFunction.InnerEdgeFlux(time, -1, x, normal, U, Uout, IndexOffset, Lenght, Output); //string bulkFluxName = null; //if (fluxFunction is OptimizedHLLCDensityFlux) { // bulkFluxName = "rho"; //} else if (fluxFunction is OptimizedHLLCMomentumFlux tmp) { // bulkFluxName = "m"; //} else if (fluxFunction is OptimizedHLLCEnergyFlux) { // bulkFluxName = "rhoE"; //} //if (writeFluxes) { // for (int i = 0; i < x.Lengths[1]; i++) { // //Console.WriteLine(String.Format("Flux at ({0:0.00000000}, {1:0.00000000}) = {2:0.00000000} \t normal = ({3:0.00000000}, {4:0.00000000})", x[0, i, 0], x[0, i, 1], Output[0, i], normal[0, i, 0], normal[0, i, 1])); // // StreamWriter // if (writer == null) { // writer = new StreamWriter("CNS_Flux.txt"); // writer.WriteLine("bulkFlux \t\t\t x \t y \t \t \t \t ### \t n_x \t n_y \t flux \t \t \t \t ### \t Uin[0] \t Uin[1] \t Uin[2] \t Uin[3] \t ### \t Uout[0] \t Uout[1] \t Uout[2] \t Uout[3]"); // } // string resultLine; // resultLine = String.Format(bulkFluxName + "\t\t ### \t {0:0.000000} \t {1:0.000000} \t ### \t {2:0.000000} \t {3:0.000000} \t {4:0.000000} \t ### \t {5:0.000000} \t {6:0.000000} \t {7:0.000000} \t {8:0.000000} \t ### \t {9:0.000000} \t {10:0.000000} \t {11:0.000000} \t {12:0.000000}", x[0, i, 0], x[0, i, 1], normal[0, i, 0], normal[0, i, 1], Output[0, i], U[0][0, i], U[1][0, i], U[2][0, i], U[3][0, i], Uout[0][0, i], Uout[1][0, i], Uout[2][0, i], Uout[3][0, i]); // writer.WriteLine(resultLine); // writer.Flush(); // } //} }