Dear Jed,

Thanks I will try to keep you updated. So I managed to get my stuff running with one process but it fails with more than one. The matrix assembly as you described it works fine but I forgot that in the FCT algorithm one also needs to assemble a matrix D that looks kinda like

D_ij = L_ij * (u[i] - u[j])

where u is a vector with solution data from a previous time step. So the problem is that I have to now access off-process values of the Vector u, and doing this for each row of D. My basic first idea was to utilize the VecScatter Example from the Petsc Manual to get the off-process values per row of L to build this matrix D. But somehow this does not really work. Any ideas on how to scatter the Vector-data so that I can get the correct Vector values ?

At the moment I'm using something along this lines (in a loop where I get the local array of u with VecGetArray --> u_arr)

MatGetRow(L, row, &ncolsL, &colsL, &valsL);

double * Dvals = new double[ncolsM]();
int * idx_to = new int[ncolsL]();
for(int k=0; k < ncolsM; k++)

    idx_to[k] = k;
MPI_Barrier(PETSC_COMM_WORLD);
//Scatter the right stuff
Vec x;
VecScatter scatter;
IS from, to;
double *vals;
VecCreateSeq(PETSC_COMM_SELF, ncolsL, &x);
ISCreateGeneral(PETSC_COMM_SELF,ncolsL,colsL,PETSC_COPY_VALUES,&from);
ISCreateGeneral(PETSC_COMM_SELF,ncolsL,idx_to,PETSC_COPY_VALUES,&to);
VecScatterCreate(u,from,x,to,&scatter);
VecScatterBegin(scatter,u,x,INSERT_VALUES,SCATTER_FORWARD);
VecScatterEnd(scatter,u,x,INSERT_VALUES,SCATTER_FORWARD);
VecGetArray(x,&vals);
for(int c=0; c < ncolsL; c++)
{
    Dvals[c] = valsL[c] * (vals[c] -  u_arr[row])

}

MatSetValues(D, 1, &row, ncolsL, colsL, Dvals, ADD_VALUES);

and so on...

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 <karabelasel...@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 <karabelasel...@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);
}

Reply via email to