static double JumpNorm(DGField f) { GridData grd = (GridData)f.GridDat; int D = grd.SpatialDimension; var e2cTrafo = grd.Edges.Edge2CellTrafos; f.MPIExchange(); double Unorm = 0; EdgeQuadrature.GetQuadrature( new int[] { D + 1 }, grd, (new EdgeQuadratureScheme()).Compile(grd, f.Basis.Degree * 2), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate NodeSet NS = QR.Nodes; EvalResult.Clear(); int NoOfNodes = NS.NoOfNodes; for (int j = 0; j < Length; j++) { int iEdge = j + i0; int jCell_IN = grd.Edges.CellIndices[iEdge, 0]; int jCell_OT = grd.Edges.CellIndices[iEdge, 1]; var uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 0 }, new int[] { j, NoOfNodes - 1, -1 }); if (jCell_OT >= 0) { int iTrafo_IN = grd.Edges.Edge2CellTrafoIndex[iEdge, 0]; int iTrafo_OT = grd.Edges.Edge2CellTrafoIndex[iEdge, 1]; MultidimensionalArray uIN = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray uOT = MultidimensionalArray.Create(1, NoOfNodes); NodeSet NS_IN = NS.GetVolumeNodeSet(grd, iTrafo_IN); NodeSet NS_OT = NS.GetVolumeNodeSet(grd, iTrafo_OT); f.Evaluate(jCell_IN, 1, NS_IN, uIN); f.Evaluate(jCell_OT, 1, NS_OT, uOT); uDiff.Acc(+1.0, uIN); uDiff.Acc(-1.0, uOT); } else { uDiff.Clear(); } } EvalResult.ApplyAll(x => x * x); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults Unorm += ResultsOfIntegration.Sum(); }).Execute(); Unorm = Unorm.MPISum(); return(Unorm.Sqrt()); }
/// <summary> /// Change-of-basis, in cell 0 /// </summary> /// <param name="jCell"></param> /// <param name="pl"></param> public MultidimensionalArray GetChangeofBasisMatrix(int jCell, PolynomialList pl) { var m_Context = this.GridDat; int N = this.Length; int M = pl.Count; int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (jCell < 0 || jCell >= J) { throw new ArgumentOutOfRangeException("cell index out of range"); } MultidimensionalArray Mtx = MultidimensionalArray.Create(N, M); var cellMask = new CellMask(m_Context, new[] { new Chunk() { i0 = jCell, Len = 1 } }, MaskType.Geometrical); // we project the basis function from 'jCell1' onto 'jCell0' CellQuadrature.GetQuadrature(new int[2] { N, M }, m_Context, (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree + pl.MaxAbsoluteDegree), // integrate over target cell delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) { NodeSet nodes_Cell0 = QR.Nodes; Debug.Assert(Length == 1); //NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); //m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0); //var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); //m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null); //nodes_Cell1.LockForever(); var phi_0 = this.CellEval(nodes_Cell0, jCell, 1).ExtractSubArrayShallow(0, -1, -1); MultidimensionalArray R = MultidimensionalArray.Create(QR.NoOfNodes, pl.Count); pl.Evaluate(nodes_Cell0, R); var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1); EvalResult.Multiply(1.0, R, phi_0, 0.0, "knm", "km", "kn"); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { Debug.Assert(Length == 1); var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1); Mtx.Clear(); Mtx.Acc(1.0, res); }).Execute(); return(Mtx); }
private MultidimensionalArray EdgeQuadrature(ICompositeQuadRule <QuadRule> surfRule) { int E = this.GridData.iLogicalEdges.Count; var ret = MultidimensionalArray.Create(E); BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature( new int[] { 1 }, this.GridData, surfRule, delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults ret.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }) .Set(ResultsOfIntegration.ExtractSubArrayShallow(-1, 0)); }).Execute(); return(ret); }
void OrthonormalityTest() { Basis B = f1.Basis; int N = B.Length; var Mtx = new FullMatrix(N, N); double TotErrSum = 0.0; CellQuadrature.GetQuadrature(new int[] { N, N }, this.GridDat, (new CellQuadratureScheme(true)).Compile(GridDat, Math.Min(B.Degree * 2, 16)), delegate(MultidimensionalArray NodesUntransformed, int iKref) { var ret = new NodeSetController.NodeSetContainer[] { GridDat.NSC.CreateContainer(NodesUntransformed, iKref) }; return(ret); }, delegate(int i0, int Length, int NoOfNodes, MultidimensionalArray EvalResult) { // void Del_Evaluate var BasisVal = B.CellEval(0, i0, Length); EvalResult.Multiply(1.0, BasisVal, BasisVal, 0.0, "jknm", "jkn", "jkm"); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults for (int i = 0; i < Length; i++) { var MassMtx = ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1); double errsum = 0; for (int n = 0; n < N; n++) { for (int m = 0; m < N; m++) { double soll = (n == m) ? 1.0 : 0.0; errsum += Math.Abs(MassMtx[m, n] - soll); } } TotErrSum += errsum; } }).Execute(); Console.WriteLine("orthonormality error sum:" + TotErrSum); }
private MultidimensionalArray CellQuadrature(ICompositeQuadRule <QuadRule> surfRule) { int J = this.GridData.iLogicalCells.NoOfLocalUpdatedCells; var ret = MultidimensionalArray.Create(J); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, this.GridData, surfRule, delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate //Integrand.Evaluate(i0, Length, 0, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults var A = ret.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }); var B = ResultsOfIntegration.ExtractSubArrayShallow(-1, 0); A.Set(B); }).Execute(); return(ret); }
MultidimensionalArray StokesAnsatzRHS(Basis TestBasis, CellBoundaryQuadratureScheme cellBndSchme, CellMask _mask, int order) { var GridDat = this.tracker.GridDat; CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null; int N = TestBasis.Length; int D = GridDat.SpatialDimension; MultidimensionalArray RHS = MultidimensionalArray.Create(D, N, _mask.NoOfItemsLocally); double[] CellN = new double[D]; // cell normal double[] SurfN = new double[D]; // level-set normal double[] OutwardTang = new double[D]; // level-set tangent, outward of cell if (D != 2) { throw new NotSupportedException("Currently only supported for spatial dimension of 2."); } //MultidimensionalArray Nudes = null; int jSgrd = 0; qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { D, N }, GridDat, cellBndSchme.Compile(GridDat, order), delegate(int i0, int Length, CellBoundaryQuadRule NS, MultidimensionalArray EvalResult) { // Evaluate //MultidimensionalArray BasisValues = TestBasis.Evaluate(0); // reference //var LSNormals = LsTrk.GetLevelSetReferenceNormals(iLevSet, 0, i0, Length); // reference MultidimensionalArray BasisValues = TestBasis.CellEval(NS.Nodes, i0, Length); // physical MultidimensionalArray LSNormals = this.LevelSetData.GetLevelSetNormals(NS.Nodes, i0, Length); // physical for (int i = 0; i < Length; i++) // loop over cells //if(i0 + i == 1) { // EvalResult.ExtractSubArrayShallow(i, -1, -1, -1).Clear(); // continue; //} { CellBoundaryQuadRule cR = qBnd.CurrentRule; int[] NodesPerEdge = cR.NumbersOfNodesPerFace; var Kref = cR.RefElement; int NoOfFaces = Kref.NoOfFaces; int iNode = 0; Debug.Assert(NoOfFaces == NodesPerEdge.Length); for (int e = 0; e < NoOfFaces; e++) // loop over the faces of the cell { if (NodesPerEdge[e] <= 0) { continue; } // reference: //for (int d = 0; d < D; d++) { // CellN[d] = Kref.FaceNormals[e, d]; //} // ~~~~ // physical: var FaceNodes = new NodeSet(Kref, cR.Nodes.ExtractSubArrayShallow(new int[] { iNode, 0 }, new int[] { iNode + NodesPerEdge[e] - 1, D - 1 })); var FaceNormals = MultidimensionalArray.Create(NodesPerEdge[e], D); GridDat.Edges.GetNormalsForCell(FaceNodes, i0, e, FaceNormals); // ~~~~ for (int _n = 0; _n < NodesPerEdge[e]; _n++) // loop over nodes in one edge { for (int d = 0; d < D; d++) { SurfN[d] = LSNormals[i, iNode, d]; CellN[d] = FaceNormals[_n, d]; // physical } tangente(SurfN, CellN, OutwardTang); for (int n = 0; n < N; n++) // loop over Test polynomials (the same as the basis polynomials) { for (int d = 0; d < D; d++) // loop over spatial direction { EvalResult[i, iNode, d, n] = BasisValues[i, iNode, n] * OutwardTang[d]; // physical //EvalResult[i, iNode, d, n] = BasisValues[iNode, n]*OutwardTang[d]; // reference } } iNode++; } } Debug.Assert(iNode == EvalResult.GetLength(1)); } }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults for (int i = 0; i < Length; i++) { var ResPart = RHS.ExtractSubArrayShallow(new int[] { 0, 0, jSgrd }, new int[] { D - 1, N - 1, jSgrd - 1 }); int NoOfFaces = ResultsOfIntegration.GetLength(1); for (int e = 0; e < NoOfFaces; e++) { var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0, 0 }, new int[] { i - 1, e - 1, D - 1, N - 1 }); ResPart.Acc(1.0, ip); } jSgrd++; } }, cs : CoordinateSystem.Physical); qBnd.Execute(); var ret = RHS.ResizeShallow(N * D, _mask.NoOfItemsLocally); return(ret); }
protected MultidimensionalArray GaußAnsatzRHS(DivergenceFreeBasis TestBasis, CellBoundaryQuadratureScheme cellBndScheme, CellMask _mask, int order) { var _Context = this.tracker.GridDat; int D = this.tracker.GridDat.Grid.SpatialDimension; int N = TestBasis.Count; var coordSys = CoordinateSystem.Reference; var LsTrk = this.tracker; int Nrhs = _mask.NoOfItemsLocally; Debug.Assert(N % D == 0); N /= D; MultidimensionalArray RHS = MultidimensionalArray.Create(N, Nrhs); var splx = this.Kref; int NoOfFaces = splx.NoOfFaces; //var normals = _Context.GridDat.Normals; CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null; int jSgrd = 0; qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { N }, _Context, cellBndScheme.Compile(_Context, order), delegate(int i0, int Length, CellBoundaryQuadRule QR, MultidimensionalArray EvalResult) { // Evaluate NodeSet Nodes = QR.Nodes; MultidimensionalArray BasisValues; if (coordSys == CoordinateSystem.Physical) { //BasisValues = TestBasis.CellEval(Nodes, i0, Length); throw new NotImplementedException("todo"); } else if (coordSys == CoordinateSystem.Reference) { BasisValues = TestBasis.Values.GetValues(Nodes); } else { throw new NotImplementedException(); } for (int i = 0; i < Length; i++) // loop over cells { CellBoundaryQuadRule cR = qBnd.CurrentRule; int[] NodesPerEdge = cR.NumbersOfNodesPerFace; Debug.Assert(object.ReferenceEquals(splx, cR.RefElement)); int iNode = 0; Debug.Assert(NoOfFaces == NodesPerEdge.Length); for (int e = 0; e < NoOfFaces; e++) // loop over the faces of the cell { for (int _n = 0; _n < NodesPerEdge[e]; _n++) // loop over nodes in one edge { for (int n = 0; n < N; n++) // loop over Test polynomials (the same as the basis polynomials) { double acc = 0; for (int d = 0; d < D; d++) // loop over spatial directions { if (coordSys == CoordinateSystem.Physical) { throw new NotImplementedException("todo"); //int q = _Context.GridDat.LocalCellIndexToEdges[i+i0, e]; //int iEdge = Math.Abs(q) - 1; //double Nsign = Math.Sign(q); //double Nd = normals[iEdge, d]; //EvalResult[i, iNode, n, d] = BasisValues[i, iNode, n]*Nd*Nsign; } else { Debug.Assert(coordSys == CoordinateSystem.Reference); double Nd = splx.FaceNormals[e, d]; //Debug.Assert(Nd == normals[iEdge, d]*Nsign); acc += BasisValues[iNode, n *D + d] * Nd; } } EvalResult[i, iNode, n] = acc; } iNode++; } } Debug.Assert(iNode == EvalResult.GetLength(1)); } }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults for (int i = 0; i < Length; i++) { var ResPart = RHS.ExtractSubArrayShallow(new int[] { 0, jSgrd }, new int[] { N - 1, jSgrd - 1 }); for (int e = 0; e < NoOfFaces; e++) { var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0 }, new int[] { i - 1, e - 1, N - 1 }); ResPart.Acc(1.0, ip); } jSgrd++; } }, cs : coordSys); qBnd.Execute(); return(RHS); }
/// <summary> /// computes derivatives in various ways and compares them against known values. /// </summary> protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { base.EndTime = 0.0; base.NoOfTimesteps = 0; int D = this.GridData.SpatialDimension; int J = this.GridData.iLogicalCells.NoOfLocalUpdatedCells; Console.WriteLine("DerivativeTest.exe, test case #" + GRID_CASE + " ******************************"); //var Fix = this.GridData.iGeomEdges.FaceIndices; //for(int iEdge = 0; iEdge < Fix.GetLength(0); iEdge++) { // Debug.Assert(Fix[iEdge, 0] >= 0); // Debug.Assert(Fix[iEdge, 1] >= 0); //} // sealing test // ================= if (this.GridData is Foundation.Grid.Classic.GridData) { TestSealing(this.GridData); } // cell volume and edge area check, if possible // =============================================== if (this.CellVolume > 0) { double err = 0; double Treshold = 1.0e-10; for (int j = 0; j < J; j++) { err += Math.Abs(this.GridData.iLogicalCells.GetCellVolume(j) - this.CellVolume); } bool passed = (err < Treshold); m_passed = m_passed && passed; Console.WriteLine("Cell volume error: " + err + " passed? " + passed); Console.WriteLine("--------------------------------------------"); } if (this.EdgeArea > 0) { double err = 0; double Treshold = 1.0e-10; int E = this.GridData.iLogicalEdges.Count; for (int e = 0; e < E; e++) { err += Math.Abs(this.GridData.iLogicalEdges.GetEdgeArea(e) - this.EdgeArea); } bool passed = (err < Treshold); m_passed = m_passed && passed; Console.WriteLine("Edge area error: " + err + " passed? " + passed); Console.WriteLine("--------------------------------------------"); } // Orthonormality of basis in physical coords // ========================================== { Basis Bs = this.f1.Basis; int N = Bs.Length; int degQuad = this.GridData.iLogicalCells.GetInterpolationDegree(0) * D + Bs.Degree + 3; int[] jG2jL = this.GridData.iGeomCells.GeomCell2LogicalCell; // mass matrix: should be identity! MultidimensionalArray MassMatrix = MultidimensionalArray.Create(J, N, N); // compute mass matrix by quadrature. var quad = CellQuadrature.GetQuadrature(new int[] { N, N }, base.GridData, (new CellQuadratureScheme()).Compile(base.GridData, degQuad), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { NodeSet QuadNodes = QR.Nodes; MultidimensionalArray BasisVals = Bs.CellEval(QuadNodes, i0, Length); EvalResult.Multiply(1.0, BasisVals, BasisVals, 0.0, "jknm", "jkn", "jkm"); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { if (jG2jL != null) { for (int i = 0; i < Length; i++) { int jG = i + i0; MassMatrix.ExtractSubArrayShallow(jG2jL[jG], -1, -1) .Acc(1.0, ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1)); } } else { MassMatrix.SetSubArray(ResultsOfIntegration, new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, N - 1, N - 1 }); } }, cs: CoordinateSystem.Physical); quad.Execute(); // check that mass matrix is Id. int MaxErrorCell = -1; double MaxError = -1; for (int j = 0; j < J; j++) { MultidimensionalArray MassMatrix_j = MassMatrix.ExtractSubArrayShallow(j, -1, -1); MassMatrix_j.AccEye(-1.0); double Norm_j = MassMatrix_j.InfNorm(); if (Norm_j > MaxError) { MaxError = Norm_j; MaxErrorCell = j; } } bool passed = (MaxError < 1.0e-8); m_passed = m_passed && passed; Console.WriteLine("Mass Matrix, maximum error in Cell #" + MaxErrorCell + ", mass matrix error norm: " + MaxError + " passed? " + passed); } // Broken Derivatives // ================= double totalVolume = (new SubGrid(CellMask.GetFullMask(this.GridData))).Volume; for (int d = 0; d < D; d++) { // compute f1Gradient_Numerical[d].Clear(); f1Gradient_Numerical[d].Derivative(1.0, f1, d); f2Gradient_Numerical[d].Clear(); f2Gradient_Numerical[d].Derivative(1.0, f2, d); // subtract analytical var Errfield1 = f1Gradient_Numerical[d].CloneAs(); Errfield1.Acc(-1, f1Gradient_Analytical[d]); var Errfield2 = f2Gradient_Numerical[d].CloneAs(); Errfield2.Acc(-1, f2Gradient_Analytical[d]); Console.WriteLine("Broken Derivatives: "); double Treshold = 1.0e-10; if (AltRefSol) { Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold } double err1_dx = Errfield1.L2Norm() / totalVolume; bool passed = (err1_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed)); double err2_dx = Errfield2.L2Norm() / totalVolume; passed = (err2_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed)); Console.WriteLine("--------------------------------------------"); } // Flux Derivatives // ================= for (int d = 0; d < D; d++) { // compute f1Gradient_Numerical[d].Clear(); f1Gradient_Numerical[d].DerivativeByFlux(1.0, f1, d); f2Gradient_Numerical[d].Clear(); f2Gradient_Numerical[d].DerivativeByFlux(1.0, f2, d); f1Gradient_Numerical[d].CheckForNanOrInf(true, true, true); f2Gradient_Numerical[d].CheckForNanOrInf(true, true, true); // subtract analytical var Errfield1 = f1Gradient_Numerical[d].CloneAs(); Errfield1.Acc(-1, f1Gradient_Analytical[d]); var Errfield2 = f2Gradient_Numerical[d].CloneAs(); Errfield2.Acc(-1, f2Gradient_Analytical[d]); Console.WriteLine("Flux Derivatives: "); double Treshold = 1.0e-10; if (AltRefSol) { Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold } double err1_dx = Errfield1.L2Norm() / totalVolume; bool passed = (err1_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed)); double err2_dx = Errfield2.L2Norm() / totalVolume; passed = (err2_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed)); Console.WriteLine("--------------------------------------------"); } // Linear flux Derivatives // ======================= for (int d = 0; d < D; d++) { double[] korrekto = f1Gradient_Numerical[d].CoordinateVector.ToArray(); // compute DerivativeByFluxLinear(f1, f1Gradient_Numerical[d], d, f1); DerivativeByFluxLinear(f2, f2Gradient_Numerical[d], d, f2); // subtract analytical var Errfield1 = f1Gradient_Numerical[d].CloneAs(); Errfield1.Acc(-1, f1Gradient_Analytical[d]); var Errfield2 = f2Gradient_Numerical[d].CloneAs(); Errfield2.Acc(-1, f2Gradient_Analytical[d]); Console.WriteLine("Linear Flux Derivatives: "); double Treshold = 1.0e-10; if (AltRefSol) { Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold } double err1_dx = Errfield1.L2Norm() / totalVolume; bool passed = (err1_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed)); double err2_dx = Errfield2.L2Norm() / totalVolume; passed = (err2_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed)); Console.WriteLine("--------------------------------------------"); } // Laplacian, nonlinear // ==================== if (!AltRefSol) { var Laplace = (new ipLaplace()).Operator(1); Laplace.Evaluate(new DGField[] { this.f1 }, new DGField[] { this.Laplace_f1_Numerical }); Laplace.Evaluate(new DGField[] { this.f2 }, new DGField[] { this.Laplace_f2_Numerical }); double Treshold = 1.0e-8; // subtract analytical var Errfield1 = Laplace_f1_Numerical.CloneAs(); Errfield1.Acc(-1, Laplace_f1_Analytical); var Errfield2 = Laplace_f2_Numerical.CloneAs(); Errfield2.Acc(-1, Laplace_f2_Analytical); double err_Lf1 = Errfield1.L2Norm() / totalVolume; bool passed = (err_Lf1 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf1, passed)); double err_Lf2 = Errfield2.L2Norm() / totalVolume; passed = (err_Lf2 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf2, passed)); Console.WriteLine("--------------------------------------------"); } // Laplacian, linear // ==================== if (!AltRefSol) { var Laplace = (new ipLaplace()).Operator(1); var LaplaceMtx = new BlockMsrMatrix(this.f1.Mapping, this.Laplace_f1_Numerical.Mapping); var LaplaceAffine = new double[LaplaceMtx.RowPartitioning.LocalLength]; Laplace.ComputeMatrix(this.f1.Mapping, null, this.Laplace_f1_Numerical.Mapping, LaplaceMtx, LaplaceAffine, false); this.Laplace_f1_Numerical.CoordinateVector.SetV(LaplaceAffine); LaplaceMtx.SpMV(1.0, this.f1.CoordinateVector, 1.0, this.Laplace_f1_Numerical.CoordinateVector); this.Laplace_f2_Numerical.CoordinateVector.SetV(LaplaceAffine); LaplaceMtx.SpMV(1.0, this.f2.CoordinateVector, 1.0, this.Laplace_f2_Numerical.CoordinateVector); // subtract analytical var Errfield1 = Laplace_f1_Numerical.CloneAs(); Errfield1.Acc(-1, Laplace_f1_Analytical); var Errfield2 = Laplace_f2_Numerical.CloneAs(); Errfield2.Acc(-1, Laplace_f2_Analytical); double Treshold = 1.0e-8; double err_Lf1 = Errfield1.L2Norm() / totalVolume; bool passed = (err_Lf1 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf1, passed)); double err_Lf2 = Errfield2.L2Norm() / totalVolume; passed = (err_Lf2 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf2, passed)); // comparison of finite difference Jacobian and Operator matrix if (TestFDJacobian) { this.f1.Clear(); var FDJbuilder = Laplace.GetFDJacobianBuilder(this.f1.Mapping.Fields, null, this.f1.Mapping, delegate(IEnumerable <DGField> U0, IEnumerable <DGField> Params) { return; }); var CheckMatrix = new BlockMsrMatrix(FDJbuilder.CodomainMapping, FDJbuilder.DomainMapping); var CheckAffine = new double[FDJbuilder.CodomainMapping.LocalLength]; FDJbuilder.ComputeMatrix(CheckMatrix, CheckAffine); var ErrMatrix = LaplaceMtx.CloneAs(); var ErrAffine = LaplaceAffine.CloneAs(); ErrMatrix.Acc(-1.0, CheckMatrix); ErrAffine.AccV(-1.0, CheckAffine); double LinfMtx = ErrMatrix.InfNorm(); double L2Aff = ErrAffine.L2NormPow2().MPISum().Sqrt(); bool passed1 = (LinfMtx < 1.0e-3); bool passed2 = (L2Aff < Treshold); Console.WriteLine("Finite Difference Jacobian: Matrix/Affine delta norm {0} {1}, passed? {2} {3}", LinfMtx, L2Aff, passed1, passed2); m_passed = m_passed && passed1; m_passed = m_passed && passed2; } Console.WriteLine("--------------------------------------------"); } // finally... // ================= if (m_passed) { Console.WriteLine("All tests passed. *****************************"); } else { Console.WriteLine("Some error above threshold. *******************"); } return(0.0); // return some artificial timestep }
/// <summary> /// Compares the cell surface and the boundary integral. /// </summary> public static void TestSealing(IGridData gdat) { int J = gdat.iLogicalCells.NoOfLocalUpdatedCells; int[,] E2Clog = gdat.iGeomEdges.LogicalCellIndices; // // compute cell surface via edge integrals // MultidimensionalArray CellSurf1 = MultidimensionalArray.Create(J); EdgeQuadrature.GetQuadrature(new int[] { 1 }, gdat, new EdgeQuadratureScheme().Compile(gdat, 2), delegate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult) { // evaluate EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // save results for (int i = 0; i < Length; i++) { int iEdge = i + i0; int jCellIn = E2Clog[iEdge, 0]; int jCellOt = E2Clog[iEdge, 1]; CellSurf1[jCellIn] += ResultsOfIntegration[i, 0]; if (jCellOt >= 0 && jCellOt < J) { CellSurf1[jCellOt] += ResultsOfIntegration[i, 0]; } } }).Execute(); // // compute cell surface via cell boundary integrals // var cbqs = new CellBoundaryQuadratureScheme(false, null); foreach (var Kref in gdat.iGeomCells.RefElements) { cbqs.AddFactory(new StandardCellBoundaryQuadRuleFactory(Kref)); } MultidimensionalArray CellSurf2 = MultidimensionalArray.Create(J); CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { 1 }, gdat, cbqs.Compile(gdat, 2), delegate(int i0, int Length, CellBoundaryQuadRule rule, MultidimensionalArray EvalResult) { // evaluate EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // save results int NoOfFaces = ResultsOfIntegration.GetLength(1); for (int i = 0; i < Length; i++) { int jCell = i + i0; for (int iFace = 0; iFace < NoOfFaces; iFace++) { CellSurf2[jCell] += ResultsOfIntegration[i, iFace, 0]; } } }, cs : CoordinateSystem.Physical).Execute(); // // compare // MultidimensionalArray Err = CellSurf1.CloneAs(); Err.Acc(-1.0, CellSurf2); double ErrNorm = Err.L2Norm(); double TotSurf = CellSurf1.L2Norm(); Console.WriteLine("Area Check " + Err.L2Norm()); Assert.LessOrEqual(ErrNorm / TotSurf, 1.0e-8); //for (int j = 0; j < J; j++) { // if (Err[j].Abs() >= 1.0e-6) { // Console.WriteLine("Mismatch between edge area and cell surface area in cell {0}, GlobalId {1}, No. of neighbors {3}, {2:0.####E-00}", j, gdat.CurrentGlobalIdPermutation.Values[j], Err[j], gdat.Cells.CellNeighbours[j].Length); // schas.SetMeanValue(j, 1); // } //} }
/// <summary> /// /// </summary> /// <param name="CellPairs"> /// 1st index: list of cells <br/> /// 2nd index: in {0, 1} /// </param> /// <param name="M"> /// 1st index: corresponds with 1st index of <paramref name="CellPairs"/><br/> /// 2nd index: matrix row index <br/> /// 3rd index: matrix column index /// </param> /// <param name="Minv">the inverse of <paramref name="M"/></param> /// <remarks> /// Let \f$ K_j \f$ and \f$ K_i \f$ be two different cells with a linear-affine /// transformation to the reference element. /// Here, \f$ j \f$=<paramref name="CellPairs"/>[a,0] and \f$ i \f$=<paramref name="CellPairs"/>[a,1]. /// The DG-basis in these cells can uniquely be represented as /// \f[ /// \phi_{j n} (\vec{x}) = p_n (\vec{x}) \vec{1}_{K_j} (\vec{x}) /// \textrm{ and } /// \phi_{i m} (\vec{x}) = q_m (\vec{x}) \vec{1}_{K_i} (\vec{x}) /// \f] /// where \f$ \vec{1}_X \f$ denotes the characteristic function for set \f$ X \f$ /// and \f$ p_n\f$ and \f$ p_m\f$ are polynomials. /// Then, for the output \f$ M \f$ =<paramref name="M"/>[a,-,-] fulfills /// \f[ /// \phi_{j n} + \sum_{m} M_{m n} \phi_{i m} /// = /// p_n \vec{1}_{K_j \cup K_i} /// \f] /// </remarks> public void GetExtrapolationMatrices(int[,] CellPairs, MultidimensionalArray M, MultidimensionalArray Minv = null) { var m_Context = this.GridDat; int N = this.Length; int Esub = CellPairs.GetLength(0); int JE = this.GridDat.iLogicalCells.Count; int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (CellPairs.GetLength(1) != 2) { throw new ArgumentOutOfRangeException("second dimension is expected to be 2!"); } if (M.Dimension != 3) { throw new ArgumentException(); } if (M.GetLength(0) != Esub) { throw new ArgumentException(); } if (M.GetLength(1) != N || M.GetLength(2) != N) { throw new ArgumentException(); } if (Minv != null) { if (Minv.GetLength(0) != Esub) { throw new ArgumentException(); } if (Minv.GetLength(1) != N || Minv.GetLength(2) != N) { throw new ArgumentException(); } } MultidimensionalArray NodesGlobal = new MultidimensionalArray(3); MultidimensionalArray Minv_tmp = MultidimensionalArray.Create(N, N); MultidimensionalArray M_tmp = MultidimensionalArray.Create(N, N); for (int esub = 0; esub < Esub; esub++) // loop over the cell pairs... { int jCell0 = CellPairs[esub, 0]; int jCell1 = CellPairs[esub, 1]; if (jCell0 < 0 || jCell0 >= JE) { throw new ArgumentOutOfRangeException("Cell index out of range."); } if (jCell1 < 0 || jCell1 >= JE) { throw new ArgumentOutOfRangeException("Cell index out of range."); } bool swap; if (jCell0 >= J) { //if(true) { swap = true; int a = jCell0; jCell0 = jCell1; jCell1 = a; } else { swap = false; } if (!m_Context.iGeomCells.IsCellAffineLinear(jCell0)) { throw new NotSupportedException("Currently not supported for curved cells."); } if (!m_Context.iGeomCells.IsCellAffineLinear(jCell1)) { throw new NotSupportedException("Currently not supported for curved cells."); } Debug.Assert(jCell0 < J); var cellMask = new CellMask(m_Context, new[] { new Chunk() { i0 = jCell0, Len = 1 } }, MaskType.Geometrical); // we project the basis function from 'jCell1' onto 'jCell0' CellQuadrature.GetQuadrature(new int[2] { N, N }, m_Context, (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree * 2), // integrate over target cell delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) { NodeSet nodes_Cell0 = QR.Nodes; Debug.Assert(Length == 1); NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0); var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null); nodes_Cell1.LockForever(); var phi_0 = this.CellEval(nodes_Cell0, jCell0, 1).ExtractSubArrayShallow(0, -1, -1); var phi_1 = this.CellEval(nodes_Cell1, jCell1, 1).ExtractSubArrayShallow(0, -1, -1); var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1); EvalResult.Multiply(1.0, phi_1, phi_0, 0.0, "kmn", "kn", "km"); }, /*_SaveIntegrationResults:*/ delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { Debug.Assert(Length == 1); var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1); Minv_tmp.Clear(); Minv_tmp.Acc(1.0, res); }).Execute(); // compute the inverse Minv_tmp.InvertTo(M_tmp); // store if (!swap) { M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp); if (Minv != null) { Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp); } } else { M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp); if (Minv != null) { Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp); } } } }
static internal void ComputeMassMatrixBlocks( IEnumerable <SpeciesId> _SpeciesIds, out Dictionary <SpeciesId, MassMatrixBlockContainer> Result, Basis b, XDGSpaceMetrics homie) { using (var tracer = new FuncTrace()) { if (b is XDGBasis) { throw new ArgumentException(); } var ctx = homie.GridDat; Result = new Dictionary <SpeciesId, MassMatrixBlockContainer>(); var schemeHelper = homie.XQuadSchemeHelper; int Nnx = b.Length; int quadorder = homie.CutCellQuadOrder; // define domains and allocate memory // ================================== foreach (var Species in _SpeciesIds) // loop over species... // interation dom { var _IntegrationDomain = homie.LevelSetRegions.GetSpeciesMask(Species).Intersect(homie.LevelSetRegions.GetCutCellMask()); // domain for mass-matrix blocks (include agglomeration targets) var _BlockDomain = _IntegrationDomain; //.Union(Agg.GetAgglomerator(Species).AggInfo.AllAffectedCells); // alloc mem for blocks var _MassMatrixBlocksSpc = MultidimensionalArray.Create(_BlockDomain.NoOfItemsLocally, Nnx, Nnx); // Subgrid index to cell index int[] _jSub2jCell = _BlockDomain.ItemEnum.ToArray(); // cell to subgrid index //Dictionary<int, int> _jCell2jSub; //if (Agg.GetAgglomerator(Species).AggInfo.AgglomerationPairs.Length > 0) { // _jCell2jSub = new Dictionary<int, int>(); // for (int i = 0; i < _jSub2jCell.Length; i++) { // _jCell2jSub.Add(_jSub2jCell[i], i); // } //} else { // _jCell2jSub = null; //} Result.Add(Species, new MassMatrixBlockContainer() { IntegrationDomain = _IntegrationDomain, MassMatrixBlocks = _MassMatrixBlocksSpc, //jCell2jSub = _jCell2jSub, jSub2jCell = _jSub2jCell }); } // compute blocks // ============== foreach (var Species in _SpeciesIds) { // get quad scheme CellQuadratureScheme scheme = schemeHelper.GetVolumeQuadScheme(Species, IntegrationDomain: Result[Species].IntegrationDomain); // result storage var MassMatrixBlocksSpc = Result[Species].MassMatrixBlocks; tracer.Info("mass matrix quad order: " + quadorder); // compute the products of the basis functions: int BlockCnt = -1; int[] BlockCell = Result[Species].jSub2jCell; CellMask speciesCells = homie.LevelSetRegions.GetSpeciesMask(Species); CellQuadrature.GetQuadrature( new int[] { Nnx, Nnx }, ctx, scheme.Compile(ctx, quadorder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Del_Evaluate // ~~~~~~~~~~~~~ var BasisVal = b.CellEval(QR.Nodes, i0, Length); EvalResult.Multiply(1.0, BasisVal, BasisVal, 0.0, "ikmn", "ikm", "ikn"); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // Del_SaveIntegrationResults // ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (int i = 0; i < Length; i++) { int jCell = i0 + i; BlockCnt++; // insert ID block in agglomeration target cells (if necessary): // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - var Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1); while (BlockCell[BlockCnt] < jCell) { // agglomeration source/target cell that is not cut // mass matrix is identity (full) or zero (void) Block.Clear(); if (speciesCells.Contains(BlockCell[BlockCnt])) { // cell is full for (int nn = 0; nn < Nnx; nn++) { Block[nn, nn] = 1.0; } } BlockCnt++; Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1); } // store computed block // - - - - - - - - - - - Debug.Assert(BlockCell[BlockCnt] == jCell); MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1) .Set(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1)); #if DEBUG for (int n = 0; n < Nnx; n++) { for (int m = 0; m < Nnx; m++) { Debug.Assert(Block[n, m] == Block[m, n]); } } #endif } }).Execute(); // ------------------------------------ quadrature end. BlockCnt++; while (BlockCnt < MassMatrixBlocksSpc.GetLength(0)) { // agglomeration source/target cell that is not cut // mass matrix is identity (full) or zero (void) var Block = MassMatrixBlocksSpc.ExtractSubArrayShallow(BlockCnt, -1, -1); Block.Clear(); if (speciesCells.Contains(BlockCell[BlockCnt])) { // cell is full for (int nn = 0; nn < Nnx; nn++) { Block[nn, nn] = 1.0; } } BlockCnt++; } /* * // test mass matrix for positive definiteness * { * int JSUB = MassMatrixBlocksSpc.GetLength(0); * SubGrid Idom = null; * * int failCount = 0; * var PosDefiniteTest = new FullMatrix(Nnx, Nnx); * * for (int jsub = 0; jsub < JSUB; jsub++) { * PosDefiniteTest.Clear(); * PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), 1.0); * * try { * PosDefiniteTest.Clear(); * PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), 1.0); * PosDefiniteTest.InvertSymmetrical(); * * //PosDefiniteTest.Clear(); * //PosDefiniteTest.AccEye(1.0); * //PosDefiniteTest.Acc(MassMatrixBlocksSpc.ExtractSubArrayShallow(jsub, -1, -1), -1.0); * //PosDefiniteTest.InvertSymmetrical(); * } catch (ArithmeticException ae) { * if (Idom == null) * Idom = new SubGrid(scheme.Domain); * * int jCell = Idom.SubgridIndex2LocalCellIndex[jsub]; * long Gid = Tracker.GridDat.Cells.GetCell(jCell).GlobalID; * * * double volFrac = Tracker.GetSpeciesVolume(jCell, Species)/ctx.Cells.GetCellVolume(jCell); * * var errString = string.Format("Indefinite mass matrix in cell: globalId = {0}, local index = {1}, species {2}; \n cell volume fraction: {3};\n [{4}]", Gid, jCell, Tracker.GetSpeciesName(Species), volFrac, ae.Message); * tracer.Logger.Error(errString); * //Console.WriteLine(errString); * failCount++; * } * } * * if (failCount > 0) { * var errString = string.Format("Indefinite mass matrix in {0} of {1} cut cells", failCount, JSUB); * tracer.Logger.Error(errString); * Console.WriteLine(errString); * } else { * Console.WriteLine("No indefinite mass matrix blocks"); * } * * } * // */ // backup before agglomeration (required if we wanna treat e.g. velocity in DG and pressure in XDG) //MultidimensionalArray[] massMatrixBlocksB4Agglom = new MultidimensionalArray[Result[Species].jSub2jCell.Length]; //Result[Species].MassMatrixBlocks_B4Agglom = massMatrixBlocksB4Agglom; //var _jCell2jSub = Result[Species].jCell2jSub; //int J = ctx.Cells.NoOfLocalUpdatedCells; //foreach (var pair in Agg.GetAgglomerator(Species).AggInfo.AgglomerationPairs) { // foreach (int jCell in new int[] { pair.jCellSource, pair.jCellTarget }) { // create a backup of source and target cell // if (jCell >= J) // continue; // int jSub = _jCell2jSub[jCell]; // if (massMatrixBlocksB4Agglom[jSub] == null) { // massMatrixBlocksB4Agglom[jSub] = MassMatrixBlocksSpc.ExtractSubArrayShallow(jSub, -1, -1).CloneAs(); // } // } //} // agglomeration //Agg.GetAgglomerator(Species).ManipulateMassMatrixBlocks(MassMatrixBlocksSpc, b, Result[Species].jSub2jCell, Result[Species].jCell2jSub); //throw new NotImplementedException("todo"); } } }