/// <summary> /// modifies a residual (i.e. an operator evaluation) /// in order to fix the pressure at some reference point /// </summary> /// <param name="currentState">current state of velocity & pressure</param> /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param> /// <param name="LsTrk"></param> /// <param name="Residual"></param> static public void SetPressureReferencePointResidual <T>(CoordinateVector currentState, int iVar, LevelSetTracker LsTrk, T Residual) where T : IList <double> { using (new FuncTrace()) { var map = currentState.Mapping; var GridDat = map.GridDat; if (Residual.Count != map.LocalLength) { throw new ArgumentException(); } Basis PressureBasis = (Basis)map.BasisS[iVar]; int D = GridDat.SpatialDimension; long GlobalID, GlobalCellIndex; bool IsInside, onthisProc; GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement()); int iRowGl = -111; if (onthisProc) { int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]); MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1);; MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D); GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell); //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]); LevelSetSignCode scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]); ReducedRegionCode rrc; int No = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); int iSpc = LsTrk.GetSpeciesIndex(rrc, scode); iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0); } iRowGl = iRowGl.MPIMax(); // clear row // --------- if (onthisProc) { // set entry in residual vector equal to corresponding value in domain vector // (as if the corresponding matrix would have a 1 in the diagonal element and 0 everywhere else) int iRow = iRowGl - map.i0; Residual[iRow] = currentState[iRow]; } } }
/// <summary> /// modifies a matrix <paramref name="Mtx"/> and a right-hand-side <paramref name="rhs"/> /// in order to fix the pressure at some reference point /// </summary> /// <param name="map">row mapping for <paramref name="Mtx"/> as well as <paramref name="rhs"/></param> /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param> /// <param name="LsTrk"></param> /// <param name="Mtx"></param> /// <param name="rhs"></param> static public void SetPressureReferencePoint <T>(UnsetteledCoordinateMapping map, int iVar, LevelSetTracker LsTrk, BlockMsrMatrix Mtx, T rhs) where T : IList <double> { using (new FuncTrace()) { var GridDat = map.GridDat; if (rhs.Count != map.LocalLength) { throw new ArgumentException(); } if (!Mtx.RowPartitioning.EqualsPartition(map) || !Mtx.ColPartition.EqualsPartition(map)) { throw new ArgumentException(); } Basis PressureBasis = (Basis)map.BasisS[iVar]; int D = GridDat.SpatialDimension; long GlobalID, GlobalCellIndex; bool IsInside, onthisProc; GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement()); int iRowGl = -111; if (onthisProc) { int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]); MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1);; MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D); GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell); //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]); LevelSetSignCode scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]); ReducedRegionCode rrc; int No = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); int iSpc = LsTrk.GetSpeciesIndex(rrc, scode); iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0); } iRowGl = iRowGl.MPIMax(); // clear row // --------- if (onthisProc) { // ref. cell is on local MPI process int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; ReducedRegionCode rrc; int NoOfSpc = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); // set matrix row to identity Mtx.ClearRow(iRowGl); Mtx.SetDiagonalElement(iRowGl, 1.0); // clear RHS int iRow = iRowGl - Mtx.RowPartitioning.i0; rhs[iRow] = 0; } // clear column // ------------ { for (int i = Mtx.RowPartitioning.i0; i < Mtx.RowPartitioning.iE; i++) { if (i != iRowGl) { Mtx[i, iRowGl] = 0; } } } } }
/// <summary> /// Computes a mapping from the new species index to the old species index, or vice-versa. /// </summary> /// <param name="jCell"> /// Local cell index. /// </param> /// <param name="New2Old"> /// If true, a mapping from new species index to previous/old species index is returned, /// if false the other way around. /// </param> /// <param name="LsTrk"> /// </param> /// <returns> /// Null, if there is no change in species ordering in cell <paramref name="jCell"/> /// from the previous level-set tracker state to the actual. /// /// Otherwise, if <paramref name="New2Old"/> is true, an array of the same length /// as the number of species currently in cell <paramref name="jCell"/>. /// - index: current species index in cell <paramref name="jCell"/>. /// - content: index of this species with respect to the previous level-set-tracker state. /// If <paramref name="New2Old"/> false, the other way around. /// </returns> public static int[] SpeciesUpdate(LevelSetTracker LsTrk, int jCell, bool New2Old) { ushort[] OldCode = LsTrk.RegionsHistory[0].RegionsCode; ushort[] NewCode = LsTrk.RegionsHistory[1].RegionsCode; // Only if the return value of this function is positive, a mapping from current species index to previous species index // - index: current species index in cell <paramref name="jCell"/>. // - content: index of this species with respect to the previous level-set-tracker state. int[] UpdateMap = null; bool AnyUpdate = false; ushort oc = OldCode[jCell]; ushort nc = NewCode[jCell]; if (!New2Old) { // swap old and new ushort b = oc; oc = nc; nc = b; } ReducedRegionCode oldRRC, newRRC; int OldNoOfSpc = LsTrk.GetNoOfSpeciesByRegionCode(oc, out oldRRC); int NewNoOfSpc = LsTrk.GetNoOfSpeciesByRegionCode(nc, out newRRC); for (int new_iSpc = 0; new_iSpc < NewNoOfSpc; new_iSpc++) { SpeciesId spId = LsTrk.GetSpeciesIdFromIndex(newRRC, new_iSpc); int old_iSpc = LsTrk.GetSpeciesIndex(oldRRC, spId); // if the species was not present in the previous state, this should be negative if (old_iSpc != new_iSpc) { if (AnyUpdate == false) { // init the update map: no change up to index 'new_iSpc' AnyUpdate = true; UpdateMap = new int[NewNoOfSpc]; for (int i = 0; i < new_iSpc; i++) { UpdateMap[i] = i; } } // index 'new_iSpc' maps to old species index UpdateMap[new_iSpc] = old_iSpc; } } if (NewNoOfSpc < OldNoOfSpc) { // the number of species is reduced - this also counts as change if (AnyUpdate == false) { // init the update map: no change up to index 'new_iSpc' AnyUpdate = true; UpdateMap = new int[NewNoOfSpc]; for (int i = 0; i < NewNoOfSpc; i++) { UpdateMap[i] = i; } } } // return return(UpdateMap); }
void UpdateBoundingBoxes() { var grd = lsTrk.GridDat; int D = grd.SpatialDimension; int J = grd.Cells.Count; var KrefS = grd.Grid.RefElements; var VolQRs = KrefS.Select(Kref => Kref.GetBruteForceQuadRule(6, 2)).ToArray(); var BruteForceVolFam = VolQRs; // cache some vals SubGrid allCut = lsTrk.Regions.GetCutCellSubGrid(); int JsubCC = allCut.LocalNoOfCells; int NoOfLevSets = lsTrk.LevelSets.Count(); MultidimensionalArray[] LevSetVals = new MultidimensionalArray[NoOfLevSets]; MultidimensionalArray[] GlobalNodes = BruteForceVolFam.Select(nscc => MultidimensionalArray.Create(nscc.Nodes.NoOfNodes, D)).ToArray(); int[] m_CutCellSubGrid_SubgridIndex2LocalCellIndex = lsTrk.Regions.GetCutCellSubGrid().SubgridIndex2LocalCellIndex; // set BoundingBox'es for cut cells // ================================ double[] pt = new double[D]; for (int jsub = 0; jsub < JsubCC; jsub++) // loop over all local cells in subgrid ... { int j_cell = m_CutCellSubGrid_SubgridIndex2LocalCellIndex[jsub]; int iKref = grd.Cells.GetRefElementIndex(j_cell); int NoOfQuadNodes = BruteForceVolFam[iKref].NoOfNodes; // loop over level sets (evaluation) ... for (int levSetIdx = 0; levSetIdx < NoOfLevSets; levSetIdx++) { LevSetVals[levSetIdx] = lsTrk.DataHistories[levSetIdx].Current.GetLevSetValues(BruteForceVolFam[iKref].Nodes, j_cell, 1); } grd.TransformLocal2Global(BruteForceVolFam[iKref].Nodes, GlobalNodes[iKref], j_cell); ReducedRegionCode rrc; int NoOfSpec = lsTrk.Regions.GetNoOfSpecies(j_cell, out rrc); this.BoundingBoxes[j_cell] = NoOfSpec.ForLoop(iSpc => new BoundingBox(D)); for (int m = 0; m < NoOfQuadNodes; m++) { GlobalNodes[iKref].GetRow(m, pt); double val0 = LevSetVals[0][0, m]; double val1 = 0; if (NoOfLevSets > 1) { val1 = LevSetVals[1][0, m]; } double val2 = 0; if (NoOfLevSets > 2) { val2 = LevSetVals[2][0, m]; } double val3 = 0; if (NoOfLevSets > 3) { val3 = LevSetVals[3][0, m]; } LevelSetSignCode LevSetCode = LevelSetSignCode.ComputeLevelSetBytecode(val0, val1, val2, val3); int iSpec = lsTrk.GetSpeciesIndex(rrc, LevSetCode); this.BoundingBoxes[j_cell][iSpec].AddPoint(pt); } } // set Boundingboxes for un-cut cells // ================================== for (int j = 0; j < J; j++) { if (this.BoundingBoxes[j] == null) { ReducedRegionCode rrc; int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j, out rrc); BoundingBox BB = new BoundingBox(D); grd.Cells.GetCellBoundingBox(j, BB); this.BoundingBoxes[j] = new BoundingBox[] { BB }; } } }