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