Hello,

My question is related to solving a generic nonlinear algebraic system in parallel. I'm using the word generic to point to the fact that the system may or may not be from a finite element/mesh type object - it's just a residual function and a Jacobian function that I can provide.

I followed the serial example in $PETSC_DIR/src/snes/tutorials/ex1.c pretty much verbatim (albeit with a slightly different objective function whose size can be controlled), and have been trying to extend it to a parallel application (the given example is strictly serial).

When I run my code in serial everything works well and I get the solution I expect. However, even if I use just two cores, the code starts returning garbage. I had a feeling it has something to do with index ordering, but I want to get this code working without using a DM object. I'm attaching my code with this email.

TL;DR Version: What modifications must be made in "$PETSC_DIR/src/snes/tutorials/ex1.c" to make it work in Parallel? Is it possible to make minimal modifications to make it run in parallel too?

Thank You,
Nidish
static char help[] = "Nonlinear Solution Trial\n";

#include <petscsnes.h>
#include <petscdmda.h>

PetscErrorCode NLFUN(SNES, Vec, Vec, void*);
PetscErrorCode NLJAC(SNES, Vec, Mat, Mat, void*);

int main(int nargs, char *sargs[])
{
  PetscInt ierr;
  PetscMPIInt rank, size;
  ierr = PetscInitialize(&nargs, &sargs, (char*)0, help); if (ierr) return ierr;
  MPI_Comm_size(PETSC_COMM_WORLD, &size);
  MPI_Comm_rank(PETSC_COMM_WORLD, &rank);

  PetscInt N=5;
  PetscScalar Fb[] = {30, 2.5};
  SNES snes;
  KSP ksp;
  PC pc;
  Vec x, r;
  Mat J;
  PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL);
  PetscOptionsGetScalar(NULL, NULL, "-F", &Fb[0], NULL);
  PetscOptionsGetScalar(NULL, NULL, "-b", &Fb[1], NULL);

  PetscPrintf(PETSC_COMM_WORLD, "%d\n", N);
  
  SNESCreate(PETSC_COMM_WORLD, &snes);

  MatCreate(PETSC_COMM_WORLD, &J);
  MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, N, N);
  MatSetFromOptions(J);
  MatSetUp(J);

  MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);
  MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);
  
  MatCreateVecs(J, &x, &r);
  VecSetFromOptions(x);
  VecSetFromOptions(r);

  /* PetscInt m, n; */
  /* MatGetLocalSize(J, &m, &n); */
  /* MatMPIAIJSetPreallocation(J, 3, NULL, N-3, NULL); */
  
  SNESSetFunction(snes, r, NLFUN, (void*)Fb);
  SNESSetJacobian(snes, J, J, NLJAC, (void*)Fb);

  SNESGetKSP(snes, &ksp);
  KSPGetPC(ksp, &pc);
  PCSetType(pc, PCNONE);
  PCSetFromOptions(pc);
  KSPSetFromOptions(ksp);

  SNESSetFromOptions(snes);

  /* Initial Guess ***********************************************************/
  /* VecSetValue(r, N-1, Fb, INSERT_MODE); */
  VecSet(r, 0.0);
  
  VecAssemblyBegin(r);
  
  VecSet(x, sqrt((PetscScalar)N));

  VecAssemblyBegin(x);
  VecAssemblyEnd(r);
  VecAssemblyEnd(x);

  ierr = SNESSolve(snes, NULL, x); CHKERRQ(ierr);

  VecAssemblyBegin(x);
  VecAssemblyBegin(r);
  VecAssemblyEnd(x);
  VecAssemblyEnd(r);

  SNESDestroy(&snes);
  VecDestroy(&x);
  MatDestroy(&J);
  PetscFinalize();
  return 0;
}

PetscErrorCode NLFUN(SNES snes, Vec x, Vec f, void* ctx)
{
  PetscErrorCode ierr;
  /* const PetscScalar *xx; */
  PetscScalar* xx;
  PetscScalar* Fb = (PetscScalar*) ctx;
  /* PetscScalar xnrm; */
  
  PetscInt is, ie, N;
  VecGetSize(x, &N);
  VecGetOwnershipRange(x, &is, &ie);
  /* VecGetArrayRead(x, &xx); */
  VecGetArray(x, &xx);  
  for (int i=is; i<ie; ++i)
    if (i==0)
      VecSetValue(f, i, 2*xx[i -is]-xx[i+1 -is], INSERT_VALUES);
    else if (i<N-1)
      VecSetValue(f, i, -xx[i-1 -is]+2*xx[i -is]-xx[i+1 -is], INSERT_VALUES);
    else if (i==N-1) {
      /* VecNorm(x, NORM_2, &xnrm); */
      /* VecSetValue(f, i, 0.5*(xnrm*xnrm-N*N), INSERT_VALUES); */

      VecSetValue(f, i, -xx[i-1 -is]+xx[i -is]+Fb[1]*pow(xx[i -is], 3)-Fb[0], INSERT_VALUES);
    }
  VecAssemblyBegin(f);
  /* VecRestoreArrayRead(x, &xx); */
  VecRestoreArray(x, &xx);  
  ierr = VecAssemblyEnd(f);

  return ierr;
}

PetscErrorCode NLJAC(SNES snes, Vec x, Mat jac, Mat B, void* ctx)
{
  PetscErrorCode ierr;
  PetscScalar xxend;
  PetscScalar* Fb = (PetscScalar*) ctx;  
  /* PetscScalar xnrm; */

  PetscInt is, ie, N;
  VecGetSize(x, &N);
  VecGetOwnershipRange(x, &is, &ie);

  PetscInt Nend = N-1;
  for (int i=is; i<ie; ++i)
    if (i==0) {
      MatSetValue(B, i, i, 2.0, INSERT_VALUES);
      MatSetValue(B, i, i+1, -1.0, INSERT_VALUES);      
    }
    else if (i<N-1) {
      MatSetValue(B, i, i-1, -1.0, INSERT_VALUES);
      MatSetValue(B, i, i, 2.0, INSERT_VALUES);
      MatSetValue(B, i, i+1, -1.0, INSERT_VALUES);
    }
    else if (i==N-1) {
      /* VecNorm(x, NORM_2, &xnrm); */
      /* MatSetValuesRow(jac, i, xx); */
      
      VecGetValues(x, 1, &Nend, &xxend);
      
      MatSetValue(B, i, i-1, -1.0, INSERT_VALUES);
      MatSetValue(B, i, i, 1.0+3*Fb[1]*pow(xxend, 2), INSERT_VALUES);

      /* PetscPrintf(PETSC_COMM_WORLD, "%e\n", xxend); */
    }
  MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
  ierr = MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);

  if (jac != B) {
  MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY);
  MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY);    
  }
  
  return ierr;
}

Reply via email to