/// <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); }
/// <summary> /// Solves the linear system A * x = b, where A is the original matrix (before the factorization), /// b = <paramref name="rhsVector"/> and x is the solution vector, which will be returned. /// </summary> /// <param name="rhsVector"> /// The right hand side vector. Its <see cref="IIndexable1D.Length"/> must be equal to /// <see cref="Matrices.IIndexable2D.NumRows"/> of the original matrix A. /// </param> /// Thrown if the length of <paramref name="rhsVector"/> is different than <see cref="Matrices.IIndexable2D.NumRows"/> /// of the original matrix A. /// </exception> public static Vector SolveLinearSystem(this ITriangulation triangulation, Vector rhsVector) { var solution = Vector.CreateZero(triangulation.Order); triangulation.SolveLinearSystem(rhsVector, solution); return(solution); }