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/mat/blockinvert.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 = PETSC_FALSE,flgb = PETSC_FALSE;
1074:   PetscReal      norm;

1077:    DMMGSolveFASSetUp(dmmg,level);
1078:   PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_9",&flgb,PETSC_NULL);
1079: 
1080:   if(flgb){

1082:     PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_full",&flg,PETSC_NULL);
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:     flg  = PETSC_FALSE;
1111:     PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_full",&flg,PETSC_NULL);
1112:     if (flg) {
1113:       for(i=0;i<1000;i++){
1114:         PetscPrintf(dmmg[level]->comm,"%D ",i+1);
1115:         DMMGSolveFASFCycle(dmmg,level,&converged);
1116:         if (dmmg[level]->monitor){
1117:           DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1118:           VecNorm(dmmg[level]->w,NORM_2,&norm);
1119:           PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1120:         }
1121:         if (converged) return(0);
1122:       }
1123:     }
1124:     else{
1125:       for(i=0;i<1000;i++){
1126:         PetscPrintf(dmmg[level]->comm,"%D ",i+1);
1127:         DMMGSolveFASMCycle(dmmg,level,&converged);
1128:         if (dmmg[level]->monitor){
1129:           DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1130:           VecNorm(dmmg[level]->w,NORM_2,&norm);
1131:           PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1132:         }

1134:         if (converged) return(0);
1135:       }

1137:     }
1138:   }
1139:   return(0);
1140: }

1142: /*
1143:           This is function is to implement one  FAS iteration 

1145: Options:

1147: -dmmg_fas_9:    using block smoother 
1148:  
1149: -dmmg_fas_full: using full FAS

1151: */
1154: PetscErrorCode DMMGSolveFASCyclen(DMMG *dmmg,PetscInt level)
1155: {
1157:   PetscTruth     converged = PETSC_FALSE, flg = PETSC_FALSE,flgb = PETSC_FALSE;
1158:   PetscReal      norm;
1159:   // PC_MG          **mg;
1160:   //PC             pc;

1163:    DMMGSolveFASSetUp(dmmg,level);
1164:      PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_9",&flgb,PETSC_NULL);
1165: 
1166:   if(flgb){

1168:     PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_full",&flg,PETSC_NULL);
1169:     if (flg) {
1170: 
1171:         DMMGSolveFASFCycle9(dmmg,level,&converged);
1172:         if (dmmg[level]->monitor){
1173:           DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1174:           VecNorm(dmmg[level]->w,NORM_2,&norm);
1175:           PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1176:         }

1178:     }
1179:     else{
1180: 
1181:         DMMGSolveFASMCycle9(dmmg,level,&converged);
1182:         if (dmmg[level]->monitor){
1183:           DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1184:           VecNorm(dmmg[level]->w,NORM_2,&norm);
1185:           PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1186:         }


1189:     }
1190:   }
1191:   else {
1192:     flg  = PETSC_FALSE;
1193:     PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_full",&flg,PETSC_NULL);
1194:     if (flg) {
1195: 
1196:         DMMGSolveFASFCycle(dmmg,level,&converged);
1197:         if (dmmg[level]->monitor){
1198:           DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1199:           VecNorm(dmmg[level]->w,NORM_2,&norm);
1200:           PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1201:         }

1203:     }
1204:     else{
1205: 
1206:         DMMGSolveFASMCycle(dmmg,level,&converged);
1207:         if (dmmg[level]->monitor){
1208:           DMMGFormFunction(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
1209:           VecNorm(dmmg[level]->w,NORM_2,&norm);
1210:           PetscPrintf(dmmg[level]->comm," FAS function norm %g\n",norm);
1211:         }



1215:     }
1216:   }
1217: 

1219:   return(0);
1220: }


1223: /*

1225: This is function to implement Nonlinear CG to accelerate FAS

1227: In order to use this acceleration, the option is

1229: -dmmg_fas_NCG



1233: */


1238: PetscErrorCode DMMGSolveFAS_NCG(DMMG *dmmg, PetscInt level)
1239: {
1240:   SNES           snes = dmmg[level]->snes;
1241:   SNES_LS        *neP = (SNES_LS*)snes->data;
1243:   PetscInt       maxits,i,lits;
1244:   PetscTruth     lssucceed;
1245:   // MatStructure   flg = DIFFERENT_NONZERO_PATTERN;
1246:   PetscReal      fnorm,gnorm,xnorm,ynorm,betaFR,betaPR,beta,betaHS,betaDY;
1247:   Vec            Y,X,F,G,W,Gradold,Sk;
1248:   //KSP            ksp;


1252:   VecDuplicate(dmmg[level]->x,&Sk);
1253:   PetscObjectReference((PetscObject)dmmg[level]->x);
1254:   if (snes->vec_sol) { VecDestroy(snes->vec_sol); }
1255:   snes->vec_sol = dmmg[level]->x;
1256:   if (!snes->setupcalled) { SNESSetUp(snes); }
1257:   if (snes->conv_hist_reset) snes->conv_hist_len = 0;
1258:   PetscLogEventBegin(SNES_Solve,snes,0,0,0);
1259:   snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;


1262:   snes->reason  = SNES_CONVERGED_ITERATING;

1264:   maxits        = snes->max_its;        /* maximum number of iterations */
1265:   X                = snes->vec_sol;        /* solution vector */
1266:   F                = snes->vec_func;        /* residual vector */
1267:   Y                = snes->work[0];        /* work vectors */
1268:   G                = snes->work[1];
1269:   W                = snes->work[2];

1271:   PetscObjectTakeAccess(snes);
1272:   snes->iter = 0;
1273:   PetscObjectGrantAccess(snes);
1274: 
1275:   X    = dmmg[level]->x;
1276:   VecCopy(X,Y);
1277:   VecCopy(X,G);

1279:   // to get the residual for the F
1280:   SNESComputeFunction(snes,X,F);
1281: 
1282:   VecNorm(F,NORM_2,&fnorm);        /* fnorm <- ||F||  */
1283:   if (fnorm != fnorm) SETERRQ(PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1284:   PetscObjectTakeAccess(snes);
1285:   snes->norm = fnorm;
1286:   PetscObjectGrantAccess(snes);
1287:   SNESLogConvHistory(snes,fnorm,0);
1288:   SNESMonitor(snes,0,fnorm);

1290:   if (fnorm < snes->abstol) {snes->reason = SNES_CONVERGED_FNORM_ABS; return(0);}

1292:   /* set parameter for default relative tolerance convergence test */
1293:   snes->ttol = fnorm*snes->rtol;
1294:   // dmmg[level]->rrtol= snes->ttol;

1296:   // set this to store the old grad
1297:   Gradold=snes->vec_sol_update;
1298: 
1299:   // compute the search direction Y
1300:   // I need to put Q(x)=x-FAS(x) here
1301:   DMMGSolveFASCyclen(dmmg,level);
1302:   //  F    = X - dmmg[level]->x; this is the gradient direction
1303:   VecAXPY(Y,-1.0,X);
1304:   // copy the gradient to the old
1305:   VecCopy(Y,Gradold);
1306:   // copy X back
1307:   VecCopy(G,X);
1308:   VecWAXPY(Sk,-1.0,X,X);
1309:   // so far I put X=X_c, F= F(x_c),  Gradold= Y=grad(x_c)

1311:   //  for (i=0; i<maxits; i++) {

1313:    for (i=0; i<10000; i++) {


1316:     PetscPrintf(PETSC_COMM_WORLD,"iter=%d",i+1);
1317: 
1318: 
1319:     // X=x_c, F=F(x_c),Y search direction; G=F(x_new), W=x_new,
1320:     VecNorm(X,NORM_2,&xnorm);
1321:     (*neP->LineSearch)(snes,neP->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);
1322:     PetscInfo4(snes,"SNESSolve_LS: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);
1323:     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
1324:     PetscPrintf(PETSC_COMM_WORLD,"step=%g,oldnorm=%g,norm=%g ",ynorm,fnorm,gnorm);
1325: 
1326:     fnorm=gnorm; //copy the new function norm; this will effect the line_search
1327:      VecWAXPY(Sk,-1.0,X,W);
1328:     //update the new solution
1329:     ierr=VecCopy(W,X);
1330:     ierr=VecCopy(G,F);

1332: 
1333:   // compute the new search direction G
1334:   // I need to put Q(x)=x-FAS(x) here

1336:   DMMGSolveFASCyclen(dmmg,level);
1337:   //G    = X - dmmg[level]->x; G is the new gradient, Y is old gradient
1338: 
1339:   VecWAXPY(G,-1.0,X,W);
1340:   // copy W back to X
1341:   VecCopy(W,X);
1342:   VecNorm(G,NORM_2,&gnorm);
1343:   VecNorm(Gradold,NORM_2,&ynorm);
1344:   betaFR = gnorm*gnorm/(ynorm*ynorm); //FR_beta
1345: 
1346:   VecWAXPY(W,-1.0,Gradold,G);
1347:   VecDot(W,G,&gnorm);
1348:   //  VecNorm(G,NORM_2,&gnorm);
1349:   VecNorm(Gradold,NORM_2,&ynorm);
1350:   betaPR = gnorm/(ynorm*ynorm); //PR_beta
1351: 
1352:   if ( betaPR<-betaFR)
1353:     {
1354:       beta =- betaFR;
1355:     }
1356:   else {
1357:     if (betaPR>betaFR)
1358:       {beta=betaFR;}
1359:     else{

1361:       beta=betaPR;
1362:     }
1363:   }
1364:   //  beta=betaFR;
1365:   //beta=betaPR;

1367:   // try another beta
1368: 
1369:      VecWAXPY(W,-1.0,Gradold,G);
1370:      VecDot(W,G,&betaHS);
1371:      VecDot(W,Y,&gnorm);
1372:      betaHS=-betaHS/gnorm;
1373:      VecDot(G,G,&betaDY);
1374:      betaDY=-betaDY/gnorm;
1375:      if(betaHS<betaDY)
1376:        beta=betaHS;
1377:      else
1378:        beta=betaDY;
1379:      if(beta<0)
1380:        beta=0;
1381: 
1382:      PetscPrintf(PETSC_COMM_WORLD,"betaHS=%g,betaDY=%g\n",betaHS,betaDY);
1383: 

1385: 
1386:     // compute the c_2
1387:     VecDot(G,Y,&gnorm);
1388:     VecDot(Gradold,Y,&ynorm);
1389:     PetscPrintf(PETSC_COMM_WORLD,"beta=%g,c_2=%g\n",beta,fabs(gnorm/ynorm));
1390:      VecNorm(G,NORM_2,&gnorm);
1391:     VecNorm(Y,NORM_2,&ynorm);
1392:     PetscPrintf(PETSC_COMM_WORLD,"size=%g\n",fabs(gnorm/(beta*ynorm)));

1394:     // update the direction: Y= G + beta * Y
1395:     VecAXPBY(Y,1.0,beta,G);
1396:     VecCopy(G,Gradold);
1397:     //ierr =VecCopy(G,Y);
1398:     snes->iter = i+1;
1399:     snes->norm = fnorm;
1400:     PetscObjectGrantAccess(snes);
1401:     SNESLogConvHistory(snes,fnorm,lits);
1402:     SNESMonitor(snes,i+1,fnorm);
1403: 
1404:      if (!lssucceed) {
1405:       PetscTruth ismin;
1406:       beta=0;
1407:       if (++snes->numFailures >= snes->maxFailures) {
1408:       snes->reason = SNES_DIVERGED_LS_FAILURE;
1409:         SNESLSCheckLocalMin_Private(snes->jacobian,F,W,fnorm,&ismin);
1410:         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
1411:         break;
1412:       }
1413:       }
1414: 

1416:     /* Test for convergence */
1417:     if (snes->ops->converged) {
1418:       VecNorm(X,NORM_2,&xnorm);        /* xnorm = || X || */
1419:       (*snes->ops->converged)(snes,snes->iter,xnorm,1.0,fnorm,&snes->reason,snes->cnvP);
1420:       if (snes->reason) {
1421:         break;
1422:       }
1423:     }
1424:   }
1425:   if (X != snes->vec_sol) {
1426:     VecCopy(X,snes->vec_sol);
1427:   }
1428:   if (F != snes->vec_func) {
1429:     VecCopy(F,snes->vec_func);
1430:   }
1431:   if (i == maxits) {
1432:     PetscInfo1(snes,"SNESSolve_LS: Maximum number of iterations has been reached: %D\n",maxits);
1433:     snes->reason = SNES_DIVERGED_MAX_IT;
1434:   }
1435:   PetscPrintf(PETSC_COMM_WORLD,"reason=%d\n",snes->reason);
1436:   // VecView(X,PETSC_VIEWER_STDOUT_WORLD);
1437:   return(0);
1438: }



1442: /*

1444: This is function to implement NonGMRES  to accelerate FAS

1446: In order to use this acceleration, the option is

1448: -dmmg_fas_NGMRES


1451: Options:

1453: -dmmg_fas_ngmres_m : the number of previous solutions to keep

1455: */

1459: PetscErrorCode DMMGSolveFAS_NGMRES(DMMG *dmmg, PetscInt level)
1460: {
1461:   SNES           snes = dmmg[level]->snes;
1463:   PetscInt       maxits=10000,i,k,l,j,subm=3,iter;
1464:  PetscOptionsGetInt(PETSC_NULL,"-dmmg_fas_ngmres_m",&subm,PETSC_NULL);

1466:   PetscTruth     restart=PETSC_FALSE, selectA=PETSC_FALSE;
1467:   PetscReal      fnorm,gnorm,dnorm,dnormtemp,dminnorm,fminnorm,tol=1.e-12,gammaA=2,epsilonB=0.1,deltaB=0.9,gammaC;
1468:   Vec            X,F,G,W,D,u[subm],res[subm];
1469:    PetscScalar    H[subm][subm],q[subm][subm],beta[subm],xi[subm],alpha[subm],alphasum,det,Hinv[16];


1473:  gammaC=2; if (gammaA>gammaC) gammaC=gammaA;
1474:  VecDuplicate(dmmg[level]->x,&X);
1475:  VecDuplicate(dmmg[level]->x,&F);
1476:  VecDuplicate(dmmg[level]->x,&W);
1477:  VecDuplicate(dmmg[level]->x,&G);
1478:  VecDuplicate(dmmg[level]->x,&D);

1480:  for(i=0;i<subm;i++) {/* get the space for the solution */
1481:    VecDuplicate(dmmg[level]->x,&u[i]);
1482:    VecDuplicate(dmmg[level]->x,&res[i]);
1483:  }

1485:   X    = dmmg[level]->x;
1486:   VecCopy(X,u[0]);
1487: 
1488:   // to get the residual for the F
1489:   SNESComputeFunction(snes,X,F);
1490:   VecCopy(F,res[0]);
1491:   VecNorm(F,NORM_2,&fnorm);        /* fnorm <- ||F||  */
1492:   fnorm=fnorm*fnorm;
1493:   iter=1;
1494:   restartline:
1495: 
1496:   q[0][0] = fnorm; fminnorm=fnorm;


1499:    for (k=1; k<maxits; k++) {

1501: 
1502:      PetscPrintf(PETSC_COMM_WORLD,"\n k=%d,iter=%d fmin=%g ",k,iter++,sqrt(fminnorm));
1503: 
1504:     /* compute the X=u^M , F=r, fnorm =||F||*/

1506:     DMMGSolveFASCyclen(dmmg,level);
1507:     SNESComputeFunction(snes,X,F);
1508:     VecNorm(F,NORM_2,&fnorm);
1509:     if (fnorm < tol) { return(0);}
1510:     fnorm =fnorm*fnorm;
1511:     if (fnorm<fminnorm) fminnorm=fnorm;
1512:     //PetscPrintf(PETSC_COMM_WORLD,"fmin=%g",sqrt(fminnorm));
1513:     /* compute u^A */
1514:     //l=min(subm,k)
1515:     l=subm;
1516:     if (k<l) l=k;
1517: 
1518:     /* compute the matrix H and RHS */
1519: 
1520: 
1521:     for(i=0;i<l;i++){
1522:       VecDot(F,res[i],&xi[i]);
1523:       beta[i]=fnorm-xi[i];
1524:     }
1525: 
1526:     for(i=0;i<l;i++){
1527:       for(j=0;j<l;j++){
1528:        H[i][j]=q[i][j]-xi[i]-xi[j]+fnorm;
1529:       }
1530:     }
1531:     /* Here is special for subm=2 */
1532:     if(l==1){
1533:       //   H[0][0] = q[0][0]-xi[0]-xi[0]+fnorm;
1534:       alpha[0]= beta[0]/H[0][0];
1535:     }
1536:     if(l==2){
1537: 
1538:       alpha[0]= ( beta[0]*H[1][1] -beta[1]*H[0][1] )/( H[0][0]*H[1][1]- H[0][1]*H[1][0]);
1539:       alpha[1]= ( beta[1]*H[0][0] -beta[0]*H[1][0] )/( H[0][0]*H[1][1]- H[0][1]*H[1][0]);
1540: 
1541:     }
1542:     if(l==3) {
1543: 
1544:   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]);
1545:       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;
1546:       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;
1547:       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;


1550:     }
1551: 
1552:     if(l==4){
1553:         Hinv[0]=H[0][0];Hinv[1]=H[0][1];Hinv[2]=H[0][2];Hinv[3]=H[0][3];
1554:       Hinv[4]=H[1][0];Hinv[5]=H[1][1];Hinv[6]=H[1][2];Hinv[7]=H[1][3];
1555:       Hinv[8]=H[2][0];Hinv[9]=H[2][1];Hinv[10]=H[2][2];Hinv[11]=H[2][3];
1556:       Hinv[12]=H[3][0];Hinv[13]=H[3][1];Hinv[14]=H[3][2];Hinv[15]=H[3][3];
1557:       Kernel_A_gets_inverse_A_4(Hinv,0.0);
1558:       for(i=0;i<l;i++)
1559:         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];
1560: 
1561:     }
1562:     alphasum=0;
1563:     for (i=0;i<l;i++)
1564:       alphasum=alphasum+alpha[i];
1565: 
1566:     /* W= u^A */
1567:     VecCopy(X,W);
1568:     VecAXPBY(W,0.0,1-alphasum,X);
1569: 
1570:     for(i=0;i<l;i++)
1571:          VecAXPY(W,alpha[i],u[i]);
1572: 
1573:     /* W= F(G) */
1574:     SNESComputeFunction(snes,W,G);
1575:     VecNorm(G,NORM_2,&gnorm);
1576:     gnorm=gnorm*gnorm;


1579: 
1580:     /* select the uA or uM */
1581:     // Criterion A
1582:     if(sqrt(gnorm)<gammaA*sqrt(fminnorm)){
1583:       //PetscPrintf(PETSC_COMM_WORLD,"Crite A\n");
1584:        selectA=PETSC_TRUE;
1585:     }
1586:     // Criterion B
1587: 
1588:     ierr=VecCopy(W,D);
1589:     ierr=VecAXPY(D,-1,X);
1590:     ierr=VecNorm(D,NORM_2,&dnorm);
1591:     dminnorm=10000000;
1592:     for(i=0;i<l;i++) {
1593:       ierr=VecCopy(W,D);
1594:       ierr=VecAXPY(D,-1,u[i]);
1595:       ierr=VecNorm(D,NORM_2,&dnormtemp);
1596:       if(dnormtemp<dminnorm) dminnorm=dnormtemp;
1597:     }
1598:      if( epsilonB*dnorm<dminnorm || sqrt(gnorm)<deltaB*sqrt(fminnorm))
1599:       selectA =PETSC_TRUE;
1600:     else
1601:       selectA=PETSC_FALSE;
1602: 
1603:     if(selectA){  /* uA selected */
1604:       selectA=PETSC_FALSE;
1605:       //   PetscPrintf(PETSC_COMM_WORLD,"Select A\n");
1606:       VecCopy(W,X);
1607:       VecCopy(G,F);
1608:       fnorm=gnorm;
1609:     }
1610:      if (fnorm<fminnorm) fminnorm=fnorm;
1611: 

1613:     /* Test for convergence */
1614:     if (sqrt(fnorm)<tol) {
1615:       return(0);
1616:     }
1617: 
1618:     /* Test for restart */
1619:     if(sqrt(gnorm)>gammaC*sqrt(fminnorm)) {
1620:       PetscPrintf(PETSC_COMM_WORLD,"restart for C ");
1621:       restart=PETSC_TRUE;
1622:     }
1623:     if(epsilonB*dnorm>dminnorm && sqrt(gnorm)>deltaB*sqrt(fminnorm)) {
1624:       PetscPrintf(PETSC_COMM_WORLD,"restart for D ");
1625:       restart=PETSC_TRUE;
1626:       }
1627:     /* Prepation for the next iteration */
1628: 
1629:      //turn off restart
1630:     //restart=PETSC_FALSE;
1631:     if(restart){
1632:       restart=PETSC_FALSE;
1633:       goto restartline;
1634:     }
1635:     else {
1636:       j=k%subm;
1637:       VecCopy(F,res[j]);
1638:       VecCopy(X,u[j]);
1639:       for(i=0;i<l;i++){
1640:           ierr= VecDot(F,res[i],&q[j][i]);
1641:         q[i][j]=q[j][i];
1642:       }
1643:       if(l<subm)
1644:       q[j][j]=fnorm;
1645:     }
1646:    }

1648:   return(0);
1649: }

1651: /*
1652: This is a function to provide the function value:

1654: x-FAS(x)

1656: */



1662: PetscErrorCode DMMGFASFunction(SNES snes,Vec x,Vec f,void *ptr)
1663: {
1664:       DMMG*          dmmg=(DMMG*)ptr;
1666:       Vec            temp;
1667:       PetscInt       level=dmmg[0]->nlevels-1;
1669: 
1670:       VecDuplicate(dmmg[level]->x,&temp);
1671: 
1672: 
1673:       VecCopy(dmmg[level]->x,temp);
1674:       VecCopy(x,dmmg[level]->x);
1675:       VecCopy(x,f);
1676: 
1677:       // I need to put -F(x)=x-FAS(x) here
1678:       DMMGSolveFASCyclen(dmmg,level);
1679:       VecAXPY(f,-1.0,dmmg[level]->x);
1680:       // y = alpha x + y.
1681:       ierr=VecCopy(temp,dmmg[level]->x);
1682:       //copy W back to X
1683: 
1684:  return(0);
1685: }



1689: /* this function is to implement Quasi-Newton method with implicit Broyden updating methods(limit memory version)

1691: In order to use this method, the option is -dmmg_fas_QNewton

1693: Options:

1695: -dmmg_fas_QNewton_m: the number of the vectors to keep for inverse of Jacobian

1697: -dmmg_fas_initialJacobian: will use matrix-free GMRES to solve the initial Jacobian 

1699:                         with  options -snes_mf -snes_max_it 1 -ksp_max_it n


1702: In this function, does not have line search and nonlinear gmres acceleration

1704: */

1708: PetscErrorCode DMMGSolveFAS_QNewton(DMMG *dmmg, PetscInt level)
1709: {

1711: 

1713:   SNES           snes = dmmg[level]->snes, snes0;
1715:   PetscInt       maxits=10000,i,k,l,subm=3,subm01;
1716:   PetscOptionsGetInt(PETSC_NULL,"-dmmg_fas_QNewton_m",&subm,PETSC_NULL);
1717:   subm01=subm-1;
1718:    PetscTruth   flg = PETSC_FALSE;
1719:    PetscReal      fnorm,gnorm,tol=1.e-12;
1720:   Vec            X,F,G,W,D,Y,v[subm],w[subm],s0,s1,F0,F1;
1721: 


1725:  PetscOptionsGetTruth(PETSC_NULL,"-dmmg_fas_initialJacobian",&flg,PETSC_NULL);
1726:  VecDuplicate(dmmg[level]->x,&X);
1727:  VecDuplicate(dmmg[level]->x,&F);
1728:  VecDuplicate(dmmg[level]->x,&W);
1729:  VecDuplicate(dmmg[level]->x,&G);
1730:  VecDuplicate(dmmg[level]->x,&D);
1731:  VecDuplicate(dmmg[level]->x,&Y);
1732:  VecDuplicate(dmmg[level]->x,&s0);
1733:  VecDuplicate(dmmg[level]->x,&s1);
1734:  VecDuplicate(dmmg[level]->x,&F0);
1735:  VecDuplicate(dmmg[level]->x,&F1);
1736: 
1737:  // creat a snes for solve the initial Jacobian
1738:  SNESCreate(dmmg[level]->comm,&snes0);
1739:  SNESSetFunction(snes0,F,DMMGFASFunction,dmmg);
1740:  SNESSetFromOptions(snes0);

1742:  for(i=0;i<subm;i++) {/* get the space for the solution */
1743:    VecDuplicate(dmmg[level]->x,&v[i]);
1744:    VecDuplicate(dmmg[level]->x,&w[i]);
1745:  }

1747:  //We first try B0==I
1748:    X    = dmmg[level]->x;
1749: 
1750:    if(flg){
1751:      ierr= VecAXPBY(Y,0.0,0.0,X);
1752:      ierr= VecCopy(X,s0);
1753:      ierr= SNESSolve(snes0,Y,s0);
1754:      ierr= VecAXPY(s0,-1.0,X);
1755:    }
1756:    else{
1757:      ierr=VecCopy(X,W);
1758:      ierr=VecCopy(X,Y);
1759: 
1760:      // I need to put -F(x)=x-FAS(x) here

1762:      DMMGSolveFASCyclen(dmmg,level);
1763:      VecAXPY(Y,-1.0,X);
1764:      // y = alpha x + y.
1765:      ierr=VecCopy(W,X);
1766:      //copy W back to X
1767: 
1768:      // Y stores the -F(x)
1769:      ierr= VecAXPBY(Y,0.0,-1.0,X);
1770:      ierr= VecCopy(Y,s0);

1772:    }
1773: 
1774:    VecAXPY(X,1.0,s0);
1775: 
1776: for(k=0; k<maxits; k++){
1777: 
1778:  /* Test for convergence */
1779:    SNESComputeFunction(snes,X,F);
1780:    VecNorm(F,NORM_2,&fnorm);        /* fnorm <- ||F||  */
1781:    PetscPrintf(PETSC_COMM_WORLD,"k=%d, fnorm=%g\n",
1782:                        k,fnorm);
1783:     if (fnorm<tol) {
1784:       return(0);
1785:     }
1786: 

1788:     if(flg){
1789:       //     ierr= SNESSolve(snes0,Y,s1);
1790:       ierr= VecAXPBY(Y,0.0,0.0,X);
1791:       ierr= VecCopy(dmmg[level]->x,s1);
1792:       ierr= SNESSolve(snes0,Y,s1);
1793:       ierr= VecAXPY(s1,-1.0,X);
1794: 
1795:     }
1796:     else{
1797:       ierr=VecCopy(X,W);
1798:       ierr=VecCopy(X,Y);
1799: 
1800:       // I need to put -F(x)=x-FAS(x) here

1802:       DMMGSolveFASCyclen(dmmg,level);
1803:       VecAXPY(Y,-1.0,X);
1804:       // y = alpha x + y.
1805:       ierr=VecCopy(W,X);
1806:       //copy W back to X
1807: 
1808:       //So far, I got X=x_k, Y=-F(x_k)
1809:       // I should solve the G=-B_0^{-1}F(x_k) first, but I choose B_0^{-1}=I,
1810:       ierr=VecCopy(Y,F1);
1811:       ierr= VecAXPBY(Y,0.0,-1.0,X);
1812:       ierr=VecCopy(Y,s1);

1814:     }
1815: 
1816:    l=subm;
1817:    if (k<l) l=k;
1818: 
1819: 
1820:    for (i=0;i<l;i++){
1821:      // compute [I+v(i)w(i)^T]*s(k)
1822:      ierr= VecDot(w[i],s1,&gnorm);
1823:      VecAXPY(s1,gnorm,v[i]);
1824: 
1825:    }
1826:    if(l==subm) {
1827:      for(i=0;i<subm01;i++){
1828:        ierr= VecCopy(w[i+1],w[i]);
1829:        ierr= VecCopy(v[i+1],v[i]);
1830:      }
1831:      l--;
1832:    }
1833:      ierr= VecCopy(s0,w[l]);
1834:      ierr= VecCopy(s0,Y);
1835:      ierr= VecCopy(s1,v[l]);
1836:      ierr= VecAXPY(Y,-1.0,s1);
1837:      ierr= VecDot(w[l],Y,&gnorm);
1838:      ierr= VecAXPBY(v[l],0.0,1.0/gnorm,w[l]);

1840:      ierr= VecDot(s1,w[l],&gnorm);
1841:      ierr= VecAXPY(s1,gnorm,v[l]);
1842:      ierr= VecCopy(s1,s0);
1843:      ierr=VecAXPY(X,1.0,s1);
1844:  }
1845:   return(0);
1846: }