/// <summary> /// Gets a list of all occupied indices in the blocking. /// </summary> public static int[] GetOccupiedIndicesList(this IBlockPartitioning B) { List <int> R = new List <int>(); for (int iBlk = B.FirstBlock; iBlk < B.LocalNoOfBlocks + B.FirstBlock; iBlk++) { int i0 = B.GetBlockI0(iBlk); int bt = B.GetBlockType(iBlk); int[] S_i0 = B.GetSubblk_i0(bt); int[] SLen = B.GetSubblkLen(bt); Debug.Assert(S_i0.Length == SLen.Length); int NoSbl = S_i0.Length; for (int iSbl = 0; iSbl < NoSbl; iSbl++) { int si0 = S_i0[iSbl]; int siE = si0 + SLen[iSbl]; for (int i = si0; i < siE; i++) { R.Add(i + i0); } } } return(R.ToArray()); }
static BlockPartitioning CloneBlockPartitioning(IBlockPartitioning part) { int J = part.LocalNoOfBlocks; int j0 = part.FirstBlock; if (!part.AllBlockSizesEqual) { throw new NotSupportedException(); } int Sz = part.GetBlockI0(j0 + 1) - part.GetBlockI0(j0); int[] BlockType = new int[J]; int maxBT = 0; for (int j = 0; j < J; j++) { int blockType = part.GetBlockType(j + j0); BlockType[j] = blockType; maxBT = Math.Max(maxBT, blockType); } int[][] _Subblk_i0 = new int[maxBT + 1][]; int[][] _SubblkLen = new int[maxBT + 1][]; for (int b = 0; b <= maxBT; b++) { _Subblk_i0[b] = part.GetSubblk_i0(b); _SubblkLen[b] = part.GetSubblkLen(b); } return(new BlockPartitioning( part.LocalLength, Sz, _Subblk_i0, _SubblkLen, BlockType, part.MPI_Comm)); }
/// <summary> /// Constructs a block partitioning from a sub-vector index list. /// </summary> /// <param name="B"></param> /// <param name="SubvectorIdx"> /// Indices into <paramref name="B"/> that should be in the result. /// </param> /// <param name="comm"></param> /// <param name="FrameBlockSize"> /// <see cref="IBlockPartitioning.AllBlockSizesEqual"/>; /// The size of the frame block: /// - if negative, not used; in this case, the length of each block can be different and is defined by the sub-blocking, i.e. by <paramref name="_Subblk_i0"/>, <paramref name="_SubblkLen"/> and <paramref name="_BlockType"/>. In this case <see cref="AllBlockSizesEqual"/> is false. /// - if positive, a frame of constant size is assumed around each block, i.e. the index range of the i-th block starts at index i*<paramref name="FrameBlockSize"/>; then <see cref="AllBlockSizesEqual"/> is true. However, the sub-blocking can still differ from block to block. /// </param> /// <returns></returns> public static BlockPartitioning GetSubBlocking <T>(this IBlockPartitioning B, T SubvectorIdx, MPI_Comm comm, int FrameBlockSize = -1) where T : IEnumerable <int> { List <int[]> Subblk_i0 = new List <int[]>(); List <int[]> SubblkLen = new List <int[]>(); List <int> BlockType = new List <int>(); int iCheck = -1; int iCurrentBlock = -1, CurrentBlockType = -12, B_i0 = -1, BLen = -1; int[] B_sblk_i0 = null; int[] B_sblkLen = null; bool[] SblkMarker = null; int LocalLength = 0; List <int> tmp_i0 = new List <int>(); List <int> tmpLen = new List <int>(); int FrameBlkAuto = 0; foreach (int i in SubvectorIdx) { B.TestIfInLocalRange(i); if (i < iCheck) { throw new ArgumentException("Sub-vector indices must be sorted."); } iCheck = i; int iBlock = B.GetBlockIndex(i); if (iBlock != iCurrentBlock) { // block change - need to do something // record actual block if (iCurrentBlock >= 0) { RecordBlock(Subblk_i0, SubblkLen, BlockType, B_sblk_i0, B_sblkLen, SblkMarker, tmp_i0, tmpLen, ref FrameBlkAuto); } // move on to next block iCurrentBlock = iBlock; CurrentBlockType = B.GetBlockType(iBlock); B_sblk_i0 = B.GetSubblk_i0(CurrentBlockType); B_sblkLen = B.GetSubblkLen(CurrentBlockType); B_i0 = B.GetBlockI0(iBlock); BLen = B.GetBlockLen(BLen); if (SblkMarker == null || SblkMarker.Length < BLen) { SblkMarker = new bool[BLen]; } else { Array.Clear(SblkMarker, 0, SblkMarker.Length); } } int iWithin = i - B_i0; Debug.Assert(iWithin >= 0); Debug.Assert(iWithin < BLen); SblkMarker[iWithin] = true; LocalLength++; } // record actual block if (iCurrentBlock >= 0) { RecordBlock(Subblk_i0, SubblkLen, BlockType, B_sblk_i0, B_sblkLen, SblkMarker, tmp_i0, tmpLen, ref FrameBlkAuto); } Debug.Assert(LocalLength == SubvectorIdx.Count()); // Debug.Assert(BlockType.Count == B.LocalNoOfBlocks); // finalize data structure // ----------------------- if (FrameBlockSize == 0) { FrameBlockSize = FrameBlkAuto; } if (FrameBlockSize > 0) { LocalLength = FrameBlockSize * BlockType.Count; } return(new BlockPartitioning(LocalLength, FrameBlockSize, Subblk_i0.ToArray(), SubblkLen.ToArray(), BlockType.ToArray(), comm)); }
/// <summary> /// Permutation matrix from an old to a new partitioning. /// </summary> /// <param name="RowPart">Row partitioning, i.e. new data partitioning.</param> /// <param name="ColPart">Column partitioning, i.e. old data partitioning.</param> /// <param name="tau"> /// Permutation from new to old Indices. /// </param> /// <returns></returns> static BlockMsrMatrix GetRowPermutationMatrix(IBlockPartitioning RowPart, IBlockPartitioning ColPart, Permutation tau) { BlockMsrMatrix P = new BlockMsrMatrix(RowPart, ColPart); //if (RowPart.LocalNoOfBlocks != tau.LocalLength) // throw new ArgumentException(); if (RowPart.TotalNoOfBlocks != tau.TotalLength) { throw new ArgumentException(); } if (!RowPart.AllBlockSizesEqual) { throw new NotSupportedException("unable to perform redistribution for variable size blocking (unable to compute offsets for variable size blocking)."); } if (!ColPart.AllBlockSizesEqual) { throw new NotSupportedException("unable to perform redistribution for variable size blocking (unable to compute offsets for variable size blocking)."); } if (RowPart.TotalLength != ColPart.TotalLength) { throw new ArgumentException(); } int IBlock = RowPart.GetBlockLen(RowPart.FirstBlock); if (ColPart.GetBlockLen(ColPart.FirstBlock) != IBlock) { throw new ArgumentException(); } int J = RowPart.LocalNoOfBlocks; long FB = RowPart.FirstBlock; long[] LocalBlockIdxS = J.ForLoop(i => i + FB); long[] TargetBlockIdxS = new long[LocalBlockIdxS.Length]; tau.EvaluatePermutation(LocalBlockIdxS, TargetBlockIdxS); MultidimensionalArray TempBlock = MultidimensionalArray.Create(IBlock, IBlock); for (int jSrc_Loc = 0; jSrc_Loc < J; jSrc_Loc++) // loop over cells resp. local block-indices { int jSrcGlob = jSrc_Loc + RowPart.FirstBlock; // block-row index int jDstGlob = (int)TargetBlockIdxS[jSrc_Loc]; // block-column index Debug.Assert(RowPart.IsLocalBlock(jSrcGlob)); int i0 = RowPart.GetBlockI0(jSrcGlob); int BT = RowPart.GetBlockType(jSrcGlob); int[] _i0 = RowPart.GetSubblk_i0(BT); int[] Len = RowPart.GetSubblkLen(BT); Debug.Assert(IBlock == RowPart.GetBlockLen(jSrcGlob)); int j0 = IBlock * jDstGlob; // this would not work for variable size blocking #if DEBUG if (ColPart.IsLocalBlock(jDstGlob)) { // column block corresponds to some cell Debug.Assert(IBlock == ColPart.GetBlockLen(jDstGlob)); Debug.Assert(j0 == ColPart.GetBlockI0(jDstGlob)); int CBT = ColPart.GetBlockType(jDstGlob); Debug.Assert(ArrayTools.AreEqual(_i0, ColPart.GetSubblk_i0(CBT))); Debug.Assert(ArrayTools.AreEqual(Len, ColPart.GetSubblkLen(CBT))); } #endif Debug.Assert(_i0.Length == Len.Length); int K = _i0.Length; for (int i = 0; i < IBlock; i++) { TempBlock[i, i] = 0.0; } for (int k = 0; k < K; k++) { int A = _i0[k]; int E = Len[k] + A; for (int i = A; i < E; i++) { TempBlock[i, i] = 1; } } P.AccBlock(i0, j0, 1.0, TempBlock); } return(P); }