Beispiel #1
0
        /// <summary>
        /// creates a non-shallow copy
        /// </summary>
        public object Clone()
        {
            var ret = new BlockDiagonalMatrix();

            ret.Blox         = this.Blox.CloneAs();
            ret.m_RowPart    = this.RowPartitioning; // immutable object, so shallow cloning is ok.
            ret.m_ColumnPart = this.ColPartition;
            return(ret);
        }
Beispiel #2
0
        public BlockDiagonalMatrix InvertSymmetrical(bool ignoreEmptyBlocks = false)
        {
            if (this.NoOfRows != this.NoOfCols)
            {
                throw new NotSupportedException("Can't invert non-square matrix.");
            }

            if (this.NoOfRowsPerBlock != this.NoOfColsPerBlock)
            {
                throw new NotSupportedException("Can't invert matrix with non-square blocks.");
            }

            // Matrix for the result
            BlockDiagonalMatrix res = new BlockDiagonalMatrix(RowPartitioning, ColPartition, NoOfRowsPerBlock, NoOfColsPerBlock);

            // FullMatrix to calculate inverse
            var tmp = MultidimensionalArray.Create(this.NoOfRowsPerBlock, NoOfColsPerBlock);

            for (int BlockNo = 0; BlockNo < NoOfBlocks; BlockNo++)
            {
                // Copy values from current block to FullMatrix
                for (int i = 0; i < this.NoOfRowsPerBlock; i++)
                {
                    for (int j = 0; j < this.NoOfColsPerBlock; j++)
                    {
                        tmp[i, j] = this.Blox[BlockNo, i, j];
                    }
                }

                if (ignoreEmptyBlocks && tmp.AbsSum() < 1e-15)
                {
                    // No inversion of empty blocks requested
                    continue;
                }

                // Calculate inverse of FullMatrix
                tmp.InvertSymmetrical();

                // Write inverse of FullMatrix to current block
                for (int i = 0; i < this.NoOfRowsPerBlock; i++)
                {
                    for (int j = 0; j < this.NoOfColsPerBlock; j++)
                    {
                        res.Blox[BlockNo, i, j] = tmp[i, j];
                    }
                }
            }

            return(res);
        }
Beispiel #3
0
        /// <summary>
        /// Calculates the inverse of this matrix and returns the result.
        /// </summary>
        /// <returns>Inverse of this matrix</returns>
        public BlockDiagonalMatrix Invert()
        {
            // Some checks
            if (this.NoOfRows != this.NoOfCols)
            {
                throw new NotSupportedException("Can't invert non-square matrix.");
            }

            if (this.NoOfRowsPerBlock != this.NoOfColsPerBlock)
            {
                throw new NotSupportedException("Can't invert matrix with non-square blocks.");
            }

            // Matrix for the result
            BlockDiagonalMatrix res = new BlockDiagonalMatrix(RowPartitioning, ColPartition, NoOfRowsPerBlock, NoOfColsPerBlock);

            // FullMatrix to calculate inverse
            for (int BlockNo = 0; BlockNo < NoOfBlocks; BlockNo++)
            {
                var tmp = MultidimensionalArray.Create(this.NoOfRowsPerBlock, NoOfColsPerBlock);
                // Copy values from current block to FullMatrix
                for (int i = 0; i < this.NoOfRowsPerBlock; i++)
                {
                    for (int j = 0; j < this.NoOfColsPerBlock; j++)
                    {
                        tmp[i, j] = this.Blox[BlockNo, i, j];
                    }
                }

                // Calculate inverse of FullMatrix
                var BlockInverse = tmp.GetInverse();

                // Write inverse of FullMatrix to current block
                for (int i = 0; i < this.NoOfRowsPerBlock; i++)
                {
                    for (int j = 0; j < this.NoOfColsPerBlock; j++)
                    {
                        res.Blox[BlockNo, i, j] = BlockInverse[i, j];
                    }
                }
            }

            return(res);
        }
Beispiel #4
0
        /// <summary>
        /// multiplies an <see cref="BlockDiagonalMatrix"/> by an <see cref="MsrMatrix"/>
        /// </summary>
        public static MsrMatrix Multiply(BlockDiagonalMatrix left, MsrMatrix right)
        {
            using (new FuncTrace()) {
                if (left.NoOfCols != right.NoOfRows)
                {
                    throw new ArgumentException("matrix size mismatch");
                }

                int _N = left.NoOfRowsPerBlock; // left blocks: no. of rows
                int _M = left.NoOfColsPerBlock; // left blocks: no. of columns = right blocks: no. of rows
                int _L = _M;                    // right blocks: no. of columns. Hope that fits, otherwise inefficient

                MsrMatrix result = new MsrMatrix(left.RowPartitioning, right.ColPartition);

                MultidimensionalArray lBlock = MultidimensionalArray.Create(_N, _M);
                //MsrMatrix.MSREntry[][] BlockRow = new MsrMatrix.MSREntry[_M][];
                //List<int> OccupiedBlocks = new List<int>();
                var OccupiedBlocks = new SortedDictionary <int, MultidimensionalArray>();
                List <MultidimensionalArray> MatrixPool = new List <MultidimensionalArray>(); // avoid realloc
                int poolCnt = 0;

                MultidimensionalArray resBlock = MultidimensionalArray.Create(_N, _L);

                // loop over all blocks ...
                int NoBlks = left.m_RowPart.LocalLength / left.NoOfRowsPerBlock;
                for (int iBlk = 0; iBlk < NoBlks; iBlk++)
                {
                    // reset:
                    OccupiedBlocks.Clear();
                    poolCnt = 0;
                    foreach (var M in MatrixPool)
                    {
                        M.Clear();
                    }

                    // upper left corner of block
                    int i0 = iBlk * _N + (int)left.RowPartitioning.i0;
                    int j0 = (i0 / _N) * _M;

                    // load block
                    for (int n = 0; n < _N; n++)
                    {
                        for (int m = 0; m < _M; m++)
                        {
                            lBlock[n, m] = left.Blox[iBlk, n, m];
                        }
                    }

                    // read Msr rows
                    int Last_rBlkCol            = int.MinValue;
                    MultidimensionalArray Block = null;
                    for (int m = 0; m < _N; m++)
                    {
                        var BlockRow = right.GetRowShallow(j0 + m);
                        foreach (var e in BlockRow)
                        {
                            if (e.m_ColIndex >= 0)
                            {
                                int rBlkCol = e.m_ColIndex / _L;

                                if (rBlkCol != Last_rBlkCol)
                                {
                                    if (!OccupiedBlocks.TryGetValue(rBlkCol, out Block))
                                    {
                                        if (MatrixPool.Count <= poolCnt)
                                        {
                                            MatrixPool.Add(MultidimensionalArray.Create(_M, _L));
                                        }

                                        Block = MatrixPool[poolCnt];
                                        OccupiedBlocks.Add(rBlkCol, Block);
                                        poolCnt++;
                                    }

                                    Last_rBlkCol = rBlkCol;
                                }

                                int jj = e.m_ColIndex % _L;

                                Block[m, jj] = e.Value;
                            }
                        }
                    }
                    Block = null;

                    // execute multiplys
                    foreach (KeyValuePair <int, MultidimensionalArray> rBlock in OccupiedBlocks)
                    {
                        resBlock.GEMM(1.0, lBlock, rBlock.Value, 0.0);

                        // upper left edge of resBlock
                        int _i0 = i0;
                        int _j0 = rBlock.Key * _L;

                        // write block
                        for (int i = 0; i < _M; i++)
                        {
                            for (int j = 0; j < _L; j++)
                            {
                                result[i + _i0, j + _j0] = resBlock[i, j];
                            }
                        }
                    }
                }


                // return
                return(result);
            }
        }