static private void CompOffsets(int i0, int L, int[] offset, UnsetteledCoordinateMapping Map) { int DELTA = offset.Length; Debug.Assert(DELTA == Map.BasisS.Count); int _o0 = Map.LocalUniqueCoordinateIndex(0, i0, 0); for (int delta = 0; delta < offset.Length; delta++) { offset[delta] = Map.LocalUniqueCoordinateIndex(delta, i0, 0) - _o0; } #if DEBUG int[] Ns = new int[DELTA]; for (int delta = 0; delta < DELTA; delta++) { Ns[delta] = Map.BasisS[delta].GetLength(i0); } for (int i = 1; i < L; i++) { for (int delta = 0; delta < DELTA; delta++) { Debug.Assert(Ns[delta] == Map.BasisS[delta].GetLength(i0 + i)); } } #endif }
/// <summary> /// computes a local unique coordinate index ("local" means local on this processor); /// this index is unique over all fields (in this mapping), over all cells, over all basis functions, /// but it's only locally (on this processor) valid. /// A local index in the update range (smaller than <see cref="NUpdate"/>) can be converted into /// a global index by adding <see cref="Partitioning.i0"/>. /// </summary> /// <param name="find"> /// the field or basis index (see <see cref="BasisS"/>); /// </param> /// <param name="j">local cell index</param> /// <param name="n">DG mode index</param> /// <param name="lsTrk"></param> /// <param name="map"></param> /// <param name="spcIdx">species index</param> public static int LocalUniqueCoordinateIndex(this UnsetteledCoordinateMapping map, LevelSetTracker lsTrk, int find, int j, int spcIdx, int n) { //; int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j, out var rrc); if (spcIdx < 0 || spcIdx >= NoOfSpc) { throw new IndexOutOfRangeException($"Species index out of range (species index is {spcIdx}, Number of species is {NoOfSpc}, cell {j})"); } Basis b = map.BasisS[find]; XDGBasis xb = b as XDGBasis; if (xb == null) { return(map.LocalUniqueCoordinateIndex(find, j, n)); } else { int i0 = map.LocalUniqueCoordinateIndex(find, j, 0); int Ns = xb.NonX_Basis.GetLength(j); if (n < 0 || n >= Ns) { throw new IndexOutOfRangeException($"DG mode index (within species) of range (DG mode index is {n}, but non-XDG basis length is {Ns}, cell {j})"); } return(i0 + Ns * spcIdx + n); } }
/// <summary> /// writes the dammed result of the integration to the sparse matrix /// </summary> protected override void SaveIntegrationResults(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { int Nmax = m_CodomainMap.MaxTotalNoOfCoordinatesPerCell; //int[] _i0 = new int[] { int.MaxValue, 0, 1 }; //int[] _iE = new int[] { -1, Nmax - 1, _i0[2] + Mmax - 1 }; int[] _i0aff = new int[] { int.MaxValue, 0 }; int[] _iEaff = new int[] { -1, Nmax - 1 }; // loop over cells... for (int i = 0; i < Length; i++) { int jCell = i + i0; int Row0 = m_CodomainMap.LocalUniqueCoordinateIndex(0, jCell, 0); int Row0_g = m_CodomainMap.i0 + Row0; _i0aff[0] = i; _iEaff[0] = -1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0aff, _iEaff); for (int r = BlockRes.GetLength(0) - 1; r >= 0; r--) { ResultVector[Row0 + r] += BlockRes[r]; } } }
/// <summary> /// Computes the permutation for the given <paramref name="RowMap"/> /// </summary> /// <param name="RowMap"></param> /// <param name="grd"></param> /// <returns></returns> public static int[] ComputePermutation(UnsetteledCoordinateMapping RowMap, GridData grd) { int J = grd.Grid.NoOfUpdateCells; int[] N = RowMap.BasisS.Select(x => x.MaximalLength).ToArray(); int NT = N.Sum(); int Gamma = RowMap.BasisS.Count; var GlobalIDs = grd.CurrentGlobalIdPermutation.Values; int[] PermutationTable; PermutationTable = new int[RowMap.LocalLength]; Debug.Assert(PermutationTable.Length == J * NT); for (int j = 0; j < J; j++) { int gid = (int)GlobalIDs[j]; int iTarg0 = gid * NT; int i0 = (int)RowMap.LocalUniqueCoordinateIndex(0, j, 0); for (int f = 0; f < Gamma; f++) { for (int n = 0; n < N[f]; n++) { int i = (int)RowMap.LocalUniqueCoordinateIndex(f, j, n); int iTarg = iTarg0 + (i - i0); PermutationTable[i] = iTarg; } } } int[] globalPermutationTable = new int[grd.Grid.NumberOfCells * NT]; unsafe { int[] displ = RowMap.GetI0s().Select(x => (int)x).ToArray(); int[] rcvCnt = new int[RowMap.MpiSize]; for (int i = 0; i < RowMap.MpiSize; i++) rcvCnt[i] = displ[i + 1] - displ[i]; fixed(int *pSnd = PermutationTable, pRcv = globalPermutationTable, pDispl = displ, pRcvCnt = rcvCnt) { csMPI.Raw.Allgatherv((IntPtr)pSnd, PermutationTable.Length, csMPI.Raw._DATATYPE.INT, (IntPtr)pRcv, (IntPtr)pRcvCnt, (IntPtr)pDispl, csMPI.Raw._DATATYPE.INT, csMPI.Raw._COMM.WORLD); } } return(globalPermutationTable); }
/// <summary> /// Prolongates/injects a vector from the full grid (<see cref="BoSSS.Foundation.Grid.GridData"/>) /// to the aggregated grid (<see cref="AggGrid"/>). /// </summary> /// <param name="FullGridVector">output;</param> /// <param name="AggGridVector">input;</param> virtual public void ProlongateToFullGrid <T, V>(T FullGridVector, V AggGridVector) where T : IList <double> where V : IList <double> // { var fullMapping = new UnsetteledCoordinateMapping(this.DGBasis); if (FullGridVector.Count != fullMapping.LocalLength) { throw new ArgumentException("mismatch in vector length", "FullGridVector"); } int L = this.LocalDim; if (AggGridVector.Count != L) { throw new ArgumentException("mismatch in vector length", "AggGridVector"); } var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; int N = this.DGBasis.Length; var FulCoords = new double[N]; var AggCoords = new double[N]; //MultidimensionalArray Trf = MultidimensionalArray.Create(N, N); for (int jAgg = 0; jAgg < JAGG; jAgg++) { int[] agCl = agCls[jAgg]; int K = agCl.Length; int i0 = jAgg * N; for (int n = 0; n < N; n++) { AggCoords[n] = AggGridVector[n + i0]; } for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int j0 = fullMapping.LocalUniqueCoordinateIndex(0, jCell, 0); //Trf.Clear(); //Trf.Acc(1.0, this.CompositeBasis[jAgg].ExtractSubArrayShallow(k, -1, -1)); var Trf = this.CompositeBasis[jAgg].ExtractSubArrayShallow(k, -1, -1); //Trf.Solve(FulCoords, AggCoords); Trf.gemv(1.0, AggCoords, 0.0, FulCoords); for (int n = 0; n < N; n++) { FullGridVector[j0 + n] = FulCoords[n]; } } } }
/// <summary> /// restricts/projects a vector from the full grid (<see cref="BoSSS.Foundation.Grid.Classic.GridData"/>) /// to the aggregated grid (<see cref="AggGrid"/>). /// </summary> /// <param name="FullGridVector">input;</param> /// <param name="AggGridVector">output;</param> virtual public void RestictFromFullGrid <T, V>(T FullGridVector, V AggGridVector) where T : IList <double> where V : IList <double> // { var fullMapping = new UnsetteledCoordinateMapping(this.DGBasis); if (FullGridVector.Count != fullMapping.LocalLength) { throw new ArgumentException("mismatch in vector length", "FullGridVector"); } int L = this.LocalDim; if (AggGridVector.Count != L) { throw new ArgumentException("mismatch in vector length", "AggGridVector"); } var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; int N = this.DGBasis.Length; var Buffer = MultidimensionalArray.Create(agCls.Max(cc => cc.Length), N); var Aggcoords = MultidimensionalArray.Create(N); for (int jAgg = 0; jAgg < JAGG; jAgg++) // loop over all aggregated cells... { int[] agCl = agCls[jAgg]; int K = agCl.Length; MultidimensionalArray coords = (K * N == Buffer.GetLength(0)) ? Buffer : Buffer.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, N - 1 }); for (int k = 0; k < K; k++) // loop over the cells which form the aggregated cell... { int jCell = agCl[k]; int j0 = fullMapping.LocalUniqueCoordinateIndex(0, jCell, 0); for (int n = 0; n < N; n++) { coords[k, n] = FullGridVector[n + j0]; } } Aggcoords.Clear(); Aggcoords.Multiply(1.0, this.CompositeBasis[jAgg], coords, 0.0, "n", "kmn", "km"); int i0 = jAgg * N; for (int n = 0; n < N; n++) { AggGridVector[n + i0] = Aggcoords[n]; } } }
/// <summary> /// writes the dammed result of the integration to the sparse matrix /// </summary> protected override void SaveIntegrationResults(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { int Mmax = m_ColMap.MaxTotalNoOfCoordinatesPerCell; int Nmax = m_RowMap.MaxTotalNoOfCoordinatesPerCell; int[] _i0 = new int[] { int.MaxValue, 0, 1 }; int[] _iE = new int[] { -1, Nmax - 1, _i0[2] + Mmax - 1 }; int[] _i0aff = new int[] { int.MaxValue, 0, 0 }; int[] _iEaff = new int[] { -1, Nmax - 1, -1 }; bool saveMtx = this.OperatorMatrix != null; bool saveAff = this.OperatorAffine != null; // loop over cells... for (int i = 0; i < Length; i++) { int jCell = i + i0; int Row0 = m_RowMap.LocalUniqueCoordinateIndex(0, jCell, 0); int Row0_g = m_RowMap.i0 + Row0; if (saveMtx) { _i0[0] = i; _iE[0] = -1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0, _iE); int Col0_g = m_ColMap.GlobalUniqueCoordinateIndex(0, jCell, 0); //for (int r = BlockRes.NoOfRows - 1; r >= 0; r--) // for (int c = BlockRes.NoOfCols - 1; c >= 0; c--) // OperatorMatrix[Row0_g + r, Col0_g + c] += BlockRes[r, c]; OperatorMatrix.AccBlock(Row0_g, Col0_g, 1.0, BlockRes); } if (saveAff) { _i0aff[0] = i; _iEaff[0] = -1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0aff, _iEaff); for (int r = BlockRes.GetLength(0) - 1; r >= 0; r--) { OperatorAffine[Row0 + r] += BlockRes[r]; } } } }
/// <summary> /// writes the dammed result of the integration to the sparse matrix /// </summary> protected override void SaveIntegrationResults(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { int GAMMA = this.m_CodomainMap.BasisS.Count; // GAMMA: number of codom/row/test variables LECQuadratureLevelSet <IMutableMatrixEx, double[]> .CompOffsets(i0, Length, out int[] offsetRow, out int[] RowNonxN, m_CodomainMap); SpeciesId[] spcS = new[] { this.SpeciesA, this.SpeciesB }; int[] _i0aff = new int[2]; int[] _iEaff = new int[2]; // loop over cells... for (int i = 0; i < Length; i++) { int jCell = i + i0; #if DEBUG Debug.Assert(RowNonxN.ListEquals(m_CodomainMap.GetNonXBasisLengths(jCell))); #endif _i0aff[0] = i; _iEaff[0] = -1; for (int gamma = 0; gamma < GAMMA; gamma++) // loop over rows... { for (int cr = 0; cr < 2; cr++) // loop over neg/pos species row... { SpeciesId rowSpc = spcS[cr]; int Row0 = m_CodomainMap.LocalUniqueCoordinateIndex(m_lsTrk, gamma, jCell, rowSpc, 0); _i0aff[1] = offsetRow[gamma] + RowNonxN[gamma] * cr; // the 'RowXbSw' is 0 for non-xdg, so both species will be added _iEaff[1] = _i0aff[1] + RowNonxN[gamma] - 1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0aff, _iEaff); for (int r = BlockRes.GetLength(0) - 1; r >= 0; r--) { ResultVector[Row0 + r] += BlockRes[r]; } } } } }
public override void RestictFromFullGrid <T, V>(T FullGridVector, V AggGridVector) { var fullMapping = new UnsetteledCoordinateMapping(this.XDGBasis); if (FullGridVector.Count != fullMapping.LocalLength) { throw new ArgumentException("mismatch in vector length", "FullGridVector"); } int L = this.LocalDim; if (AggGridVector.Count != L) { throw new ArgumentException("mismatch in vector length", "AggGridVector"); } var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; int Nmax = this.XDGBasis.MaximalLength; int N = this.DGBasis.Length; Debug.Assert(Nmax % N == 0); var Buffer = MultidimensionalArray.Create(agCls.Max(cc => cc.Length), N); var AggCoords = MultidimensionalArray.Create(N); for (int jAgg = 0; jAgg < JAGG; jAgg++) // loop over all composite cells... { int[] agCl = agCls[jAgg]; int K = agCl.Length; MultidimensionalArray FulCoords = (K * N == Buffer.GetLength(0)) ? Buffer : Buffer.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, N - 1 }); int i0Agg = jAgg * Nmax, i0Full; if (this.SpeciesIndexMapping[jAgg] == null) { // default branch: // use restiction/prolongation from un-cut basis // +++++++++++++++++++++++++++++++++++++++++++++ for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; i0Full = jCell * Nmax; for (int n = 0; n < N; n++) { FulCoords[k, n] = FullGridVector[n + i0Full]; } } MultidimensionalArray Trf = base.CompositeBasis[jAgg]; AggCoords.Clear(); AggCoords.Multiply(1.0, Trf, FulCoords, 0.0, "n", "kmn", "km"); int _i0 = jAgg * N; for (int n = 0; n < N; n++) { AggGridVector[n + i0Agg] = AggCoords[n]; } } else { int NoSpc = this.NoOfSpecies[jAgg]; int[,] sim = SpeciesIndexMapping[jAgg]; Debug.Assert(sim.GetLength(0) == NoSpc); Debug.Assert(sim.GetLength(1) == K); for (int iSpcAgg = 0; iSpcAgg < NoSpc; iSpcAgg++) { for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int iSpcBase = sim[iSpcAgg, k]; if (iSpcBase < 0) { for (int n = 0; n < N; n++) { FulCoords[k, n] = 0; } } else { i0Full = fullMapping.LocalUniqueCoordinateIndex(0, jCell, iSpcBase * N); for (int n = 0; n < N; n++) { FulCoords[k, n] = FullGridVector[i0Full + n]; } } } MultidimensionalArray Trf; if (this.XCompositeBasis[jAgg] == null || this.XCompositeBasis[jAgg][iSpcAgg] == null) { Trf = base.CompositeBasis[jAgg]; } else { Trf = this.XCompositeBasis[jAgg][iSpcAgg]; } AggCoords.Clear(); AggCoords.Multiply(1.0, Trf, FulCoords, 0.0, "n", "kmn", "km"); for (int n = 0; n < N; n++) { AggGridVector[i0Agg + iSpcAgg * N + n] = AggCoords[n]; } } } } }
public override void ProlongateToFullGrid <T, V>(T FullGridVector, V AggGridVector) { var fullMapping = new UnsetteledCoordinateMapping(this.XDGBasis); if (FullGridVector.Count != fullMapping.LocalLength) { throw new ArgumentException("mismatch in vector length", "FullGridVector"); } int L = this.LocalDim; if (AggGridVector.Count != L) { throw new ArgumentException("mismatch in vector length", "AggGridVector"); } var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; int Nmax = this.XDGBasis.MaximalLength; int N = this.DGBasis.Length; Debug.Assert(Nmax % N == 0); var FulCoords = new double[N]; var AggCoords = new double[N]; for (int jAgg = 0; jAgg < JAGG; jAgg++) // loop over all composite cells... { int[] agCl = agCls[jAgg]; int K = agCl.Length; if (this.SpeciesIndexMapping[jAgg] == null) { Debug.Assert(this.XCompositeBasis[jAgg] == null); int i0 = jAgg * Nmax; // index offset into 'AggGridVector' for (int n = 0; n < N; n++) { AggCoords[n] = AggGridVector[n + i0]; } for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int j0 = fullMapping.LocalUniqueCoordinateIndex(0, jCell, 0); MultidimensionalArray Trf = base.CompositeBasis[jAgg].ExtractSubArrayShallow(k, -1, -1); //Trf.Solve(FulCoords, AggCoords); Trf.GEMV(1.0, AggCoords, 0.0, FulCoords); for (int n = 0; n < N; n++) { FullGridVector[j0 + n] = FulCoords[n]; } } } else { int NoSpc = this.NoOfSpecies[jAgg]; int[,] sim = SpeciesIndexMapping[jAgg]; Debug.Assert(sim.GetLength(0) == NoSpc); Debug.Assert(sim.GetLength(1) == K); for (int iSpcAgg = 0; iSpcAgg < NoSpc; iSpcAgg++) { int i0 = jAgg * Nmax + iSpcAgg * N; // index offset into 'AggGridVector' for (int n = 0; n < N; n++) { AggCoords[n] = AggGridVector[n + i0]; } for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int iSpcBase = sim[iSpcAgg, k]; if (iSpcBase < 0) { continue; } int j0 = fullMapping.LocalUniqueCoordinateIndex(0, jCell, iSpcBase * N); MultidimensionalArray Trf; if (this.XCompositeBasis[jAgg] == null || this.XCompositeBasis[jAgg][iSpcAgg] == null) { Trf = base.CompositeBasis[jAgg].ExtractSubArrayShallow(k, -1, -1); } else { Trf = this.XCompositeBasis[jAgg][iSpcAgg].ExtractSubArrayShallow(k, -1, -1); } Trf.GEMV(1.0, AggCoords, 0.0, FulCoords); for (int n = 0; n < N; n++) { FullGridVector[j0 + n] = FulCoords[n]; } } } } } }
/// <summary> /// Computes a mapping from the new, cell local DG coordinate index to the previous/old DG coordinate 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> /// <param name="Map"> /// DG coordinate mapping. /// </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 degrees-of-freedom currently in cell <paramref name="jCell"/>. /// - index: current DOF index in cell <paramref name="jCell"/>. /// - content: index of this DOF with respect to the previous level-set-tracker state. /// If <paramref name="New2Old"/> false, the other way around. /// </returns> public static int[] MappingUpdate(LevelSetTracker LsTrk, int jCell, UnsetteledCoordinateMapping Map, bool New2Old) { int[] SpeciesMap = SpeciesUpdate(LsTrk, jCell, New2Old); if (SpeciesMap == null) { return(null); } int NoVar = Map.NoOfVariables; XDGBasis[] XBasiseS = new XDGBasis[NoVar]; Basis[] BasiseS = new Basis[NoVar]; int[] Ns = new int[NoVar]; for (int iVar = 0; iVar < NoVar; iVar++) { Basis b = Map.BasisS[iVar]; XBasiseS[iVar] = b as XDGBasis; if (XBasiseS[iVar] != null) { BasiseS[iVar] = XBasiseS[iVar].NonX_Basis; } else { BasiseS[iVar] = b; } Ns[iVar] = BasiseS[iVar].Length; } //List<int> oldIdx = new List<int>(); //List<int> newIdx = new List<int>(); int[] IdxMap = new int[Map.MaxTotalNoOfCoordinatesPerCell]; ArrayTools.SetAll(IdxMap, int.MinValue); bool AnyRelocation = false; int i0 = Map.LocalUniqueCoordinateIndex(0, jCell, 0); for (int iVar = 0; iVar < NoVar; iVar++) { int i0Var = Map.LocalUniqueCoordinateIndex(iVar, jCell, 0); int N = Ns[iVar]; int offset = i0Var - i0; if (XBasiseS[iVar] != null) { // XDG-field for (int i = 0; i < SpeciesMap.Length; i++) { int ii = SpeciesMap[i]; for (int n = 0; n < N; n++) { int idxS = offset + n + i * N; int idxT = ii >= 0 ? offset + n + ii * N : int.MinValue; Debug.Assert(IdxMap[idxS] < 0); IdxMap[idxS] = idxT; AnyRelocation |= (idxS != idxT); } } } else { // single-phase-field for (int n = 0; n < N; n++) { int idx = offset + n; //oldIdx.Add(idx); //newIdx.Add(idx); Debug.Assert(IdxMap[idx] < 0); IdxMap[idx] = idx; } } } return(IdxMap); //if (AnyRelocation) // return IdxMap; //else // return null; }
/// <summary> /// Tools for updating RHS under level-set movement, when ordering of DOFs (the mapping) changes. /// </summary> public static void OperatorLevelSetUpdate(LevelSetTracker LsTrk, double[] Affine, UnsetteledCoordinateMapping RowMap) { using (new FuncTrace()) { if (RowMap.LocalLength != Affine.Length) { throw new ArgumentException(); } if (!object.ReferenceEquals(LsTrk.GridDat, RowMap.GridDat)) { throw new ArgumentException(); } BoSSS.Foundation.Grid.IGridData GridData = LsTrk.GridDat; int J = GridData.iLogicalCells.NoOfLocalUpdatedCells; int GAMMA = RowMap.NoOfVariables; //int DELTA = ColMap.NoOfVariables; //int ColBlockSize = ColMap.MaxTotalNoOfCoordinatesPerCell; int RowBlockSize = RowMap.MaxTotalNoOfCoordinatesPerCell; int Gj0 = GridData.CellPartitioning.i0; int NoOfSpc = LsTrk.TotalNoOfSpecies; double[] OldAffine = new double[RowBlockSize]; Dictionary <int, int[]> jNeighs = new Dictionary <int, int[]>(); // Key: global cell index // values: re-sorting for species in this cell Tuple <int, int[], double[]>[] oldRows = new Tuple <int, int[], double[]> [RowBlockSize]; // loop over cells for (int j = 0; j < J; j++) { int[] RowIdxUpdate = MappingUpdate(LsTrk, j, RowMap, false); // affine vector update // -------------------- if (Affine != null && RowIdxUpdate != null) { // some update occurred // +++++++++++++++++++++++ int i0 = RowMap.LocalUniqueCoordinateIndex(0, j, 0); Debug.Assert(i0 + RowBlockSize <= RowMap.LocalLength); Debug.Assert(i0 >= 0); for (int i = 0; i < RowBlockSize; i++) { OldAffine[i] = Affine[i + i0]; Affine[i + i0] = 0.0; } for (int i = 0; i < RowBlockSize; i++) { int k = RowIdxUpdate[i]; if (k < 0) { if (OldAffine[i] != 0.0) { throw new ApplicationException("Cannot kill non-null entry."); } } else { Affine[i0 + k] = OldAffine[i]; } } } } } }
/// <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()); }