xref: /petsc/src/dm/interface/dmget.c (revision 4e97f8ebb84dd841ee7d0d48926a4de5d5170225)
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   ierr = VecSetErrorIfLocked(*g, 2);CHKERRQ(ierr);
267   for (j=0; j<DM_MAX_WORK_VECTORS; j++) {
268     if (*g == dm->globalout[j]) {
269       dm->globalout[j] = NULL;
270       for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
271         if (!dm->globalin[i]) {
272           dm->globalin[i] = *g;
273           goto alldone;
274         }
275       }
276     }
277   }
278   ierr = VecDestroy(g);CHKERRQ(ierr);
279 alldone:
280   *g = NULL;
281   PetscFunctionReturn(0);
282 }
283 
284 /*@C
285    DMHasNamedGlobalVector - check for a named, persistent global vector
286 
287    Not Collective
288 
289    Input Arguments:
290 +  dm - DM to hold named vectors
291 -  name - unique name for Vec
292 
293    Output Arguments:
294 .  exists - true if the vector was previously created
295 
296    Level: developer
297 
298    Note: If a Vec with the given name does not exist, it is created.
299 
300 .seealso: DMGetNamedGlobalVector(),DMRestoreNamedLocalVector()
301 @*/
302 PetscErrorCode DMHasNamedGlobalVector(DM dm,const char *name,PetscBool *exists)
303 {
304   PetscErrorCode ierr;
305   DMNamedVecLink link;
306 
307   PetscFunctionBegin;
308   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
309   PetscValidCharPointer(name,2);
310   PetscValidPointer(exists,3);
311   *exists = PETSC_FALSE;
312   for (link=dm->namedglobal; link; link=link->next) {
313     PetscBool match;
314     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
315     if (match) {
316       *exists = PETSC_TRUE;
317       break;
318     }
319   }
320   PetscFunctionReturn(0);
321 }
322 
323 /*@C
324    DMGetNamedGlobalVector - get access to a named, persistent global vector
325 
326    Collective on DM
327 
328    Input Arguments:
329 +  dm - DM to hold named vectors
330 -  name - unique name for Vec
331 
332    Output Arguments:
333 .  X - named Vec
334 
335    Level: developer
336 
337    Note: If a Vec with the given name does not exist, it is created.
338 
339 .seealso: DMRestoreNamedGlobalVector()
340 @*/
341 PetscErrorCode DMGetNamedGlobalVector(DM dm,const char *name,Vec *X)
342 {
343   PetscErrorCode ierr;
344   DMNamedVecLink link;
345 
346   PetscFunctionBegin;
347   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
348   PetscValidCharPointer(name,2);
349   PetscValidPointer(X,3);
350   for (link=dm->namedglobal; link; link=link->next) {
351     PetscBool match;
352     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
353     if (match) {
354       if (link->status != DMVEC_STATUS_IN) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' already checked out",name);
355       goto found;
356     }
357   }
358 
359   /* Create the Vec */
360   ierr            = PetscNew(&link);CHKERRQ(ierr);
361   ierr            = PetscStrallocpy(name,&link->name);CHKERRQ(ierr);
362   ierr            = DMCreateGlobalVector(dm,&link->X);CHKERRQ(ierr);
363   link->next      = dm->namedglobal;
364   dm->namedglobal = link;
365 
366 found:
367   *X           = link->X;
368   link->status = DMVEC_STATUS_OUT;
369   PetscFunctionReturn(0);
370 }
371 
372 /*@C
373    DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
374 
375    Collective on DM
376 
377    Input Arguments:
378 +  dm - DM on which the vector was gotten
379 .  name - name under which the vector was gotten
380 -  X - Vec to restore
381 
382    Output Arguments:
383 
384    Level: developer
385 
386 .seealso: DMGetNamedGlobalVector()
387 @*/
388 PetscErrorCode DMRestoreNamedGlobalVector(DM dm,const char *name,Vec *X)
389 {
390   PetscErrorCode ierr;
391   DMNamedVecLink link;
392 
393   PetscFunctionBegin;
394   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
395   PetscValidCharPointer(name,2);
396   PetscValidPointer(X,3);
397   PetscValidHeaderSpecific(*X,VEC_CLASSID,3);
398   for (link=dm->namedglobal; link; link=link->next) {
399     PetscBool match;
400     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
401     if (match) {
402       if (link->status != DMVEC_STATUS_OUT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' was not checked out",name);
403       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);
404       link->status = DMVEC_STATUS_IN;
405       *X           = NULL;
406       PetscFunctionReturn(0);
407     }
408   }
409   SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Could not find Vec name '%s' to restore",name);
410   PetscFunctionReturn(0);
411 }
412 
413 /*@C
414    DMHasNamedLocalVector - check for a named, persistent local vector
415 
416    Not Collective
417 
418    Input Arguments:
419 +  dm - DM to hold named vectors
420 -  name - unique name for Vec
421 
422    Output Arguments:
423 .  exists - true if the vector was previously created
424 
425    Level: developer
426 
427    Note: If a Vec with the given name does not exist, it is created.
428 
429 .seealso: DMGetNamedGlobalVector(),DMRestoreNamedLocalVector()
430 @*/
431 PetscErrorCode DMHasNamedLocalVector(DM dm,const char *name,PetscBool *exists)
432 {
433   PetscErrorCode ierr;
434   DMNamedVecLink link;
435 
436   PetscFunctionBegin;
437   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
438   PetscValidCharPointer(name,2);
439   PetscValidPointer(exists,3);
440   *exists = PETSC_FALSE;
441   for (link=dm->namedlocal; link; link=link->next) {
442     PetscBool match;
443     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
444     if (match) {
445       *exists = PETSC_TRUE;
446       break;
447     }
448   }
449   PetscFunctionReturn(0);
450 }
451 
452 /*@C
453    DMGetNamedLocalVector - get access to a named, persistent local vector
454 
455    Not Collective
456 
457    Input Arguments:
458 +  dm - DM to hold named vectors
459 -  name - unique name for Vec
460 
461    Output Arguments:
462 .  X - named Vec
463 
464    Level: developer
465 
466    Note: If a Vec with the given name does not exist, it is created.
467 
468 .seealso: DMGetNamedGlobalVector(),DMRestoreNamedLocalVector()
469 @*/
470 PetscErrorCode DMGetNamedLocalVector(DM dm,const char *name,Vec *X)
471 {
472   PetscErrorCode ierr;
473   DMNamedVecLink link;
474 
475   PetscFunctionBegin;
476   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
477   PetscValidCharPointer(name,2);
478   PetscValidPointer(X,3);
479   for (link=dm->namedlocal; link; link=link->next) {
480     PetscBool match;
481     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
482     if (match) {
483       if (link->status != DMVEC_STATUS_IN) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' already checked out",name);
484       goto found;
485     }
486   }
487 
488   /* Create the Vec */
489   ierr           = PetscNew(&link);CHKERRQ(ierr);
490   ierr           = PetscStrallocpy(name,&link->name);CHKERRQ(ierr);
491   ierr           = DMCreateLocalVector(dm,&link->X);CHKERRQ(ierr);
492   link->next     = dm->namedlocal;
493   dm->namedlocal = link;
494 
495 found:
496   *X           = link->X;
497   link->status = DMVEC_STATUS_OUT;
498   PetscFunctionReturn(0);
499 }
500 
501 /*@C
502    DMRestoreNamedLocalVector - restore access to a named, persistent local vector
503 
504    Not Collective
505 
506    Input Arguments:
507 +  dm - DM on which the vector was gotten
508 .  name - name under which the vector was gotten
509 -  X - Vec to restore
510 
511    Output Arguments:
512 
513    Level: developer
514 
515 .seealso: DMRestoreNamedGlobalVector(),DMGetNamedLocalVector()
516 @*/
517 PetscErrorCode DMRestoreNamedLocalVector(DM dm,const char *name,Vec *X)
518 {
519   PetscErrorCode ierr;
520   DMNamedVecLink link;
521 
522   PetscFunctionBegin;
523   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
524   PetscValidCharPointer(name,2);
525   PetscValidPointer(X,3);
526   PetscValidHeaderSpecific(*X,VEC_CLASSID,3);
527   for (link=dm->namedlocal; link; link=link->next) {
528     PetscBool match;
529     ierr = PetscStrcmp(name,link->name,&match);CHKERRQ(ierr);
530     if (match) {
531       if (link->status != DMVEC_STATUS_OUT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Vec name '%s' was not checked out",name);
532       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);
533       link->status = DMVEC_STATUS_IN;
534       *X           = NULL;
535       PetscFunctionReturn(0);
536     }
537   }
538   SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Could not find Vec name '%s' to restore",name);
539   PetscFunctionReturn(0);
540 }
541