Date: 2015-10-02T22:24:21+00:00

Actual source code: aspin.c
petsc-3.6.2 2015-10-02
Report Typos and Errors

      1: #include <petsc/private/snesimpl.h>             /*I   "petscsnes.h"   I*/
      2: #include <petscdm.h>

      6: PetscErrorCode MatMultASPIN(Mat m,Vec X,Vec Y)
      7: {
      9:   void           *ctx;
     10:   SNES           snes;
     11:   PetscInt       n,i;
     12:   VecScatter     *oscatter;
     13:   SNES           *subsnes;
     14:   PetscBool      match;
     15:   MPI_Comm       comm;
     16:   KSP            ksp;
     17:   Vec            *x,*b;
     18:   Vec            W;
     19:   SNES           npc;
     20:   Mat            subJ,subpJ;

     23:   MatShellGetContext(m,&ctx);
     24:   snes = (SNES)ctx;
     25:   SNESGetNPC(snes,&npc);
     26:   SNESGetFunction(npc,&W,NULL,NULL);
     27:   PetscObjectTypeCompare((PetscObject)npc,SNESNASM,&match);
     28:   if (!match) {
     29:     PetscObjectGetComm((PetscObject)snes,&comm);
     30:     SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"MatMultASPIN requires that the nonlinear preconditioner be Nonlinear additive Schwarz");
     31:   }
     32:   SNESNASMGetSubdomains(npc,&n,&subsnes,NULL,&oscatter,NULL);
     33:   SNESNASMGetSubdomainVecs(npc,&n,&x,&b,NULL,NULL);

     35:   VecSet(Y,0);
     36:   MatMult(npc->jacobian_pre,X,W);

     38:   for (i=0;i<n;i++) {
     39:     VecScatterBegin(oscatter[i],W,b[i],INSERT_VALUES,SCATTER_FORWARD);
     40:   }
     41:   for (i=0;i<n;i++) {
     42:     VecScatterEnd(oscatter[i],W,b[i],INSERT_VALUES,SCATTER_FORWARD);
     43:     VecSet(x[i],0.);
     44:     SNESGetJacobian(subsnes[i],&subJ,&subpJ,NULL,NULL);
     45:     SNESGetKSP(subsnes[i],&ksp);
     46:     KSPSetOperators(ksp,subJ,subpJ);
     47:     KSPSolve(ksp,b[i],x[i]);
     48:     VecScatterBegin(oscatter[i],x[i],Y,ADD_VALUES,SCATTER_REVERSE);
     49:   }
     50:   for (i=0;i<n;i++) {
     51:     VecScatterEnd(oscatter[i],x[i],Y,ADD_VALUES,SCATTER_REVERSE);
     52:   }
     53:   return(0);
     54: }

     58: /* -------------------------------------------------------------------------- */
     59: /*MC
     60:       SNESASPIN - Helper SNES type for Additive-Schwarz Preconditioned Inexact Newton

     62:    Options Database:
     63: +  -npc_snes_ - options prefix of the nonlinear subdomain solver (must be of type NASM)
     64: .  -npc_sub_snes_ - options prefix of the subdomain nonlinear solves
     65: .  -npc_sub_ksp_ - options prefix of the subdomain Krylov solver
     66: -  -npc_sub_pc_ - options prefix of the subdomain preconditioner

     68:     Notes: This routine sets up an instance of NETWONLS with nonlinear left preconditioning.  It differs from other
     69:     similar functionality in SNES as it creates a linear shell matrix that corresponds to the product:

     71:     \sum_{i=0}^{N_b}J_b({X^b_{converged}})^{-1}J(X + \sum_{i=0}^{N_b}(X^b_{converged} - X^b))

     73:     which is the ASPIN preconditioned matrix. Similar solvers may be constructed by having matrix-free differencing of
     74:     nonlinear solves per linear iteration, but this is far more efficient when subdomain sparse-direct preconditioner
     75:     factorizations are reused on each application of J_b^{-1}.

     77:    Level: intermediate

     79: .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNASM, SNESGetNPC(), SNESGetNPCSide()

     81: M*/
     82: PETSC_EXTERN PetscErrorCode SNESCreate_ASPIN(SNES snes)
     83: {
     85:   SNES           npc;
     86:   KSP            ksp;
     87:   PC             pc;
     88:   Mat            aspinmat;
     89:   MPI_Comm       comm;
     90:   Vec            F;
     91:   PetscInt       n;
     92:   SNESLineSearch linesearch;

     95:   /* set up the solver */
     96:   SNESSetType(snes,SNESNEWTONLS);
     97:   SNESSetNPCSide(snes,PC_LEFT);
     98:   SNESSetFunctionType(snes,SNES_FUNCTION_PRECONDITIONED);
     99:   SNESGetNPC(snes,&npc);
    100:   SNESSetType(npc,SNESNASM);
    101:   SNESNASMSetType(npc,PC_ASM_BASIC);
    102:   SNESNASMSetComputeFinalJacobian(npc,PETSC_TRUE);
    103:   SNESGetKSP(snes,&ksp);
    104:   KSPGetPC(ksp,&pc);
    105:   PCSetType(pc,PCNONE);
    106:   PetscObjectGetComm((PetscObject)snes,&comm);
    107:   SNESGetLineSearch(snes,&linesearch);
    108:   SNESLineSearchSetType(linesearch,SNESLINESEARCHBT);

    110:   /* set up the shell matrix */
    111:   SNESGetFunction(snes,&F,NULL,NULL);
    112:   VecGetLocalSize(F,&n);
    113:   MatCreateShell(comm,n,n,PETSC_DECIDE,PETSC_DECIDE,snes,&aspinmat);
    114:   MatSetType(aspinmat,MATSHELL);
    115:   MatShellSetOperation(aspinmat,MATOP_MULT,(void(*)(void))MatMultASPIN);

    117:   SNESSetJacobian(snes,aspinmat,NULL,NULL,NULL);
    118:   MatDestroy(&aspinmat);

    120:   return(0);
    121: }