Actual source code: dmshell.c
petsc-3.7.1 2016-05-15
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: }