/// <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());
        }
Beispiel #2
0
        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));
        }
Beispiel #4
0
        /// <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);
        }