Hello,

Sorry for my bad example...

So maybe it is simpler I give you my complete code called TSIRM for A Two-Stage Iteration with least-squares Residual Minimization algorithm to solve large sparse linear systems (https://www.researchgate.net/publication/277571149_TSIRM_A_Two-Stage_Iteration_with_least-squares_Residual_Minimization_algorithm_to_solve_large_sparse_linear_systems) It is still under in development as a solver for PETSc (with few comments in the code...)

In this code, I use FGMRES as an inner solver only for 30 iterations (I want to put this as a parameter after) For the outer iteration I apply a minimization method on the residual each 12 outer iterations (this is the parameter colS in the code, this will also be a parameter after). The minimization is CGLS conjugate gradient with least square. There are useless messages when running the code (but they are interesting to understand the behavior of the code)

Some examples:

With SNES ex35

With FGMRES
time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun -np 3 ./ex35 -snes_rtol 1.e-12 -snes_monitor -ksp_type fgmres -da_grid_x 660 -da_grid_y 660
  0 SNES Function norm 3.808595655784e+02
  1 SNES Function norm 3.785299355288e-03
  2 SNES Function norm 3.766792406275e-08
  3 SNES Function norm 1.428490284661e-09

real    2m35.576s
user    7m44.008s
sys    0m2.504s


With TSIRM
time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun -np 3 ./ex35 -snes_rtol 1.e-12 -snes_monitor -ksp_type tsirm -da_grid_x 660 -da_grid_y 660
  0 SNES Function norm 3.808595655784e+02
Enter tsirm
Size of vector 435600
converged 0
Norm of error 270.484, outer iteration 0 270.484 reason 0
Norm of error 236.805, outer iteration 0 236.805 reason 0
Norm of error 213.261, outer iteration 0 213.261 reason 0
....
Norm of error 5.84204e-13, outer iteration 3 5.84204e-13 reason 0
Norm of error 4.61092e-13, outer iteration 3 4.61092e-13 reason 0
Norm of error 3.74294e-13, outer iteration 3 3.74294e-13 reason 2
             -- Execution time : 22.2333 (s)
             -- Total number of iterations : 1199
  3 SNES Function norm 1.432052860297e-09

real    0m53.639s
user    2m39.120s
sys    0m1.652s





With KSP 15

with FGMRES

time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun -np 3 ./ex15 -m 800 -n 800 -ksp_type fgmres -ksp_rtol 1e-6 -pc_type mg
Norm of error 1.79776 iterations 1102

real    0m51.147s
user    2m32.788s
sys    0m0.508s


With TSIRM

time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun -np 3 ./ex15 -m 800 -n 800 -ksp_type tsirm -ksp_rtol 1e-6 -pc_type mg
Enter tsirm
Size of vector 640000
converged 0
Norm of error 0.0970815, outer iteration 0 0.0970815 reason 0
Norm of error 0.0368809, outer iteration 0 0.0368809 reason 0
Norm of error 0.0223725, outer iteration 0 0.0223725 reason 0
Norm of error 0.0163448, outer iteration 0 0.0163448 reason 0
Norm of error 0.013248, outer iteration 0 0.013248 reason 0
Norm of error 0.0112125, outer iteration 0 0.0112125 reason 0
Norm of error 0.00961675, outer iteration 0 0.00961675 reason 0
Norm of error 0.00825048, outer iteration 0 0.00825048 reason 0
Norm of error 0.00707865, outer iteration 0 0.00707865 reason 0
Norm of error 0.00606273, outer iteration 0 0.00606273 reason 0
Norm of error 0.00516968, outer iteration 0 0.00516968 reason 0
Norm of error 0.00439978, outer iteration 0 0.00439978 reason 0
Norm of error 5.22567e-05, outer iteration 1 5.22567e-05 reason 2
             -- Execution time : 18.8489 (s)
             -- Total number of iterations : 386
Norm of error 0.901491 iterations 26

real    0m19.263s
user    0m57.248s
sys    0m0.400s




With KSP ex45 (with two KSPs not as in this code, we obtain faster results TSIRM with the ASM preconditioner than FGMRES with HYPRE or with ASM)
With one KSP (this code)
It crashes...

time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun -np 3 ./ex45 -da_grid_x 160 -da_grid_y 160 -da_grid_z 160 -ksp_type tsirm -ksp_rtol 1e-10 -pc_type asm -ksp_monitor
Enter tsirm
Size of vector 4096000
[1]PETSC ERROR: --------------------- Error Message --------------------------------------------------------------
[1]PETSC ERROR: Object is in wrong state
[1]PETSC ERROR:  Vec is locked read only, argument # 1
[1]PETSC ERROR: See http://www.mcs.anl.gov/petsc/documentation/faq.html for trouble shooting.
[1]PETSC ERROR: Petsc Release Version 3.6.0, Jun, 09, 2015
[1]PETSC ERROR: ./ex45 on a arch-linux2-c-debug named extinction by couturie Wed Jul 15 21:43:51 2015 [1]PETSC ERROR: Configure options --download-openmpi --download-hypre --download-f2cblaslapack --with-fc=0 [1]PETSC ERROR: #1 VecGetArray() line 1646 in /home/couturie/work/petsc-3.6.0/src/vec/vec/interface/rvector.c [1]PETSC ERROR: #2 VecGetArray3d() line 2411 in /home/couturie/work/petsc-3.6.0/src/vec/vec/interface/rvector.c [1]PETSC ERROR: #3 DMDAVecGetArray() line 77 in /home/couturie/work/petsc-3.6.0/src/dm/impls/da/dagetarray.c [1]PETSC ERROR: #4 ComputeRHS() line 84 in /home/couturie/work/petsc-3.6.0/src/ksp/ksp/examples/tutorials/ex45.c [1]PETSC ERROR: #5 KSPSetUp() line 277 in /home/couturie/work/petsc-3.6.0/src/ksp/ksp/interface/itfunc.c [1]PETSC ERROR: #6 KSPSolve_TSIRM() line 135 in /home/couturie/work/petsc-3.6.0/src/ksp/ksp/impls/gmres/tsirm.c



Thank you in advance,

Raphaël


On Wed, Jul 15, 2015 at 12:04 PM, Raphaël Couturier <[email protected] <mailto:[email protected]>> wrote:

    Hello,

    I want to make a new solver inside petsc.
    This solver is based on a 2 stage method. So I have one outer
    iteration and one inner iteration. For the inner iteration I can
    use gmres or one of its variants.
    I succeeded to make my algorithm by creating a new ksp (that
    copies the linear system). So I have tried to do that without
    creating a new ksp. It works well with ksp examples that don't use
    dmda and with snes examples.


The code you sent does not make any sense to me. How can KSPSolve(ksp, NULL, NULL) be meaningful?

Also, can't you get exactly this effect using PCKSP?

 Thanks,

    Matt

    So I have tried to make a really simple ksp (only to test) in
    which I simply call another ksp.
    Here is the part of the code (and attached is the complete code):
       PetscErrorCode ierr;
       ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
       KSPSetType(ksp,KSPFGMRES);
       ierr = KSPSolve(ksp, NULL, NULL); CHKERRQ(ierr);
       PetscFunctionReturn(0);


    For example with the ksp example 15:
     time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun  -np 3 ./ex15 -m
    200 -n 200 -ksp_type test  -ksp_rtol 1e-10 -pc_type mg -ksp_monitor
    there is no problem, I obtain the good result.

    But with the ksp example 45 (based on dmda):
    time $PETSC_DIR/arch-linux2-c-debug/bin/mpirun  -np 1 ./ex45
    -ksp_type test  -ksp_rtol 1e-10 -pc_type mg -ksp_monitor

    It crashes with that (I didn't change anything in ex45)
    [0]PETSC ERROR: Object is in wrong state
    [0]PETSC ERROR:  Vec is locked read only, argument # 1
    [0]PETSC ERROR: See
    http://www.mcs.anl.gov/petsc/documentation/faq.html for trouble
    shooting.
    [0]PETSC ERROR: Petsc Release Version 3.6.0, Jun, 09, 2015
    [0]PETSC ERROR: ./ex45 on a arch-linux2-c-debug named extinction
    by couturie Wed Jul 15 18:45:39 2015
    [0]PETSC ERROR: Configure options --download-openmpi
    --download-hypre --download-f2cblaslapack --with-fc=0
    [0]PETSC ERROR: #1 VecGetArray() line 1646 in
    /home/couturie/work/petsc-3.6.0/src/vec/vec/interface/rvector.c
    [0]PETSC ERROR: #2 VecGetArray3d() line 2411 in
    /home/couturie/work/petsc-3.6.0/src/vec/vec/interface/rvector.c
    [0]PETSC ERROR: #3 DMDAVecGetArray() line 77 in
    /home/couturie/work/petsc-3.6.0/src/dm/impls/da/dagetarray.c
    [0]PETSC ERROR: #4 ComputeRHS() line 84 in
    /home/couturie/work/petsc-3.6.0/src/ksp/ksp/examples/tutorials/ex45.c
    [0]PETSC ERROR: #5 KSPSetUp() line 277 in
    /home/couturie/work/petsc-3.6.0/src/ksp/ksp/interface/itfunc.c
    [0]PETSC ERROR: #6 KSPSolve() line 546 in
    /home/couturie/work/petsc-3.6.0/src/ksp/ksp/interface/itfunc.c
    [0]PETSC ERROR: #7 KSPSolve_TEST() line 43 in
    /home/couturie/work/petsc-3.6.0/src/ksp/ksp/impls/gmres/test.c
    [0]PETSC ERROR: #8 KSPSolve() line 604 in
    /home/couturie/work/petsc-3.6.0/src/ksp/ksp/interface/itfunc.c
    [0]PETSC ERROR: #9 main() line 51 in
    /home/couturie/work/petsc-3.6.0/src/ksp/ksp/examples/tutorials/ex45.c


    I don't understand since many examples in snes are good with my
    code and they use dmda.
    Do any of you have an idea of the problem?

    Of course, I have a bad solution that consists in creating a new
    ksp but I would like to do without, if possible.

    Thank you in advance,
    Regards,

    Raphaël Couturier




--
What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead.
-- Norbert Wiener

#include <petsc/private/kspimpl.h>        /*I "petscksp.h" I*/



#undef __FUNCT__
#define __FUNCT__ "KSPSetUp_TSIRM"
static PetscErrorCode KSPSetUp_TSIRM(KSP ksp)
{
  PetscErrorCode ierr;
  PetscBool      diagonalscale;

  PetscFunctionBegin;
  //Maybe this need to be improved, I copied this from other solvers
  ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr);
  if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);
  ierr = KSPSetWorkVecs(ksp,9);CHKERRQ(ierr);
  PetscFunctionReturn(0);
}












#undef __FUNCT__
#define __FUNCT__ "KSPSolve_TSIRM"
 PetscErrorCode KSPSolve_TSIRM(KSP ksp) {

  //Variables

  PetscScalar  gamma, alpha, oldgamma, beta;
  PetscReal norm=20, cgprec=1e-40;
  PetscInt giter=0, ColS=12, col=0, iter=0, iterations=15, Iiter=0;
  PetscErrorCode ierr;
  PetscScalar T1, T2;

  PetscInt total=0;
  PetscInt size;
  PetscInt Istart,Iend;
  PetscInt i,its;
  Vec       residu;
  Mat S, AS;
  PetscScalar *array;
  PetscInt *ind_row;
  Vec Alpha, p, ss, vect, r, q, Ax,x, b;
  Mat A;

  PetscInt first_iteration=1;


  PetscReal res=99999999;


  ierr = PetscPrintf(PETSC_COMM_WORLD, "Enter tsirm\n"); CHKERRQ(ierr);
  
  KSPGetRhs(ksp,&b);
  KSPGetOperators(ksp,&A,NULL);
  KSPGetSolution(ksp,&x);



  VecGetSize(b,&size);

  ierr = PetscPrintf(PETSC_COMM_WORLD, "Size of vector %D\n", size); CHKERRQ(ierr);

  PetscInt aa,bb;
  MatGetOwnershipRange(A,&aa,&bb);



  ierr = MatCreate(PETSC_COMM_WORLD, &S);CHKERRQ(ierr);
  ierr = MatSetSizes(S, bb-aa,  PETSC_DECIDE, size, ColS); CHKERRQ(ierr);
  ierr = MatSetType(S, MATMPIDENSE); CHKERRQ(ierr);
  ierr = MatSetUp(S); CHKERRQ(ierr);


  ierr = MatGetOwnershipRange(S, &Istart, &Iend); CHKERRQ(ierr);

  ierr = VecCreate(PETSC_COMM_WORLD, &Alpha); CHKERRQ(ierr);
  ierr = VecSetSizes(Alpha, PETSC_DECIDE, ColS); CHKERRQ(ierr);
  ierr = VecSetFromOptions(Alpha); CHKERRQ(ierr);
  ierr = VecDuplicate(Alpha, &vect); CHKERRQ(ierr);
  ierr = VecDuplicate(Alpha, &p); CHKERRQ(ierr);
  ierr = VecDuplicate(Alpha, &ss); CHKERRQ(ierr);
  ierr = VecDuplicate(b, &r); CHKERRQ(ierr);
  ierr = VecDuplicate(b, &q); CHKERRQ(ierr);
  ierr = VecDuplicate(b, &Ax); CHKERRQ(ierr);

  ierr = VecDuplicate(b,&residu);CHKERRQ(ierr);


   


  //indexes of row (these indexes are global)
  ind_row = (PetscInt*)malloc(sizeof(PetscInt)*(Iend-Istart));
  for(i=0; i<Iend-Istart; i++) ind_row[i] = i + Istart;


  PetscInt restart=30;



 PetscReal aa1,aa2,aa3;
 PetscInt old_maxits;
 
 ierr = KSPGetTolerances(ksp, &aa1, &aa2, &aa3, &old_maxits); CHKERRQ(ierr);



  
  ierr = KSPSetTolerances(ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, restart); CHKERRQ(ierr);



  KSPSetType(ksp,KSPFGMRES);
  ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); CHKERRQ(ierr);


  //GMRES WITH MINIMIZATION
  T1 = MPI_Wtime();

  ierr = KSPSetUp(ksp); CHKERRQ(ierr);
  



  //previously it seemed good but with SNES it seems not good....
  /*  ierr = KSP_MatMult(ksp,A,x,r);CHKERRQ(ierr);
    VecAXPY(r,-1,b);
  VecNorm(r, NORM_2, &res);
  ksp->reason=0;
  ierr = PetscPrintf(PETSC_COMM_WORLD, "converged %d\n",ksp->reason); CHKERRQ(ierr);
   */
  

  ierr = PetscPrintf(PETSC_COMM_WORLD, "converged %d\n",ksp->reason); CHKERRQ(ierr);

  


  do{
    for(col=0; col<ColS  &&    ksp->reason==0 ; col++){

      //Solve
      ierr = KSPSolve(ksp, b, x); CHKERRQ(ierr);

      ierr = KSPGetIterationNumber(ksp, &its); CHKERRQ(ierr);
      total += its; Iiter ++;



      //Build S'
      ierr = VecGetArray(x, &array);
      ierr = MatSetValues(S, Iend-Istart, ind_row, 1, &col, array, INSERT_VALUES);
      VecRestoreArray(x, &array);

      KSPGetResidualNorm(ksp,&norm);
      res=norm;

      KSPConvergedDefault(ksp,ksp->its,res,&ksp->reason,ksp->cnvP);


      ierr = PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g, outer iteration %D %g reason %D \n", norm, giter,ksp->rnorm, ksp->reason); CHKERRQ(ierr);

    }

    //minimization step
    if(ksp->reason==0)
     {

      MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
      MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);


      //Build the AS matrix
      if(first_iteration) {
        MatMatMult(A,S, MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AS);
        first_iteration=0;
      }
      else
        MatMatMult(A,S, MAT_REUSE_MATRIX,PETSC_DEFAULT,&AS);




      //Minimization with the CGLS conjugate gradient least square method
      MatMult(AS, Alpha, r);  VecAYPX(r, -1, b); //r_0 = b-AS*x_0


      MatMultTranspose(AS, r, p); //p_0 = AS'*r_0




      ierr = VecCopy(p, ss); CHKERRQ(ierr); //p_0 = s_0
      VecNorm(ss, NORM_2, &gamma); gamma = gamma * gamma; //gamma = norm2(s)^2
      while(gamma>cgprec && iter<iterations){
        MatMult(AS, p, q); //q = AS*p
        VecNorm(q, NORM_2, &alpha); alpha = alpha * alpha; //alpha = norm2(q)^2
        alpha = gamma / alpha;
        VecAXPY(Alpha, alpha, p); //Alpha += alpha*p
        VecAXPY(r, -alpha, q); //r -= alpha*q
        MatMultTranspose(AS, r, ss); // ss = AS'*r
        oldgamma = gamma;
        VecNorm(ss, NORM_2, &gamma); gamma = gamma * gamma; //gamma = norm2(s)^2
        beta = gamma / oldgamma;
        VecAYPX(p, beta, ss); //p = s+beta*p;
        iter ++;
      }

      iter = 0; giter ++;
      //Minimizer
      MatMult(S, Alpha, x); //x = S*Alpha;
    }






  } while (giter<ksp->max_it && ksp->reason==0 );



  //we need to put TSIRM otherwise for the next step, ksp will use FGMRES !!
  KSPSetType(ksp,KSPTSIRM);
  //we put the old max number of iterations (if an application need to change the ksp)
  ierr = KSPSetTolerances(ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, old_maxits); CHKERRQ(ierr);


  T2 = MPI_Wtime();
  ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Execution time : %g (s)\n", T2-T1); CHKERRQ(ierr);
  ierr = PetscPrintf(PETSC_COMM_WORLD, "\t\t\t -- Total number of iterations : %D\n", total); CHKERRQ(ierr);



  //free allocated variables
  ierr = VecDestroy(&Alpha);CHKERRQ(ierr);
  ierr = MatDestroy(&S);CHKERRQ(ierr);
  ierr = VecDestroy(&vect);CHKERRQ(ierr);
  ierr = VecDestroy(&p);CHKERRQ(ierr);
  ierr = VecDestroy(&ss);CHKERRQ(ierr);
  ierr = VecDestroy(&r);CHKERRQ(ierr);
  ierr = VecDestroy(&q);CHKERRQ(ierr);
  ierr = VecDestroy(&Ax);CHKERRQ(ierr);
  ierr = VecDestroy(&residu);CHKERRQ(ierr);

  PetscFunctionReturn(0);






}












#undef __FUNCT__
#define __FUNCT__ "KSPCreate_TSIRM"
PETSC_EXTERN PetscErrorCode KSPCreate_TSIRM(KSP ksp)
{
  PetscErrorCode ierr;

  PetscFunctionBegin;
  ksp->data = (void*)0;

  ierr = KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);CHKERRQ(ierr);
  ierr = KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_RIGHT,1);CHKERRQ(ierr);

  ksp->ops->setup          = KSPSetUp_TSIRM;
  ksp->ops->solve          = KSPSolve_TSIRM;
  ksp->ops->destroy        = KSPDestroyDefault;
  ksp->ops->buildsolution  = KSPBuildSolutionDefault;
  ksp->ops->buildresidual  = KSPBuildResidualDefault;
  ksp->ops->setfromoptions = 0;
  ksp->ops->view           = 0;
#if defined(PETSC_USE_COMPLEX)
  SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"This is not supported for complex numbers");
#endif
  PetscFunctionReturn(0);
}
















Reply via email to