# [petsc-users] MatSetValues

Barry Smith bsmith at mcs.anl.gov
Mon Jan 25 13:07:33 CST 2016

> On Jan 25, 2016, at 12:15 PM, Vasileios Kalantzis <kalan019 at umn.edu> wrote:
>
> Dear all,
>
> I am trying to form an approximation of the
> Schur complement S = C-E'*(B\E) of a matrix
> A = [B, E ; E', C]. Matrix C is stored as a
> distributed Mat object while matrices B and E
> are locally distributed to each processor (the
> block partitioning comes from a Domain
> Decomposition point-of-view). All matrices B, E,
> and C are sparse.
>
> I already have a sparse version of -E'*(B\E)
> computed. Moreover, -E'*(B\E)  is block-diagonal.
> The only issue now is how to merge (add) C and
> -E'*(B\E). The way i do the addition right now is
> based on checking every entry of -E'*(B\E) and,
> if larger than a threshold value, add it to C using
> the MatSetValue routine. The above is being done
> in parallel for each diagonal block of -E'*(B\E).
>
> The code works fine numerically but my approach
> is too slow if -E'*(B\E) is not highly sparse.

This is a guess, but if you inserting new nonzero locations into C with MatSetValues() then this will be very slow. Are you inserting new locations?

If so, here is what you need to do. Sweep through the rows of C/-E'*(B\E)  determining the number of nonzeros that will be in the result and then use MatCreateMPIAIJ() or MatMPIAIJSetPreallocation() to preallocate the space in a new matrix, say D. Then sweep through all the rows again actually calling the MatSetValues() and put the entries into D. Switching from non-preallocation to preallocation will speed it up dramatically (factors of 100's or more) if you were inserting new locations.

Barry

>
> I know that I can set many entries together by
> using the MatSetValues routine but I am not
> sure how to do it because the sparsity pattern of
> each column of -E'*(B\E) differs. Maybe I can
> assemble the sparsified Schur complement
> column-by-column using MatSetValues but is
> there any other idea perhaps?
>
> Thanks ! :)