1*eed5f15bSPeter Brune 2*eed5f15bSPeter Brune /* 3*eed5f15bSPeter Brune Defines a SNES that can consist of a collection of SNESes 4*eed5f15bSPeter Brune */ 5*eed5f15bSPeter Brune #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 6*eed5f15bSPeter Brune 7*eed5f15bSPeter Brune const char *const SNESCompositeTypes[] = {"ADDITIVE","MULTIPLICATIVE","SNESCompositeType","SNES_COMPOSITE",0}; 8*eed5f15bSPeter Brune 9*eed5f15bSPeter Brune typedef struct _SNES_CompositeLink *SNES_CompositeLink; 10*eed5f15bSPeter Brune struct _SNES_CompositeLink { 11*eed5f15bSPeter Brune SNES snes; 12*eed5f15bSPeter Brune SNES_CompositeLink next; 13*eed5f15bSPeter Brune SNES_CompositeLink previous; 14*eed5f15bSPeter Brune }; 15*eed5f15bSPeter Brune 16*eed5f15bSPeter Brune typedef struct { 17*eed5f15bSPeter Brune SNES_CompositeLink head; 18*eed5f15bSPeter Brune SNESCompositeType type; 19*eed5f15bSPeter Brune Vec Xorig; 20*eed5f15bSPeter Brune } SNES_Composite; 21*eed5f15bSPeter Brune 22*eed5f15bSPeter Brune #undef __FUNCT__ 23*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeApply_Multiplicative" 24*eed5f15bSPeter Brune static PetscErrorCode SNESCompositeApply_Multiplicative(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) 25*eed5f15bSPeter Brune { 26*eed5f15bSPeter Brune PetscErrorCode ierr; 27*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 28*eed5f15bSPeter Brune SNES_CompositeLink next = jac->head; 29*eed5f15bSPeter Brune Vec FSub; 30*eed5f15bSPeter Brune PetscReal fsubnorm; 31*eed5f15bSPeter Brune 32*eed5f15bSPeter Brune PetscFunctionBegin; 33*eed5f15bSPeter Brune if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); 34*eed5f15bSPeter Brune if (snes->normtype == SNES_NORM_FUNCTION) { 35*eed5f15bSPeter Brune ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); 36*eed5f15bSPeter Brune if (fnorm) {ierr = SNESSetInitialFunctionNorm(next->snes,*fnorm);CHKERRQ(ierr);} 37*eed5f15bSPeter Brune } 38*eed5f15bSPeter Brune ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); 39*eed5f15bSPeter Brune 40*eed5f15bSPeter Brune while (next->next) { 41*eed5f15bSPeter Brune /* only copy the function over in the case where the functions correspond */ 42*eed5f15bSPeter Brune if (next->snes->pcside == PC_RIGHT && next->snes->normtype != SNES_NORM_NONE) { 43*eed5f15bSPeter Brune ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); 44*eed5f15bSPeter Brune ierr = SNESGetFunctionNorm(next->snes,&fsubnorm);CHKERRQ(ierr); 45*eed5f15bSPeter Brune next = next->next; 46*eed5f15bSPeter Brune ierr = SNESSetInitialFunction(next->snes,FSub);CHKERRQ(ierr); 47*eed5f15bSPeter Brune ierr = SNESSetInitialFunctionNorm(next->snes,fsubnorm);CHKERRQ(ierr); 48*eed5f15bSPeter Brune } else { 49*eed5f15bSPeter Brune next = next->next; 50*eed5f15bSPeter Brune } 51*eed5f15bSPeter Brune ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); 52*eed5f15bSPeter Brune } 53*eed5f15bSPeter Brune if (next->snes->pcside == PC_RIGHT) { 54*eed5f15bSPeter Brune ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); 55*eed5f15bSPeter Brune ierr = VecCopy(FSub,F);CHKERRQ(ierr); 56*eed5f15bSPeter Brune if (fnorm) {ierr = SNESGetFunctionNorm(next->snes,fnorm);CHKERRQ(ierr);} 57*eed5f15bSPeter Brune } else if (snes->normtype == SNES_NORM_FUNCTION) { 58*eed5f15bSPeter Brune SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 59*eed5f15bSPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 60*eed5f15bSPeter Brune } 61*eed5f15bSPeter Brune PetscFunctionReturn(0); 62*eed5f15bSPeter Brune } 63*eed5f15bSPeter Brune 64*eed5f15bSPeter Brune #undef __FUNCT__ 65*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeApply_Additive" 66*eed5f15bSPeter Brune static PetscErrorCode SNESCompositeApply_Additive(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) 67*eed5f15bSPeter Brune { 68*eed5f15bSPeter Brune PetscErrorCode ierr; 69*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 70*eed5f15bSPeter Brune SNES_CompositeLink next = jac->head; 71*eed5f15bSPeter Brune Vec Y,Xorig; 72*eed5f15bSPeter Brune 73*eed5f15bSPeter Brune PetscFunctionBegin; 74*eed5f15bSPeter Brune Y = snes->vec_sol_update; 75*eed5f15bSPeter Brune if (!jac->Xorig) {ierr = VecDuplicate(X,&jac->Xorig);CHKERRQ(ierr);} 76*eed5f15bSPeter Brune Xorig = jac->Xorig; 77*eed5f15bSPeter Brune ierr = VecCopy(X,Xorig); 78*eed5f15bSPeter Brune if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); 79*eed5f15bSPeter Brune ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); 80*eed5f15bSPeter Brune if (snes->normtype == SNES_NORM_FUNCTION) { 81*eed5f15bSPeter Brune ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); 82*eed5f15bSPeter Brune if (fnorm) {ierr = SNESSetInitialFunctionNorm(next->snes,*fnorm);CHKERRQ(ierr);} 83*eed5f15bSPeter Brune while (next->next) { 84*eed5f15bSPeter Brune next = next->next; 85*eed5f15bSPeter Brune ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); 86*eed5f15bSPeter Brune if (fnorm) {ierr = SNESSetInitialFunctionNorm(next->snes,*fnorm);CHKERRQ(ierr);} 87*eed5f15bSPeter Brune } 88*eed5f15bSPeter Brune } 89*eed5f15bSPeter Brune next = jac->head; 90*eed5f15bSPeter Brune while (next->next) { 91*eed5f15bSPeter Brune next = next->next; 92*eed5f15bSPeter Brune ierr = VecCopy(X,Y);CHKERRQ(ierr); 93*eed5f15bSPeter Brune ierr = SNESSolve(next->snes,B,Y);CHKERRQ(ierr); 94*eed5f15bSPeter Brune ierr = VecAXPY(Y,-1.0,Xorig);CHKERRQ(ierr); 95*eed5f15bSPeter Brune ierr = VecAXPY(Y,1.0,X);CHKERRQ(ierr); 96*eed5f15bSPeter Brune } 97*eed5f15bSPeter Brune if (snes->normtype == SNES_NORM_FUNCTION) { 98*eed5f15bSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 99*eed5f15bSPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 100*eed5f15bSPeter Brune } 101*eed5f15bSPeter Brune PetscFunctionReturn(0); 102*eed5f15bSPeter Brune } 103*eed5f15bSPeter Brune #undef __FUNCT__ 104*eed5f15bSPeter Brune #define __FUNCT__ "SNESSetUp_Composite" 105*eed5f15bSPeter Brune static PetscErrorCode SNESSetUp_Composite(SNES snes) 106*eed5f15bSPeter Brune { 107*eed5f15bSPeter Brune PetscErrorCode ierr; 108*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 109*eed5f15bSPeter Brune SNES_CompositeLink next = jac->head; 110*eed5f15bSPeter Brune 111*eed5f15bSPeter Brune PetscFunctionBegin; 112*eed5f15bSPeter Brune while (next) { 113*eed5f15bSPeter Brune ierr = SNESSetFromOptions(next->snes);CHKERRQ(ierr); 114*eed5f15bSPeter Brune next = next->next; 115*eed5f15bSPeter Brune } 116*eed5f15bSPeter Brune PetscFunctionReturn(0); 117*eed5f15bSPeter Brune } 118*eed5f15bSPeter Brune 119*eed5f15bSPeter Brune #undef __FUNCT__ 120*eed5f15bSPeter Brune #define __FUNCT__ "SNESReset_Composite" 121*eed5f15bSPeter Brune static PetscErrorCode SNESReset_Composite(SNES snes) 122*eed5f15bSPeter Brune { 123*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 124*eed5f15bSPeter Brune PetscErrorCode ierr; 125*eed5f15bSPeter Brune SNES_CompositeLink next = jac->head; 126*eed5f15bSPeter Brune 127*eed5f15bSPeter Brune PetscFunctionBegin; 128*eed5f15bSPeter Brune while (next) { 129*eed5f15bSPeter Brune ierr = SNESReset(next->snes);CHKERRQ(ierr); 130*eed5f15bSPeter Brune next = next->next; 131*eed5f15bSPeter Brune } 132*eed5f15bSPeter Brune ierr = VecDestroy(&jac->Xorig);CHKERRQ(ierr); 133*eed5f15bSPeter Brune PetscFunctionReturn(0); 134*eed5f15bSPeter Brune } 135*eed5f15bSPeter Brune 136*eed5f15bSPeter Brune #undef __FUNCT__ 137*eed5f15bSPeter Brune #define __FUNCT__ "SNESDestroy_Composite" 138*eed5f15bSPeter Brune static PetscErrorCode SNESDestroy_Composite(SNES snes) 139*eed5f15bSPeter Brune { 140*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 141*eed5f15bSPeter Brune PetscErrorCode ierr; 142*eed5f15bSPeter Brune SNES_CompositeLink next = jac->head,next_tmp; 143*eed5f15bSPeter Brune 144*eed5f15bSPeter Brune PetscFunctionBegin; 145*eed5f15bSPeter Brune ierr = SNESReset_Composite(snes);CHKERRQ(ierr); 146*eed5f15bSPeter Brune while (next) { 147*eed5f15bSPeter Brune ierr = SNESDestroy(&next->snes);CHKERRQ(ierr); 148*eed5f15bSPeter Brune next_tmp = next; 149*eed5f15bSPeter Brune next = next->next; 150*eed5f15bSPeter Brune ierr = PetscFree(next_tmp);CHKERRQ(ierr); 151*eed5f15bSPeter Brune } 152*eed5f15bSPeter Brune ierr = PetscFree(snes->data);CHKERRQ(ierr); 153*eed5f15bSPeter Brune PetscFunctionReturn(0); 154*eed5f15bSPeter Brune } 155*eed5f15bSPeter Brune 156*eed5f15bSPeter Brune #undef __FUNCT__ 157*eed5f15bSPeter Brune #define __FUNCT__ "SNESSetFromOptions_Composite" 158*eed5f15bSPeter Brune static PetscErrorCode SNESSetFromOptions_Composite(SNES snes) 159*eed5f15bSPeter Brune { 160*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 161*eed5f15bSPeter Brune PetscErrorCode ierr; 162*eed5f15bSPeter Brune PetscInt nmax = 8,i; 163*eed5f15bSPeter Brune SNES_CompositeLink next; 164*eed5f15bSPeter Brune char *sneses[8]; 165*eed5f15bSPeter Brune PetscBool flg; 166*eed5f15bSPeter Brune 167*eed5f15bSPeter Brune PetscFunctionBegin; 168*eed5f15bSPeter Brune ierr = PetscOptionsHead("Composite preconditioner options");CHKERRQ(ierr); 169*eed5f15bSPeter Brune ierr = PetscOptionsEnum("-snes_composite_type","Type of composition","SNESCompositeSetType",SNESCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr); 170*eed5f15bSPeter Brune if (flg) { 171*eed5f15bSPeter Brune ierr = SNESCompositeSetType(snes,jac->type);CHKERRQ(ierr); 172*eed5f15bSPeter Brune } 173*eed5f15bSPeter Brune ierr = PetscOptionsStringArray("-snes_composite_sneses","List of composite solvers","SNESCompositeAddSNES",sneses,&nmax,&flg);CHKERRQ(ierr); 174*eed5f15bSPeter Brune if (flg) { 175*eed5f15bSPeter Brune for (i=0; i<nmax; i++) { 176*eed5f15bSPeter Brune ierr = SNESCompositeAddSNES(snes,sneses[i]);CHKERRQ(ierr); 177*eed5f15bSPeter Brune ierr = PetscFree(sneses[i]);CHKERRQ(ierr); /* deallocate string sneses[i], which is allocated in PetscOptionsStringArray() */ 178*eed5f15bSPeter Brune } 179*eed5f15bSPeter Brune } 180*eed5f15bSPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 181*eed5f15bSPeter Brune 182*eed5f15bSPeter Brune next = jac->head; 183*eed5f15bSPeter Brune while (next) { 184*eed5f15bSPeter Brune ierr = SNESSetFromOptions(next->snes);CHKERRQ(ierr); 185*eed5f15bSPeter Brune next = next->next; 186*eed5f15bSPeter Brune } 187*eed5f15bSPeter Brune PetscFunctionReturn(0); 188*eed5f15bSPeter Brune } 189*eed5f15bSPeter Brune 190*eed5f15bSPeter Brune #undef __FUNCT__ 191*eed5f15bSPeter Brune #define __FUNCT__ "SNESView_Composite" 192*eed5f15bSPeter Brune static PetscErrorCode SNESView_Composite(SNES snes,PetscViewer viewer) 193*eed5f15bSPeter Brune { 194*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 195*eed5f15bSPeter Brune PetscErrorCode ierr; 196*eed5f15bSPeter Brune SNES_CompositeLink next = jac->head; 197*eed5f15bSPeter Brune PetscBool iascii; 198*eed5f15bSPeter Brune 199*eed5f15bSPeter Brune PetscFunctionBegin; 200*eed5f15bSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 201*eed5f15bSPeter Brune if (iascii) { 202*eed5f15bSPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Composite SNES type - %s\n",SNESCompositeTypes[jac->type]);CHKERRQ(ierr); 203*eed5f15bSPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"SNESes on composite preconditioner follow\n");CHKERRQ(ierr); 204*eed5f15bSPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr); 205*eed5f15bSPeter Brune } 206*eed5f15bSPeter Brune if (iascii) { 207*eed5f15bSPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 208*eed5f15bSPeter Brune } 209*eed5f15bSPeter Brune while (next) { 210*eed5f15bSPeter Brune ierr = SNESView(next->snes,viewer);CHKERRQ(ierr); 211*eed5f15bSPeter Brune next = next->next; 212*eed5f15bSPeter Brune } 213*eed5f15bSPeter Brune if (iascii) { 214*eed5f15bSPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 215*eed5f15bSPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr); 216*eed5f15bSPeter Brune } 217*eed5f15bSPeter Brune PetscFunctionReturn(0); 218*eed5f15bSPeter Brune } 219*eed5f15bSPeter Brune 220*eed5f15bSPeter Brune /* ------------------------------------------------------------------------------*/ 221*eed5f15bSPeter Brune 222*eed5f15bSPeter Brune #undef __FUNCT__ 223*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeSetType_Composite" 224*eed5f15bSPeter Brune static PetscErrorCode SNESCompositeSetType_Composite(SNES snes,SNESCompositeType type) 225*eed5f15bSPeter Brune { 226*eed5f15bSPeter Brune SNES_Composite *jac = (SNES_Composite*)snes->data; 227*eed5f15bSPeter Brune 228*eed5f15bSPeter Brune PetscFunctionBegin; 229*eed5f15bSPeter Brune jac->type = type; 230*eed5f15bSPeter Brune PetscFunctionReturn(0); 231*eed5f15bSPeter Brune } 232*eed5f15bSPeter Brune 233*eed5f15bSPeter Brune #undef __FUNCT__ 234*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeAddSNES_Composite" 235*eed5f15bSPeter Brune static PetscErrorCode SNESCompositeAddSNES_Composite(SNES snes,SNESType type) 236*eed5f15bSPeter Brune { 237*eed5f15bSPeter Brune SNES_Composite *jac; 238*eed5f15bSPeter Brune SNES_CompositeLink next,ilink; 239*eed5f15bSPeter Brune PetscErrorCode ierr; 240*eed5f15bSPeter Brune PetscInt cnt = 0; 241*eed5f15bSPeter Brune const char *prefix; 242*eed5f15bSPeter Brune char newprefix[8]; 243*eed5f15bSPeter Brune DM dm; 244*eed5f15bSPeter Brune 245*eed5f15bSPeter Brune PetscFunctionBegin; 246*eed5f15bSPeter Brune ierr = PetscNewLog(snes,struct _SNES_CompositeLink,&ilink);CHKERRQ(ierr); 247*eed5f15bSPeter Brune ilink->next = 0; 248*eed5f15bSPeter Brune ierr = SNESCreate(PetscObjectComm((PetscObject)snes),&ilink->snes);CHKERRQ(ierr); 249*eed5f15bSPeter Brune ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)ilink->snes);CHKERRQ(ierr); 250*eed5f15bSPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 251*eed5f15bSPeter Brune ierr = SNESSetDM(ilink->snes,dm);CHKERRQ(ierr); 252*eed5f15bSPeter Brune 253*eed5f15bSPeter Brune jac = (SNES_Composite*)snes->data; 254*eed5f15bSPeter Brune next = jac->head; 255*eed5f15bSPeter Brune if (!next) { 256*eed5f15bSPeter Brune jac->head = ilink; 257*eed5f15bSPeter Brune ilink->previous = NULL; 258*eed5f15bSPeter Brune } else { 259*eed5f15bSPeter Brune cnt++; 260*eed5f15bSPeter Brune while (next->next) { 261*eed5f15bSPeter Brune next = next->next; 262*eed5f15bSPeter Brune cnt++; 263*eed5f15bSPeter Brune } 264*eed5f15bSPeter Brune next->next = ilink; 265*eed5f15bSPeter Brune ilink->previous = next; 266*eed5f15bSPeter Brune } 267*eed5f15bSPeter Brune ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 268*eed5f15bSPeter Brune ierr = SNESSetOptionsPrefix(ilink->snes,prefix);CHKERRQ(ierr); 269*eed5f15bSPeter Brune sprintf(newprefix,"sub_%d_",(int)cnt); 270*eed5f15bSPeter Brune ierr = SNESAppendOptionsPrefix(ilink->snes,newprefix);CHKERRQ(ierr); 271*eed5f15bSPeter Brune ierr = SNESSetType(ilink->snes,type);CHKERRQ(ierr); 272*eed5f15bSPeter Brune PetscFunctionReturn(0); 273*eed5f15bSPeter Brune } 274*eed5f15bSPeter Brune 275*eed5f15bSPeter Brune #undef __FUNCT__ 276*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeGetSNES_Composite" 277*eed5f15bSPeter Brune static PetscErrorCode SNESCompositeGetSNES_Composite(SNES snes,PetscInt n,SNES *subsnes) 278*eed5f15bSPeter Brune { 279*eed5f15bSPeter Brune SNES_Composite *jac; 280*eed5f15bSPeter Brune SNES_CompositeLink next; 281*eed5f15bSPeter Brune PetscInt i; 282*eed5f15bSPeter Brune 283*eed5f15bSPeter Brune PetscFunctionBegin; 284*eed5f15bSPeter Brune jac = (SNES_Composite*)snes->data; 285*eed5f15bSPeter Brune next = jac->head; 286*eed5f15bSPeter Brune for (i=0; i<n; i++) { 287*eed5f15bSPeter Brune if (!next->next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"Not enough SNESes in composite preconditioner"); 288*eed5f15bSPeter Brune next = next->next; 289*eed5f15bSPeter Brune } 290*eed5f15bSPeter Brune *subsnes = next->snes; 291*eed5f15bSPeter Brune PetscFunctionReturn(0); 292*eed5f15bSPeter Brune } 293*eed5f15bSPeter Brune 294*eed5f15bSPeter Brune /* -------------------------------------------------------------------------------- */ 295*eed5f15bSPeter Brune #undef __FUNCT__ 296*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeSetType" 297*eed5f15bSPeter Brune /*@ 298*eed5f15bSPeter Brune SNESCompositeSetType - Sets the type of composite preconditioner. 299*eed5f15bSPeter Brune 300*eed5f15bSPeter Brune Logically Collective on SNES 301*eed5f15bSPeter Brune 302*eed5f15bSPeter Brune Input Parameter: 303*eed5f15bSPeter Brune + snes - the preconditioner context 304*eed5f15bSPeter Brune - type - SNES_COMPOSITE_ADDITIVE (default), SNES_COMPOSITE_MULTIPLICATIVE 305*eed5f15bSPeter Brune 306*eed5f15bSPeter Brune Options Database Key: 307*eed5f15bSPeter Brune . -snes_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 308*eed5f15bSPeter Brune 309*eed5f15bSPeter Brune Level: Developer 310*eed5f15bSPeter Brune 311*eed5f15bSPeter Brune .keywords: SNES, set, type, composite preconditioner, additive, multiplicative 312*eed5f15bSPeter Brune @*/ 313*eed5f15bSPeter Brune PetscErrorCode SNESCompositeSetType(SNES snes,SNESCompositeType type) 314*eed5f15bSPeter Brune { 315*eed5f15bSPeter Brune PetscErrorCode ierr; 316*eed5f15bSPeter Brune 317*eed5f15bSPeter Brune PetscFunctionBegin; 318*eed5f15bSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 319*eed5f15bSPeter Brune PetscValidLogicalCollectiveEnum(snes,type,2); 320*eed5f15bSPeter Brune ierr = PetscTryMethod(snes,"SNESCompositeSetType_C",(SNES,SNESCompositeType),(snes,type));CHKERRQ(ierr); 321*eed5f15bSPeter Brune PetscFunctionReturn(0); 322*eed5f15bSPeter Brune } 323*eed5f15bSPeter Brune 324*eed5f15bSPeter Brune #undef __FUNCT__ 325*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeAddSNES" 326*eed5f15bSPeter Brune /*@C 327*eed5f15bSPeter Brune SNESCompositeAddSNES - Adds another SNES to the composite SNES. 328*eed5f15bSPeter Brune 329*eed5f15bSPeter Brune Collective on SNES 330*eed5f15bSPeter Brune 331*eed5f15bSPeter Brune Input Parameters: 332*eed5f15bSPeter Brune + snes - the preconditioner context 333*eed5f15bSPeter Brune - type - the type of the new preconditioner 334*eed5f15bSPeter Brune 335*eed5f15bSPeter Brune Level: Developer 336*eed5f15bSPeter Brune 337*eed5f15bSPeter Brune .keywords: SNES, composite preconditioner, add 338*eed5f15bSPeter Brune @*/ 339*eed5f15bSPeter Brune PetscErrorCode SNESCompositeAddSNES(SNES snes,SNESType type) 340*eed5f15bSPeter Brune { 341*eed5f15bSPeter Brune PetscErrorCode ierr; 342*eed5f15bSPeter Brune 343*eed5f15bSPeter Brune PetscFunctionBegin; 344*eed5f15bSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 345*eed5f15bSPeter Brune ierr = PetscTryMethod(snes,"SNESCompositeAddSNES_C",(SNES,SNESType),(snes,type));CHKERRQ(ierr); 346*eed5f15bSPeter Brune PetscFunctionReturn(0); 347*eed5f15bSPeter Brune } 348*eed5f15bSPeter Brune 349*eed5f15bSPeter Brune #undef __FUNCT__ 350*eed5f15bSPeter Brune #define __FUNCT__ "SNESCompositeGetSNES" 351*eed5f15bSPeter Brune /*@ 352*eed5f15bSPeter Brune SNESCompositeGetSNES - Gets one of the SNES objects in the composite SNES. 353*eed5f15bSPeter Brune 354*eed5f15bSPeter Brune Not Collective 355*eed5f15bSPeter Brune 356*eed5f15bSPeter Brune Input Parameter: 357*eed5f15bSPeter Brune + snes - the preconditioner context 358*eed5f15bSPeter Brune - n - the number of the snes requested 359*eed5f15bSPeter Brune 360*eed5f15bSPeter Brune Output Parameters: 361*eed5f15bSPeter Brune . subsnes - the SNES requested 362*eed5f15bSPeter Brune 363*eed5f15bSPeter Brune Level: Developer 364*eed5f15bSPeter Brune 365*eed5f15bSPeter Brune .keywords: SNES, get, composite preconditioner, sub preconditioner 366*eed5f15bSPeter Brune 367*eed5f15bSPeter Brune .seealso: SNESCompositeAddSNES() 368*eed5f15bSPeter Brune @*/ 369*eed5f15bSPeter Brune PetscErrorCode SNESCompositeGetSNES(SNES snes,PetscInt n,SNES *subsnes) 370*eed5f15bSPeter Brune { 371*eed5f15bSPeter Brune PetscErrorCode ierr; 372*eed5f15bSPeter Brune 373*eed5f15bSPeter Brune PetscFunctionBegin; 374*eed5f15bSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 375*eed5f15bSPeter Brune PetscValidPointer(subsnes,3); 376*eed5f15bSPeter Brune ierr = PetscUseMethod(snes,"SNESCompositeGetSNES_C",(SNES,PetscInt,SNES*),(snes,n,subsnes));CHKERRQ(ierr); 377*eed5f15bSPeter Brune PetscFunctionReturn(0); 378*eed5f15bSPeter Brune } 379*eed5f15bSPeter Brune 380*eed5f15bSPeter Brune #undef __FUNCT__ 381*eed5f15bSPeter Brune #define __FUNCT__ "SNESSolve_Composite" 382*eed5f15bSPeter Brune PetscErrorCode SNESSolve_Composite(SNES snes) 383*eed5f15bSPeter Brune { 384*eed5f15bSPeter Brune Vec F; 385*eed5f15bSPeter Brune Vec X; 386*eed5f15bSPeter Brune Vec B; 387*eed5f15bSPeter Brune PetscInt i; 388*eed5f15bSPeter Brune PetscReal fnorm = 0.0; 389*eed5f15bSPeter Brune PetscErrorCode ierr; 390*eed5f15bSPeter Brune SNESNormType normtype; 391*eed5f15bSPeter Brune SNES_Composite *comp = (SNES_Composite*)snes->data; 392*eed5f15bSPeter Brune 393*eed5f15bSPeter Brune PetscFunctionBegin; 394*eed5f15bSPeter Brune X = snes->vec_sol; 395*eed5f15bSPeter Brune F = snes->vec_func; 396*eed5f15bSPeter Brune B = snes->vec_rhs; 397*eed5f15bSPeter Brune 398*eed5f15bSPeter Brune ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 399*eed5f15bSPeter Brune snes->iter = 0; 400*eed5f15bSPeter Brune snes->norm = 0.; 401*eed5f15bSPeter Brune ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 402*eed5f15bSPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 403*eed5f15bSPeter Brune ierr = SNESGetNormType(snes, &normtype);CHKERRQ(ierr); 404*eed5f15bSPeter Brune if (normtype == SNES_NORM_FUNCTION || normtype == SNES_NORM_INITIAL_ONLY || normtype == SNES_NORM_INITIAL_FINAL_ONLY) { 405*eed5f15bSPeter Brune if (!snes->vec_func_init_set) { 406*eed5f15bSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 407*eed5f15bSPeter Brune if (snes->domainerror) { 408*eed5f15bSPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 409*eed5f15bSPeter Brune PetscFunctionReturn(0); 410*eed5f15bSPeter Brune } 411*eed5f15bSPeter Brune } else snes->vec_func_init_set = PETSC_FALSE; 412*eed5f15bSPeter Brune 413*eed5f15bSPeter Brune /* convergence test */ 414*eed5f15bSPeter Brune if (!snes->norm_init_set) { 415*eed5f15bSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 416*eed5f15bSPeter Brune if (PetscIsInfOrNanReal(fnorm)) { 417*eed5f15bSPeter Brune snes->reason = SNES_DIVERGED_FNORM_NAN; 418*eed5f15bSPeter Brune PetscFunctionReturn(0); 419*eed5f15bSPeter Brune } 420*eed5f15bSPeter Brune } else { 421*eed5f15bSPeter Brune fnorm = snes->norm_init; 422*eed5f15bSPeter Brune snes->norm_init_set = PETSC_FALSE; 423*eed5f15bSPeter Brune } 424*eed5f15bSPeter Brune ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 425*eed5f15bSPeter Brune snes->iter = 0; 426*eed5f15bSPeter Brune snes->norm = fnorm; 427*eed5f15bSPeter Brune ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 428*eed5f15bSPeter Brune ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 429*eed5f15bSPeter Brune ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); 430*eed5f15bSPeter Brune 431*eed5f15bSPeter Brune /* set parameter for default relative tolerance convergence test */ 432*eed5f15bSPeter Brune snes->ttol = fnorm*snes->rtol; 433*eed5f15bSPeter Brune 434*eed5f15bSPeter Brune /* test convergence */ 435*eed5f15bSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 436*eed5f15bSPeter Brune if (snes->reason) PetscFunctionReturn(0); 437*eed5f15bSPeter Brune } else { 438*eed5f15bSPeter Brune ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 439*eed5f15bSPeter Brune ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 440*eed5f15bSPeter Brune ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); 441*eed5f15bSPeter Brune } 442*eed5f15bSPeter Brune 443*eed5f15bSPeter Brune /* Call general purpose update function */ 444*eed5f15bSPeter Brune if (snes->ops->update) { 445*eed5f15bSPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 446*eed5f15bSPeter Brune } 447*eed5f15bSPeter Brune 448*eed5f15bSPeter Brune for (i = 0; i < snes->max_its; i++) { 449*eed5f15bSPeter Brune if (comp->type == SNES_COMPOSITE_ADDITIVE) { 450*eed5f15bSPeter Brune ierr = SNESCompositeApply_Additive(snes,X,B,F,&fnorm);CHKERRQ(ierr); 451*eed5f15bSPeter Brune } else if (comp->type == SNES_COMPOSITE_MULTIPLICATIVE) { 452*eed5f15bSPeter Brune ierr = SNESCompositeApply_Multiplicative(snes,X,B,F,&fnorm);CHKERRQ(ierr); 453*eed5f15bSPeter Brune } else { 454*eed5f15bSPeter Brune } 455*eed5f15bSPeter Brune if ((i == snes->max_its - 1) && (normtype == SNES_NORM_INITIAL_FINAL_ONLY || normtype == SNES_NORM_FINAL_ONLY)) { 456*eed5f15bSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 457*eed5f15bSPeter Brune if (snes->domainerror) { 458*eed5f15bSPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 459*eed5f15bSPeter Brune break; 460*eed5f15bSPeter Brune } 461*eed5f15bSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 462*eed5f15bSPeter Brune if (PetscIsInfOrNanReal(fnorm)) { 463*eed5f15bSPeter Brune snes->reason = SNES_DIVERGED_FNORM_NAN; 464*eed5f15bSPeter Brune break; 465*eed5f15bSPeter Brune } 466*eed5f15bSPeter Brune } 467*eed5f15bSPeter Brune /* Monitor convergence */ 468*eed5f15bSPeter Brune ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 469*eed5f15bSPeter Brune snes->iter = i+1; 470*eed5f15bSPeter Brune snes->norm = fnorm; 471*eed5f15bSPeter Brune ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 472*eed5f15bSPeter Brune ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 473*eed5f15bSPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 474*eed5f15bSPeter Brune /* Test for convergence */ 475*eed5f15bSPeter Brune if (normtype == SNES_NORM_FUNCTION) {ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);} 476*eed5f15bSPeter Brune if (snes->reason) break; 477*eed5f15bSPeter Brune /* Call general purpose update function */ 478*eed5f15bSPeter Brune if (snes->ops->update) {ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);} 479*eed5f15bSPeter Brune } 480*eed5f15bSPeter Brune if (normtype == SNES_NORM_FUNCTION) { 481*eed5f15bSPeter Brune if (i == snes->max_its) { 482*eed5f15bSPeter Brune ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",snes->max_its);CHKERRQ(ierr); 483*eed5f15bSPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 484*eed5f15bSPeter Brune } 485*eed5f15bSPeter Brune } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; 486*eed5f15bSPeter Brune PetscFunctionReturn(0); 487*eed5f15bSPeter Brune } 488*eed5f15bSPeter Brune 489*eed5f15bSPeter Brune /* -------------------------------------------------------------------------------------------*/ 490*eed5f15bSPeter Brune 491*eed5f15bSPeter Brune /*MC 492*eed5f15bSPeter Brune SNESCOMPOSITE - Build a preconditioner by composing together several nonlinear solvers 493*eed5f15bSPeter Brune 494*eed5f15bSPeter Brune Options Database Keys: 495*eed5f15bSPeter Brune + -snes_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 496*eed5f15bSPeter Brune - -snes_composite_sneses - <snes0,snes1,...> list of SNESes to compose 497*eed5f15bSPeter Brune 498*eed5f15bSPeter Brune Level: intermediate 499*eed5f15bSPeter Brune 500*eed5f15bSPeter Brune Concepts: composing solvers 501*eed5f15bSPeter Brune 502*eed5f15bSPeter Brune .seealso: SNESCreate(), SNESSetType(), SNESType (for list of available types), SNES, 503*eed5f15bSPeter Brune SNESSHELL, SNESCompositeSetType(), SNESCompositeSpecialSetAlpha(), SNESCompositeAddSNES(), 504*eed5f15bSPeter Brune SNESCompositeGetSNES() 505*eed5f15bSPeter Brune 506*eed5f15bSPeter Brune M*/ 507*eed5f15bSPeter Brune 508*eed5f15bSPeter Brune #undef __FUNCT__ 509*eed5f15bSPeter Brune #define __FUNCT__ "SNESCreate_Composite" 510*eed5f15bSPeter Brune PETSC_EXTERN PetscErrorCode SNESCreate_Composite(SNES snes) 511*eed5f15bSPeter Brune { 512*eed5f15bSPeter Brune PetscErrorCode ierr; 513*eed5f15bSPeter Brune SNES_Composite *jac; 514*eed5f15bSPeter Brune 515*eed5f15bSPeter Brune PetscFunctionBegin; 516*eed5f15bSPeter Brune ierr = PetscNewLog(snes,SNES_Composite,&jac);CHKERRQ(ierr); 517*eed5f15bSPeter Brune 518*eed5f15bSPeter Brune snes->ops->solve = SNESSolve_Composite; 519*eed5f15bSPeter Brune snes->ops->setup = SNESSetUp_Composite; 520*eed5f15bSPeter Brune snes->ops->reset = SNESReset_Composite; 521*eed5f15bSPeter Brune snes->ops->destroy = SNESDestroy_Composite; 522*eed5f15bSPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_Composite; 523*eed5f15bSPeter Brune snes->ops->view = SNESView_Composite; 524*eed5f15bSPeter Brune 525*eed5f15bSPeter Brune snes->data = (void*)jac; 526*eed5f15bSPeter Brune jac->type = SNES_COMPOSITE_ADDITIVE; 527*eed5f15bSPeter Brune jac->head = 0; 528*eed5f15bSPeter Brune 529*eed5f15bSPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESCompositeSetType_C","SNESCompositeSetType_Composite",SNESCompositeSetType_Composite);CHKERRQ(ierr); 530*eed5f15bSPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESCompositeAddSNES_C","SNESCompositeAddSNES_Composite",SNESCompositeAddSNES_Composite);CHKERRQ(ierr); 531*eed5f15bSPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESCompositeGetSNES_C","SNESCompositeGetSNES_Composite",SNESCompositeGetSNES_Composite);CHKERRQ(ierr); 532*eed5f15bSPeter Brune PetscFunctionReturn(0); 533*eed5f15bSPeter Brune } 534*eed5f15bSPeter Brune 535