xref: /petsc/src/snes/impls/composite/snescomposite.c (revision eed5f15bc2a3dc26d54d7c2989531114c489d821)
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