Actual source code: dmget.c

      1: #include <petsc/private/dmimpl.h>

      3: /*@
      4:   DMGetLocalVector - Gets a PETSc vector that may be used with the `DM` local routines. This vector has spaces for the ghost values.

      6:   Not Collective

      8:   Input Parameter:
      9: . dm - the `DM`

     11:   Output Parameter:
     12: . g - the local vector

     14:   Level: beginner

     16:   Note:
     17:   The vector values are NOT initialized and may have garbage in them, so you may need
     18:   to zero them.

     20:   The output parameter, `g`, is a regular PETSc vector that should be returned with
     21:   `DMRestoreLocalVector()` DO NOT call `VecDestroy()` on it.

     23:   This is intended to be used for vectors you need for a short time, like within a single function call.
     24:   For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your
     25:   code you should use `DMCreateLocalVector()`.

     27:   VecStride*() operations can be useful when using `DM` with dof > 1

     29: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
     30:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
     31:           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`,
     32:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearLocalVectors()`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`
     33: @*/
     34: PetscErrorCode DMGetLocalVector(DM dm, Vec *g)
     35: {
     36:   PetscFunctionBegin;
     38:   PetscAssertPointer(g, 2);
     39:   for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
     40:     if (dm->localin[i]) {
     41:       DM vdm;

     43:       *g             = dm->localin[i];
     44:       dm->localin[i] = NULL;

     46:       PetscCall(VecGetDM(*g, &vdm));
     47:       PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
     48:       PetscCall(VecSetDM(*g, dm));
     49:       goto alldone;
     50:     }
     51:   }
     52:   PetscCall(DMCreateLocalVector(dm, g));

     54: alldone:
     55:   for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
     56:     if (!dm->localout[i]) {
     57:       dm->localout[i] = *g;
     58:       break;
     59:     }
     60:   }
     61:   PetscFunctionReturn(PETSC_SUCCESS);
     62: }

     64: /*@
     65:   DMRestoreLocalVector - Returns a PETSc vector that was
     66:   obtained from `DMGetLocalVector()`. Do not use with vector obtained via
     67:   `DMCreateLocalVector()`.

     69:   Not Collective

     71:   Input Parameters:
     72: + dm - the `DM`
     73: - g  - the local vector

     75:   Level: beginner

     77: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
     78:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
     79:           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMGetLocalVector()`, `DMClearLocalVectors()`
     80: @*/
     81: PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g)
     82: {
     83:   PetscInt i, j;

     85:   PetscFunctionBegin;
     87:   PetscAssertPointer(g, 2);
     88:   for (j = 0; j < DM_MAX_WORK_VECTORS; j++) {
     89:     if (*g == dm->localout[j]) {
     90:       DM vdm;

     92:       PetscCall(VecGetDM(*g, &vdm));
     93:       PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
     94:       PetscCall(VecSetDM(*g, NULL));
     95:       dm->localout[j] = NULL;
     96:       for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
     97:         if (!dm->localin[i]) {
     98:           dm->localin[i] = *g;
     99:           goto alldone;
    100:         }
    101:       }
    102:     }
    103:   }
    104:   PetscCall(VecDestroy(g));
    105: alldone:
    106:   *g = NULL;
    107:   PetscFunctionReturn(PETSC_SUCCESS);
    108: }

    110: /*@
    111:   DMGetGlobalVector - Gets a PETSc vector that may be used with the `DM` global routines.

    113:   Collective

    115:   Input Parameter:
    116: . dm - the `DM`

    118:   Output Parameter:
    119: . g - the global vector

    121:   Level: beginner

    123:   Note:
    124:   The vector values are NOT initialized and may have garbage in them, so you may need
    125:   to zero them.

    127:   The output parameter, `g`, is a regular PETSc vector that should be returned with
    128:   `DMRestoreGlobalVector()` DO NOT call `VecDestroy()` on it.

    130:   This is intended to be used for vectors you need for a short time, like within a single function call.
    131:   For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your
    132:   code you should use `DMCreateGlobalVector()`.

    134:   VecStride*() operations can be useful when using `DM` with dof > 1

    136: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
    137:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
    138:           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
    139:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearGlobalVectors()`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`
    140: @*/
    141: PetscErrorCode DMGetGlobalVector(DM dm, Vec *g)
    142: {
    143:   PetscInt i;

    145:   PetscFunctionBegin;
    147:   PetscAssertPointer(g, 2);
    148:   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
    149:     if (dm->globalin[i]) {
    150:       DM vdm;

    152:       *g              = dm->globalin[i];
    153:       dm->globalin[i] = NULL;

    155:       PetscCall(VecGetDM(*g, &vdm));
    156:       PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
    157:       PetscCall(VecSetDM(*g, dm));
    158:       goto alldone;
    159:     }
    160:   }
    161:   PetscCall(DMCreateGlobalVector(dm, g));

    163: alldone:
    164:   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
    165:     if (!dm->globalout[i]) {
    166:       dm->globalout[i] = *g;
    167:       break;
    168:     }
    169:   }
    170:   PetscFunctionReturn(PETSC_SUCCESS);
    171: }

    173: /*@
    174:   DMClearGlobalVectors - Destroys all the global vectors that have been created for `DMGetGlobalVector()` calls in this `DM`

    176:   Collective

    178:   Input Parameter:
    179: . dm - the `DM`

    181:   Level: developer

    183: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
    184:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
    185:           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
    186:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearLocalVectors()`
    187: @*/
    188: PetscErrorCode DMClearGlobalVectors(DM dm)
    189: {
    190:   PetscInt i;

    192:   PetscFunctionBegin;
    194:   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
    195:     Vec g;

    197:     PetscCheck(!dm->globalout[i], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of global vectors that has a global vector obtained with DMGetGlobalVector()");
    198:     g               = dm->globalin[i];
    199:     dm->globalin[i] = NULL;
    200:     if (g) {
    201:       DM vdm;

    203:       PetscCall(VecGetDM(g, &vdm));
    204:       PetscCheck(!vdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing global vector that has a DM attached");
    205:     }
    206:     PetscCall(VecDestroy(&g));
    207:   }
    208:   PetscFunctionReturn(PETSC_SUCCESS);
    209: }

    211: /*@
    212:   DMClearLocalVectors - Destroys all the local vectors that have been created for `DMGetLocalVector()` calls in this `DM`

    214:   Collective

    216:   Input Parameter:
    217: . dm - the `DM`

    219:   Level: developer

    221: .seealso: `DM`, `DMCreateLocalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
    222:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMLocalToLocalBegin()`,
    223:           `DMLocalToLocalEnd()`, `DMRestoreLocalVector()`
    224:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearGlobalVectors()`
    225: @*/
    226: PetscErrorCode DMClearLocalVectors(DM dm)
    227: {
    228:   PetscInt i;

    230:   PetscFunctionBegin;
    232:   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
    233:     Vec g;

    235:     PetscCheck(!dm->localout[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of local vectors that has a local vector obtained with DMGetLocalVector()");
    236:     g              = dm->localin[i];
    237:     dm->localin[i] = NULL;
    238:     if (g) {
    239:       DM vdm;

    241:       PetscCall(VecGetDM(g, &vdm));
    242:       PetscCheck(!vdm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Clearing local vector that has a DM attached");
    243:     }
    244:     PetscCall(VecDestroy(&g));
    245:   }
    246:   PetscFunctionReturn(PETSC_SUCCESS);
    247: }

    249: /*@
    250:   DMRestoreGlobalVector - Returns a PETSc vector that
    251:   obtained from `DMGetGlobalVector()`. Do not use with vector obtained via
    252:   `DMCreateGlobalVector()`.

    254:   Not Collective

    256:   Input Parameters:
    257: + dm - the `DM`
    258: - g  - the global vector

    260:   Level: beginner

    262: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
    263:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToGlobalBegin()`,
    264:           `DMGlobalToGlobalEnd()`, `DMGlobalToGlobal()`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMClearGlobalVectors()`
    265: @*/
    266: PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g)
    267: {
    268:   PetscInt i, j;

    270:   PetscFunctionBegin;
    272:   PetscAssertPointer(g, 2);
    273:   PetscCall(VecSetErrorIfLocked(*g, 2));
    274:   for (j = 0; j < DM_MAX_WORK_VECTORS; j++) {
    275:     if (*g == dm->globalout[j]) {
    276:       DM vdm;

    278:       PetscCall(VecGetDM(*g, &vdm));
    279:       PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
    280:       PetscCall(VecSetDM(*g, NULL));
    281:       dm->globalout[j] = NULL;
    282:       for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
    283:         if (!dm->globalin[i]) {
    284:           dm->globalin[i] = *g;
    285:           goto alldone;
    286:         }
    287:       }
    288:     }
    289:   }
    290:   PetscCall(VecDestroy(g));
    291: alldone:
    292:   *g = NULL;
    293:   PetscFunctionReturn(PETSC_SUCCESS);
    294: }

    296: /*@
    297:   DMClearNamedGlobalVectors - Destroys all the named global vectors that have been created with `DMGetNamedGlobalVector()` in this `DM`

    299:   Collective

    301:   Input Parameter:
    302: . dm - the `DM`

    304:   Level: developer

    306: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
    307: @*/
    308: PetscErrorCode DMClearNamedGlobalVectors(DM dm)
    309: {
    310:   DMNamedVecLink nnext;

    312:   PetscFunctionBegin;
    314:   nnext           = dm->namedglobal;
    315:   dm->namedglobal = NULL;
    316:   for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
    317:     nnext = nlink->next;
    318:     PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has global Vec named '%s' checked out", nlink->name);
    319:     PetscCall(PetscFree(nlink->name));
    320:     PetscCall(VecDestroy(&nlink->X));
    321:     PetscCall(PetscFree(nlink));
    322:   }
    323:   PetscFunctionReturn(PETSC_SUCCESS);
    324: }

    326: /*@
    327:   DMClearNamedLocalVectors - Destroys all the named local vectors that have been created with `DMGetNamedLocalVector()` in this `DM`

    329:   Collective

    331:   Input Parameter:
    332: . dm - the `DM`

    334:   Level: developer

    336: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedGlobalVectors()`
    337: @*/
    338: PetscErrorCode DMClearNamedLocalVectors(DM dm)
    339: {
    340:   DMNamedVecLink nnext;

    342:   PetscFunctionBegin;
    344:   nnext          = dm->namedlocal;
    345:   dm->namedlocal = NULL;
    346:   for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
    347:     nnext = nlink->next;
    348:     PetscCheck(nlink->status == DMVEC_STATUS_IN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM still has local Vec named '%s' checked out", nlink->name);
    349:     PetscCall(PetscFree(nlink->name));
    350:     PetscCall(VecDestroy(&nlink->X));
    351:     PetscCall(PetscFree(nlink));
    352:   }
    353:   PetscFunctionReturn(PETSC_SUCCESS);
    354: }

    356: /*@
    357:   DMHasNamedGlobalVector - check for a named, persistent global vector created with `DMGetNamedGlobalVector()`

    359:   Not Collective

    361:   Input Parameters:
    362: + dm   - `DM` to hold named vectors
    363: - name - unique name for `Vec`

    365:   Output Parameter:
    366: . exists - true if the vector was previously created

    368:   Level: developer

    370: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedGlobalVectors()`
    371: @*/
    372: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
    373: {
    374:   DMNamedVecLink link;

    376:   PetscFunctionBegin;
    378:   PetscAssertPointer(name, 2);
    379:   PetscAssertPointer(exists, 3);
    380:   *exists = PETSC_FALSE;
    381:   for (link = dm->namedglobal; link; link = link->next) {
    382:     PetscBool match;
    383:     PetscCall(PetscStrcmp(name, link->name, &match));
    384:     if (match) {
    385:       *exists = PETSC_TRUE;
    386:       break;
    387:     }
    388:   }
    389:   PetscFunctionReturn(PETSC_SUCCESS);
    390: }

    392: /*@
    393:   DMGetNamedGlobalVector - get access to a named, persistent global vector

    395:   Collective

    397:   Input Parameters:
    398: + dm   - `DM` to hold named vectors
    399: - name - unique name for `X`

    401:   Output Parameter:
    402: . X - named `Vec`

    404:   Level: developer

    406:   Note:
    407:   If a `Vec` with the given name does not exist, it is created.

    409: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMHasNamedGlobalVector()`, `DMClearNamedGlobalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
    410: @*/
    411: PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
    412: {
    413:   DMNamedVecLink link;

    415:   PetscFunctionBegin;
    417:   PetscAssertPointer(name, 2);
    418:   PetscAssertPointer(X, 3);
    419:   for (link = dm->namedglobal; link; link = link->next) {
    420:     PetscBool match;

    422:     PetscCall(PetscStrcmp(name, link->name, &match));
    423:     if (match) {
    424:       DM vdm;

    426:       PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
    427:       PetscCall(VecGetDM(link->X, &vdm));
    428:       PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
    429:       PetscCall(VecSetDM(link->X, dm));
    430:       goto found;
    431:     }
    432:   }

    434:   /* Create the Vec */
    435:   PetscCall(PetscNew(&link));
    436:   PetscCall(PetscStrallocpy(name, &link->name));
    437:   PetscCall(DMCreateGlobalVector(dm, &link->X));
    438:   link->next      = dm->namedglobal;
    439:   dm->namedglobal = link;

    441: found:
    442:   *X           = link->X;
    443:   link->status = DMVEC_STATUS_OUT;
    444:   PetscFunctionReturn(PETSC_SUCCESS);
    445: }

    447: /*@
    448:   DMRestoreNamedGlobalVector - restore access to a named, persistent global vector

    450:   Collective

    452:   Input Parameters:
    453: + dm   - `DM` on which `X` was gotten
    454: . name - name under which `X` was gotten
    455: - X    - `Vec` to restore

    457:   Level: developer

    459: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMClearNamedGlobalVectors()`
    460: @*/
    461: PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
    462: {
    463:   DMNamedVecLink link;

    465:   PetscFunctionBegin;
    467:   PetscAssertPointer(name, 2);
    468:   PetscAssertPointer(X, 3);
    470:   for (link = dm->namedglobal; link; link = link->next) {
    471:     PetscBool match;

    473:     PetscCall(PetscStrcmp(name, link->name, &match));
    474:     if (match) {
    475:       DM vdm;

    477:       PetscCall(VecGetDM(*X, &vdm));
    478:       PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
    479:       PetscCheck(link->X == *X, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Attempt to restore Vec name '%s', but Vec does not match the cache", name);
    480:       PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");

    482:       link->status = DMVEC_STATUS_IN;
    483:       PetscCall(VecSetDM(link->X, NULL));
    484:       *X = NULL;
    485:       PetscFunctionReturn(PETSC_SUCCESS);
    486:     }
    487:   }
    488:   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
    489: }

    491: /*@
    492:   DMHasNamedLocalVector - check for a named, persistent local vector created with `DMGetNamedLocalVector()`

    494:   Not Collective

    496:   Input Parameters:
    497: + dm   - `DM` to hold named vectors
    498: - name - unique name for `Vec`

    500:   Output Parameter:
    501: . exists - true if the vector was previously created

    503:   Level: developer

    505:   Note:
    506:   If a `Vec` with the given name does not exist, it is created.

    508: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedLocalVectors()`
    509: @*/
    510: PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
    511: {
    512:   DMNamedVecLink link;

    514:   PetscFunctionBegin;
    516:   PetscAssertPointer(name, 2);
    517:   PetscAssertPointer(exists, 3);
    518:   *exists = PETSC_FALSE;
    519:   for (link = dm->namedlocal; link; link = link->next) {
    520:     PetscBool match;
    521:     PetscCall(PetscStrcmp(name, link->name, &match));
    522:     if (match) {
    523:       *exists = PETSC_TRUE;
    524:       break;
    525:     }
    526:   }
    527:   PetscFunctionReturn(PETSC_SUCCESS);
    528: }

    530: /*@
    531:   DMGetNamedLocalVector - get access to a named, persistent local vector

    533:   Not Collective

    535:   Input Parameters:
    536: + dm   - `DM` to hold named vectors
    537: - name - unique name for `X`

    539:   Output Parameter:
    540: . X - named `Vec`

    542:   Level: developer

    544:   Note:
    545:   If a `Vec` with the given name does not exist, it is created.

    547: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMHasNamedLocalVector()`, `DMClearNamedLocalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
    548: @*/
    549: PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
    550: {
    551:   DMNamedVecLink link;

    553:   PetscFunctionBegin;
    555:   PetscAssertPointer(name, 2);
    556:   PetscAssertPointer(X, 3);
    557:   for (link = dm->namedlocal; link; link = link->next) {
    558:     PetscBool match;

    560:     PetscCall(PetscStrcmp(name, link->name, &match));
    561:     if (match) {
    562:       DM vdm;

    564:       PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
    565:       PetscCall(VecGetDM(link->X, &vdm));
    566:       PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
    567:       PetscCall(VecSetDM(link->X, dm));
    568:       goto found;
    569:     }
    570:   }

    572:   /* Create the Vec */
    573:   PetscCall(PetscNew(&link));
    574:   PetscCall(PetscStrallocpy(name, &link->name));
    575:   PetscCall(DMCreateLocalVector(dm, &link->X));
    576:   link->next     = dm->namedlocal;
    577:   dm->namedlocal = link;

    579: found:
    580:   *X           = link->X;
    581:   link->status = DMVEC_STATUS_OUT;
    582:   PetscFunctionReturn(PETSC_SUCCESS);
    583: }

    585: /*@
    586:   DMRestoreNamedLocalVector - restore access to a named, persistent local vector obtained with `DMGetNamedLocalVector()`

    588:   Not Collective

    590:   Input Parameters:
    591: + dm   - `DM` on which `X` was gotten
    592: . name - name under which `X` was gotten
    593: - X    - `Vec` to restore

    595:   Level: developer

    597: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
    598: @*/
    599: PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
    600: {
    601:   DMNamedVecLink link;

    603:   PetscFunctionBegin;
    605:   PetscAssertPointer(name, 2);
    606:   PetscAssertPointer(X, 3);
    608:   for (link = dm->namedlocal; link; link = link->next) {
    609:     PetscBool match;

    611:     PetscCall(PetscStrcmp(name, link->name, &match));
    612:     if (match) {
    613:       DM vdm;

    615:       PetscCall(VecGetDM(*X, &vdm));
    616:       PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
    617:       PetscCheck(link->X == *X, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Attempt to restore Vec name '%s', but Vec does not match the cache", name);
    618:       PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");

    620:       link->status = DMVEC_STATUS_IN;
    621:       PetscCall(VecSetDM(link->X, NULL));
    622:       *X = NULL;
    623:       PetscFunctionReturn(PETSC_SUCCESS);
    624:     }
    625:   }
    626:   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
    627: }