xref: /petsc/src/dm/interface/dmget.c (revision 6a5217c03994f2d95bb2e6dbd8bed42381aeb015)
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(0);
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: 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(0);
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: 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(0);
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     PetscCheckFalse(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(0);
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     PetscCheckFalse(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(0);
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(0);
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(0);
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(0);
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(0);
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(0);
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(0);
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(0);
563     }
564   }
565   SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Could not find Vec name '%s' to restore",name);
566 }
567