void IInnerEdgeSource_V.InternalEdge_V(ref EdgeFormParams inp, MultidimensionalArray Koeff_V) { int j0 = inp.e0; int Len = inp.Len; int N = inp.Nodes.GetLength(1); // nodes per cell int D = inp.Nodes.GetLength(2); // spatial dim. int NoOfVars = this.ArgumentOrdering.Count; // check dimension of input array Koeff_V.CheckLengths(Len, N, 2); // create temp mem: int NP = (this.ParameterOrdering != null) ? this.ParameterOrdering.Count : 0; double[] ParamsPos = new double[NP]; double[] ParamsNeg = new double[NP]; CommonParams cp; cp.Normal = new Vector(D); cp.X = new Vector(D); cp.Parameters_IN = ParamsNeg; cp.Parameters_OUT = ParamsPos; cp.time = inp.time; cp.iEdge = -123456; cp.GridDat = null; // temp mem. double[] uA = new double[NoOfVars]; double[] uB = new double[NoOfVars]; double[,] Grad_uA = new double[NoOfVars, D]; double[,] Grad_uB = new double[NoOfVars, D]; double vA = 0; double vB = 0; double[] Grad_vA = new double[D]; double[] Grad_vB = new double[D]; for (int j = 0; j < Len; j++) // loop over items... { int iSpcNeg = 0; int iSpcPos = 1; cp.jCellIn = j + inp.e0; cp.jCellOut = cp.jCellIn; for (int n = 0; n < N; n++) // loop over nodes... { cp.Normal.SetFrom(inp.Normals, j, n); cp.X.SetFrom(inp.Nodes, j, n); for (int i = 0; i < NP; i++) { ParamsPos[i] = inp.ParameterVars_OUT[i][j, n]; ParamsNeg[i] = inp.ParameterVars_IN[i][j, n]; } Koeff_V[j, n, iSpcNeg] = GetSourceCoeff(ref vA, ref cp, uA, uB, Grad_uA, Grad_uB, ref vA, ref vB, Grad_vA, Grad_vB); Koeff_V[j, n, iSpcPos] = GetSourceCoeff(ref vB, ref cp, uA, uB, Grad_uA, Grad_uB, ref vA, ref vB, Grad_vA, Grad_vB); } } }
public void InternalEdge_GradV(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); Debug.Assert(fot.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; for (int node = 0; node < NumOfNodes; node++) // loop over nodes... { double uJump = 0.5 * (Uin[0][cell, node] - Uout[0][cell, node]); double fluxIn = efp.ParameterVars_IN[0][cell, node] * uJump; double fluxOut = efp.ParameterVars_OUT[0][cell, node] * uJump; for (int d = 0; d < GridData.SpatialDimension; d++) { double n = efp.Normals[cell, node, d]; fin[cell, node, d] -= fluxIn * n; fot[cell, node, d] -= fluxOut * n; } } } }
void IEdgeform_GradUxGradV.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray GradUxGradV) { InitGlobals(efp); Debug.Assert(L == efp.Len); Debug.Assert(efp.ParameterVars_IN.Length == NoParams); Debug.Assert(efp.ParameterVars_OUT.Length == NoParams); Debug.Assert(efp.Len == GradUxGradV.GetLength(0)); Debug.Assert(2 == GradUxGradV.GetLength(2)); Debug.Assert(2 == GradUxGradV.GetLength(3)); Debug.Assert(NoArgs == GradUxGradV.GetLength(4)); Debug.Assert(D == GradUxGradV.GetLength(6)); Debug.Assert(D == GradUxGradV.GetLength(6)); CommonParams cp = default(CommonParams); cp.Normale = new double[D]; cp.X = new double[D]; cp.Parameters_IN = new double[NoParams]; cp.Parameters_OUT = new double[NoParams]; cp.GridDat = efp.GridDat; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normale[d] = efp.Normals[l, k, d]; cp.X[d] = efp.NodesGlobal[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cp.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { for (int c = 0; c < NoArgs; c++) { GradUxGradV[l, k, 0, 0, c, d1, d2] = GetCoeff(ref Grad_uA[c, d1], ref Grad_vA[d2], ref cp); GradUxGradV[l, k, 0, 1, c, d1, d2] = GetCoeff(ref Grad_uB[c, d1], ref Grad_vA[d2], ref cp); GradUxGradV[l, k, 1, 0, c, d1, d2] = GetCoeff(ref Grad_uA[c, d1], ref Grad_vB[d2], ref cp); GradUxGradV[l, k, 1, 1, c, d1, d2] = GetCoeff(ref Grad_uB[c, d1], ref Grad_vB[d2], ref cp); } } } } } }
/// <summary> /// see <see cref="IInnerEdgeform_UxGradV.InternalEdge_UxGradV"/> /// </summary> void IInnerEdgeform_UxGradV.InternalEdge_UxGradV(ref EdgeFormParams efp, MultidimensionalArray UxGradV) { InitGlobals(efp); var E2C = efp.GridDat.iGeomEdges.CellIndices; Debug.Assert(L == efp.Len); Debug.Assert(efp.ParameterVars_IN.Length == NoParams); Debug.Assert(efp.ParameterVars_OUT.Length == NoParams); Debug.Assert(efp.Len == UxGradV.GetLength(0)); Debug.Assert(2 == UxGradV.GetLength(2)); Debug.Assert(2 == UxGradV.GetLength(3)); Debug.Assert(NoArgs == UxGradV.GetLength(4)); Debug.Assert(D == UxGradV.GetLength(5)); CommonParams cp; cp.Normal = new Vector(D); cp.X = new Vector(D); cp.Parameters_IN = new double[NoParams]; cp.Parameters_OUT = new double[NoParams]; cp.GridDat = efp.GridDat; cp.time = efp.time; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; cp.jCellIn = E2C[cp.iEdge, 0]; cp.jCellOut = E2C[cp.iEdge, 1]; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normal[d] = efp.Normals[l, k, d]; cp.X[d] = efp.Nodes[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cp.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d = 0; d < D; d++) { for (int c = 0; c < NoArgs; c++) { UxGradV[l, k, 0, 0, c, d] = GetCoeff(ref uA[c], ref Grad_vA[d], ref cp); UxGradV[l, k, 0, 1, c, d] = GetCoeff(ref uB[c], ref Grad_vA[d], ref cp); UxGradV[l, k, 1, 0, c, d] = GetCoeff(ref uA[c], ref Grad_vB[d], ref cp); UxGradV[l, k, 1, 1, c, d] = GetCoeff(ref uB[c], ref Grad_vB[d], ref cp); } } } } }
/// <summary> /// Consistency and penalty term /// </summary> void INonlinEdgeForm_V.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell int dimension = efp.GridDat.SpatialDimension; for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; // Penalty is calculated according to the formula in background cells int jCellIn = this.GridData.Edges.CellIndices[iEdge, 0]; double penalty = 2 * this.penalties[jCellIn]; byte edgeTag = this.GridData.iGeomEdges.EdgeTags[iEdge]; XDGHeatBcType edgeType = this.boundaryCondMap.EdgeTag2Type[edgeTag]; Func <double[], double, double> dirichletFunction = this.boundaryCondMap.bndFunction["u"][edgeTag]; for (int node = 0; node < NumOfNodes; node++) // loop over nodes... // Global node coordinates { double[] X = new double[dimension]; for (int i = 0; i < dimension; i++) { X[i] = efp.NodesGlobal[cell, node, i]; } // SIPG Flux Loops double viscosityIn = efp.ParameterVars_IN[0][cell, node]; switch (edgeType) { case XDGHeatBcType.Dirichlet: double g_D = dirichletFunction(X, efp.time); double flux = 0.0; for (int d = 0; d < GridData.SpatialDimension; d++) { double n = efp.Normals[cell, node, d]; flux -= viscosityIn * GradUin[0][cell, node, d] * n; // Consistency term } flux += viscosityIn * (Uin[0][cell, node] - g_D) * penalty; // Penalty term fin[cell, node] += flux; break; default: // Boundary value is zero neumann boundary, i.e. do nothing break; } } } }
static private void EvalComponent <T>(ref EdgeFormParams _inParams, int gamma, EquationComponentArgMapping <T> bf, Stopwatch[] timers, MultidimensionalArray SumBufIn, MultidimensionalArray SumBufOt, MultidimensionalArray[] FieldValuesPos, MultidimensionalArray[] FieldValuesNeg, MultidimensionalArray[] FieldGradientValuesPos, MultidimensionalArray[] FieldGradientValuesNeg, int DELTA, Stopwatch timer, Action <T, MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray, MultidimensionalArray> ComponentFunc) where T : ILevelSetForm // { timer.Start(); for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++) // loop over equation components { var comp = bf.m_AllComponentsOfMyType[i]; int NoOfArgs = bf.NoOfArguments[i]; Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count); int NoOfParams = bf.NoOfParameters[i]; Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0)); // map arguments var uA = bf.MapArguments(FieldValuesNeg, comp, true); var uB = bf.MapArguments(FieldValuesPos, comp, true); var Grad_uA = bf.MapArguments(FieldGradientValuesNeg, comp, true); var Grad_uB = bf.MapArguments(FieldGradientValuesPos, comp, true); // map parameters _inParams.ParameterVars_OUT = new MultidimensionalArray[NoOfParams]; _inParams.ParameterVars_IN = new MultidimensionalArray[NoOfParams]; for (int c = 0; c < NoOfParams; c++) { int targ = bf.AllToSub[i, c + NoOfArgs]; Debug.Assert(targ >= 0); _inParams.ParameterVars_OUT[c] = FieldValuesPos[targ]; _inParams.ParameterVars_IN[c] = FieldValuesNeg[targ]; } // evaluate equation components timers[i].Start(); ComponentFunc(comp, uA, uB, Grad_uA, Grad_uB, SumBufIn, SumBufOt); timers[i].Stop(); #if DEBUG SumBufIn.CheckForNanOrInf(); SumBufOt.CheckForNanOrInf(); #endif } timer.Stop(); }
/// <summary> /// Symmetry term /// </summary> void INonlinEdgeForm_GradV.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell int dimension = efp.GridDat.SpatialDimension; for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; byte edgeTag = this.GridData.iGeomEdges.EdgeTags[iEdge]; XDGHeatBcType edgeType = this.boundaryCondMap.EdgeTag2Type[edgeTag]; Func <double[], double, double> dirichletFunction = this.boundaryCondMap.bndFunction["u"][edgeTag]; for (int node = 0; node < NumOfNodes; node++) // loop over nodes... // Global node coordinates { double[] X = new double[dimension]; for (int i = 0; i < dimension; i++) { X[i] = efp.NodesGlobal[cell, node, i]; } switch (edgeType) { case XDGHeatBcType.Dirichlet: double g_D = dirichletFunction(X, efp.time); //double uJump = 0.5 * (Uin[0][cell, node] - g_D); double uJump = 1.0 * (Uin[0][cell, node] - g_D); double fluxIn = efp.ParameterVars_IN[0][cell, node] * uJump; for (int d = 0; d < GridData.SpatialDimension; d++) { double n = efp.Normals[cell, node, d]; fin[cell, node, d] -= fluxIn * n; } break; default: // Boundary value is zero neumann boundary, i.e. do nothing break; } } } }
/// <summary> /// see <see cref="IEdgeform_GradUxV.InternalEdge"/> /// </summary> void IEdgeform_GradUxV.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray GradUxV) { InitGlobals(efp); Debug.Assert(efp.ParameterVars_IN.Length == NoParams); Debug.Assert(efp.ParameterVars_OUT.Length == NoParams); CommonParams cp = default(CommonParams); cp.Normale = new double[D]; cp.X = new double[D]; cp.Parameters_IN = new double[NoParams]; cp.Parameters_OUT = new double[NoParams]; cp.GridDat = efp.GridDat; cp.time = efp.time; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normale[d] = efp.Normals[l, k, d]; cp.X[d] = efp.NodesGlobal[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cp.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d = 0; d < D; d++) { for (int c = 0; c < NoArgs; c++) { GradUxV[l, k, 0, 0, c, d] = GetCoeff(ref Grad_uA[c, d], ref vA, ref cp); GradUxV[l, k, 0, 1, c, d] = GetCoeff(ref Grad_uB[c, d], ref vA, ref cp); GradUxV[l, k, 1, 0, c, d] = GetCoeff(ref Grad_uA[c, d], ref vB, ref cp); GradUxV[l, k, 1, 1, c, d] = GetCoeff(ref Grad_uB[c, d], ref vB, ref cp); } } } } }
private void InitGlobals(EdgeFormParams efp) { D = efp.GridDat.SpatialDimension; K = efp.Normals.GetLength(1); L = efp.Len; NoArgs = this.ArgumentOrdering.Count; NoParams = this.ParameterOrdering != null ? this.ParameterOrdering.Count : 0; uA = new double[NoArgs]; uB = new double[NoArgs]; Grad_uA = new double[NoArgs, D]; Grad_uB = new double[NoArgs, D]; Grad_vA = new double[D]; Grad_vB = new double[D]; }
void INonlinEdgeForm_V.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { //int NumOfCells = efp.Len; //Debug.Assert(fin.GetLength(0) == NumOfCells); //int NumOfNodes = fin.GetLength(1); // no of nodes per cell //int NumOfArguments = this.ArgumentOrdering.Count; //Debug.Assert(NumOfArguments == Uin.Length); //Debug.Assert(NumOfArguments == GradUin.Length); //double[] U_in = new double[NumOfArguments]; //double[] U_ot = new double[NumOfArguments]; //double[,] GradU_in = new double[dimension, NumOfArguments]; //for (int cell = 0; cell < NumOfCells; cell++) { // loop over cells... // int iEdge = efp.e0 + cell; // for (int node = 0; node < NumOfNodes; node++) { // loop over nodes... // for (int na = 0; na < NumOfArguments; na++) { // U_in[na] = Uin[na][cell, node]; // for (int d = 0; d < dimension; d++) { // GradU_in[d, na] = GradUin[na][cell, node, d]; // } // } // // SIPG Flux Loops // //double flux = 0.0; // //for (int k = 0; k < dimension; k++) { // // double nk = efp.Normals[cell, node, k]; // // for (int l = 0; l < dimension; l++) { // // double nl = efp.Normals[cell, node, l]; // // for (int j = 0; j < NumOfArguments; j++) { // // // consistency // // flux -= (GTensorOut[k, l, j] * GradU_in[l,j]) * nk; // // // penalty // // flux += (GTensorOut[k, l, j]) * (U_in[j] - U_ot[j]) * nl * Penalty * nk; // // } // // } // //} // //fin[cell, node] += flux; // } //} }
void IEdgeform_GradUxGradV.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray GradUxGradV) { InitGlobals(efp); CommonParamsBnd cp = default(CommonParamsBnd); cp.Normale = new double[D]; cp.X = new double[D]; cp.Parameters_IN = new double[NoParams]; cp.GridDat = efp.GridDat; cp.time = efp.time; var _EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; cp.EdgeTag = _EdgeTags[cp.iEdge]; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normale[d] = efp.Normals[l, k, d]; cp.X[d] = efp.NodesGlobal[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; } for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { for (int c = 0; c < NoArgs; c++) { GradUxGradV[l, k, c, d1, d2] = GetCoeffBnd(ref Grad_uA[c, d1], ref Grad_vA[d2], ref cp); } } } } } }
/// <summary> /// see <see cref="IEdgeSource_GradV.InternalEdge"/> /// </summary> void IInnerEdgeSource_GradV.InternalEdge_GradV(ref EdgeFormParams efp, MultidimensionalArray GradV) { InitGlobals(efp); var E2C = efp.GridDat.iGeomEdges.CellIndices; CommonParams cp; cp.Normal = new Vector(D); cp.X = new Vector(D); cp.Parameters_IN = new double[NoParams]; cp.Parameters_OUT = new double[NoParams]; cp.GridDat = efp.GridDat; cp.time = efp.time; var _EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; cp.jCellIn = E2C[cp.iEdge, 0]; cp.jCellOut = E2C[cp.iEdge, 1]; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normal[d] = efp.Normals[l, k, d]; cp.X[d] = efp.Nodes[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cp.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d = 0; d < D; d++) { GradV[l, k, 0, d] = GetSourceCoeff(ref Grad_vA[d], ref cp); GradV[l, k, 1, d] = GetSourceCoeff(ref Grad_vB[d], ref cp); } } } }
/// <summary> /// see <see cref="IBoundaryEdgeform_UxGradV.BoundaryEdge_UxGradV"/> /// </summary> void IBoundaryEdgeform_UxGradV.BoundaryEdge_UxGradV(ref EdgeFormParams efp, MultidimensionalArray UxGradV) { InitGlobals(efp); CommonParamsBnd cp; cp.Normal = new Vector(D); cp.X = new Vector(D); cp.Parameters_IN = new double[NoParams]; cp.GridDat = efp.GridDat; cp.time = efp.time; var _EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; cp.EdgeTag = _EdgeTags[cp.iEdge]; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normal[d] = efp.Normals[l, k, d]; cp.X[d] = efp.Nodes[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; } for (int d = 0; d < D; d++) { for (int c = 0; c < NoArgs; c++) { UxGradV[l, k, c, d] = GetCoeffBnd(ref uA[c], ref Grad_vA[d], ref cp); } } } } }
/// <summary> /// see <see cref="IEdgeSource_GradV.InternalEdge"/> /// </summary> void IEdgeSource_GradV.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray GradV) { InitGlobals(efp); CommonParams cp = default(CommonParams); cp.Normale = new double[D]; cp.X = new double[D]; cp.Parameters_IN = new double[NoParams]; cp.Parameters_OUT = new double[NoParams]; cp.GridDat = efp.GridDat; var _EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normale[d] = efp.Normals[l, k, d]; cp.X[d] = efp.NodesGlobal[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cp.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d = 0; d < D; d++) { GradV[l, k, 0, d] = GetSourceCoeff(ref Grad_vA[d], ref cp); GradV[l, k, 1, d] = GetSourceCoeff(ref Grad_vB[d], ref cp); } } } }
void INonlinEdgeform_V.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot, bool adiaWall) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); Debug.Assert(fot.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; //double Penalty = penalty(gridDat.Edges.CellIndices[iEdge, 0], gridDat.Edges.CellIndices[iEdge, 1], gridDat.Cells.cj); int jCellIn = gridData.Edges.CellIndices[iEdge, 0]; int jCellOut = gridData.Edges.CellIndices[iEdge, 1]; double Penalty = penaltyFactor * Math.Max(cellLengthScale[jCellIn], cellLengthScale[jCellOut]); for (int node = 0; node < NumOfNodes; node++) // loop over nodes... // SIPG Flux Loops { double viscosityIn = efp.ParameterVars_IN[0][cell, node]; double viscosityOut = efp.ParameterVars_OUT[0][cell, node]; double flux = 0.0; for (int d = 0; d < dimension; d++) { double n = efp.Normals[cell, node, d]; flux -= 0.5 * (viscosityIn * GradUin[0][cell, node, d] + viscosityOut * GradUout[0][cell, node, d]) * n; } flux += Math.Max(viscosityIn, viscosityOut) * (Uin[0][cell, node] - Uout[0][cell, node]) * Penalty; fin[cell, node] += flux; fot[cell, node] -= flux; } } }
public void InternalEdge_V(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); Debug.Assert(fot.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; // Penalty is calculated according to the formula in background cells int jCellIn = this.GridData.Edges.CellIndices[iEdge, 0]; int jCellOut = this.GridData.Edges.CellIndices[iEdge, 1]; double penalty = Math.Max(this.penalties[jCellIn], this.penalties[jCellOut]); for (int node = 0; node < NumOfNodes; node++) // loop over nodes... // SIPG Flux Loops { double viscosityIn = efp.ParameterVars_IN[0][cell, node]; double viscosityOut = efp.ParameterVars_OUT[0][cell, node]; double flux = 0.0; for (int d = 0; d < GridData.SpatialDimension; d++) { double n = efp.Normals[cell, node, d]; flux -= 0.5 * (viscosityIn * GradUin[0][cell, node, d] + viscosityOut * GradUout[0][cell, node, d]) * n; // Consistency term } flux += Math.Max(viscosityIn, viscosityOut) * (Uin[0][cell, node] - Uout[0][cell, node]) * penalty; // Penalty term fin[cell, node] += flux; fot[cell, node] -= flux; } } }
void INonlinEdgeForm_GradV.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { //Boundary value is zero neumann boundary! // i.e. do nothing! //int NumOfCells = efp.Len; //Debug.Assert(fin.GetLength(0) == NumOfCells); //int NumOfNodes = fin.GetLength(1); // no of nodes per cell //int NumOfArguments = this.ArgumentOrdering.Count; //Debug.Assert(NumOfArguments == Uin.Length); //Debug.Assert(NumOfArguments == GradUin.Length); //double[] U_in = new double[NumOfArguments]; //double[] U_ot = new double[NumOfArguments]; //for (int cell = 0; cell < NumOfCells; cell++) { // loop over cells... // int iEdge = efp.e0 + cell; // for (int node = 0; node < NumOfNodes; node++) { // loop over nodes... // for (int na = 0; na < NumOfArguments; na++) { // U_in[na] = Uin[na][cell, node]; // } // //// Reference implementation // //for (int d = 0; d < dimension; d++) { // // double n = efp.Normals[cell, node, d]; // // fin[cell, node, d] -= 0.5 * efp.ParameterVars_IN[0][cell, node] * n; // //} // } //} }
/// <summary> /// see <see cref="IEdgeSource_V.BoundaryEdge"/> /// </summary> void IEdgeSource_V.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray V) { InitGlobals(efp); CommonParamsBnd cp = default(CommonParamsBnd); cp.Normale = new double[D]; cp.X = new double[D]; cp.Parameters_IN = new double[NoParams]; cp.GridDat = efp.GridDat; cp.time = efp.time; var _EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over edges { cp.iEdge = efp.e0 + l; cp.EdgeTag = _EdgeTags[cp.iEdge]; for (int k = 0; k < K; k++) // loop over quadrature nodes { for (int d = 0; d < D; d++) { cp.Normale[d] = efp.Normals[l, k, d]; cp.X[d] = efp.NodesGlobal[l, k, d]; } for (int np = 0; np < NoParams; np++) { cp.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; } V[l, k] = GetSourceCoeffBnd(ref vA, ref cp); } } }
void INonlinInnerEdgeForm_V.NonlinInternalEdge_V(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot) { bool adiaWall = this.AdiabaticWall; int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); Debug.Assert(fot.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell int NumOfArguments = this.ArgumentOrdering.Count; Debug.Assert(NumOfArguments == Uin.Length); Debug.Assert(NumOfArguments == GradUin.Length); Debug.Assert(NumOfArguments == Uout.Length); Debug.Assert(NumOfArguments == GradUout.Length); double[] U_in = new double[NumOfArguments]; double[] U_ot = new double[NumOfArguments]; double[,] GradU_in = new double[dimension, NumOfArguments]; double[,] GradU_ot = new double[dimension, NumOfArguments]; int[,] E2Cl = gridDat.iGeomEdges.LogicalCellIndices; for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; //double Penalty = penalty(gridDat.Edges.CellIndices[iEdge, 0], gridDat.Edges.CellIndices[iEdge, 1], gridDat.Cells.cj); int jCellIn = E2Cl[iEdge, 0]; int jCellOut = E2Cl[iEdge, 1]; double Penalty = penaltyFactor * Math.Max(cellMetric[jCellIn], cellMetric[jCellOut]); if (EVIL_HACK_CELL_INDEX >= 0) { Penalty = penaltyFactor * cellMetric[EVIL_HACK_CELL_INDEX]; } for (int node = 0; node < NumOfNodes; node++) // loop over nodes... { for (int na = 0; na < NumOfArguments; na++) { U_in[na] = Uin[na][cell, node]; U_ot[na] = Uout[na][cell, node]; for (int d = 0; d < dimension; d++) { GradU_in[d, na] = GradUin[na][cell, node, d]; GradU_ot[d, na] = GradUout[na][cell, node, d]; } } unsafe { fixed(double *pGin = GTensorIn, pGOut = GTensorOut) { UpdateBoundaryTensorComponent(U_in, adiaWall, dimension, pGin, material, cell); UpdateBoundaryTensorComponent(U_ot, adiaWall, dimension, pGOut, material, cell); } } //UpdateTensorComponent(U_in, dimension, GTensorIn, material); //UpdateTensorComponent(U_ot, dimension, GTensorOut, material); // SIPG Flux Loops //double flux = 0.0; //for (int k = 0; k < dimension; k++) { // double nk = efp.Normals[cell, node, k]; // for (int l = 0; l < dimension; l++) { // double nl = efp.Normals[cell, node, l]; // for (int j = 0; j < NumOfArguments; j++) { // // consistency // flux -= 0.5 * (GTensorIn[k, l, j] * GradU_in[l,j] + GTensorOut[k, l, j] * GradU_ot[l,j]) * nk; // // penalty // flux += 0.5 * (GTensorIn[k, l, j] + GTensorOut[k, l, j]) * (U_in[j] - U_ot[j]) * nl * Penalty * nk; // } // } //} //fin[cell, node] += flux; //fot[cell, node] -= flux; double flux = 0.0; unsafe { fixed(double *pGin = GTensorIn, pGot = GTensorOut, pGradUin = GradU_in, pGradUot = GradU_ot, pUin = U_in, pUot = U_ot) { double *pGinVar = pGin; double *pGotVar = pGot; for (int k = 0; k < dimension; k++) { double *pGradUinVar = pGradUin; double *pGradUotVar = pGradUot; double nk = efp.Normals[cell, node, k]; for (int l = 0; l < dimension; l++) { double factor = efp.Normals[cell, node, l] * Penalty * nk; double *pUinVar = pUin; double *pUotVar = pUot; for (int j = 0; j < NumOfArguments; j++) { // consistency flux -= 0.5 * (*pGinVar * *pGradUinVar + *pGotVar * *pGradUotVar) * nk; // penalty flux += 0.5 * (*pGinVar + *pGotVar) * (*pUinVar - *pUotVar) * factor; //Increment Pointer pGinVar++; pGotVar++; pGradUinVar++; pGradUotVar++; pUinVar++; pUotVar++; } } } } } fin[cell, node] += flux; fot[cell, node] -= flux; } } }
void INonlinEdgeForm_V.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot) { InternalEdge_V(ref efp, Uin, Uout, GradUin, GradUout, fin, fot); }
void INonlinEdgeform_GradV.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot, bool adiaWall) { int L = efp.Len; Debug.Assert(fin.GetLength(0) == L); Debug.Assert(fot.GetLength(0) == L); int K = fin.GetLength(1); // no of nodes per cell int D = efp.GridDat.SpatialDimension; int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count; Debug.Assert(_NOParams == efp.ParameterVars_IN.Length); Debug.Assert(_NOParams == efp.ParameterVars_OUT.Length); int _NOargs = this.ArgumentOrdering.Count; Debug.Assert(_NOargs == Uin.Length); Debug.Assert(_NOargs == GradUin.Length); Debug.Assert(_NOargs == Uout.Length); Debug.Assert(_NOargs == GradUout.Length); CommonParams cpv; cpv.GridDat = efp.GridDat; cpv.Parameters_IN = new double[_NOParams]; cpv.Parameters_OUT = new double[_NOParams]; cpv.Normale = new double[D]; cpv.X = new double[D]; cpv.time = efp.time; double[] _GradV_in = new double[D]; double[,] _GradU_in = new double[_NOargs, D]; double[] _U_in = new double[_NOargs]; double _V_in = 0.0; double[] _GradV_ot = new double[D]; double[,] _GradU_ot = new double[_NOargs, D]; double[] _U_ot = new double[_NOargs]; double _V_ot = 0.0; for (int l = 0; l < L; l++) // loop over cells... { cpv.iEdge = efp.e0 + l; for (int k = 0; k < K; k++) // loop over nodes... { for (int np = 0; np < _NOParams; np++) { cpv.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cpv.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d = 0; d < D; d++) { cpv.Normale[d] = efp.Normals[l, k, d]; cpv.X[d] = efp.NodesGlobal[l, k, d]; } for (int na = 0; na < _NOargs; na++) { Debug.Assert((Uin[na] != null) == (Uout[na] != null)); if (Uin[na] != null) { _U_in[na] = Uin[na][l, k]; _U_ot[na] = Uout[na][l, k]; } else { _U_in[na] = 0; _U_ot[na] = 0; } Debug.Assert((GradUin[na] != null) == (GradUout[na] != null)); if (GradUin[na] != null) { for (int d = 0; d < D; d++) { _GradU_in[na, d] = GradUin[na][l, k, d]; _GradU_ot[na, d] = GradUout[na][l, k, d]; } } else { for (int d = 0; d < D; d++) { _GradU_in[na, d] = 0; _GradU_ot[na, d] = 0; } } } for (int d = 0; d < D; d++) { _GradV_in[d] = 1; fin[l, k, d] += edgeForm.InnerEdgeForm(ref cpv, _U_in, _U_ot, _GradU_in, _GradU_ot, _V_in, _V_ot, _GradV_in, _GradV_ot); _GradV_in[d] = 0; _GradV_ot[d] = 1; fot[l, k, d] += edgeForm.InnerEdgeForm(ref cpv, _U_in, _U_ot, _GradU_in, _GradU_ot, _V_in, _V_ot, _GradV_in, _GradV_ot); _GradV_ot[d] = 0; } } } }
void INonlinEdgeform_GradV.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray f) { int L = efp.Len; Debug.Assert(f.GetLength(0) == L); int K = f.GetLength(1); // no of nodes per cell int D = efp.GridDat.SpatialDimension; int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count; Debug.Assert(_NOParams == efp.ParameterVars_IN.Length); int _NOargs = this.ArgumentOrdering.Count; Debug.Assert(_NOargs == Uin.Length); Debug.Assert(_NOargs == GradUin.Length); CommonParamsBnd cpv; cpv.GridDat = efp.GridDat; cpv.Parameters_IN = new double[_NOParams]; cpv.Normale = new double[D]; cpv.X = new double[D]; cpv.time = efp.time; double[] _GradV_in = new double[D]; double[,] _GradU_in = new double[_NOargs, D]; double[] _U_in = new double[_NOargs]; double _V_in = 0.0; byte[] EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over cells... { cpv.iEdge = efp.e0 + l; cpv.EdgeTag = EdgeTags[cpv.iEdge]; for (int k = 0; k < K; k++) // loop over nodes... { for (int np = 0; np < _NOParams; np++) { cpv.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; } for (int d = 0; d < D; d++) { cpv.Normale[d] = efp.Normals[l, k, d]; cpv.X[d] = efp.NodesGlobal[l, k, d]; } for (int na = 0; na < _NOargs; na++) { if (Uin[na] != null) { _U_in[na] = Uin[na][l, k]; } else { _U_in[na] = 0; } if (GradUin[na] != null) { for (int d = 0; d < D; d++) { _GradU_in[na, d] = GradUin[na][l, k, d]; } } else { for (int d = 0; d < D; d++) { _GradU_in[na, d] = 0; } } } for (int d = 0; d < D; d++) { _GradV_in[d] = 1; f[l, k, d] += edgeForm.BoundaryEdgeForm(ref cpv, _U_in, _GradU_in, _V_in, _GradV_in); _GradV_in[d] = 0; } } } }
/// <summary> /// Reformulates the given parameters into <paramref name="efp"/>, /// <paramref name="UBoundary"/> and <paramref name="normals"/>, which /// are in the form required by /// <see cref="INonlinEdgeForm_GradV.InternalEdge"/> /// and <see cref="INonlinEdgeForm_V.InternalEdge"/> /// </summary> /// <param name="prm"></param> /// <param name="U"></param> /// <param name="GradU"></param> /// <param name="efp"></param> /// <param name="UBoundary"></param> /// <param name="normals"></param> private void AdaptParameters(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, out EdgeFormParams efp, out MultidimensionalArray[] UBoundary, out MultidimensionalArray normals) { Debug.Assert(U[0].GetLength(0) == 1, "Number of cells must be 1"); Debug.Assert(prm.Len == 1, "Number of cells must be 1"); INonlinEdgeForm_GradV flux = fluxFunction; int noOfCells = 1; int noOfNodesPerCell = prm.Xglobal.GetLength(1); UBoundary = new MultidimensionalArray[U.Length]; for (int k = 0; k < U.Length; k++) { UBoundary[k] = MultidimensionalArray.Create(noOfCells, noOfNodesPerCell); } normals = MultidimensionalArray.Create( noOfCells, noOfNodesPerCell, CompressibleEnvironment.NumberOfDimensions); Material material = speciesMap.GetMaterial(double.NaN); for (int j = 0; j < noOfNodesPerCell; j++) { double[] x = new double[CompressibleEnvironment.NumberOfDimensions]; double[] normal = new double[CompressibleEnvironment.NumberOfDimensions]; double abs = 0.0; for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { x[d] = prm.Xglobal[0, j, d]; normal[d] = prm.ParameterVars[d][0, j]; abs += normal[d] * normal[d]; } abs = Math.Sqrt(abs); Debug.Assert(abs > 1e-10, "Extremely flat level set gradient"); for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { normal[d] /= abs; } StateVector stateIn = new StateVector(material, U, 0, j, CompressibleEnvironment.NumberOfDimensions); StateVector stateBoundary = boundaryCondition.GetBoundaryState( prm.time, x, normal, stateIn); Debug.Assert(stateBoundary.IsValid, "Invalid boundary state"); double[] UBoundaryLocal = stateBoundary.ToArray(); for (int k = 0; k < U.Length; k++) { UBoundary[k][0, j] = UBoundaryLocal[k]; } for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { normals[0, j, d] = normal[d]; } } efp = new EdgeFormParams() { e0 = Math.Abs(prm.GridDat.iLogicalCells.Cells2Edges[prm.j0][0]) - 1, // THIS IS AN EVIL HACK; NEEDS TO BE CHANGED GridDat = prm.GridDat, Len = prm.Len, NodesGlobal = prm.Xglobal, Normals = normals, ParameterVars_IN = prm.ParameterVars, ParameterVars_OUT = prm.ParameterVars, time = prm.time }; }
void INonlinEdgeForm_GradV.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray f) { //Do nothing }
void INonlinEdgeForm_GradV.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fIN, MultidimensionalArray fOT) { //Do nothing }
void INonlinInnerEdgeForm_GradV.NonlinInternalEdge_GradV(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot) { bool adiaWall = this.AdiabaticWall; int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); Debug.Assert(fot.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell int NumOfArguments = this.ArgumentOrdering.Count; Debug.Assert(NumOfArguments == Uin.Length); Debug.Assert(NumOfArguments == GradUin.Length); Debug.Assert(NumOfArguments == Uout.Length); Debug.Assert(NumOfArguments == GradUout.Length); double[] U_in = new double[NumOfArguments]; double[] U_ot = new double[NumOfArguments]; for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; //double Penalty = penalty(gridDat.Edges.CellIndices[iEdge, 0], gridDat.Edges.CellIndices[iEdge, 1], gridDat.Cells.cj); for (int node = 0; node < NumOfNodes; node++) // loop over nodes... { for (int na = 0; na < NumOfArguments; na++) { U_in[na] = Uin[na][cell, node]; U_ot[na] = Uout[na][cell, node]; } unsafe { fixed(double *pGin = GTensorIn, pGOut = GTensorOut) { UpdateBoundaryTensorComponent(U_in, adiaWall, dimension, pGin, material, cell); UpdateBoundaryTensorComponent(U_ot, adiaWall, dimension, pGOut, material, cell); } } //UpdateTensorComponent(U_in, dimension, GTensorIn, material); //UpdateTensorComponent(U_ot, dimension, GTensorOut, material); //for (int k = 0; k < dimension; k++) { // for (int l = 0; l < dimension; l++) { // double n = efp.Normals[cell, node, l]; // for (int j = 0; j < NumOfArguments; j++) { // double uJump = U_in[j] - U_ot[j]; // fin[cell, node, k] -= 0.5 * GTensorIn[k, l, j] * uJump * n; // fot[cell, node, k] -= 0.5 * GTensorOut[k, l, j] * uJump * n; // } // } //} unsafe { fixed(double *pGin = GTensorIn, pGot = GTensorOut, pUin = U_in, pUot = U_ot) { double *pGinVar = pGin; double *pGotVar = pGot; for (int k = 0; k < dimension; k++) { double accIn = 0; double accOut = 0; for (int l = 0; l < dimension; l++) { double *pUinVar = pUin; double *pUotVar = pUot; double n = efp.Normals[cell, node, l]; for (int j = 0; j < NumOfArguments; j++) { double uJump = *pUinVar - *pUotVar; accIn -= 0.5 * *pGinVar * uJump * n; accOut -= 0.5 * *pGotVar * uJump * n; //Increment Pointer pGinVar++; pGotVar++; pUinVar++; pUotVar++; } } fin[cell, node, k] += accIn; fot[cell, node, k] += accOut; } } } } } }
void INonlinBoundaryEdgeForm_V.NonlinBoundaryEdge_V(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { //Do Nothing }
void INonlinInnerEdgeForm_V.NonlinInternalEdge_V(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot) { //Do nothing }
void INonlinBoundaryEdgeForm_V.NonlinBoundaryEdge_V(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell int NumOfArguments = this.ArgumentOrdering.Count; Debug.Assert(NumOfArguments == Uin.Length); Debug.Assert(NumOfArguments == GradUin.Length); double[] U_in = new double[NumOfArguments]; double[] U_ot = new double[NumOfArguments]; double[,] GradU_in = new double[dimension, NumOfArguments]; StateVector stateIn; StateVector stateOut; int[,] E2Cl = gridDat.iGeomEdges.LogicalCellIndices; for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; //double Penalty = penalty(gridDat.Edges.CellIndices[iEdge, 0], gridDat.Edges.CellIndices[iEdge, 1], gridDat.Cells.cj); int jCellIn = E2Cl[iEdge, 0]; double Penalty = penaltyFactor * cellMetric[jCellIn]; for (int node = 0; node < NumOfNodes; node++) // loop over nodes... { for (int na = 0; na < NumOfArguments; na++) { U_in[na] = Uin[na][cell, node]; for (int d = 0; d < dimension; d++) { GradU_in[d, na] = GradUin[na][cell, node, d]; } } //Preparing for BoundaryState double[] X = new double[dimension]; double[] Normale = new double[dimension]; for (int i = 0; i < dimension; i++) { X[i] = efp.Nodes[cell, node, i]; Normale[i] = efp.Normals[cell, node, i]; } stateIn = new StateVector(U_in, speciesMap.GetMaterial(double.NaN)); stateOut = boundaryMap.GetBoundaryState(efp.GridDat.iGeomEdges.EdgeTags[iEdge], 0.0, X, Normale, stateIn); U_ot = stateOut.ToArray(); bool adiabaticWall = edgeTagBool[efp.GridDat.iGeomEdges.EdgeTags[iEdge]]; unsafe { fixed(double *pGOut = GTensorOut) { UpdateBoundaryTensorComponent(U_ot, adiabaticWall, dimension, pGOut, material, cell); } } // SIPG Flux Loops //double flux = 0.0; //for (int k = 0; k < dimension; k++) { // double nk = efp.Normals[cell, node, k]; // for (int l = 0; l < dimension; l++) { // double nl = efp.Normals[cell, node, l]; // for (int j = 0; j < NumOfArguments; j++) { // // consistency // flux -= (GTensorOut[k, l, j] * GradU_in[l,j]) * nk; // // penalty // flux += (GTensorOut[k, l, j]) * (U_in[j] - U_ot[j]) * nl * Penalty * nk; // } // } //} //fin[cell, node] += flux; double flux = 0.0; unsafe { fixed(double *pGout = GTensorOut, pGradUin = GradU_in, pUin = U_in, pUot = U_ot) { double *pGoutVar = pGout; for (int k = 0; k < dimension; k++) { double *pGradUinVar = pGradUin; double nk = efp.Normals[cell, node, k]; for (int l = 0; l < dimension; l++) { double factor = efp.Normals[cell, node, l] * Penalty * nk; double *pUinVar = pUin; double *pUotVar = pUot; for (int j = 0; j < NumOfArguments; j++) { // consistency flux -= *pGoutVar * *pGradUinVar * nk; // penalty flux += *pGoutVar * (*pUinVar - *pUotVar) * factor; //Increment Pointer pGradUinVar++; pGoutVar++; pUinVar++; pUotVar++; } } } } } fin[cell, node] += flux; } } }
void INonlinBoundaryEdgeForm_GradV.NonlinBoundaryEdge_GradV(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray fin) { int NumOfCells = efp.Len; Debug.Assert(fin.GetLength(0) == NumOfCells); int NumOfNodes = fin.GetLength(1); // no of nodes per cell int NumOfArguments = this.ArgumentOrdering.Count; Debug.Assert(NumOfArguments == Uin.Length); Debug.Assert(NumOfArguments == GradUin.Length); double[] U_in = new double[NumOfArguments]; double[] U_ot = new double[NumOfArguments]; StateVector stateIn; StateVector stateOut; for (int cell = 0; cell < NumOfCells; cell++) // loop over cells... { int iEdge = efp.e0 + cell; //double Penalty = penalty(gridDat.Edges.CellIndices[iEdge, 0], gridDat.Edges.CellIndices[iEdge, 1], gridDat.Cells.cj); for (int node = 0; node < NumOfNodes; node++) // loop over nodes... { for (int na = 0; na < NumOfArguments; na++) { U_in[na] = Uin[na][cell, node]; } //Preparing for BoundaryState double[] X = new double[dimension]; double[] Normale = new double[dimension]; for (int i = 0; i < dimension; i++) { X[i] = efp.Nodes[cell, node, i]; Normale[i] = efp.Normals[cell, node, i]; } stateIn = new StateVector(U_in, speciesMap.GetMaterial(double.NaN)); stateOut = boundaryMap.GetBoundaryState(efp.GridDat.iGeomEdges.EdgeTags[iEdge], 0.0, X, Normale, stateIn); U_ot = stateOut.ToArray(); bool adiabaticWall = edgeTagBool[efp.GridDat.iGeomEdges.EdgeTags[iEdge]]; unsafe { fixed(double *pGOut = GTensorOut) { UpdateBoundaryTensorComponent(U_ot, adiabaticWall, dimension, pGOut, material, cell); } } //// Reference implementation //for (int k = 0; k < dimension; k++) { // for (int l = 0; l < dimension; l++) { // double n = efp.Normals[cell, node, l]; // for (int j = 0; j < NumOfArguments; j++) { // fin[cell, node, k] -= GTensorOut[k, l, j] * (U_in[j] - U_ot[j]) * n; // } // } //} unsafe { fixed(double *pGot = GTensorOut, gUin = U_in, gUot = U_ot) { double *pGotVar = pGot; for (int k = 0; k < dimension; k++) { for (int l = 0; l < dimension; l++) { double n = efp.Normals[cell, node, l]; double *pUinVar = gUin; double *pUotVar = gUot; for (int j = 0; j < NumOfArguments; j++) { fin[cell, node, k] -= *pGotVar * (*pUinVar - *pUotVar) * n; //Increment Pointer pGotVar++; pUinVar++; pUotVar++; } } } } } } } }