1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2111ade9eSPeter Brune #include <petscdm.h> 3eaedb033SPeter Brune 4eaedb033SPeter Brune typedef struct { 5eaedb033SPeter Brune PetscInt n; /* local subdomains */ 6eaedb033SPeter Brune SNES *subsnes; /* nonlinear solvers for each subdomain */ 7eaedb033SPeter Brune Vec *x; /* solution vectors */ 8111ade9eSPeter Brune Vec *xl; /* solution local vectors */ 9111ade9eSPeter Brune Vec *y; /* step vectors */ 10eaedb033SPeter Brune Vec *b; /* rhs vectors */ 11f10b3e88SPatrick Farrell Vec weight; /* weighting for adding updates on overlaps, in global space */ 12111ade9eSPeter Brune VecScatter *oscatter; /* scatter from global space to the subdomain global space */ 13f10b3e88SPatrick Farrell VecScatter *oscatter_copy; /* copy of the above */ 14111ade9eSPeter Brune VecScatter *iscatter; /* scatter from global space to the nonoverlapping subdomain space */ 15111ade9eSPeter Brune VecScatter *gscatter; /* scatter from global space to the subdomain local space */ 16111ade9eSPeter Brune PCASMType type; /* ASM type */ 17111ade9eSPeter Brune PetscBool usesdm; /* use the DM for setting up the subproblems */ 18d728fb7dSPeter Brune PetscBool finaljacobian; /* compute the jacobian of the converged solution */ 19610116beSPeter Brune PetscReal damping; /* damping parameter for updates from the blocks */ 20a4f17876SPeter Brune PetscBool same_local_solves; /* flag to determine if the solvers have been individually modified */ 21f10b3e88SPatrick Farrell PetscBool weight_set; /* use a weight in the overlap updates */ 22b20c023fSPeter Brune 23b20c023fSPeter Brune /* logging events */ 24b20c023fSPeter Brune PetscLogEvent eventrestrictinterp; 25b20c023fSPeter Brune PetscLogEvent eventsubsolve; 26602bec5dSPeter Brune 27602bec5dSPeter Brune PetscInt fjtype; /* type of computed jacobian */ 28602bec5dSPeter Brune Vec xinit; /* initial solution in case the final jacobian type is computed as first */ 29eaedb033SPeter Brune } SNES_NASM; 30eaedb033SPeter Brune 31b20c023fSPeter Brune const char *const SNESNASMTypes[] = {"NONE","RESTRICT","INTERPOLATE","BASIC","PCASMType","PC_ASM_",0}; 32602bec5dSPeter Brune const char *const SNESNASMFJTypes[] = {"FINALOUTER","FINALINNER","INITIAL"}; 33b20c023fSPeter Brune 3440244768SBarry Smith static PetscErrorCode SNESReset_NASM(SNES snes) 35eaedb033SPeter Brune { 36eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 37eaedb033SPeter Brune PetscErrorCode ierr; 38eaedb033SPeter Brune PetscInt i; 396e111a19SKarl Rupp 40eaedb033SPeter Brune PetscFunctionBegin; 41eaedb033SPeter Brune for (i=0; i<nasm->n; i++) { 42111ade9eSPeter Brune if (nasm->xl) { ierr = VecDestroy(&nasm->xl[i]);CHKERRQ(ierr); } 43f5f7c1b9SKarl Rupp if (nasm->x) { ierr = VecDestroy(&nasm->x[i]);CHKERRQ(ierr); } 44111ade9eSPeter Brune if (nasm->y) { ierr = VecDestroy(&nasm->y[i]);CHKERRQ(ierr); } 45bc8c1f72SJose Roman if (nasm->b) { ierr = VecDestroy(&nasm->b[i]);CHKERRQ(ierr); } 46eaedb033SPeter Brune 47bc8c1f72SJose Roman if (nasm->subsnes) { ierr = SNESDestroy(&nasm->subsnes[i]);CHKERRQ(ierr); } 48111ade9eSPeter Brune if (nasm->oscatter) { ierr = VecScatterDestroy(&nasm->oscatter[i]);CHKERRQ(ierr); } 49f10b3e88SPatrick Farrell if (nasm->oscatter_copy) { ierr = VecScatterDestroy(&nasm->oscatter_copy[i]);CHKERRQ(ierr); } 50111ade9eSPeter Brune if (nasm->iscatter) { ierr = VecScatterDestroy(&nasm->iscatter[i]);CHKERRQ(ierr); } 51111ade9eSPeter Brune if (nasm->gscatter) { ierr = VecScatterDestroy(&nasm->gscatter[i]);CHKERRQ(ierr); } 52eaedb033SPeter Brune } 53111ade9eSPeter Brune 540677ede6SBarry Smith ierr = PetscFree(nasm->x);CHKERRQ(ierr); 550677ede6SBarry Smith ierr = PetscFree(nasm->xl);CHKERRQ(ierr); 560677ede6SBarry Smith ierr = PetscFree(nasm->y);CHKERRQ(ierr); 570677ede6SBarry Smith ierr = PetscFree(nasm->b);CHKERRQ(ierr); 58111ade9eSPeter Brune 59602bec5dSPeter Brune if (nasm->xinit) {ierr = VecDestroy(&nasm->xinit);CHKERRQ(ierr);} 60602bec5dSPeter Brune 610677ede6SBarry Smith ierr = PetscFree(nasm->subsnes);CHKERRQ(ierr); 620677ede6SBarry Smith ierr = PetscFree(nasm->oscatter);CHKERRQ(ierr); 63f10b3e88SPatrick Farrell ierr = PetscFree(nasm->oscatter_copy);CHKERRQ(ierr); 640677ede6SBarry Smith ierr = PetscFree(nasm->iscatter);CHKERRQ(ierr); 650677ede6SBarry Smith ierr = PetscFree(nasm->gscatter);CHKERRQ(ierr); 66b20c023fSPeter Brune 67f10b3e88SPatrick Farrell if (nasm->weight_set) { 68f10b3e88SPatrick Farrell ierr = VecDestroy(&nasm->weight);CHKERRQ(ierr); 69f10b3e88SPatrick Farrell } 70f10b3e88SPatrick Farrell 71b20c023fSPeter Brune nasm->eventrestrictinterp = 0; 72b20c023fSPeter Brune nasm->eventsubsolve = 0; 73eaedb033SPeter Brune PetscFunctionReturn(0); 74eaedb033SPeter Brune } 75eaedb033SPeter Brune 7640244768SBarry Smith static PetscErrorCode SNESDestroy_NASM(SNES snes) 77eaedb033SPeter Brune { 78eaedb033SPeter Brune PetscErrorCode ierr; 796e111a19SKarl Rupp 80eaedb033SPeter Brune PetscFunctionBegin; 81eaedb033SPeter Brune ierr = SNESReset_NASM(snes);CHKERRQ(ierr); 8222d28d08SBarry Smith ierr = PetscFree(snes->data);CHKERRQ(ierr); 83eaedb033SPeter Brune PetscFunctionReturn(0); 84eaedb033SPeter Brune } 85eaedb033SPeter Brune 8640244768SBarry Smith static PetscErrorCode DMGlobalToLocalSubDomainDirichletHook_Private(DM dm,Vec g,InsertMode mode,Vec l,void *ctx) 870adebc6cSBarry Smith { 88111ade9eSPeter Brune PetscErrorCode ierr; 89111ade9eSPeter Brune Vec bcs = (Vec)ctx; 906e111a19SKarl Rupp 91111ade9eSPeter Brune PetscFunctionBegin; 92111ade9eSPeter Brune ierr = VecCopy(bcs,l);CHKERRQ(ierr); 93111ade9eSPeter Brune PetscFunctionReturn(0); 94111ade9eSPeter Brune } 95111ade9eSPeter Brune 9640244768SBarry Smith static PetscErrorCode SNESSetUp_NASM(SNES snes) 97eaedb033SPeter Brune { 98eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 99eaedb033SPeter Brune PetscErrorCode ierr; 10076857b2aSPeter Brune DM dm,subdm; 101111ade9eSPeter Brune DM *subdms; 102111ade9eSPeter Brune PetscInt i; 103eaedb033SPeter Brune const char *optionsprefix; 104111ade9eSPeter Brune Vec F; 105ed3c11a9SPeter Brune PetscMPIInt size; 106ed3c11a9SPeter Brune KSP ksp; 107ed3c11a9SPeter Brune PC pc; 108eaedb033SPeter Brune 109eaedb033SPeter Brune PetscFunctionBegin; 110eaedb033SPeter Brune if (!nasm->subsnes) { 111eaedb033SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1120a696f66SPeter Brune if (dm) { 113eaedb033SPeter Brune nasm->usesdm = PETSC_TRUE; 1140298fd71SBarry Smith ierr = DMCreateDomainDecomposition(dm,&nasm->n,NULL,NULL,NULL,&subdms);CHKERRQ(ierr); 115ce94432eSBarry Smith if (!subdms) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"DM has no default decomposition defined. Set subsolves manually with SNESNASMSetSubdomains()."); 116111ade9eSPeter Brune ierr = DMCreateDomainDecompositionScatters(dm,nasm->n,subdms,&nasm->iscatter,&nasm->oscatter,&nasm->gscatter);CHKERRQ(ierr); 117f10b3e88SPatrick Farrell ierr = PetscMalloc1(nasm->n, &nasm->oscatter_copy);CHKERRQ(ierr); 118f10b3e88SPatrick Farrell for (i=0; i<nasm->n; i++) { 119f10b3e88SPatrick Farrell ierr = VecScatterCopy(nasm->oscatter[i], &nasm->oscatter_copy[i]);CHKERRQ(ierr); 120f10b3e88SPatrick Farrell } 121eaedb033SPeter Brune 122eaedb033SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 123785e854fSJed Brown ierr = PetscMalloc1(nasm->n,&nasm->subsnes);CHKERRQ(ierr); 124111ade9eSPeter Brune for (i=0; i<nasm->n; i++) { 125cdb298fcSPeter Brune ierr = SNESCreate(PETSC_COMM_SELF,&nasm->subsnes[i]);CHKERRQ(ierr); 1267a2f0ea0SPatrick Farrell ierr = PetscObjectIncrementTabLevel((PetscObject)nasm->subsnes[i], (PetscObject)snes, 1);CHKERRQ(ierr); 127cdb298fcSPeter Brune ierr = SNESAppendOptionsPrefix(nasm->subsnes[i],optionsprefix);CHKERRQ(ierr); 128cdb298fcSPeter Brune ierr = SNESAppendOptionsPrefix(nasm->subsnes[i],"sub_");CHKERRQ(ierr); 129cdb298fcSPeter Brune ierr = SNESSetDM(nasm->subsnes[i],subdms[i]);CHKERRQ(ierr); 130ed3c11a9SPeter Brune ierr = MPI_Comm_size(PetscObjectComm((PetscObject)nasm->subsnes[i]),&size);CHKERRQ(ierr); 131ed3c11a9SPeter Brune if (size == 1) { 132ed3c11a9SPeter Brune ierr = SNESGetKSP(nasm->subsnes[i],&ksp);CHKERRQ(ierr); 133ed3c11a9SPeter Brune ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 134ed3c11a9SPeter Brune ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 135ed3c11a9SPeter Brune ierr = PCSetType(pc,PCLU);CHKERRQ(ierr); 136ed3c11a9SPeter Brune } 137cdb298fcSPeter Brune ierr = SNESSetFromOptions(nasm->subsnes[i]);CHKERRQ(ierr); 138111ade9eSPeter Brune ierr = DMDestroy(&subdms[i]);CHKERRQ(ierr); 139111ade9eSPeter Brune } 140111ade9eSPeter Brune ierr = PetscFree(subdms);CHKERRQ(ierr); 141ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Cannot construct local problems automatically without a DM!"); 142ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set subproblems manually if there is no DM!"); 143111ade9eSPeter Brune /* allocate the global vectors */ 144e245e0aaSPeter Brune if (!nasm->x) { 1451795a4d1SJed Brown ierr = PetscCalloc1(nasm->n,&nasm->x);CHKERRQ(ierr); 146e245e0aaSPeter Brune } 147e245e0aaSPeter Brune if (!nasm->xl) { 1481795a4d1SJed Brown ierr = PetscCalloc1(nasm->n,&nasm->xl);CHKERRQ(ierr); 149e245e0aaSPeter Brune } 150e245e0aaSPeter Brune if (!nasm->y) { 1511795a4d1SJed Brown ierr = PetscCalloc1(nasm->n,&nasm->y);CHKERRQ(ierr); 152e245e0aaSPeter Brune } 153e245e0aaSPeter Brune if (!nasm->b) { 1541795a4d1SJed Brown ierr = PetscCalloc1(nasm->n,&nasm->b);CHKERRQ(ierr); 155e245e0aaSPeter Brune } 156111ade9eSPeter Brune 157111ade9eSPeter Brune for (i=0; i<nasm->n; i++) { 1580298fd71SBarry Smith ierr = SNESGetFunction(nasm->subsnes[i],&F,NULL,NULL);CHKERRQ(ierr); 15976857b2aSPeter Brune if (!nasm->x[i]) {ierr = VecDuplicate(F,&nasm->x[i]);CHKERRQ(ierr);} 16076857b2aSPeter Brune if (!nasm->y[i]) {ierr = VecDuplicate(F,&nasm->y[i]);CHKERRQ(ierr);} 16176857b2aSPeter Brune if (!nasm->b[i]) {ierr = VecDuplicate(F,&nasm->b[i]);CHKERRQ(ierr);} 16276857b2aSPeter Brune if (!nasm->xl[i]) { 163111ade9eSPeter Brune ierr = SNESGetDM(nasm->subsnes[i],&subdm);CHKERRQ(ierr); 164111ade9eSPeter Brune ierr = DMCreateLocalVector(subdm,&nasm->xl[i]);CHKERRQ(ierr); 1650298fd71SBarry Smith ierr = DMGlobalToLocalHookAdd(subdm,DMGlobalToLocalSubDomainDirichletHook_Private,NULL,nasm->xl[i]);CHKERRQ(ierr); 166111ade9eSPeter Brune } 16761ba4676SBarry Smith } 168602bec5dSPeter Brune if (nasm->finaljacobian) { 169602bec5dSPeter Brune ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 170602bec5dSPeter Brune if (nasm->fjtype == 2) { 171602bec5dSPeter Brune ierr = VecDuplicate(snes->vec_sol,&nasm->xinit);CHKERRQ(ierr); 172602bec5dSPeter Brune } 173602bec5dSPeter Brune for (i=0; i<nasm->n;i++) { 174602bec5dSPeter Brune ierr = SNESSetUpMatrices(nasm->subsnes[i]);CHKERRQ(ierr); 175602bec5dSPeter Brune } 176602bec5dSPeter Brune } 177eaedb033SPeter Brune PetscFunctionReturn(0); 178eaedb033SPeter Brune } 179eaedb033SPeter Brune 18040244768SBarry Smith static PetscErrorCode SNESSetFromOptions_NASM(PetscOptionItems *PetscOptionsObject,SNES snes) 181eaedb033SPeter Brune { 182eaedb033SPeter Brune PetscErrorCode ierr; 183111ade9eSPeter Brune PCASMType asmtype; 184a4f17876SPeter Brune PetscBool flg,monflg,subviewflg; 185111ade9eSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 1866e111a19SKarl Rupp 187eaedb033SPeter Brune PetscFunctionBegin; 188e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Nonlinear Additive Schwartz options");CHKERRQ(ierr); 189111ade9eSPeter Brune ierr = PetscOptionsEnum("-snes_nasm_type","Type of restriction/extension","",SNESNASMTypes,(PetscEnum)nasm->type,(PetscEnum*)&asmtype,&flg);CHKERRQ(ierr); 190e0331734SPeter Brune if (flg) {ierr = SNESNASMSetType(snes,asmtype);CHKERRQ(ierr);} 191b20c023fSPeter Brune flg = PETSC_FALSE; 192b20c023fSPeter Brune monflg = PETSC_TRUE; 1935dfa0f3bSBarry Smith ierr = PetscOptionsReal("-snes_nasm_damping","The new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains)","SNESNASMSetDamping",nasm->damping,&nasm->damping,&flg);CHKERRQ(ierr); 194610116beSPeter Brune if (flg) {ierr = SNESNASMSetDamping(snes,nasm->damping);CHKERRQ(ierr);} 195a4f17876SPeter Brune subviewflg = PETSC_FALSE; 196a4f17876SPeter Brune ierr = PetscOptionsBool("-snes_nasm_sub_view","Print detailed information for every processor when using -snes_view","",subviewflg,&subviewflg,&flg);CHKERRQ(ierr); 197a4f17876SPeter Brune if (flg) { 198a4f17876SPeter Brune nasm->same_local_solves = PETSC_FALSE; 199a4f17876SPeter Brune if (!subviewflg) { 200a4f17876SPeter Brune nasm->same_local_solves = PETSC_TRUE; 201a4f17876SPeter Brune } 202a4f17876SPeter Brune } 203d728fb7dSPeter Brune ierr = PetscOptionsBool("-snes_nasm_finaljacobian","Compute the global jacobian of the final iterate (for ASPIN)","",nasm->finaljacobian,&nasm->finaljacobian,NULL);CHKERRQ(ierr); 204602bec5dSPeter Brune ierr = PetscOptionsEList("-snes_nasm_finaljacobian_type","The type of the final jacobian computed.","",SNESNASMFJTypes,3,SNESNASMFJTypes[0],&nasm->fjtype,NULL);CHKERRQ(ierr); 205a4f17876SPeter Brune ierr = PetscOptionsBool("-snes_nasm_log","Log times for subSNES solves and restriction","",monflg,&monflg,&flg);CHKERRQ(ierr); 206b20c023fSPeter Brune if (flg) { 207b20c023fSPeter Brune ierr = PetscLogEventRegister("SNESNASMSubSolve",((PetscObject)snes)->classid,&nasm->eventsubsolve);CHKERRQ(ierr); 208b20c023fSPeter Brune ierr = PetscLogEventRegister("SNESNASMRestrict",((PetscObject)snes)->classid,&nasm->eventrestrictinterp);CHKERRQ(ierr); 209b20c023fSPeter Brune } 210eaedb033SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 211eaedb033SPeter Brune PetscFunctionReturn(0); 212eaedb033SPeter Brune } 213eaedb033SPeter Brune 21440244768SBarry Smith static PetscErrorCode SNESView_NASM(SNES snes, PetscViewer viewer) 215eaedb033SPeter Brune { 216b20c023fSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 217b20c023fSPeter Brune PetscErrorCode ierr; 218a4f17876SPeter Brune PetscMPIInt rank,size; 219dd2fa690SBarry Smith PetscInt i,N,bsz; 220b20c023fSPeter Brune PetscBool iascii,isstring; 221b20c023fSPeter Brune PetscViewer sviewer; 222ce94432eSBarry Smith MPI_Comm comm; 223b20c023fSPeter Brune 224b20c023fSPeter Brune PetscFunctionBegin; 225ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 226b20c023fSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 227b20c023fSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 228b20c023fSPeter Brune ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 229a4f17876SPeter Brune ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 230b2566f29SBarry Smith ierr = MPIU_Allreduce(&nasm->n,&N,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 231b20c023fSPeter Brune if (iascii) { 232efd4aadfSBarry Smith ierr = PetscViewerASCIIPrintf(viewer, " total subdomain blocks = %D\n",N);CHKERRQ(ierr); 233a4f17876SPeter Brune if (nasm->same_local_solves) { 234a4f17876SPeter Brune if (nasm->subsnes) { 235a4f17876SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Local solve is the same for all blocks:\n");CHKERRQ(ierr); 236a4f17876SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2373f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 238a4f17876SPeter Brune if (!rank) { 239a4f17876SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 240a4f17876SPeter Brune ierr = SNESView(nasm->subsnes[0],sviewer);CHKERRQ(ierr); 241a4f17876SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 242a4f17876SPeter Brune } 2433f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 244a4f17876SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 245a4f17876SPeter Brune } 246a4f17876SPeter Brune } else { 247a4f17876SPeter Brune /* print the solver on each block */ 2481575c14dSBarry Smith ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 249b20c023fSPeter Brune ierr = PetscViewerASCIISynchronizedPrintf(viewer," [%d] number of local blocks = %D\n",(int)rank,nasm->n);CHKERRQ(ierr); 250b20c023fSPeter Brune ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2511575c14dSBarry Smith ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 252a4f17876SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Local solve info for each block is in the following SNES objects:\n");CHKERRQ(ierr); 253b20c023fSPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 254a4f17876SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr); 2553f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 256a4f17876SPeter Brune for (i=0; i<nasm->n; i++) { 257a4f17876SPeter Brune ierr = VecGetLocalSize(nasm->x[i],&bsz);CHKERRQ(ierr); 258a4f17876SPeter Brune ierr = PetscViewerASCIIPrintf(sviewer,"[%d] local block number %D, size = %D\n",(int)rank,i,bsz);CHKERRQ(ierr); 259b20c023fSPeter Brune ierr = SNESView(nasm->subsnes[i],sviewer);CHKERRQ(ierr); 260a4f17876SPeter Brune ierr = PetscViewerASCIIPrintf(sviewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr); 261b20c023fSPeter Brune } 2623f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 263a4f17876SPeter Brune ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 264b20c023fSPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 265a4f17876SPeter Brune } 266b20c023fSPeter Brune } else if (isstring) { 267b20c023fSPeter Brune ierr = PetscViewerStringSPrintf(viewer," blocks=%D,type=%s",N,SNESNASMTypes[nasm->type]);CHKERRQ(ierr); 2683f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 269b20c023fSPeter Brune if (nasm->subsnes && !rank) {ierr = SNESView(nasm->subsnes[0],sviewer);CHKERRQ(ierr);} 2703f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 271b20c023fSPeter Brune } 272eaedb033SPeter Brune PetscFunctionReturn(0); 273eaedb033SPeter Brune } 274eaedb033SPeter Brune 275e0331734SPeter Brune /*@ 276e0331734SPeter Brune SNESNASMSetType - Set the type of subdomain update used 277e0331734SPeter Brune 278e0331734SPeter Brune Logically Collective on SNES 279e0331734SPeter Brune 280e0331734SPeter Brune Input Parameters: 281e0331734SPeter Brune + SNES - the SNES context 282e0331734SPeter Brune - type - the type of update, PC_ASM_BASIC or PC_ASM_RESTRICT 283e0331734SPeter Brune 284e0331734SPeter Brune Level: intermediate 285e0331734SPeter Brune 286e0331734SPeter Brune .keywords: SNES, NASM 287e0331734SPeter Brune 288e0331734SPeter Brune .seealso: SNESNASM, SNESNASMGetType(), PCASMSetType() 289e0331734SPeter Brune @*/ 290e0331734SPeter Brune PetscErrorCode SNESNASMSetType(SNES snes,PCASMType type) 291e0331734SPeter Brune { 292e0331734SPeter Brune PetscErrorCode ierr; 293e0331734SPeter Brune PetscErrorCode (*f)(SNES,PCASMType); 294e0331734SPeter Brune 295e0331734SPeter Brune PetscFunctionBegin; 296e0331734SPeter Brune ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNASMSetType_C",&f);CHKERRQ(ierr); 297e0331734SPeter Brune if (f) {ierr = (f)(snes,type);CHKERRQ(ierr);} 298e0331734SPeter Brune PetscFunctionReturn(0); 299e0331734SPeter Brune } 300e0331734SPeter Brune 30140244768SBarry Smith static PetscErrorCode SNESNASMSetType_NASM(SNES snes,PCASMType type) 302e0331734SPeter Brune { 303e0331734SPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 304e0331734SPeter Brune 305e0331734SPeter Brune PetscFunctionBegin; 306e0331734SPeter Brune if (type != PC_ASM_BASIC && type != PC_ASM_RESTRICT) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"SNESNASM only supports basic and restrict types"); 307e0331734SPeter Brune nasm->type = type; 308e0331734SPeter Brune PetscFunctionReturn(0); 309e0331734SPeter Brune } 310e0331734SPeter Brune 311e0331734SPeter Brune /*@ 312e0331734SPeter Brune SNESNASMGetType - Get the type of subdomain update used 313e0331734SPeter Brune 314e0331734SPeter Brune Logically Collective on SNES 315e0331734SPeter Brune 316e0331734SPeter Brune Input Parameters: 317e0331734SPeter Brune . SNES - the SNES context 318e0331734SPeter Brune 319e0331734SPeter Brune Output Parameters: 320e0331734SPeter Brune . type - the type of update 321e0331734SPeter Brune 322e0331734SPeter Brune Level: intermediate 323e0331734SPeter Brune 324e0331734SPeter Brune .keywords: SNES, NASM 325e0331734SPeter Brune 326e0331734SPeter Brune .seealso: SNESNASM, SNESNASMSetType(), PCASMGetType() 327e0331734SPeter Brune @*/ 328e0331734SPeter Brune PetscErrorCode SNESNASMGetType(SNES snes,PCASMType *type) 329e0331734SPeter Brune { 330e0331734SPeter Brune PetscErrorCode ierr; 331e0331734SPeter Brune 332e0331734SPeter Brune PetscFunctionBegin; 3332a808120SBarry Smith ierr = PetscUseMethod(snes,"SNESNASMGetType_C",(SNES,PCASMType*),(snes,type));CHKERRQ(ierr); 334e0331734SPeter Brune PetscFunctionReturn(0); 335e0331734SPeter Brune } 336e0331734SPeter Brune 33740244768SBarry Smith static PetscErrorCode SNESNASMGetType_NASM(SNES snes,PCASMType *type) 338e0331734SPeter Brune { 339e0331734SPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 340e0331734SPeter Brune 341e0331734SPeter Brune PetscFunctionBegin; 342e0331734SPeter Brune *type = nasm->type; 343e0331734SPeter Brune PetscFunctionReturn(0); 344e0331734SPeter Brune } 345e0331734SPeter Brune 34676857b2aSPeter Brune /*@ 34776857b2aSPeter Brune SNESNASMSetSubdomains - Manually Set the context required to restrict and solve subdomain problems. 34876857b2aSPeter Brune 34976857b2aSPeter Brune Not Collective 35076857b2aSPeter Brune 35176857b2aSPeter Brune Input Parameters: 35276857b2aSPeter Brune + SNES - the SNES context 35376857b2aSPeter Brune . n - the number of local subdomains 35476857b2aSPeter Brune . subsnes - solvers defined on the local subdomains 35576857b2aSPeter Brune . iscatter - scatters into the nonoverlapping portions of the local subdomains 35676857b2aSPeter Brune . oscatter - scatters into the overlapping portions of the local subdomains 35776857b2aSPeter Brune - gscatter - scatters into the (ghosted) local vector of the local subdomain 35876857b2aSPeter Brune 35976857b2aSPeter Brune Level: intermediate 36076857b2aSPeter Brune 36176857b2aSPeter Brune .keywords: SNES, NASM 36276857b2aSPeter Brune 36376857b2aSPeter Brune .seealso: SNESNASM, SNESNASMGetSubdomains() 36476857b2aSPeter Brune @*/ 365a6dfd86eSKarl Rupp PetscErrorCode SNESNASMSetSubdomains(SNES snes,PetscInt n,SNES subsnes[],VecScatter iscatter[],VecScatter oscatter[],VecScatter gscatter[]) 366a6dfd86eSKarl Rupp { 367eaedb033SPeter Brune PetscErrorCode ierr; 368111ade9eSPeter Brune PetscErrorCode (*f)(SNES,PetscInt,SNES*,VecScatter*,VecScatter*,VecScatter*); 3696e111a19SKarl Rupp 370eaedb033SPeter Brune PetscFunctionBegin; 3710005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNASMSetSubdomains_C",&f);CHKERRQ(ierr); 3724b838e8fSPeter Brune if (f) {ierr = (f)(snes,n,subsnes,iscatter,oscatter,gscatter);CHKERRQ(ierr);} 373eaedb033SPeter Brune PetscFunctionReturn(0); 374eaedb033SPeter Brune } 375eaedb033SPeter Brune 37640244768SBarry Smith static PetscErrorCode SNESNASMSetSubdomains_NASM(SNES snes,PetscInt n,SNES subsnes[],VecScatter iscatter[],VecScatter oscatter[],VecScatter gscatter[]) 377a6dfd86eSKarl Rupp { 378eaedb033SPeter Brune PetscInt i; 379eaedb033SPeter Brune PetscErrorCode ierr; 380eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 3816e111a19SKarl Rupp 382eaedb033SPeter Brune PetscFunctionBegin; 383ce94432eSBarry Smith if (snes->setupcalled) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNASMSetSubdomains() should be called before calling SNESSetUp()."); 384eaedb033SPeter Brune 385111ade9eSPeter Brune /* tear down the previously set things */ 386111ade9eSPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 387111ade9eSPeter Brune 388eaedb033SPeter Brune nasm->n = n; 389111ade9eSPeter Brune if (oscatter) { 390111ade9eSPeter Brune for (i=0; i<n; i++) {ierr = PetscObjectReference((PetscObject)oscatter[i]);CHKERRQ(ierr);} 391eaedb033SPeter Brune } 392111ade9eSPeter Brune if (iscatter) { 393111ade9eSPeter Brune for (i=0; i<n; i++) {ierr = PetscObjectReference((PetscObject)iscatter[i]);CHKERRQ(ierr);} 394eaedb033SPeter Brune } 395111ade9eSPeter Brune if (gscatter) { 396111ade9eSPeter Brune for (i=0; i<n; i++) {ierr = PetscObjectReference((PetscObject)gscatter[i]);CHKERRQ(ierr);} 397111ade9eSPeter Brune } 398111ade9eSPeter Brune if (oscatter) { 399785e854fSJed Brown ierr = PetscMalloc1(n,&nasm->oscatter);CHKERRQ(ierr); 400f10b3e88SPatrick Farrell ierr = PetscMalloc1(n,&nasm->oscatter_copy);CHKERRQ(ierr); 401eaedb033SPeter Brune for (i=0; i<n; i++) { 402111ade9eSPeter Brune nasm->oscatter[i] = oscatter[i]; 403f10b3e88SPatrick Farrell ierr = VecScatterCopy(oscatter[i], &nasm->oscatter_copy[i]);CHKERRQ(ierr); 404eaedb033SPeter Brune } 405111ade9eSPeter Brune } 406111ade9eSPeter Brune if (iscatter) { 407785e854fSJed Brown ierr = PetscMalloc1(n,&nasm->iscatter);CHKERRQ(ierr); 408eaedb033SPeter Brune for (i=0; i<n; i++) { 409111ade9eSPeter Brune nasm->iscatter[i] = iscatter[i]; 410eaedb033SPeter Brune } 411eaedb033SPeter Brune } 412111ade9eSPeter Brune if (gscatter) { 413785e854fSJed Brown ierr = PetscMalloc1(n,&nasm->gscatter);CHKERRQ(ierr); 414eaedb033SPeter Brune for (i=0; i<n; i++) { 415111ade9eSPeter Brune nasm->gscatter[i] = gscatter[i]; 416eaedb033SPeter Brune } 417eaedb033SPeter Brune } 418111ade9eSPeter Brune 419eaedb033SPeter Brune if (subsnes) { 420785e854fSJed Brown ierr = PetscMalloc1(n,&nasm->subsnes);CHKERRQ(ierr); 421eaedb033SPeter Brune for (i=0; i<n; i++) { 422eaedb033SPeter Brune nasm->subsnes[i] = subsnes[i]; 423eaedb033SPeter Brune } 424a4f17876SPeter Brune nasm->same_local_solves = PETSC_FALSE; 425eaedb033SPeter Brune } 426eaedb033SPeter Brune PetscFunctionReturn(0); 427eaedb033SPeter Brune } 428eaedb033SPeter Brune 42976857b2aSPeter Brune /*@ 43076857b2aSPeter Brune SNESNASMGetSubdomains - Get the local subdomain context. 43176857b2aSPeter Brune 43276857b2aSPeter Brune Not Collective 43376857b2aSPeter Brune 43476857b2aSPeter Brune Input Parameters: 43576857b2aSPeter Brune . SNES - the SNES context 43676857b2aSPeter Brune 43776857b2aSPeter Brune Output Parameters: 43876857b2aSPeter Brune + n - the number of local subdomains 43976857b2aSPeter Brune . subsnes - solvers defined on the local subdomains 44076857b2aSPeter Brune . iscatter - scatters into the nonoverlapping portions of the local subdomains 44176857b2aSPeter Brune . oscatter - scatters into the overlapping portions of the local subdomains 44276857b2aSPeter Brune - gscatter - scatters into the (ghosted) local vector of the local subdomain 44376857b2aSPeter Brune 44476857b2aSPeter Brune Level: intermediate 44576857b2aSPeter Brune 44676857b2aSPeter Brune .keywords: SNES, NASM 44776857b2aSPeter Brune 44876857b2aSPeter Brune .seealso: SNESNASM, SNESNASMSetSubdomains() 44976857b2aSPeter Brune @*/ 45076857b2aSPeter Brune PetscErrorCode SNESNASMGetSubdomains(SNES snes,PetscInt *n,SNES *subsnes[],VecScatter *iscatter[],VecScatter *oscatter[],VecScatter *gscatter[]) 45176857b2aSPeter Brune { 45276857b2aSPeter Brune PetscErrorCode ierr; 45376857b2aSPeter Brune PetscErrorCode (*f)(SNES,PetscInt*,SNES**,VecScatter**,VecScatter**,VecScatter**); 45476857b2aSPeter Brune 45576857b2aSPeter Brune PetscFunctionBegin; 4560005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNASMGetSubdomains_C",&f);CHKERRQ(ierr); 4574b838e8fSPeter Brune if (f) {ierr = (f)(snes,n,subsnes,iscatter,oscatter,gscatter);CHKERRQ(ierr);} 45876857b2aSPeter Brune PetscFunctionReturn(0); 45976857b2aSPeter Brune } 46076857b2aSPeter Brune 46140244768SBarry Smith static PetscErrorCode SNESNASMGetSubdomains_NASM(SNES snes,PetscInt *n,SNES *subsnes[],VecScatter *iscatter[],VecScatter *oscatter[],VecScatter *gscatter[]) 46276857b2aSPeter Brune { 46376857b2aSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 46476857b2aSPeter Brune 46576857b2aSPeter Brune PetscFunctionBegin; 46676857b2aSPeter Brune if (n) *n = nasm->n; 46776857b2aSPeter Brune if (oscatter) *oscatter = nasm->oscatter; 46876857b2aSPeter Brune if (iscatter) *iscatter = nasm->iscatter; 46976857b2aSPeter Brune if (gscatter) *gscatter = nasm->gscatter; 470a4f17876SPeter Brune if (subsnes) { 471a4f17876SPeter Brune *subsnes = nasm->subsnes; 472a4f17876SPeter Brune nasm->same_local_solves = PETSC_FALSE; 473a4f17876SPeter Brune } 47476857b2aSPeter Brune PetscFunctionReturn(0); 47576857b2aSPeter Brune } 47676857b2aSPeter Brune 47776857b2aSPeter Brune /*@ 47876857b2aSPeter Brune SNESNASMGetSubdomainVecs - Get the processor-local subdomain vectors 47976857b2aSPeter Brune 48076857b2aSPeter Brune Not Collective 48176857b2aSPeter Brune 48276857b2aSPeter Brune Input Parameters: 48376857b2aSPeter Brune . SNES - the SNES context 48476857b2aSPeter Brune 48576857b2aSPeter Brune Output Parameters: 48676857b2aSPeter Brune + n - the number of local subdomains 48776857b2aSPeter Brune . x - The subdomain solution vector 48876857b2aSPeter Brune . y - The subdomain step vector 48976857b2aSPeter Brune . b - The subdomain RHS vector 49076857b2aSPeter Brune - xl - The subdomain local vectors (ghosted) 49176857b2aSPeter Brune 49276857b2aSPeter Brune Level: developer 49376857b2aSPeter Brune 49476857b2aSPeter Brune .keywords: SNES, NASM 49576857b2aSPeter Brune 49676857b2aSPeter Brune .seealso: SNESNASM, SNESNASMGetSubdomains() 49776857b2aSPeter Brune @*/ 49876857b2aSPeter Brune PetscErrorCode SNESNASMGetSubdomainVecs(SNES snes,PetscInt *n,Vec **x,Vec **y,Vec **b, Vec **xl) 49976857b2aSPeter Brune { 50076857b2aSPeter Brune PetscErrorCode ierr; 50176857b2aSPeter Brune PetscErrorCode (*f)(SNES,PetscInt*,Vec**,Vec**,Vec**,Vec**); 50276857b2aSPeter Brune 50376857b2aSPeter Brune PetscFunctionBegin; 5040005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNASMGetSubdomainVecs_C",&f);CHKERRQ(ierr); 5054b838e8fSPeter Brune if (f) {ierr = (f)(snes,n,x,y,b,xl);CHKERRQ(ierr);} 50676857b2aSPeter Brune PetscFunctionReturn(0); 50776857b2aSPeter Brune } 50876857b2aSPeter Brune 50940244768SBarry Smith static PetscErrorCode SNESNASMGetSubdomainVecs_NASM(SNES snes,PetscInt *n,Vec **x,Vec **y,Vec **b,Vec **xl) 51076857b2aSPeter Brune { 51176857b2aSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 51276857b2aSPeter Brune 51376857b2aSPeter Brune PetscFunctionBegin; 51476857b2aSPeter Brune if (n) *n = nasm->n; 51576857b2aSPeter Brune if (x) *x = nasm->x; 51676857b2aSPeter Brune if (y) *y = nasm->y; 51776857b2aSPeter Brune if (b) *b = nasm->b; 51876857b2aSPeter Brune if (xl) *xl = nasm->xl; 51976857b2aSPeter Brune PetscFunctionReturn(0); 52076857b2aSPeter Brune } 52176857b2aSPeter Brune 522d728fb7dSPeter Brune /*@ 523d728fb7dSPeter Brune SNESNASMSetComputeFinalJacobian - Schedules the computation of the global and subdomain jacobians upon convergence 524d728fb7dSPeter Brune 525d728fb7dSPeter Brune Collective on SNES 526d728fb7dSPeter Brune 527d728fb7dSPeter Brune Input Parameters: 528d728fb7dSPeter Brune + SNES - the SNES context 529d728fb7dSPeter Brune - flg - indication of whether to compute the jacobians or not 530d728fb7dSPeter Brune 531d728fb7dSPeter Brune Level: developer 532d728fb7dSPeter Brune 53395452b02SPatrick Sanan Notes: 53495452b02SPatrick Sanan This is used almost exclusively in the implementation of ASPIN, where the converged subdomain and global jacobian 535d728fb7dSPeter Brune is needed at each linear iteration. 536d728fb7dSPeter Brune 537d728fb7dSPeter Brune .keywords: SNES, NASM, ASPIN 538d728fb7dSPeter Brune 539d728fb7dSPeter Brune .seealso: SNESNASM, SNESNASMGetSubdomains() 540d728fb7dSPeter Brune @*/ 541d728fb7dSPeter Brune PetscErrorCode SNESNASMSetComputeFinalJacobian(SNES snes,PetscBool flg) 542d728fb7dSPeter Brune { 543d728fb7dSPeter Brune PetscErrorCode (*f)(SNES,PetscBool); 544d728fb7dSPeter Brune PetscErrorCode ierr; 545d728fb7dSPeter Brune 546d728fb7dSPeter Brune PetscFunctionBegin; 5470005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNASMSetComputeFinalJacobian_C",&f);CHKERRQ(ierr); 5484b838e8fSPeter Brune if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);} 549d728fb7dSPeter Brune PetscFunctionReturn(0); 550d728fb7dSPeter Brune } 551d728fb7dSPeter Brune 55240244768SBarry Smith static PetscErrorCode SNESNASMSetComputeFinalJacobian_NASM(SNES snes,PetscBool flg) 553d728fb7dSPeter Brune { 554d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 555d728fb7dSPeter Brune 556d728fb7dSPeter Brune PetscFunctionBegin; 557d728fb7dSPeter Brune nasm->finaljacobian = flg; 558d728fb7dSPeter Brune PetscFunctionReturn(0); 559d728fb7dSPeter Brune } 56076857b2aSPeter Brune 561610116beSPeter Brune /*@ 562610116beSPeter Brune SNESNASMSetDamping - Sets the update damping for NASM 563610116beSPeter Brune 564610116beSPeter Brune Logically collective on SNES 565610116beSPeter Brune 566610116beSPeter Brune Input Parameters: 567610116beSPeter Brune + SNES - the SNES context 568610116beSPeter Brune - dmp - damping 569610116beSPeter Brune 570610116beSPeter Brune Level: intermediate 571610116beSPeter Brune 57295452b02SPatrick Sanan Notes: 57395452b02SPatrick Sanan The new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 5745dfa0f3bSBarry Smith 575610116beSPeter Brune .keywords: SNES, NASM, damping 576610116beSPeter Brune 577610116beSPeter Brune .seealso: SNESNASM, SNESNASMGetDamping() 578610116beSPeter Brune @*/ 579610116beSPeter Brune PetscErrorCode SNESNASMSetDamping(SNES snes,PetscReal dmp) 580610116beSPeter Brune { 581610116beSPeter Brune PetscErrorCode (*f)(SNES,PetscReal); 582610116beSPeter Brune PetscErrorCode ierr; 583610116beSPeter Brune 584610116beSPeter Brune PetscFunctionBegin; 585610116beSPeter Brune ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNASMSetDamping_C",(void (**)(void))&f);CHKERRQ(ierr); 586e24b0d94SPeter Brune if (f) {ierr = (f)(snes,dmp);CHKERRQ(ierr);} 587610116beSPeter Brune PetscFunctionReturn(0); 588610116beSPeter Brune } 589610116beSPeter Brune 59040244768SBarry Smith static PetscErrorCode SNESNASMSetDamping_NASM(SNES snes,PetscReal dmp) 591610116beSPeter Brune { 592610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 593610116beSPeter Brune 594610116beSPeter Brune PetscFunctionBegin; 595610116beSPeter Brune nasm->damping = dmp; 596610116beSPeter Brune PetscFunctionReturn(0); 597610116beSPeter Brune } 598610116beSPeter Brune 599610116beSPeter Brune /*@ 600610116beSPeter Brune SNESNASMGetDamping - Gets the update damping for NASM 601610116beSPeter Brune 602610116beSPeter Brune Not Collective 603610116beSPeter Brune 604610116beSPeter Brune Input Parameters: 605610116beSPeter Brune + SNES - the SNES context 606610116beSPeter Brune - dmp - damping 607610116beSPeter Brune 608610116beSPeter Brune Level: intermediate 609610116beSPeter Brune 610610116beSPeter Brune .keywords: SNES, NASM, damping 611610116beSPeter Brune 612610116beSPeter Brune .seealso: SNESNASM, SNESNASMSetDamping() 613610116beSPeter Brune @*/ 614610116beSPeter Brune PetscErrorCode SNESNASMGetDamping(SNES snes,PetscReal *dmp) 615610116beSPeter Brune { 616610116beSPeter Brune PetscErrorCode ierr; 617610116beSPeter Brune 618610116beSPeter Brune PetscFunctionBegin; 6194a2f8832SBarry Smith ierr = PetscUseMethod(snes,"SNESNASMGetDamping_C",(SNES,PetscReal*),(snes,dmp));CHKERRQ(ierr); 620610116beSPeter Brune PetscFunctionReturn(0); 621610116beSPeter Brune } 622610116beSPeter Brune 62340244768SBarry Smith static PetscErrorCode SNESNASMGetDamping_NASM(SNES snes,PetscReal *dmp) 624610116beSPeter Brune { 625610116beSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 626610116beSPeter Brune 627610116beSPeter Brune PetscFunctionBegin; 628610116beSPeter Brune *dmp = nasm->damping; 629610116beSPeter Brune PetscFunctionReturn(0); 630610116beSPeter Brune } 631610116beSPeter Brune 632610116beSPeter Brune 63314eb1c5cSMatthew G. Knepley /* 63414eb1c5cSMatthew G. Knepley Input Parameters: 63514eb1c5cSMatthew G. Knepley + snes - The solver 63614eb1c5cSMatthew G. Knepley . B - The RHS vector 63714eb1c5cSMatthew G. Knepley - X - The initial guess 63814eb1c5cSMatthew G. Knepley 63914eb1c5cSMatthew G. Knepley Output Parameters: 64014eb1c5cSMatthew G. Knepley . Y - The solution update 64114eb1c5cSMatthew G. Knepley 64214eb1c5cSMatthew G. Knepley TODO: All scatters should be packed into one 64314eb1c5cSMatthew G. Knepley */ 6440adebc6cSBarry Smith PetscErrorCode SNESNASMSolveLocal_Private(SNES snes,Vec B,Vec Y,Vec X) 6450adebc6cSBarry Smith { 646eaedb033SPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 647258e1594SPeter Brune SNES subsnes; 648eaedb033SPeter Brune PetscInt i; 649610116beSPeter Brune PetscReal dmp; 650eaedb033SPeter Brune PetscErrorCode ierr; 651f10b3e88SPatrick Farrell Vec Xl,Bl,Yl,Xlloc; 652f10b3e88SPatrick Farrell VecScatter iscat,oscat,gscat,oscat_copy; 653111ade9eSPeter Brune DM dm,subdm; 654e0331734SPeter Brune PCASMType type; 6550adebc6cSBarry Smith 656eaedb033SPeter Brune PetscFunctionBegin; 657e0331734SPeter Brune ierr = SNESNASMGetType(snes,&type);CHKERRQ(ierr); 658eaedb033SPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 659111ade9eSPeter Brune ierr = VecSet(Y,0);CHKERRQ(ierr); 660b20c023fSPeter Brune if (nasm->eventrestrictinterp) {ierr = PetscLogEventBegin(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} 661eaedb033SPeter Brune for (i=0; i<nasm->n; i++) { 662f10b3e88SPatrick Farrell /* scatter the solution to the global solution and the local solution */ 663f10b3e88SPatrick Farrell Xl = nasm->x[i]; 66470c78f05SPeter Brune Xlloc = nasm->xl[i]; 66570c78f05SPeter Brune oscat = nasm->oscatter[i]; 666f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 667f10b3e88SPatrick Farrell gscat = nasm->gscatter[i]; 668f10b3e88SPatrick Farrell ierr = VecScatterBegin(oscat,X,Xl,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 66970c78f05SPeter Brune ierr = VecScatterBegin(gscat,X,Xlloc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 67070c78f05SPeter Brune if (B) { 67170c78f05SPeter Brune /* scatter the RHS to the local RHS */ 67270c78f05SPeter Brune Bl = nasm->b[i]; 673f10b3e88SPatrick Farrell ierr = VecScatterBegin(oscat_copy,B,Bl,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 67470c78f05SPeter Brune } 67570c78f05SPeter Brune } 676b20c023fSPeter Brune if (nasm->eventrestrictinterp) {ierr = PetscLogEventEnd(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} 677b20c023fSPeter Brune 678b20c023fSPeter Brune 679b20c023fSPeter Brune if (nasm->eventsubsolve) {ierr = PetscLogEventBegin(nasm->eventsubsolve,snes,0,0,0);CHKERRQ(ierr);} 68070c78f05SPeter Brune for (i=0; i<nasm->n; i++) { 68170c78f05SPeter Brune Xl = nasm->x[i]; 68270c78f05SPeter Brune Xlloc = nasm->xl[i]; 68370c78f05SPeter Brune Yl = nasm->y[i]; 684258e1594SPeter Brune subsnes = nasm->subsnes[i]; 685258e1594SPeter Brune ierr = SNESGetDM(subsnes,&subdm);CHKERRQ(ierr); 686111ade9eSPeter Brune iscat = nasm->iscatter[i]; 687111ade9eSPeter Brune oscat = nasm->oscatter[i]; 688f10b3e88SPatrick Farrell oscat_copy = nasm->oscatter_copy[i]; 689111ade9eSPeter Brune gscat = nasm->gscatter[i]; 690f10b3e88SPatrick Farrell ierr = VecScatterEnd(oscat,X,Xl,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 691ed3c11a9SPeter Brune ierr = VecScatterEnd(gscat,X,Xlloc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 69224b7f281SPeter Brune if (B) { 69324b7f281SPeter Brune Bl = nasm->b[i]; 694f10b3e88SPatrick Farrell ierr = VecScatterEnd(oscat_copy,B,Bl,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 695ed3c11a9SPeter Brune } else Bl = NULL; 696f10b3e88SPatrick Farrell 697ed3c11a9SPeter Brune ierr = DMSubDomainRestrict(dm,oscat,gscat,subdm);CHKERRQ(ierr); 698111ade9eSPeter Brune ierr = VecCopy(Xl,Yl);CHKERRQ(ierr); 699ed3c11a9SPeter Brune ierr = SNESSolve(subsnes,Bl,Xl);CHKERRQ(ierr); 700ed3c11a9SPeter Brune ierr = VecAYPX(Yl,-1.0,Xl);CHKERRQ(ierr); 701f10b3e88SPatrick Farrell ierr = VecScale(Yl, nasm->damping);CHKERRQ(ierr); 702e0331734SPeter Brune if (type == PC_ASM_BASIC) { 703111ade9eSPeter Brune ierr = VecScatterBegin(oscat,Yl,Y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 704e0331734SPeter Brune } else if (type == PC_ASM_RESTRICT) { 705111ade9eSPeter Brune ierr = VecScatterBegin(iscat,Yl,Y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 706ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Only basic and restrict types are supported for SNESNASM"); 707eaedb033SPeter Brune } 708ed3c11a9SPeter Brune if (nasm->eventsubsolve) {ierr = PetscLogEventEnd(nasm->eventsubsolve,snes,0,0,0);CHKERRQ(ierr);} 709ed3c11a9SPeter Brune if (nasm->eventrestrictinterp) {ierr = PetscLogEventBegin(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} 71070c78f05SPeter Brune for (i=0; i<nasm->n; i++) { 71170c78f05SPeter Brune Yl = nasm->y[i]; 71270c78f05SPeter Brune iscat = nasm->iscatter[i]; 71370c78f05SPeter Brune oscat = nasm->oscatter[i]; 714e0331734SPeter Brune if (type == PC_ASM_BASIC) { 71570c78f05SPeter Brune ierr = VecScatterEnd(oscat,Yl,Y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 716e0331734SPeter Brune } else if (type == PC_ASM_RESTRICT) { 71770c78f05SPeter Brune ierr = VecScatterEnd(iscat,Yl,Y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 718ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Only basic and restrict types are supported for SNESNASM"); 71970c78f05SPeter Brune } 720f10b3e88SPatrick Farrell if (nasm->weight_set) { 721f10b3e88SPatrick Farrell ierr = VecPointwiseMult(Y,Y,nasm->weight);CHKERRQ(ierr); 722f10b3e88SPatrick Farrell } 723b20c023fSPeter Brune if (nasm->eventrestrictinterp) {ierr = PetscLogEventEnd(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} 7245dfa0f3bSBarry Smith ierr = SNESNASMGetDamping(snes,&dmp);CHKERRQ(ierr); 725610116beSPeter Brune ierr = VecAXPY(X,dmp,Y);CHKERRQ(ierr); 726eaedb033SPeter Brune PetscFunctionReturn(0); 727eaedb033SPeter Brune } 728eaedb033SPeter Brune 72940244768SBarry Smith static PetscErrorCode SNESNASMComputeFinalJacobian_Private(SNES snes, Vec Xfinal) 730d728fb7dSPeter Brune { 731602bec5dSPeter Brune Vec X = Xfinal; 732d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 733d728fb7dSPeter Brune SNES subsnes; 734ca44f815SPeter Brune PetscInt i,lag = 1; 735d728fb7dSPeter Brune PetscErrorCode ierr; 736e59f0a30SPeter Brune Vec Xlloc,Xl,Fl,F; 737d728fb7dSPeter Brune VecScatter oscat,gscat; 738d728fb7dSPeter Brune DM dm,subdm; 739d1e9a80fSBarry Smith 740d728fb7dSPeter Brune PetscFunctionBegin; 741602bec5dSPeter Brune if (nasm->fjtype == 2) X = nasm->xinit; 742e59f0a30SPeter Brune F = snes->vec_func; 743365a6726SPeter Brune if (snes->normschedule == SNES_NORM_NONE) {ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);} 744d1e9a80fSBarry Smith ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); 745d728fb7dSPeter Brune ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 746d728fb7dSPeter Brune if (nasm->eventrestrictinterp) {ierr = PetscLogEventBegin(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} 747602bec5dSPeter Brune if (nasm->fjtype != 1) { 748d728fb7dSPeter Brune for (i=0; i<nasm->n; i++) { 749d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 750d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 751d728fb7dSPeter Brune ierr = VecScatterBegin(gscat,X,Xlloc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 752602bec5dSPeter Brune } 753d728fb7dSPeter Brune } 754d728fb7dSPeter Brune if (nasm->eventrestrictinterp) {ierr = PetscLogEventEnd(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} 755d728fb7dSPeter Brune for (i=0; i<nasm->n; i++) { 756e59f0a30SPeter Brune Fl = nasm->subsnes[i]->vec_func; 757d728fb7dSPeter Brune Xl = nasm->x[i]; 758d728fb7dSPeter Brune Xlloc = nasm->xl[i]; 759d728fb7dSPeter Brune subsnes = nasm->subsnes[i]; 760d728fb7dSPeter Brune oscat = nasm->oscatter[i]; 761d728fb7dSPeter Brune gscat = nasm->gscatter[i]; 762602bec5dSPeter Brune if (nasm->fjtype != 1) {ierr = VecScatterEnd(gscat,X,Xlloc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);} 763ed3c11a9SPeter Brune ierr = SNESGetDM(subsnes,&subdm);CHKERRQ(ierr); 764d728fb7dSPeter Brune ierr = DMSubDomainRestrict(dm,oscat,gscat,subdm);CHKERRQ(ierr); 765602bec5dSPeter Brune if (nasm->fjtype != 1) { 766d728fb7dSPeter Brune ierr = DMLocalToGlobalBegin(subdm,Xlloc,INSERT_VALUES,Xl);CHKERRQ(ierr); 767d728fb7dSPeter Brune ierr = DMLocalToGlobalEnd(subdm,Xlloc,INSERT_VALUES,Xl);CHKERRQ(ierr); 768602bec5dSPeter Brune } 769ca44f815SPeter Brune if (subsnes->lagjacobian == -1) subsnes->lagjacobian = -2; 770ca44f815SPeter Brune else if (subsnes->lagjacobian > 1) lag = subsnes->lagjacobian; 771602bec5dSPeter Brune ierr = SNESComputeFunction(subsnes,Xl,Fl);CHKERRQ(ierr); 772d1e9a80fSBarry Smith ierr = SNESComputeJacobian(subsnes,Xl,subsnes->jacobian,subsnes->jacobian_pre);CHKERRQ(ierr); 773ca44f815SPeter Brune if (lag > 1) subsnes->lagjacobian = lag; 774d728fb7dSPeter Brune } 775d728fb7dSPeter Brune PetscFunctionReturn(0); 776d728fb7dSPeter Brune } 777d728fb7dSPeter Brune 77840244768SBarry Smith static PetscErrorCode SNESSolve_NASM(SNES snes) 779eaedb033SPeter Brune { 780eaedb033SPeter Brune Vec F; 781eaedb033SPeter Brune Vec X; 782eaedb033SPeter Brune Vec B; 783111ade9eSPeter Brune Vec Y; 784eaedb033SPeter Brune PetscInt i; 785ed3c11a9SPeter Brune PetscReal fnorm = 0.0; 786eaedb033SPeter Brune PetscErrorCode ierr; 787365a6726SPeter Brune SNESNormSchedule normschedule; 788d728fb7dSPeter Brune SNES_NASM *nasm = (SNES_NASM*)snes->data; 789eaedb033SPeter Brune 790eaedb033SPeter Brune PetscFunctionBegin; 791c579b300SPatrick Farrell 7926c4ed002SBarry Smith if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 793c579b300SPatrick Farrell 794fffbeea8SBarry Smith ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 795eaedb033SPeter Brune X = snes->vec_sol; 796111ade9eSPeter Brune Y = snes->vec_sol_update; 797eaedb033SPeter Brune F = snes->vec_func; 798eaedb033SPeter Brune B = snes->vec_rhs; 799eaedb033SPeter Brune 800e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 801eaedb033SPeter Brune snes->iter = 0; 802eaedb033SPeter Brune snes->norm = 0.; 803e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 804eaedb033SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 805365a6726SPeter Brune ierr = SNESGetNormSchedule(snes, &normschedule);CHKERRQ(ierr); 806365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY) { 807eaedb033SPeter Brune /* compute the initial function and preconditioned update delX */ 808eaedb033SPeter Brune if (!snes->vec_func_init_set) { 809eaedb033SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 8101aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 811eaedb033SPeter Brune 812eaedb033SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 813422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 814e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 815eaedb033SPeter Brune snes->iter = 0; 816eaedb033SPeter Brune snes->norm = fnorm; 817e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 818a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 819eaedb033SPeter Brune ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); 820eaedb033SPeter Brune 821eaedb033SPeter Brune /* test convergence */ 822eaedb033SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 823eaedb033SPeter Brune if (snes->reason) PetscFunctionReturn(0); 824eaedb033SPeter Brune } else { 825e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 826a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 827eaedb033SPeter Brune ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); 828eaedb033SPeter Brune } 829eaedb033SPeter Brune 830eaedb033SPeter Brune /* Call general purpose update function */ 831eaedb033SPeter Brune if (snes->ops->update) { 832eaedb033SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 833eaedb033SPeter Brune } 834602bec5dSPeter Brune /* copy the initial solution over for later */ 835602bec5dSPeter Brune if (nasm->fjtype == 2) {ierr = VecCopy(X,nasm->xinit);CHKERRQ(ierr);} 836eaedb033SPeter Brune 837eaedb033SPeter Brune for (i=0; i < snes->max_its; i++) { 838111ade9eSPeter Brune ierr = SNESNASMSolveLocal_Private(snes,B,Y,X);CHKERRQ(ierr); 839365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS || ((i == snes->max_its - 1) && (normschedule == SNES_NORM_INITIAL_FINAL_ONLY || normschedule == SNES_NORM_FINAL_ONLY))) { 840eaedb033SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 841eaedb033SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 842422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 843eaedb033SPeter Brune } 844eaedb033SPeter Brune /* Monitor convergence */ 845e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 846eaedb033SPeter Brune snes->iter = i+1; 847eaedb033SPeter Brune snes->norm = fnorm; 848e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 849a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 850eaedb033SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 851eaedb033SPeter Brune /* Test for convergence */ 852365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS) {ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);} 853d728fb7dSPeter Brune if (snes->reason) break; 854eaedb033SPeter Brune /* Call general purpose update function */ 855e59f0a30SPeter Brune if (snes->ops->update) {ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);} 856eaedb033SPeter Brune } 85707b62357SFande Kong if (nasm->finaljacobian) { 85807b62357SFande Kong ierr = SNESNASMComputeFinalJacobian_Private(snes,X);CHKERRQ(ierr); 85907b62357SFande Kong SNESCheckJacobianDomainerror(snes); 86007b62357SFande Kong } 861365a6726SPeter Brune if (normschedule == SNES_NORM_ALWAYS) { 862eaedb033SPeter Brune if (i == snes->max_its) { 863eaedb033SPeter Brune ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",snes->max_its);CHKERRQ(ierr); 864eaedb033SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 865eaedb033SPeter Brune } 8661aa26658SKarl Rupp } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; /* NASM is meant to be used as a preconditioner */ 867eaedb033SPeter Brune PetscFunctionReturn(0); 868eaedb033SPeter Brune } 869eaedb033SPeter Brune 870eaedb033SPeter Brune /*MC 871eaedb033SPeter Brune SNESNASM - Nonlinear Additive Schwartz 872eaedb033SPeter Brune 87370c78603SPeter Brune Options Database: 87470c78603SPeter Brune + -snes_nasm_log - enable logging events for the communication and solve stages 87570c78603SPeter Brune . -snes_nasm_type <basic,restrict> - type of subdomain update used 8765dfa0f3bSBarry Smith . -snes_asm_damping <dmp> - the new solution is obtained as old solution plus dmp times (sum of the solutions on the subdomains) 87770c78603SPeter Brune . -snes_nasm_finaljacobian - compute the local and global jacobians of the final iterate 878150d49b7SHong Zhang . -snes_nasm_finaljacobian_type <finalinner,finalouter,initial> - pick state the jacobian is calculated at 87970c78603SPeter Brune . -sub_snes_ - options prefix of the subdomain nonlinear solves 88070c78603SPeter Brune . -sub_ksp_ - options prefix of the subdomain Krylov solver 88170c78603SPeter Brune - -sub_pc_ - options prefix of the subdomain preconditioner 88270c78603SPeter Brune 883eaedb033SPeter Brune Level: advanced 884eaedb033SPeter Brune 885*951fe5abSBarry Smith Developer Note: This is a non-Newton based nonlinear solver that does not directly require a Jacobian; hence the flag snes->usesksp is set to 886*951fe5abSBarry Smith false and SNESView() and -snes_view do not display a KSP object. However the flag nasm->finaljacobian is set (for example if 887*951fe5abSBarry Smith NASM is used as a nonlinear preconditioner for KSPASPIN) then SNESSetUpMatrices() is called to generate the Jacobian (needed by KSPASPIN) 888*951fe5abSBarry Smith and this utilizes the KSP for storing the matrices, but the KSP is never used for solving a linear system. Note that when SNESNASM is 889*951fe5abSBarry Smith used by SNESASPIN they share the same Jacobian matrices because SNESSetUp() (called on the outer SNES KSPASPIN) causes the inner SNES 890*951fe5abSBarry Smith object (in this case SNESNASM) to inherit the outer Jacobian matrices. 891*951fe5abSBarry Smith 8924f02bc6aSBarry Smith References: 89396a0c994SBarry Smith . 1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 8944f02bc6aSBarry Smith SIAM Review, 57(4), 2015 8954f02bc6aSBarry Smith 8965dfa0f3bSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types), SNESNASMSetType(), SNESNASMGetType(), SNESNASMSetSubdomains(), SNESNASMGetSubdomains(), SNESNASMGetSubdomainVecs(), SNESNASMSetComputeFinalJacobian(), SNESNASMSetDamping(), SNESNASMGetDamping() 897eaedb033SPeter Brune M*/ 898eaedb033SPeter Brune 8998cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NASM(SNES snes) 900eaedb033SPeter Brune { 901eaedb033SPeter Brune SNES_NASM *nasm; 902eaedb033SPeter Brune PetscErrorCode ierr; 903eaedb033SPeter Brune 904eaedb033SPeter Brune PetscFunctionBegin; 905b00a9115SJed Brown ierr = PetscNewLog(snes,&nasm);CHKERRQ(ierr); 906eaedb033SPeter Brune snes->data = (void*)nasm; 907eaedb033SPeter Brune 908eaedb033SPeter Brune nasm->n = PETSC_DECIDE; 909eaedb033SPeter Brune nasm->subsnes = 0; 910eaedb033SPeter Brune nasm->x = 0; 911111ade9eSPeter Brune nasm->xl = 0; 912111ade9eSPeter Brune nasm->y = 0; 913eaedb033SPeter Brune nasm->b = 0; 914111ade9eSPeter Brune nasm->oscatter = 0; 915f10b3e88SPatrick Farrell nasm->oscatter_copy = 0; 916111ade9eSPeter Brune nasm->iscatter = 0; 917111ade9eSPeter Brune nasm->gscatter = 0; 918610116beSPeter Brune nasm->damping = 1.; 919111ade9eSPeter Brune 920111ade9eSPeter Brune nasm->type = PC_ASM_BASIC; 921d728fb7dSPeter Brune nasm->finaljacobian = PETSC_FALSE; 922a4f17876SPeter Brune nasm->same_local_solves = PETSC_TRUE; 923f10b3e88SPatrick Farrell nasm->weight_set = PETSC_FALSE; 924eaedb033SPeter Brune 925eaedb033SPeter Brune snes->ops->destroy = SNESDestroy_NASM; 926eaedb033SPeter Brune snes->ops->setup = SNESSetUp_NASM; 927eaedb033SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NASM; 928eaedb033SPeter Brune snes->ops->view = SNESView_NASM; 929eaedb033SPeter Brune snes->ops->solve = SNESSolve_NASM; 930eaedb033SPeter Brune snes->ops->reset = SNESReset_NASM; 931eaedb033SPeter Brune 932eaedb033SPeter Brune snes->usesksp = PETSC_FALSE; 933efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 934eaedb033SPeter Brune 9354fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE; 9364fc747eaSLawrence Mitchell 937602bec5dSPeter Brune nasm->fjtype = 0; 938602bec5dSPeter Brune nasm->xinit = NULL; 9390298fd71SBarry Smith nasm->eventrestrictinterp = 0; 9400298fd71SBarry Smith nasm->eventsubsolve = 0; 941b20c023fSPeter Brune 942eaedb033SPeter Brune if (!snes->tolerancesset) { 943eaedb033SPeter Brune snes->max_its = 10000; 944eaedb033SPeter Brune snes->max_funcs = 10000; 945eaedb033SPeter Brune } 946eaedb033SPeter Brune 947e0331734SPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMSetType_C",SNESNASMSetType_NASM);CHKERRQ(ierr); 948e0331734SPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMGetType_C",SNESNASMGetType_NASM);CHKERRQ(ierr); 949bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMSetSubdomains_C",SNESNASMSetSubdomains_NASM);CHKERRQ(ierr); 950bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMGetSubdomains_C",SNESNASMGetSubdomains_NASM);CHKERRQ(ierr); 95190bcee39SPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMSetDamping_C",SNESNASMSetDamping_NASM);CHKERRQ(ierr); 95290bcee39SPeter Brune ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMGetDamping_C",SNESNASMGetDamping_NASM);CHKERRQ(ierr); 953bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMGetSubdomainVecs_C",SNESNASMGetSubdomainVecs_NASM);CHKERRQ(ierr); 954bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNASMSetComputeFinalJacobian_C",SNESNASMSetComputeFinalJacobian_NASM);CHKERRQ(ierr); 955eaedb033SPeter Brune PetscFunctionReturn(0); 956eaedb033SPeter Brune } 95799e0435eSBarry Smith 958448b6425SPatrick Farrell /*@ 959448b6425SPatrick Farrell SNESNASMGetSNES - Gets a subsolver 960448b6425SPatrick Farrell 961448b6425SPatrick Farrell Not collective 962448b6425SPatrick Farrell 963448b6425SPatrick Farrell Input Parameters: 964448b6425SPatrick Farrell + snes - the SNES context 965448b6425SPatrick Farrell - i - the number of the subsnes to get 966448b6425SPatrick Farrell 967448b6425SPatrick Farrell Output Parameters: 968448b6425SPatrick Farrell . subsnes - the subsolver context 969448b6425SPatrick Farrell 970448b6425SPatrick Farrell Level: intermediate 971448b6425SPatrick Farrell 972448b6425SPatrick Farrell .keywords: SNES, NASM 973448b6425SPatrick Farrell 974448b6425SPatrick Farrell .seealso: SNESNASM, SNESNASMGetNumber() 975448b6425SPatrick Farrell @*/ 976448b6425SPatrick Farrell PetscErrorCode SNESNASMGetSNES(SNES snes,PetscInt i,SNES *subsnes) 977448b6425SPatrick Farrell { 978448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM*)snes->data; 979448b6425SPatrick Farrell 980448b6425SPatrick Farrell PetscFunctionBegin; 981448b6425SPatrick Farrell if (i < 0 || i >= nasm->n) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"No such subsolver"); 982448b6425SPatrick Farrell *subsnes = nasm->subsnes[i]; 983448b6425SPatrick Farrell PetscFunctionReturn(0); 984448b6425SPatrick Farrell } 985448b6425SPatrick Farrell 986448b6425SPatrick Farrell /*@ 987448b6425SPatrick Farrell SNESNASMGetNumber - Gets number of subsolvers 988448b6425SPatrick Farrell 989448b6425SPatrick Farrell Not collective 990448b6425SPatrick Farrell 991448b6425SPatrick Farrell Input Parameters: 992448b6425SPatrick Farrell . snes - the SNES context 993448b6425SPatrick Farrell 994448b6425SPatrick Farrell Output Parameters: 995448b6425SPatrick Farrell . n - the number of subsolvers 996448b6425SPatrick Farrell 997448b6425SPatrick Farrell Level: intermediate 998448b6425SPatrick Farrell 999448b6425SPatrick Farrell .keywords: SNES, NASM 1000448b6425SPatrick Farrell 1001448b6425SPatrick Farrell .seealso: SNESNASM, SNESNASMGetSNES() 1002448b6425SPatrick Farrell @*/ 1003448b6425SPatrick Farrell PetscErrorCode SNESNASMGetNumber(SNES snes,PetscInt *n) 1004448b6425SPatrick Farrell { 1005448b6425SPatrick Farrell SNES_NASM *nasm = (SNES_NASM*)snes->data; 1006448b6425SPatrick Farrell 1007448b6425SPatrick Farrell PetscFunctionBegin; 1008448b6425SPatrick Farrell *n = nasm->n; 1009448b6425SPatrick Farrell PetscFunctionReturn(0); 1010448b6425SPatrick Farrell } 1011448b6425SPatrick Farrell 1012f10b3e88SPatrick Farrell /*@ 1013f10b3e88SPatrick Farrell SNESNASMSetWeight - Sets weight to use when adding overlapping updates 1014f10b3e88SPatrick Farrell 1015f10b3e88SPatrick Farrell Collective 1016f10b3e88SPatrick Farrell 1017f10b3e88SPatrick Farrell Input Parameters: 1018f10b3e88SPatrick Farrell + snes - the SNES context 1019f10b3e88SPatrick Farrell - weight - the weights to use (typically 1/N for each dof, where N is the number of patches it appears in) 1020f10b3e88SPatrick Farrell 1021f10b3e88SPatrick Farrell Level: intermediate 1022f10b3e88SPatrick Farrell 1023f10b3e88SPatrick Farrell .keywords: SNES, NASM 1024f10b3e88SPatrick Farrell 1025f10b3e88SPatrick Farrell .seealso: SNESNASM 1026f10b3e88SPatrick Farrell @*/ 1027f10b3e88SPatrick Farrell PetscErrorCode SNESNASMSetWeight(SNES snes,Vec weight) 1028f10b3e88SPatrick Farrell { 1029f10b3e88SPatrick Farrell SNES_NASM *nasm = (SNES_NASM*)snes->data; 1030f10b3e88SPatrick Farrell PetscErrorCode ierr; 1031f10b3e88SPatrick Farrell 1032f10b3e88SPatrick Farrell PetscFunctionBegin; 1033f10b3e88SPatrick Farrell 1034f10b3e88SPatrick Farrell ierr = VecDestroy(&nasm->weight);CHKERRQ(ierr); 1035f10b3e88SPatrick Farrell nasm->weight_set = PETSC_TRUE; 1036f10b3e88SPatrick Farrell nasm->weight = weight; 1037f10b3e88SPatrick Farrell ierr = PetscObjectReference((PetscObject)nasm->weight);CHKERRQ(ierr); 1038f10b3e88SPatrick Farrell 1039f10b3e88SPatrick Farrell PetscFunctionReturn(0); 1040f10b3e88SPatrick Farrell } 1041