Actual source code: damg.c
1:
2: #include <petscdm.h> /*I "petscdm.h" I*/
3: #include <petscksp.h> /*I "petscksp.h" I*/
4: #include <petscpcmg.h> /*I "petscpcmg.h" I*/
5: #include <petscdmmg.h> /*I "petscdmmg.h" I*/
6: #include <private/pcimpl.h> /*I "petscpc.h" I*/
8: /*
9: Code for almost fully managing multigrid/multi-level linear solvers for DM grids
10: */
14: /*@C
15: DMMGCreate - Creates a DM based multigrid solver object. This allows one to
16: easily implement MG methods on regular grids.
18: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
19: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
21: Collective on MPI_Comm
23: Input Parameter:
24: + comm - the processors that will share the grids and solution process
25: . nlevels - number of multigrid levels (if this is negative it CANNOT be reset with -dmmg_nlevels
26: - user - an optional user context
28: Output Parameters:
29: . - the context
31: Options Database:
32: + -dmmg_nlevels <levels> - number of levels to use
33: . -pc_mg_galerkin - use Galerkin approach to compute coarser matrices
34: - -dmmg_mat_type <type> - matrix type that DMMG should create, defaults to MATAIJ
36: Notes:
37: To provide a different user context for each level call DMMGSetUser() after calling
38: this routine
40: Level: advanced
42: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser(), DMMGSetMatType(), DMMGSetNullSpace(), DMMGSetInitialGuess(),
43: DMMGSetISColoringType()
45: @*/
46: PetscErrorCode DMMGCreate(MPI_Comm comm,PetscInt nlevels,void *user,DMMG **dmmg)
47: {
49: PetscInt i;
50: DMMG *p;
51: PetscBool ftype;
52: char mtype[256];
55: if (nlevels < 0) {
56: nlevels = -nlevels;
57: } else {
58: PetscOptionsGetInt(0,"-dmmg_nlevels",&nlevels,PETSC_IGNORE);
59: }
60: if (nlevels < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot set levels less than 1");
62: PetscMalloc(nlevels*sizeof(DMMG),&p);
63: for (i=0; i<nlevels; i++) {
64: PetscNew(struct _n_DMMG,&p[i]);
65: p[i]->nlevels = nlevels - i;
66: p[i]->comm = comm;
67: p[i]->user = user;
68: p[i]->updatejacobianperiod = 1;
69: p[i]->updatejacobian = PETSC_TRUE;
70: p[i]->isctype = IS_COLORING_GLOBAL;
71: PetscStrallocpy(MATAIJ,&p[i]->mtype);
72: }
73: *dmmg = p;
75: PetscOptionsGetString(PETSC_NULL,"-dmmg_mat_type",mtype,256,&ftype);
76: if (ftype) {
77: DMMGSetMatType(*dmmg,mtype);
78: }
79: return(0);
80: }
84: /*@C
85: DMMGSetMatType - Sets the type of matrices that DMMG will create for its solvers.
87: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
88: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
90: Logically Collective on MPI_Comm
92: Input Parameters:
93: + dmmg - the DMMG object created with DMMGCreate()
94: - mtype - the matrix type, defaults to MATAIJ
96: Level: intermediate
98: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser(), DMMGCreate(), DMMGSetNullSpace()
100: @*/
101: PetscErrorCode DMMGSetMatType(DMMG *dmmg,const MatType mtype)
102: {
103: PetscInt i;
107: for (i=0; i<dmmg[0]->nlevels; i++) {
108: PetscFree(dmmg[i]->mtype);
109: PetscStrallocpy(mtype,&dmmg[i]->mtype);
110: }
111: return(0);
112: }
116: /*@C
117: DMMGSetOptionsPrefix - Sets the prefix used for the solvers inside a DMMG
119: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
120: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
122: Logically Collective on MPI_Comm
124: Input Parameters:
125: + dmmg - the DMMG object created with DMMGCreate()
126: - prefix - the prefix string
128: Level: intermediate
130: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser(), DMMGCreate(), DMMGSetNullSpace()
132: @*/
133: PetscErrorCode DMMGSetOptionsPrefix(DMMG *dmmg,const char prefix[])
134: {
135: PetscInt i;
137:
139: for (i=0; i<dmmg[0]->nlevels; i++) {
140: PetscStrallocpy(prefix,&dmmg[i]->prefix);
141: }
142: return(0);
143: }
147: /*@C
148: DMMGDestroy - Destroys a DM based multigrid solver object.
150: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
151: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
153: Collective on DMMG
155: Input Parameter:
156: . - the context
158: Level: advanced
160: .seealso DMMGCreate()
162: @*/
163: PetscErrorCode DMMGDestroy(DMMG *dmmg)
164: {
166: PetscInt i,nlevels = dmmg[0]->nlevels;
169: if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");
171: for (i=1; i<nlevels; i++) {
172: MatDestroy(&dmmg[i]->R);
173: }
174: for (i=0; i<nlevels; i++) {
175: PetscFree(dmmg[i]->prefix);
176: PetscFree(dmmg[i]->mtype);
177: DMDestroy(&dmmg[i]->dm);
178: VecDestroy(&dmmg[i]->x);
179: VecDestroy(&dmmg[i]->b);
180: VecDestroy(&dmmg[i]->r);
181: VecDestroy(&dmmg[i]->work1);
182: VecDestroy(&dmmg[i]->w);
183: VecDestroy(&dmmg[i]->work2);
184: VecDestroy(&dmmg[i]->lwork1);
185: MatDestroy(&dmmg[i]->B);
186: MatDestroy(&dmmg[i]->J);
187: VecDestroy(&dmmg[i]->Rscale);
188: MatFDColoringDestroy(&dmmg[i]->fdcoloring);
189: if (dmmg[i]->ksp && !dmmg[i]->snes) {KSPDestroy(&dmmg[i]->ksp);}
190: PetscObjectDestroy((PetscObject*)&dmmg[i]->snes);
191: VecScatterDestroy(&dmmg[i]->inject);
192: PetscFree(dmmg[i]);
193: }
194: PetscFree(dmmg);
195: return(0);
196: }
200: /*@C
201: DMMGSetDM - Sets the coarse grid information for the grids
203: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
204: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
206: Logically Collective on DMMG and DM
208: Input Parameter:
209: + dmmg - the context
210: - dm - the DMDA or DMComposite object
212: Options Database Keys:
213: . -dmmg_refine: Use the input problem as the coarse level and refine.
214: . -dmmg_refine false: Use the input problem as the fine level and coarsen.
216: Level: advanced
218: .seealso DMMGCreate(), DMMGDestroy(), DMMGSetMatType()
220: @*/
221: PetscErrorCode DMMGSetDM(DMMG *dmmg, DM dm)
222: {
223: PetscInt nlevels = dmmg[0]->nlevels;
224: PetscBool doRefine = PETSC_TRUE;
225: PetscInt i;
226: DM *hierarchy;
230: if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");
232: /* Create DM data structure for all the levels */
233: PetscOptionsGetBool(PETSC_NULL, "-dmmg_refine", &doRefine, PETSC_IGNORE);
234: PetscObjectReference((PetscObject) dm);
235: PetscMalloc(nlevels*sizeof(DM),&hierarchy);
236: if (doRefine) {
237: DMRefineHierarchy(dm,nlevels-1,hierarchy);
238: dmmg[0]->dm = dm;
239: for(i=1; i<nlevels; ++i) {
240: dmmg[i]->dm = hierarchy[i-1];
241: }
242: } else {
243: dmmg[nlevels-1]->dm = dm;
244: DMCoarsenHierarchy(dm,nlevels-1,hierarchy);
245: for(i=0; i<nlevels-1; ++i) {
246: dmmg[nlevels-2-i]->dm = hierarchy[i];
247: }
248: }
249: PetscFree(hierarchy);
250: /* Cleanup old structures (should use some private Destroy() instead) */
251: for(i = 0; i < nlevels; ++i) {
252: MatDestroy(&dmmg[i]->B);
253: MatDestroy(&dmmg[i]->J);
254: }
256: /* Create work vectors and matrix for each level */
257: for (i=0; i<nlevels; i++) {
258: DMCreateGlobalVector(dmmg[i]->dm,&dmmg[i]->x);
259: VecDuplicate(dmmg[i]->x,&dmmg[i]->b);
260: VecDuplicate(dmmg[i]->x,&dmmg[i]->r);
261: }
263: /* Create interpolation/restriction between levels */
264: for (i=1; i<nlevels; i++) {
265: DMGetInterpolation(dmmg[i-1]->dm,dmmg[i]->dm,&dmmg[i]->R,PETSC_NULL);
266: }
267: return(0);
268: }
273: /*@C
274: DMMGSolve - Actually solves the (non)linear system defined with the DMMG
276: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
277: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
279: Collective on DMMG
281: Input Parameter:
282: . dmmg - the context
284: Level: advanced
286: Options Database:
287: + -dmmg_grid_sequence - use grid sequencing to get the initial solution for each level from the previous
288: - -dmmg_monitor_solution - display the solution at each iteration
290: Notes: For linear (KSP) problems may be called more than once, uses the same
291: matrices but recomputes the right hand side for each new solve. Call DMMGSetKSP()
292: to generate new matrices.
293:
294: .seealso DMMGCreate(), DMMGDestroy(), DMMG, DMMGSetSNES(), DMMGSetKSP(), DMMGSetUp(), DMMGSetMatType()
296: @*/
297: PetscErrorCode DMMGSolve(DMMG *dmmg)
298: {
300: PetscInt i,nlevels = dmmg[0]->nlevels;
301: PetscBool gridseq = PETSC_FALSE,vecmonitor = PETSC_FALSE,flg;
304: PetscOptionsGetBool(0,"-dmmg_grid_sequence",&gridseq,PETSC_NULL);
305: PetscOptionsGetBool(0,"-dmmg_monitor_solution",&vecmonitor,PETSC_NULL);
306: if (gridseq) {
307: if (dmmg[0]->initialguess) {
308: (*dmmg[0]->initialguess)(dmmg[0],dmmg[0]->x);
309: if (dmmg[0]->ksp && !dmmg[0]->snes) {
310: KSPSetInitialGuessNonzero(dmmg[0]->ksp,PETSC_TRUE);
311: }
312: }
313: for (i=0; i<nlevels-1; i++) {
314: (*dmmg[i]->solve)(dmmg,i);
315: if (vecmonitor) {
316: VecView(dmmg[i]->x,PETSC_VIEWER_DRAW_(dmmg[i]->comm));
317: }
318: MatInterpolate(dmmg[i+1]->R,dmmg[i]->x,dmmg[i+1]->x);
319: if (dmmg[i+1]->ksp && !dmmg[i+1]->snes) {
320: KSPSetInitialGuessNonzero(dmmg[i+1]->ksp,PETSC_TRUE);
321: }
322: }
323: } else {
324: if (dmmg[nlevels-1]->initialguess) {
325: (*dmmg[nlevels-1]->initialguess)(dmmg[nlevels-1],dmmg[nlevels-1]->x);
326: }
327: }
329: /*VecView(dmmg[nlevels-1]->x,PETSC_VIEWER_DRAW_WORLD);*/
331: (*DMMGGetFine(dmmg)->solve)(dmmg,nlevels-1);
332: if (vecmonitor) {
333: VecView(dmmg[nlevels-1]->x,PETSC_VIEWER_DRAW_(dmmg[nlevels-1]->comm));
334: }
336: flg = PETSC_FALSE;
337: PetscOptionsGetBool(PETSC_NULL,"-dmmg_view",&flg,PETSC_NULL);
338: if (flg && !PetscPreLoadingOn) {
339: PetscViewer viewer;
340: PetscViewerASCIIGetStdout(dmmg[0]->comm,&viewer);
341: DMMGView(dmmg,viewer);
342: }
343: flg = PETSC_FALSE;
344: PetscOptionsGetBool(PETSC_NULL,"-dmmg_view_binary",&flg,PETSC_NULL);
345: if (flg && !PetscPreLoadingOn) {
346: DMMGView(dmmg,PETSC_VIEWER_BINARY_(dmmg[0]->comm));
347: }
348: return(0);
349: }
353: PetscErrorCode DMMGSolveKSP(DMMG *dmmg,PetscInt level)
354: {
358: if (dmmg[level]->rhs) {
359: CHKMEMQ;
360: (*dmmg[level]->rhs)(dmmg[level],dmmg[level]->b);
361: CHKMEMQ;
362: }
363: KSPSolve(dmmg[level]->ksp,dmmg[level]->b,dmmg[level]->x);
364: return(0);
365: }
367: /*
368: For each level (of grid sequencing) this sets the interpolation/restriction and
369: work vectors needed by the multigrid preconditioner within the KSP
370: (for nonlinear problems the KSP inside the SNES) of that level.
372: Also sets the KSP monitoring on all the levels if requested by user.
374: */
377: PetscErrorCode DMMGSetUpLevel(DMMG *dmmg,KSP ksp,PetscInt nlevels)
378: {
379: PetscErrorCode ierr;
380: PetscInt i;
381: PC pc;
382: PetscBool ismg,ismf,isshell,ismffd;
383: KSP lksp; /* solver internal to the multigrid preconditioner */
384: MPI_Comm *comms;
387: if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");
389: /* use fgmres on outer iteration by default */
390: KSPSetType(ksp,KSPFGMRES);
391: KSPGetPC(ksp,&pc);
392: PCSetType(pc,PCMG);
393: PetscMalloc(nlevels*sizeof(MPI_Comm),&comms);
394: for (i=0; i<nlevels; i++) {
395: comms[i] = dmmg[i]->comm;
396: }
397: PCMGSetLevels(pc,nlevels,comms);
398: PetscFree(comms);
399: PCMGSetType(pc,PC_MG_FULL);
401: PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
402: if (ismg) {
403: /* set solvers for each level */
404: for (i=0; i<nlevels; i++) {
405: if (i < nlevels-1) { /* don't set for finest level, they are set in PCApply_MG()*/
406: PCMGSetX(pc,i,dmmg[i]->x);
407: PCMGSetRhs(pc,i,dmmg[i]->b);
408: }
409: if (i > 0) {
410: PCMGSetR(pc,i,dmmg[i]->r);
411: }
412: /* If using a matrix free multiply and did not provide an explicit matrix to build
413: the preconditioner then must use no preconditioner
414: */
415: PetscTypeCompare((PetscObject)dmmg[i]->B,MATSHELL,&isshell);
416: PetscTypeCompare((PetscObject)dmmg[i]->B,MATDAAD,&ismf);
417: PetscTypeCompare((PetscObject)dmmg[i]->B,MATMFFD,&ismffd);
418: if (isshell || ismf || ismffd) {
419: PC lpc;
420: PCMGGetSmoother(pc,i,&lksp);
421: KSPGetPC(lksp,&lpc);
422: PCSetType(lpc,PCNONE);
423: }
424: }
426: /* Set interpolation/restriction between levels */
427: for (i=1; i<nlevels; i++) {
428: PCMGSetInterpolation(pc,i,dmmg[i]->R);
429: PCMGSetRestriction(pc,i,dmmg[i]->R);
430: }
431: }
432: return(0);
433: }
437: /*@C
438: DMMGSetKSP - Sets the linear solver object that will use the grid hierarchy
440: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
441: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
443: Logically Collective on DMMG
445: Input Parameter:
446: + dmmg - the context
447: . func - function to compute linear system matrix on each grid level
448: - rhs - function to compute right hand side on each level (need only work on the finest grid
449: if you do not use grid sequencing)
451: Level: advanced
453: Notes: For linear problems my be called more than once, reevaluates the matrices if it is called more
454: than once. Call DMMGSolve() directly several times to solve with the same matrix but different
455: right hand sides.
456:
457: .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), DMMGSetMatType()
459: @*/
460: PetscErrorCode DMMGSetKSP(DMMG *dmmg,PetscErrorCode (*rhs)(DMMG,Vec),PetscErrorCode (*func)(DMMG,Mat,Mat))
461: {
463: PetscInt i,nlevels = dmmg[0]->nlevels,level;
464: PetscBool ismg,galerkin=PETSC_FALSE;
465: PC pc;
466: KSP lksp;
467:
469: if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");
471: if (!dmmg[0]->ksp) {
472: /* create solvers for each level if they don't already exist*/
473: for (i=0; i<nlevels; i++) {
475: KSPCreate(dmmg[i]->comm,&dmmg[i]->ksp);
476: PetscObjectIncrementTabLevel((PetscObject)dmmg[i]->ksp,PETSC_NULL,nlevels-i);
477: KSPSetOptionsPrefix(dmmg[i]->ksp,dmmg[i]->prefix);
478: DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);
479: KSPSetFromOptions(dmmg[i]->ksp);
481: /* if the multigrid is being run with Galerkin then these matrices do not need to be created except on the finest level
482: we do not take advantage of this because it may be that Galerkin has not yet been selected for the KSP object
483: These are also used if grid sequencing is selected for the linear problem. We should probably turn off grid sequencing
484: for the linear problem */
485: if (!dmmg[i]->B) {
486: DMGetMatrix(dmmg[i]->dm,dmmg[nlevels-1]->mtype,&dmmg[i]->B);
487: }
488: if (!dmmg[i]->J) {
489: dmmg[i]->J = dmmg[i]->B;
490: PetscObjectReference((PetscObject) dmmg[i]->J);
491: }
493: dmmg[i]->solve = DMMGSolveKSP;
494: dmmg[i]->rhs = rhs;
495: }
496: }
498: /* evalute matrix on each level */
499: KSPGetPC(dmmg[nlevels-1]->ksp,&pc);
500: PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
501: if (ismg) {
502: PCMGGetGalerkin(pc,&galerkin);
503: }
504: if (func) {
505: if (galerkin) {
506: (*func)(dmmg[nlevels-1],dmmg[nlevels-1]->J,dmmg[nlevels-1]->B);
507: } else {
508: for (i=0; i<nlevels; i++) {
509: (*func)(dmmg[i],dmmg[i]->J,dmmg[i]->B);
510: }
511: }
512: }
514: for (i=0; i<nlevels-1; i++) {
515: KSPSetOptionsPrefix(dmmg[i]->ksp,"dmmg_");
516: }
518: for (level=0; level<nlevels; level++) {
519: KSPSetOperators(dmmg[level]->ksp,dmmg[level]->J,dmmg[level]->B,SAME_NONZERO_PATTERN);
520: KSPGetPC(dmmg[level]->ksp,&pc);
521: if (ismg) {
522: for (i=0; i<=level; i++) {
523: PCMGGetSmoother(pc,i,&lksp);
524: KSPSetOperators(lksp,dmmg[i]->J,dmmg[i]->B,SAME_NONZERO_PATTERN);
525: }
526: }
527: }
529: return(0);
530: }
534: /*@C
535: DMMGView - prints information on a DM based multi-level preconditioner
537: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
538: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
540: Collective on DMMG and PetscViewer
542: Input Parameter:
543: + dmmg - the context
544: - viewer - the viewer
546: Level: advanced
548: .seealso DMMGCreate(), DMMGDestroy(), DMMGSetMatType()
550: @*/
551: PetscErrorCode DMMGView(DMMG *dmmg,PetscViewer viewer)
552: {
554: PetscInt i,nlevels = dmmg[0]->nlevels;
555: PetscMPIInt flag;
556: MPI_Comm comm;
557: PetscBool iascii,isbinary;
562: PetscObjectGetComm((PetscObject)viewer,&comm);
563: MPI_Comm_compare(comm,dmmg[0]->comm,&flag);
564: if (flag != MPI_CONGRUENT && flag != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the DMMG and the PetscViewer");
566: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
567: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
568: if (isbinary) {
569: for (i=0; i<nlevels; i++) {
570: MatView(dmmg[i]->J,viewer);
571: }
572: for (i=1; i<nlevels; i++) {
573: MatView(dmmg[i]->R,viewer);
574: }
575: } else {
576: if (iascii) {
577: PetscViewerASCIIPrintf(viewer,"DMMG Object with %D levels\n",nlevels);
578: if (dmmg[0]->isctype == IS_COLORING_GLOBAL) {
579: PetscViewerASCIIPrintf(viewer,"Using global (nonghosted) Jacobian coloring computation\n");
580: } else {
581: PetscViewerASCIIPrintf(viewer,"Using ghosted Jacobian coloring computation\n");
582: }
583: }
584: for (i=0; i<nlevels; i++) {
585: PetscViewerASCIIPushTab(viewer);
586: DMView(dmmg[i]->dm,viewer);
587: PetscViewerASCIIPopTab(viewer);
588: }
589: if (iascii) {
590: PetscViewerASCIIPrintf(viewer,"Using matrix type %s\n",dmmg[nlevels-1]->mtype);
591: }
592: if (DMMGGetKSP(dmmg)) {
593: KSPView(DMMGGetKSP(dmmg),viewer);
594: } else if (DMMGGetSNES(dmmg)) {
595: SNESView(DMMGGetSNES(dmmg),viewer);
596: } else if (iascii) {
597: PetscViewerASCIIPrintf(viewer,"DMMG does not have a SNES or KSP set\n");
598: }
599: }
600: return(0);
601: }
605: /*@C
606: DMMGSetNullSpace - Indicates the null space in the linear operator (this is needed by the linear solver)
608: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
609: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
611: Logically Collective on DMMG
613: Input Parameter:
614: + dmmg - the context
615: . has_cnst - is the constant vector in the null space
616: . n - number of null vectors (excluding the possible constant vector)
617: - func - a function that fills an array of vectors with the null vectors (must be orthonormal), may be PETSC_NULL
619: Level: advanced
621: .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), MatNullSpaceCreate(), KSPSetNullSpace(), DMMGSetMatType()
623: @*/
624: PetscErrorCode DMMGSetNullSpace(DMMG *dmmg,PetscBool has_cnst,PetscInt n,PetscErrorCode (*func)(DMMG,Vec[]))
625: {
627: PetscInt i,j,nlevels = dmmg[0]->nlevels;
628: Vec *nulls = 0;
629: MatNullSpace nullsp;
630: KSP iksp;
631: PC pc,ipc;
632: PetscBool ismg,isred;
635: if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");
636: if (!dmmg[0]->ksp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call AFTER DMMGSetKSP() or DMMGSetSNES()");
637: if ((n && !func) || (!n && func)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and func() must be set together");
638: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative number of vectors in null space n = %D",n);
640: for (i=0; i<nlevels; i++) {
641: if (n) {
642: VecDuplicateVecs(dmmg[i]->b,n,&nulls);
643: (*func)(dmmg[i],nulls);
644: }
645: MatNullSpaceCreate(dmmg[i]->comm,has_cnst,n,nulls,&nullsp);
646: KSPSetNullSpace(dmmg[i]->ksp,nullsp);
647: for (j=i; j<nlevels; j++) {
648: KSPGetPC(dmmg[j]->ksp,&pc);
649: PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
650: if (ismg) {
651: PCMGGetSmoother(pc,i,&iksp);
652: KSPSetNullSpace(iksp, nullsp);
653: }
654: }
655: MatNullSpaceDestroy(&nullsp);
656: if (n) {
657: VecDestroyVecs(n,&nulls);
658: }
659: }
660: /* make all the coarse grid solvers have LU shift since they are singular */
661: for (i=0; i<nlevels; i++) {
662: KSPGetPC(dmmg[i]->ksp,&pc);
663: PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
664: if (ismg) {
665: PCMGGetSmoother(pc,0,&iksp);
666: KSPGetPC(iksp,&ipc);
667: PetscTypeCompare((PetscObject)ipc,PCREDUNDANT,&isred);
668: if (isred) {
669: KSP iksp;
670: PCRedundantGetKSP(ipc,&iksp);
671: KSPGetPC(iksp,&ipc);
672: }
673: PCFactorSetShiftType(ipc,MAT_SHIFT_POSITIVE_DEFINITE);
674: }
675: }
676: return(0);
677: }
681: /*@C
682: DMMGInitialGuessCurrent - Use with DMMGSetInitialGuess() to use the current value in the
683: solution vector (obtainable with DMMGGetx()) as the initial guess. Otherwise for linear
684: problems zero is used for the initial guess (unless grid sequencing is used). For nonlinear
685: problems this is not needed; it always uses the previous solution as the initial guess.
687: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
688: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
690: Logically Collective on DMMG
692: Input Parameter:
693: + dmmg - the context
694: - vec - dummy argument
696: Level: intermediate
698: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetInitialGuess()
700: @*/
701: PetscErrorCode DMMGInitialGuessCurrent(DMMG dmmg,Vec vec)
702: {
704: return(0);
705: }
709: /*@C
710: DMMGSetInitialGuess - Sets the function that computes an initial guess.
712: This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems.
713: See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c
715: Logically Collective on DMMG
717: Input Parameter:
718: + dmmg - the context
719: - guess - the function
721: Notes: For nonlinear problems, if this is not set, then the current value in the
722: solution vector (obtained with DMMGGetX()) is used. Thus is if you doing 'time
723: stepping' it will use your current solution as the guess for the next timestep.
724: If grid sequencing is used (via -dmmg_grid_sequence) then the "guess" function
725: is used only on the coarsest grid.
726: For linear problems, if this is not set, then 0 is used as an initial guess.
727: If you would like the linear solver to also (like the nonlinear solver) use
728: the current solution vector as the initial guess then use DMMGInitialGuessCurrent()
729: as the function you pass in
731: Level: intermediate
734: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGInitialGuessCurrent(), DMMGSetGalekin(), DMMGSetMatType(), DMMGSetNullSpace()
736: @*/
737: PetscErrorCode DMMGSetInitialGuess(DMMG *dmmg,PetscErrorCode (*guess)(DMMG,Vec))
738: {
739: PetscInt i,nlevels = dmmg[0]->nlevels;
743: for (i=0; i<nlevels; i++) {
744: if (dmmg[i]->ksp && !dmmg[i]->snes) {
745: KSPSetInitialGuessNonzero(dmmg[i]->ksp,PETSC_TRUE);
746: }
747: dmmg[i]->initialguess = guess;
748: }
749: return(0);
750: }