<div dir="ltr"><div>Is it possible to set the size of the COMPACT matrix as large as the WIDE matrix, then do MatAYPX(WIDE, 0, COMPACT, SUBSET_NONZERO_PATTERN), i.e, WIDE = 0*WIDE + COMPACT? You need to build WIDE upfront once, but if you repeat, the other MatAYPX will be fast.</div><div><br></div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">--Junchao Zhang</div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Sep 26, 2024 at 1:13 PM Barry Smith <<a href="mailto:bsmith@petsc.dev">bsmith@petsc.dev</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Frank,<br>
<br>
Sorry for the confusion. MatCopy() and MatAXPY() only work for identically sized matrices.<br>
<br>
Even if the two matrices are the same size but one, say A, has a subset of nonzeros than the other, say B, what you want to do is non-trivial. This is because to do a copy you must MatAssembly the matrix first and this squeezes out the zero locations that you would like to fill in B.<br>
<br>
A simple solution is in the code that computes the subset of entries, call MatSetValues() twice, once for A and once for B. Not entirely satisfying but it will work and be reasonably efficient.<br>
<br>
<br>
Barry<br>
<br>
<br>
> On Sep 26, 2024, at 1:50 PM, Frank Bramkamp <<a href="mailto:bramkamp@nsc.liu.se" target="_blank">bramkamp@nsc.liu.se</a>> wrote:<br>
> <br>
> Dear PETSc team,<br>
> <br>
> <br>
> I would like to create two matrices. The first matrix is based on a compact stencil (COMPACT), and the second one has an extended stencil (WIDE)<br>
> So the non-zero elements of the COMPACT matrix is contained in the WIDE matrix as well. But the WIDE matrix shall contain some additional elements.<br>
> I try to create the COMPACT matrix first, then copy it to the WIDE matrix and then add some more terms to the WIDE matrix.<br>
> We want to create a matrix that is based on a lower order approximation of our scheme which serves as basis matrix for preconditioning,<br>
> where we want to have a more accurate jacobian which has a larger stencil, that is based on the lower approximation plus some additional non-zero elements.<br>
> We want to avoid that we have to call the same routines twice to setup the more accurate matrix, but copy the elements from the lower order (compact) matrix.<br>
> <br>
> <br>
> I try to use MatCopy to copy the COMPACT matrix into the WIDE matrix. Somehow I cannot figure out to do this,<br>
> since there is always a problem wirh non conforming sizes<br>
> <br>
> [0]PETSC ERROR: Nonconforming object sizes<br>
> [0]PETSC ERROR: Mat A,Mat B: global dim (4,8) (4,8)<br>
> <br>
> <br>
> Here is a basic example that I try.<br>
> Adding additional elements to the WIDE matrix is disabled right now, since MatCopy already gives a problem.<br>
> I thought that in MatCopy(COMPACT, WIDE, DIFFERENT_NONZERO_PATTERN, ierr)<br>
> the option DIFFERENT_NONZERO_PATTERN should enable to copy different matrix sizes into each other.<br>
> Or is that not possible to do ?!<br>
> <br>
> Here the COMPACT matrix is a 4x4 matrix and the WIDE matrix 8x8, for a basic test.<br>
> <br>
> Thanks, Frank Bramkamp<br>
> <br>
> <br>
> <br>
> <br>
> program petsc_matrix_example<br>
> #include <petsc/finclude/petsc.h><br>
> use petsc<br>
> implicit none<br>
> <br>
> PetscErrorCode :: ierr<br>
> Mat :: COMPACT, WIDE<br>
> PetscInt :: m, n, MM, NN, d_nz<br>
> PetscInt :: i, j<br>
> PetscScalar :: additional_value<br>
> <br>
> ! Initialize PETSc<br>
> call PetscInitialize(PETSC_NULL_CHARACTER, ierr)<br>
> <br>
> ! Set dimensions for COMPACT matrix<br>
> m = 4 ! Local rows<br>
> n = 4 ! Local columns<br>
> MM = 4 ! Global rows<br>
> NN = 4 ! Global columns<br>
> d_nz = 4 ! Estimated non-zeros per row (diagonal) o_nz = 0 ! Estimated non-zeros per row (off-diagonal)<br>
> <br>
> ! Create COMPACT matrix<br>
> call MatCreateSeqAIJ(PETSC_COMM_SELF, MM, NN, PETSC_DECIDE, PETSC_NULL_INTEGER, COMPACT, ierr)<br>
> <br>
> ! Set some values in COMPACT matrix (example) do i = 0, M-1<br>
> do i = 0, NN-1<br>
> !do j = max(0, i-1), min(NN-1, i+1)<br>
> do j = 0,NN-1<br>
> call MatSetValue(COMPACT, i, j, 1.0_PETSC_REAL_KIND, INSERT_VALUES, ierr)<br>
> end do<br>
> end do<br>
> <br>
> ! Assemble COMPACT matrix<br>
> call MatAssemblyBegin(COMPACT, MAT_FINAL_ASSEMBLY, ierr)<br>
> call MatAssemblyEnd(COMPACT, MAT_FINAL_ASSEMBLY, ierr)<br>
> <br>
> ! Set dimensions for WIDE matrix<br>
> n = 8 ! Increase local columns<br>
> NN = 8 ! Increase global columns<br>
> m = 8<br>
> MM = 8<br>
> d_nz = 8<br>
> <br>
> ! Create WIDE matrix<br>
> call MatCreateSeqAIJ(PETSC_COMM_SELF, MM, NN, PETSC_DECIDE, PETSC_NULL_INTEGER, WIDE, ierr)<br>
> <br>
> ! Assemble WIDE matrix: MUST WE ASSMBLE THE MATRIX BEFORE MatCOPY ?!<br>
> call MatAssemblyBegin(WIDE, MAT_FINAL_ASSEMBLY, ierr) <br>
> call MatAssemblyEnd(WIDE, MAT_FINAL_ASSEMBLY, ierr)<br>
> <br>
> ! Copy elements from COMPACT to WIDE<br>
> call MatCopy(COMPACT, WIDE, DIFFERENT_NONZERO_PATTERN, ierr)<br>
> <br>
> <br>
> <br>
> !call MatAssemblyBegin(WIDE, MAT_FINAL_ASSEMBLY, ierr) <br>
> <br>
> ! Add additional elements to WIDE matrix<br>
> !!$ additional_value = 10.0<br>
> !!$<br>
> !!$ ! original<br>
> !!$ !do i = 0, MM-1<br>
> !!$ ! do j = NN/2, NN-1<br>
> !!$ ! call MatSetValue(WIDE, i, j, additional_value, INSERT_VALUES, ierr)<br>
> !!$ ! end do<br>
> !!$ !end do<br>
> !!$<br>
> !!$ do i = 0, NN-1<br>
> !!$ do j = max(0, i-1), min(NN-1, i+1)<br>
> !!$ call MatSetValue(WIDE, i, j, 10.0_PETSC_REAL_KIND, ADD_VALUES, ierr)<br>
> !!$ end do<br>
> !!$ end do<br>
> <br>
> <br>
> ! Assemble WIDE matrix again<br>
> call MatAssemblyBegin(WIDE, MAT_FINAL_ASSEMBLY, ierr)<br>
> call MatAssemblyEnd(WIDE, MAT_FINAL_ASSEMBLY, ierr)<br>
> <br>
> ! View matrices (optional)<br>
> call PetscPrintf(PETSC_COMM_WORLD, "COMPACT matrix:\n", ierr)<br>
> call MatView(COMPACT, PETSC_VIEWER_STDOUT_WORLD, ierr)<br>
> call PetscPrintf(PETSC_COMM_WORLD, "WIDE matrix:\n", ierr)<br>
> call MatView(WIDE, PETSC_VIEWER_STDOUT_WORLD, ierr)<br>
> <br>
> ! Clean up<br>
> call MatDestroy(COMPACT, ierr)<br>
> call MatDestroy(WIDE, ierr)<br>
> <br>
> ! Finalize PETSc<br>
> call PetscFinalize(ierr)<br>
> <br>
> end program petsc_matrix_example<br>
> <br>
> <br>
<br>
</blockquote></div>