/// <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); } }