xref: /petsc/src/dm/interface/dmget.c (revision 21e3ffae2f3b73c0bd738cf6d0a809700fc04bb0)
1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
2 
3 /*@
4    DMGetLocalVector - Gets a PETSc vector that may be used with the DM local routines. This vector has spaces for the ghost values.
5 
6    Not Collective
7 
8    Input Parameter:
9 .  dm - the dm
10 
11    Output Parameter:
12 .  g - the local vector
13 
14    Level: beginner
15 
16    Note:
17    The vector values are NOT initialized and may have garbage in them, so you may need
18    to zero them.
19 
20    The output parameter, g, is a regular PETSc vector that should be returned with
21    DMRestoreLocalVector() DO NOT call VecDestroy() on it.
22 
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().
26 
27    VecStride*() operations can be useful when using DM with dof > 1
28 
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;
37   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38   PetscValidPointer(g, 2);
39   for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
40     if (dm->localin[i]) {
41       DM vdm;
42 
43       *g             = dm->localin[i];
44       dm->localin[i] = NULL;
45 
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));
53 
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 }
63 
64 /*@
65    DMRestoreLocalVector - Returns a PETSc vector that was
66      obtained from `DMGetLocalVector()`. Do not use with vector obtained via
67      `DMCreateLocalVector()`.
68 
69    Not Collective
70 
71    Input Parameters:
72 +  dm - the dm
73 -  g - the local vector
74 
75    Level: beginner
76 
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;
84 
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87   PetscValidPointer(g, 2);
88   for (j = 0; j < DM_MAX_WORK_VECTORS; j++) {
89     if (*g == dm->localout[j]) {
90       DM vdm;
91 
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 }
109 
110 /*@
111    DMGetGlobalVector - Gets a PETSc vector that may be used with the `DM` global routines.
112 
113    Collective on dm
114 
115    Input Parameter:
116 .  dm - the dm
117 
118    Output Parameter:
119 .  g - the global vector
120 
121    Level: beginner
122 
123    Note:
124    The vector values are NOT initialized and may have garbage in them, so you may need
125    to zero them.
126 
127    The output parameter, g, is a regular PETSc vector that should be returned with
128    `DMRestoreGlobalVector()` DO NOT call `VecDestroy()` on it.
129 
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()`.
133 
134    VecStride*() operations can be useful when using `DM` with dof > 1
135 
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;
144 
145   PetscFunctionBegin;
146   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
147   PetscValidPointer(g, 2);
148   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
149     if (dm->globalin[i]) {
150       DM vdm;
151 
152       *g              = dm->globalin[i];
153       dm->globalin[i] = NULL;
154 
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));
162 
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 }
172 
173 /*@
174    DMClearGlobalVectors - Destroys all the global vectors that have been stashed in this DM
175 
176    Collective on dm
177 
178    Input Parameter:
179 .  dm - the dm
180 
181    Level: developer
182 
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;
191 
192   PetscFunctionBegin;
193   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
194   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
195     Vec g;
196 
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;
202 
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 }
210 
211 /*@
212    DMClearLocalVectors - Destroys all the local vectors that have been stashed in this DM
213 
214    Collective on dm
215 
216    Input Parameter:
217 .  dm - the dm
218 
219    Level: developer
220 
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;
229 
230   PetscFunctionBegin;
231   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
232   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
233     Vec g;
234 
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;
240 
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 }
248 
249 /*@
250    DMRestoreGlobalVector - Returns a PETSc vector that
251      obtained from DMGetGlobalVector(). Do not use with vector obtained via
252      DMCreateGlobalVector().
253 
254    Not Collective
255 
256    Input Parameters:
257 +  dm - the dm
258 -  g - the global vector
259 
260    Level: beginner
261 
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;
269 
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
272   PetscValidPointer(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;
277 
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 }
295 
296 /*@C
297    DMHasNamedGlobalVector - check for a named, persistent global vector
298 
299    Not Collective
300 
301    Input Parameters:
302 +  dm - DM to hold named vectors
303 -  name - unique name for Vec
304 
305    Output Parameter:
306 .  exists - true if the vector was previously created
307 
308    Level: developer
309 
310    Note: If a Vec with the given name does not exist, it is created.
311 
312 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
313 @*/
314 PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
315 {
316   DMNamedVecLink link;
317 
318   PetscFunctionBegin;
319   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
320   PetscValidCharPointer(name, 2);
321   PetscValidBoolPointer(exists, 3);
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 }
333 
334 /*@C
335    DMGetNamedGlobalVector - get access to a named, persistent global vector
336 
337    Collective on dm
338 
339    Input Parameters:
340 +  dm - DM to hold named vectors
341 -  name - unique name for Vec
342 
343    Output Parameter:
344 .  X - named Vec
345 
346    Level: developer
347 
348    Note: If a Vec with the given name does not exist, it is created.
349 
350 .seealso: `DMRestoreNamedGlobalVector()`
351 @*/
352 PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
353 {
354   DMNamedVecLink link;
355 
356   PetscFunctionBegin;
357   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
358   PetscValidCharPointer(name, 2);
359   PetscValidPointer(X, 3);
360   for (link = dm->namedglobal; link; link = link->next) {
361     PetscBool match;
362 
363     PetscCall(PetscStrcmp(name, link->name, &match));
364     if (match) {
365       DM vdm;
366 
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   }
374 
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;
381 
382 found:
383   *X           = link->X;
384   link->status = DMVEC_STATUS_OUT;
385   PetscFunctionReturn(PETSC_SUCCESS);
386 }
387 
388 /*@C
389    DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
390 
391    Collective on dm
392 
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
397 
398    Level: developer
399 
400 .seealso: `DMGetNamedGlobalVector()`
401 @*/
402 PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
403 {
404   DMNamedVecLink link;
405 
406   PetscFunctionBegin;
407   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
408   PetscValidCharPointer(name, 2);
409   PetscValidPointer(X, 3);
410   PetscValidHeaderSpecific(*X, VEC_CLASSID, 3);
411   for (link = dm->namedglobal; link; link = link->next) {
412     PetscBool match;
413 
414     PetscCall(PetscStrcmp(name, link->name, &match));
415     if (match) {
416       DM vdm;
417 
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");
422 
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 }
431 
432 /*@C
433    DMHasNamedLocalVector - check for a named, persistent local vector
434 
435    Not Collective
436 
437    Input Parameters:
438 +  dm - DM to hold named vectors
439 -  name - unique name for Vec
440 
441    Output Parameter:
442 .  exists - true if the vector was previously created
443 
444    Level: developer
445 
446    Note: If a Vec with the given name does not exist, it is created.
447 
448 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
449 @*/
450 PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
451 {
452   DMNamedVecLink link;
453 
454   PetscFunctionBegin;
455   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
456   PetscValidCharPointer(name, 2);
457   PetscValidBoolPointer(exists, 3);
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 }
469 
470 /*@C
471    DMGetNamedLocalVector - get access to a named, persistent local vector
472 
473    Not Collective
474 
475    Input Parameters:
476 +  dm - DM to hold named vectors
477 -  name - unique name for Vec
478 
479    Output Parameter:
480 .  X - named Vec
481 
482    Level: developer
483 
484    Note: If a Vec with the given name does not exist, it is created.
485 
486 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
487 @*/
488 PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
489 {
490   DMNamedVecLink link;
491 
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
494   PetscValidCharPointer(name, 2);
495   PetscValidPointer(X, 3);
496   for (link = dm->namedlocal; link; link = link->next) {
497     PetscBool match;
498 
499     PetscCall(PetscStrcmp(name, link->name, &match));
500     if (match) {
501       DM vdm;
502 
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   }
510 
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;
517 
518 found:
519   *X           = link->X;
520   link->status = DMVEC_STATUS_OUT;
521   PetscFunctionReturn(PETSC_SUCCESS);
522 }
523 
524 /*@C
525    DMRestoreNamedLocalVector - restore access to a named, persistent local vector
526 
527    Not Collective
528 
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
533 
534    Level: developer
535 
536 .seealso: `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`
537 @*/
538 PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
539 {
540   DMNamedVecLink link;
541 
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
544   PetscValidCharPointer(name, 2);
545   PetscValidPointer(X, 3);
546   PetscValidHeaderSpecific(*X, VEC_CLASSID, 3);
547   for (link = dm->namedlocal; link; link = link->next) {
548     PetscBool match;
549 
550     PetscCall(PetscStrcmp(name, link->name, &match));
551     if (match) {
552       DM vdm;
553 
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");
558 
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 }
567