xref: /petsc/src/dm/interface/dmget.c (revision effebcaf36779a7960a3371bb2c397d1b7c25a76)
1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
2 
3 /*@
4    DMGetLocalVector - Gets a Seq PETSc vector that
5    may be used with the DMXXX routines. This vector has spaces for the ghost values.
6 
7    Not Collective
8 
9    Input Parameter:
10 .  dm - the distributed array
11 
12    Output Parameter:
13 .  g - the local vector
14 
15    Level: beginner
16 
17    Note:
18    The vector values are NOT initialized and may have garbage in them, so you may need
19    to zero them.
20 
21    The output parameter, g, is a regular PETSc vector that should be returned with
22    DMRestoreLocalVector() DO NOT call VecDestroy() on it.
23 
24    This is intended to be used for vectors you need for a short time, like within a single function call.
25    For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your
26    code you should use DMCreateLocalVector().
27 
28    VecStride*() operations can be useful when using DM with dof > 1
29 
30 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
31           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
32           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMRestoreLocalVector(),
33           VecStrideMax(), VecStrideMin(), VecStrideNorm()
34 @*/
35 PetscErrorCode  DMGetLocalVector(DM dm,Vec *g)
36 {
37   PetscErrorCode ierr,i;
38 
39   PetscFunctionBegin;
40   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
41   PetscValidPointer(g,2);
42   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
43     if (dm->localin[i]) {
44       *g             = dm->localin[i];
45       dm->localin[i] = NULL;
46       goto alldone;
47     }
48   }
49   ierr = DMCreateLocalVector(dm,g);CHKERRQ(ierr);
50 
51 alldone:
52   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
53     if (!dm->localout[i]) {
54       dm->localout[i] = *g;
55       break;
56     }
57   }
58   PetscFunctionReturn(0);
59 }
60 
61 /*@
62    DMRestoreLocalVector - Returns a Seq PETSc vector that
63      obtained from DMGetLocalVector(). Do not use with vector obtained via
64      DMCreateLocalVector().
65 
66    Not Collective
67 
68    Input Parameter:
69 +  dm - the distributed array
70 -  g - the local vector
71 
72    Level: beginner
73 
74 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
75           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
76           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMGetLocalVector()
77 @*/
78 PetscErrorCode  DMRestoreLocalVector(DM dm,Vec *g)
79 {
80   PetscErrorCode ierr;
81   PetscInt       i,j;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
85   PetscValidPointer(g,2);
86   for (j=0; j<DM_MAX_WORK_VECTORS; j++) {
87     if (*g == dm->localout[j]) {
88       dm->localout[j] = NULL;
89       for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
90         if (!dm->localin[i]) {
91           dm->localin[i] = *g;
92           goto alldone;
93         }
94       }
95     }
96   }
97   ierr = VecDestroy(g);CHKERRQ(ierr);
98 alldone:
99   *g = NULL;
100   PetscFunctionReturn(0);
101 }
102 
103 /*@
104    DMGetGlobalVector - Gets a MPI PETSc vector that
105    may be used with the DMXXX routines.
106 
107    Collective on dm
108 
109    Input Parameter:
110 .  dm - the distributed array
111 
112    Output Parameter:
113 .  g - the global vector
114 
115    Level: beginner
116 
117    Note:
118    The vector values are NOT initialized and may have garbage in them, so you may need
119    to zero them.
120 
121    The output parameter, g, is a regular PETSc vector that should be returned with
122    DMRestoreGlobalVector() DO NOT call VecDestroy() on it.
123 
124    This is intended to be used for vectors you need for a short time, like within a single function call.
125    For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your
126    code you should use DMCreateGlobalVector().
127 
128    VecStride*() operations can be useful when using DM with dof > 1
129 
130 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
131           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
132           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMRestoreLocalVector()
133           VecStrideMax(), VecStrideMin(), VecStrideNorm()
134 
135 @*/
136 PetscErrorCode  DMGetGlobalVector(DM dm,Vec *g)
137 {
138   PetscErrorCode ierr;
139   PetscInt       i;
140 
141   PetscFunctionBegin;
142   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
143   PetscValidPointer(g,2);
144   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
145     if (dm->globalin[i]) {
146       *g              = dm->globalin[i];
147       dm->globalin[i] = NULL;
148       goto alldone;
149     }
150   }
151   ierr = DMCreateGlobalVector(dm,g);CHKERRQ(ierr);
152 
153 alldone:
154   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
155     if (!dm->globalout[i]) {
156       dm->globalout[i] = *g;
157       break;
158     }
159   }
160   PetscFunctionReturn(0);
161 }
162 
163 /*@
164    DMClearGlobalVectors - Destroys all the global vectors that have been stashed in this DM
165 
166    Collective on dm
167 
168    Input Parameter:
169 .  dm - the distributed array
170 
171    Level: developer
172 
173 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
174           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
175           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMRestoreLocalVector()
176           VecStrideMax(), VecStrideMin(), VecStrideNorm()
177 
178 @*/
179 PetscErrorCode  DMClearGlobalVectors(DM dm)
180 {
181   PetscErrorCode ierr;
182   PetscInt       i;
183 
184   PetscFunctionBegin;
185   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
186   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
187     Vec g;
188     if (dm->globalout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Clearing DM of global vectors that has a global vector obtained with DMGetGlobalVector()");
189     g = dm->globalin[i];
190     dm->globalin[i] = NULL;
191     ierr = VecDestroy(&g);CHKERRQ(ierr);
192   }
193   PetscFunctionReturn(0);
194 }
195 
196 /*@
197    DMClearLocalVectors - Destroys all the local vectors that have been stashed in this DM
198 
199    Collective on dm
200 
201    Input Parameter:
202 .  dm - the distributed array
203 
204    Level: developer
205 
206 .seealso: DMCreateLocalVector(), VecDuplicate(), VecDuplicateVecs(),
207           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMLocalToLocalBegin(),
208           DMLocalToLocalEnd(), DMLocalToLocalBegin(), DMCreateLocalVector(), DMRestoreLocalVector()
209           VecStrideMax(), VecStrideMin(), VecStrideNorm()
210 
211 @*/
212 PetscErrorCode  DMClearLocalVectors(DM dm)
213 {
214   PetscErrorCode ierr;
215   PetscInt       i;
216 
217   PetscFunctionBegin;
218   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
219   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
220     Vec g;
221     if (dm->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Clearing DM of local vectors that has a local vector obtained with DMGetLocalVector()");
222     g = dm->localin[i];
223     dm->localin[i] = NULL;
224     ierr = VecDestroy(&g);CHKERRQ(ierr);
225   }
226   PetscFunctionReturn(0);
227 }
228 
229 /*@
230    DMRestoreGlobalVector - Returns a Seq PETSc vector that
231      obtained from DMGetGlobalVector(). Do not use with vector obtained via
232      DMCreateGlobalVector().
233 
234    Not Collective
235 
236    Input Parameter:
237 +  dm - the distributed array
238 -  g - the global vector
239 
240    Level: beginner
241 
242 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
243           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToGlobalBegin(),
244           DMGlobalToGlobalEnd(), DMGlobalToGlobal(), DMCreateLocalVector(), DMGetGlobalVector()
245 @*/
246 PetscErrorCode  DMRestoreGlobalVector(DM dm,Vec *g)
247 {
248   PetscErrorCode ierr;
249   PetscInt       i,j;
250 
251   PetscFunctionBegin;
252   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
253   PetscValidPointer(g,2);
254   ierr = VecSetErrorIfLocked(*g, 2);CHKERRQ(ierr);
255   for (j=0; j<DM_MAX_WORK_VECTORS; j++) {
256     if (*g == dm->globalout[j]) {
257       dm->globalout[j] = NULL;
258       for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
259         if (!dm->globalin[i]) {
260           dm->globalin[i] = *g;
261           goto alldone;
262         }
263       }
264     }
265   }
266   ierr = VecDestroy(g);CHKERRQ(ierr);
267 alldone:
268   *g = NULL;
269   PetscFunctionReturn(0);
270 }
271 
272 /*@C
273    DMHasNamedGlobalVector - check for a named, persistent global vector
274 
275    Not Collective
276 
277    Input Arguments:
278 +  dm - DM to hold named vectors
279 -  name - unique name for Vec
280 
281    Output Arguments:
282 .  exists - true if the vector was previously created
283 
284    Level: developer
285 
286    Note: If a Vec with the given name does not exist, it is created.
287 
288 .seealso: DMGetNamedGlobalVector(),DMRestoreNamedLocalVector()
289 @*/
290 PetscErrorCode DMHasNamedGlobalVector(DM dm,const char *name,PetscBool *exists)
291 {
292   PetscErrorCode ierr;
293   DMNamedVecLink link;
294 
295   PetscFunctionBegin;
296   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
297   PetscValidCharPointer(name,2);
298   PetscValidBoolPointer(exists,3);
299   *exists = PETSC_FALSE;
300   for (link=dm->namedglobal; link; link=link->next) {
301     PetscBool match;
302     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
303     if (match) {
304       *exists = PETSC_TRUE;
305       break;
306     }
307   }
308   PetscFunctionReturn(0);
309 }
310 
311 /*@C
312    DMGetNamedGlobalVector - get access to a named, persistent global vector
313 
314    Collective on dm
315 
316    Input Arguments:
317 +  dm - DM to hold named vectors
318 -  name - unique name for Vec
319 
320    Output Arguments:
321 .  X - named Vec
322 
323    Level: developer
324 
325    Note: If a Vec with the given name does not exist, it is created.
326 
327 .seealso: DMRestoreNamedGlobalVector()
328 @*/
329 PetscErrorCode DMGetNamedGlobalVector(DM dm,const char *name,Vec *X)
330 {
331   PetscErrorCode ierr;
332   DMNamedVecLink link;
333 
334   PetscFunctionBegin;
335   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
336   PetscValidCharPointer(name,2);
337   PetscValidPointer(X,3);
338   for (link=dm->namedglobal; link; link=link->next) {
339     PetscBool match;
340     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
341     if (match) {
342       if (link->status != DMVEC_STATUS_IN) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' already checked out",name);
343       goto found;
344     }
345   }
346 
347   /* Create the Vec */
348   ierr            = PetscNew(&link);CHKERRQ(ierr);
349   ierr            = PetscStrallocpy(name,&link->name);CHKERRQ(ierr);
350   ierr            = DMCreateGlobalVector(dm,&link->X);CHKERRQ(ierr);
351   link->next      = dm->namedglobal;
352   dm->namedglobal = link;
353 
354 found:
355   *X           = link->X;
356   link->status = DMVEC_STATUS_OUT;
357   PetscFunctionReturn(0);
358 }
359 
360 /*@C
361    DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
362 
363    Collective on dm
364 
365    Input Arguments:
366 +  dm - DM on which the vector was gotten
367 .  name - name under which the vector was gotten
368 -  X - Vec to restore
369 
370    Output Arguments:
371 
372    Level: developer
373 
374 .seealso: DMGetNamedGlobalVector()
375 @*/
376 PetscErrorCode DMRestoreNamedGlobalVector(DM dm,const char *name,Vec *X)
377 {
378   PetscErrorCode ierr;
379   DMNamedVecLink link;
380 
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
383   PetscValidCharPointer(name,2);
384   PetscValidPointer(X,3);
385   PetscValidHeaderSpecific(*X,VEC_CLASSID,3);
386   for (link=dm->namedglobal; link; link=link->next) {
387     PetscBool match;
388     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
389     if (match) {
390       if (link->status != DMVEC_STATUS_OUT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' was not checked out",name);
391       if (link->X != *X) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Attempt to restore Vec name '%s', but Vec does not match the cache",name);
392       link->status = DMVEC_STATUS_IN;
393       *X           = NULL;
394       PetscFunctionReturn(0);
395     }
396   }
397   SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Could not find Vec name '%s' to restore",name);
398   PetscFunctionReturn(0);
399 }
400 
401 /*@C
402    DMHasNamedLocalVector - check for a named, persistent local vector
403 
404    Not Collective
405 
406    Input Arguments:
407 +  dm - DM to hold named vectors
408 -  name - unique name for Vec
409 
410    Output Arguments:
411 .  exists - true if the vector was previously created
412 
413    Level: developer
414 
415    Note: If a Vec with the given name does not exist, it is created.
416 
417 .seealso: DMGetNamedGlobalVector(),DMRestoreNamedLocalVector()
418 @*/
419 PetscErrorCode DMHasNamedLocalVector(DM dm,const char *name,PetscBool *exists)
420 {
421   PetscErrorCode ierr;
422   DMNamedVecLink link;
423 
424   PetscFunctionBegin;
425   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
426   PetscValidCharPointer(name,2);
427   PetscValidPointer(exists,3);
428   *exists = PETSC_FALSE;
429   for (link=dm->namedlocal; link; link=link->next) {
430     PetscBool match;
431     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
432     if (match) {
433       *exists = PETSC_TRUE;
434       break;
435     }
436   }
437   PetscFunctionReturn(0);
438 }
439 
440 /*@C
441    DMGetNamedLocalVector - get access to a named, persistent local vector
442 
443    Not Collective
444 
445    Input Arguments:
446 +  dm - DM to hold named vectors
447 -  name - unique name for Vec
448 
449    Output Arguments:
450 .  X - named Vec
451 
452    Level: developer
453 
454    Note: If a Vec with the given name does not exist, it is created.
455 
456 .seealso: DMGetNamedGlobalVector(),DMRestoreNamedLocalVector()
457 @*/
458 PetscErrorCode DMGetNamedLocalVector(DM dm,const char *name,Vec *X)
459 {
460   PetscErrorCode ierr;
461   DMNamedVecLink link;
462 
463   PetscFunctionBegin;
464   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
465   PetscValidCharPointer(name,2);
466   PetscValidPointer(X,3);
467   for (link=dm->namedlocal; link; link=link->next) {
468     PetscBool match;
469     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
470     if (match) {
471       if (link->status != DMVEC_STATUS_IN) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' already checked out",name);
472       goto found;
473     }
474   }
475 
476   /* Create the Vec */
477   ierr           = PetscNew(&link);CHKERRQ(ierr);
478   ierr           = PetscStrallocpy(name,&link->name);CHKERRQ(ierr);
479   ierr           = DMCreateLocalVector(dm,&link->X);CHKERRQ(ierr);
480   link->next     = dm->namedlocal;
481   dm->namedlocal = link;
482 
483 found:
484   *X           = link->X;
485   link->status = DMVEC_STATUS_OUT;
486   PetscFunctionReturn(0);
487 }
488 
489 /*@C
490    DMRestoreNamedLocalVector - restore access to a named, persistent local vector
491 
492    Not Collective
493 
494    Input Arguments:
495 +  dm - DM on which the vector was gotten
496 .  name - name under which the vector was gotten
497 -  X - Vec to restore
498 
499    Output Arguments:
500 
501    Level: developer
502 
503 .seealso: DMRestoreNamedGlobalVector(),DMGetNamedLocalVector()
504 @*/
505 PetscErrorCode DMRestoreNamedLocalVector(DM dm,const char *name,Vec *X)
506 {
507   PetscErrorCode ierr;
508   DMNamedVecLink link;
509 
510   PetscFunctionBegin;
511   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
512   PetscValidCharPointer(name,2);
513   PetscValidPointer(X,3);
514   PetscValidHeaderSpecific(*X,VEC_CLASSID,3);
515   for (link=dm->namedlocal; link; link=link->next) {
516     PetscBool match;
517     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
518     if (match) {
519       if (link->status != DMVEC_STATUS_OUT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' was not checked out",name);
520       if (link->X != *X) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Attempt to restore Vec name '%s', but Vec does not match the cache",name);
521       link->status = DMVEC_STATUS_IN;
522       *X           = NULL;
523       PetscFunctionReturn(0);
524     }
525   }
526   SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Could not find Vec name '%s' to restore",name);
527   PetscFunctionReturn(0);
528 }
529