/// <summary> /// Solves the Reinitialisation-problem locally, i.e. cell by cell. /// </summary> /// <param name="Accepted"> /// </param> /// <param name="Recalc"></param> /// <param name="phi_accepted"> /// Input: level-set field values for the accepted cells/vallues in these cells are unchanged on exit. /// Output: level-set-field values for cells in <see cref="Recalc"/>. /// </param> /// <param name="_sign"></param> /// <param name="gradPhi"></param> void LocalSolve(CellMask Accepted, CellMask Recalc, SinglePhaseField phi_accepted, VectorField <SinglePhaseField> gradPhi, double _sign, SinglePhaseField DiffusionCoeff) { // loop over 'Recalc' - cells... foreach (int jCell in Recalc.ItemEnum) { double mini, maxi; this.Stpw_geomSolver.Start(); this.lsGeom.LocalSolve(jCell, Accepted.GetBitMaskWithExternal(), phi_accepted, _sign, out mini, out maxi); this.Stpw_geomSolver.Stop(); this.Stpw_reinitSolver.Start(); this.lsEllipt.LocalSolve(jCell, Accepted.GetBitMaskWithExternal(), phi_accepted, gradPhi); this.Stpw_reinitSolver.Stop(); //bool q = LocalSolve_Iterative(jCell, Accepted.GetBitMask(), phi_accepted, gradPhi); //if(!q) // Console.WriteLine("Local solver not converged."); } }
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> /// Polynomial extrapolation between cells. /// </summary> /// <param name="ExtrapolateTo">contains all cells for which extrapolated values should be computed</param> /// <param name="ExtrapolateFrom">contains all cells with "known values"</param> /// <returns> /// The number of cells (locally) for which the algorithm was not able to extrapolate a value /// </returns> virtual public int CellExtrapolation(CellMask ExtrapolateTo, CellMask ExtrapolateFrom) { MPICollectiveWatchDog.Watch(); int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; int NoOfNeigh; int[] NeighIdx; int[][] CN = this.GridDat.iLogicalCells.CellNeighbours; // mark all cells in which species 'Id' is known // --------------------------------------------- BitArray ValueIsKnown = ExtrapolateFrom.GetBitMaskWithExternal().CloneAs(); CellMask _ExtrapolateTo = ExtrapolateTo.Except(ExtrapolateFrom); BitArray NeedToKnowValue = _ExtrapolateTo.GetBitMask(); this.Clear(_ExtrapolateTo); // repeat until (for species 'Id' the DOF' of) all cells // that contain (at least a fraction of) species 'Id' are known... // ------------------------------------------------------------------ int NoOfCells_ToExtrapolate = _ExtrapolateTo.NoOfItemsLocally; int NoOfCells_ExtrapolatedInSweep = 1; int sweepcnt = 0; List <double> scaling = new List <double>(); List <int[]> CellPairs = new List <int[]>(); BitArray cells_mod_in_sweep = new BitArray(J); while (true) { // MPI-parallel evaluation of termination criterion // ------------------------------------------------ int bool_LocalRun = ((NoOfCells_ToExtrapolate > 0) && (NoOfCells_ExtrapolatedInSweep > 0)) ? 1 : 0; int bool_GlobalRun = 0; unsafe { csMPI.Raw.Allreduce((IntPtr)(&bool_LocalRun), (IntPtr)(&bool_GlobalRun), 1, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.MAX, csMPI.Raw._COMM.WORLD); } if (bool_GlobalRun <= 0) { // finished on all MPI processors break; } // MPI-update before local sweep: necessary for consistent result of alg. this.MPIExchange(); if (sweepcnt > 0) { ValueIsKnown.MPIExchange(this.GridDat); } // local work // ---------- if (bool_LocalRun > 0) { sweepcnt++; NoOfCells_ExtrapolatedInSweep = 0; scaling.Clear(); CellPairs.Clear(); cells_mod_in_sweep.SetAll(false); for (int j = 0; j < J; j++) { // determine whether there is something to do for cell 'j' or not ... bool needToKnowSpecies = NeedToKnowValue[j]; bool _mustbeExtrapolated = needToKnowSpecies && !ValueIsKnown[j]; if (_mustbeExtrapolated) { // continuation for this cell is needed // ++++++++++++++++++++++++++++++++++++ // try to find a neighbour NeighIdx = CN[j].CloneAs(); NoOfNeigh = NeighIdx.Length; int FoundNeighs = 0; for (int nn = 0; nn < NoOfNeigh; nn++) { if (ValueIsKnown[NeighIdx[nn]]) { // bingo FoundNeighs++; } else { NeighIdx[nn] = -1; // not usable } } if (FoundNeighs <= 0) { // hope for better luck in next sweep continue; } //Array.Clear(u2, 0, N); for (int nn = 0; nn < NoOfNeigh; nn++) { if (NeighIdx[nn] < 0) { continue; } int _2 = j; // cell to extrapolate TO int _1 = NeighIdx[nn]; // cell to extrapolate FROM CellPairs.Add(new int[] { _1, _2 }); double ooFoundNeighs = 1.0 / (double)FoundNeighs; scaling.Add(ooFoundNeighs); } cells_mod_in_sweep[j] = true; NoOfCells_ExtrapolatedInSweep++; } } int E = CellPairs.Count; int[,] _CellPairs = new int[E, 2]; for (int e = 0; e < E; e++) { _CellPairs.SetRow(e, CellPairs[e]); } double[] preScale = new double[scaling.Count]; preScale.SetAll(1.0); this.CellExtrapolation(_CellPairs, scaling, preScale); for (int j = 0; j < J; j++) { if (cells_mod_in_sweep[j] == true) { ValueIsKnown[j] = true; } } NoOfCells_ToExtrapolate -= NoOfCells_ExtrapolatedInSweep; } } // return // ------ return(NoOfCells_ToExtrapolate); }
/// <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; } } }