/// <summary> /// two <see cref="Basis"/>-objects are equal, if their polynomial list /// (<see cref="Polynomials"/>) is equal (equal Guid for each entry). /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { if (obj.GetType() != typeof(Basis)) { return(false); } Basis other = (Basis)obj; if (!object.ReferenceEquals(other.m_GridDat, this.m_GridDat)) { return(false); } int L = m_GridDat.iGeomCells.RefElements.Length; Debug.Assert(this.Polynomials.Count == L); Debug.Assert(other.Polynomials.Count == L); for (int l = 0; l < L; l++) { int N = this.Polynomials[l].Count; if (other.Polynomials[l].Count != N) { return(false); } for (int i = N - 1; i >= 0; i--) { if (!this.Polynomials[l][i].Equals(other.Polynomials[l][i])) { return(false); } } } return(true); }
private static void CheckArgs(int j0, int L, NodeSet NS, Basis basis, MultidimensionalArray Coördinates, MultidimensionalArray ResultAcc, out int D, out int N, out int M, out bool AffineLinear) { D = basis.GridDat.SpatialDimension; // spatial dimension N = basis.GetLength(j0); // number of coordinates per cell M = NS.NoOfNodes; // number of nodes AffineLinear = basis.GridDat.iGeomCells.IsCellAffineLinear(j0); Debug.Assert(basis.GetType() == typeof(Basis)); Debug.Assert(Coördinates.Dimension == 2); Debug.Assert(Coördinates.GetLength(0) == L); Debug.Assert(Coördinates.GetLength(1) == N); #if DEBUG for (int i = 1; i < L; i++) { int jCell = j0 + i; Debug.Assert(basis.GridDat.iGeomCells.IsCellAffineLinear(jCell) == AffineLinear); Debug.Assert(basis.GetLength(jCell) == N); } #endif }
private static void CheckArgs(int j0, int L, NodeSet NS, Basis basis, MultidimensionalArray Coördinates, MultidimensionalArray ResultAcc, out int D, out int N, out int M, out bool AffineLinear) { int[] g2l = basis.GridDat.iGeomCells.GeomCell2LogicalCell; D = basis.GridDat.SpatialDimension; // spatial dimension if (g2l == null) { N = basis.GetLength(j0); // number of coordinates per cell -- standard grid } else { N = basis.GetLength(g2l[j0]); // number of coordinates per cell -- aggregation grid } M = NS.NoOfNodes; // number of nodes AffineLinear = basis.GridDat.iGeomCells.IsCellAffineLinear(j0); Debug.Assert(basis.GetType() == typeof(Basis)); Debug.Assert(Coördinates.Dimension == 2); Debug.Assert(Coördinates.GetLength(1) == N); #if DEBUG for (int i = 1; i < L; i++) { int jCell = j0 + i; Debug.Assert(basis.GridDat.iGeomCells.IsCellAffineLinear(jCell) == AffineLinear); if (g2l == null) { Debug.Assert(basis.GetLength(jCell) == N); } else { Debug.Assert(basis.GetLength(g2l[jCell]) == N); } } #endif }
public override void GetRestrictionMatrix(BlockMsrMatrix RST, MultigridMapping mgMap, int iF) { if (!object.ReferenceEquals(mgMap.AggBasis[iF], this)) { throw new ArgumentException(); } //MsrMatrix RST = new MsrMatrix(mgMap.Partitioning, mgMap.ProblemMapping); int JAGG = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; int[] degrees = mgMap.DgDegree; int NoFld = degrees.Length; int N_rest; // = new int[NoFld]; int N_full; // = new int[NoFld]; { BoSSS.Foundation.Basis b = mgMap.ProblemMapping.BasisS[iF]; BoSSS.Foundation.Basis NxB = (b is BoSSS.Foundation.XDG.XDGBasis) ? ((BoSSS.Foundation.XDG.XDGBasis)b).NonX_Basis : b; N_rest = NxB.Polynomials[0].Where(poly => poly.AbsoluteDegree <= degrees[iF]).Count(); N_full = NxB.Length; } int mgMap_Offset = mgMap.Partitioning.i0; for (int jAgg = 0; jAgg < JAGG; jAgg++) { int[] AgCell = this.AggGrid.iLogicalCells.AggregateCellToParts[jAgg]; int K = AgCell.Length; int NoSpc_Agg = this.NoOfSpecies[jAgg]; // number of species in aggregate cell for (int iSpc_Agg = 0; iSpc_Agg < NoSpc_Agg; iSpc_Agg++) // loop over all species in aggregate cell { { // loop over DG fields in the mapping int NROW = N_rest; int NCOL = N_full; Debug.Assert(mgMap.AggBasis[iF].GetLength(jAgg, degrees[iF]) == N_rest * NoSpc_Agg); int i0Agg_Loc = mgMap.LocalUniqueIndex(iF, jAgg, N_rest * iSpc_Agg); int i0Agg = i0Agg_Loc + mgMap_Offset; Debug.Assert(i0Agg >= mgMap.Partitioning.i0); Debug.Assert(i0Agg < mgMap.Partitioning.iE); if (this.SpeciesIndexMapping[jAgg] == null) { Debug.Assert(NoSpc_Agg == 1); Debug.Assert(NoSpc_Agg == 1); // default branch: // use restriction/prolongation from un-cut basis // +++++++++++++++++++++++++++++++++++++++++++++ MultidimensionalArray Trf = base.CompositeBasis[jAgg]; for (int k = 0; k < K; k++) // loop over the cells which form the aggregated cell... { int jCell = AgCell[k]; int i0Full = mgMap.ProblemMapping.GlobalUniqueCoordinateIndex(iF, jCell, 0); var Block = Trf.ExtractSubArrayShallow(k, -1, -1); for (int nRow = 0; nRow < NROW; nRow++) { for (int nCol = 0; nCol < NCOL; nCol++) { RST[i0Agg + nRow, i0Full + nCol] = Block[nCol, nRow]; } } } } else { int NoSpc = this.NoOfSpecies[jAgg]; int[,] sim = SpeciesIndexMapping[jAgg]; Debug.Assert(sim.GetLength(0) == NoSpc); Debug.Assert(sim.GetLength(1) == K); MultidimensionalArray Trf; if (this.XCompositeBasis[jAgg] == null || this.XCompositeBasis[jAgg][iSpc_Agg] == null) { Trf = base.CompositeBasis[jAgg]; } else { Trf = this.XCompositeBasis[jAgg][iSpc_Agg]; } for (int k = 0; k < K; k++) // loop over the cells which form the aggregated cell... { int jCell = AgCell[k]; int iSpcBase = sim[iSpc_Agg, k]; if (iSpcBase < 0) { //for(int n = 0; n < N; n++) // FulCoords[k, n] = 0; } else { int i0Full = mgMap.ProblemMapping.GlobalUniqueCoordinateIndex(iF, jCell, iSpcBase * N_full); var Block = Trf.ExtractSubArrayShallow(k, -1, -1); for (int nRow = 0; nRow < NROW; nRow++) { for (int nCol = 0; nCol < NCOL; nCol++) { RST[i0Agg + nRow, i0Full + nCol] = Block[nCol, nRow]; } } } } } } } } //return RST; }
/// <summary> /// Polynomial extrapolation between cells. /// </summary> /// <param name="CellPairs"> /// A list of which cells should be extrapolated to which cells. <br/> /// 1st index: enumeration;<br/> /// 2nd index, in the range of 0 to 1: 0: cell to extrapolate from (source), i.e. values in this cell remain unchanged. /// 1: cell to extrapolate to (target), the values in this cell will be the polynomial continuation of the "cell to extrapolate from". /// </param> /// <param name="scl"> /// optional scaling for the target cells /// </param> /// <param name="beta"> /// optional input scaling scaling for the target cells /// </param> virtual public void CellExtrapolation <T, U>(int[,] CellPairs, T scl = default(T), U beta = default(U)) where T : IList <double> where U : IList <double> // { //MPICollectiveWatchDog.Watch(); if (CellPairs.GetLength(1) != 2) { throw new ArgumentOutOfRangeException("second dimension is expected to be 2!"); } //if (!SurpressMPIUpdate) // this.MPIExchange(); int Esub = CellPairs.GetLength(0); Basis B = this.Basis; int N = B.Length; int JE = this.GridDat.iLogicalCells.Count; int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (scl != null) { if (scl.Count != Esub) { throw new ArgumentException(); } } var M = MultidimensionalArray.Create(Esub, N, N); B.GetExtrapolationMatrices(CellPairs, M); double[] V = null, W = null; for (int esub = 0; esub < Esub; esub++) { var M_tmp = M.ExtractSubArrayShallow(esub, -1, -1); int jCell0 = CellPairs[esub, 0]; int jCell1 = CellPairs[esub, 1]; if (jCell0 < 0 || jCell0 >= JE) { throw new ArgumentOutOfRangeException(); } if (jCell1 < 0 || jCell1 >= J) { throw new ArgumentOutOfRangeException(); } if (!this.GridDat.iGeomCells.IsCellAffineLinear(jCell0)) { throw new NotSupportedException("Currently not supported for curved cells."); } if (!this.GridDat.iGeomCells.IsCellAffineLinear(jCell1)) { throw new NotSupportedException("Currently not supported for curved cells."); } double _scl = 1.0; if (scl != null) { _scl = scl[esub]; } double _beta = 0.0; if (beta != null) { _beta = beta[esub]; } if (esub == 0) { V = new double[this.Coordinates.NoOfCols]; W = new double[this.Coordinates.NoOfCols]; } { this.Coordinates.GetRow(jCell0, V); this.Coordinates.GetRow(jCell1, W); for (int n = 0; n < N; n++) { double acc0 = 0; for (int m = 0; m < N; m++) { acc0 += V[m] * M_tmp[n, m]; } W[n] = W[n] * _beta + acc0 * _scl; } this.Coordinates.SetRow(jCell1, W); } } }
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> /// evaluation of DG field; may be used in derived classes to implement <see cref="DGField.Evaluate(int,int,NodeSet,MultidimensionalArray,int,double)"/>. /// </summary> protected static void EvaluateInternal(int j0, int L, NodeSet NS, Basis basis, MultidimensionalArray Coördinates, int coördOffset, MultidimensionalArray ResultAcc, double ResultPreScale) { int D, N, NumNodes; bool AffineLinear; CheckArgs(j0, L, NS, basis, Coördinates, ResultAcc, out D, out N, out NumNodes, out AffineLinear); Debug.Assert(ResultAcc.Dimension == 2); Debug.Assert(L == ResultAcc.GetLength(0)); Debug.Assert(NumNodes == ResultAcc.GetLength(1)); /* * MultidimensionalArray BasisValues; * BasisValues = basis.CellEval(NS, j0, L); * Debug.Assert(BasisValues.GetLength(0) == L, "No. of. cells mismatch"); * Debug.Assert(BasisValues.GetLength(1) == M, "No. of. nodes mismatch"); * Debug.Assert(BasisValues.GetLength(2) == N, "No. of. basis elements mismatch"); * * ResultAcc.Multiply(1.0, Coördinates, BasisValues, ResultPreScale, "jm", "jn", "jmn"); */ //int[] geom2log = basis.GridDat.iGeomCells.GeomCell2LogicalCell; MultidimensionalArray BasisValues = basis.Evaluate(NS); if (L == 1 && AffineLinear) { // Special optimization for single-cell evaluation: // this happens very often for edge quadrature, so it is quite relevant. double scale0 = basis.GridDat.ChefBasis.Scaling[j0]; Debug.Assert(basis.GridDat.iGeomCells.GeomCell2LogicalCell == null || basis.GridDat.iGeomCells.GeomCell2LogicalCell[j0] == j0); MultidimensionalArray Coördinates_j; if (coördOffset == 0 && Coördinates.GetLength(0) == 1) { Coördinates_j = Coördinates; } else { Coördinates_j = Coördinates.ExtractSubArrayShallow(new int[] { coördOffset, 0 }, new int[] { coördOffset, N - 1 }); } ResultAcc.Multiply(scale0, Coördinates_j, BasisValues, ResultPreScale, ref mp_jk_jm_km); //"jk", "jm", "km"); } else { int iBuf; MultidimensionalArray trfCoördinates = TempBuffer.GetTempMultidimensionalarray(out iBuf, L, N); TransformCoördinates(j0, L, basis, Coördinates, coördOffset, N, AffineLinear, trfCoördinates); if (ResultAcc.IsContinious && trfCoördinates.IsContinious && BasisValues.IsContinious) { unsafe { fixed(double *_pResultAcc = ResultAcc.Storage, _ptrfCoördinates = trfCoördinates.Storage, _pBasisValues = BasisValues.Storage) { double *pResultAcc = _pResultAcc + ResultAcc.Index(0, 0); double *ptrfCoördinates = _ptrfCoördinates + trfCoördinates.Index(0, 0); double *pBasisValues = _pBasisValues + BasisValues.Index(0, 0); //#if DEBUG // MultidimensionalArray check = ResultAcc.CloneAs(); //#endif int _M = ResultAcc.GetLength(1); // entspricht k (node index) int _N = ResultAcc.GetLength(0); // entspricht j (cell index) int _K = BasisValues.GetLength(1); // entspricht m (DG mode index) // NOTE: dimensions in FORTRAN order: // pBasisValues : _K x _M // ptrfCoördinates : _K x _N // pResultAcc : _M x _N // // => FORTRAN GEMM // pResultAcc = pBasisValues^T * ptrfCoördinates int TRANSA = 'T'; int TRANSB = 'N'; BLAS.dgemm(TRANSA, TRANSB, _M, _N, _K, 1.0, pBasisValues, _K, ptrfCoördinates, _K, ResultPreScale, pResultAcc, _M); //#if DEBUG // check.Multiply(1.0, trfCoördinates, BasisValues, ResultPreScale, ref mp_jk_jm_km); // check.Acc(-1.0, ResultAcc); // double error = check.L2Norm(); // Console.WriteLine("GEMM error: " + error); // Debug.Assert(error < 1.0); //#endif } } } else { ResultAcc.Multiply(1.0, trfCoördinates, BasisValues, ResultPreScale, ref mp_jk_jm_km); //"jk", "jm", "km"); } TempBuffer.FreeTempBuffer(iBuf); } }
/// <summary> /// evaluation of DG field gradient; may be used in derived classes to implement <see cref="EvaluateGradient"/>. /// </summary> protected static void EvaluateGradientInternal(int j0, int L, NodeSet NS, Basis basis, MultidimensionalArray Coördinates, int coördOffset, MultidimensionalArray ResultAcc, double ResultPreScale) { int D, N, K; bool AffineLinear; CheckArgs(j0, L, NS, basis, Coördinates, ResultAcc, out D, out N, out K, out AffineLinear); Debug.Assert(ResultAcc.Dimension == 3); Debug.Assert(L == ResultAcc.GetLength(0)); Debug.Assert(K == ResultAcc.GetLength(1)); Debug.Assert(D == ResultAcc.GetLength(2)); /* * MultidimensionalArray BasisGradValues; * BasisGradValues = basis.CellEvalGradient(NS, j0, L); * * ResultAcc.Multiply(1.0, Coördinates, BasisGradValues, ResultPreScale, "jmd", "jn", "jmnd"); */ MultidimensionalArray BasisGradValues = basis.EvaluateGradient(NS); int iBuf1, iBuf2; if (AffineLinear) { // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // affine-linear-cell: // Inverse Jacobian different for each cell, but constant among nodes // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (L == 1) { // Special optimization for single-cell evaluation: // this happens very often for edge quadrature, so it is quite relevant. double scale0 = basis.GridDat.ChefBasis.Scaling[j0]; MultidimensionalArray GradientRef = TempBuffer.GetTempMultidimensionalarray(out iBuf2, L, K, D); MultidimensionalArray InvJacobi = basis.GridDat.iGeomCells.InverseTransformation.ExtractSubArrayShallow(j0, -1, -1); Debug.Assert(basis.GridDat.iGeomCells.GeomCell2LogicalCell == null || basis.GridDat.iGeomCells.GeomCell2LogicalCell[j0] == j0); MultidimensionalArray Coördinates_j; if (coördOffset == 0 && Coördinates.GetLength(0) == 1) { Coördinates_j = Coördinates; } else { Coördinates_j = Coördinates.ExtractSubArrayShallow(new int[] { coördOffset, 0 }, new int[] { coördOffset, N - 1 }); } GradientRef.Multiply(scale0, Coördinates_j, BasisGradValues, 0.0, ref mp_jke_jm_kme); // gradient in reference coördinates ResultAcc.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_jkd_ed_jke); TempBuffer.FreeTempBuffer(iBuf2); } else { MultidimensionalArray trfCoördinates = TempBuffer.GetTempMultidimensionalarray(out iBuf1, L, N); MultidimensionalArray GradientRef = TempBuffer.GetTempMultidimensionalarray(out iBuf2, L, K, D); MultidimensionalArray InvJacobi = basis.GridDat.iGeomCells.InverseTransformation.ExtractSubArrayShallow(new int[] { j0, 0, 0 }, new int[] { j0 + L - 1, D - 1, D - 1 }); TransformCoördinates(j0, L, basis, Coördinates, coördOffset, N, AffineLinear, trfCoördinates); GradientRef.Multiply(1.0, trfCoördinates, BasisGradValues, 0.0, ref mp_jke_jm_kme); // gradient in reference coördinates ResultAcc.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_jkd_jed_jke); TempBuffer.FreeTempBuffer(iBuf1); TempBuffer.FreeTempBuffer(iBuf2); } } else { // ++++++++++++++++++++++++++++++++++++++++++++++++++++++ // curved-cell: // Inverse Jacobian different for each node and each cell // ++++++++++++++++++++++++++++++++++++++++++++++++++++++ MultidimensionalArray trfCoördinates = TempBuffer.GetTempMultidimensionalarray(out iBuf1, L, N); MultidimensionalArray GradientRef = TempBuffer.GetTempMultidimensionalarray(out iBuf2, L, K, D); MultidimensionalArray InvJacobi = basis.GridDat.InverseJacobian.GetValue_Cell(NS, j0, L); TransformCoördinates(j0, L, basis, Coördinates, coördOffset, N, AffineLinear, trfCoördinates); GradientRef.Multiply(1.0, trfCoördinates, BasisGradValues, 0.0, ref mp_jke_jm_kme); // gradient in reference coördinates ResultAcc.Multiply(1.0, InvJacobi, GradientRef, ResultPreScale, ref mp_jkd_jked_jke); TempBuffer.FreeTempBuffer(iBuf1); TempBuffer.FreeTempBuffer(iBuf2); } }
private static void TransformCoördinates(int j0, int L, Basis basis, MultidimensionalArray Coördinates, int coördOffset, int N, bool AffineLinear, MultidimensionalArray trfCoördinates) { int[] geom2log = basis.GridDat.iGeomCells.GeomCell2LogicalCell; if (geom2log != null) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // aggregation grid branch -- apply index trafo to coordinates // (j0..j0+L) are geometical grid indices // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // extract trafo MultidimensionalArray trafo = basis.GridDat.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(j0, L, basis.Degree); Debug.Assert(trafo.GetLength(0) == L); if (trafo.GetLength(1) > N) { trafo = trafo.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { L - 1, N - 1, N - 1 }); } // apply trafo unsafe { fixed(int *p_geom2log = geom2log) { trfCoördinates.Multiply(1.0, trafo, Coördinates, 0.0, ref mp_jm_jmn_Tjn, p_geom2log, p_geom2log, trfPreOffset_A: 0, trfCycle_A: 0, trfPostOffset_A: 0, trfPreOffset_B: coördOffset, trfCycle_B: 1, trfPostOffset_B: 0); // geom cell to logical cell trafo for coördinates } } } else if (AffineLinear) { // +++++++++++++++++++++++++ // affine-linear grid branch // +++++++++++++++++++++++++ // extract coördinates MultidimensionalArray _Coördinates; if (coördOffset > 0 || coördOffset + L < Coördinates.GetLength(0)) { _Coördinates = Coördinates.ExtractSubArrayShallow(new[] { coördOffset, 0 }, new[] { coördOffset + L - 1, N - 1 }); } else { _Coördinates = Coördinates; } // extract trafo MultidimensionalArray scale = basis.GridDat.ChefBasis.Scaling.ExtractSubArrayShallow(new int[] { j0 }, new int[] { j0 + L - 1 }); // apply trafo trfCoördinates.Multiply(1.0, scale, _Coördinates, 0.0, ref mp_jn_j_jn); } else { // ++++++++++++++++++ // curved cell branch // ++++++++++++++++++ // extract coördinates MultidimensionalArray _Coördinates; if (coördOffset > 0 || coördOffset + L < Coördinates.GetLength(0)) { _Coördinates = Coördinates.ExtractSubArrayShallow(new[] { coördOffset, 0 }, new[] { coördOffset + L - 1, N - 1 }); } else { _Coördinates = Coördinates; } // extract trafo MultidimensionalArray trafo = basis.GridDat.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(j0, L, basis.Degree); Debug.Assert(trafo.GetLength(0) == L); if (trafo.GetLength(1) > N) { trafo = trafo.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { L - 1, N - 1, N - 1 }); } // apply trafo trfCoördinates.Multiply(1.0, trafo, _Coördinates, 0.0, ref mp_jm_jmn_jn); } }
/// <summary> /// /// </summary> /// <param name="ctx"></param> /// <param name="D"></param> /// <param name="b"></param> public Tensor2Field(Context ctx, int D, Basis b) : this(ctx, D, b, "") { }
/// <summary> /// /// </summary> /// <param name="ctx"></param> /// <param name="D"></param> /// <param name="b"></param> /// <param name="id"></param> public Tensor2Field(Context ctx, int D, Basis b, string id) { throw new NotImplementedException(); }
/// <summary> /// constructs a new field with an empty identification string /// (see <see cref="DGField.Identification"/>); Because of this, this /// field can't be used for IO; /// </summary> public SinglePhaseField(Basis __Basis) : this(__Basis, null) { }
/// <summary> /// an implementation of <see cref="FieldFactory{T}"/> that creates /// <see cref="SinglePhaseField"/>-DG-fields. /// </summary> /// <param name="__Basis">The basis that is used for this field</param> /// <param name="__Identification"> /// identification string for this field; This can be null or empty, /// however, if IO should be performed for this object, the /// identification must be unique within the given context. /// </param> /// <returns>a <see cref="SinglePhaseField"/>-instance</returns> public static SinglePhaseField Factory(Basis __Basis, String __Identification) { return(new SinglePhaseField(__Basis, __Identification)); }
/// <summary> /// ctor /// </summary> /// <param name="D"> /// number of components, i.d. dimension (see <see cref="Dim"/>) /// </param> /// <param name="b"></param> /// <param name="fac"> /// factory for the instantiation of <see cref="DGField"/>-objects; By /// the factory model, it becomes possible to use this container for /// different subclasses of <see cref="DGField"/>. /// </param> public VectorField(int D, Basis b, Func <Basis, string, T> fac) : this(D, b, "", fac) { }