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: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
 30:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
 31:           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`,
 32:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
 33: @*/
 34: PetscErrorCode DMGetLocalVector(DM dm, Vec *g)
 35: {
 36:   PetscFunctionBegin;
 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()`
 80: @*/
 81: PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g)
 82: {
 83:   PetscInt i, j;

 85:   PetscFunctionBegin;
 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 on dm

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()`
140: @*/
141: PetscErrorCode DMGetGlobalVector(DM dm, Vec *g)
142: {
143:   PetscInt i;

145:   PetscFunctionBegin;
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 stashed in this DM

176:    Collective on dm

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

181:    Level: developer

183: .seealso: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
184:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
185:           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
186:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
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 stashed in this DM

214:    Collective on dm

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

219:    Level: developer

221: .seealso: `DMCreateLocalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
222:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMLocalToLocalBegin()`,
223:           `DMLocalToLocalEnd()`, `DMLocalToLocalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
224:           `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
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], PetscObjectComm((PetscObject)dm), 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, PetscObjectComm((PetscObject)dm), 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: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
263:           `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToGlobalBegin()`,
264:           `DMGlobalToGlobalEnd()`, `DMGlobalToGlobal()`, `DMCreateLocalVector()`, `DMGetGlobalVector()`
265: @*/
266: PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g)
267: {
268:   PetscInt i, j;

270:   PetscFunctionBegin;
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: /*@C
297:    DMHasNamedGlobalVector - check for a named, persistent global vector

299:    Not Collective

301:    Input Parameters:
302: +  dm - DM to hold named vectors
303: -  name - unique name for Vec

305:    Output Parameter:
306: .  exists - true if the vector was previously created

308:    Level: developer

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

312: .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
313: @*/
314: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
315: {
316:   DMNamedVecLink link;

318:   PetscFunctionBegin;
322:   *exists = PETSC_FALSE;
323:   for (link = dm->namedglobal; link; link = link->next) {
324:     PetscBool match;
325:     PetscCall(PetscStrcmp(name, link->name, &match));
326:     if (match) {
327:       *exists = PETSC_TRUE;
328:       break;
329:     }
330:   }
331:   PetscFunctionReturn(PETSC_SUCCESS);
332: }

334: /*@C
335:    DMGetNamedGlobalVector - get access to a named, persistent global vector

337:    Collective on dm

339:    Input Parameters:
340: +  dm - DM to hold named vectors
341: -  name - unique name for Vec

343:    Output Parameter:
344: .  X - named Vec

346:    Level: developer

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

350: .seealso: `DMRestoreNamedGlobalVector()`
351: @*/
352: PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
353: {
354:   DMNamedVecLink link;

356:   PetscFunctionBegin;
360:   for (link = dm->namedglobal; link; link = link->next) {
361:     PetscBool match;

363:     PetscCall(PetscStrcmp(name, link->name, &match));
364:     if (match) {
365:       DM vdm;

367:       PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
368:       PetscCall(VecGetDM(link->X, &vdm));
369:       PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
370:       PetscCall(VecSetDM(link->X, dm));
371:       goto found;
372:     }
373:   }

375:   /* Create the Vec */
376:   PetscCall(PetscNew(&link));
377:   PetscCall(PetscStrallocpy(name, &link->name));
378:   PetscCall(DMCreateGlobalVector(dm, &link->X));
379:   link->next      = dm->namedglobal;
380:   dm->namedglobal = link;

382: found:
383:   *X           = link->X;
384:   link->status = DMVEC_STATUS_OUT;
385:   PetscFunctionReturn(PETSC_SUCCESS);
386: }

388: /*@C
389:    DMRestoreNamedGlobalVector - restore access to a named, persistent global vector

391:    Collective on dm

393:    Input Parameters:
394: +  dm - DM on which the vector was gotten
395: .  name - name under which the vector was gotten
396: -  X - Vec to restore

398:    Level: developer

400: .seealso: `DMGetNamedGlobalVector()`
401: @*/
402: PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
403: {
404:   DMNamedVecLink link;

406:   PetscFunctionBegin;
411:   for (link = dm->namedglobal; link; link = link->next) {
412:     PetscBool match;

414:     PetscCall(PetscStrcmp(name, link->name, &match));
415:     if (match) {
416:       DM vdm;

418:       PetscCall(VecGetDM(*X, &vdm));
419:       PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
420:       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);
421:       PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");

423:       link->status = DMVEC_STATUS_IN;
424:       PetscCall(VecSetDM(link->X, NULL));
425:       *X = NULL;
426:       PetscFunctionReturn(PETSC_SUCCESS);
427:     }
428:   }
429:   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
430: }

432: /*@C
433:    DMHasNamedLocalVector - check for a named, persistent local vector

435:    Not Collective

437:    Input Parameters:
438: +  dm - DM to hold named vectors
439: -  name - unique name for Vec

441:    Output Parameter:
442: .  exists - true if the vector was previously created

444:    Level: developer

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

448: .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
449: @*/
450: PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
451: {
452:   DMNamedVecLink link;

454:   PetscFunctionBegin;
458:   *exists = PETSC_FALSE;
459:   for (link = dm->namedlocal; link; link = link->next) {
460:     PetscBool match;
461:     PetscCall(PetscStrcmp(name, link->name, &match));
462:     if (match) {
463:       *exists = PETSC_TRUE;
464:       break;
465:     }
466:   }
467:   PetscFunctionReturn(PETSC_SUCCESS);
468: }

470: /*@C
471:    DMGetNamedLocalVector - get access to a named, persistent local vector

473:    Not Collective

475:    Input Parameters:
476: +  dm - DM to hold named vectors
477: -  name - unique name for Vec

479:    Output Parameter:
480: .  X - named Vec

482:    Level: developer

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

486: .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
487: @*/
488: PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
489: {
490:   DMNamedVecLink link;

492:   PetscFunctionBegin;
496:   for (link = dm->namedlocal; link; link = link->next) {
497:     PetscBool match;

499:     PetscCall(PetscStrcmp(name, link->name, &match));
500:     if (match) {
501:       DM vdm;

503:       PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
504:       PetscCall(VecGetDM(link->X, &vdm));
505:       PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
506:       PetscCall(VecSetDM(link->X, dm));
507:       goto found;
508:     }
509:   }

511:   /* Create the Vec */
512:   PetscCall(PetscNew(&link));
513:   PetscCall(PetscStrallocpy(name, &link->name));
514:   PetscCall(DMCreateLocalVector(dm, &link->X));
515:   link->next     = dm->namedlocal;
516:   dm->namedlocal = link;

518: found:
519:   *X           = link->X;
520:   link->status = DMVEC_STATUS_OUT;
521:   PetscFunctionReturn(PETSC_SUCCESS);
522: }

524: /*@C
525:    DMRestoreNamedLocalVector - restore access to a named, persistent local vector

527:    Not Collective

529:    Input Parameters:
530: +  dm - DM on which the vector was gotten
531: .  name - name under which the vector was gotten
532: -  X - Vec to restore

534:    Level: developer

536: .seealso: `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`
537: @*/
538: PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
539: {
540:   DMNamedVecLink link;

542:   PetscFunctionBegin;
547:   for (link = dm->namedlocal; link; link = link->next) {
548:     PetscBool match;

550:     PetscCall(PetscStrcmp(name, link->name, &match));
551:     if (match) {
552:       DM vdm;

554:       PetscCall(VecGetDM(*X, &vdm));
555:       PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
556:       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);
557:       PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");

559:       link->status = DMVEC_STATUS_IN;
560:       PetscCall(VecSetDM(link->X, NULL));
561:       *X = NULL;
562:       PetscFunctionReturn(PETSC_SUCCESS);
563:     }
564:   }
565:   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
566: }