MultidimensionalArray Compute_OrthonormalizationTrafo(int j0, int Len, int Degree) { // init // ==== int iKref = this.m_Owner.iGeomCells.GetRefElementIndex(j0); PolynomialList Polys = this.GetOrthonormalPolynomials(Degree)[iKref]; int N = Polys.Count; CellType cellType = this.m_Owner.iGeomCells.GetCellType(j0); #if DEBUG // checking for (int j = 1; j < Len; j++) { int jCell = j + j0; if (this.m_Owner.iGeomCells.GetCellType(jCell) != cellType) { throw new NotSupportedException("All cells in chunk must have same type."); } } #endif // storage for result MultidimensionalArray NonlinOrtho = MultidimensionalArray.Create(Len, N, N); if (m_Owner.iGeomCells.IsCellAffineLinear(j0)) { // affine-linear branch // ++++++++++++++++++++ MultidimensionalArray scl = this.Scaling; for (int j = 0; j < Len; j++) { int jCell = j + j0; double scl_j = scl[jCell]; for (int n = 0; n < N; n++) { NonlinOrtho[j, n, n] = scl_j; } } } else { // nonlinear cells branch // ++++++++++++++++++++++ // init // ==== var Kref = m_Owner.iGeomCells.GetRefElement(j0); int deg; // polynomial degree of integrand: Degree of Jacobi determinat + 2* degree of basis polynomials in ref.-space. { int D = m_Owner.SpatialDimension; deg = Kref.GetInterpolationDegree(cellType); if (deg > 1) { deg -= 1; } deg *= D; deg += 2 * Degree; } var qr = Kref.GetQuadratureRule((int)deg); int K = qr.NoOfNodes; // evaluate basis polys in ref space // ================================= MultidimensionalArray BasisValues = this.EvaluateBasis(qr.Nodes, Degree); Debug.Assert(BasisValues.GetLength(0) == K); if (BasisValues.GetLength(0) > N) { BasisValues = BasisValues.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, N - 1 }); } // compute \f$ A_{k n m} = \phi_{k n} \phi_{k m} w_{k} \f$ // (cell-INdependentd part of mass matrix computation) // ================================================================== MultidimensionalArray A = MultidimensionalArray.Create(K, N, N); A.Multiply(1.0, qr.Weights, BasisValues, BasisValues, 0.0, "knm", "k", "kn", "km"); // Determine mass matrix \f$ M \f$ in all cells by quadrature // \f$ M_{n m} = \sum_{k} J_k A_{k n m} \f$ // ===================================================== MultidimensionalArray J = m_Owner.JacobianDeterminat.GetValue_Cell(qr.Nodes, j0, Len); // store mass-matrix in 'NonlinOrtho' to save mem alloc NonlinOrtho.Multiply(1.0, A, J, 0.0, "jmn", "knm", "jk"); // Compute change-of-basis for all cells // (invese of cholesky) // ===================================== for (int j = 0; j < Len; j++) { MultidimensionalArray Mj = NonlinOrtho.ExtractSubArrayShallow(j, -1, -1); // mass-matrix of basis on refrence element in cell j+j0 #if DEBUG MultidimensionalArray MjClone = Mj.CloneAs(); #endif //Mj.InvertSymmetrical(); Mj.SymmetricLDLInversion(Mj, null); // clear lower triangular part // Debug.Assert(Mj.NoOfCols == N); for (int n = 1; n < N; n++) { for (int m = 0; m < n; m++) { Mj[n, m] = 0.0; } } #if DEBUG MultidimensionalArray B = NonlinOrtho.ExtractSubArrayShallow(j, -1, -1); MultidimensionalArray Bt = B.Transpose(); double MjNorm = MjClone.InfNorm(); double Bnorm = B.InfNorm(); MultidimensionalArray check = IMatrixExtensions.GEMM(Bt, MjClone, B); check.AccEye(-1.0); double checkNorm = check.InfNorm(); double RelErr = checkNorm / Math.Max(MjNorm, Bnorm); Debug.Assert(RelErr < 1.0e-5, "Fatal error in numerical orthonomalization on nonlinear cell."); #endif } } // return // ========= return(NonlinOrtho); }
/// <summary> /// Compares the cell surface and the boundary integral. /// </summary> public static void TestSealing(GridData gdat) { int J = gdat.Cells.NoOfLocalUpdatedCells; int[,] E2C = gdat.Edges.CellIndices; // // 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 = E2C[iEdge, 0]; int jCellOt = E2C[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.Cells.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> /// Checks the minimal/maximal resolution of the material sample points and add/remove sample points if necessary /// </summary> protected bool Reseeding() { bool reseed = false; double domain_shift = DomainSize; if (this is PolarFourierLevSet) { domain_shift = 0.0; } int sp = 0; int numSp = current_interfaceP.Lengths[0]; while (sp < numSp) { // determine distance between two successive points (independent var in domainsize) double dist = getDomainDistance(current_interfaceP, sp, +1); if (dist <= 2.0 * InterfaceResolution && dist >= InterfaceResolution / 2.0) { sp += 1; } else { // check for adding if (dist > 2.0 * InterfaceResolution) { Console.WriteLine("Reseeding: Adding after sp = {0}", sp); reseed = true; // add to current_interfaceP MultidimensionalArray interP_Cache = current_interfaceP.CloneAs(); current_interfaceP = MultidimensionalArray.Create(numSp + 1, 2); int dp = 0; for (int p = 0; p < numSp + 1; p++) { if (p == sp + 1) { // interpolate the new sample point if (p == numSp) { current_interfaceP[p, 0] = (interP_Cache[sp, 0] + domain_shift + interP_Cache[0, 0]) / 2; current_interfaceP[p, 1] = (interP_Cache[sp, 1] + interP_Cache[0, 1]) / 2; } else { current_interfaceP[p, 0] = (interP_Cache[sp, 0] + interP_Cache[sp + 1, 0]) / 2; current_interfaceP[p, 1] = (interP_Cache[sp, 1] + interP_Cache[sp + 1, 1]) / 2; } dp = -1; } else { current_interfaceP[p, 0] = interP_Cache[p + dp, 0]; current_interfaceP[p, 1] = interP_Cache[p + dp, 1]; } } numSp = current_interfaceP.Lengths[0]; // add to interfaceP (History) //History_MultiArray interP_historyCache = interfaceP.CloneAs(); //interfaceP.Clear(); //for (int i = 0; i <= interfaceP.m_capacity; i++) { // MultidimensionalArray item = MultidimensionalArray.Create(current_interfaceP.Lengths); // dp = 0; // for (int p = 0; p < numSp; p++) { // if (p == sp + 1) { // // interpolate the new sample point // if (p == numSp - 1) { // item[p, 0] = ((interP_historyCache[-i])[sp, 0] + domain_shift + (interP_historyCache[-i])[0, 0]) / 2; // item[p, 1] = ((interP_historyCache[-i])[sp, 1] + (interP_historyCache[-i])[0, 1]) / 2; // } else { // item[p, 0] = ((interP_historyCache[-i])[sp, 0] + (interP_historyCache[-i])[sp + 1, 0]) / 2; // item[p, 1] = ((interP_historyCache[-i])[sp, 1] + (interP_historyCache[-i])[sp + 1, 1]) / 2; // } // dp = -1; // } else { // item[p, 0] = (interP_historyCache[-i])[p + dp, 0]; // item[p, 1] = (interP_historyCache[-i])[p + dp, 1]; // } // } // interfaceP.setHistoryEntry(-i, item); //} // velocity hist //History_MultiArray velAtInter_historyCache = velocityAtInterfaceP.CloneAs(); //velocityAtInterfaceP.Clear(); //for (int i = 0; i <= velocityAtInterfaceP.m_capacity; i++) { // MultidimensionalArray item = MultidimensionalArray.Create(current_interfaceP.Lengths); // dp = 0; // for (int p = 0; p < numSp; p++) { // if (p == sp + 1) { // // interpolate the new sample point // if (p == numSp - 1) { // item[p, 1] = ((velAtInter_historyCache[-i])[sp, 0] + (velAtInter_historyCache[-i])[0, 0]) / 2; // item[p, 1] = ((velAtInter_historyCache[-i])[sp, 1] + (velAtInter_historyCache[-i])[0, 1]) / 2; // } else { // item[p, 1] = ((velAtInter_historyCache[-i])[sp, 0] + (velAtInter_historyCache[-i])[sp + 1, 0]) / 2; // item[p, 1] = ((velAtInter_historyCache[-i])[sp, 1] + (velAtInter_historyCache[-i])[sp + 1, 1]) / 2; // } // dp = -1; // } else { // item[p, 0] = (velAtInter_historyCache[-i])[p + dp, 0]; // item[p, 1] = (velAtInter_historyCache[-i])[p + dp, 1]; // } // } // velocityAtInterfaceP.setHistoryEntry(-i, item); //} // set next sample point to check sp += 2; } // check for removing if (dist < (InterfaceResolution / 2.0)) { // check which points to remove double dist_left = getDomainDistance(current_interfaceP, sp, -1); double dist_right = getDomainDistance(current_interfaceP, sp + 1, +1); int pdel = 0; if (dist_left <= dist_right) { // remove current sample point sp pdel = sp; } else { // remove the next one sp+1 pdel = sp + 1; } Console.WriteLine("Reseeding: Removing sp = {0}", pdel); reseed = true; MultidimensionalArray interP_Cache = current_interfaceP.CloneAs(); current_interfaceP = MultidimensionalArray.Create(numSp - 1, 2); int dp = 0; for (int p = 0; p < numSp - 1; p++) { if (p == pdel) { dp = +1; } current_interfaceP[p, 0] = interP_Cache[p + dp, 0]; current_interfaceP[p, 1] = interP_Cache[p + dp, 1]; } numSp = current_interfaceP.Lengths[0]; // remove in interfaceP (History) //History_MultiArray interP_historyCache = interfaceP.CloneAs(); //interfaceP.Clear(); //for (int i = 0; i <= interfaceP.m_capacity; i++) { // MultidimensionalArray item = MultidimensionalArray.Create(current_interfaceP.Lengths); // dp = 0; // for (int p = 0; p < numSp; p++) { // if (p == pdel) { // dp = +1; // } // item[p, 0] = (interP_historyCache[-i])[p + dp, 0]; // item[p, 1] = (interP_historyCache[-i])[p + dp, 1]; // } // interfaceP.setHistoryEntry(-i, item); //} // velocity hist //History_MultiArray velAtInter_historyCache = velocityAtInterfaceP.CloneAs(); //velocityAtInterfaceP.Clear(); //for (int i = 0; i <= velocityAtInterfaceP.m_capacity; i++) { // MultidimensionalArray item = MultidimensionalArray.Create(current_interfaceP.Lengths); // dp = 0; // for (int p = 0; p < numSp; p++) { // if (p == pdel) { // dp = +1; // } // item[p, 0] = (velAtInter_historyCache[-i])[p + dp, 0]; // item[p, 1] = (velAtInter_historyCache[-i])[p + dp, 1]; // } // velocityAtInterfaceP.setHistoryEntry(-i, item); //} } } } return(reseed); }