Exemple #1
0
        /// <summary>
        /// Calculates the Schur complement of M/C = S = A - B^T * inv(C) * B, where M = [A B; B^T C].
        /// This method constructs inv(C) * B one column at a time and uses that column to calculate the superdiagonal
        /// entries of the corresponding column of B^T * inv(C) * B.
        /// </summary>
        public static SymmetricMatrix CalcSchurComplementSymmetric(SymmetricMatrix A, CscMatrix B, ITriangulation inverseC)
        { //TODO: Unfortunately this cannot take advantage of MKL for CSC^T * vector.
            double[] valuesB     = B.RawValues;
            int[]    rowIndicesB = B.RawRowIndices;
            int[]    colOffsetsB = B.RawColOffsets;
            var      S           = SymmetricMatrix.CreateZero(A.Order);

            for (int j = 0; j < B.NumColumns; ++j)
            {
                // column j of (inv(C) * B) = inv(C) * column j of B
                Vector   colB     = B.GetColumn(j);
                double[] colInvCB = inverseC.SolveLinearSystem(colB).RawData;

                // column j of (B^T * inv(C) * B) = B^T * column j of (inv(C) * B)
                // However we only need the superdiagonal part of this column.
                // Thus we only multiply the rows i of B^T (stored as columns i of B) with i <= j.
                for (int i = 0; i <= j; ++i)
                {
                    double dot      = 0.0;
                    int    colStart = colOffsetsB[i];     //inclusive
                    int    colEnd   = colOffsetsB[i + 1]; //exclusive
                    for (int k = colStart; k < colEnd; ++k)
                    {
                        dot += valuesB[k] * colInvCB[rowIndicesB[k]];
                    }

                    // Perform the subtraction S = A - (B^T * inv(C) * B) for the current (i, j)
                    int indexS = S.Find1DIndex(i, j);
                    S.RawData[indexS] = A.RawData[indexS] - dot;
                }
            }

            return(S);
        }
        public void SolveLinearSystems(CscMatrix rhsVectors, Matrix solutionVectors)
        {
            Preconditions.CheckSystemSolutionDimensions(this.NumRows, rhsVectors.NumRows);
            Preconditions.CheckMultiplicationDimensions(this.Order, solutionVectors.NumRows);
            Preconditions.CheckSameColDimension(rhsVectors, solutionVectors);

            for (int j = 0; j < rhsVectors.NumColumns; ++j)
            {
                double[] rhsColumn = rhsVectors.GetColumn(j).RawData;
                int      offset    = j * NumRows;
                SolveWithOffsets(Order, values, diagOffsets, rhsColumn, 0, solutionVectors.RawData, offset);
            }
        }