static bool IsCellCut(int iEdge, int[,] E2C, LevelSetTracker.LevelSetRegions regions, SpeciesId mySp) { int jCell0 = E2C[iEdge, 0]; int iSpc_cell0 = regions.GetSpeciesIndex(mySp, jCell0); if (iSpc_cell0 != 0) { return(true); } int jCell1 = E2C[iEdge, 1]; if (jCell1 >= 0) { int iSpc_cell1 = regions.GetSpeciesIndex(mySp, jCell1); if (iSpc_cell1 != 0) { return(true); } } return(false); }
public MiniMapping(UnsetteledCoordinateMapping Map, SpeciesId spId, LevelSetTracker.LevelSetRegions r) { m_Map = Map; m_spId = spId; m_LsRegion = r; Basis[] BS = Map.BasisS.ToArray(); NS = new int[BS.Length]; VarIsXdg = new bool[BS.Length]; NoOfVars = BS.Length; for (int iVar = 0; iVar < BS.Length; iVar++) { XDGBasis xBasis = BS[iVar] as XDGBasis; if (xBasis != null) { NS[iVar] = xBasis.NonX_Basis.Length; //m_LsTrk = xBasis.Tracker; VarIsXdg[iVar] = true; } else { NS[iVar] = BS[iVar].Length; VarIsXdg[iVar] = false; } MaxDeg = Math.Max(MaxDeg, BS[iVar].Degree); } }
/// <summary> /// ctor /// </summary> /// <param name="lsTrk">level set tracker</param> /// <param name="spcId">species which should be framed</param> /// <param name="__FullMap"></param> /// <param name="SupportExternal"> /// true: support also indices related to external/ghost cells /// </param> public FrameBase(LevelSetTracker.LevelSetRegions regions, SpeciesId spcId, UnsetteledCoordinateMapping __FullMap, bool SupportExternal) { m_Regions = regions; m_spcId = spcId; FrameMap = CreateMap(__FullMap); FullMap = __FullMap; m_supportExternal = SupportExternal; Setup_Frame2Full(); // Frame2Full is almost used every time, so we set it up immediately // (in contrast, Full2Frame is set up on demand) }
/// <summary> /// returns global unique indices which correlate to a certain sub-set of ... /// <list type="bullet"> /// <item>the mappings's basis (<paramref name="mapping"/>, <see cref="UnsetteledCoordinateMapping.BasisS"/>).</item> /// <item>species (<paramref name="_SpcIds"/>).</item> /// <item>cells (<paramref name="cm"/>).</item> /// </list> /// </summary> /// <param name="mapping"> /// the mapping /// </param> /// <param name="Fields"> /// determines which fields should be in the sub-vector-indices-list /// </param> /// <param name="_SpcIds"> /// determines which species should be in the sub-vector-indices-list; null indicates all species. /// </param> /// <param name="cm"> /// determines which cells should be in the sub-vector-indices-list; null indicates all cells. /// </param> /// <param name="regions"> /// Determines which XDG-coordinate belongs to which species. /// </param> /// <param name="presenceTest"> /// if true, cells where some species has zero measure are excluded from the sub-vector-indices-list. /// </param> /// <param name="drk"> /// a cell-agglomeration object: if null, ignored; if provided, /// cells which are eliminated by the agglomeration are excluded from the sub-vector-indices-list /// </param> /// <returns>a list of global (over all MPI processes) unique indices.</returns> static public int[] GetSubvectorIndices(this UnsetteledCoordinateMapping mapping, LevelSetTracker.LevelSetRegions regions, int[] Fields, ICollection <SpeciesId> _SpcIds = null, CellMask cm = null, bool presenceTest = true, MultiphaseCellAgglomerator drk = null) { #region Check Arguments // ========= SpeciesId[] SpcIds = null; if (_SpcIds == null) { // take all species, if arg is null SpcIds = regions.SpeciesIdS.ToArray(); } else { SpcIds = _SpcIds.ToArray(); } if (SpcIds.Length <= 0) { // return will be empty for no species return(new int[0]); } #endregion #region collect cells which are excluded by agglomeration // ================================================= int[][] ExcludeLists; if (drk != null) { ExcludeLists = new int[regions.SpeciesIdS.Count][]; // new Dictionary<SpeciesId, int[]>(); foreach (var id in SpcIds) { int[] ExcludeList = drk.GetAgglomerator(id).AggInfo.AgglomerationPairs.Select(pair => pair.jCellSource).ToArray(); Array.Sort(ExcludeList); ExcludeLists[id.cntnt - LevelSetTracker.___SpeciesIDOffest] = ExcludeList; } } else { ExcludeLists = null; } #endregion #region determine over which cells we want to loop // ========================================== CellMask loopCells; if ((new HashSet <SpeciesId>(regions.SpeciesIdS)).SetEquals(new HashSet <SpeciesId>(SpcIds))) { if (cm == null) { loopCells = CellMask.GetFullMask(regions.GridDat); } else { loopCells = cm; } } else { loopCells = regions.GetSpeciesMask(SpcIds[0]); for (int i = 1; i < SpcIds.Length; i++) { loopCells = loopCells.Intersect(regions.GetSpeciesMask(SpcIds[i])); } if (cm != null) { loopCells = loopCells.Intersect(cm); } } #endregion #region build list // ========== var R = new List <int>(); // which basis is XDG? var _BasisS = mapping.BasisS.ToArray(); XDGBasis[] _XBasisS = new XDGBasis[_BasisS.Length]; for (int i = 0; i < _BasisS.Length; i++) { _XBasisS[i] = _BasisS[i] as XDGBasis; } Tuple <int, SpeciesId>[] iSpcS = new Tuple <int, SpeciesId> [SpcIds.Length]; int KK; int Len_iSpcS = iSpcS.Length; int[] ExcludeListsPointer = new int[regions.SpeciesIdS.Count]; // loop over cells? foreach (int jCell in loopCells.ItemEnum) { int NoOfSpc = regions.GetNoOfSpecies(jCell); #region // // in cell 'jCell', for each species in 'SpcIds' ... // * is the species present in 'jCell'? // * what is the species index in 'jCell'? // * we also have to consider that due to agglomeration, the respective cut-cell for the species might have been agglomerated. // so we determine // * 'KK' is the number of species (from 'SpcIds') which is actually present and not agglomerated in 'jCell' // * for i in (0 ... KK-1), iSpcS[i] is a tuple of (Species-index-in-cell, SpeciesID) // // yes, the following code sucks: KK = 0; for (int k = 0; k < Len_iSpcS; k++) // loop over all species (provided as argument)... { SpeciesId id = SpcIds[k]; int __iSpcS = regions.GetSpeciesIndex(id, jCell); if (__iSpcS >= 0) { // species index is non-negative, so indices for the species are allocated ... if (!presenceTest || regions.IsSpeciesPresentInCell(id, jCell)) { // species is also present (i.e. has a greater-than-zero measure ... if (drk == null) { // no agglomeration exclution iSpcS[KK] = new Tuple <int, SpeciesId>(__iSpcS, id); KK++; } else { int q = id.cntnt - LevelSetTracker.___SpeciesIDOffest; var el = ExcludeLists[q]; while (ExcludeListsPointer[q] < el.Length && el[ExcludeListsPointer[q]] < jCell) { ExcludeListsPointer[q]++; } Debug.Assert(ExcludeListsPointer[q] >= el.Length || el[ExcludeListsPointer[q]] >= jCell); if (ExcludeListsPointer[q] >= el.Length || el[ExcludeListsPointer[q]] != jCell) { // cell is also not agglomerated ... iSpcS[KK] = new Tuple <int, SpeciesId>(__iSpcS, id); KK++; } } } } } if (KK > 1) { Array.Sort <Tuple <int, SpeciesId> >(iSpcS, 0, KK, new ilPSP.FuncComparer <Tuple <int, SpeciesId> >((a, b) => a.Item1 - b.Item1)); } // --------- esc (end of sucking code) #endregion for (int k = 0; k < KK; k++) // loop over species in cell { int iSpc = iSpcS[k].Item1; for (int i = 0; i < Fields.Length; i++) { int iField = Fields[i]; if (_XBasisS[iField] == null) { int N = _BasisS[iField].GetLength(jCell); int i0 = mapping.LocalUniqueCoordinateIndex(iField, jCell, 0); for (int n = 0; n < N; n++) { R.Add(i0 + n); } } else { int N = _XBasisS[iField].DOFperSpeciesPerCell; int i0 = mapping.LocalUniqueCoordinateIndex(iField, jCell, 0) + iSpc * N; for (int n = 0; n < N; n++) { R.Add(i0 + n); } } } } } #endregion return(R.ToArray()); }
/// <summary> /// computes the mass matrices for a given mapping and accumulates the mass matrix to some other matrix. /// </summary> public void AccMassMatrix <T>(T M, UnsetteledCoordinateMapping mapping, IDictionary <SpeciesId, IEnumerable <double> > _alpha, bool inverse = false) where T : IMutableMatrixEx // { using (new FuncTrace()) { var _basisS = mapping.BasisS.ToArray(); var ctx = _basisS[0].GridDat; int J = ctx.iLogicalCells.NoOfLocalUpdatedCells; if (!M.RowPartitioning.EqualsPartition(mapping)) { throw new ArgumentException("Mismatch in row mapping."); } if (!M.ColPartition.EqualsPartition(mapping)) { throw new ArgumentException("Mismatch in column mapping."); } if (!_alpha.Keys.IsSubsetOf(this.AvailableSpecies)) { throw new ArgumentException("trying to obtain mass matrix for species that is not supported by this factory."); } foreach (var __alpha in _alpha.Values) { if (__alpha.Count() != _basisS.Length) { throw new ArgumentException("Number of alpha's must match number of variables/fields in mapping."); } } LevelSetTracker.LevelSetRegions regions = null;// XDGSpaceMetrics.LevelSetRegions; // compute the Mass-Blocks for the cut cells... // -------------------------------------------- int _MaxDeg = _basisS.Max(b => b.Degree); var RequestedSpecies = _alpha.Keys; UpdateBlocks(_MaxDeg, RequestedSpecies); Dictionary <SpeciesId, MassMatrixBlockContainer>[] invBlocks = null; if (inverse) { invBlocks = GetInverseMassMatrixBlocks(RequestedSpecies, mapping.BasisS.Select(b => b.Degree).ToArray()); //VariableAgglomerationSwitch = new bool[VariableAgglomerationSwitch.Length]; //VariableAgglomerationSwitch.SetAll(true); // we already took care about this in the 'GetInverseMassMatrixBlocks' } // set the matrix // -------------- for (int fld = 0; fld < _basisS.Length; fld++) // loop over Variables in mapping... // loop over species... { foreach (var species in _alpha.Keys) { double alpha = _alpha[species].ElementAt(fld); int[] jSub2jCell = this.MassBlocks[species].jSub2jCell; if (alpha != 0.0) { // properties of the basis XDGBasis Xbasis = _basisS[fld] as XDGBasis; Basis nonXbasis; Basis basis = _basisS[fld]; if (Xbasis != null) { nonXbasis = Xbasis.NonX_Basis; regions = Xbasis.Tracker.Regions; // compute species indices with respect to **actual** regions !!!! //if (!object.ReferenceEquals(Xbasis.Tracker, this.XDGSpaceMetrics.)) // throw new ArgumentException(); } else { nonXbasis = _basisS[fld]; } int N = nonXbasis.Length; // get Mass-Matrix subblock MultidimensionalArray Mass; if (!inverse) { Mass = this.MassBlocks[species].MassMatrixBlocks; } else { Mass = invBlocks[fld][species].MassMatrixBlocks; Debug.Assert(Mass.GetLength(1) == N); Debug.Assert(Mass.GetLength(2) == N); } // set diagonal element 1.0 in all cells of the subgrid // (later, we subtract 1.0 from the diagonal in cut cells) var speciesMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species); { foreach (int jCell in speciesMask.ItemEnum) { int iSpc = 0; if (Xbasis != null) { int NoOfSpc = regions.GetNoOfSpecies(jCell); iSpc = regions.GetSpeciesIndex(species, jCell); } int n0 = mapping.GlobalUniqueCoordinateIndex(fld, jCell, N * iSpc); for (int n = 0; n < N; n++) { M[n0 + n, n0 + n] += alpha; } } } // now, set then Non-Identity blocks in the cut cells var speciesBitMask = speciesMask.GetBitMask(); { int JSUB = jSub2jCell.Length; for (int jsub = 0; jsub < JSUB; jsub++) // loop over cut cells { int jCell = jSub2jCell[jsub]; if (!speciesBitMask[jCell]) { continue; } int iSpc = 0; if (Xbasis != null) { int NoOfSpc = regions.GetNoOfSpecies(jCell); iSpc = regions.GetSpeciesIndex(species, jCell); } var MassSub = Mass.ExtractSubArrayShallow(new int[] { jsub, 0, 0 }, new int[] { jsub - 1, N - 1, N - 1 }); int i0 = mapping.GlobalUniqueCoordinateIndex(fld, jCell, N * iSpc); for (int n = 0; n < N; n++) // loop over rows (within block) { for (int m = 0; m < N; m++) // loop over columns (within block) { M[i0 + n, i0 + m] += alpha * MassSub[n, m] - (m == n ? alpha : 0.0); } } } } } } } } }