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()`
 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`, `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`, `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

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()`
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

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

219:    Level: developer

221: .seealso: `DM`, `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: `DM`, `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: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
311: @*/
312: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
313: {
314:   DMNamedVecLink link;

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

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

335:    Collective

337:    Input Parameters:
338: +  dm - `DM` to hold named vectors
339: -  name - unique name for `Vec`

341:    Output Parameter:
342: .  X - named `Vec`

344:    Level: developer

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

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

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

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

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

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

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

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

390:    Collective

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

397:    Level: developer

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

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

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

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

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

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

434:    Not Collective

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

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

443:    Level: developer

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

448: .seealso: `DM`, `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:
485:    If a `Vec` with the given name does not exist, it is created.

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

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

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

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

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

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

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

528:    Not Collective

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

535:    Level: developer

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

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

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

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

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