Il 31/08/21 17:32, Jed Brown ha scritto:
Matteo Semplice <[email protected]> writes:

Hi.

We are writing a code for a FD scheme on an irregular domain and thus
the local stencil is quite variable: we have inner nodes, boundary nodes
and inactive nodes, each with their own stencil type and offset with
respect to the grid node. We currently create a matrix with
DMCreateMatrix on a DMDA and for now have set the option
MAT_NEW_NONZERO_LOCATIONS to PETSC_TRUE, but its time to render the code
memory-efficient. The layout created automatically is correct for inner
nodes, wrong for boundary ones (off-centered stencils) and redundant for
outer nodes.

After the preprocessing stage (including stencil creation) we'd be in
position to set the nonzero pattern properly.

Do we need to start from a Mat created by CreateMatrix? Or is it ok to
call DMCreateMatrix (so that the splitting among CPUs and the block size
are set by PETSc) and then call a MatSetPreallocation routine?
You can call MatXAIJSetPreallocation after. It'll handle all matrix types so 
you don't have to shepherd data for all the specific preallocations.

Hi.

Actually I am still struggling with this... Let me explain.

My code relies on a SNES and the matrix I need to preallocate is the Jacobian. So I do:

in the main file
  ierr = DMCreateMatrix(ctx.daAll,&ctx.J);CHKERRQ(ierr);
  ierr = setJacobianPattern(ctx,ctx.J);CHKERRQ(ierr); //calling MatXAIJSetPreallocation on the second argument   ierr = MatSetOption(ctx.J,MAT_NEW_NONZERO_LOCATIONS,*******); CHKERRQ(ierr);//allow new nonzeros?

  ierr = SNESSetFunction(snes,ctx.F      ,FormFunction,(void *) &ctx); CHKERRQ(ierr);   ierr = SNESSetJacobian(snes,ctx.J,ctx.J,FormJacobian,(void *) &ctx); CHKERRQ(ierr);

  ierr = FormSulfationRHS(ctx, ctx.U0, ctx.RHS);CHKERRQ(ierr);
  ierr = SNESSolve(snes,ctx.RHS,ctx.U); CHKERRQ(ierr);

and

PetscErrorCode FormJacobian(SNES snes,Vec U,Mat J, Mat P,void *_ctx)

does (this is a 2 dof finite difference problem, so logically 2x2 blocks in J)

    ierr = setJac00(....,P) //calls to MatSetValues in the 00 block

    ierr = setJac01(....,P) //calls to MatSetValues in the 01 block

    ierr = setJac1X(....,P) //calls to MatSetValues in the 10 ans 11 block

    ierr = MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
    ierr = MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);

If I run with MAT_NEW_NONZERO_LOCATIONS=TRUE, all runs fine and using the -info option I see that no mallocs are performed during Assembly.

Computing F
  0 SNES Function norm 7.672682917097e+02
Computing J
[0] MatAssemblyEnd_SeqAIJ(): Matrix size: 71874 X 71874; storage space: 17661 unneeded,191714 used
[0] MatAssemblyEnd_SeqAIJ(): Number of mallocs during MatSetValues() is 0
[0] MatAssemblyEnd_SeqAIJ(): Maximum nonzeros in any row is 27
[0] MatCheckCompressedRow(): Found the ratio (num_zerorows 0)/(num_localrows 71874) < 0.6. Do not use CompressedRow routines.

If I omit the call to setJacobianPattern, info reports a nonsero number of mallocs, so somehow the setJacobianPattern routine should be doing its job correctly.

However, if I run with MAT_NEW_NONZERO_LOCATIONS=FALSE, the Jacobian is entirely zero and no error messages appear until the KSP tries to do its job:

Computing F
  0 SNES Function norm 7.672682917097e+02
Computing J
[0] MatAssemblyEnd_SeqAIJ(): Matrix size: 71874 X 71874; storage space: 209375 unneeded,0 used
[0] MatAssemblyEnd_SeqAIJ(): Number of mallocs during MatSetValues() is 0
[0] MatAssemblyEnd_SeqAIJ(): Maximum nonzeros in any row is 0
[0] MatCheckCompressedRow(): Found the ratio (num_zerorows 71874)/(num_localrows 71874) > 0.6. Use CompressedRow routines.
... and then KSP complains!

I have tried adding MAT_FLUSH_ASSEMBLY calls inside the subroutines, but nothing changes.

So I have 2 questions:

1. If, as a temporary solution, I leave MAT_NEW_NONZERO_LOCATIONS=TRUE, am I going to incur in performance penalties even if no new nonzeros are created by my assembly routine?

2. Can you guess what is causing the problem?

Thanks

    Matteo






Reply via email to