Actual source code: dmshell.c

petsc-3.7.3 2016-08-01
Report Typos and Errors
  1: #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
  2: #include <petscmat.h>
  3: #include <petsc/private/dmimpl.h>

  5: typedef struct  {
  6:   Vec        Xglobal;
  7:   Vec        Xlocal;
  8:   Mat        A;
  9:   VecScatter gtol;
 10:   VecScatter ltog;
 11:   VecScatter ltol;
 12:   void       *ctx;
 13: } DM_Shell;

 17: /*@
 18:    DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
 19:    Collective

 21:    Input Arguments:
 22: +  dm - shell DM
 23: .  g - global vector
 24: .  mode - InsertMode
 25: -  l - local vector

 27:    Level: advanced

 29:    Note:  This is not normally called directly by user code, generally user code calls DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function. 

 31: .seealso: DMGlobalToLocalEndDefaultShell()
 32: @*/
 33: PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
 34: {
 36:   DM_Shell       *shell = (DM_Shell*)dm->data;

 39:   if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
 40:   VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);
 41:   return(0);
 42: }

 46: /*@
 47:    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
 48:    Collective

 50:    Input Arguments:
 51: +  dm - shell DM
 52: .  g - global vector
 53: .  mode - InsertMode
 54: -  l - local vector

 56:    Level: advanced

 58: .seealso: DMGlobalToLocalBeginDefaultShell()
 59: @*/
 60: PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
 61: {
 63:   DM_Shell       *shell = (DM_Shell*)dm->data;

 66:    if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
 67:   VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);
 68:   return(0);
 69: }

 73: /*@
 74:    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
 75:    Collective

 77:    Input Arguments:
 78: +  dm - shell DM
 79: .  l - local vector
 80: .  mode - InsertMode
 81: -  g - global vector

 83:    Level: advanced

 85:    Note:  This is not normally called directly by user code, generally user code calls DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function. 

 87: .seealso: DMLocalToGlobalEndDefaultShell()
 88: @*/
 89: PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
 90: {
 92:   DM_Shell       *shell = (DM_Shell*)dm->data;

 95:   if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
 96:   VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);
 97:   return(0);
 98: }

102: /*@
103:    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
104:    Collective

106:    Input Arguments:
107: +  dm - shell DM
108: .  l - local vector
109: .  mode - InsertMode
110: -  g - global vector

112:    Level: advanced

114: .seealso: DMLocalToGlobalBeginDefaultShell()
115: @*/
116: PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
117: {
119:   DM_Shell       *shell = (DM_Shell*)dm->data;

122:    if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
123:   VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);
124:   return(0);
125: }

129: /*@
130:    DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter
131:    Collective

133:    Input Arguments:
134: +  dm - shell DM
135: .  g - the original local vector
136: -  mode - InsertMode

138:    Output Parameter:
139: .  l  - the local vector with correct ghost values

141:    Level: advanced

143:    Note:  This is not normally called directly by user code, generally user code calls DMLocalToLocalBegin() and DMLocalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToLocal() then those routines might have reason to call this function. 

145: .seealso: DMLocalToLocalEndDefaultShell()
146: @*/
147: PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
148: {
150:   DM_Shell       *shell = (DM_Shell*)dm->data;

153:   if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
154:   VecScatterBegin(shell->ltol,g,l,mode,SCATTER_FORWARD);
155:   return(0);
156: }

160: /*@
161:    DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter
162:    Collective

164:    Input Arguments:
165: +  dm - shell DM
166: .  g - the original local vector
167: -  mode - InsertMode

169:    Output Parameter:
170: .  l  - the local vector with correct ghost values

172:    Level: advanced

174: .seealso: DMLocalToLocalBeginDefaultShell()
175: @*/
176: PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
177: {
179:   DM_Shell       *shell = (DM_Shell*)dm->data;

182:    if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
183:   VecScatterEnd(shell->ltol,g,l,mode,SCATTER_FORWARD);
184:   return(0);
185: }

189: static PetscErrorCode DMCreateMatrix_Shell(DM dm,Mat *J)
190: {
192:   DM_Shell       *shell = (DM_Shell*)dm->data;
193:   Mat            A;

198:   if (!shell->A) {
199:     if (shell->Xglobal) {
200:       PetscInt m,M;
201:       PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation\n");
202:       VecGetSize(shell->Xglobal,&M);
203:       VecGetLocalSize(shell->Xglobal,&m);
204:       MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);
205:       MatSetSizes(shell->A,m,m,M,M);
206:       MatSetType(shell->A,dm->mattype);
207:       MatSetUp(shell->A);
208:     } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
209:   }
210:   A = shell->A;
211:   /* the check below is tacky and incomplete */
212:   if (dm->mattype) {
213:     PetscBool flg,aij,seqaij,mpiaij;
214:     PetscObjectTypeCompare((PetscObject)A,dm->mattype,&flg);
215:     PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);
216:     PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);
217:     PetscStrcmp(dm->mattype,MATAIJ,&aij);
218:     if (!flg) {
219:       if (!(aij && (seqaij || mpiaij))) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",dm->mattype,((PetscObject)A)->type_name);
220:     }
221:   }
222:   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
223:     PetscObjectReference((PetscObject)A);
224:     MatZeroEntries(A);
225:     *J   = A;
226:   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
227:     MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);
228:     MatZeroEntries(*J);
229:   }
230:   return(0);
231: }

235: PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
236: {
238:   DM_Shell       *shell = (DM_Shell*)dm->data;
239:   Vec            X;

244:   *gvec = 0;
245:   X     = shell->Xglobal;
246:   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
247:   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
248:     PetscObjectReference((PetscObject)X);
249:     VecZeroEntries(X);
250:     *gvec = X;
251:   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
252:     VecDuplicate(X,gvec);
253:     VecZeroEntries(*gvec);
254:   }
255:   VecSetDM(*gvec,dm);
256:   return(0);
257: }

261: PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
262: {
264:   DM_Shell       *shell = (DM_Shell*)dm->data;
265:   Vec            X;

270:   *gvec = 0;
271:   X     = shell->Xlocal;
272:   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
273:   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
274:     PetscObjectReference((PetscObject)X);
275:     VecZeroEntries(X);
276:     *gvec = X;
277:   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
278:     VecDuplicate(X,gvec);
279:     VecZeroEntries(*gvec);
280:   }
281:   VecSetDM(*gvec,dm);
282:   return(0);
283: }

287: /*@
288:    DMShellSetContext - set some data to be usable by this DM

290:    Collective

292:    Input Arguments:
293: +  dm - shell DM
294: -  ctx - the context

296:    Level: advanced

298: .seealso: DMCreateMatrix(), DMShellGetContext()
299: @*/
300: PetscErrorCode DMShellSetContext(DM dm,void *ctx)
301: {
302:   DM_Shell       *shell = (DM_Shell*)dm->data;
304:   PetscBool      isshell;

308:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
309:   if (!isshell) return(0);
310:   shell->ctx = ctx;
311:   return(0);
312: }

316: /*@
317:    DMShellGetContext - set some data to be usable by this DM

319:    Collective

321:    Input Argument:
322: .  dm - shell DM

324:    Output Argument:
325: .  ctx - the context

327:    Level: advanced

329: .seealso: DMCreateMatrix(), DMShellSetContext()
330: @*/
331: PetscErrorCode DMShellGetContext(DM dm,void **ctx)
332: {
333:   DM_Shell       *shell = (DM_Shell*)dm->data;
335:   PetscBool      isshell;

339:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
340:   if (!isshell) return(0);
341:   *ctx = shell->ctx;
342:   return(0);
343: }

347: /*@
348:    DMShellSetMatrix - sets a template matrix associated with the DMShell

350:    Collective

352:    Input Arguments:
353: +  dm - shell DM
354: -  J - template matrix

356:    Level: advanced

358: .seealso: DMCreateMatrix(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
359: @*/
360: PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
361: {
362:   DM_Shell       *shell = (DM_Shell*)dm->data;
364:   PetscBool      isshell;

369:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
370:   if (!isshell) return(0);
371:   PetscObjectReference((PetscObject)J);
372:   MatDestroy(&shell->A);
373:   shell->A = J;
374:   return(0);
375: }

379: /*@C
380:    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM

382:    Logically Collective on DM

384:    Input Arguments:
385: +  dm - the shell DM
386: -  func - the function to create a matrix

388:    Level: advanced

390: .seealso: DMCreateMatrix(), DMShellSetMatrix(), DMShellSetContext(), DMShellGetContext()
391: @*/
392: PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,Mat*))
393: {

397:   dm->ops->creatematrix = func;
398:   return(0);
399: }

403: /*@
404:    DMShellSetGlobalVector - sets a template global vector associated with the DMShell

406:    Logically Collective on DM

408:    Input Arguments:
409: +  dm - shell DM
410: -  X - template vector

412:    Level: advanced

414: .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
415: @*/
416: PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
417: {
418:   DM_Shell       *shell = (DM_Shell*)dm->data;
420:   PetscBool      isshell;

425:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
426:   if (!isshell) return(0);
427:   PetscObjectReference((PetscObject)X);
428:   VecDestroy(&shell->Xglobal);
429:   shell->Xglobal = X;
430:   return(0);
431: }

435: /*@C
436:    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM

438:    Logically Collective

440:    Input Arguments:
441: +  dm - the shell DM
442: -  func - the creation routine

444:    Level: advanced

446: .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
447: @*/
448: PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
449: {

453:   dm->ops->createglobalvector = func;
454:   return(0);
455: }

459: /*@
460:    DMShellSetLocalVector - sets a template local vector associated with the DMShell

462:    Logically Collective on DM

464:    Input Arguments:
465: +  dm - shell DM
466: -  X - template vector

468:    Level: advanced

470: .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
471: @*/
472: PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
473: {
474:   DM_Shell       *shell = (DM_Shell*)dm->data;
476:   PetscBool      isshell;

481:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
482:   if (!isshell) return(0);
483:   PetscObjectReference((PetscObject)X);
484:   VecDestroy(&shell->Xlocal);
485:   shell->Xlocal = X;
486:   return(0);
487: }

491: /*@C
492:    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM

494:    Logically Collective

496:    Input Arguments:
497: +  dm - the shell DM
498: -  func - the creation routine

500:    Level: advanced

502: .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix(), DMShellSetContext(), DMShellGetContext()
503: @*/
504: PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
505: {

509:   dm->ops->createlocalvector = func;
510:   return(0);
511: }

515: /*@C
516:    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter

518:    Logically Collective on DM

520:    Input Arguments
521: +  dm - the shell DM
522: .  begin - the routine that begins the global to local scatter
523: -  end - the routine that ends the global to local scatter

525:    Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
526:    DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers 

528:    Level: advanced

530: .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
531: @*/
532: PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
534:   dm->ops->globaltolocalbegin = begin;
535:   dm->ops->globaltolocalend = end;
536:   return(0);
537: }

541: /*@C
542:    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter

544:    Logically Collective on DM

546:    Input Arguments
547: +  dm - the shell DM
548: .  begin - the routine that begins the local to global scatter
549: -  end - the routine that ends the local to global scatter

551:    Notes: If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then
552:    DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers 

554:    Level: advanced

556: .seealso: DMShellSetGlobalToLocal()
557: @*/
558: PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
560:   dm->ops->localtoglobalbegin = begin;
561:   dm->ops->localtoglobalend = end;
562:   return(0);
563: }

567: /*@C
568:    DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter

570:    Logically Collective on DM

572:    Input Arguments
573: +  dm - the shell DM
574: .  begin - the routine that begins the local to local scatter
575: -  end - the routine that ends the local to local scatter

577:    Notes: If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then
578:    DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers 

580:    Level: advanced

582: .seealso: DMShellSetGlobalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
583: @*/
584: PetscErrorCode DMShellSetLocalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
586:   dm->ops->localtolocalbegin = begin;
587:   dm->ops->localtolocalend = end;
588:   return(0);
589: }

593: /*@
594:    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication

596:    Logically Collective on DM

598:    Input Arguments
599: +  dm - the shell DM
600: -  gtol - the global to local VecScatter context

602:    Level: advanced

604: .seealso: DMShellSetGlobalToLocal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
605: @*/
606: PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
607: {
608:   DM_Shell       *shell = (DM_Shell*)dm->data;

612:   PetscObjectReference((PetscObject)gtol);
613:   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
614:   VecScatterDestroy(&shell->gtol);
615:   shell->gtol = gtol;
616:   return(0);
617: }

621: /*@
622:    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication

624:    Logically Collective on DM

626:    Input Arguments
627: +  dm - the shell DM
628: -  ltog - the local to global VecScatter context

630:    Level: advanced

632: .seealso: DMShellSetLocalToGlobal(), DMLocalToGlobalBeginDefaultShell(), DMLocalToGlobalEndDefaultShell()
633: @*/
634: PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
635: {
636:   DM_Shell       *shell = (DM_Shell*)dm->data;

640:   PetscObjectReference((PetscObject)ltog);
641:   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
642:   VecScatterDestroy(&shell->ltog);
643:   shell->ltog = ltog;
644:   return(0);
645: }

649: /*@
650:    DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication

652:    Logically Collective on DM

654:    Input Arguments
655: +  dm - the shell DM
656: -  ltol - the local to local VecScatter context

658:    Level: advanced

660: .seealso: DMShellSetLocalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
661: @*/
662: PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol)
663: {
664:   DM_Shell       *shell = (DM_Shell*)dm->data;

668:   PetscObjectReference((PetscObject)ltol);
669:   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
670:   VecScatterDestroy(&shell->ltol);
671:   shell->ltol = ltol;
672:   return(0);
673: }

677: /*@C
678:    DMShellSetCoarsen - Set the routine used to coarsen the shell DM

680:    Logically Collective on DM

682:    Input Arguments
683: +  dm - the shell DM
684: -  coarsen - the routine that coarsens the DM

686:    Level: advanced

688: .seealso: DMShellSetRefine(), DMCoarsen(), DMShellSetContext(), DMShellGetContext()
689: @*/
690: PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM,MPI_Comm,DM*))
691: {
693:   PetscBool      isshell;

697:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
698:   if (!isshell) return(0);
699:   dm->ops->coarsen = coarsen;
700:   return(0);
701: }

705: /*@C
706:    DMShellSetRefine - Set the routine used to refine the shell DM

708:    Logically Collective on DM

710:    Input Arguments
711: +  dm - the shell DM
712: -  refine - the routine that refines the DM

714:    Level: advanced

716: .seealso: DMShellSetCoarsen(), DMRefine(), DMShellSetContext(), DMShellGetContext()
717: @*/
718: PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM,MPI_Comm,DM*))
719: {
721:   PetscBool      isshell;

725:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
726:   if (!isshell) return(0);
727:   dm->ops->refine = refine;
728:   return(0);
729: }

733: /*@C
734:    DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator

736:    Logically Collective on DM

738:    Input Arguments
739: +  dm - the shell DM
740: -  interp - the routine to create the interpolation

742:    Level: advanced

744: .seealso: DMShellSetCreateInjection(), DMCreateInterpolation(), DMShellSetCreateRestriction(), DMShellSetContext(), DMShellGetContext()
745: @*/
746: PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM,DM,Mat*,Vec*))
747: {
749:   PetscBool      isshell;

753:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
754:   if (!isshell) return(0);
755:   dm->ops->createinterpolation = interp;
756:   return(0);
757: }

761: /*@C
762:    DMShellSetCreateRestriction - Set the routine used to create the restriction operator

764:    Logically Collective on DM

766:    Input Arguments
767: +  dm - the shell DM
768: -  striction- the routine to create the restriction

770:    Level: advanced

772: .seealso: DMShellSetCreateInjection(), DMCreateInterpolation(), DMShellSetContext(), DMShellGetContext()
773: @*/
774: PetscErrorCode DMShellSetCreateRestriction(DM dm, PetscErrorCode (*restriction)(DM,DM,Mat*))
775: {
777:   PetscBool      isshell;

781:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
782:   if (!isshell) return(0);
783:   dm->ops->createrestriction = restriction;
784:   return(0);
785: }

789: /*@C
790:    DMShellSetCreateInjection - Set the routine used to create the injection operator

792:    Logically Collective on DM

794:    Input Arguments
795: +  dm - the shell DM
796: -  inject - the routine to create the injection

798:    Level: advanced

800: .seealso: DMShellSetCreateInterpolation(), DMCreateInjection(), DMShellSetContext(), DMShellGetContext()
801: @*/
802: PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM,DM,Mat*))
803: {
805:   PetscBool      isshell;

809:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
810:   if (!isshell) return(0);
811:   dm->ops->getinjection = inject;
812:   return(0);
813: }

817: /*@C
818:    DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the shell DM

820:    Logically Collective on DM

822:    Input Arguments
823: +  dm - the shell DM
824: -  decomp - the routine to create the decomposition

826:    Level: advanced

828: .seealso: DMCreateFieldDecomposition(), DMShellSetContext(), DMShellGetContext()
829: @*/
830: PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM,PetscInt*,char***, IS**,DM**))
831: {
833:   PetscBool      isshell;

837:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
838:   if (!isshell) return(0);
839:   dm->ops->createfielddecomposition = decomp;
840:   return(0);
841: }

843: /*@C
844:    DMShellSetCreateSubDM - Set the routine used to create a sub DM from the shell DM

846:    Logically Collective on DM

848:    Input Arguments
849: +  dm - the shell DM
850: -  subdm - the routine to create the decomposition

852:    Level: advanced

854: .seealso: DMCreateSubDM(), DMShellSetContext(), DMShellGetContext()
855: @*/
858: PetscErrorCode DMShellSetCreateSubDM(DM dm, PetscErrorCode (*subdm)(DM,PetscInt,PetscInt[],IS*,DM*))
859: {
861:   PetscBool      isshell;

865:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
866:   if (!isshell) return(0);
867:   dm->ops->createsubdm = subdm;
868:   return(0);
869: }

873: static PetscErrorCode DMDestroy_Shell(DM dm)
874: {
876:   DM_Shell       *shell = (DM_Shell*)dm->data;

879:   MatDestroy(&shell->A);
880:   VecDestroy(&shell->Xglobal);
881:   VecDestroy(&shell->Xlocal);
882:   VecScatterDestroy(&shell->gtol);
883:   VecScatterDestroy(&shell->ltog);
884:   VecScatterDestroy(&shell->ltol);
885:   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
886:   PetscFree(shell);
887:   return(0);
888: }

892: static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
893: {
895:   DM_Shell       *shell = (DM_Shell*)dm->data;

898:   VecView(shell->Xglobal,v);
899:   return(0);
900: }

904: static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
905: {
907:   DM_Shell       *shell = (DM_Shell*)dm->data;

910:   VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);
911:   VecLoad(shell->Xglobal,v);
912:   return(0);
913: }

917: PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
918: {

922:   if (subdm) {DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);}
923:   DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);
924:   return(0);
925: }

929: PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
930: {
932:   DM_Shell       *shell;

935:   PetscNewLog(dm,&shell);
936:   dm->data = shell;

938:   PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);

940:   dm->ops->destroy            = DMDestroy_Shell;
941:   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
942:   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
943:   dm->ops->creatematrix       = DMCreateMatrix_Shell;
944:   dm->ops->view               = DMView_Shell;
945:   dm->ops->load               = DMLoad_Shell;
946:   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
947:   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
948:   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
949:   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
950:   dm->ops->localtolocalbegin  = DMLocalToLocalBeginDefaultShell;
951:   dm->ops->localtolocalend    = DMLocalToLocalEndDefaultShell;
952:   dm->ops->createsubdm        = DMCreateSubDM_Shell;
953:   return(0);
954: }

958: /*@
959:     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data

961:     Collective on MPI_Comm

963:     Input Parameter:
964: .   comm - the processors that will share the global vector

966:     Output Parameters:
967: .   shell - the shell DM

969:     Level: advanced

971: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector(), DMShellSetContext(), DMShellGetContext()
972: @*/
973: PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
974: {

979:   DMCreate(comm,dm);
980:   DMSetType(*dm,DMSHELL);
981:   DMSetUp(*dm);
982:   return(0);
983: }