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