/// <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; } } } }
/// <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; } } } }
public override double BoundaryEdgeForm(ref CommonParamsBnd inp, double[] _uA, double[,] _Grad_uA, double _vA, double[] _Grad_vA) { double Acc = 0.0; double pnlty = 2 * this.GetPenalty(inp.jCellIn, -1); double nuA = this.Nu(inp.X, inp.Parameters_IN, inp.jCellIn); XDGHeatBcType edgeType = this.boundaryCondMap.EdgeTag2Type[inp.EdgeTag]; switch (edgeType) { case XDGHeatBcType.Dirichlet: Func <double[], double, double> dirichletFunction = this.boundaryCondMap.bndFunction["u"][inp.EdgeTag]; double g_D = dirichletFunction(inp.X, inp.time); for (int d = 0; d < inp.D; d++) { double nd = inp.Normal[d]; Acc += (nuA * _Grad_uA[0, d]) * (_vA) * nd; // consistency Acc += (nuA * _Grad_vA[d]) * (_uA[0] - g_D) * nd; // symmetry } Acc *= this.m_alpha; Acc -= nuA * (_uA[0] - g_D) * (_vA - 0) * pnlty; // penalty break; case XDGHeatBcType.ZeroNeumann: double g_N = 0.0; Acc += nuA * g_N * _vA * this.m_alpha; // consistency break; default: throw new NotSupportedException(); } return(Acc); }