Actual source code: damgsnesad.c
1: #define PETSCSNES_DLL
2:
3: #include petscda.h
4: #include petscmg.h
5: #include petscdmmg.h
6: #include ../src/inline/ilu.h
7: #include ../src/snes/impls/ls/ls.h
10: EXTERN PetscErrorCode NLFRelax_DAAD(NLF,MatSORType,PetscInt,Vec);
11: EXTERN PetscErrorCode NLFRelax_DAAD4(NLF,MatSORType,PetscInt,Vec);
12: EXTERN PetscErrorCode NLFRelax_DAAD9(NLF,MatSORType,PetscInt,Vec);
13: EXTERN PetscErrorCode NLFRelax_DAADb(NLF,MatSORType,PetscInt,Vec);
15: EXTERN PetscErrorCode DMMGFormFunction(SNES,Vec,Vec,void *);
16: EXTERN PetscErrorCode SNESLSCheckLocalMin_Private(Mat,Vec,Vec,PetscReal,PetscTruth*);
20: /*
21: DMMGComputeJacobianWithAdic - Evaluates the Jacobian via Adic when the user has provided
22: a local function evaluation routine.
23: */
24: PetscErrorCode DMMGComputeJacobianWithAdic(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
25: {
26: DMMG dmmg = (DMMG) ptr;
28: Vec localX;
29: DA da = (DA) dmmg->dm;
32: DAGetLocalVector(da,&localX);
33: DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
34: DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
35: DAComputeJacobian1WithAdic(da,localX,*B,dmmg->user);
36: DARestoreLocalVector(da,&localX);
37: /* Assemble true Jacobian; if it is different */
38: if (*J != *B) {
39: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
40: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
41: }
42: MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
43: *flag = SAME_NONZERO_PATTERN;
44: return(0);
45: }
49: /*@
50: SNESDAComputeJacobianWithAdic - This is a universal Jacobian evaluation routine
51: that may be used with SNESSetJacobian() as long as the user context has a DA as
52: its first record and DASetLocalAdicFunction() has been called.
54: Collective on SNES
56: Input Parameters:
57: + snes - the SNES context
58: . X - input vector
59: . J - Jacobian
60: . B - Jacobian used in preconditioner (usally same as J)
61: . flag - indicates if the matrix changed its structure
62: - ptr - optional user-defined context, as set by SNESSetFunction()
64: Level: intermediate
66: .seealso: DASetLocalFunction(), DASetLocalAdicFunction(), SNESSetFunction(), SNESSetJacobian()
68: @*/
69: PetscErrorCode SNESDAComputeJacobianWithAdic(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
70: {
71: DA da = *(DA*) ptr;
73: Vec localX;
76: DAGetLocalVector(da,&localX);
77: DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
78: DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
79: DAComputeJacobian1WithAdic(da,localX,*B,ptr);
80: DARestoreLocalVector(da,&localX);
81: /* Assemble true Jacobian; if it is different */
82: if (*J != *B) {
83: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
84: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
85: }
86: MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
87: *flag = SAME_NONZERO_PATTERN;
88: return(0);
89: }
91: #include ../src/ksp/pc/impls/mg/mgimpl.h
92: /*
93: This is pre-beta FAS code. It's design should not be taken seriously!
95: R is the usual multigrid restriction (e.g. the tranpose of piecewise linear interpolation)
96: Q is either a scaled injection or the usual R
97: */
100: PetscErrorCode DMMGSolveFAS(DMMG *dmmg,PetscInt level)
101: {
103: PetscInt i,j,k;
104: PetscReal norm;
105: PC_MG **mg;
106: PC pc;
109: VecSet(dmmg[level]->r,0.0);
110: for (j=1; j<=level; j++) {
111: if (!dmmg[j]->inject) {
112: DMGetInjection(dmmg[j-1]->dm,dmmg[j]->dm,&dmmg[j]->inject);
113: }
114: }
116: KSPGetPC(dmmg[level]->ksp,&pc);
117: mg = ((PC_MG**)pc->data);
119: for(i = 0; i < 100; i++) {
121: for(j = level; j > 0; j--) {
123: /* Relax residual_fine --> F(x_fine) = 0 */
124: for(k = 0; k < dmmg[j]->presmooth; k++) {
125: NLFRelax_DAAD(dmmg[j]->nlf, SOR_SYMMETRIC_SWEEP, 1, dmmg[j]->x);
126: }
128: /* R*(residual_fine - F(x_fine)) */
129: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
130: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
132: if (j == level || dmmg[j]->monitorall) {
133: /* norm( residual_fine - f(x_fine) ) */
134: VecNorm(dmmg[j]->w,NORM_2,&norm);
135: if (j == level) {
136: if (norm < dmmg[level]->abstol) goto theend;
137: if (i == 0) {
138: dmmg[level]->rrtol = norm*dmmg[level]->rtol;
139: } else {
140: if (norm < dmmg[level]->rrtol) goto theend;
141: }
142: }
143: if (dmmg[j]->monitorall) {
144: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
145: PetscPrintf(dmmg[j]->comm,"FAS function norm %G\n",norm);
146: }
147: }
149: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
150:
151: /* F(Q*x_fine) */
152: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
153: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
154: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
156: /* residual_coarse = F(Q*x_fine) + R*(residual_fine - F(x_fine)) */
157: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
159: /* save Q*x_fine into b (needed when interpolating compute x back up */
160: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
161: }
163: for (j=0; j<dmmg[0]->coarsesmooth; j++) {
164: NLFRelax_DAAD(dmmg[0]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[0]->x);
165: }
166: if (dmmg[0]->monitorall){
167: DMMGFormFunction(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
168: VecAXPY(dmmg[0]->w,-1.0,dmmg[0]->r);
169: VecNorm(dmmg[0]->w,NORM_2,&norm);
170: for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm," ");}
171: PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %G\n",norm);
172: }
174: for (j=1; j<=level; j++) {
175: /* x_fine = x_fine + R'*(x_coarse - Q*x_fine) */
176: VecAXPY(dmmg[j-1]->x,-1.0,dmmg[j-1]->b);
177: MatInterpolateAdd(mg[j]->interpolate,dmmg[j-1]->x,dmmg[j]->x,dmmg[j]->x);
179: if (dmmg[j]->monitorall) {
180: /* norm( F(x_fine) - residual_fine ) */
181: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
182: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
183: VecNorm(dmmg[j]->w,NORM_2,&norm);
184: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
185: PetscPrintf(dmmg[j]->comm,"FAS function norm %G\n",norm);
186: }
188: /* Relax residual_fine - F(x_fine) = 0 */
189: for (k=0; k<dmmg[j]->postsmooth; k++) {
190: NLFRelax_DAAD(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
191: }
193: if (dmmg[j]->monitorall) {
194: /* norm( F(x_fine) - residual_fine ) */
195: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
196: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
197: VecNorm(dmmg[j]->w,NORM_2,&norm);
198: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
199: PetscPrintf(dmmg[j]->comm,"FAS function norm %G\n",norm);
200: }
201: }
203: if (dmmg[level]->monitor){
204: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
205: VecNorm(dmmg[level]->w,NORM_2,&norm);
206: PetscPrintf(dmmg[level]->comm,"%D FAS function norm %G\n",i+1,norm);
207: }
208: }
209: theend:
210: return(0);
211: }
213: /*
214: This is the point-block version of FAS
215: */
218: PetscErrorCode DMMGSolveFASb(DMMG *dmmg,PetscInt level)
219: {
221: PetscInt i,j,k;
222: PetscReal norm;
223: PC_MG **mg;
224: PC pc;
227: VecSet(dmmg[level]->r,0.0);
228: for (j=1; j<=level; j++) {
229: if (!dmmg[j]->inject) {
230: DMGetInjection(dmmg[j-1]->dm,dmmg[j]->dm,&dmmg[j]->inject);
231: }
232: }
234: KSPGetPC(dmmg[level]->ksp,&pc);
235: mg = ((PC_MG**)pc->data);
237: for (i=0; i<100; i++) {
239: for (j=level; j>0; j--) {
241: /* Relax residual_fine - F(x_fine) = 0 */
242: for (k=0; k<dmmg[j]->presmooth; k++) {
243: NLFRelax_DAADb(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
244: }
246: /* R*(residual_fine - F(x_fine)) */
247: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
248: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
250: if (j == level || dmmg[j]->monitorall) {
251: /* norm( residual_fine - f(x_fine) ) */
252: VecNorm(dmmg[j]->w,NORM_2,&norm);
253: if (j == level) {
254: if (norm < dmmg[level]->abstol) goto theend;
255: if (i == 0) {
256: dmmg[level]->rrtol = norm*dmmg[level]->rtol;
257: } else {
258: if (norm < dmmg[level]->rrtol) goto theend;
259: }
260: }
261: }
263: if (dmmg[j]->monitorall) {
264: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
265: PetscPrintf(dmmg[j]->comm,"FAS function norm %G\n",norm);
266: }
267: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
268:
269: /* F(Q*x_fine) */
270: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
271: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
272: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
274: /* residual_coarse = F(Q*x_fine) + R*(residual_fine - F(x_fine)) */
275: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
277: /* save Q*x_fine into b (needed when interpolating compute x back up */
278: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
279: }
281: for (j=0; j<dmmg[0]->coarsesmooth; j++) {
282: NLFRelax_DAADb(dmmg[0]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[0]->x);
283: }
284: if (dmmg[0]->monitorall){
285: DMMGFormFunction(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
286: VecAXPY(dmmg[0]->w,-1.0,dmmg[0]->r);
287: VecNorm(dmmg[0]->w,NORM_2,&norm);
288: for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm," ");}
289: PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %G\n",norm);
290: }
292: for (j=1; j<=level; j++) {
293: /* x_fine = x_fine + R'*(x_coarse - Q*x_fine) */
294: VecAXPY(dmmg[j-1]->x,-1.0,dmmg[j-1]->b);
295: MatInterpolateAdd(mg[j]->interpolate,dmmg[j-1]->x,dmmg[j]->x,dmmg[j]->x);
297: if (dmmg[j]->monitorall) {
298: /* norm( F(x_fine) - residual_fine ) */
299: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
300: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
301: VecNorm(dmmg[j]->w,NORM_2,&norm);
302: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
303: PetscPrintf(dmmg[j]->comm,"FAS function norm %G\n",norm);
304: }
306: /* Relax residual_fine - F(x_fine) = 0 */
307: for (k=0; k<dmmg[j]->postsmooth; k++) {
308: NLFRelax_DAADb(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
309: }
311: if (dmmg[j]->monitorall) {
312: /* norm( F(x_fine) - residual_fine ) */
313: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
314: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
315: VecNorm(dmmg[j]->w,NORM_2,&norm);
316: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
317: PetscPrintf(dmmg[j]->comm,"FAS function norm %G\n",norm);
318: }
319: }
321: if (dmmg[level]->monitor){
322: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
323: VecNorm(dmmg[level]->w,NORM_2,&norm);
324: PetscPrintf(dmmg[level]->comm,"%D FAS function norm %G\n",i+1,norm);
325: }
326: }
327: theend:
328: return(0);
329: }
332: #include "adic/ad_utils.h"
337: PetscErrorCode PetscADView(PetscInt N,PetscInt nc,double *ptr,PetscViewer viewer)
338: {
339: PetscInt i,j,nlen = PetscADGetDerivTypeSize();
340: char *cptr = (char*)ptr;
341: double *values;
345: for (i=0; i<N; i++) {
346: PetscPrintf(PETSC_COMM_SELF,"Element %D value %G derivatives: ",i,*(double*)cptr);
347: values = PetscADGetGradArray(cptr);
348: for (j=0; j<nc; j++) {
349: PetscPrintf(PETSC_COMM_SELF,"%G ",*values++);
350: }
351: PetscPrintf(PETSC_COMM_SELF,"\n");
352: cptr += nlen;
353: }
355: return(0);
356: }
360: PetscErrorCode DMMGSolveFAS4(DMMG *dmmg,PetscInt level)
361: {
363: PetscInt i,j,k;
364: PetscReal norm;
365: PetscScalar zero = 0.0,mone = -1.0,one = 1.0;
366: PC_MG **mg;
367: PC pc;
370: VecSet(dmmg[level]->r,zero);
371: for (j=1; j<=level; j++) {
372: if (!dmmg[j]->inject) {
373: DMGetInjection(dmmg[j-1]->dm,dmmg[j]->dm,&dmmg[j]->inject);
374: }
375: }
377: KSPGetPC(dmmg[level]->ksp,&pc);
378: mg = ((PC_MG**)pc->data);
379: for (i=0; i<100; i++) {
381: for (j=level; j>0; j--) {
382: PetscPrintf(PETSC_COMM_WORLD,"I am here");
383: /* Relax residual_fine - F(x_fine) = 0 */
384: for (k=0; k<dmmg[j]->presmooth; k++) {
385: NLFRelax_DAAD4(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
386: }
388: /* R*(residual_fine - F(x_fine)) */
389: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
390: VecAYPX(dmmg[j]->w,mone,dmmg[j]->r);
392: if (j == level || dmmg[j]->monitorall) {
393: /* norm( residual_fine - f(x_fine) ) */
394: VecNorm(dmmg[j]->w,NORM_2,&norm);
395: if (j == level) {
396: if (norm < dmmg[level]->abstol) goto theend;
397: if (i == 0) {
398: dmmg[level]->rrtol = norm*dmmg[level]->rtol;
399: } else {
400: if (norm < dmmg[level]->rrtol) goto theend;
401: }
402: }
403: } PetscPrintf(PETSC_COMM_WORLD,"I am here");
405: if (dmmg[j]->monitorall) {
406: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
407: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
408: }
409: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
410:
411: /* F(R*x_fine) */
412: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
413: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
414: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
416: /* residual_coarse = F(R*x_fine) + R*(residual_fine - F(x_fine)) */
417: VecAYPX(dmmg[j-1]->r,one,dmmg[j-1]->w);
419: /* save R*x_fine into b (needed when interpolating compute x back up */
420: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
421: }
423: for (j=0; j<dmmg[0]->presmooth; j++) {
424: NLFRelax_DAAD4(dmmg[0]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[0]->x);
425: }
426: if (dmmg[0]->monitorall){
427: DMMGFormFunction(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
428: VecAXPY(dmmg[0]->w,mone,dmmg[0]->r);
429: VecNorm(dmmg[0]->w,NORM_2,&norm);
430: for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm," ");}
431: PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %g\n",norm);
432: }
434: for (j=1; j<=level; j++) {
435: /* x_fine = x_fine + R'*(x_coarse - R*x_fine) */
436: VecAXPY(dmmg[j-1]->x,mone,dmmg[j-1]->b);
437: MatInterpolateAdd(mg[j]->interpolate,dmmg[j-1]->x,dmmg[j]->x,dmmg[j]->x);
439: if (dmmg[j]->monitorall) {
440: /* norm( F(x_fine) - residual_fine ) */
441: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
442: VecAXPY(dmmg[j]->w,mone,dmmg[j]->r);
443: VecNorm(dmmg[j]->w,NORM_2,&norm);
444: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
445: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
446: }
448: /* Relax residual_fine - F(x_fine) = 0 */
449: for (k=0; k<dmmg[j]->postsmooth; k++) {
450: NLFRelax_DAAD4(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
451: }
453: if (dmmg[j]->monitorall) {
454: /* norm( F(x_fine) - residual_fine ) */
455: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
456: VecAXPY(dmmg[j]->w,mone,dmmg[j]->r);
457: VecNorm(dmmg[j]->w,NORM_2,&norm);
458: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
459: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
460: }
461: }
463: if (dmmg[level]->monitor){
464: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
465: VecNorm(dmmg[level]->w,NORM_2,&norm);
466: PetscPrintf(dmmg[level]->comm,"%D FAS function norm %g\n",i,norm);
467: }
468: }
469: theend:
470: return(0);
471: }
473: /*
474: This function provide several FAS v_cycle iteration
476: iter: the number of FAS it run
478: */
481: PetscErrorCode DMMGSolveFASn(DMMG *dmmg,PetscInt level,PetscInt iter)
482: {
484: PetscInt i,j,k;
485: PetscReal norm;
486: PC_MG **mg;
487: PC pc;
490: VecSet(dmmg[level]->r,0.0);
491: for (j=1; j<=level; j++) {
492: if (!dmmg[j]->inject) {
493: DMGetInjection(dmmg[j-1]->dm,dmmg[j]->dm,&dmmg[j]->inject);
494: }
495: }
497: KSPGetPC(dmmg[level]->ksp,&pc);
498: mg = ((PC_MG**)pc->data);
500: for (i=0; i<iter; i++) {
502: for (j=level; j>0; j--) {
504: /* Relax residual_fine - F(x_fine) = 0 */
505: for (k=0; k<dmmg[j]->presmooth; k++) {
506: NLFRelax_DAAD(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
507: }
509: /* R*(residual_fine - F(x_fine)) */
510: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
511: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
513: if (j == level || dmmg[j]->monitorall) {
514: /* norm( residual_fine - f(x_fine) ) */
515: VecNorm(dmmg[j]->w,NORM_2,&norm);
516: if (j == level) {
517: if (norm < dmmg[level]->abstol) goto theend;
518: if (i == 0) {
519: dmmg[level]->rrtol = norm*dmmg[level]->rtol;
520: } else {
521: if (norm < dmmg[level]->rrtol) goto theend;
522: }
523: }
524: }
526: if (dmmg[j]->monitorall) {
527: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
528: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
529: }
530: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
531:
532: /* F(RI*x_fine) */
533: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
534: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
535: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
537: /* residual_coarse = F(RI*x_fine) + R*(residual_fine - F(x_fine)) */
538: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
540: /* save RI*x_fine into b (needed when interpolating compute x back up */
541: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
542: }
544: for (j=0; j<dmmg[0]->coarsesmooth; j++) {
545: NLFRelax_DAAD(dmmg[0]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[0]->x);
546: }
547: if (dmmg[0]->monitorall){
548: DMMGFormFunction(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
549: VecAXPY(dmmg[0]->w,-1.0,dmmg[0]->r);
550: VecNorm(dmmg[0]->w,NORM_2,&norm);
551: for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm," ");}
552: PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %g\n",norm);
553: }
555: for (j=1; j<=level; j++) {
556: /* x_fine = x_fine + R'*(x_coarse - RI*x_fine) */
557: VecAXPY(dmmg[j-1]->x,-1.0,dmmg[j-1]->b);
558: MatInterpolateAdd(mg[j]->interpolate,dmmg[j-1]->x,dmmg[j]->x,dmmg[j]->x);
560: if (dmmg[j]->monitorall) {
561: /* norm( F(x_fine) - residual_fine ) */
562: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
563: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
564: VecNorm(dmmg[j]->w,NORM_2,&norm);
565: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
566: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
567: }
569: /* Relax residual_fine - F(x_fine) = 0 */
570: for (k=0; k<dmmg[j]->postsmooth; k++) {
571: NLFRelax_DAAD(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
572: }
574: if (dmmg[j]->monitorall) {
575: /* norm( F(x_fine) - residual_fine ) */
576: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
577: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
578: VecNorm(dmmg[j]->w,NORM_2,&norm);
579: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
580: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
581: }
582: }
584: if (dmmg[level]->monitor){
585: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
586: VecNorm(dmmg[level]->w,NORM_2,&norm);
587: PetscPrintf(dmmg[level]->comm,"%D FAS function norm %g\n",i+1,norm);
588: }
589: }
590: theend:
591: return(0);
592: }
593: /*
594: This is a simple FAS setup function
595: */
600: PetscErrorCode DMMGSolveFASSetUp(DMMG *dmmg,PetscInt level)
601: {
603: PetscInt j;//,nlevels=dmmg[0]->nlevels-1;
604: //PC pc;
607: VecSet(dmmg[level]->r,0.0);
608: for (j=1; j<=level; j++) {
609: if (!dmmg[j]->inject) {
610: DMGetInjection(dmmg[j-1]->dm,dmmg[j]->dm,&dmmg[j]->inject);
611: }
612: }
613: VecSet(dmmg[level]->r,0.0);
614: dmmg[level]->rrtol = 0.0001*dmmg[level]->rtol;//I want to get more precise solution with FAS
615: return(0);
616: }
619: /*
620: This is function to implement multiplicative FAS
623: Options:
624:
625: -dmmg_fas_cycles 1 : FAS v-cycle
626: 2 : FAS w-cycle
629: */
633: PetscErrorCode DMMGSolveFASMCycle(DMMG *dmmg,PetscInt level,PetscTruth* converged)
634: {
636: PetscInt j,k,cycles=1,nlevels=level;//nlevels=dmmg[0]->nlevels-1;
637: // I need to put nlevels=level in order to get grid sequence correctly
638: PetscReal norm;
639: PC_MG **mg;
640: PC pc;
641:
643:
645: PetscOptionsGetInt(PETSC_NULL,"-dmmg_fas_cycles",&cycles,PETSC_NULL);
646:
647: KSPGetPC(dmmg[level]->ksp,&pc);
648: mg = ((PC_MG**)pc->data);
650: j=level;
652: if(j) {/* not the coarsest level */
653: /* Relax residual_fine - F(x_fine) = 0 */
654: for (k=0; k<dmmg[j]->presmooth; k++) {
655: NLFRelax_DAAD(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
656: }
657:
658:
660: /* R*(residual_fine - F(x_fine)) */
661: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
662: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
664: if (j == nlevels || dmmg[j]->monitorall) {
665: /* norm( residual_fine - f(x_fine) ) */
666: VecNorm(dmmg[j]->w,NORM_2,&norm);
667:
668: if (j == nlevels) {
669: if (norm < dmmg[level]->abstol) {
670: *converged = PETSC_TRUE;
671: goto theend;
672: }
674: if (norm < dmmg[level]->rrtol){
675: *converged = PETSC_TRUE;
676: goto theend;
677:
678: }
679: }
680: }
682: if (dmmg[j]->monitorall) {
683: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
684: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
685: }
686: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
687:
688: /* F(RI*x_fine) */
689: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
690: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
691: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
693: /* residual_coarse = F(RI*x_fine) + R*(residual_fine - F(x_fine)) */
694: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
696: /* save RI*x_fine into b (needed when interpolating compute x back up */
697: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
698:
699:
700: while (cycles--) {
701: DMMGSolveFASMCycle(dmmg,level-1,converged);
702: }
703: }
704: else { /* for the coarsest level */
705: for (k=0; k<dmmg[0]->coarsesmooth; k++) {
706: NLFRelax_DAAD(dmmg[0]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[0]->x);
707: }
708: if (dmmg[0]->monitorall){
709: DMMGFormFunction(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
710: VecAXPY(dmmg[0]->w,-1.0,dmmg[0]->r);
711: VecNorm(dmmg[0]->w,NORM_2,&norm);
712: for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm," ");}
713: PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %g\n",norm);
714: }
715: if (j == nlevels || dmmg[j]->monitorall) {
716: /* norm( residual_fine - f(x_fine) ) */
717: VecNorm(dmmg[j]->w,NORM_2,&norm);
718:
719: if (j == nlevels) {
720: if (norm < dmmg[level]->abstol) {
721: *converged = PETSC_TRUE;
722: goto theend;
723: }
724:
725: if (norm < dmmg[level]->rrtol){
726: *converged = PETSC_TRUE;
727: goto theend;
728:
729: }
730: }
731: }
733:
734: }
735: j=level;
736: if(j) { /* not for the coarsest level */
737: /* x_fine = x_fine + R'*(x_coarse - RI*x_fine) */
738: VecAXPY(dmmg[j-1]->x,-1.0,dmmg[j-1]->b);
739: MatInterpolateAdd(mg[j]->interpolate,dmmg[j-1]->x,dmmg[j]->x,dmmg[j]->x);
741: if (dmmg[j]->monitorall) {
742: /* norm( F(x_fine) - residual_fine ) */
743: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
744: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
745: VecNorm(dmmg[j]->w,NORM_2,&norm);
746: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
747: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
748: }
750: /* Relax residual_fine - F(x_fine) = 0 */
751: for (k=0; k<dmmg[j]->postsmooth; k++) {
752: NLFRelax_DAAD(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
753: }
755: if (dmmg[j]->monitorall) {
756: /* norm( F(x_fine) - residual_fine ) */
757: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
758: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
759: VecNorm(dmmg[j]->w,NORM_2,&norm);
760: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
761: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
762: }
763:
764:
765: }
766: theend:
767: return(0);
768: }
770: /*
771: This is function to implement multiplicative FAS with block smoother
774: Options:
775:
776: -dmmg_fas_cycles 1 : FAS v-cycle
777: 2 : FAS w-cycle
780: */
785: PetscErrorCode DMMGSolveFASMCycle9(DMMG *dmmg,PetscInt level,PetscTruth* converged)
786: {
788: PetscInt j,k,cycles=1,nlevels=level;//nlevels=dmmg[0]->nlevels-1;
789: // I need to put nlevels=level in order to get grid sequence correctly
790: PetscReal norm;
791: PC_MG **mg;
792: PC pc;
793:
795:
796:
797: PetscOptionsGetInt(PETSC_NULL,"-dmmg_fas_cycles",&cycles,PETSC_NULL);
798:
799: KSPGetPC(dmmg[level]->ksp,&pc);
800: mg = ((PC_MG**)pc->data);
801: // for (j=level; j>0; j--) {
802: j=level;
803: //PetscPrintf(dmmg[level]->comm,"j=%d,nlevels=%d",j,nlevels);
804: if(j) {/* not the coarsest level */
805: /* Relax residual_fine - F(x_fine) = 0 */
806: for (k=0; k<dmmg[j]->presmooth; k++) {
807: NLFRelax_DAAD9(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
808: }
809:
810:
812: /* R*(residual_fine - F(x_fine)) */
813: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
814: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
816: if (j == nlevels || dmmg[j]->monitorall) {
817: /* norm( residual_fine - f(x_fine) ) */
818: VecNorm(dmmg[j]->w,NORM_2,&norm);
819:
820: if (j == nlevels) {
821: if (norm < dmmg[level]->abstol) {
822: *converged = PETSC_TRUE;
823: goto theend;
824: }
825: /* if (i == 0) {
826: dmmg[level]->rrtol = norm*dmmg[level]->rtol;
827: } else {*/
828: if (norm < dmmg[level]->rrtol){
829: *converged = PETSC_TRUE;
830: goto theend;
831:
832: }
833: }
834: }
836: if (dmmg[j]->monitorall) {
837: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
838: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
839: }
840: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
841:
842: /* F(RI*x_fine) */
843: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
844: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
845: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
847: /* residual_coarse = F(RI*x_fine) + R*(residual_fine - F(x_fine)) */
848: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
850: /* save RI*x_fine into b (needed when interpolating compute x back up */
851: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
852:
853:
854: while (cycles--) {
855: DMMGSolveFASMCycle9(dmmg,level-1,converged);
856: }
857: }
858: else { /* for the coarsest level */
859: for (k=0; k<dmmg[0]->coarsesmooth; k++) {
860: NLFRelax_DAAD9(dmmg[0]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[0]->x);
861: }
862: if (dmmg[0]->monitorall){
863: DMMGFormFunction(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
864: VecAXPY(dmmg[0]->w,-1.0,dmmg[0]->r);
865: VecNorm(dmmg[0]->w,NORM_2,&norm);
866: for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm," ");}
867: PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %g\n",norm);
868: }
869: if (j == nlevels || dmmg[j]->monitorall) {
870: /* norm( residual_fine - f(x_fine) ) */
871: VecNorm(dmmg[j]->w,NORM_2,&norm);
872:
873: if (j == nlevels) {
874: if (norm < dmmg[level]->abstol) {
875: *converged = PETSC_TRUE;
876: goto theend;
877: }
878: /* if (i == 0) {
879: dmmg[level]->rrtol = norm*dmmg[level]->rtol;
880: } else {*/
881: if (norm < dmmg[level]->rrtol){
882: *converged = PETSC_TRUE;
883: goto theend;
884:
885: }
886: }
887: }
889:
890: }
891: j=level;
892: if(j) { /* not for the coarsest level */
893: /* x_fine = x_fine + R'*(x_coarse - RI*x_fine) */
894: VecAXPY(dmmg[j-1]->x,-1.0,dmmg[j-1]->b);
895: MatInterpolateAdd(mg[j]->interpolate,dmmg[j-1]->x,dmmg[j]->x,dmmg[j]->x);
897: if (dmmg[j]->monitorall) {
898: /* norm( F(x_fine) - residual_fine ) */
899: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
900: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
901: VecNorm(dmmg[j]->w,NORM_2,&norm);
902: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
903: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
904: }
906: /* Relax residual_fine - F(x_fine) = 0 */
907: for (k=0; k<dmmg[j]->postsmooth; k++) {
908: NLFRelax_DAAD9(dmmg[j]->nlf,SOR_SYMMETRIC_SWEEP,1,dmmg[j]->x);
909: }
911: if (dmmg[j]->monitorall) {
912: /* norm( F(x_fine) - residual_fine ) */
913: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
914: VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
915: VecNorm(dmmg[j]->w,NORM_2,&norm);
916: for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm," ");}
917: PetscPrintf(dmmg[j]->comm,"FAS function norm %g\n",norm);
918: }
919:
920: /* if(j==nlevels){
921: if (dmmg[level]->monitor){
922: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
923: VecNorm(dmmg[level]->w,NORM_2,&norm);
924:
925: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
926:
927: }
928: }*/
929: }
930: theend:
931: return(0);
932: }
934: /*
935: This is function to implement full FAS with block smoother(9 points together)
938: Options:
939:
940: -dmmg_fas_cycles 1 : FAS v-cycle
941: 2 : FAS w-cycle
944: */
949: PetscErrorCode DMMGSolveFASFCycle(DMMG *dmmg,PetscInt l,PetscTruth* converged)
950: {
952: PetscInt j;//l = dmmg[0]->nlevels-1;
953: PC_MG **mg;
954: PC pc;
957: KSPGetPC(dmmg[l]->ksp,&pc);
958: mg = ((PC_MG**)pc->data);
959: // restriction all the way down to the coarse level
960: if(l>0) {
961: for(j=l;j>0;j--) {
962:
963: /* R*(residual_fine - F(x_fine)) */
964: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
965: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
967: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
968:
969: /* F(RI*x_fine) */
970: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
971: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
972: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
974: /* residual_coarse = F(RI*x_fine) + R*(residual_fine - F(x_fine)) */
975: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
977: /* save RI*x_fine into b (needed when interpolating compute x back up */
978: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
980: }
982: // all the way up to the finest level
983: for (j=0; j<l; j++) {
984: DMMGSolveFASMCycle(dmmg,j,PETSC_NULL);
985: /* x_fine = x_fine + R'*(x_coarse - RI*x_fine) */
986: VecAXPY(dmmg[j]->x,-1.0,dmmg[j]->b);
987: MatInterpolateAdd(mg[j+1]->interpolate,dmmg[j]->x,dmmg[j+1]->x,dmmg[j+1]->x);
989: }
990: }
991: DMMGSolveFASMCycle(dmmg,l,converged);
992: return(0);
993: }
997: /*
998: This is function to implement full FAS with block smoother ( 9 points together)
1001: Options:
1002:
1003: -dmmg_fas_cycles 1 : FAS v-cycle
1004: 2 : FAS w-cycle
1007: */
1010: PetscErrorCode DMMGSolveFASFCycle9(DMMG *dmmg,PetscInt l,PetscTruth* converged)
1011: {
1013: PetscInt j;//l = dmmg[0]->nlevels-1;
1014: PC_MG **mg;
1015: PC pc;
1018: KSPGetPC(dmmg[l]->ksp,&pc);
1019: mg = ((PC_MG**)pc->data);
1020: // restriction all the way down to the coarse level
1021: if(l>0) {
1022: for(j=l;j>0;j--) {
1023:
1024: /* R*(residual_fine - F(x_fine)) */
1025: DMMGFormFunction(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
1026: VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
1028: MatRestrict(mg[j]->restrct,dmmg[j]->w,dmmg[j-1]->r);
1029:
1030: /* F(RI*x_fine) */
1031: VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
1032: VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD);
1033: DMMGFormFunction(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);
1035: /* residual_coarse = F(RI*x_fine) + R*(residual_fine - F(x_fine)) */
1036: VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);
1038: /* save RI*x_fine into b (needed when interpolating compute x back up */
1039: VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
1041: }
1043: // all the way up to the finest level
1044: for (j=0; j<l; j++) {
1045: DMMGSolveFASMCycle9(dmmg,j,PETSC_NULL);
1046: /* x_fine = x_fine + R'*(x_coarse - RI*x_fine) */
1047: VecAXPY(dmmg[j]->x,-1.0,dmmg[j]->b);
1048: MatInterpolateAdd(mg[j+1]->interpolate,dmmg[j]->x,dmmg[j+1]->x,dmmg[j+1]->x);
1050: }
1051: }
1052: DMMGSolveFASMCycle9(dmmg,l,converged);
1053: return(0);
1054: }
1056: /*
1057: This is function is to solve nonlinear system with FAS
1059: Options:
1061: -dmmg_fas_9: using block smoother
1062:
1063: -dmmg_fas_full: using full FAS
1066: */
1069: PetscErrorCode DMMGSolveFASCycle(DMMG *dmmg,PetscInt level)
1070: {
1072: PetscInt i;
1073: PetscTruth converged = PETSC_FALSE, flg,flgb;
1074: PetscReal norm;
1077: DMMGSolveFASSetUp(dmmg,level);
1078: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_9",&flgb);
1079:
1080: if(flgb){
1082: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_full",&flg);
1083: if (flg) {
1084: for(i=0;i<1000;i++){
1085: PetscPrintf(dmmg[level]->comm,"%D ",i+1);
1086: DMMGSolveFASFCycle9(dmmg,level,&converged);
1087: if (dmmg[level]->monitor){
1088: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1089: VecNorm(dmmg[level]->w,NORM_2,&norm);
1090: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1091: }
1092: if (converged) return(0);
1093: }
1094: }
1095: else{
1096: for(i=0;i<1000;i++){
1097: PetscPrintf(dmmg[level]->comm,"%D ",i+1);
1098: DMMGSolveFASMCycle9(dmmg,level,&converged);
1099: if (dmmg[level]->monitor){
1100: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1101: VecNorm(dmmg[level]->w,NORM_2,&norm);
1102: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1103: }
1105: if (converged) return(0);
1106: }
1107: }
1108: }
1109: else {
1110: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_full",&flg);
1111: if (flg) {
1112: for(i=0;i<1000;i++){
1113: PetscPrintf(dmmg[level]->comm,"%D ",i+1);
1114: DMMGSolveFASFCycle(dmmg,level,&converged);
1115: if (dmmg[level]->monitor){
1116: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1117: VecNorm(dmmg[level]->w,NORM_2,&norm);
1118: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1119: }
1120: if (converged) return(0);
1121: }
1122: }
1123: else{
1124: for(i=0;i<1000;i++){
1125: PetscPrintf(dmmg[level]->comm,"%D ",i+1);
1126: DMMGSolveFASMCycle(dmmg,level,&converged);
1127: if (dmmg[level]->monitor){
1128: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1129: VecNorm(dmmg[level]->w,NORM_2,&norm);
1130: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1131: }
1133: if (converged) return(0);
1134: }
1136: }
1137: }
1138: return(0);
1139: }
1141: /*
1142: This is function is to implement one FAS iteration
1144: Options:
1146: -dmmg_fas_9: using block smoother
1147:
1148: -dmmg_fas_full: using full FAS
1150: */
1153: PetscErrorCode DMMGSolveFASCyclen(DMMG *dmmg,PetscInt level)
1154: {
1156: PetscTruth converged = PETSC_FALSE, flg,flgb;
1157: PetscReal norm;
1158: // PC_MG **mg;
1159: //PC pc;
1162: DMMGSolveFASSetUp(dmmg,level);
1163: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_9",&flgb);
1164:
1165: if(flgb){
1167: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_full",&flg);
1168: if (flg) {
1169:
1170: DMMGSolveFASFCycle9(dmmg,level,&converged);
1171: if (dmmg[level]->monitor){
1172: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1173: VecNorm(dmmg[level]->w,NORM_2,&norm);
1174: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1175: }
1177: }
1178: else{
1179:
1180: DMMGSolveFASMCycle9(dmmg,level,&converged);
1181: if (dmmg[level]->monitor){
1182: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1183: VecNorm(dmmg[level]->w,NORM_2,&norm);
1184: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1185: }
1188: }
1189: }
1190: else {
1191: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_full",&flg);
1192: if (flg) {
1193:
1194: DMMGSolveFASFCycle(dmmg,level,&converged);
1195: if (dmmg[level]->monitor){
1196: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1197: VecNorm(dmmg[level]->w,NORM_2,&norm);
1198: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1199: }
1201: }
1202: else{
1203:
1204: DMMGSolveFASMCycle(dmmg,level,&converged);
1205: if (dmmg[level]->monitor){
1206: DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1207: VecNorm(dmmg[level]->w,NORM_2,&norm);
1208: PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1209: }
1213: }
1214: }
1215:
1217: return(0);
1218: }
1221: /*
1223: This is function to implement Nonlinear CG to accelerate FAS
1225: In order to use this acceleration, the option is
1227: -dmmg_fas_NCG
1231: */
1236: PetscErrorCode DMMGSolveFAS_NCG(DMMG *dmmg, PetscInt level)
1237: {
1238: SNES snes = dmmg[level]->snes;
1239: SNES_LS *neP = (SNES_LS*)snes->data;
1241: PetscInt maxits,i,lits;
1242: PetscTruth lssucceed;
1243: // MatStructure flg = DIFFERENT_NONZERO_PATTERN;
1244: PetscReal fnorm,gnorm,xnorm,ynorm,betaFR,betaPR,beta,betaHS,betaDY;
1245: Vec Y,X,F,G,W,Gradold,Sk;
1246: //KSP ksp;
1250: VecDuplicate(dmmg[level]->x,&Sk);
1251: PetscObjectReference((PetscObject)dmmg[level]->x);
1252: if (snes->vec_sol) { VecDestroy(snes->vec_sol); }
1253: snes->vec_sol = dmmg[level]->x;
1254: if (!snes->setupcalled) { SNESSetUp(snes); }
1255: if (snes->conv_hist_reset) snes->conv_hist_len = 0;
1256: PetscLogEventBegin(SNES_Solve,snes,0,0,0);
1257: snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;
1260: snes->reason = SNES_CONVERGED_ITERATING;
1262: maxits = snes->max_its; /* maximum number of iterations */
1263: X = snes->vec_sol; /* solution vector */
1264: F = snes->vec_func; /* residual vector */
1265: Y = snes->work[0]; /* work vectors */
1266: G = snes->work[1];
1267: W = snes->work[2];
1269: PetscObjectTakeAccess(snes);
1270: snes->iter = 0;
1271: PetscObjectGrantAccess(snes);
1272:
1273: X = dmmg[level]->x;
1274: VecCopy(X,Y);
1275: VecCopy(X,G);
1277: // to get the residual for the F
1278: SNESComputeFunction(snes,X,F);
1279:
1280: VecNorm(F,NORM_2,&fnorm); /* fnorm <- ||F|| */
1281: if (fnorm != fnorm) SETERRQ(PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1282: PetscObjectTakeAccess(snes);
1283: snes->norm = fnorm;
1284: PetscObjectGrantAccess(snes);
1285: SNESLogConvHistory(snes,fnorm,0);
1286: SNESMonitor(snes,0,fnorm);
1288: if (fnorm < snes->abstol) {snes->reason = SNES_CONVERGED_FNORM_ABS; return(0);}
1290: /* set parameter for default relative tolerance convergence test */
1291: snes->ttol = fnorm*snes->rtol;
1292: // dmmg[level]->rrtol= snes->ttol;
1294: // set this to store the old grad
1295: Gradold=snes->vec_sol_update;
1296:
1297: // compute the search direction Y
1298: // I need to put Q(x)=x-FAS(x) here
1299: DMMGSolveFASCyclen(dmmg,level);
1300: // F = X - dmmg[level]->x; this is the gradient direction
1301: VecAXPY(Y,-1.0,X);
1302: // copy the gradient to the old
1303: VecCopy(Y,Gradold);
1304: // copy X back
1305: VecCopy(G,X);
1306: VecWAXPY(Sk,-1.0,X,X);
1307: // so far I put X=X_c, F= F(x_c), Gradold= Y=grad(x_c)
1309: // for (i=0; i<maxits; i++) {
1311: for (i=0; i<10000; i++) {
1314: PetscPrintf(PETSC_COMM_WORLD,"iter=%d",i+1);
1315:
1316:
1317: // X=x_c, F=F(x_c),Y search direction; G=F(x_new), W=x_new,
1318: VecNorm(X,NORM_2,&xnorm);
1319: (*neP->LineSearch)(snes,neP->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);
1320: PetscInfo4(snes,"SNESSolve_LS: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);
1321: if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
1322: PetscPrintf(PETSC_COMM_WORLD,"step=%g,oldnorm=%g,norm=%g ",ynorm,fnorm,gnorm);
1323:
1324: fnorm=gnorm; //copy the new function norm; this will effect the line_search
1325: VecWAXPY(Sk,-1.0,X,W);
1326: //update the new solution
1327: ierr=VecCopy(W,X);
1328: ierr=VecCopy(G,F);
1330:
1331: // compute the new search direction G
1332: // I need to put Q(x)=x-FAS(x) here
1334: DMMGSolveFASCyclen(dmmg,level);
1335: //G = X - dmmg[level]->x; G is the new gradient, Y is old gradient
1336:
1337: VecWAXPY(G,-1.0,X,W);
1338: // copy W back to X
1339: VecCopy(W,X);
1340: VecNorm(G,NORM_2,&gnorm);
1341: VecNorm(Gradold,NORM_2,&ynorm);
1342: betaFR = gnorm*gnorm/(ynorm*ynorm); //FR_beta
1343:
1344: VecWAXPY(W,-1.0,Gradold,G);
1345: VecDot(W,G,&gnorm);
1346: // VecNorm(G,NORM_2,&gnorm);
1347: VecNorm(Gradold,NORM_2,&ynorm);
1348: betaPR = gnorm/(ynorm*ynorm); //PR_beta
1349:
1350: if ( betaPR<-betaFR)
1351: {
1352: beta =- betaFR;
1353: }
1354: else {
1355: if (betaPR>betaFR)
1356: {beta=betaFR;}
1357: else{
1359: beta=betaPR;
1360: }
1361: }
1362: // beta=betaFR;
1363: //beta=betaPR;
1365: // try another beta
1366:
1367: VecWAXPY(W,-1.0,Gradold,G);
1368: VecDot(W,G,&betaHS);
1369: VecDot(W,Y,&gnorm);
1370: betaHS=-betaHS/gnorm;
1371: VecDot(G,G,&betaDY);
1372: betaDY=-betaDY/gnorm;
1373: if(betaHS<betaDY)
1374: beta=betaHS;
1375: else
1376: beta=betaDY;
1377: if(beta<0)
1378: beta=0;
1379:
1380: PetscPrintf(PETSC_COMM_WORLD,"betaHS=%g,betaDY=%g\n",betaHS,betaDY);
1381:
1383:
1384: // compute the c_2
1385: VecDot(G,Y,&gnorm);
1386: VecDot(Gradold,Y,&ynorm);
1387: PetscPrintf(PETSC_COMM_WORLD,"beta=%g,c_2=%g\n",beta,fabs(gnorm/ynorm));
1388: VecNorm(G,NORM_2,&gnorm);
1389: VecNorm(Y,NORM_2,&ynorm);
1390: PetscPrintf(PETSC_COMM_WORLD,"size=%g\n",fabs(gnorm/(beta*ynorm)));
1392: // update the direction: Y= G + beta * Y
1393: VecAXPBY(Y,1.0,beta,G);
1394: VecCopy(G,Gradold);
1395: //ierr =VecCopy(G,Y);
1396: snes->iter = i+1;
1397: snes->norm = fnorm;
1398: PetscObjectGrantAccess(snes);
1399: SNESLogConvHistory(snes,fnorm,lits);
1400: SNESMonitor(snes,i+1,fnorm);
1401:
1402: if (!lssucceed) {
1403: PetscTruth ismin;
1404: beta=0;
1405: if (++snes->numFailures >= snes->maxFailures) {
1406: snes->reason = SNES_DIVERGED_LS_FAILURE;
1407: SNESLSCheckLocalMin_Private(snes->jacobian,F,W,fnorm,&ismin);
1408: if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
1409: break;
1410: }
1411: }
1412:
1414: /* Test for convergence */
1415: if (snes->ops->converged) {
1416: VecNorm(X,NORM_2,&xnorm); /* xnorm = || X || */
1417: (*snes->ops->converged)(snes,snes->iter,xnorm,1.0,fnorm,&snes->reason,snes->cnvP);
1418: if (snes->reason) {
1419: break;
1420: }
1421: }
1422: }
1423: if (X != snes->vec_sol) {
1424: VecCopy(X,snes->vec_sol);
1425: }
1426: if (F != snes->vec_func) {
1427: VecCopy(F,snes->vec_func);
1428: }
1429: if (i == maxits) {
1430: PetscInfo1(snes,"SNESSolve_LS: Maximum number of iterations has been reached: %D\n",maxits);
1431: snes->reason = SNES_DIVERGED_MAX_IT;
1432: }
1433: PetscPrintf(PETSC_COMM_WORLD,"reason=%d\n",snes->reason);
1434: // VecView(X,PETSC_VIEWER_STDOUT_WORLD);
1435: return(0);
1436: }
1440: /*
1442: This is function to implement NonGMRES to accelerate FAS
1444: In order to use this acceleration, the option is
1446: -dmmg_fas_NGMRES
1449: Options:
1451: -dmmg_fas_ngmres_m : the number of previous solutions to keep
1453: */
1457: PetscErrorCode DMMGSolveFAS_NGMRES(DMMG *dmmg, PetscInt level)
1458: {
1459: SNES snes = dmmg[level]->snes;
1461: PetscInt maxits=10000,i,k,l,j,subm=3,iter;
1462: PetscOptionsGetInt(PETSC_NULL,"-dmmg_fas_ngmres_m",&subm,PETSC_NULL);
1464: PetscTruth restart=PETSC_FALSE, selectA=PETSC_FALSE;
1465: PetscReal fnorm,gnorm,dnorm,dnormtemp,dminnorm,fminnorm,tol=1.e-12,gammaA=2,epsilonB=0.1,deltaB=0.9,gammaC;
1466: Vec X,F,G,W,D,u[subm],res[subm];
1467: PetscScalar H[subm][subm],q[subm][subm],beta[subm],xi[subm],alpha[subm],alphasum,det,Hinv[16];
1471: gammaC=2; if (gammaA>gammaC) gammaC=gammaA;
1472: VecDuplicate(dmmg[level]->x,&X);
1473: VecDuplicate(dmmg[level]->x,&F);
1474: VecDuplicate(dmmg[level]->x,&W);
1475: VecDuplicate(dmmg[level]->x,&G);
1476: VecDuplicate(dmmg[level]->x,&D);
1478: for(i=0;i<subm;i++) {/* get the space for the solution */
1479: VecDuplicate(dmmg[level]->x,&u[i]);
1480: VecDuplicate(dmmg[level]->x,&res[i]);
1481: }
1483: X = dmmg[level]->x;
1484: VecCopy(X,u[0]);
1485:
1486: // to get the residual for the F
1487: SNESComputeFunction(snes,X,F);
1488: VecCopy(F,res[0]);
1489: VecNorm(F,NORM_2,&fnorm); /* fnorm <- ||F|| */
1490: fnorm=fnorm*fnorm;
1491: iter=1;
1492: restartline:
1493:
1494: q[0][0] = fnorm; fminnorm=fnorm;
1497: for (k=1; k<maxits; k++) {
1499:
1500: PetscPrintf(PETSC_COMM_WORLD,"\n k=%d,iter=%d fmin=%g ",k,iter++,sqrt(fminnorm));
1501:
1502: /* compute the X=u^M , F=r, fnorm =||F||*/
1504: DMMGSolveFASCyclen(dmmg,level);
1505: SNESComputeFunction(snes,X,F);
1506: VecNorm(F,NORM_2,&fnorm);
1507: if (fnorm < tol) { return(0);}
1508: fnorm =fnorm*fnorm;
1509: if (fnorm<fminnorm) fminnorm=fnorm;
1510: //PetscPrintf(PETSC_COMM_WORLD,"fmin=%g",sqrt(fminnorm));
1511: /* compute u^A */
1512: //l=min(subm,k)
1513: l=subm;
1514: if (k<l) l=k;
1515:
1516: /* compute the matrix H and RHS */
1517:
1518:
1519: for(i=0;i<l;i++){
1520: VecDot(F,res[i],&xi[i]);
1521: beta[i]=fnorm-xi[i];
1522: }
1523:
1524: for(i=0;i<l;i++){
1525: for(j=0;j<l;j++){
1526: H[i][j]=q[i][j]-xi[i]-xi[j]+fnorm;
1527: }
1528: }
1529: /* Here is special for subm=2 */
1530: if(l==1){
1531: // H[0][0] = q[0][0]-xi[0]-xi[0]+fnorm;
1532: alpha[0]= beta[0]/H[0][0];
1533: }
1534: if(l==2){
1535:
1536: alpha[0]= ( beta[0]*H[1][1] -beta[1]*H[0][1] )/( H[0][0]*H[1][1]- H[0][1]*H[1][0]);
1537: alpha[1]= ( beta[1]*H[0][0] -beta[0]*H[1][0] )/( H[0][0]*H[1][1]- H[0][1]*H[1][0]);
1538:
1539: }
1540: if(l==3) {
1541:
1542: det = H[0][0]*(H[1][1]*H[2][2]-H[1][2]*H[2][1])-H[0][1]*(H[1][0]*H[2][2]-H[1][2]*H[2][0])+H[0][2]*(H[1][0]*H[2][1]-H[1][1]*H[2][0]);
1543: alpha[0]= (beta[0]*(H[1][1]*H[2][2]-H[1][2]*H[2][1])-H[0][1]*(beta[1]*H[2][2]-H[1][2]*beta[2])+H[0][2]*(beta[1]*H[2][1]-H[1][1]*beta[2]))/det;
1544: alpha[1]=(H[0][0]*(beta[1]*H[2][2]-H[1][2]*beta[2])-beta[0]*(H[1][0]*H[2][2]-H[1][2]*H[2][0])+H[0][2]*(H[1][0]*beta[2]-beta[1]*H[2][0]))/det;
1545: alpha[2]=(H[0][0]*(H[1][1]*beta[2]-beta[1]*H[2][1])-H[0][1]*(H[1][0]*beta[2]-beta[1]*H[2][0])+beta[0]*(H[1][0]*H[2][1]-H[1][1]*H[2][0]))/det;
1548: }
1549:
1550: if(l==4){
1551: Hinv[0]=H[0][0];Hinv[1]=H[0][1];Hinv[2]=H[0][2];Hinv[3]=H[0][3];
1552: Hinv[4]=H[1][0];Hinv[5]=H[1][1];Hinv[6]=H[1][2];Hinv[7]=H[1][3];
1553: Hinv[8]=H[2][0];Hinv[9]=H[2][1];Hinv[10]=H[2][2];Hinv[11]=H[2][3];
1554: Hinv[12]=H[3][0];Hinv[13]=H[3][1];Hinv[14]=H[3][2];Hinv[15]=H[3][3];
1555: Kernel_A_gets_inverse_A_4(Hinv,0.0);
1556: for(i=0;i<l;i++)
1557: alpha[i]=Hinv[4*i]*beta[0]+Hinv[4*i+1]*beta[1]+Hinv[4*i+2]*beta[2]+Hinv[4*i+3]*beta[3];
1558:
1559: }
1560: alphasum=0;
1561: for (i=0;i<l;i++)
1562: alphasum=alphasum+alpha[i];
1563:
1564: /* W= u^A */
1565: VecCopy(X,W);
1566: VecAXPBY(W,0.0,1-alphasum,X);
1567:
1568: for(i=0;i<l;i++)
1569: VecAXPY(W,alpha[i],u[i]);
1570:
1571: /* W= F(G) */
1572: SNESComputeFunction(snes,W,G);
1573: VecNorm(G,NORM_2,&gnorm);
1574: gnorm=gnorm*gnorm;
1577:
1578: /* select the uA or uM */
1579: // Criterion A
1580: if(sqrt(gnorm)<gammaA*sqrt(fminnorm)){
1581: //PetscPrintf(PETSC_COMM_WORLD,"Crite A\n");
1582: selectA=PETSC_TRUE;
1583: }
1584: // Criterion B
1585:
1586: ierr=VecCopy(W,D);
1587: ierr=VecAXPY(D,-1,X);
1588: ierr=VecNorm(D,NORM_2,&dnorm);
1589: dminnorm=10000000;
1590: for(i=0;i<l;i++) {
1591: ierr=VecCopy(W,D);
1592: ierr=VecAXPY(D,-1,u[i]);
1593: ierr=VecNorm(D,NORM_2,&dnormtemp);
1594: if(dnormtemp<dminnorm) dminnorm=dnormtemp;
1595: }
1596: if( epsilonB*dnorm<dminnorm || sqrt(gnorm)<deltaB*sqrt(fminnorm))
1597: selectA =PETSC_TRUE;
1598: else
1599: selectA=PETSC_FALSE;
1600:
1601: if(selectA){ /* uA selected */
1602: selectA=PETSC_FALSE;
1603: // PetscPrintf(PETSC_COMM_WORLD,"Select A\n");
1604: VecCopy(W,X);
1605: VecCopy(G,F);
1606: fnorm=gnorm;
1607: }
1608: if (fnorm<fminnorm) fminnorm=fnorm;
1609:
1611: /* Test for convergence */
1612: if (sqrt(fnorm)<tol) {
1613: return(0);
1614: }
1615:
1616: /* Test for restart */
1617: if(sqrt(gnorm)>gammaC*sqrt(fminnorm)) {
1618: PetscPrintf(PETSC_COMM_WORLD,"restart for C ");
1619: restart=PETSC_TRUE;
1620: }
1621: if(epsilonB*dnorm>dminnorm && sqrt(gnorm)>deltaB*sqrt(fminnorm)) {
1622: PetscPrintf(PETSC_COMM_WORLD,"restart for D ");
1623: restart=PETSC_TRUE;
1624: }
1625: /* Prepation for the next iteration */
1626:
1627: //turn off restart
1628: //restart=PETSC_FALSE;
1629: if(restart){
1630: restart=PETSC_FALSE;
1631: goto restartline;
1632: }
1633: else {
1634: j=k%subm;
1635: VecCopy(F,res[j]);
1636: VecCopy(X,u[j]);
1637: for(i=0;i<l;i++){
1638: ierr= VecDot(F,res[i],&q[j][i]);
1639: q[i][j]=q[j][i];
1640: }
1641: if(l<subm)
1642: q[j][j]=fnorm;
1643: }
1644: }
1646: return(0);
1647: }
1649: /*
1650: This is a function to provide the function value:
1652: x-FAS(x)
1654: */
1660: PetscErrorCode DMMGFASFunction(SNES snes,Vec x,Vec f,void *ptr)
1661: {
1662: DMMG* dmmg=(DMMG*)ptr;
1664: Vec temp;
1665: PetscInt level=dmmg[0]->nlevels-1;
1667:
1668: VecDuplicate(dmmg[level]->x,&temp);
1669:
1670:
1671: VecCopy(dmmg[level]->x,temp);
1672: VecCopy(x,dmmg[level]->x);
1673: VecCopy(x,f);
1674:
1675: // I need to put -F(x)=x-FAS(x) here
1676: DMMGSolveFASCyclen(dmmg,level);
1677: VecAXPY(f,-1.0,dmmg[level]->x);
1678: // y = alpha x + y.
1679: ierr=VecCopy(temp,dmmg[level]->x);
1680: //copy W back to X
1681:
1682: return(0);
1683: }
1687: /* this function is to implement Quasi-Newton method with implicit Broyden updating methods(limit memory version)
1689: In order to use this method, the option is -dmmg_fas_QNewton
1691: Options:
1693: -dmmg_fas_QNewton_m: the number of the vectors to keep for inverse of Jacobian
1695: -dmmg_fas_initialJacobian: will use matrix-free GMRES to solve the initial Jacobian
1697: with options -snes_mf -snes_max_it 1 -ksp_max_it n
1700: In this function, does not have line search and nonlinear gmres acceleration
1702: */
1706: PetscErrorCode DMMGSolveFAS_QNewton(DMMG *dmmg, PetscInt level)
1707: {
1709:
1711: SNES snes = dmmg[level]->snes, snes0;
1713: PetscInt maxits=10000,i,k,l,subm=3,subm01;
1714: PetscOptionsGetInt(PETSC_NULL,"-dmmg_fas_QNewton_m",&subm,PETSC_NULL);
1715: subm01=subm-1;
1716: PetscTruth flg;
1717: PetscReal fnorm,gnorm,tol=1.e-12;
1718: Vec X,F,G,W,D,Y,v[subm],w[subm],s0,s1,F0,F1;
1719:
1723: PetscOptionsHasName(PETSC_NULL,"-dmmg_fas_initialJacobian",&flg);
1724: VecDuplicate(dmmg[level]->x,&X);
1725: VecDuplicate(dmmg[level]->x,&F);
1726: VecDuplicate(dmmg[level]->x,&W);
1727: VecDuplicate(dmmg[level]->x,&G);
1728: VecDuplicate(dmmg[level]->x,&D);
1729: VecDuplicate(dmmg[level]->x,&Y);
1730: VecDuplicate(dmmg[level]->x,&s0);
1731: VecDuplicate(dmmg[level]->x,&s1);
1732: VecDuplicate(dmmg[level]->x,&F0);
1733: VecDuplicate(dmmg[level]->x,&F1);
1734:
1735: // creat a snes for solve the initial Jacobian
1736: SNESCreate(dmmg[level]->comm,&snes0);
1737: SNESSetFunction(snes0,F,DMMGFASFunction,dmmg);
1738: SNESSetFromOptions(snes0);
1740: for(i=0;i<subm;i++) {/* get the space for the solution */
1741: VecDuplicate(dmmg[level]->x,&v[i]);
1742: VecDuplicate(dmmg[level]->x,&w[i]);
1743: }
1745: //We first try B0==I
1746: X = dmmg[level]->x;
1747:
1748: if(flg){
1749: ierr= VecAXPBY(Y,0.0,0.0,X);
1750: ierr= VecCopy(X,s0);
1751: ierr= SNESSolve(snes0,Y,s0);
1752: ierr= VecAXPY(s0,-1.0,X);
1753: }
1754: else{
1755: ierr=VecCopy(X,W);
1756: ierr=VecCopy(X,Y);
1757:
1758: // I need to put -F(x)=x-FAS(x) here
1760: DMMGSolveFASCyclen(dmmg,level);
1761: VecAXPY(Y,-1.0,X);
1762: // y = alpha x + y.
1763: ierr=VecCopy(W,X);
1764: //copy W back to X
1765:
1766: // Y stores the -F(x)
1767: ierr= VecAXPBY(Y,0.0,-1.0,X);
1768: ierr= VecCopy(Y,s0);
1770: }
1771:
1772: VecAXPY(X,1.0,s0);
1773:
1774: for(k=0; k<maxits; k++){
1775:
1776: /* Test for convergence */
1777: SNESComputeFunction(snes,X,F);
1778: VecNorm(F,NORM_2,&fnorm); /* fnorm <- ||F|| */
1779: PetscPrintf(PETSC_COMM_WORLD,"k=%d, fnorm=%g\n",
1780: k,fnorm);
1781: if (fnorm<tol) {
1782: return(0);
1783: }
1784:
1786: if(flg){
1787: // ierr= SNESSolve(snes0,Y,s1);
1788: ierr= VecAXPBY(Y,0.0,0.0,X);
1789: ierr= VecCopy(dmmg[level]->x,s1);
1790: ierr= SNESSolve(snes0,Y,s1);
1791: ierr= VecAXPY(s1,-1.0,X);
1792:
1793: }
1794: else{
1795: ierr=VecCopy(X,W);
1796: ierr=VecCopy(X,Y);
1797:
1798: // I need to put -F(x)=x-FAS(x) here
1800: DMMGSolveFASCyclen(dmmg,level);
1801: VecAXPY(Y,-1.0,X);
1802: // y = alpha x + y.
1803: ierr=VecCopy(W,X);
1804: //copy W back to X
1805:
1806: //So far, I got X=x_k, Y=-F(x_k)
1807: // I should solve the G=-B_0^{-1}F(x_k) first, but I choose B_0^{-1}=I,
1808: ierr=VecCopy(Y,F1);
1809: ierr= VecAXPBY(Y,0.0,-1.0,X);
1810: ierr=VecCopy(Y,s1);
1812: }
1813:
1814: l=subm;
1815: if (k<l) l=k;
1816:
1817:
1818: for (i=0;i<l;i++){
1819: // compute [I+v(i)w(i)^T]*s(k)
1820: ierr= VecDot(w[i],s1,&gnorm);
1821: VecAXPY(s1,gnorm,v[i]);
1822:
1823: }
1824: if(l==subm) {
1825: for(i=0;i<subm01;i++){
1826: ierr= VecCopy(w[i+1],w[i]);
1827: ierr= VecCopy(v[i+1],v[i]);
1828: }
1829: l--;
1830: }
1831: ierr= VecCopy(s0,w[l]);
1832: ierr= VecCopy(s0,Y);
1833: ierr= VecCopy(s1,v[l]);
1834: ierr= VecAXPY(Y,-1.0,s1);
1835: ierr= VecDot(w[l],Y,&gnorm);
1836: ierr= VecAXPBY(v[l],0.0,1.0/gnorm,w[l]);
1838: ierr= VecDot(s1,w[l],&gnorm);
1839: ierr= VecAXPY(s1,gnorm,v[l]);
1840: ierr= VecCopy(s1,s0);
1841: ierr=VecAXPY(X,1.0,s1);
1842: }
1843: return(0);
1844: }