[petsc-users] Construct Matrix based on row and column values

Elias Karabelas karabelaselias at gmail.com
Wed Apr 8 02:16:40 CDT 2020


Dear Jed,

I'm done implementing my FCT-Solver and it works fairly well on a small 
amount of MPI-Procs. Additionally to your little snippet I have used a 
VecScatterToAll.

Reason is that the flux correction f_i takes the form Sum_{j} alpha_ij 
r_ij where r_ij is defined on the sparsity pattern of my FEM Matrix and 
alpha_ij is based on two vectors Rp and Rm. So basically I need 
off-process values of these vectors to construct alpha which I made with 
a VecScatterToAll. However I guess this will slow down my overall 
program quite significant. Any Ideas?

Best regards

Elias

On 23/03/2020 15:53, Jed Brown wrote:
> Thanks; please don't drop the list.
>
> I'd be curious whether this operation is common enough that we should
> add it to PETSc.  My hesitance has been that people may want many
> different variants when working with systems of equations, for example.
>
> Elias Karabelas <karabelaselias at gmail.com> writes:
>
>> Dear Jed,
>>
>> Yes the Matrix A comes from assembling a FEM-convection-diffusion
>> operator over a tetrahedral mesh. So my matrix graph should be
>> symmetric. Thanks for the snippet
>>
>> On 23/03/2020 15:42, Jed Brown wrote:
>>> Elias Karabelas <karabelaselias at gmail.com> writes:
>>>
>>>> Dear Users,
>>>>
>>>> I want to implement a FCT (flux corrected transport) scheme with PETSc.
>>>> To this end I have amongst other things create a Matrix whose entries
>>>> are given by
>>>>
>>>> L_ij = -max(0, A_ij, A_ji) for i neq j
>>>>
>>>> L_ii = Sum_{j=0,..n, j neq i} L_ij
>>>>
>>>> where Mat A is an (non-symmetric) Input Matrix created beforehand.
>>>>
>>>> I was wondering how to do this. My first search brought me to
>>>> https://www.mcs.anl.gov/petsc/petsc-current/src/mat/examples/tutorials/ex16.c.html
>>>>
>>>>
>>>> but this just goes over the rows of one matrix to set new values and now
>>>> I would need to run over the rows and columns of the matrix. My Idea was
>>>> to just create a transpose of A and do the same but then the row-layout
>>>> will be different and I can't use the same for loop for A and AT and
>>>> thus also won't be able to calculate the max's above.
>>> Does your matrix have symmetric nonzero structure?  (It's typical for
>>> finite element methods.)
>>>
>>> If so, all the indices will match up so I think you can do something like:
>>>
>>> for (row=rowstart; row<rowend; row++) {
>>>     PetscScalar Lvals[MAX_LEN];
>>>     PetscInt diag;
>>>     MatGetRow(A, row, &ncols, &cols, &vals);
>>>     MatGetRow(At, row, &ncolst, &colst, &valst);
>>>     assert(ncols == ncolst); // symmetric structure
>>>     PetscScalar sum = 0;
>>>     for (c=0; c<ncols; c++) {
>>>       assert(cols[c] == colst[c]); // symmetric structure
>>>       if (cols[c] == row) diag = c;
>>>       else sum -= (Lvals[c] = -max(0, vals[c], valst[c]));
>>>     }
>>>     Lvals[diag] = sum;
>>>     MatSetValues(L, 1, &row, ncols, cols, Lvals, INSERT_VALUES);
>>>     MatRestoreRow(A, row, &ncols, &cols, &vals);
>>>     MatRestoreRow(At, row, &ncolst, &colst, &valst);
>>> }


More information about the petsc-users mailing list