Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manually setting matrix entries #261

Open
mkofler96 opened this issue Mar 4, 2025 · 2 comments
Open

Manually setting matrix entries #261

mkofler96 opened this issue Mar 4, 2025 · 2 comments

Comments

@mkofler96
Copy link

Hello,

I was wondering if it is possible to manually set entries of the matrix in the linear system.

If I look at the example given at the main page, I would like to manually change the sparse matrix AA.

# Form the linear system of equations (AX=B)
A = mfem.OperatorPtr()
B = mfem.Vector()
X = mfem.Vector()
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B)
print("Size of linear system: " + str(A.Height()))

# Solve the linear system using PCG and store the solution in x
AA = mfem.OperatorHandle2SparseMatrix(A)

# works
AA.Set(0, 0, 1)

# does not work
AA.Set(0, 10, 1)

While changinging the entry (0,0) works, because it is already present, adding a new entry at (0,10) gives the following error:

MFEM abort: Could not find entry for row = 0, col = 10
 ... in function: mfem::real_t& mfem::SparseMatrix::SearchRow(int, int)
 ... in file: /__w/PyMFEM/PyMFEM/PyMFEM/external/mfem/linalg/sparsemat.hpp:930

Traceback (most recent call last):
  File "/usr2/mkofler/PyMFEM/examplefrom_git.py", line 43, in <module>
    AA.Set(0, 10, 1)
RuntimeError: PyMFEM error (mfem::ErrorException): MFEM abort: Could not find entry for row = 0, col = 10
 ... in function: mfem::real_t& mfem::SparseMatrix::SearchRow(int, int)
 ... in file: /__w/PyMFEM/PyMFEM/PyMFEM/external/mfem/linalg/sparsemat.hpp:930

Is there another possibility of how I could do this? I was also looking for a way to convert the sparse matrix to a dense matrix and changing the entries there, but I have not found a way of doing this.

I would be happy if someone could help me out here and thanks for the great work.

@sshiraiwa
Copy link
Member

Hi @mkofler96
I guess that the error indicates that you are trying to set the matrix element which is not occupied (non-zero).
A sparsematrix in MFEM is a CSR matrix and it is expensive to change the matrix filling pattern.

My favorite recipe in this situation is to convert the MFEM matrix to scipy's sparse matrix, where you can manipulate more efficiently
using other data format ( including the conversion to full dense matrix.) Then, I put it back to MFEM SparseMatrix.

Converting it to Scipy sparse matrix can be done like

###  this is found in mfem.common.sparse_utils
def sparsemat_to_scipycsr(mat, dtype):
     w, h = mat.Width(), mat.Height()
     I = mat.GetIArray()
     J = mat.GetJArray()
     data = mat.GetDataArray()
     mat.LoseData()
     m1 =csr_matrix((data, J, I), shape = (h, w),
                    dtype = dtype)
     return m1

An example of creating SparseMatrix from scratch is

def run_test():
    print("Test sparsemat module")
    indptr = np.array([0, 2, 3, 6], dtype=np.int32)
    indices = np.array([0, 2, 2, 0, 1, 2], dtype=np.int32)
    data = np.array([1, 2, 3, 4, 5, 6], dtype=float)
    
    mat = mfem.SparseMatrix([indptr, indices, data, 3,3])
    mat.Print()
    mat.PrintInfo()

@v-dobrev, @tzanio : if there is a different way, which can be done by just calling MFEM's API,
please let us know.

@mkofler96
Copy link
Author

Thank you @sshiraiwa vey much for the quick answer, this was exactly what I was looking for.

I also found that there is a method ToDenseMatrix on the mfem._ser.sparsemat.SparseMatrix class. But of course working directly on sparse matrices is way better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants