public void UpdateDomain(CellMask cm, bool RestrictToCellMask = true) { var GridDat = m_bInput.GridDat; int J = GridDat.iLogicalCells.NoOfLocalUpdatedCells; this.Domain = cm; int[][] newStencils = new int[J][]; var Mask = cm.GetBitMaskWithExternal(); foreach (int jCell in cm.ItemEnum) { int[] NeighCells, dummy; GridDat.GetCellNeighbours(jCell, GetCellNeighbours_Mode.ViaVertices, out NeighCells, out dummy); if (RestrictToCellMask == true) { NeighCells = NeighCells.Where(j => Mask[j]).ToArray(); } Array.Sort(NeighCells); int[] newStencil = ArrayTools.Cat(new int[] { jCell }, NeighCells); if (this.Stencils == null || this.Stencils[jCell] == null && newStencil.Length > 0 || !ArrayTools.AreEqual(this.Stencils[jCell], newStencil)) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // a re-computation of the aggregate cell basis is necessary // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ComputeAggregateBasis(jCell, NeighCells); } newStencils[jCell] = newStencil; } for (int j = 0; j < J; j++) { if (newStencils[j] == null && this.AggregateBasisTrafo[j] != null) { this.AggregateBasisTrafo[j] = null; } Debug.Assert((newStencils[j] == null) == (this.AggregateBasisTrafo[j] == null)); if (newStencils[j] != null) { Debug.Assert(newStencils[j].Length == this.AggregateBasisTrafo[j].GetLength(0)); } } this.Stencils = newStencils; }
/// <summary> /// /// </summary> /// <param name="output">output</param> /// <param name="cm">mask on which the filtering should be performed</param> /// <param name="input">input</param> /// <param name="mode"></param> public static void FilterStencilProjection(SinglePhaseField output, CellMask cm, SinglePhaseField input, PatchRecoveryMode mode) { var GridDat = input.GridDat; if (!object.ReferenceEquals(output.GridDat, GridDat)) { throw new ArgumentException(); } if (!object.ReferenceEquals(input.GridDat, GridDat)) { throw new ArgumentException(); } if (cm == null) { cm = CellMask.GetFullMask(GridDat); } switch (mode) { case PatchRecoveryMode.L2_unrestrictedDom: case PatchRecoveryMode.L2_restrictedDom: { var Mask = cm.GetBitMaskWithExternal(); bool RestrictToCellMask = mode == PatchRecoveryMode.L2_restrictedDom; foreach (int jCell in cm.ItemEnum) { int[] NeighCells, dummy; GridDat.GetCellNeighbours(jCell, GetCellNeighbours_Mode.ViaVertices, out NeighCells, out dummy); if (RestrictToCellMask == true) { NeighCells = NeighCells.Where(j => Mask[j]).ToArray(); } FilterStencilProjection(output, jCell, NeighCells, input); } return; } case PatchRecoveryMode.ChebychevInteroplation: { int P = input.Basis.Degree * 3; double[] ChebyNodes = ChebyshevNodes(P); NodeSet Nds = new NodeSet(GridDat.iGeomCells.RefElements[0], P, 1); Nds.SetColumn(0, ChebyNodes); Nds.LockForever(); Polynomial[] Polynomials = GetNodalPolynomials(ChebyNodes); MultidimensionalArray PolyVals = MultidimensionalArray.Create(P, P); for (int p = 0; p < P; p++) { Polynomials[p].Evaluate(PolyVals.ExtractSubArrayShallow(p, -1), Nds); for (int i = 0; i < P; i++) { Debug.Assert(Math.Abs(((i == p) ? 1.0 : 0.0) - PolyVals[p, i]) <= 1.0e-8); } } foreach (int jCell in cm.ItemEnum) { AffineTrafo T; var NodalValues = NodalPatchRecovery(jCell, ChebyNodes, input, out T); /* * MultidimensionalArray Nodes2D = MultidimensionalArray.Create(P, P, 2); * for (int i = 0; i < P; i++) { * for (int j = 0; j < P; j++) { * Nodes2D[i, j, 0] = ChebyNodes[i]; * Nodes2D[i, j, 1] = ChebyNodes[j]; * } * } * var _Nodes2D = Nodes2D.ResizeShallow(P*P, 2); * var xNodes = _Nodes2D.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { P*P - 1, 0 }); * var yNodes = _Nodes2D.ExtractSubArrayShallow(new int[] { 0, 1 }, new int[] { P*P - 1, 1 }); * int K = P*P; * * MultidimensionalArray xPolyVals = MultidimensionalArray.Create(P, K); * MultidimensionalArray yPolyVals = MultidimensionalArray.Create(P, K); * * for (int p = 0; p < P; p++) { * Polynomials[p].Evaluate(yPolyVals.ExtractSubArrayShallow(p, -1), yNodes); * Polynomials[p].Evaluate(xPolyVals.ExtractSubArrayShallow(p, -1), xNodes); * * } * * * double ERR = 0; * for (int k = 0; k < K; k++) { * * double x = xNodes[k, 0]; * double y = yNodes[k, 0]; * * double acc = 0; * double BasisHits = 0.0; * for (int i = 0; i < P; i++) { * for (int j = 0; j < P; j++) { * * bool isNode = (Math.Abs(x - ChebyNodes[i]) < 1.0e-8) && (Math.Abs(y - ChebyNodes[j]) < 1.0e-8); * double BasisSoll = isNode ? 1.0 : 0.0; * if (isNode) * Console.WriteLine(); * * double Basis_ij = xPolyVals[i, k]*yPolyVals[j, k]; * * Debug.Assert((Basis_ij - BasisSoll).Abs() < 1.0e-8); * * BasisHits += Math.Abs(Basis_ij); * * acc += Basis_ij*NodalValues[i, j]; * } * } * Debug.Assert(Math.Abs(BasisHits - 1.0) < 1.0e-8); * * * * * double soll = yNodes[k,0]; * Debug.Assert((soll - acc).Pow2() < 1.0e-7); * ERR = (soll - acc).Pow2(); * } * Console.WriteLine(ERR); */ output.ProjectField(1.0, delegate(int j0, int Len, NodeSet Nodes, MultidimensionalArray result) { var K = Nodes.NoOfNodes; MultidimensionalArray NT = T.Transform(Nodes); var xNodes = new NodeSet(null, NT.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, 0 })); var yNodes = new NodeSet(null, NT.ExtractSubArrayShallow(new int[] { 0, 1 }, new int[] { K - 1, 1 })); MultidimensionalArray xPolyVals = MultidimensionalArray.Create(P, K); MultidimensionalArray yPolyVals = MultidimensionalArray.Create(P, K); for (int p = 0; p < P; p++) { Polynomials[p].Evaluate(yPolyVals.ExtractSubArrayShallow(p, -1), yNodes); Polynomials[p].Evaluate(xPolyVals.ExtractSubArrayShallow(p, -1), xNodes); } for (int k = 0; k < K; k++) { double acc = 0; for (int i = 0; i < P; i++) { for (int j = 0; j < P; j++) { acc += xPolyVals[i, k] * yPolyVals[j, k] * NodalValues[i, j]; } } result[0, k] = acc; } }, new CellQuadratureScheme(true, new CellMask(input.GridDat, Chunk.GetSingleElementChunk(jCell)))); } return; } } }