Block decomposition allows you to decompose a square matrix into interleaved submatrix blocks (AA, AB, BA, BB). This is commonly used to extract boundary components of a finite element matrix to apply boundary conditions.
- Define Membership: Create a
Vector<bool> where true indicates entries belonging to set 'A' (e.g., boundary nodes) and false indicates set 'B' (interior nodes). - Decompose: Use
blockDecomposeSquare to generate a BlockDecompositionResult. - Partition Vectors: Use
decomposeVector to split a global vector (like a RHS vector) into components for A and B. - Solve and Reassemble: Solve the reduced system using the sub-blocks and
reassembleVector to combine the interior solution and boundary values into a full vector.
// Hypothetical input data
SparseMatrix<double> mat = /* your square matrix */;
size_t N = mat.rows();
size_t NBoundary = /* ... */;
Vector<double> rhsVals = Vector<double>::Zero(N); // rhs for the system
Vector<double> bcVals = Vector<double>::Ones(NBoundary); // boundary values at
// some nodes
// Build the membership vector, which indicates which entries should be separated
// in to set "A" (others are in "B")
Vector<bool> setAMembership(N);
for(size_t i = 0; i < N; i++) {
if(/* element i is boundary */) {
setAMembership(i) = true;
} else {
setAMembership(i) = false;
}
}
// Construct the decomposition
BlockDecompositionResult<double> decomp =
blockDecomposeSquare(mat, setAMembership, true);
// The four sub-blocks of the matrix are now in
// decomp.AA, decomp.AB, decomp.BA, decomp.BB
// Split up the rhs vector
Vector<double> rhsValsA, rhsValsB;
decomposeVector(decomp, rhsVals, rhsValsA, rhsValsB);
// Solve problem
Vector<double> combinedRHS = rhsValsA - decomp.AB * bcVals;
Vector<double> Aresult = solve(decomp.AA, combinedRHS);
// Combine the two boundary conditions and interior solution to a full vector
Vector<double> result = reassembleVector(decomp, Aresult, bcVals);