/// <summary> /// Computes refinement and coarsening lists /// (inputs for <see cref="GridData.Adapt(IEnumerable{int}, IEnumerable{int[]}, out GridCorrelation)"/>), /// based on the max refinement level provided by the calling solver. This method is fully parallized. /// </summary> /// <param name="currentGrid"> /// </param> /// <param name="cellsToRefine"> /// Output, local indices of cells which should be refined. /// </param> /// <param name="cellsToCoarsen"> /// Output, clusters of cells (identified by local cell indices) which can be combined into coarser cells. /// </param> /// <param name="CellsMaxRefineLevel"> /// All cells, sorted in CellMask with their desired maximum level of refinement. Due to its nature as a list it is possible to define multiple different mask. /// ATTENTION: If to many CellMasks are defined the refinement algorithm might be slow. /// </param> /// <returns> /// True if any refinement or coarsening of the current grid should be performed; otherwise false. /// </returns> public static bool ComputeGridChange(GridData currentGrid, CellMask CellsNotOKToCoarsen, List <Tuple <int, BitArray> > CellsMaxRefineLevel, out List <int> cellsToRefine, out List <int[]> cellsToCoarsen) { int[][] globalCellNeigbourship = GetGlobalCellNeigbourship(currentGrid); int[] CellsWithMaxRefineLevel = GetAllCellsWithMaxRefineLevel(currentGrid, CellsMaxRefineLevel); int[] levelIndicator = GetGlobalLevelIndicator(currentGrid, CellsWithMaxRefineLevel, globalCellNeigbourship); int[] globalDesiredLevel = GetGlobalDesiredLevel(currentGrid, levelIndicator, globalCellNeigbourship); cellsToRefine = GetCellsToRefine(currentGrid, globalDesiredLevel); BitArray oK2Coarsen = GetCellsOk2Coarsen(currentGrid, CellsNotOKToCoarsen, globalDesiredLevel, globalCellNeigbourship); int[][] coarseningClusters = FindCoarseningClusters(oK2Coarsen, currentGrid); cellsToCoarsen = GetCoarseningCells(currentGrid, coarseningClusters); bool anyChangeInGrid = (cellsToRefine.Count() == 0 && cellsToCoarsen.Count() == 0) ? false : true; bool[] exchangeGridChange = anyChangeInGrid.MPIGatherO(0); exchangeGridChange = exchangeGridChange.MPIBroadcast(0); for (int m = 0; m < exchangeGridChange.Length; m++) { if (exchangeGridChange[m]) { anyChangeInGrid = true; } } return(anyChangeInGrid); }
/// <summary> /// Gets all cells to refine and writes them to a int-list. /// </summary> /// <param name="currentGrid"> /// </param> /// <param name="cellsNotOK2Coarsen"> /// A CellMask of all cells which should never be coarsend, e.g. all cut cells. /// </param> /// <param name="globalDesiredLevel"> /// The desired level of all global cells. /// </param> /// <param name="globalCellNeigbourship"> /// Jaggerd int-array where the first index refers to the current cell and the second one to the neighbour cells. /// </param> private static BitArray GetCellsOk2Coarsen(GridData currentGrid, CellMask cellsNotOK2Coarsen, int[] globalDesiredLevel, int[][] globalCellNeigbourship) { int oldJ = currentGrid.Cells.NoOfLocalUpdatedCells; BitArray oK2Coarsen = new BitArray(oldJ); Partitioning cellPartitioning = currentGrid.CellPartitioning; int i0 = cellPartitioning.i0; int myRank = currentGrid.MpiRank; int[][] cellNeighbours = currentGrid.Cells.CellNeighbours; for (int globalCellIndex = i0; globalCellIndex < i0 + oldJ; globalCellIndex++) { int localCellIndex = globalCellIndex - i0; int ActualLevel_j = currentGrid.Cells.GetCell(localCellIndex).RefinementLevel; if (ActualLevel_j > globalDesiredLevel[globalCellIndex] && globalDesiredLevel[globalCellIndex] >= globalCellNeigbourship[globalCellIndex].Select(neighbourIndex => globalDesiredLevel[neighbourIndex]).Max() - 1) { oK2Coarsen[localCellIndex] = true; } } if (cellsNotOK2Coarsen != null) { foreach (int j in cellsNotOK2Coarsen.ItemEnum) { oK2Coarsen[j] = false; } } return(oK2Coarsen); }
/// <summary> /// ctor /// </summary> /// <param name="volMask"> /// volume mask for those cells which should be contained in the subgrid /// </param> public SubGrid(CellMask volMask) { MPICollectiveWatchDog.Watch(); if (volMask.MaskType != MaskType.Logical) { throw new ArgumentException(); } this.m_VolumeMask = volMask; m_GridData = volMask.GridData; }
/// <summary> /// Computes refinement and coarsening lists /// (inputs for <see cref="GridData.Adapt(IEnumerable{int}, IEnumerable{int[]}, out GridCorrelation)"/>), /// based on a refinement indicator. If the calculation should work parallel it is recommend to use <see cref="ComputeGridChange(GridData, List{Tuple{int, CellMask}}, out List{int}, out List{int[]})"/>. /// </summary> /// <param name="currentGrid"> /// Current grid. /// </param> /// <param name="levelIndicator"> /// Mapping from (local cell index, current refinement level) to desired refinement level for the respective cell, /// see <see cref="Cell.RefinementLevel"/>. /// </param> /// <param name="cellsToRefine"> /// Output, local indices of cells which should be refined. /// </param> /// <param name="cellsToCoarsen"> /// Output, clusters of cells (identified by local cell indices) which can be combined into coarser cells. /// </param> /// <param name="CutCells"> /// If not null, a mask of cells in which coarsening is forbidden (usually cut-cells); /// </param> /// <returns> /// True if any refinement or coarsening of the current grid should be performed; otherwise false. /// </returns> public static bool ComputeGridChange(GridData currentGrid, CellMask CutCells, Func <int, int, int> levelIndicator, out List <int> cellsToRefine, out List <int[]> cellsToCoarsen) { int[][] globalCellNeigbourship = GetGlobalCellNeigbourship(currentGrid); int[] globalDesiredLevel = GetGlobalDesiredLevel(currentGrid, levelIndicator, globalCellNeigbourship); cellsToRefine = GetCellsToRefine(currentGrid, globalDesiredLevel); BitArray oK2Coarsen = GetCellsOk2Coarsen(currentGrid, CutCells, globalDesiredLevel, globalCellNeigbourship); int[][] coarseningClusters = FindCoarseningClusters(oK2Coarsen, currentGrid); cellsToCoarsen = GetCoarseningCells(currentGrid, coarseningClusters); bool anyChangeInGrid = (cellsToRefine.Count() == 0 && cellsToCoarsen.Count() == 0) ? false : true; return(anyChangeInGrid); }
/// <summary> /// Computes <see cref="SubgridIndex2LocalCellIndex"/> /// </summary> /// <returns></returns> private int[] ComputeSubgridIndex2LocalCellIndex() { MPICollectiveWatchDog.Watch(); CellMask msk = m_VolumeMask; int[] subgridIndex2LocalCellIndex = new int[msk.NoOfItemsLocally_WithExternal]; int jj = 0; foreach (Chunk c in msk.GetEnumerableWithExternal()) { for (int k = 0; k < c.Len; k++) { subgridIndex2LocalCellIndex[jj] = c.i0 + k; jj++; } } return(subgridIndex2LocalCellIndex); }
/// <summary> /// Constructor for the grid refinement controller, defines input cells /// </summary> /// <param name="currentGrid"> /// Current grid. /// </param> /// <param name="cutCells"> /// Cut cells will have always the max refinement level. Null is a valid input if no level-set is used. /// </param> /// <param name="cellsNotOK2Coarsen"> /// Cells which are not allowed to be coarsend. It is not necessary to include cut cells here, as they are handled by the cutCells CellMask. /// </param> public GridRefinementController(GridData currentGrid, CellMask cutCells, CellMask cellsNotOK2Coarsen = null) { CurrentGrid = currentGrid; CellPartitioning = CurrentGrid.CellPartitioning; LocalNumberOfCells = CurrentGrid.Cells.NoOfLocalUpdatedCells; GlobalIndexOfFirstLocalCell = CellPartitioning.i0; GlobalNumberOfCells = CellPartitioning.TotalLength; CutCells = cutCells; if (CutCells == null) { CutCells = CellMask.GetEmptyMask(CurrentGrid); } if (cellsNotOK2Coarsen == null) { cellsNotOK2Coarsen = CellMask.GetEmptyMask(CurrentGrid); } CellsNotOK2Coarsen = cellsNotOK2Coarsen.Union(CutCells).GetBitMask(); }
/// <summary> /// Converts this /// from a geometrical (<see cref="IGridData.iGeomCells"/>) mask /// to a logical (<see cref="IGridData.iLogicalCells"/>) mask. /// </summary> /// <returns></returns> public CellMask ToLogicalMask() { if (base.MaskType != MaskType.Geometrical) { throw new NotSupportedException(); } if (base.GridData is Grid.Classic.GridData || GridData.iGeomCells.GeomCell2LogicalCell == null) { // logical and geometrical cells are identical - return a clone of this mask return(new CellMask(base.GridData, base.Sequence, MaskType.Logical)); } else { int[] jG2jL = GridData.iGeomCells.GeomCell2LogicalCell; int Jl = GridData.iLogicalCells.NoOfLocalUpdatedCells; BitArray ba = new BitArray(Jl); foreach (Chunk c in this) // loop over chunks of logical cells... { for (int jG = 0; jG < c.JE; jG++) // loop over cells in chunk... { int jL = jG2jL[jG]; ba[jL] = true; } } var cmL = new CellMask(base.GridData, ba, MaskType.Logical); #if DEBUG // convert new logical mask back to geometrical and see if both masks are equal BitArray shouldBeEqual = (cmL.ToGeometicalMask()).GetBitMask(); BitArray thisMask = this.GetBitMask(); Debug.Assert(shouldBeEqual.Length == thisMask.Length); for (int j = 0; j < shouldBeEqual.Length; j++) { Debug.Assert(shouldBeEqual[j] == thisMask[j]); } #endif return(cmL); } }
/// <summary> /// see <see cref="DGField.Acc(double,DGField,Grid.CellMask)"/>; /// </summary> public override void Acc(double mult, DGField a, Grid.CellMask cm) { using (new FuncTrace()) { if (!a.Basis.Equals(this.Basis)) { throw new ArgumentException("Basis of 'a' must be equal to basis of this field", "a"); } SinglePhaseField _a = a as SinglePhaseField; if (cm == null && _a != null && this.m_Mda_Coordinates.IsContinious && _a.m_Mda_Coordinates.IsContinious) { // optimized branch // ++++++++++++++++ double[] storThis = this.m_Mda_Coordinates.Storage; double[] strOther = _a.m_Mda_Coordinates.Storage; int i0This = this.m_Mda_Coordinates.Index(0, 0); int i0Othr = _a.m_Mda_Coordinates.Index(0, 0); int N = this.Mapping.LocalLength; int inc = 1; unsafe { fixed(double *pStorThis = storThis, pStrOther = strOther) { BLAS.F77_BLAS.DAXPY(ref N, ref mult, pStrOther, ref inc, pStorThis, ref inc); } } } else { // default branch // ++++++++++++++ base.Acc(mult, a, cm); } } }
/// <summary> /// a cell is in the returned cell mask if /// it is a neighbor cell of this edge mask and if it is also neighbor of <paramref name="X"/> /// </summary> public CellMask GetAdjacentCellsCond(CellMask X) { var gridData = (Grid.Classic.GridData)(base.GridData); int J = gridData.Cells.NoOfLocalUpdatedCells; int[,] AllEdges = gridData.Edges.CellIndices; BitArray mask = new BitArray(J); BitArray Xmask = X.GetBitMaskWithExternal(); foreach (var ch in this) { int L = ch.i0 + ch.Len; for (int l = ch.i0; l < L; l++) { int cellIn = AllEdges[l, 0]; int cellOt = AllEdges[l, 1]; bool Out = (cellOt > 0 && Xmask[cellOt]); bool In_ = Xmask[cellIn]; if (!(Out || In_)) { continue; } if (cellIn < J) { mask[cellIn] = true; } if (cellOt >= 0 && cellOt < J) { mask[cellOt] = true; } } } return(new CellMask(gridData, mask, MaskType.Logical)); }
/// <summary> /// Computes refinement and coarsening lists /// (inputs for <see cref="GridData.Adapt(IEnumerable{int}, IEnumerable{int[]}, out GridCorrelation)"/>), /// based on a refinement indicator. /// </summary> /// <param name="CurrentGrid"> /// Current grid. /// </param> /// <param name="LevelIndicator"> /// Mapping from (local cell index, current refinement level) to desired refinement level for the respective cell, /// see <see cref="Cell.RefinementLevel"/>. /// </param> /// <param name="CellsToRefineList"> /// Output, local indices of cells which should be refined. /// </param> /// <param name="Coarsening"> /// Output, clusters of cells (identified by local cell indices) which can be combined into coarser cells. /// </param> /// <param name="CutCells"> /// If not null, a mask of cells in which coarsening is forbidden (usually cut-cells); /// </param> /// <returns> /// True if any refinement or coarsening of the current grid should be performed; otherwise false. /// </returns> public static bool ComputeGridChange(GridData CurrentGrid, CellMask CutCells, Func <int, int, int> LevelIndicator, out List <int> CellsToRefineList, out List <int[]> Coarsening) { int oldJ = CurrentGrid.Cells.NoOfLocalUpdatedCells; bool NoRefinement = true; int[] DesiredLevel = new int[oldJ]; for (int j = 0; j < oldJ; j++) { int CurrentLevel_j = CurrentGrid.Cells.GetCell(j).RefinementLevel; int DesiredLevel_j = LevelIndicator(j, CurrentLevel_j); if (DesiredLevel[j] < DesiredLevel_j) { DesiredLevel[j] = DesiredLevel_j; NoRefinement = false; RefineNeighboursRecursive(CurrentGrid, DesiredLevel, j, DesiredLevel_j - 1); } } BitArray Ok2Coarsen = new BitArray(oldJ); for (int j = 0; j < oldJ; j++) { int ActualLevel_j = CurrentGrid.Cells.GetCell(j).RefinementLevel; int DesiredLevel_j = DesiredLevel[j]; int[][] CellNeighbours = CurrentGrid.Cells.CellNeighbours; if (ActualLevel_j > DesiredLevel_j && DesiredLevel_j >= CellNeighbours[j].Select(cn => DesiredLevel[cn]).Max() - 1) { Ok2Coarsen[j] = true; } } if (CutCells != null) { foreach (int j in CutCells.ItemEnum) { Ok2Coarsen[j] = false; } } int[][] CClusters = FindCoarseningClusters(Ok2Coarsen, CurrentGrid); Coarsening = new List <int[]>(); int NoOfCellsToCoarsen = 0; for (int j = 0; j < oldJ; j++) { if (CClusters[j] != null) { NoOfCellsToCoarsen++; Debug.Assert(CClusters[j].Contains(j)); if (j == CClusters[j].Min()) { Coarsening.Add(CClusters[j]); } } } CellsToRefineList = new List <int>(); if ((!NoRefinement) || (Coarsening.Count > 0)) { for (int j = 0; j < oldJ; j++) { int ActualLevel_j = CurrentGrid.Cells.GetCell(j).RefinementLevel; int DesiredLevel_j = DesiredLevel[j]; if (ActualLevel_j < DesiredLevel_j) { CellsToRefineList.Add(j); } } } // If any cells which should refined are members of CutCells if (CellsToRefineList.Count == 0 && Coarsening.Count == 0) { NoRefinement = true; } return(!NoRefinement); }
/// <summary> /// Find the cell which contains some point <paramref name="pt"/>; /// If <paramref name="pt"/> is not within any cell, the cell with its /// center nearest to <paramref name="pt"/> is returned and in this /// case, <paramref name="IsInside"/> is false. /// </summary> /// <param name="pt"></param> /// <param name="GlobalId"> /// the Global ID of the found cell; /// </param> /// <param name="GlobalIndex"> /// the Global index of the found cell; /// </param> /// <param name="IsInside"> /// true, if <paramref name="pt"/> is within the cell identified by /// <paramref name="GlobalId"/>; /// otherwise, false; /// </param> /// <param name="OnThisProcess"> /// If true, the cell <paramref name="GlobalId"/> is located on the current MPI process. /// </param> /// <param name="CM"> /// optional cell mask to restrict the search region /// </param> /// <remarks> /// This operation is relatively costly, as it needs to perform a sweep /// over all cells, it should not be used for performance-critical /// tasks.<br/> /// This operation is MPI-collective, the output-values are equal on /// all MPI-processors. /// </remarks> static public void LocatePoint(this IGridData gdat, double[] pt, out long GlobalId, out long GlobalIndex, out bool IsInside, out bool OnThisProcess, CellMask CM = null) { using (new FuncTrace()) { if (pt.Length != gdat.SpatialDimension) { throw new ArgumentException("length must be equal to spatial dimension", "pt"); } ilPSP.MPICollectiveWatchDog.Watch(MPI.Wrappers.csMPI.Raw._COMM.WORLD); int MpiRank = gdat.CellPartitioning.MpiRank; int MpiSize = gdat.CellPartitioning.MpiSize; int J = gdat.iLogicalCells.NoOfLocalUpdatedCells; int D = gdat.SpatialDimension; MultidimensionalArray center = MultidimensionalArray.Create(1, 1, D); // cell center in global coordinates MultidimensionalArray _pt = MultidimensionalArray.Create(1, D); // point to search for for (int d = 0; d < D; d++) { _pt[0, d] = pt[d]; } MultidimensionalArray _pt_local = MultidimensionalArray.Create(1, 1, D); // .. in cell-local coordinate double[] pt_local = new double[D]; // sweep over locally updated cells ... // ==================================== int jL_MinDistCel = 0; // logical cell with minimum distance int jG_MinDistCel = 0; // geometrical cell with minimum distance double MinDist = double.MaxValue; int j_Within = -1; if (CM == null) { CM = CellMask.GetFullMask(gdat); } foreach (int jL in CM.ItemEnum) { foreach (int j in gdat.GetGeometricCellIndices(jL)) { // compute distance // ================ { var smplx = gdat.iGeomCells.GetRefElement(j); gdat.TransformLocal2Global(smplx.Center, j, 1, center, 0); double dist = 0; for (int d = 0; d < D; d++) { double del = pt[d] - center[0, 0, d]; dist += del * del; } dist = Math.Sqrt(dist); if (dist < MinDist) { MinDist = dist; jL_MinDistCel = jL; jG_MinDistCel = j; } } // transform back into cell // ======================== { try { gdat.TransformGlobal2Local(_pt, _pt_local, j, 1, 0); for (int d = 0; d < D; d++) { pt_local[d] = _pt_local[0, 0, d]; } var smplx = gdat.iGeomCells.GetRefElement(j); if (smplx.IsWithin(pt_local)) { j_Within = j; } } catch (ArithmeticException) { // probably outside... } } } } // ======================================== // First case: point is inside of some cell // ======================================== int lowestWithinRank = j_Within >= 0 ? MpiRank : int.MaxValue; lowestWithinRank = lowestWithinRank.MPIMin(); // lowest rank which found a cell that contains the point: // this rank will be the official finder! if (lowestWithinRank < MpiSize) { LocatPointHelper(gdat, lowestWithinRank, j_Within, out GlobalId, out GlobalIndex, out OnThisProcess); IsInside = true; return; } // ======================================== // Second case: point is outside of all cells // ======================================== double MinDistGlobal = MinDist.MPIMin(); int lowestMinimumRank = MinDistGlobal == MinDist ? MpiRank : int.MaxValue; lowestMinimumRank = lowestMinimumRank.MPIMin(); // find minimum rank on which the global minimum was reached. if (lowestMinimumRank < 0 || lowestMinimumRank >= MpiSize) { throw new ApplicationException(); } LocatPointHelper(gdat, lowestMinimumRank, jL_MinDistCel, out GlobalId, out GlobalIndex, out OnThisProcess); IsInside = false; return; } }
/// <summary> /// Returns an enumeration of geometrical cell chunks (first index an length) for a given cell mask. /// </summary> /// <param name="CM"></param> /// <param name="MaxVecLen"></param> /// <param name="ConsecutiveMask"></param> /// <returns></returns> public static IEnumerable <Tuple <int, int> > GetGeometricCellChunks(this CellMask CM, int MaxVecLen, CellInfo ConsecutiveMask = CellInfo.Undefined) { var ret = new Mask2GeomChunks_Enumable() { CM = CM, MaxVecLen = MaxVecLen, ConsecutiveMask = ConsecutiveMask }; #if DEBUG int JG = CM.GridData.iGeomCells.Count; BitArray test = new BitArray(JG); foreach (var t_i0_len in ret) { int j0 = t_i0_len.Item1; int Len = t_i0_len.Item2; var Flag_j0 = CM.GridData.iGeomCells.InfoFlags[j0] & ConsecutiveMask; for (int j = j0; j < j0 + Len; j++) { Debug.Assert(test[j] == false); // each geometric cell is touched only once. test[j] = true; var Flag_j = CM.GridData.iGeomCells.InfoFlags[j0] & ConsecutiveMask; Debug.Assert(Flag_j == Flag_j0); // each geometric cell has the same } } BitArray CMmask = CM.GetBitMask(); int[][] L2G = CM.GridData.iLogicalCells.AggregateCellToParts; for (int jL = 0; jL < CMmask.Count; jL++) { if (L2G == null || L2G[jL] == null) { int jG = jL; if (CMmask[jL] != test[jG]) { var r = new Mask2GeomChunks_Enumable() { CM = CM, MaxVecLen = MaxVecLen, ConsecutiveMask = ConsecutiveMask }; foreach (var _t_i0_len in r) { int j0 = _t_i0_len.Item1; int Len = _t_i0_len.Item2; for (int j = j0; j < j0 + Len; j++) { Console.WriteLine(j); } } Debugger.Break(); } Debug.Assert(CMmask[jL] == test[jG]); } else { foreach (int jG in L2G[jL]) { Debug.Assert(CMmask[jL] == test[jG]); } } } #endif return(ret); }
public void Dispose() { CMenum.Dispose(); CMenum = null; CM = null; // object can never be used again. }
/// <summary> /// computes a global time-step length ("delta t") according to the /// Courant-Friedrichs-Lax - criterion, based on a velocity /// vector (<paramref name="velvect"/>) and the cell size /// this.<see cref="Cells"/>.<see cref="CellData.h_min"/>; /// </summary> /// <param name="velvect"> /// components of a velocity vector /// </param> /// <param name="max"> /// an upper maximum for the return value; This is useful if the velocity /// defined by <paramref name="velvect"/> is 0 or very small everywhere; /// </param> /// <param name="cm"> /// optional restriction of domain. /// </param> /// <returns> /// the minimum (over all cells j in all processes) of <see cref="CellData.h_min"/>[j] /// over v, where v is the Euclidean norm of a vector build from /// <paramref name="velvect"/>; /// This vector is evaluated at cell center and all cell vertices. /// The return value is the same on all processes; /// </returns> static public double ComputeCFLTime <T>(this IGridData __gdat, IEnumerable <T> velvect, double max, CellMask cm = null) where T : DGField // { using (var tr = new FuncTrace()) { GridData gdat = (GridData)__gdat; ilPSP.MPICollectiveWatchDog.Watch(MPI.Wrappers.csMPI.Raw._COMM.WORLD); T[] _velvect = velvect.ToArray(); if (cm == null) { cm = CellMask.GetFullMask(gdat); } int D = gdat.SpatialDimension; var KrefS = gdat.Grid.RefElements; // find cfl number on this processor // --------------------------------- var m_CFL_EvalPoints = new NodeSet[KrefS.Length]; for (int i = 0; i < KrefS.Length; i++) { var Kref = KrefS[i]; int N = Kref.NoOfVertices + 1; MultidimensionalArray vert = MultidimensionalArray.Create(N, D); vert.SetSubArray(Kref.Vertices, new int[] { 0, 0 }, new int[] { N - 2, D - 1 }); m_CFL_EvalPoints[i] = new NodeSet(Kref, vert); } // evaluators an memory for result int VecMax = 1000; DGField[] evalers = new DGField[_velvect.Length]; MultidimensionalArray[] fieldValues = new MultidimensionalArray[_velvect.Length]; for (int i = 0; i < _velvect.Length; i++) { evalers[i] = _velvect[i]; fieldValues[i] = MultidimensionalArray.Create(VecMax, m_CFL_EvalPoints[0].NoOfNodes); } var h_min = gdat.Cells.h_min; int K = _velvect.Length; double cflhere = max; //for (int j = 0; j < J; j += VectorSize) { foreach (Chunk chk in cm) { int VectorSize = VecMax; for (int j = chk.i0; j < chk.JE; j += VectorSize) { if (j + VectorSize > chk.JE + 1) { VectorSize = chk.JE - j; } VectorSize = gdat.Cells.GetNoOfSimilarConsecutiveCells(CellInfo.RefElementIndex_Mask, j, VectorSize); int iKref = gdat.Cells.GetRefElementIndex(j); int N = m_CFL_EvalPoints[iKref].GetLength(0); if (fieldValues[0].GetLength(0) != VectorSize) { for (int i = 0; i < _velvect.Length; i++) { fieldValues[i].Allocate(VectorSize, N); } } for (int k = 0; k < K; k++) { evalers[k].Evaluate(j, VectorSize, m_CFL_EvalPoints[iKref], fieldValues[k], 0, 0.0); } // loop over cells ... for (int jj = j; jj < j + VectorSize; jj++) { // loop over nodes ... for (int n = 0; n < N; n++) { double velabs = 0; // loop over velocity components ... for (int k = 0; k < K; k++) { double v = fieldValues[k][jj - j, n]; velabs += v * v; } velabs = Math.Sqrt(velabs); double cfl = h_min[jj] / velabs; cflhere = Math.Min(cfl, cflhere); } } } } // find the minimum over all processes via MPI and return // ------------------------------------------------------ double cfltotal; unsafe { csMPI.Raw.Allreduce((IntPtr)(&cflhere), (IntPtr)(&cfltotal), 1, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD); } tr.Info("computed CFL timestep: " + cfltotal); return(cfltotal); } }
/// <summary> /// ctor /// </summary> /// <param name="volMask"> /// volume mask for those cells which should be contained in the subgrid /// </param> public SubGrid(CellMask volMask) { MPICollectiveWatchDog.Watch(); this.m_VolumeMask = volMask; m_GridData = volMask.GridData; }