feat(poly): refactoring PolytropeOperator to work on the reduced system so as to avoid rank deficiencies
This commit is contained in:
@@ -1,5 +1,96 @@
|
||||
//
|
||||
// Created by Emily Boudreaux on 6/4/25.
|
||||
//
|
||||
|
||||
#include "utilities.h"
|
||||
#include "mfem.hpp"
|
||||
|
||||
namespace serif::utilities {
|
||||
mfem::SparseMatrix buildReducedMatrix(
|
||||
const mfem::SparseMatrix& matrix,
|
||||
const mfem::Array<int>& trialEssentialDofs,
|
||||
const mfem::Array<int>& testEssentialDofs
|
||||
) {
|
||||
int M_orig = matrix.Height();
|
||||
int N_orig = matrix.Width();
|
||||
|
||||
// 1. Create boolean lookup tables for eliminated rows/columns
|
||||
// These tables help quickly check if an original row/column index is eliminated.
|
||||
mfem::Array<bool> row_is_eliminated(M_orig);
|
||||
row_is_eliminated = false; // Initialize all to false (no rows eliminated yet)
|
||||
for (int i = 0; i < testEssentialDofs.Size(); ++i) {
|
||||
int r_idx = testEssentialDofs[i];
|
||||
if (r_idx >= 0 && r_idx < M_orig) { // Check for valid index
|
||||
row_is_eliminated[r_idx] = true;
|
||||
}
|
||||
}
|
||||
|
||||
mfem::Array<bool> col_is_eliminated(N_orig);
|
||||
col_is_eliminated = false; // Initialize all to false (no columns eliminated yet)
|
||||
for (int i = 0; i < trialEssentialDofs.Size(); ++i) {
|
||||
int c_idx = trialEssentialDofs[i];
|
||||
if (c_idx >= 0 && c_idx < N_orig) { // Check for valid index
|
||||
col_is_eliminated[c_idx] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Create mappings from old (original) indices to new indices
|
||||
// Also, count the number of rows and columns in the new, reduced matrix.
|
||||
mfem::Array<int> old_row_to_new_row(M_orig);
|
||||
int num_new_rows = 0;
|
||||
for (int i = 0; i < M_orig; ++i) {
|
||||
if (row_is_eliminated[i]) {
|
||||
old_row_to_new_row[i] = -1; // Mark as eliminated (no corresponding new row)
|
||||
} else {
|
||||
old_row_to_new_row[i] = num_new_rows++; // Assign the next available new row index
|
||||
}
|
||||
}
|
||||
|
||||
mfem::Array<int> old_col_to_new_col(N_orig);
|
||||
int num_new_cols = 0;
|
||||
for (int i = 0; i < N_orig; ++i) {
|
||||
if (col_is_eliminated[i]) {
|
||||
old_col_to_new_col[i] = -1; // Mark as eliminated (no corresponding new column)
|
||||
} else {
|
||||
old_col_to_new_col[i] = num_new_cols++; // Assign the next available new column index
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Create the new sparse matrix with the calculated reduced dimensions.
|
||||
// It's initially empty (no non-zero entries).
|
||||
mfem::SparseMatrix A_new(num_new_rows, num_new_cols);
|
||||
|
||||
// 4. Iterate through the non-zero entries of the original matrix (A_orig).
|
||||
// A_orig is typically stored in Compressed Sparse Row (CSR) format.
|
||||
// GetI() returns row pointers, GetJ() returns column indices, GetData() returns values.
|
||||
const int* I_orig = matrix.GetI();
|
||||
const int* J_orig = matrix.GetJ();
|
||||
const double* V_orig = matrix.GetData(); // Assuming double, can be templated if needed
|
||||
|
||||
for (int r_orig = 0; r_orig < M_orig; ++r_orig) {
|
||||
// If the original row is marked for elimination, skip all its entries.
|
||||
if (row_is_eliminated[r_orig]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the new row index for the current original row.
|
||||
int r_new = old_row_to_new_row[r_orig];
|
||||
|
||||
// Iterate through non-zero entries in the current original row r_orig.
|
||||
// I_orig[r_orig] is the start index in J_orig and V_orig for row r_orig.
|
||||
// I_orig[r_orig+1]-1 is the end index.
|
||||
for (int k = I_orig[r_orig]; k < I_orig[r_orig + 1]; ++k) {
|
||||
int c_orig = J_orig[k]; // Original column index of the non-zero entry
|
||||
double val = V_orig[k]; // Value of the non-zero entry
|
||||
|
||||
if (col_is_eliminated[c_orig]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int c_new = old_col_to_new_col[c_orig];
|
||||
|
||||
A_new.Add(r_new, c_new, val);
|
||||
}
|
||||
}
|
||||
|
||||
A_new.Finalize();
|
||||
|
||||
return A_new;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user