[petsc-users] Construct Matrix based on row and column values
Elias Karabelas
karabelaselias at gmail.com
Wed Apr 15 03:36:59 CDT 2020
Hi Junchao,
This seems to work.
Thanks
Elias
On 08/04/2020 19:02, Junchao Zhang wrote:
> Hi, Elias,
> VecScatterToAll is implemented with MPI_Allgatherv. If not large
> scale, I guess it won't be a problem. I assume you want to assemble a
> MATMPIAIJ D with
> D_ij = L_ij * (u[i] - u[j])
> Since D has the same sparsity pattern as L, we may have (not tested),
>
> Mat A,B;
> const PetscInt *garray,*cols;
> VecScatter vscat;
> PetscInt i,j,m,n,ncols;
> Vec ur;
> PetscScalar *ulocal,*uremote,val,*vals;
> IS from,to;
> ierr = MatMPIAIJGetSeqAIJ(L,&A,&B,&garray);CHKERRQ(ierr);
> ierr = MatGetSize(B,&NULL,&n);CHKERRQ(ierr); /* garray[]'s length = n */
> ierr = VecCreateSeq(PETSC_COMM_SELF,n,&ur);CHKERRQ(ierr); /* ur stores
> needed off-proc entries of u */
> ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);
> ierr =
> ISCreateGeneral(PETSC_COMM_SELF,n,garray,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
> ierr = VecScatterCreate(u,from,ur,to,&vscat);CHKERRQ(ierr); /* vscat
> is D's Mvctx, which however is not exposed to users */
> ierr =
> VecScatterBegin(vscat,u,ur,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
> ierr =
> VecScatterEnd(vscat,u,ur,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
> ierr = VecGetArrayRead(u,&ulocal);CHKERRQ(ierr);
> ierr = VecGetArrayRead(ur,&uremote);CHKERRQ(ierr);
> ierr = MatGetOwnershipRange(D,&rstart,NULL);CHKERRQ(ierr);
> ierr = MatGetOwnershipRangeColumn(D,&cstart,NULL);
> ierr = MatDuplicate(L,&D,MAT_DO_NOT_COPY_VALUES);CHKERRQ(ierr);
> ierr =
> MatSetOption(D,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
> ierr = MatAssemblyBegin(D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
> ierr = MatGetSize(A,&m,NULL);CHKERRQ(ierr);
> for (i=0; i<m; i++) {
> ierr = MatGetRow(A,i,ncols,cols,vals);
> for (j=0; j<ncols; j++) {
> val = vals[j]*(ulocal[i] - ulocal[cols[j]]);
> ierr =
> MatSetValue(D,rstart+i,cstart+cols[j],val,INSERT_VALUES);CHKERRQ(ierr);
> }
> ierr = MatGetRow(B,i,ncols,cols,vals);
> for (j=0; j<ncols; j++) {
> val = vals[j]*(ulocal[i] - uremote[cols[j]]);
> ierr =
> MatSetValue(D,rstart+i,garray[cols[j]],val,INSERT_VALUES);CHKERRQ(ierr);
> }
> }
> ierr = MatAssemblyEnd(D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
> ierr = VecRestoreArrayRead(u,&ulocal);CHKERRQ(ierr);
> ierr = VecRestoreArrayRead(ur,&uremote);CHKERRQ(ierr);
>
> --Junchao Zhang
>
> On Wed, Apr 8, 2020 at 2:17 AM Elias Karabelas
> <karabelaselias at gmail.com <mailto:karabelaselias at gmail.com>> wrote:
>
> 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
> <mailto: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
> <mailto: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);
> >>> }
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-users/attachments/20200415/79dc3ebf/attachment-0001.html>
More information about the petsc-users
mailing list