/// <summary> /// see <see cref="DGField.Evaluate(int,int,NodeSet,MultidimensionalArray,int,double)"/> /// </summary> override public void Evaluate(int j0, int Len, NodeSet NS, MultidimensionalArray result, int ResultIndexOffset, double ResultPreScale) { int D = GridDat.SpatialDimension; // spatial dimension int N = m_Basis.Length; // number of coordinates per cell int M = NS.NoOfNodes; // number of nodes if (result.Dimension != 2) { throw new ArgumentOutOfRangeException("result", "dimension of result array must be 2"); } if (Len > result.GetLength(0) + ResultIndexOffset) { throw new ArgumentOutOfRangeException("mismatch between Len and 0-th length of result"); } if (result.GetLength(1) != M) { throw new ArgumentOutOfRangeException(); } var coöSys = NS.GetNodeCoordinateSystem(this.GridDat); var resultAcc = result.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, M - 1 }); if (coöSys != NodeCoordinateSystem.CellCoord) { throw new ArgumentOutOfRangeException(); } var coord = m_Mda_Coordinates.ExtractSubArrayShallow(new int[] { j0, 0 }, new int[] { j0 + Len - 1, N - 1 }); DGField.EvaluateInternal(j0, Len, NS, this.m_Basis, coord, resultAcc, ResultPreScale); }
/// <summary> /// Evaluates the gradient of the field; /// </summary> /// <param name="j0">local index of the first cell to evaluate</param> /// <param name="Len">Number of cells to evaluate</param> /// <param name="NS"> /// As usual, the node set. /// </param> /// <param name="result"> /// on exit, result of the evaluations are accumulated there; /// the original content is scaled by <paramref name="ResultPreScale"/>; /// 1st index: cell index minus <paramref name="j0"/>; /// 2nd index: node index; /// 3rd index: spatial coordinate; /// </param> /// <param name="ResultCellindexOffset"> /// an offset for the first index of <paramref name="result"/>; /// </param> /// <param name="ResultPreScale"> /// see <paramref name="result"/> /// </param> public override void EvaluateGradient(int j0, int Len, NodeSet NS, MultidimensionalArray result, int ResultCellindexOffset, double ResultPreScale) { int D = GridDat.SpatialDimension; // spatial dimension int N = m_Basis.Length; // number of coordinates per cell int M = NS.NoOfNodes; // number of nodes var resultAcc = result.ExtractSubArrayShallow(new int[] { ResultCellindexOffset, 0, 0 }, new int[] { ResultCellindexOffset + Len - 1, M - 1, D - 1 }); var coöSys = NS.GetNodeCoordinateSystem(this.GridDat); if (coöSys != NodeCoordinateSystem.CellCoord) { throw new ArgumentOutOfRangeException(); } DGField.EvaluateGradientInternal(j0, Len, NS, this.m_Basis, m_Mda_Coordinates, j0, resultAcc, ResultPreScale); }
protected static void EvaluateEdgeInternal(int e0, int Len, NodeSet NS, Basis _Basis, MultidimensionalArray Coord, MultidimensionalArray valIN, MultidimensionalArray valOT, MultidimensionalArray meanValIN, MultidimensionalArray meanValOT, MultidimensionalArray gradIN, MultidimensionalArray gradOT, double ResultPreScale) { // checks and init // =============== var grd = _Basis.GridDat; int NoOfNodes = NS.NoOfNodes; bool AffineLinear = grd.iGeomEdges.IsEdgeAffineLinear(e0); Debug.Assert(NS.GetNodeCoordinateSystem(grd) == NodeCoordinateSystem.EdgeCoord); Debug.Assert(valIN == null || valIN.Dimension == 2); Debug.Assert(valOT == null || valOT.Dimension == 2); Debug.Assert(valIN == null || valIN.GetLength(0) == Len); Debug.Assert(valOT == null || valOT.GetLength(0) == Len); Debug.Assert(valIN == null || valIN.GetLength(1) == NoOfNodes); Debug.Assert(valOT == null || valOT.GetLength(1) == NoOfNodes); int[,] trfIdx = grd.iGeomEdges.Edge2CellTrafoIndex; int[,] E2Cl = grd.iGeomEdges.LogicalCellIndices; int[,] E2Cg = grd.iGeomEdges.CellIndices; // transform DG coördinates // ======================== int Nin = _Basis.GetLength(E2Cl[e0, 0]); int Not = Nin; #if DEBUG for (int e = 0; e < Len; e++) { int iEdge = e + e0; int jCellIN = E2Cl[iEdge, 0]; int jCellOT = E2Cl[iEdge, 1]; Debug.Assert(_Basis.GetLength(jCellIN) == Nin); if (jCellOT >= 0) { Debug.Assert(_Basis.GetLength(jCellOT) == Not); } } #endif int iBufIN, iBufOT = 0; MultidimensionalArray trfCoördinatesIN = TempBuffer.GetTempMultidimensionalarray(out iBufIN, Len, Nin); MultidimensionalArray trfCoördinatesOT = Not > 0 ? TempBuffer.GetTempMultidimensionalarray(out iBufOT, Len, Not) : null; TransformCoördinatesEdge(e0, Len, grd, Coord, Nin, Not, _Basis.Degree, AffineLinear, trfCoördinatesIN, trfCoördinatesOT); // Evaluate // ======== unsafe { fixed(int *pTrfIndex = trfIdx) { MultidimensionalArray BasisValues = null; Debug.Assert((valIN != null) == (valOT != null)); if (valIN != null) { // compute the values // ------------------- BasisValues = grd.ChefBasis.EdgeEval.GetValues(NS, e0, Len, _Basis.Degree); Debug.Assert(BasisValues.Dimension == 3); MultidimensionalArray BasisValuesIN, BasisValuesOT; if (BasisValues.GetLength(2) > Nin) { BasisValuesIN = BasisValues.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { BasisValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1 }); } else { BasisValuesIN = BasisValues; } if (BasisValues.GetLength(2) > Not) { if (Nin == Not) { BasisValuesOT = BasisValuesIN; } else { BasisValuesOT = BasisValues.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { BasisValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1 }); } } else { BasisValuesOT = BasisValues; } { valIN.Multiply(1.0, trfCoördinatesIN, BasisValuesIN, ResultPreScale, ref mp_ik_im_Tikm, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0); } if (Not > 0) { valOT.Multiply(1.0, trfCoördinatesOT, BasisValuesOT, ResultPreScale, ref mp_ik_im_Tikm, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0); } } Debug.Assert((meanValIN != null) == (meanValOT != null)); if (meanValIN != null) { // compute the mean values // ----------------------- var _Basis0Values = BasisValues; if (_Basis0Values == null) { _Basis0Values = grd.ChefBasis.EdgeEval.GetValues(NS, e0, Len, 0); } // assume the 0-th basis polynomial \f$ \phi_0 \f$ is constant! _Basis0Values = _Basis0Values.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { BasisValues.GetLength(0) - 1, -1, -1 }); // DG coördinates for the 0-th mode: var _trfCoördinatesIN = trfCoördinatesIN.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Len - 1, -1 }); var _trfCoördinatesOT = trfCoördinatesOT.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { Len - 1, -1 }); { meanValIN.Multiply(1.0, _trfCoördinatesIN, _Basis0Values, ResultPreScale, ref mp_i_i_Ti, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0); } if (Not > 0) { meanValOT.Multiply(1.0, _trfCoördinatesOT, _Basis0Values, ResultPreScale, ref mp_i_i_Ti, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0); } } Debug.Assert((gradIN != null) == (gradOT != null)); if (gradIN != null) { // compute gradient values // ----------------------- int D = grd.SpatialDimension; int iBuf2; MultidimensionalArray GradientRef = TempBuffer.GetTempMultidimensionalarray(out iBuf2, Len, NoOfNodes, D); MultidimensionalArray BasisGradValues = grd.ChefBasis.EdgeGradientEval.GetValues(NS, e0, Len, _Basis.Degree); Debug.Assert(BasisGradValues.Dimension == 4); MultidimensionalArray BasisGradValuesIN, BasisGradValuesOT; if (BasisGradValues.GetLength(2) > Nin) { BasisGradValuesIN = BasisGradValues.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { BasisGradValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1, D - 1 }); } else { BasisGradValuesIN = BasisGradValues; } if (BasisGradValues.GetLength(2) > Not) { if (Nin == Not) { BasisGradValuesOT = BasisGradValuesIN; } else { BasisGradValuesOT = BasisGradValues.ExtractSubArrayShallow(new int[] { 0, 0, 0, 0 }, new int[] { BasisGradValues.GetLength(0) - 1, NoOfNodes - 1, Nin - 1, D - 1 }); } } else { BasisGradValuesOT = BasisGradValues; } if (AffineLinear) { // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // affine-linear-cell: // Inverse Jacobian different for each cell, but constant among nodes // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ var InvJacobi = grd.iGeomCells.InverseTransformation; Debug.Assert(grd is Grid.Classic.GridData, "implementation only valid for classic grid"); Debug.Assert(object.ReferenceEquals(E2Cg, E2Cl)); fixed(int *pE2Cl = E2Cl) { { GradientRef.Multiply(1.0, trfCoördinatesIN, BasisGradValuesIN, 0.0, ref mp_ike_im_Tikme, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates gradIN.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_ikd_Tied_ike, pE2Cl, pE2Cl, trfPreOffset_A: (2 * e0), trfCycle_A: 2, trfPostOffset_A: 0, trfPreOffset_B: 0, trfCycle_B: 0, trfPostOffset_B: 0); } if (Not > 0) { GradientRef.Multiply(1.0, trfCoördinatesOT, BasisGradValuesOT, 0.0, ref mp_ike_im_Tikme, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates gradOT.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_ikd_Tied_ike, pE2Cl, pE2Cl, trfPreOffset_A: (2 * e0 + 1), trfCycle_A: 2, trfPostOffset_A: 0, trfPreOffset_B: 0, trfCycle_B: 0, trfPostOffset_B: 0); } } } else { // ++++++++++++++++++++++++++++++++++++++++++++++++++++++ // curved-cell: // Inverse Jacobian different for each node and each cell // ++++++++++++++++++++++++++++++++++++++++++++++++++++++ MultidimensionalArray invJacobiIN, invJacobiOT; var TiJ = grd.InverseJacobian.GetValue_EdgeDV(NS, e0, Len); invJacobiIN = TiJ.Item1; invJacobiOT = TiJ.Item2; { GradientRef.Multiply(1.0, trfCoördinatesIN, BasisGradValuesIN, 0.0, ref mp_ike_im_Tikme, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates, i.e. \f$ \nabla_{\vec{xi}} \f$ gradIN.Multiply(1.0, invJacobiIN, GradientRef, ResultPreScale, ref mp_ikd_iked_ike); // gradient in physical coördinates, i.e. \f$ \nabla_{\vec{x}}n \f$ } if (Not > 0) { GradientRef.Multiply(1.0, trfCoördinatesOT, BasisGradValuesOT, 0.0, ref mp_ike_im_Tikme, pTrfIndex, pTrfIndex, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: (2 * e0 + 1), trfCycle_B: 2, trfPostOffset_B: 0); // gradient in reference coördinates, i.e. \f$ \nabla_{\vec{xi}} \f$ gradOT.Multiply(1.0, invJacobiOT, GradientRef, ResultPreScale, ref mp_ikd_iked_ike); // gradient in physical coördinates, i.e. \f$ \nabla_{\vec{x}} \f$ } } TempBuffer.FreeTempBuffer(iBuf2); } } } TempBuffer.FreeTempBuffer(iBufIN); if (Not > 0) { TempBuffer.FreeTempBuffer(iBufOT); } /* * { * var _BasisValues = grd.ChefBasis.EdgeEval.GetValues(NS, e0, Len, _Basis.Degree); * * * var resultINAccCheck = valIN.CloneAs(); * var resultOTAccCheck = valOT.CloneAs(); * * for(int e = 0; e < Len; e++) { * int iEdge = e + e0; * int jCellIN = E2C[iEdge, 0]; * int jCellOT = E2C[iEdge, 1]; * int iTrfIN = trfIdx[iEdge, 0]; * int iTrfOT = trfIdx[iEdge, 1]; * * for(int k = 0; k < NoOfNodes; k++) { * int BN = _Basis.GetLength(jCellIN); * * resultINAccCheck[e, k] *= ResultPreScale; * resultOTAccCheck[e, k] *= ResultPreScale; * * for(int n = 0; n < BN; n++) { * double Cinerr = trfCoördinatesIN[e, n] - Coord[jCellIN, n]; * double Coterr = jCellOT >= 0 ? trfCoördinatesOT[e, n] - Coord[jCellOT, n] : 0.0; * * if(Math.Abs(Cinerr) > 1.0e-5) * Console.WriteLine("44fuckIN" + e); * if(Math.Abs(Coterr) > 1.0e-5) * Console.WriteLine("44fuckOT" + e); * * * resultINAccCheck[e, k] += Coord[jCellIN, n] * _BasisValues[iTrfIN, k, n]; * if(jCellOT >= 0) * resultOTAccCheck[e, k] += Coord[jCellOT, n] * _BasisValues[iTrfOT, k, n]; * * } * * double Vinerr = resultINAccCheck[e, k] - valIN[e, k]; * double Voterr = jCellOT >= 0 ? resultOTAccCheck[e, k] - valOT[e, k] : 0.0; * * * * if(Math.Abs(Vinerr) > 1.0e-5) * Console.WriteLine("44fuckIN" + e); * if(Math.Abs(Voterr) > 1.0e-5) * Console.WriteLine("44fuckOT" + e); * } * * } * * //resultINAcc.Set(resultINAccCheck); * //resultOTAcc.Set(resultOTAccCheck); * } */ }
/// <summary> /// Evaluates the field along edges. /// </summary> /// <param name="ResultIndexOffset"> /// An offset for the first index of <paramref name="ValueIN"/> resp. <paramref name="ValueOT"/>, /// i.e. the first result will be written to /// <paramref name="ValueIN"/>[<paramref name="ResultIndexOffset"/>,*]. /// </param> /// <param name="e0">Index of the first edge to evaluate.</param> /// <param name="Len">Number of edges to evaluate</param> /// <param name="NS"> /// nodes to evaluate at /// </param> /// <param name="ValueIN"> /// If not null, contains the following output: /// On exit, the value of the DG field at the given nodes are /// <em>accumulated</em> (!) there. Before the values are added, /// the original content is scaled by <paramref name="ResultPreScale"/>.<br/> /// The array is 2-dimensional: /// <list type="bullet"> /// <item> /// 1st index: edge index <i>j</i> - <paramref name="e0"/>; /// </item> /// <item> /// 2nd index: node index <i>k</i>, corresponds with 1st index of /// the node set <paramref name="NS"/>; /// </item> /// </list> /// </param> /// <param name="ValueOUT"> /// Same as <paramref name="ValueIN"/>. /// </param> /// <param name="MeanValueIN"> /// If not null, contains the following output: /// On exit, the mean values of the DG field at the given edges are /// <em>accumulated</em> (!) there. Before the values are added, /// the original content is scaled by <paramref name="ResultPreScale"/>.<br/> /// The array is 2-dimensional: /// <list type="bullet"> /// <item> /// 1st index: edge index <i>j</i> - <paramref name="e0"/>; /// </item> /// <item> /// 2nd index: node index <i>k</i>, corresponds with 1st index of /// the node set <paramref name="NS"/>; /// </item> /// </list> /// </param> /// <param name="MeanValueOT"> /// Same as <paramref name="MeanValueIN"/>. /// </param> /// <param name="GradientIN"> /// If not null, contains the following output: /// On exit, the value of the gradient of DG field at the given nodes /// are <em>accumulated</em> (!) there. Before the values are added, /// the original content is scaled by <paramref name="ResultPreScale"/>.<br/> /// The array is 3-dimensional: /// <list type="bullet"> /// <item> /// 1st index: edge index <i>j</i> - <paramref name="e0"/>; /// </item> /// <item> /// 2nd index: node index <i>k</i>, corresponds with 1st index of /// the node set <paramref name="NS"/>; /// </item> /// <item> /// 2rd index: spatial dimension; /// </item> /// </list> /// </param> /// <param name="GradientOT"> /// Same as <paramref name="GradientIN"/>. /// </param> /// <param name="ResultPreScale"> /// Scaling that is applied to <paramref name="ValueIN"/> and <paramref name="ValueOUT"/> before /// the field evaluation is added /// </param> public override void EvaluateEdge(int e0, int Len, NodeSet NS, MultidimensionalArray ValueIN, MultidimensionalArray ValueOT, MultidimensionalArray MeanValueIN = null, MultidimensionalArray MeanValueOT = null, MultidimensionalArray GradientIN = null, MultidimensionalArray GradientOT = null, int ResultIndexOffset = 0, double ResultPreScale = 0.0) // { int D = GridDat.SpatialDimension; // spatial dimension int N = m_Basis.Length; // number of coordinates per cell int K = NS.NoOfNodes; // number of nodes if ((ValueIN != null) != (ValueOT != null)) { throw new ArgumentException(); } if ((MeanValueIN != null) != (MeanValueOT != null)) { throw new ArgumentException(); } if ((GradientIN != null) != (GradientOT != null)) { throw new ArgumentException(); } if (ValueIN != null) { if (ValueIN.Dimension != 2) { throw new ArgumentException("result", "dimension of result array must be 2"); } if (Len > ValueIN.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (ValueIN.GetLength(1) != K) { throw new ArgumentException(); } if (ValueOT.Dimension != 2) { throw new ArgumentException("result", "dimension of result array must be 2"); } if (Len > ValueOT.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (ValueOT.GetLength(1) != K) { throw new ArgumentException(); } if (!(ResultIndexOffset == 0 && Len == ValueIN.GetLength(0))) { ValueIN = ValueIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1 }); } if (!(ResultIndexOffset == 0 && Len == ValueOT.GetLength(0))) { ValueOT = ValueOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1 }); } } if (MeanValueIN != null) { if (MeanValueIN.Dimension != 1) { throw new ArgumentException("Dimension of mean-value result array must be 1."); } if (Len > MeanValueIN.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (MeanValueOT.Dimension != 1) { throw new ArgumentException("Dimension of mean-value result array must be 1."); } if (Len > MeanValueOT.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (!(ResultIndexOffset == 0 && Len == MeanValueIN.GetLength(0))) { MeanValueIN = MeanValueIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset }, new int[] { ResultIndexOffset + Len - 1 }); } if (!(ResultIndexOffset == 0 && Len == MeanValueOT.GetLength(0))) { MeanValueOT = MeanValueOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset }, new int[] { ResultIndexOffset + Len - 1 }); } } if (GradientIN != null) { if (GradientIN.Dimension != 3) { throw new ArgumentException("Dimension of gradient result array must be 3."); } if (Len > GradientIN.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (GradientIN.GetLength(1) != K) { throw new ArgumentException(); } if (GradientIN.GetLength(2) != D) { throw new ArgumentException(); } if (GradientOT.Dimension != 3) { throw new ArgumentException("Dimension of gradient result array must be 3."); } if (Len > GradientOT.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (GradientOT.GetLength(1) != K) { throw new ArgumentException(); } if (GradientOT.GetLength(2) != D) { throw new ArgumentException(); } if (!(ResultIndexOffset == 0 && Len == GradientIN.GetLength(0))) { GradientIN = GradientIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1, D - 1 }); } if (!(ResultIndexOffset == 0 && Len == GradientOT.GetLength(0))) { GradientOT = GradientOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1, D - 1 }); } } var coöSys = NS.GetNodeCoordinateSystem(this.GridDat); if (coöSys != NodeCoordinateSystem.EdgeCoord) { throw new ArgumentOutOfRangeException(); } DGField.EvaluateEdgeInternal(e0, Len, NS, this.m_Basis, this.m_Mda_Coordinates, ValueIN, ValueOT, MeanValueIN, MeanValueOT, GradientIN, GradientOT, ResultPreScale); }